Code

Imported Upstream version 5.5.0 upstream upstream/5.5.0
authorSebastian Harl <sh@tokkee.org>
Fri, 21 Aug 2015 12:14:05 +0000 (14:14 +0200)
committerSebastian Harl <sh@tokkee.org>
Fri, 21 Aug 2015 12:14:05 +0000 (14:14 +0200)
479 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
TODO [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
bindings/Makefile.am [new file with mode: 0644]
bindings/Makefile.in [new file with mode: 0644]
bindings/java/Makefile.am [new file with mode: 0644]
bindings/java/Makefile.in [new file with mode: 0644]
bindings/java/org/collectd/api/Collectd.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdConfigInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdFlushInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdInitInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdLogInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdMatchFactoryInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdMatchInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdNotificationInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdReadInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdShutdownInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdTargetFactoryInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdTargetInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/CollectdWriteInterface.java [new file with mode: 0644]
bindings/java/org/collectd/api/DataSet.java [new file with mode: 0644]
bindings/java/org/collectd/api/DataSource.java [new file with mode: 0644]
bindings/java/org/collectd/api/Notification.java [new file with mode: 0644]
bindings/java/org/collectd/api/OConfigItem.java [new file with mode: 0644]
bindings/java/org/collectd/api/OConfigValue.java [new file with mode: 0644]
bindings/java/org/collectd/api/PluginData.java [new file with mode: 0644]
bindings/java/org/collectd/api/ValueList.java [new file with mode: 0644]
bindings/java/org/collectd/java/GenericJMX.java [new file with mode: 0644]
bindings/java/org/collectd/java/GenericJMXConfConnection.java [new file with mode: 0644]
bindings/java/org/collectd/java/GenericJMXConfMBean.java [new file with mode: 0644]
bindings/java/org/collectd/java/GenericJMXConfValue.java [new file with mode: 0644]
bindings/java/org/collectd/java/JMXMemory.java [new file with mode: 0644]
bindings/perl/Makefile.PL [new file with mode: 0644]
bindings/perl/lib/Collectd.pm [new file with mode: 0644]
bindings/perl/lib/Collectd/Plugins/Monitorus.pm [new file with mode: 0644]
bindings/perl/lib/Collectd/Plugins/OpenVZ.pm [new file with mode: 0644]
bindings/perl/lib/Collectd/Unixsock.pm [new file with mode: 0644]
bindings/perl/uninstall_mod.pl [new file with mode: 0644]
compile [new file with mode: 0755]
config.guess [new file with mode: 0755]
config.sub [new file with mode: 0755]
configure [new file with mode: 0755]
configure.ac [new file with mode: 0644]
contrib/GenericJMX.conf [new file with mode: 0644]
contrib/README [new file with mode: 0644]
contrib/SpamAssassin/Collectd.pm [new file with mode: 0644]
contrib/SpamAssassin/example.cf [new file with mode: 0644]
contrib/add_rra.sh [new file with mode: 0755]
contrib/aix/collectd.spec [new file with mode: 0644]
contrib/aix/init.d-collectd [new file with mode: 0755]
contrib/collectd.service [new file with mode: 0644]
contrib/collectd2html.pl [new file with mode: 0644]
contrib/collectd_network.py [new file with mode: 0644]
contrib/collectd_unix_sock.rb [new file with mode: 0644]
contrib/collectd_unixsock.py [new file with mode: 0644]
contrib/collection.cgi [new file with mode: 0755]
contrib/collection.conf [new file with mode: 0644]
contrib/collection3/README [new file with mode: 0644]
contrib/collection3/bin/.htaccess [new file with mode: 0644]
contrib/collection3/bin/graph.cgi [new file with mode: 0755]
contrib/collection3/bin/index.cgi [new file with mode: 0755]
contrib/collection3/bin/json.cgi [new file with mode: 0755]
contrib/collection3/etc/.htaccess [new file with mode: 0644]
contrib/collection3/etc/collection.conf [new file with mode: 0644]
contrib/collection3/lib/.htaccess [new file with mode: 0644]
contrib/collection3/lib/Collectd/Config.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Common.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Config.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/ArcCounts.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/Df.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/GenericIO.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/GenericStacked.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/JavaMemory.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/Load.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/PsCputime.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/TableSize.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/Type/Wirkleistung.pm [new file with mode: 0644]
contrib/collection3/lib/Collectd/Graph/TypeLoader.pm [new file with mode: 0644]
contrib/collection3/share/.htaccess [new file with mode: 0644]
contrib/collection3/share/navigate.js [new file with mode: 0644]
contrib/collection3/share/shortcut-icon.png [new file with mode: 0644]
contrib/collection3/share/style.css [new file with mode: 0644]
contrib/collection3/test.px [new file with mode: 0644]
contrib/cussh.pl [new file with mode: 0755]
contrib/examples/MyPlugin.pm [new file with mode: 0644]
contrib/examples/myplugin.c [new file with mode: 0644]
contrib/exec-ksm.sh [new file with mode: 0755]
contrib/exec-munin.conf [new file with mode: 0644]
contrib/exec-munin.px [new file with mode: 0755]
contrib/exec-nagios.conf [new file with mode: 0644]
contrib/exec-nagios.px [new file with mode: 0755]
contrib/exec-smartctl [new file with mode: 0755]
contrib/fedora/collectd.spec [new file with mode: 0644]
contrib/fedora/init.d-collectd [new file with mode: 0644]
contrib/iptables/accounting.sh [new file with mode: 0755]
contrib/migrate-3-4.px [new file with mode: 0755]
contrib/migrate-4-5.px [new file with mode: 0755]
contrib/network-proxy.py [new file with mode: 0644]
contrib/oracle/create_schema.ddl [new file with mode: 0644]
contrib/oracle/db_systat.sql [new file with mode: 0644]
contrib/php-collection/browser.js [new file with mode: 0644]
contrib/php-collection/config.php [new file with mode: 0644]
contrib/php-collection/definitions.local.php [new file with mode: 0644]
contrib/php-collection/definitions.php [new file with mode: 0644]
contrib/php-collection/functions.php [new file with mode: 0644]
contrib/php-collection/graph.php [new file with mode: 0644]
contrib/php-collection/index.php [new file with mode: 0644]
contrib/postgresql/collectd_insert.sql [new file with mode: 0644]
contrib/python/getsigchld.py [new file with mode: 0644]
contrib/redhat/collectd.spec [new file with mode: 0644]
contrib/redhat/collection3.conf [new file with mode: 0644]
contrib/redhat/init.d-collectd [new file with mode: 0644]
contrib/redhat/php-collection.conf [new file with mode: 0644]
contrib/rrd_filter.px [new file with mode: 0755]
contrib/sles10.1/collectd.spec [new file with mode: 0644]
contrib/sles10.1/init.d-collectd [new file with mode: 0755]
contrib/snmp-data.conf [new file with mode: 0644]
contrib/snmp-probe-host.px [new file with mode: 0755]
contrib/solaris-smf/README [new file with mode: 0644]
contrib/solaris-smf/collectd [new file with mode: 0755]
contrib/solaris-smf/collectd.xml [new file with mode: 0644]
contrib/systemd.collectd.service [new file with mode: 0644]
contrib/upstart.collectd.conf [new file with mode: 0644]
contrib/wiki2changelog.pl [new file with mode: 0755]
depcomp [new file with mode: 0755]
install-sh [new file with mode: 0755]
libltdl/COPYING.LIB [new file with mode: 0644]
libltdl/Makefile.am [new file with mode: 0644]
libltdl/Makefile.in [new file with mode: 0644]
libltdl/README [new file with mode: 0644]
libltdl/aclocal.m4 [new file with mode: 0644]
libltdl/argz.c [new file with mode: 0644]
libltdl/argz_.h [new file with mode: 0644]
libltdl/config-h.in [new file with mode: 0644]
libltdl/config/compile [new file with mode: 0755]
libltdl/config/config.guess [new file with mode: 0755]
libltdl/config/config.sub [new file with mode: 0755]
libltdl/config/depcomp [new file with mode: 0755]
libltdl/config/install-sh [new file with mode: 0755]
libltdl/config/ltmain.sh [new file with mode: 0644]
libltdl/config/missing [new file with mode: 0755]
libltdl/config/test-driver [new file with mode: 0755]
libltdl/config/ylwrap [new file with mode: 0755]
libltdl/configure [new file with mode: 0755]
libltdl/configure.ac [new file with mode: 0644]
libltdl/libltdl/lt__alloc.h [new file with mode: 0644]
libltdl/libltdl/lt__dirent.h [new file with mode: 0644]
libltdl/libltdl/lt__glibc.h [new file with mode: 0644]
libltdl/libltdl/lt__private.h [new file with mode: 0644]
libltdl/libltdl/lt__strl.h [new file with mode: 0644]
libltdl/libltdl/lt_dlloader.h [new file with mode: 0644]
libltdl/libltdl/lt_error.h [new file with mode: 0644]
libltdl/libltdl/lt_system.h [new file with mode: 0644]
libltdl/libltdl/slist.h [new file with mode: 0644]
libltdl/loaders/dld_link.c [new file with mode: 0644]
libltdl/loaders/dlopen.c [new file with mode: 0644]
libltdl/loaders/dyld.c [new file with mode: 0644]
libltdl/loaders/load_add_on.c [new file with mode: 0644]
libltdl/loaders/loadlibrary.c [new file with mode: 0644]
libltdl/loaders/preopen.c [new file with mode: 0644]
libltdl/loaders/shl_load.c [new file with mode: 0644]
libltdl/lt__alloc.c [new file with mode: 0644]
libltdl/lt__dirent.c [new file with mode: 0644]
libltdl/lt__strl.c [new file with mode: 0644]
libltdl/lt_dlloader.c [new file with mode: 0644]
libltdl/lt_error.c [new file with mode: 0644]
libltdl/ltdl.c [new file with mode: 0644]
libltdl/ltdl.h [new file with mode: 0644]
libltdl/m4/argz.m4 [new file with mode: 0644]
libltdl/m4/libtool.m4 [new file with mode: 0644]
libltdl/m4/ltdl.m4 [new file with mode: 0644]
libltdl/m4/ltoptions.m4 [new file with mode: 0644]
libltdl/m4/ltsugar.m4 [new file with mode: 0644]
libltdl/m4/ltversion.m4 [new file with mode: 0644]
libltdl/m4/lt~obsolete.m4 [new file with mode: 0644]
libltdl/slist.c [new file with mode: 0644]
ltmain.sh [new file with mode: 0755]
missing [new file with mode: 0755]
src/Makefile.am [new file with mode: 0644]
src/Makefile.in [new file with mode: 0644]
src/aggregation.c [new file with mode: 0644]
src/amqp.c [new file with mode: 0644]
src/apache.c [new file with mode: 0644]
src/apcups.c [new file with mode: 0644]
src/apple_sensors.c [new file with mode: 0644]
src/aquaero.c [new file with mode: 0644]
src/ascent.c [new file with mode: 0644]
src/barometer.c [new file with mode: 0644]
src/battery.c [new file with mode: 0644]
src/bind.c [new file with mode: 0644]
src/ceph.c [new file with mode: 0644]
src/cgroups.c [new file with mode: 0644]
src/collectd-email.5 [new file with mode: 0644]
src/collectd-email.pod [new file with mode: 0644]
src/collectd-exec.5 [new file with mode: 0644]
src/collectd-exec.pod [new file with mode: 0644]
src/collectd-java.5 [new file with mode: 0644]
src/collectd-java.pod [new file with mode: 0644]
src/collectd-nagios.1 [new file with mode: 0644]
src/collectd-nagios.c [new file with mode: 0644]
src/collectd-nagios.pod [new file with mode: 0644]
src/collectd-perl.5 [new file with mode: 0644]
src/collectd-perl.pod [new file with mode: 0644]
src/collectd-python.5 [new file with mode: 0644]
src/collectd-python.pod [new file with mode: 0644]
src/collectd-snmp.5 [new file with mode: 0644]
src/collectd-snmp.pod [new file with mode: 0644]
src/collectd-tg.1 [new file with mode: 0644]
src/collectd-tg.c [new file with mode: 0644]
src/collectd-tg.pod [new file with mode: 0644]
src/collectd-threshold.5 [new file with mode: 0644]
src/collectd-threshold.pod [new file with mode: 0644]
src/collectd-unixsock.5 [new file with mode: 0644]
src/collectd-unixsock.pod [new file with mode: 0644]
src/collectd.1 [new file with mode: 0644]
src/collectd.conf.5 [new file with mode: 0644]
src/collectd.conf.in [new file with mode: 0644]
src/collectd.conf.pod [new file with mode: 0644]
src/collectd.pod [new file with mode: 0644]
src/collectdctl.1 [new file with mode: 0644]
src/collectdctl.c [new file with mode: 0644]
src/collectdctl.pod [new file with mode: 0644]
src/collectdmon.1 [new file with mode: 0644]
src/collectdmon.c [new file with mode: 0644]
src/collectdmon.pod [new file with mode: 0644]
src/config.h.in [new file with mode: 0644]
src/conntrack.c [new file with mode: 0644]
src/contextswitch.c [new file with mode: 0644]
src/cpu.c [new file with mode: 0644]
src/cpufreq.c [new file with mode: 0644]
src/cpython.h [new file with mode: 0644]
src/csv.c [new file with mode: 0644]
src/curl.c [new file with mode: 0644]
src/curl_json.c [new file with mode: 0644]
src/curl_xml.c [new file with mode: 0644]
src/daemon/Makefile.am [new file with mode: 0644]
src/daemon/Makefile.in [new file with mode: 0644]
src/daemon/collectd.c [new file with mode: 0644]
src/daemon/collectd.h [new file with mode: 0644]
src/daemon/common.c [new file with mode: 0644]
src/daemon/common.h [new file with mode: 0644]
src/daemon/common_test.c [new file with mode: 0644]
src/daemon/configfile.c [new file with mode: 0644]
src/daemon/configfile.h [new file with mode: 0644]
src/daemon/filter_chain.c [new file with mode: 0644]
src/daemon/filter_chain.h [new file with mode: 0644]
src/daemon/meta_data.c [new file with mode: 0644]
src/daemon/meta_data.h [new file with mode: 0644]
src/daemon/plugin.c [new file with mode: 0644]
src/daemon/plugin.h [new file with mode: 0644]
src/daemon/plugin_mock.c [new file with mode: 0644]
src/daemon/types_list.c [new file with mode: 0644]
src/daemon/types_list.h [new file with mode: 0644]
src/daemon/utils_avltree.c [new file with mode: 0644]
src/daemon/utils_avltree.h [new file with mode: 0644]
src/daemon/utils_avltree_test.c [new file with mode: 0644]
src/daemon/utils_cache.c [new file with mode: 0644]
src/daemon/utils_cache.h [new file with mode: 0644]
src/daemon/utils_cache_mock.c [new file with mode: 0644]
src/daemon/utils_complain.c [new file with mode: 0644]
src/daemon/utils_complain.h [new file with mode: 0644]
src/daemon/utils_heap.c [new file with mode: 0644]
src/daemon/utils_heap.h [new file with mode: 0644]
src/daemon/utils_heap_test.c [new file with mode: 0644]
src/daemon/utils_llist.c [new file with mode: 0644]
src/daemon/utils_llist.h [new file with mode: 0644]
src/daemon/utils_match.c [new file with mode: 0644]
src/daemon/utils_match.h [new file with mode: 0644]
src/daemon/utils_random.c [new file with mode: 0644]
src/daemon/utils_random.h [new file with mode: 0644]
src/daemon/utils_subst.c [new file with mode: 0644]
src/daemon/utils_subst.h [new file with mode: 0644]
src/daemon/utils_tail.c [new file with mode: 0644]
src/daemon/utils_tail.h [new file with mode: 0644]
src/daemon/utils_tail_match.c [new file with mode: 0644]
src/daemon/utils_tail_match.h [new file with mode: 0644]
src/daemon/utils_threshold.c [new file with mode: 0644]
src/daemon/utils_threshold.h [new file with mode: 0644]
src/daemon/utils_time.c [new file with mode: 0644]
src/daemon/utils_time.h [new file with mode: 0644]
src/daemon/utils_time_mock.c [new file with mode: 0644]
src/dbi.c [new file with mode: 0644]
src/df.c [new file with mode: 0644]
src/disk.c [new file with mode: 0644]
src/dns.c [new file with mode: 0644]
src/drbd.c [new file with mode: 0644]
src/email.c [new file with mode: 0644]
src/entropy.c [new file with mode: 0644]
src/ethstat.c [new file with mode: 0644]
src/exec.c [new file with mode: 0644]
src/fhcount.c [new file with mode: 0644]
src/filecount.c [new file with mode: 0644]
src/fscache.c [new file with mode: 0644]
src/gmond.c [new file with mode: 0644]
src/hddtemp.c [new file with mode: 0644]
src/interface.c [new file with mode: 0644]
src/ipc.c [new file with mode: 0644]
src/ipmi.c [new file with mode: 0644]
src/iptables.c [new file with mode: 0644]
src/ipvs.c [new file with mode: 0644]
src/irq.c [new file with mode: 0644]
src/java.c [new file with mode: 0644]
src/libcollectdclient/Makefile.am [new file with mode: 0644]
src/libcollectdclient/Makefile.in [new file with mode: 0644]
src/libcollectdclient/client.c [new file with mode: 0644]
src/libcollectdclient/collectd/client.h [new file with mode: 0644]
src/libcollectdclient/collectd/lcc_features.h [new file with mode: 0644]
src/libcollectdclient/collectd/lcc_features.h.in [new file with mode: 0644]
src/libcollectdclient/collectd/network.h [new file with mode: 0644]
src/libcollectdclient/collectd/network_buffer.h [new file with mode: 0644]
src/libcollectdclient/libcollectdclient.pc.in [new file with mode: 0644]
src/libcollectdclient/network.c [new file with mode: 0644]
src/libcollectdclient/network_buffer.c [new file with mode: 0644]
src/liboconfig/AUTHORS [new file with mode: 0644]
src/liboconfig/COPYING [new file with mode: 0644]
src/liboconfig/ChangeLog [new file with mode: 0644]
src/liboconfig/Makefile.am [new file with mode: 0644]
src/liboconfig/Makefile.in [new file with mode: 0644]
src/liboconfig/aux_types.h [new file with mode: 0644]
src/liboconfig/oconfig.c [new file with mode: 0644]
src/liboconfig/oconfig.h [new file with mode: 0644]
src/liboconfig/parser.c [new file with mode: 0644]
src/liboconfig/parser.h [new file with mode: 0644]
src/liboconfig/parser.y [new file with mode: 0644]
src/liboconfig/scanner.c [new file with mode: 0644]
src/liboconfig/scanner.l [new file with mode: 0644]
src/load.c [new file with mode: 0644]
src/log_logstash.c [new file with mode: 0644]
src/logfile.c [new file with mode: 0644]
src/lpar.c [new file with mode: 0644]
src/lvm.c [new file with mode: 0644]
src/madwifi.c [new file with mode: 0644]
src/madwifi.h [new file with mode: 0644]
src/match_empty_counter.c [new file with mode: 0644]
src/match_hashed.c [new file with mode: 0644]
src/match_regex.c [new file with mode: 0644]
src/match_timediff.c [new file with mode: 0644]
src/match_value.c [new file with mode: 0644]
src/mbmon.c [new file with mode: 0644]
src/md.c [new file with mode: 0644]
src/memcachec.c [new file with mode: 0644]
src/memcached.c [new file with mode: 0644]
src/memory.c [new file with mode: 0644]
src/mic.c [new file with mode: 0644]
src/modbus.c [new file with mode: 0644]
src/multimeter.c [new file with mode: 0644]
src/mysql.c [new file with mode: 0644]
src/netapp.c [new file with mode: 0644]
src/netlink.c [new file with mode: 0644]
src/network.c [new file with mode: 0644]
src/network.h [new file with mode: 0644]
src/nfs.c [new file with mode: 0644]
src/nginx.c [new file with mode: 0644]
src/notify_desktop.c [new file with mode: 0644]
src/notify_email.c [new file with mode: 0644]
src/ntpd.c [new file with mode: 0644]
src/numa.c [new file with mode: 0644]
src/nut.c [new file with mode: 0644]
src/olsrd.c [new file with mode: 0644]
src/onewire.c [new file with mode: 0644]
src/openldap.c [new file with mode: 0644]
src/openvpn.c [new file with mode: 0644]
src/oracle.c [new file with mode: 0644]
src/perl.c [new file with mode: 0644]
src/pf.c [new file with mode: 0644]
src/pinba.c [new file with mode: 0644]
src/pinba.proto [new file with mode: 0644]
src/ping.c [new file with mode: 0644]
src/postgresql.c [new file with mode: 0644]
src/postgresql_default.conf [new file with mode: 0644]
src/powerdns.c [new file with mode: 0644]
src/processes.c [new file with mode: 0644]
src/protocols.c [new file with mode: 0644]
src/pyconfig.c [new file with mode: 0644]
src/python.c [new file with mode: 0644]
src/pyvalues.c [new file with mode: 0644]
src/redis.c [new file with mode: 0644]
src/riemann.proto [new file with mode: 0644]
src/routeros.c [new file with mode: 0644]
src/rrdcached.c [new file with mode: 0644]
src/rrdtool.c [new file with mode: 0644]
src/sensors.c [new file with mode: 0644]
src/serial.c [new file with mode: 0644]
src/sigrok.c [new file with mode: 0644]
src/smart.c [new file with mode: 0644]
src/snmp.c [new file with mode: 0644]
src/statsd.c [new file with mode: 0644]
src/swap.c [new file with mode: 0644]
src/syslog.c [new file with mode: 0644]
src/table.c [new file with mode: 0644]
src/tail.c [new file with mode: 0644]
src/tail_csv.c [new file with mode: 0644]
src/tape.c [new file with mode: 0644]
src/target_notification.c [new file with mode: 0644]
src/target_replace.c [new file with mode: 0644]
src/target_scale.c [new file with mode: 0644]
src/target_set.c [new file with mode: 0644]
src/target_v5upgrade.c [new file with mode: 0644]
src/tcpconns.c [new file with mode: 0644]
src/teamspeak2.c [new file with mode: 0644]
src/ted.c [new file with mode: 0644]
src/testing.h [new file with mode: 0644]
src/thermal.c [new file with mode: 0644]
src/threshold.c [new file with mode: 0644]
src/tokyotyrant.c [new file with mode: 0644]
src/turbostat.c [new file with mode: 0644]
src/types.db [new file with mode: 0644]
src/types.db.5 [new file with mode: 0644]
src/types.db.pod [new file with mode: 0644]
src/unixsock.c [new file with mode: 0644]
src/uptime.c [new file with mode: 0644]
src/users.c [new file with mode: 0644]
src/utils_cmd_flush.c [new file with mode: 0644]
src/utils_cmd_flush.h [new file with mode: 0644]
src/utils_cmd_getthreshold.c [new file with mode: 0644]
src/utils_cmd_getthreshold.h [new file with mode: 0644]
src/utils_cmd_getval.c [new file with mode: 0644]
src/utils_cmd_getval.h [new file with mode: 0644]
src/utils_cmd_listval.c [new file with mode: 0644]
src/utils_cmd_listval.h [new file with mode: 0644]
src/utils_cmd_putnotif.c [new file with mode: 0644]
src/utils_cmd_putnotif.h [new file with mode: 0644]
src/utils_cmd_putval.c [new file with mode: 0644]
src/utils_cmd_putval.h [new file with mode: 0644]
src/utils_crc32.c [new file with mode: 0644]
src/utils_crc32.h [new file with mode: 0644]
src/utils_db_query.c [new file with mode: 0644]
src/utils_db_query.h [new file with mode: 0644]
src/utils_dns.c [new file with mode: 0644]
src/utils_dns.h [new file with mode: 0644]
src/utils_fbhash.c [new file with mode: 0644]
src/utils_fbhash.h [new file with mode: 0644]
src/utils_format_graphite.c [new file with mode: 0644]
src/utils_format_graphite.h [new file with mode: 0644]
src/utils_format_json.c [new file with mode: 0644]
src/utils_format_json.h [new file with mode: 0644]
src/utils_ignorelist.c [new file with mode: 0644]
src/utils_ignorelist.h [new file with mode: 0644]
src/utils_latency.c [new file with mode: 0644]
src/utils_latency.h [new file with mode: 0644]
src/utils_mount.c [new file with mode: 0644]
src/utils_mount.h [new file with mode: 0644]
src/utils_mount_test.c [new file with mode: 0644]
src/utils_parse_option.c [new file with mode: 0644]
src/utils_parse_option.h [new file with mode: 0644]
src/utils_rrdcreate.c [new file with mode: 0644]
src/utils_rrdcreate.h [new file with mode: 0644]
src/utils_vl_lookup.c [new file with mode: 0644]
src/utils_vl_lookup.h [new file with mode: 0644]
src/utils_vl_lookup_test.c [new file with mode: 0644]
src/uuid.c [new file with mode: 0644]
src/varnish.c [new file with mode: 0644]
src/virt.c [new file with mode: 0644]
src/vmem.c [new file with mode: 0644]
src/vserver.c [new file with mode: 0644]
src/wireless.c [new file with mode: 0644]
src/write_graphite.c [new file with mode: 0644]
src/write_http.c [new file with mode: 0644]
src/write_kafka.c [new file with mode: 0644]
src/write_log.c [new file with mode: 0644]
src/write_mongodb.c [new file with mode: 0644]
src/write_redis.c [new file with mode: 0644]
src/write_riemann.c [new file with mode: 0644]
src/write_riemann_threshold.c [new file with mode: 0644]
src/write_sensu.c [new file with mode: 0644]
src/write_tsdb.c [new file with mode: 0644]
src/xmms.c [new file with mode: 0644]
src/zfs_arc.c [new file with mode: 0644]
src/zookeeper.c [new file with mode: 0644]
version-gen.sh [new file with mode: 0755]
ylwrap [new file with mode: 0755]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..3f63c3d
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,301 @@
+Permanent project members
+=========================
+
+Florian "octo" Forster <octo at verplant.org>
+ - Initial author.
+
+Sebastian "tokkee" Harl <sh at tokkee.org>
+ - Bugfixes and enhancements in many places all around the project.
+ - perl plugin.
+ - users plugin.
+ - vserver plugin.
+ - Debian package.
+
+
+Contributors (sorted alphabetically)
+====================================
+
+Akkarit Sangpetch <asangpet at andrew.cmu.edu>
+ - write_mongodb plugin.
+
+Alessandro Iurlano <alessandro.iurlano at gmail.com>
+ - Initial filecount plugin.
+
+Alex Deymo <deymo at chromium.org>
+ - aquaero plugin.
+
+Alvaro Barcellos <alvaro.barcellos at gmail.com>
+ - Don't-fork patch.
+
+Amit Gupta <amit.gupta221 at gmail.com>
+ - Multiple servers in the apache plugin.
+ - curl_xml plugin.
+
+Andreas Henriksson <andreas at fatal.se>
+ - libmnl support in the netlink plugin.
+
+Andy Parkins <andyp at fussylogic.co.uk>
+ - battery plugin: sysfs code.
+
+Anthony Dewhurst <dewhurst at gmail.com>
+ - zfs_arc plugin.
+
+Anthony Gialluca <tonyabg at charter.net>
+ - apcups plugin.
+
+Antony Dovgal <tony at daylessday.org>
+ - memcached plugin.
+
+Aurélien Reynaud <collectd at wattapower.net>
+ - LPAR plugin.
+ - Various fixes for AIX, HP-UX and Solaris.
+
+Benjamin Gilbert <bgilbert at cs.cmu.edu>
+ - Improvements to the LVM plugin.
+
+Bert Vermeulen <bert at biot.com>
+ - sigrok plugin
+
+Brett Hawn <bhawn at llnw.com>
+ - write_tsdb plugin for http://opentsdb.net/
+
+Bruno Prémont <bonbons at linux-vserver.org>
+ - BIND plugin.
+ - Many bug reports and -fixes in various plugins,
+   especially a nasty bug in the network plugin.
+ - Wireshark dissector.
+
+Chad Malfait <malfaitc at yahoo.com>
+ - LVM plugin.
+
+Chris Lundquist <clundquist at bluebox.net>
+ - Improvements to the write_mongodb plugin.
+
+Christophe Kalt <collectd at klb.taranis.org>
+ - The version 3 `log' mode.
+ - Many Solaris related hints and fixes.
+
+Cyril Feraudet <cyril at feraudet.com>
+ - ethstat plugin.
+
+Dan Berrange <berrange at redhat.com>
+ - uuid plugin.
+
+Dan Ryder <daryder at cisco.com>
+ - ceph plugin.
+
+David Bacher <drbacher at gmail.com>
+ - serial plugin.
+
+Doug MacEachern <dougm at hyperic.com>
+ - The `-T' option (config testing mode).
+ - OpenVPN plugin.
+ - jcollectd (two-way JMX integration).
+ - A few other patches to various plugins.
+ - curl_json plugin.
+
+Edward “Koko” Konetzko <konetzed at quixoticagony.com>
+ - fscache plugin.
+
+Evan Felix <evan.felix at pnnl.gov>
+ - mic plugin.
+
+Fabian Linzberger <e at lefant.net>
+ - Percentage aggregation for `collectd-nagios'.
+
+Fabien Wernli <cpan at faxm0dem.org>
+ - Solaris improvements in the memory and interfaces plugin.
+
+Fabrice A. Marie <fabrice at kibinlabs.com>
+ - write_sensu plugin.
+
+Flavio Stanchina <flavio at stanchina.net>
+ - mbmon plugin.
+
+Franck Lombardi
+ - UNIX socket code for the memcached plugin.
+
+Jason Pepas <cell at ices.utexas.edu>
+ - nfs plugin.
+
+J. Javier Maestro <jjmaestro at ieee.org>
+ - Write-Graphite plugin: UDP support and LogSendErrors flag.
+
+Jeremy Katz <jeremy at katzbox.net>
+ - percentage reporting in memory and swap plugins.
+ - zookeeper plugin.
+
+Jérôme Renard <jerome.renard at gmail.com>
+ - varnish plugin.
+
+Jiri Tyr <jiri.tyr at gmail.com>
+ - fhcount plugin.
+
+Kevin Bowling <kbowling at llnw.com>
+ - write_tsdb plugin for http://opentsdb.net/
+
+Kimo Rosenbaum <kimor79 at yahoo.com>
+ - openldap plugin.
+
+Kris Nielander <nielander at fox-it.com>
+ - tail_csv plugin.
+
+Luboš Staněk <kolektor at atlas.cz>
+ - sensors plugin improvements.
+ - Time and effort to find a nasty bug in the ntpd-plugin.
+
+Luke Herberling <collectd at c-ware.com>
+ - powerdns plugin.
+ - Initial `tail' subsystem by:
+
+Lyonel Vincent <lyonel at ezix.org>
+ - processes plugin.
+
+Manuel Sanmartin
+ - AIX port of the following plugins:
+   + cpu
+   + disk
+   + interface
+   + load
+   + memory
+   + processes
+   + swap
+ - Various AIX-related fixes and hacks.
+
+Marc Fournier <marc.fournier at camptocamp.com>
+ - Various fixes to the varnish plugin.
+ - RPM specfile update.
+ - libmnl support in the netlink plugin.
+ - linux support in the zfs_arc plugin.
+ - openldap plugin.
+
+Marco Chiappero <marco at absence.it>
+ - uptime plugin.
+ - ip6tables support in the iptables plugin.
+ - openvpn plugin (support for more status file formats)
+
+Michael Hanselmann <public at hansmi.ch>
+ - md plugin.
+
+Michael Schenck <mschenck at digitalocean.com>
+ - IO time support to disk plugin.
+
+Michael Stapelberg <michael+git at stapelberg.de>
+ - OpenBSD port of the tcpconns plugin.
+ - cgroups plugin.
+
+Michał Mirosław <mirq-linux at rere.qmqm.pl>
+ - thermal plugin.
+ - Streamlines recursive directory traversion.
+
+Mirko Buffoni <briareos at eswat.org>
+ - Port/Socket selection in the MySQL plugin.
+
+Niki W. Waibel <niki.waibel at newlogic.com>
+ - Initial autotools fixes.
+ - libltdl code.
+ - getmnt-wizardry.
+
+Oleg King <king2 at kaluga.ru>
+ - Added support for the statgrab library to
+   + the cpu plugin,
+   + the disk plugin, and
+   + the users plugin.
+
+Ondrej Zajicek <santiago at crfreenet.org>
+ - madwifi plugin.
+
+Patrik Weiskircher <weiskircher at inqnet.at>
+ - Contextswitch plugin.
+ - Forkrate counter in the processes plugin.
+ - INode count in the DF plugin.
+
+Paul Sadauskas <psadauskas at gmail.com>
+ - tokyotyrant plugin.
+ - `ReportByDevice' option of the df plugin.
+ - write_http plugin.
+
+Peter Holik <peter at holik.at>
+ - cpufreq plugin.
+ - multimeter plugin.
+ - irq plugin.
+ - Some bugfixes in the exec plugin.
+ - Notifications in the ipmi plugin.
+
+Phoenix Kayo <kayo.k11.4 at gmail.com>
+ - pinba plugin.
+
+Pierre-Yves Ritschard <pyr at spootnik.org>
+ - Write-Riemann plugin.
+ - Write-Graphite plugin: Notification support.
+ - Write-Kafka plugin.
+ - Log-Logstash plugin.
+ - Normalization in the CPU plugin.
+ - Relative values in the Load plugin.
+
+Piotr Hosowicz <the55 at wp.pl>
+ - SMF manifest for collectd.
+
+Richard W. M. Jones <rjones at redhat.com>
+ - virt plugin.
+ - uuid plugin.
+
+Roman Klesel <roman.klesel at noris.de>
+ - Oracle schema and sample SQL statements to be used with the Oracle plugin.
+
+Rodolphe Quiédeville <rquiedeville at bearstech.com>
+ - Lock statistics in the mysql plugin.
+
+Scott Garrett <sgarrett at technomancer.com>
+ - tape plugin.
+
+Scott Sanders <scott at jssjr.com>
+ - Write-Graphite plugin.
+
+Sebastien Pahl <sebastien.pahl at dotcloud.com>
+ - AMQP plugin.
+
+Simon Kuhnle <simon at blarzwurst.de>
+ - OpenBSD code for the cpu and memory plugins.
+
+Sjoerd van der Berg <harekiet at gmail.com>
+ - iptables plugin.
+
+Stefan Hacker <stefan.hacker at web.de>
+ - teamspeak2 plugin.
+
+Sven Trenkel <collectd at semidefinite.de>
+ - netapp plugin.
+ - python plugin.
+
+Tim Laszlo <tim.laszlo at gmail.com>
+ - drbd plugin.
+
+Thomas Meson <zllak at hycik.org>
+ - Graphite support for the AMQP plugin.
+
+Tomasz Pala <gotar at pld-linux.org>
+ - conntrack plugin.
+
+Tommie Gannert <d00-tga at d.kth.se>
+ - PID-file patch.
+
+Vincent Bernat <vincent at bernat.im>
+ - smart plugin.
+
+Vincent Brillault <git at lerya.net>
+ - turbostat plugin, based on Len Brown <len.brown at intel.com> kernel tool
+
+Vincent Stehlé <vincent.stehle at free.fr>
+ - hddtemp plugin.
+
+Wilfried Goesgens <dothebart at citadel.org>
+ - linux support in the zfs_arc plugin.
+
+Xin Li <delphij at freebsd.org>
+ - FreeBSD port of the ZFS-ARC plugin.
+
+collectd is available at:
+  <http://collectd.org/>
+
+Enjoy :)
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..191af71
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,371 @@
+collectd consists of a daemon and numerous plugins. The daemon is licensed
+under the "MIT License"; its source files are located at src/daemon/. The
+plugins are licenses individually, please check the top of the plugin's source
+file(s) to see which license applies. The majority of plugins is licensed
+either under the "MIT License" or the "GNU General Public License".
+
+The "MIT License" and "GNU General Public License" follow. Other licenses, not
+included in this file, should be considered "as published by the Open Source
+Initiative (OSI)".
+
+MIT License
+===========
+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.
+
+GNU General Public License (GPL)
+================================
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..b0a997c
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,2898 @@
+2015-05-27, Version 5.5.0
+       * Build system: Ability to make out-of-tree builds has been fixed.
+         Thanks to Vincent Bernat. #792
+       * Build system, Disk and Users plugins: Detection and use of libstatgrab
+         ≧ 0.90 has been added. Thanks to Vincent Bernat. #445, #795, #806,
+         #807, #908
+       * Build system, Memory, CPU, TCPConns and Processes plugins: Numerous
+         fixes related to OpenBSD support have been added. Thanks to Landry
+         Breuil. #777, #778, #779, #808
+       * Build system: Plugins now only export "module_register()". Thanks to
+         Florian Forster.
+       * Build system: Various cleanups and improvements have been done. Thanks
+         to Marc Fournier.
+       * collectd: Numerous internal changes and improvements to the daemon and
+         the plugin API have been make. Thanks to Florian Forster, Pierre-Yves
+         Ritschard and Alex Petrov. #512, #727
+       * collectd: Numerous spelling mistakes have been corrected in comments
+         and documentation and several error messages have been improved.
+         Thanks to Ruben Kerkhof, Abhinav Upadhyay, Olivier Bazoud, Pierre-Yves
+         Ritschard, Tim Smith, Moshe Zada, Katelyn Perry and Marc Fournier.
+       * collectd: Rules/Targets can now be appended to existing Filter Chains.
+         Thanks to Marc Falzon. #444
+       * collectd: Failing Filter Chains destinations will now log the list of
+         available write targets. Thanks to Wilfried Goesgens. #650, #1043
+       * collectd: Support for process signaling and management by upstart and
+         systemd has been implemented for the Linux platform. Thanks to
+         Pierre-Yves Ritschard and Marc Fournier. #798, #811, #814
+       * collectd: The "CollectInternalStats" option has been added. Thanks to
+         Yves Mettier. #691
+       * collectd: The daemon source code and dependencies have moved to the
+         "src/daemon/" directory. Thanks to Florian Forster.
+       * collectd: The new "MaxReadInterval" option allows to cap the
+         exponential retry interval of plugins read errors. Thanks to Alexey
+         Remizov and Florian Forster. #713
+       * collectd: The "-P" command-line option now has precedence over the
+         "PIDFile" option. Thanks to Thomas D. #553
+       * collection.cgi: Various data-source related adjustments have been
+         made. Thanks to Fabiano Pires and Sebastian Harl.
+       * libcollectdclient: Now propagates errors when signing / encrypting
+         network packets. Thanks to Florian Forster.
+       * Configuration: Support for unquoted IPv6 addresses has been added.
+         Thanks to Sebastian Harl. #489
+       * Documentation: Various improvements have been done. Thanks to Florian
+         Forster and Marc Fournier.
+       * Examples: the sample C plugin has been updated to the current plugin
+         API. Thanks to Sebastian Harl.
+       * Licensing: The following components have been relicensed to the MIT
+         license: the Apple Sensors, Ascent, DBI, E-Mail, Entropy, GenericJMX,
+         gmond, LogFile, nginx, Notify Desktop, NTPd, NUT, olsrd, Perl, Ping,
+         PostgreSQL, Protocols, RouterOS, RRDCacheD, SNMP, StatsD, SysLog,
+         Table, Tail, UnixSock, vmem, VServer, Wireless, Write Riemann and XMMS
+         plugins, the core collectd daemon, the collectdmon, collectd-nagios
+         and collectd-tg utilities, all the Targets and Matches, liboconfig,
+         most of the "utils_*" files and the plugin API.
+       * Tests: A test suite has been added. Thanks to Florian Forster.
+       * Threshold: The hysteresis calculation has been made more reliable.
+         Thanks to Jan Kundrát. #581
+       * Threshold: Various fixes and improvements have been made. Thanks to
+         Manuel Luis Sanmartín Rozada. #649, #644
+       * AMQP plugin: The "ConnectionRetryDelay" option has been added,
+         allowing to delay reconnection. Thanks to Yoga Ramalingam and Marc
+         Fournier. #833
+       * AMQP plugin: The "QueueDurable" and "QueueAutoDelete" options have
+         been added, giving control over queue creation and deletion. Thanks to
+         David Blundell and Marc Fournier. #623
+       * Apache, Ascent, BIND, cURL, cURL-JSON, cURL-XML, nginx and Write HTTP
+         plugins: Customizing the "User-Agent" field is now possible at
+         compile-time. Thanks to Jeremy Katz. #440
+       * Apache, Ascent, BIND, cURL, cURL-JSON, cURL-XML, nginx plugins: The
+         connection will be reset if it hasn't completed within the configured
+         "Interval". The new "Timeout" option gives control over this behavior.
+         Thanks to Jan Kundrát and Marc Fournier. #982, #983, #993
+       * Apache, Ascent, cURL, cURL-JSON, cURL-XML, nginx, Write HTTP plugins:
+         Allow usernames and passwords to contain colons if built against
+         libcurl ≧ 7.19.1. Thanks to Marc Fournier. #695, #947
+       * Apache plugin: The "SSLCiphers" option gives control over the
+         encryption algorithms to use with TLS connections. Thanks to Toni
+         Moreno. #946
+       * Barometer plugin: This new plugin reads sensor data from various
+         Freescale and Bosch digital barometers. Thanks to Tomas Menzl. #69,
+         #693
+       * Battery plugin: Reporting values as percentages and reporting degraded
+         batteries has been added. Thanks to Florian Forster.
+       * Battery plugin: Support for reading values from sysfs on Linux has
+         been added. Thanks to Andy Parkins, Nicholas Humfrey, Peter Wu and
+         Florian Forster. #725, #810, #998
+       * Battery plugin: The value for current is no longer supplied unless the
+         battery provides this information. Thanks to Florian Forster.
+       * BIND plugin: Bind's XML v3 API is now supported; Thanks to Victor
+         Berger, Bruno Prémont and Michal Humpula. #742, #847
+       * Ceph plugin: This new plugin collects statistics from the Ceph
+         distributed storage system. Thanks to Dan Ryder, Dennis Zou, Colin
+         McCabe, Sage Weil. #522, #598
+       * ConnTrack plugin: Support for reporting values as percentages as well
+         as legacy conntrack files in "/proc" has been added. Thanks to
+         Pierre-Yves Ritschard. #497, #680
+       * CPU plugin: The plugin is now able to report values as percentages and
+         aggregate values per-state and per-CPU. Thanks to Pierre-Yves
+         Ritschard, Florian Forster, Fabien Wernli, Nicholas Humfrey and
+         Wilfried Goesgens. #499, #516, #639 #734, #812, #802
+       * cURL-JSON plugin: Extracting values from complex JSON structures has
+         been enhanced. Thanks to Jim Radford. #408, #411
+       * cURL-JSON plugin: Intervals can now be configured on a per-URL basis.
+         Thanks to Stan Sawa. #685
+       * cURL-JSON, cURL-XML, Write HTTP plugins: These plugins now also follow
+         HTTP redirects. Thanks to Marc Fournier.
+       * cURL, cURL-JSON, cURL-XML plugins: HTTP Digest authentication has been
+         implemented. Thanks to Frank Cornelis. #482
+       * DBI, Oracle, PostgreSQL plugins: A "MetadataFrom" parameter has been
+         added which allows to set metadata from database columns. Thanks to
+         Mark Wong. #317, #321
+       * DBI plugin: Querying several databases in parallel is now possible.
+         Thanks to Vincent Bernat. #453
+       * Disk plugin: On the Linux platform, disk names can now get looked up
+         in udev with the "UdevNameAttr" option. Thanks to Patrick Mooney. #537
+       * Disk plugin: This plugin now collects several additional I/O-related
+         metrics on the Linux platform. Thanks to Florian Forster and Michael
+         Schenck. #705, #759
+       * DRBD plugin: This new plugin reads Linux's Distributed Replicated
+         Block Device (DRBD) statistics. Thanks to Tim Laszlo. #566, #700
+       * Exec, UnixSock plugins: The "PUTNOTIF" command now allows to set
+         metadata on notifications. Thanks to John-John Tedro. #416
+       * fhcount plugin: This new plugin reports the number of used file
+         handles. Thanks to Jiri Tyr. #1009
+       * GenericJMX plugin: A Class Loader for "JMXConnectorFactory" has been
+         added, allowing the plugin to work with JBOSS > 7. Thanks to Alexandre
+         Moutot. #452
+       * IPC plugin: This new plugin collects information related to shared
+         memory. Thanks to Andrés J. Díaz. #925
+       * Java plugin: Now uses the hostname defined in the configuration file.
+         Thanks to Pierre-Yves Ritschard. #530, #681
+       * Load plugin: The plugin is now able to report values as percentages.
+         Thanks to Vedran Bartonicek and Pierre-Yves Ritschard. #344, #498
+       * Log Logstash plugin: This new plugin writes collectd logs and events
+         as Logstash JSON formatted events. Thanks to Pierre-Yves Ritschard.
+         #360
+       * LVM plugin: The plugin collects thin pool data volumes size, and no
+         longer reports virtual volumes. Thanks to Benjamin Gilbert. #603
+       * memcached plugin: "listen_disabled_num" are now also reported. Thanks
+         to Matt Cottingham. #622
+       * Memory plugin: Slab memory reporting on the Linux platform has been
+         added. Thanks to Manuel CISSÉ and Marc Fournier. #560, #697
+       * Memory plugin: The plugin is now able to report values as percentages.
+         Thanks to Jeremy Katz, Florian Forster and Manuel CISSÉ. #501, #511,
+         #559
+       * Modbus plugin: Selecting between holding and input registers is now
+         possible. Thanks to Jan Vitek. #338
+       * Modbus plugin: Support for accessing devices through an RS-485 serial
+         port has been added. Thanks to Eric Sandeen.
+       * Multimeter plugin: This plugin isn't built by default on the AIX
+         platform anymore. Thanks to Manuel Luis Sanmartin Rozada. #549, #684
+       * MySQL and PostgreSQL plugins: Passing "127.0.0.1" as a host will now
+         result in the global Hostname being used in metric names. Thanks to
+         Jeremy Katz. #441
+       * MySQL plugin: InnoDB, Select and Sort statistics collection has been
+         added. Thanks to Wilson Felipe, Marek Becka and Pierre-Yves Ritschard.
+         #248, #621, #699, #824
+       * MySQL plugin: The "Alias" and "ConnectTimeout" options have been
+         added. Thanks to William Tisäter.
+       * Netlink plugin: Support for 64bit netlink counters has been added.
+         Thanks to Marek Becka. #435
+       * Network plugin: The "ReconnectInterval" configuration option has been
+         added. Thanks to John Ferlito. #732
+       * NFS plugin: Support for NFSv4.0 has been implemented. Thanks to Marek
+         Becka. #550
+       * OneWire plugin: Support for more temperature-providing sensor families
+         has been added. Thanks to Tomasz Torcz. #672
+       * OneWire plugin: Support for full OWFS path and more device families
+         has been implemented. Thanks to Tomas Menzl. #68
+       * OpenLDAP plugin: This new plugin reads monitoring information from
+         OpenLDAP's "cn=Monitor" subtree. Thanks to Kimo Rosenbaum, Marc
+         Fournier and Nicholas Humfrey. #719
+       * OpenVPN plugin: Support for OpenVPN 2.3.0 has been implemented. Thanks
+         to Ed Okerson. #252
+       * OpenVZ plugin: Various improvements have been made, making the plugin
+         report values like the other collectd plugins do. Thanks to Chris
+         Lundquist. #264
+       * Perl plugin: A new "listval_filter" method has been added, various
+         internal cleanups and improvements have been made and a test suite has
+         been added. Thanks to Matthias Bethke. #728
+       * PostgreSQL plugin: The new "ExpireDelay" option allows skipping older
+         values pending write when the database slows down. Thanks to Stephen
+         O'Dor. #593
+       * PowerDNS plugin: The plugin was updated for stats from pdns 3.4.3.
+         Thanks to Ruben Kerkhof. #965
+       * Processes plugin: A memory-usage related optimization for low-profile
+         systems has been added. Thanks to Florian Forster. #652
+       * Python plugin: Support for Python3 has been improved, "ModulePath" is
+         now prepended to "sys.path", and the "get_dataset()" function has been
+         added to the Python API. Thanks to Sven Trenkel and Patrick Browne.
+         #890, #751, #771
+       * Redis and Write_Redis plugins: The support library has been switched
+         from credis to hiredis. Thanks to Andrés J. Díaz, Victor Seva, Marc
+         Fournier, Johan Bergström, Michael Spiegle and brianpkelly. #296,
+         #464, #475, #799, #1030
+       * Redis plugin: Custom commands can now be used to fetch values stored
+         in Redis. Thanks to Pierre-Yves Ritschard. #816
+       * Redis plugin: Support for passwords up to 512 characters long has been
+         added. Thanks to Jeremy Katz. #532
+       * Sensors plugin: Support for lm_sensors' power sensors has been added.
+         Thanks to Jan Kundrát. #571
+       * SMART plugin: This new plugin collects SMART statistics from disk
+         drives. Thanks to Vincent Bernat. #797
+       * SNMP plugin: A blacklist/whitelist feature can now be used to filter
+         which OIDs to collect. Thanks to Christophe Courtaut. #414
+       * SNMP plugin: SNMPv3 authentication and encryption support has been
+         implemented. Thanks to Michael Pilat. #362
+       * SNMP plugin: Two error messages have been disambiguated. Thanks to
+         Sergey. #939, #952
+       * Swap plugin: The plugin is now able to report values as percentages.
+         Thanks to Jeremy Katz and Florian Forster. #500, #510
+       * Swap plugin: The plugin no longer fails on Linux systems where
+         "SwapCached" isn't exposed by the kernel. Thanks to Florian Forster.
+         #733
+       * Tail plugin: "GaugeInc" and "GaugeAdd" options have been implemented.
+         Thanks to Andre Ferraz. #673
+       * Tail plugin: Intervals can now be configured on a per-File basis.
+         Thanks to Tom Leaman. #446
+       * TCPConns plugin: The "AllPortsSummary" option, allowing to summarize
+         all connections, has been added. Thanks to Marek Becka. #488
+       * TCPConns plugin: Three metrics were renamed on the AIX platform, for
+         the sake of consistency. Thanks to Manuel Luis Sanmartín Rozada. #546
+       * Turbostat plugin: This new plugin reads CPU frequency and C-state
+         residency on modern Intel turbo-capable processors. Thanks to Vincent
+         Brillault, Jean Delvare and Nicolas Iooss. #651
+       * UnixSock plugin: The "GETTHRESHOLD" command has been re-added. Thanks
+         to Manuel Luis Sanmartín Rozada. #674
+       * Varnish plugin: Varnish 4 support has been added, as well as as
+         monitoring metrics only available in Varnish 4. Thanks to Marc
+         Fournier. #618, #783
+       * virt plugin: Guests memory usage is now also collected. Thanks to
+         Tiago Carvalho, jazzmes and Zollner Robert.
+       * virt plugin: It is now possible to chose between using guests' name or
+         UUID as plugin_instance. Thanks to Remi Ferrand. #385
+       * virt plugin: The libvirt plugin has been renamed to virt. Thanks to
+         Florian Forster.
+       * Write Graphite plugin: When the connection to graphite fails,
+         reconnection attempts are now limited to once per second. Thanks to
+         Florian Forster. #625
+       * Write HTTP plugin: Multi-instance support of this plugin has been
+         improved. The "<URL "url">" block has been deprecated in favor of
+         "<Node "identifier">". Thanks to Marc Fournier. #902
+       * Write HTTP plugin: Several TLS-related configuration options have been
+         added. Thanks to Ingmar Runge. #666
+       * Write HTTP plugin: The "LowSpeedLimit" and "Timeout" options allow to
+         reset slow/stalled network connections. Thanks to loginator17 and Marc
+         Fournier. #752, #985
+       * Write HTTP plugin: The size of the payload posted to the HTTP server
+         can now be controlled with the "BufferSize" option. Thanks to Florian
+         Forster. #722
+       * Write Kafka plugin: This new plugin sends data to Apache Kafka, a
+         distributed messaging queue. Thanks to Pierre-Yves Ritschard,
+         ciomaire, Vincent Bernat, Marc Fournier. #670, #694, #794, #853, #014
+       * Write Log plugin: This new plugin dispatches collected values to the
+         configured log destination(s). Thanks to Pierre-Yves Ritschard. #886
+       * Write Riemann plugin: Extra meta strings are now added as attributes
+         in notifications. Thanks to John-John Tedro. #417
+       * Write Riemann plugin: Notification message are now sent to the Riemann
+         server via the description field. Thanks to Adrian Miron. #575
+       * Write Riemann plugin: Support for custom attributes has been added.
+         Thanks to Pierre-Yves Ritschard. #459
+       * Write Riemann plugin: Support had been implemented for sending events
+         to Riemann in batches (when using TCP), and is enabled by default.
+         Thanks to Pierre-Yves Ritschard. #800
+       * Write Riemann plugin: The "EventServicePrefix" option has been added,
+         which adds a prefix to event service names. Thanks to Moshe Zada. #706
+       * Write Riemann plugin: Threshold checks can now be passed down to the
+         Riemann server. Thanks to Pierre-Yves Ritschard. #518
+       * Write Sensu plugin: This new plugin submits values to Sensu, a stream
+         processing and monitoring system. Thanks to Fabrice A. Marie and Marc
+         Fournier. #912, #1001, #1016
+       * Write TSDB plugin: This new plugin sends data to OpenTSDB, a scalable
+         time series database. Thanks to Kevin Bowling, Florian Forster, Dallin
+         Young, Michael Schenck and Pierre-Yves Ritschard. #703, #772, #945
+       * ZFS ARC plugin: Support for ZFS-on-Linux has been added. Thanks to
+         Marc Fournier and Wilfried Goesgens. #552
+       * Zookeeper plugin: This new plugin reads data from the Apache Zookeeper
+         "MNTR" command. Thanks to Jeremy Katz. #826
+
+2015-02-26, Version 5.4.2
+       * Build system: Numerous fixes. Thanks to Bjørn Nordbø, Jim Radford,
+         KOMEDA Shinji, Lauri Tirkkonen, Manuel Luis Sanmartin Rozada, Marc
+         Fournier, Rainer Müller, Yoga Ramalingam and Yves Mettier. #326,
+         #373, #653, #828
+       * collectd: A use-after-free has been fixed in the "parse_value()"
+         function. Thanks to Matthias Urlichs.
+       * collectd: Fix carriage return sign in types_list Thanks to Marc
+         Fournier and @NsLib.
+       * collectd: Fix programming error in src/configfile.c. Thanks to
+         Wilfried Goesgens.
+       * collectd: An off-by-one error has been fixed in the
+         "strstripnewline()" function. Patch by Florian Forster.
+       * collectd: Use the complain mechanism to report filter chain write
+         failures. Thanks to Sebastian Harl.
+       * collectd: Spelling and grammar of error messages have been fixed.
+         Thanks to Katelyn Perry and Tim Laszlo.
+       * collectdctl: Fixed buffering issues which caused trouble on AIX and
+         Solaris. Thanks to Yoga Ramalingam.
+       * Documentation: Details and example about multi-instance filterchain
+         targets have been added. Thanks to Marc Fournier.
+       * Documentation: The "CollectStatistics" option of the rrdcached has
+         been documented. Thanks to Micha Krause. #907
+       * Documentation: The write_redis has been documented. Thanks to Marc
+         Fournier.
+       * Documentation: The "GraphiteSeparateInstances" and
+         "GraphiteAlwaysAppendDS" options of the amqp have been documented.
+         Thanks to Marc Fournier.
+       * Documentation: Documentation of the "AutoLoadPlugin" option has been
+         improved. Thanks to Florian Forster. #715
+       * aggregation: "utils_vl_lookup": A race when creating user objects
+         has been fixed. Thanks to Sebastian Harl. #535
+       * cpu: Temperature code for Mac&nbsp;OS&nbsp;X has been removed.
+         Thanks to Florian Forster and Marc Fournier. #22
+       * cURL, cURL-JSON, cURL-XML and Write HTTP plugins: Call
+         "curl_global_init()" in the plugins' "init()" callback. Thanks to
+         Jeremy Katz.
+       * cURL and memcachec plugins: Fix calculation of gauge, average,
+         minimum and maximum. Previously, they were calculated from the start
+         of the daemon, which is not the documented behavior. Thanks to
+         Florian Forster. #663
+       * curl-json: A bug, which triggered when two URLs with a long common
+         prefix were configured, was fixed. Thanks to Marc Fournier. #582
+       * dbi: Compatibility with new versions of libdbi has been restored.
+         Thanks to Florian Forster. #950
+       * Exec, UnixSock plugins: Fix parsing of the "time" option of the
+         "PUTNOTIF" command. Thanks to Adrian Miron. #477
+       * ipmi: A conflict with the java over the "SIGUSR2" signal has been
+         fixed. Thanks to Vincent Bernat. #114
+       * java: Conversion from Java's time representation to collectd's
+         representation has been fixed. Thanks to Manuel Luis Sanmartín
+         Rozada.
+       * java: Make sure "cjni_thread_detach()" is called on all paths.
+         Thanks to Florian Forster.
+       * LogFile and SysLog plugins: Avoid total silence in case of a
+         misconfiguration. Thanks to Marc Fournier and Wilfried Goesgens.
+       * network: Support for recent versions of gcrypt has been added.
+         Thanks to Vincent Bernat. #632
+       * network: Robustness of the client connecting behavior has been
+         improved. Thanks to Florian Forster. #627
+       * python: Don't create empty "meta_data_t" objects. Thanks to Florian
+         Forster. #716
+       * python: Fix Py list length check in "cpy_build_meta()". Thanks to
+         Yoga Ramalingam.
+       * python: The "interval" member was fixed to export seconds as a
+         double. Thanks to Justin Burnham.
+       * RRDtool and RRDCacheD plugins: A memory leak when creating RRD files
+         has been fixed. Thanks to Yves Mettier. #661
+       * snmp: Fix a memory leak. Thanks to Marc Fournier and Pierre-Yves
+         Ritschard. #610, #804
+       * statsd: Support for samplerates in timer metrics was added. Thanks
+         to John Leach. #461
+       * swap: Fix behavior under OpenVZ by making "cached" optional. Thanks
+         to Florian Forster. #733
+       * threshold: Population of the "time" field in notifications has been
+         added. Thanks to Manuel Luis Sanmartín Rozada.
+       * libvirt: Only gather stats for running domains. Thanks to Ruben
+         Kerkhof.
+       * lvm: An issue with Volume Groups (VGs) without Logical Volumes (LVs)
+         has been fixed. Thanks to Jan Kundrát.
+       * write_graphite: Escape characters not supported by Graphite. Thanks
+         to Pierre-Yves Ritschard and Marc Fournier.
+       * write_http: Make callback names context-dependent. Thanks to Marc
+         Fournier. #821
+       * write_redis: A formatting bug, which resulted in totally unusable
+         numbers being transmitted to Redis, was fixed. Thanks to Marc
+         Fournier.
+       * write_riemann: Receive acknowledge message when using TCP. Thanks to
+         John-John Tedro.
+
+2014-01-26, Version 5.4.1
+       * amqp plugin: Add support for RabbitMQ 0.4.x to avoid compiler
+         warnings. Thanks to Sebastian Harl for implementing this.
+       * apache / network plugins: Improved initialization order hopefully
+         resolved gcrypt initialization problems.
+       * aquaero plugin: The type used to submit fan utilization was fixed.
+         Thanks to Alex Deymo for the patch.
+       * cgroups plugin: A small memory leak was fixed. Checking the existence
+         of a mount option without a value was fixed. More permissive parsing
+         of the cpuacct.stats file fixes support for some versions of Linux.
+         Thanks to Marc Fournier for bug reports and patches.
+       * curl plugin: Fix <Match> blocks without an instance. Thanks to
+         Alexander Golovko for reporting and Sebastian Harl for fixing this.
+       * curl_json plugin: Potentially invalid memory access has been
+         sanitized. Thanks to Jim Radford for his patch.
+       * interface plugin: Fix behavior under FreeBSD 10: Reporting of
+         per-address statistics caused duplicate updates to the same metric.
+         Thanks to demon / @trtrmitya for the patch.
+       * write_graphite plugin: Use TCP to connect to Graphite by default. The
+         default changed from TCP to UDP between 5.3.1 and 5.4.0, which is a
+         regression. Thanks to Marc Fournier for fixing this. Reconnect
+         behavior was improved. Thanks to Michael Hart for his patch.
+       * zfs_arc plugin: Collect "allocated" and "stolen" on FreeBSD only.
+
+2013-08-18, Version 5.4.0
+       * collectd: The "LoadPlugin" config option no longer attempts to load
+         plugins twice. If more than one "LoadPlugin" statement or block is
+         encountered, only the first will have any effect.
+       * collectd: The "AutoLoadPlugin" option allows to automatically load
+         plugins for which a configuration is found.
+       * collectd: The "WriteQueueLimitHigh" and "WriteQueueLimitLow" options
+         allow collectd to drop values when under stress, to avoid running out
+         of memory. Thanks to Yves Mettier for his patch.
+       * amqp plugin: The "GraphiteSeparateInstances" and
+         "GraphiteAlwaysAppendDS" options have been added. Thanks to Laurent
+         for the patch.
+       * aquaero plugin: This new plugin reads various metrics, e.g. fan
+         speeds and temperatures, from Aquaero 5, a fan and water cooling
+         control panel. Thanks to Alex Deymo for his patch.
+       * curl plugin: The "MeasureResponseCode" option has been added. Thanks
+         to Jan Matějka for his patch.
+       * curl_json plugin: Support for UNIX domain sockets and array wildcards
+         has been added. Thanks to Jim Radford for his patch.
+       * curl_xml plugin: Support for long URLs has been improved.
+       * cgroups plugin: This new plugin collects CPU accounting information
+         for processes in a cgroup. Thanks to Michael Stapelberg for his patch.
+       * df plugin: The "ValuesAbsolute" and "ValuesPercentage" options have
+         been added. Thanks to Vedran Bartonicek for the patch.
+       * exec plugin: Do UID / GID lookups before forking. This should prevent
+         a race condition in the NSS library. Thanks to Ceri Storey for the
+         patch.
+       * lvm plugin: This new plugin collects size information from Linux'
+         Logical Volume Manager (LVM). Thanks to Chad Malfait for his work.
+       * memcached plugin: Support for increment and decrement counts has been
+         added. Thanks to Blake Matheny for the patch.
+       * mic plugin: This new plugin collects CPU and memory usage, power
+         consumption and temperatures of Intel's Many-Integrated-Core (MIC)
+         architecture, such as Xeon Phi cards. Thanks to Evan Felix for his
+         work.
+       * netlink plugin: This plugin has been converted to use the supported
+         "libmnl" library. Thanks to Andreas Henriksson for his patch.
+       * nginx plugin: Collection of accepted and handled connections has been
+         added. Thanks to Patrick Shan for his patch.
+       * sigrok plugin: This new plugin collects metrics from sigrok, a signal
+         processing framework reading various hardware devices, from light
+         meters to spectrum analyzers. Thanks to Bert Vermeulen for his patch.
+       * statsd plugin: This new plugin listens to a UDP socket and reads
+         metrics in the StatsD format.
+       * varnish plugin: Many additional metrics have been added. Thanks to
+         Nick Stenning for his patch.
+       * write_graphite plugin: Support for "UDP" has been added. Thanks to
+         Javier Maestro for his patch.
+       * write_riemann plugin: The "TTLFactor" option has been added.
+       * zfs_arc plugin: Support for FreeBSD has been added. Thanks to Xin Li
+         for his patch.
+
+2015-02-26, Version 5.3.2
+       * Build system: Numerous fixes. Thanks to Bjørn Nordbø, Jim Radford,
+         KOMEDA Shinji, Lauri Tirkkonen, Manuel Luis Sanmartin Rozada, Marc
+         Fournier, Rainer Müller, Yoga Ramalingam and Yves Mettier. #326,
+         #373, #653, #828
+       * collectd: A use-after-free has been fixed in the "parse_value()"
+         function. Thanks to Matthias Urlichs.
+       * collectd: Fix carriage return sign in types_list Thanks to Marc
+         Fournier and @NsLib.
+       * collectd: Fix programming error in src/configfile.c Thanks to
+         Wilfried Goesgens.
+       * collectd: An off-by-one error has been fixed in the
+         "strstripnewline()" function. Patch by Florian Forster.
+       * collectd: Use the complain mechanism to report filter chain write
+         failures. Thanks to Sebastian Harl.
+       * collectd: Spelling and grammar of error messages have been fixed.
+         Thanks to Katelyn Perry and Tim Laszlo.
+       * collectdctl: Fixed buffering issues which caused trouble on AIX and
+         Solaris. Thanks to Yoga Ramalingam.
+       * Documentation: Details and example about multi-instance filterchain
+         targets have been added. Thanks to Marc Fournier.
+       * Documentation: The "CollectStatistics" option of the rrdcached has
+         been documented. Thanks to Micha Krause. #907
+       * Documentation: The write_redis has been documented. Thanks to Marc
+         Fournier.
+       * Documentation: The synopsis of the threshold has been fixed. Thanks
+         to Fabien Wernli.
+       * Documentation: The "GraphiteSeparateInstances" and
+         "GraphiteAlwaysAppendDS" options of the amqp have been documented.
+         Thanks to Marc Fournier.
+       * aggregation: "utils_vl_lookup": A race when creating user objects
+         has been fixed. Thanks to Sebastian Harl. #535
+       * cpu: Temperature code for Mac&nbsp;OS&nbsp;X has been removed.
+         Thanks to Florian Forster and Marc Fournier. #22
+       * csv: A regression which would lead to the "DataDir" option to be
+         ignored has been fixed. Thanks to Manuel Luis Sanmartin Rozada.
+       * curl, curl-json, curl-xml and write_http plugins: Call
+         "curl_global_init()" in the plugins' "init()" callback. Thanks to
+         Jeremy Katz.
+       * curl and memcachec plugins: Fix calculation of gauge, average,
+         minimum and maximum. Previously, they were calculated from the start
+         of the daemon, which is not the documented behavior. Thanks to
+         Florian Forster. #663
+       * dbi plugin: Compatibility with new versions of libdbi has been
+         restored. Thanks to Florian Forster. #950
+       * exec, unixsock plugins: Fix parsing of the "time" option of the
+         "PUTNOTIF" command. Thanks to Adrian Miron. #477
+       * java: Conversion from Java's time representation to collectd's
+         representation has been fixed. Thanks to Manuel Luis Sanmartín
+         Rozada.
+       * ipmi: A conflict with the java over the "SIGUSR2" signal has been
+         fixed. Thanks to Vincent Bernat. #114
+       * java: Make sure "cjni_thread_detach()" is called on all paths.
+         Thanks to Florian Forster.
+       * logfile and syslog plugins: Avoid total silence in case of a
+         misconfiguration. Thanks to Marc Fournier and Wilfried Goesgens.
+       * memcached: Connecting to a UNIX socket has been fixed. Thanks to Jim
+         Radford.
+       * network: Support for recent versions of gcrypt has been added.
+         Thanks to Vincent Bernat. #632
+       * network: Robustness of the client connecting behavior has been
+         improved. Thanks to Florian Forster. #627
+       * python: Don't create empty "meta_data_t" objects. Thanks to Florian
+         Forster. #716
+       * python: Fix Py list length check in "cpy_build_meta()". Thanks to
+         Yoga Ramalingam.
+       * python: The "interval" member was fixed to export seconds as a
+         double. Thanks to Justin Burnham.
+       * replace and set targets: Fix error message. Thanks to Marc Fournier.
+         #448
+       * rrdtool and rrdcached plugins: Honor the "DataDir" config option;
+         this fixes a regression. Thanks to Florian Forster. #380
+       * rrdtool and rrdcached plugins: A memory leak when creating RRD files
+         has been fixed. Thanks to Yves Mettier. #661
+       * snmp: Fix a memory leak. Thanks to Marc Fournier and Pierre-Yves
+         Ritschard. #610, #804
+       * swap: Fix behavior under OpenVZ by making "cached" optional. Thanks
+         to Florian Forster. #733
+       * threshold: Population of the "time" field in notifications has been
+         added. Thanks to Manuel Luis Sanmartín Rozada.
+       * libvirt: Only gather stats for running domains. Thanks to Ruben
+         Kerkhof.
+       * write_graphite: Escape characters not supported by Graphite. Thanks
+         to Pierre-Yves Ritschard and Marc Fournier.
+       * write_http: Make callback names context-dependent. Thanks to Marc
+         Fournier. #821
+       * write_riemann: Receive acknowledge message when using TCP. Thanks to
+         John-John Tedro.
+
+2013-07-13, Version 5.3.1
+       * Documentation: Various fixes.
+       * Configuration: Fix error handling: Errors in included files were
+         ignored, causing configuration mistakes to go unnoticed.
+       * dns plugin: Don't abort when PCAP returns an error.
+       * modbus plugin: The reconnection strategy was improved, fixing a
+         segfault in the libmodbud library. Thanks to Stefan Nickl and
+         Fabien Wernli for their patches.
+       * mysql plugin: The notification about a newly running MySQL slave
+         thread has been fixed. Thanks to Joaquín Cuenca Abela for the patch.
+       * snmp plugin: A build issue has been fixed (C99 mixed declaration).
+         The end-of-tree check has been improved by Pierre-Yves Ritschard.
+       * threshold plugin: Handling of the "Interesting" configuration option
+         has been fixed. Thanks to Björn for the patch.
+       * write_riemann plugin: A memory leak has been fixed. Thanks to Dave
+         Cottlehuber for reporting it.
+
+2013-04-09, Version 5.3.0
+       * collectd: The "Include" statements can now be limited to include
+         only matching files in a directory. Thanks to Sebastian Harl for his
+         patch.
+       * collectd: Dispatches / writes are now handled by a thread pool. This
+         improves reliability and throughput for instances configured to act
+         as a "server". Thanks to Sebastian Harl and Dan Fandrich for
+         reviewing this change and fixing bugs.
+       * aggregation plugin: Selection of value lists is now possible using
+         regular expressions. Parts of the identifier of the resulting metric
+         can now be set via the configuration file.
+       * apcups plugin: The "ReportSeconds" option has been implemented.
+       * curl* plugins: Support for POST requests and custom request headers
+         has been added. Thanks to Dan Fandrich for his patch.
+       * curl_xml plugin: Support for XML namespaces has been added. Thanks
+         to Dan Fandrich for his patch.
+       * dbi plugin: Support for numeric options has been added. The
+         "Host" option has been added. Thanks to Daniel Hilst for his patch.
+       * disk plugin: Support for systems with >256 has been fixed. Thanks to
+         Greg Mason for his patch.
+       * libvirt plugin: Support for memory allocation has been added. Thanks
+         to Johan Wirén for his patch.
+       * netapp plugin: Support for "SnapVault", "VFiler" and deduplication /
+         compression and quota metrics. Thanks to Sebastian Harl for his
+         patches and teamix GmbH for sponsoring this work.
+       * postgresql plugin: The reconnection logic has been improved. Thanks
+         to Sebastian Harl for his patches.
+       * rrdtool, rrdcached plugins: The "CreateFilesAsync" option has been
+         implemented. When enabled, new RRD files will be created
+         asynchronously, which improved throughput of "server" instances.
+         Many thanks to Yves Mettier for all his input and code.
+       * tail_csv plugin: This new plugins allows to read metrics from CSV
+         files, such as Snort's statistics file. Thanks to Kris Nielander for
+         his patch.
+       * write_mongodb plugin: Authentication options have been added.
+       * write_riemann plugin: This new plugin allows sending metrics to
+         Riemann, a stream processing and alerting tool. Big thanks to
+         Pierre-Yves Ritschard for his work.
+
+2013-04-08, Version 5.2.2
+       * Build system: A bad interaction between the Java detection code and
+         libltdl has been fixed. Thanks to Dave Cottlehuber for his patch.
+         Installation of the Perl bindings has been improved / fixed. Thanks
+         to Sebastian Harl for his patch.
+       * collectd: Fixed read callback scheduling at startup.
+       * apache, ascent, bind, curl, curl_json, curl_xml, nginx and
+         write_http plugins: Portability fixes, protection from infinite
+         redirect loops, improved error handling and incorrect dereferences
+         have been fixed. Most of these are related to the cURL library.
+         Thanks to Dan Fandrich for his patches.
+       * logfile plugin: Flush the output file handle. This works around
+         caching when logging to STDOUT and redirecting into a file. Thanks
+         to Nathan Huff for the patch.
+       * mysql plugin: Fix a memory leak in the error handling. Thanks to
+         Tomas Doran for his patch.
+       * netapp plugin: Fix the interval with which values are dispatched.
+       * network plugin: Build issues under FreeBSD and initialization have
+         been fixed. Thanks to Ed Schouten for his patch.
+       * nfs plugin: A compilation problem has been fixed.
+       * notify_email plugin: Add a character set to the mail header. Thanks
+         to Manuel Cissé for his patch.
+       * pf plugin: Build issues have been fixed.
+       * postgresql plugin: Build issues have been fixed.
+       * rrdcached plugin: Connect to the daemon from the read callback.
+       * snmp plugin: Matching of SNMP subtrees has been improved. Thanks to
+         "jkrabbe" for the patch.
+       * thermal plugin: The initialization of dispatched value lists has
+         been fixed. Thanks to Markus Knetschke for his patch.
+       * unixsock plugin: Parsing of options with an underscore, e.g.
+         "plugin_instance" has been fixed. Thanks to Tommie Gannert for his
+         patch.
+
+2013-01-27, Version 5.2.1
+       * Build system: "make distcheck" has been fixed. Build fixes Solaris
+         and systems without gcrypt. Thanks to Yves Mettier for his patches.
+       * collectd: The complaint mechanism was fixed. It reported messages
+         more frequently than intended.
+       * collectd-tg: A manual page has been added.
+       * dns plugin: Build issues on FreeBSD have been fixed. Thanks to
+         Ed Schouten for his patch.
+       * ethstat plugin: Fix the "Map" config option. An incorrectly used
+         character pointer may lead to a segmentation fault.
+       * network plugin: Build issues on FreeBSD have been fixed. Thanks to
+         Ed Schouten for his patch.
+       * postgresql plugin: A memory leak in the writing code has been fixed.
+         A use-after-free issue that happened when more than one database was
+         configured was fixed. Thanks to Sebastian Harl for fixing these
+         problems.
+       * redis plugin: A build failure has been fixed. Thanks to Pierre-Yves
+         Ritschard for his patch.
+       * varnish plugin: Fix a problem with instances without name.
+       * write_graphite plugin: A regression which rendered the
+         "SeparateInstances" and "AlwaysAppendDS" options unusable has been
+         fixed. A failed assertion when using types with many data sources
+         has been fixed. Improve reporting of connection errors to not spam
+         log files too much. Thanks to Pierre-Yves Ritschard for reporting
+         the logging problem.
+       * zfs_arc plugin: Fix the type used for mutex misses. Thanks to Yves
+         Mettier for reporting this bug.
+
+2012-11-17, Version 5.2.0
+       * collectd: The performance of the LISTVAL command has been improved.
+         Thanks to Yves Mettier for the patch.
+       * collectd: The possibility to configure the collection interval on a
+         per-plugin basis has been added. Huge thanks to Sebastian Harl for
+         his work.
+       * collectd-tg: This new binary allows to generate random but real
+         looking collectd network traffic. This can be used to load-test new
+         plugin, for example.
+       * libcollectdclient: Code for constructing and sending network packets
+         in the binary format has been added.
+       * aggregation plugin: This new plugin allows to aggregate multiple
+         value lists into one.
+       * amqp and write_http plugins: Meta data is now included in the JSON
+         output format. Thanks to Mark Wong for the patch.
+       * amqp plugin: Support for "Graphite" output has been added. Thanks to
+         Thomas Meson for the patch.
+       * contextswitch plugin: Support for AIX has been added. Thanks to
+         Manuel Rozada for his patch.
+       * disk plugin: The "UseBSDName" config option has been added to the
+         Mac OS X version.
+       * GenericJMX plugin: Automatically determine the host name if it isn't
+         configured.
+       * libvirt plugin: The "number" interface format has been added. Thanks
+         to "Davide Guerri" for the patch.
+       * memcached plugin: Support for multiple connections has been added.
+         Thanks to Nicolas Szalay for the patch.
+       * ntpd plugin: The "IncludeUnitID" config option has been added. The
+         behavior when a peer is unreachable has been improved. Thanks to
+         Johan Kiviniemi for the patches.
+       * oracle plugin: The "Host" config option has been added.
+       * pf plugin: This new plugin allows to collect statistics from BSD's
+         packet filter "pf". Thanks to Pierre-Yves Ritschard and Stefan Rinkes
+         for their work.
+       * postgresql plugin: The "Instance" config option has been added.
+         Support for writing values to a PostgreSQL database has been added.
+         Thanks to Sebastian Harl for the patches.
+       * processes plugin: Support for Solaris has been added. Thanks to
+         Cosmin Ioiart for the patch.
+       * redis plugin: Support for authenticating via password has been added.
+         Thanks to biancalana for the patch.
+       * rrdcached plugin: The "HeartBeat", "RRARows", "RRATimespan",
+         "StepSize" and "XFF" config options have been added.
+       * swap plugin: The "ReportBytes" config option has been added. The AIX
+         version now also exports "reserved" pages and swap-in / swap-out
+         "traffic". Thanks to Manuel Rozada for the patch.
+       * tcpconns plugin: Use a netlink socket rather than reading from /proc
+         for improved performance. Thanks to Michael Stapelberg for the patch.
+
+2013-04-08, Version 5.1.3
+       * Build system: A bad interaction between the Java detection code and
+         libltdl has been fixed. Thanks to Dave Cottlehuber for his patch.
+       * collectd: Fixed read callback scheduling at startup.
+       * apache, ascent, bind, curl, curl_json, curl_xml, nginx and
+         write_http plugins: Portability fixes, protection from infinite
+         redirect loops, improved error handling and incorrect dereferences
+         have been fixed. Most of these are related to the cURL library.
+         Thanks to Dan Fandrich for his patches.
+       * logfile plugin: Flush the output file handle. This works around
+         caching when logging to STDOUT and redirecting into a file. Thanks
+         to Nathan Huff for the patch.
+       * mysql plugin: Fix a memory leak in the error handling. Thanks to
+         Tomas Doran for his patch.
+       * netapp plugin: Fix the interval with which values are dispatched.
+       * network plugin: Build issues under FreeBSD and initialization have
+         been fixed. Thanks to Ed Schouten for his patch.
+       * nfs plugin: A compilation problem has been fixed.
+       * notify_email plugin: Add a character set to the mail header. Thanks
+         to Manuel Cissé for his patch.
+       * rrdcached plugin: Connect to the daemon from the read callback.
+       * snmp plugin: Matching of SNMP subtrees has been improved. Thanks to
+         "jkrabbe" for the patch.
+       * thermal plugin: The initialization of dispatched value lists has
+         been fixed. Thanks to Markus Knetschke for his patch.
+       * unixsock plugin: Parsing of options with an underscore, e.g.
+         "plugin_instance" has been fixed. Thanks to Tommie Gannert for his
+         patch.
+
+2013-01-25, Version 5.1.2
+       * Build system: "make distcheck" has been fixed. Thanks to Yves
+         Mettier for his patches.
+       * collectd: The complaint mechanism was fixed. It reported messages
+         more frequently than intended.
+       * dns plugin: Build issues on FreeBSD have been fixed. Thanks to
+         Ed Schouten for his patch.
+       * ethstat plugin: Fix the "Map" config option. An incorrectly used
+         character pointer may lead to a segmentation fault.
+       * network plugin: Build issues on FreeBSD have been fixed. Thanks to
+         Ed Schouten for his patch.
+       * varnish plugin: Fix a problem with instances without name.
+       * write_graphite: Improve reporting of connection errors to not spam
+         log files too much. Thanks to Pierre-Yves Ritschard for reporting
+         this problem.
+       * zfs_arc plugin: Fix the type used for mutex misses. Thanks to Yves
+         Mettier for reporting this bug.
+
+2012-11-11, Version 5.1.1
+       * collectd: Create new directories with mode 0777 and let umask remove
+         unwanted permission bits.
+       * collectd: Build issues have been fixed.
+       * collectd: An incorrect assertion has been fixed in some common code
+         for Solaris. This should resolve pseudo-random assertion failures
+         under Solaris. Thanks to Jeff Blane for his help debugging this.
+       * collectd: A couple of memory leaks through PThread thread attributes
+         have been fixed. Thanks to Gerrie Roos for fixing these.
+       * collectdctl: Fix PUTVAL for data sets with multiple data sources.
+         Thanks to Cyril Feraudet for reporting this problem.
+       * contrib/migrate-4-5.px: Handle to "df" to "df_complex" conversion
+         correctly.
+       * apcups plugin: Improve the reconnect behavior.
+       * curl_xml plugin: The "Host" setting was silently ignored. Thanks to
+         Fabien Wernli for fixing this.
+       * df plugin: Ignore "rootfs" devices under Linux to avoid having them
+         reported twice. Thanks to Brune Prémont for fixing this.
+       * disk plugin: Fix incorrect computation of read and write latency (the
+         "disk_time" type). Previously, the numbers reported where too small
+         by a factor of "interval", e.g. when the interval is set to 10
+         seconds, the values were too low by a factor of 10. Thanks to Manuel
+         Sanmartin for reporting this problem.
+       * dns plugin: A build issue under Solaris has been fixed. A erroneous
+         define that could lead to the reporting of bad data has been fixed by
+         Daniel Sutto.
+       * ethstat plugin: An off-by-one error and potential use of
+         uninitialized memory has been fixed. Thanks to Mark Voelker for
+         reporting these problems.
+       * memcachec plugin: A bug in the configuration handling has been fixed.
+         Thanks to Pascal Hofmann for fixing this issue.
+       * mysql plugin: Fix a bug when registering multiple databases. Thanks
+         to Sebastian Harl for fixing this.
+       * netapp plugin: Correctly close the connection on communication
+         errors.
+       * netlink plugin: The function used to query statistics has been
+         changed to be more in line with iproute2's behavior. Thanks to
+         "KIvosak" for the patch.
+       * network plugin: Initialization of libgcrypt has been fixed. Thanks to
+         Chris Lundquist for his patch.
+       * oracle plugin: Error messages have been improved.
+       * ping plugin: Don't enter the exponential back-off mode when
+         ping_send() fails. This should make recovery after a network failure
+         much faster.
+       * python plugin: Memory leaks have been fixed. Thanks to Tommie Gannert
+         and Sven Trenkel for fixing this.
+       * redis plugin: Fix a compilation problem on FreeBSD. Thanks to
+         "biancalana" for the fix.
+       * rrdtool plugin: Fix an out-of-bounds array access when printing a
+         warning message. Thanks to Will Hawkins for fixing this bug.
+       * snmp plugin: Support for the SNMP_ENDOFMIBVIEW return value has been
+         added. Support for more complex / unusual MIBs / subtrees has been
+         added. Thanks to Mark Juric to test the changes and point out these
+         problems.
+       * varnish plugin: Support for multiple instances of Varnish 3 has been
+         fixed. Thanks to Jonathan Huot for the patch.
+       * write_mongodb plugin: Add compatibility with libmongo 0.6.0 and
+         later. Thanks to Chris Lundquist for this patch.
+
+2012-04-01, Version 5.1.0
+       * Build system, iptables plugin: The shipped version of libiptc has
+         been removed.
+       * collectd-nagios: A list of value lists can now be queried using
+         "-n LIST". Thanks to Sebastian Harl for his patches.
+       * bind plugin: The "ParseTime" option has been added. It allows to use
+         the system time rather than the time reported by BIND.
+       * curl, memcachec, tail plugins: The "ExcludeRegexp" option has been
+         added. Thanks to Peter Warasin for his initial patch.
+       * ethstat plugin: The new "ethstat" plugin reads performance statistics
+         directly from ethernet cards. Thanks to Cyril Feraudet for his patch.
+       * GenericJMX plugin: Support for querying MBean "Operations" (in
+         addition to "Attributes") has been added. Thanks to Pierre-Yves
+         Ritschard for his patch.
+       * irq plugin: The selection / ignore code now uses the default
+         ignorelist infrastructure, providing the standard feature set, e.g.
+         regex matching.
+       * md plugin: The new "md" plugin reports the number of disks in various
+         states in Linux software RAID devices. Thanks to Michael Hanselmann
+         for his patch.
+       * modbus plugin: Support for signed integer register types has been
+         added.
+       * nfs plugin: Support for Solaris has been added. Thanks to Cosmin
+         Ioiart for his patch.
+       * numa plugin: The new "numa" plugin reports statistics of the
+         Non-Uniform Memory Access (NUMA) subsystem of Linux.
+       * processes plugin: Various fixes for the FreeBSD implementation.
+         Thanks to Phil Kulin for his patch.
+       * rrdcached plugin: Passing flushes to the caching daemon has been
+         added.
+       * sensors plugin: The initialization code has been improved. Thanks to
+         Henrique de Moraes Holschuh for his patch.
+       * swap plugin: The "ReportByDevice" option has been added.
+       * syslog plugin: Support for writing notifications has been added.
+         Thanks to Fabien Wernli for his patch.
+       * tcpconns plugin: Support for AIX has been added. Thanks to Manuel
+         Luis Sanmartín Rozada for his patch.
+       * threshold plugin: The "PersistOK" option has been added. Thanks to
+         Aaron Brady for his patch.
+       * varnish plugin: Support for Varnish 3.0 has been added. Thanks to
+         Jérôme Renard for his patches.
+       * write_mongodb plugin: The new "write_mongodb" plugin writes value
+         lists to MongoDB, a shema-less database. Thanks to Akkarit Sangpetch
+         and Chris Lundquist for their work.
+       * write_graphite plugin: The new "write_graphite" plugin writes value
+         lists to Carbon, the storage layer of the Graphite time-series
+         database. Thanks to Scott Sanders and Pierre-Yves Ritschard for their
+         work.
+       * zfs_arc plugin: Several new statistics have been added. Thanks to
+         Aurelien Rougemont for his patches.
+       * scale target: Support for scaling specific data sources only has been
+         added. Thanks to Gerrie Roos for his patch.
+
+2012-11-11, Version 5.0.5
+       * collectd: Create new directories with mode 0777 and let umask remove
+         unwanted permission bits.
+       * collectd: Build issues have been fixed.
+       * collectd: An incorrect assertion has been fixed in some common code
+         for Solaris. This should resolve pseudo-random assertion failures
+         under Solaris. Thanks to Jeff Blane for his help debugging this.
+       * collectd: A couple of memory leaks through PThread thread attributes
+         have been fixed. Thanks to Gerrie Roos for fixing these.
+       * collectdctl: Fix PUTVAL for data sets with multiple data sources.
+         Thanks to Cyril Feraudet for reporting this problem.
+       * contrib/migrate-4-5.px: Handle to "df" to "df_complex" conversion
+         correctly.
+       * apcups plugin: Improve the reconnect behavior.
+       * curl_xml plugin: The "Host" setting was silently ignored. Thanks to
+         Fabien Wernli for fixing this.
+       * df plugin: Ignore "rootfs" devices under Linux to avoid having them
+         reported twice. Thanks to Brune Prémont for fixing this.
+       * disk plugin: Fix incorrect computation of read and write latency (the
+         "disk_time" type). Previously, the numbers reported where too small
+         by a factor of "interval", e.g. when the interval is set to 10
+         seconds, the values were too low by a factor of 10. Thanks to Manuel
+         Sanmartin for reporting this problem.
+       * dns plugin: A build issue under Solaris has been fixed. A erroneous
+         define that could lead to the reporting of bad data has been fixed by
+         Daniel Sutto.
+       * memcachec plugin: A bug in the configuration handling has been fixed.
+         Thanks to Pascal Hofmann for fixing this issue.
+       * mysql plugin: Fix a bug when registering multiple databases. Thanks
+         to Sebastian Harl for fixing this.
+       * netapp plugin: Correctly close the connection on communication
+         errors.
+       * netlink plugin: The function used to query statistics has been
+         changed to be more in line with iproute2's behavior. Thanks to
+         "KIvosak" for the patch.
+       * network plugin: Initialization of libgcrypt has been fixed. Thanks to
+         Chris Lundquist for his patch.
+       * oracle plugin: Error messages have been improved.
+       * ping plugin: Don't enter the exponential back-off mode when
+         ping_send() fails. This should make recovery after a network failure
+         much faster.
+       * python plugin: Memory leaks have been fixed. Thanks to Tommie Gannert
+         and Sven Trenkel for fixing this.
+       * redis plugin: Fix a compilation problem on FreeBSD. Thanks to
+         "biancalana" for the fix.
+       * rrdtool plugin: Fix an out-of-bounds array access when printing a
+         warning message. Thanks to Will Hawkins for fixing this bug.
+       * snmp plugin: Support for the SNMP_ENDOFMIBVIEW return value has been
+         added. Support for more complex / unusual MIBs / subtrees has been
+         added. Thanks to Mark Juric to test the changes and point out these
+         problems.
+
+2012-04-01, Version 5.0.4
+       * Build system: Fix the use of a libltdl macro. Thanks to Clemens Lang
+         for fixing this. Adresses some issues with building the iptables
+         plugin under Gentoo.
+       * libcollectdclient: A memory leak in the lcc_getval() function has
+         been fixed. Thanks to Jason Schmidlapp for finding and fixing this
+         issue.
+       * bind plugin: The use of 'QType" types has been fixed.
+       * df plugin: Fixed compiler issue under Mac OS X 10.7.
+       * conntrack plugin: Support zero as legitimate value. Thanks to Louis
+         Opter for his patch.
+       * memcached plugin: Increased the size of a static buffer, which was
+         truncating status messages form memcached. Thanks to Timon for the
+         patch.
+       * network plugin: Forwarding of notifications has been disabled. This
+         was a contition not checked for before, which may retult in an
+         endless loop.
+       * processes plugin: Support for process names with spaces has been
+         added to the Linux implementation. Thanks to Darrell Bishop for his
+         patch.
+       * perl plugin: A race condition in several callbacks, including log and
+         write callbacks, has been fixed. Thanks to "Rrpv" for reporting this
+         bug.
+       * snmp plugin: A bug when casting unsigned integers to gauge values has
+         been fixed: Unsigned integers would be cast to a signed integer and
+         then to a gauge, possibly resulting in a negative value.
+       * tcpconns plugin: Compilation with newer versions of the FreeBSD
+         runtime has been fixed.
+
+2012-02-19, Version 5.0.3
+       * Build system: Fix problems when building the ipvs and iptables
+         plugins. Thanks to Sebastian Harl for his patch. A bashism in the
+         version-gen.sh script has been fixed. Thanks to Jo-Philipp Wich for
+         his patch.
+       * csv and rrdtool plugins: Print a more helpful error message when the
+         DataDir is a symlink pointing to a non-existing location. Thanks to
+         Jonathan Nieder for his patch.
+       * exec plugin: Fix a problem when using select(2) to read from file
+         handles. Thanks to Gerrie Roos for his patch.
+       * network plugin: An incorrect error message in the handling of the
+         "Interface" configuration option has been fixed. Thanks to Gerrie
+         Roos for his patch.
+       * oracle plugin: A potential endless loop in the error handling has
+         been fixed.
+       * python plugin: A crash bug in the configuration handling has been
+         fixed. Thanks to Sven Trenkel for his patch.
+       * interfaces plugin: The change which was supposed to ignore "bogus"
+         interfaces has been reverted, since it ignored legit interfaces, such
+         as bonding pseudo-devices as well.
+
+2012-01-21, Version 5.0.2
+       * curl_xml plugin: Fix handling of file:// and other URLs (which don't
+         follow HTTP status codes). Thanks to Fabien Wernli for his patch!
+       * df plugin: Fix handling of negative "available" counts. This can
+         occur with some file systems, for example UFS. Thanks to Toni Ylenius
+         for his patch.
+       * interface plugin: "mac" interfaces are now ignored on Solaris. These
+         pseudo-interfaces occur multiple times, causing warnings. Also switch
+         to 64-bit counters on Solaris, improving overflow behavior for
+         high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for
+         their patches.
+       * memory plugin: Account kernel and unused memory under Solaris. Thanks
+         to Fabien Wernli for his patch.
+       * network plugin: A bug in the interaction between the Network plugin
+         and filter chains has been fixed: When a filter modified a field such
+         as the hostname, subsequent values in the same network packets could
+         have ended up using the modified name rather than the original name.
+         Thanks to Sebastian Harl for identifying the problem.
+       * oracle plugin: A memory leak has been fixed in the parameter handling.
+       * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel
+         for fixing this bug!
+
+2011-10-07, Version 5.0.1
+       * collectd: A mutex leak has been fixed in the meta data code. Thanks
+         to Rafal Lesniak for his patch.
+       * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks
+         to Peter Green for his patch.
+       * csv plugin: The line buffer size has been increased. Thanks to Colin
+         McCabe for the patch.
+       * curl_json plugin: Don't use the "parent" node to build the type
+         instance, if it is empty. Compatibility with libyajl 2 has been
+         added. Thanks to "spupykin" of the Arch Linux project for the initial
+         code. Formatting of time has been fixed in the JSON module.
+       * exec plugin: Fix the timestamp value passed to notification scripts.
+         Thanks to Alexander Kovalenko for fixing this.
+       * iptables plugin: Fix linking with some versions of libiptc.
+       * irq plugin: Fix support for interrupts under Linux. The old code
+         assumed that interrupts have a numeric value -- this is no longer
+         true for Linux. Thanks to Bostjan Skufca for implementing this.
+       * notify_desktop plugin: Compatibility with libnotify 0.7 has been
+         added. Thanks to Samuli Suominen for his patch.
+       * processes plugin: Fix handling of regular expressions containing
+         spaces. Thanks for Sebastian Harl for fixing this.
+       * rrdtool, rrdcached plugins: Improve precision of the XFF parameter.
+         Previously, values like 0.999 would have been rounded to 1.0. Thanks
+         to Francois-Xavier Bourlet for fixing this.
+       * varnish plugin: Fix data type handling of some metrics. Some values
+         were submitted as gauge even though they were derives.
+       * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike
+         Flisher for the fix.
+
+2011-03-28, Version 5.0.0
+       * collectd: The "FQDNLookup" option is now enabled by default.
+       * collectd: The internal representation of time has been changed to
+         allow a higher accuracy than one second.
+       * collectdcmd: This new command line utility can send various commands
+         to collectd using the UnixSock plugin. Thanks to Håkon Dugstad
+         Johnsen and Sebastian Harl for their code.
+       * collectd-nagios: The "-m" option has been implemented (treat NaNs as
+         critical).
+       * collectd-tg: Traffic generator creating bogus network traffic
+         compatible to the Network plugin. This utility can be used to
+         stress-test new write plugins and collectd in general.
+       * libcollectdclient: Creating and sending network packets has been
+         added to the collectd client library.
+       * All data sets: The data source name of all data sets with exactly
+         one data source has been changed to "value".
+       * All plugins: All "counter" data sources have been converted to
+         "derive" data sources. All plugins now use "derive" by default, but
+         plugins such as the network plugin can still handle "counter", of
+         course. The minimum value of all derive data sources is zero, the
+         maximum value is unspecified.
+       * amqp plugin: The new AMQP plugin can send data to and receive data
+         from an AMQP broker. Thanks to Sebastien Pahl for his code.
+       * apache plugin: Backwards compatibility code has been removed.
+         Support for the IBM HTTP Server has been added. Thanks to Manuel
+         Luis Sanmartín Rozada for his patch.
+       * contextswitch plugin: Support for sysctlbyname(3) has been added.
+         Thanks to Kimo Rosenbaum for his patch.
+       * df plugin: The default behavior has been changed to be equivalent to
+         the "ReportReserved" behavior of v4.
+       * dns plugin: Improved RFC 1035 name parsing has been imported from
+         "dnstop".
+       * exec plugin: Backwards compatibility code has been removed.
+       * GenericJMX plugin: The "InstancePrefix" option has been added to
+         "Connection" blocks.
+       * hddtemp plugin: The "TranslateDevicename" config option has been
+         removed.
+       * interface plugin: Use the "plugin instance" to store the interface
+         value.
+       * libvirt plugin: The "InterfaceFormat" option has been added. Thanks
+         to Ruben Kerkhof for his patch.
+       * lpar plugin: New plugins for "logical partitions", a virtualization
+         technique of POWER CPUs. Thanks to Aurélien Reynaud for his code and
+         patience.
+       * modbus plugin: Support for libmodbus 2.9.2 has been added and the
+         license has been changed to LGPLv2.1.
+       * mysql plugin: Backwards compatibility code has been removed. The
+         data sets used have been improved.
+       * network plugin: The default buffer size has been increased to
+         1452 bytes.
+       * perl plugin: Backwards compatibility code has been removed.
+       * postgresql plugin: Backwards compatibility code has been removed.
+       * redis plugin: Plugin for collecting statistics from Redis, a key-
+         value store, has been added. Thanks to Andres J. Diaz for his code.
+       * swap plugin: Implement collection of physical and virtual memory
+         statistics under Solaris. The new default is collecting physical
+         memory. Thanks to Aurélien Reynaud for his patches.
+       * threshold plugin: The threshold configuration has been moved into
+         this separate plugin.
+       * unixsock plugin: The "DeleteSocket" option has been added.
+       * varnish plugin: The new Varnish plugin reads statistics from
+         Varnish, a web accelerator. Thanks to Jérôme Renard and Marc
+         Fournier for their contributions.
+       * write_redis: New plugin for writing data to Redis, a key-value
+         store.
+       * zfs_arc plugin: The data sets have been replaced by more elegant
+         alternatives.
+       * v5upgrade target: Target for converting v4 data sets to the v5
+         schema.
+
+2013-04-07, Version 4.10.9
+       * Build system: A bad interaction between the Java detection code and
+         libltdl has been fixed. Thanks to Dave Cottlehuber for his patch.
+       * apache, ascent, bind, curl, curl_json, curl_xml, nginx and
+         write_http plugins: Portability fixes, protection from infinite
+         redirect loops, improved error handling and incorrect dereferences
+         have been fixed. Most of these are related to the cURL library.
+         Thanks to Dan Fandrich for his patches.
+       * logfile plugin: Flush the output file handle. This works around
+         caching when logging to STDOUT and redirecting into a file. Thanks
+         to Nathan Huff for the patch.
+       * network plugin: Build issues under FreeBSD and initialization have
+         been fixed. Thanks to Ed Schouten for his patch.
+       * mysql plugin: Fix a memory leak in the error handling. Thanks to
+         Tomas Doran for his patch.
+       * thermal plugin: The initialization of dispatched value lists has
+         been fixed. Thanks to Markus Knetschke for his patch.
+       * unixsock plugin: Parsing of options with an underscore, e.g.
+         "plugin_instance" has been fixed. Thanks to Tommie Gannert for his
+         patch.
+
+2012-11-11, Version 4.10.8
+       * collectd: Create new directories with mode 0777 and let umask remove
+         unwanted permission bits.
+       * collectd: Build issues have been fixed.
+       * collectd: An incorrect assertion has been fixed in some common code
+         for Solaris. This should resolve pseudo-random assertion failures
+         under Solaris. Thanks to Jeff Blane for his help debugging this.
+       * collectd: A couple of memory leaks through PThread thread attributes
+         have been fixed. Thanks to Gerrie Roos for fixing these.
+       * apcups plugin: Improve the reconnect behavior.
+       * df plugin: Ignore "rootfs" devices under Linux to avoid having them
+         reported twice. Thanks to Brune Prémont for fixing this.
+       * disk plugin: Fix incorrect computation of read and write latency (the
+         "disk_time" type). Previously, the numbers reported where too small
+         by a factor of "interval", e.g. when the interval is set to 10
+         seconds, the values were too low by a factor of 10. Thanks to Manuel
+         Sanmartin for reporting this problem.
+       * dns plugin: A build issue under Solaris has been fixed. A erroneous
+         define that could lead to the reporting of bad data has been fixed by
+         Daniel Sutto.
+       * memcachec plugin: A bug in the configuration handling has been fixed.
+         Thanks to Pascal Hofmann for fixing this issue.
+       * netapp plugin: Correctly close the connection on communication
+         errors.
+       * netlink plugin: The function used to query statistics has been
+         changed to be more in line with iproute2's behavior. Thanks to
+         "KIvosak" for the patch.
+       * network plugin: Initialization of libgcrypt has been fixed. Thanks to
+         Chris Lundquist for his patch.
+       * oracle plugin: Error messages have been improved.
+       * ping plugin: Don't enter the exponential back-off mode when
+         ping_send() fails. This should make recovery after a network failure
+         much faster.
+       * python plugin: Memory leaks have been fixed. Thanks to Tommie Gannert
+         and Sven Trenkel for fixing this.
+       * rrdtool plugin: Fix an out-of-bounds array access when printing a
+         warning message. Thanks to Will Hawkins for fixing this bug.
+       * snmp plugin: Support for the SNMP_ENDOFMIBVIEW return value has been
+         added. Support for more complex / unusual MIBs / subtrees has been
+         added. Thanks to Mark Juric to test the changes and point out these
+         problems.
+
+2012-04-01, Version 4.10.7
+       * Build system: Fix the use of a libltdl macro. Thanks to Clemens Lang
+         for fixing this. Adresses some issues with building the iptables
+         plugin under Gentoo.
+       * libcollectdclient: A memory leak in the lcc_getval() function has
+         been fixed. Thanks to Jason Schmidlapp for finding and fixing this
+         issue.
+       * bind plugin: The use of 'QType" types has been fixed.
+       * df plugin: Fixed compiler issue under Mac OS X 10.7.
+       * conntrack plugin: Support zero as legitimate value. Thanks to Louis
+         Opter for his patch.
+       * memcached plugin: Increased the size of a static buffer, which was
+         truncating status messages form memcached. Thanks to Timon for the
+         patch.
+       * network plugin: Forwarding of notifications has been disabled. This
+         was a contition not checked for before, which may retult in an
+         endless loop.
+       * processes plugin: Support for process names with spaces has been
+         added to the Linux implementation. Thanks to Darrell Bishop for his
+         patch.
+       * perl plugin: A race condition in several callbacks, including log and
+         write callbacks, has been fixed. Thanks to "Rrpv" for reporting this
+         bug.
+       * snmp plugin: A bug when casting unsigned integers to gauge values has
+         been fixed: Unsigned integers would be cast to a signed integer and
+         then to a gauge, possibly resulting in a negative value.
+       * tcpconns plugin: Compilation with newer versions of the FreeBSD
+         runtime has been fixed.
+
+2012-02-19, Version 4.10.6
+       * Build system: Fix problems when building the ipvs and iptables
+         plugins. Thanks to Sebastian Harl for his patch. A bashism in the
+         version-gen.sh script has been fixed. Thanks to Jo-Philipp Wich for
+         his patch.
+       * csv and rrdtool plugins: Print a more helpful error message when the
+         DataDir is a symlink pointing to a non-existing location. Thanks to
+         Jonathan Nieder for his patch.
+       * exec plugin: Fix a problem when using select(2) to read from file
+         handles. Thanks to Gerrie Roos for his patch.
+       * network plugin: An incorrect error message in the handling of the
+         "Interface" configuration option has been fixed. Thanks to Gerrie
+         Roos for his patch.
+       * oracle plugin: A potential endless loop in the error handling has
+         been fixed.
+       * python plugin: A crash bug in the configuration handling has been
+         fixed. Thanks to Sven Trenkel for his patch.
+       * interfaces plugin: The change which was supposed to ignore "bogus"
+         interfaces has been reverted, since it ignored legit interfaces, such
+         as bonding pseudo-devices as well.
+
+2012-01-21, Version 4.10.5
+       * curl_xml plugin: Fix handling of file:// and other URLs (which don't
+         follow HTTP status codes). Thanks to Fabien Wernli for his patch!
+       * df plugin: Fix handling of negative "available" counts. This can
+         occur with some file systems, for example UFS. Thanks to Toni Ylenius
+         for his patch.
+       * interface plugin: "mac" interfaces are now ignored on Solaris. These
+         pseudo-interfaces occur multiple times, causing warnings. Also switch
+         to 64-bit counters on Solaris, improving overflow behavior for
+         high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for
+         their patches.
+       * memory plugin: Account kernel and unused memory under Solaris. Thanks
+         to Fabien Wernli for his patch.
+       * network plugin: A bug in the interaction between the Network plugin
+         and filter chains has been fixed: When a filter modified a field such
+         as the hostname, subsequent values in the same network packets could
+         have ended up using the modified name rather than the original name.
+         Thanks to Sebastian Harl for identifying the problem.
+       * oracle plugin: A memory leak has been fixed in the parameter handling.
+       * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel
+         for fixing this bug!
+
+2011-10-14, Version 4.10.4
+       * collectd: A mutex leak has been fixed in the meta data code. Thanks
+         to Rafal Lesniak for his patch.
+       * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks
+         to Peter Green for his patch.
+       * csv plugin: The line buffer size has been increased. Thanks to Colin
+         McCabe for the patch.
+       * curl_json plugin: Don't use the "parent" node to build the type
+         instance, if it is empty. Compatibility with libyajl 2 has been
+         added. Thanks to "spupykin" of the Arch Linux project for the initial
+         code.
+       * iptables plugin: Fix linking with some versions of libiptc.
+       * irq plugin: Fix support for interrupts under Linux. The old code
+         assumed that interrupts have a numeric value -- this is no longer
+         true for Linux. Thanks to Bostjan Skufca for implementing this.
+       * notify_desktop plugin: Compatibility with libnotify 0.7 has been
+         added. Thanks to Samuli Suominen for his patch.
+       * processes plugin: Fix handling of regular expressions containing
+         spaces. Thanks for Sebastian Harl for fixing this.
+       * rrdtool, rrdcached plugins: Improve precision of the XFF parameter.
+         Previously, values like 0.999 would have been rounded to 1.0. Thanks
+         to Francois-Xavier Bourlet for fixing this.
+       * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike
+         Flisher for the fix.
+
+2011-03-26, Version 4.10.3
+       * Documentation: Several updates and additions. Thanks to Sebastian Harl.
+       * collectd: Build issues (compiler warnings) have been fixed. Thanks to
+         Bruno Prémont.
+       * collectd: Threshold subsection: Handling of NAN values in the
+         percentage calculation has been fixed.
+       * collectd, java plugin, ntpd plugin: Several diagnostic messages have
+         been improved.
+       * curl_json plugin: Handling of arrays has been fixed.
+       * libvirt plugin: A bug in reading the virtual CPU statistics has been
+         fixed. Thanks to “JLPC” for reporting this problem.
+       * modbus plugin: Compatibility with libmodbus 2.0.3 has been restored.
+       * processes plugin: Potentially erroneous behavior has been fixed in an
+         error handling case.
+       * python plugin: Fix dispatching of values from Python scripts to
+         collectd. Thanks to Gregory Szorc for finding and fixing this
+         problem.
+
+2010-11-27, Version 4.10.2
+       * Documentation: Various documentation fixes.
+       * collectd: If including one configuration file fails, continue with
+         the rest of the configuration if possible.
+       * collectd: Fix a bug in the read function scheduling. In rare cases
+         read functions may not have been called as often as requested.
+       * collectd: Concurrency issues with errno(3) under AIX have been
+         fixed: A thread-safe version of errno has to be requested under AIX.
+         Thanks to Aurélien Reynaud for his patch.
+       * collectd: A left-over hard-coded 2 has been replaced by the
+         configurable timeout value.
+       * curl, memcachec, tail plugins: Fix handling of "DERIVE" data
+         sources. Matching the end of a string has been improved; thanks to
+         Sebastian Harl for the patch.
+       * curl_json plugin: Fix a problem when parsing 64bit integers. Reading
+         JSON data from non-HTTP sources has been fixed.
+       * netapp plugin: Pass the interval setting to the dispatch function.
+         Restore compatibility to NetApp Release 7.3. Thanks to Sven Trenkel
+         for the patch.
+       * network plugin: Be less verbose about unchecked signatures, in order
+         to prevent spamming the logs.
+       * notify_email plugin: Concurrency problems have been fixed.
+       * python plugin: Set "sys.argv", since many scripts don't expect that
+         it may not be set. Thanks to Sven Trenkel for the patch.
+       * rrdtool, rrdcached plugin: Fix a too strict assertion when creating
+         RRD files.
+       * swap plugin: A bug which lead to incorrect I/O values has been
+         fixed.
+       * value match: A minor memory leak has been fixed. Thanks to Sven
+         Trenkel for the patch.
+
+2010-07-09, Version 4.10.1
+       * Build system: Checking for "strtok_r" under Solaris has been fixed.
+       * Portability: Fixes for Solaris 8 have been applied. Thanks to
+         Alexander Wuerstlein for his patch.
+       * collectd: The shutdown speed when terminating the read threads has
+         been improved.
+       * libcollectdclient: A format error in the PUTVAL command has been
+         removed. Thanks to Johan Van den Brande for fixing this.
+       * df plugin: An error message shown when "cu_mount_getlist" fails has
+         been added.
+       * processes plugin: Missing initialization code for IO members of a
+         struct has been added. Thanks to Aurélien Reynaud for fixing this.
+       * python plugin: Memory leaks in the write and notification callbacks
+         have been fixed. A possible crash when the plugin was loaded but not
+         configured has been fixed. Thanks to Sven Trenkel for his patches.
+       * snmp plugin: Verbosity with regard to unknown ASN types has been
+         increased. A build problem on PowerPC and ARM processors has been
+         fixed by Aurélien Reynaud; thanks!
+       * powerdns plugin: Compatibility changes for PowerDNS 2.9.22 and above
+         have been applied. Thanks to Luke Heberling for his changes.
+
+2010-05-01, Version 4.10.0
+       * collectd: JSON output now includes the "dstypes" and "dsnames"
+         fields. This makes it easier for external applications to interpret
+         the data. Thanks to Chris Buben for his work.
+       * collectd: The new "Timeout" option can be used to specify a
+         "timeout" for missing values. This is used in the threshold checking
+         code to detect missing values. Thanks to Andrés J. Díaz for the
+         patch.
+       * apache plugin: Support for "IdleWorkers" (Apache 1.*: "IdleServers")
+         has been added.
+       * curl plugin: The new "ExcludeRegex" allows to easily exclude certain
+         lines from the match.
+       * curl_xml plugin: This new plugin allows to read XML files using cURL
+         and extract metrics included in the files. Thanks to Amit Gupta for
+         his work.
+       * filecount plugin: The new "IncludeHidden" option allows to include
+         "hidden" files and directories in the statistics. Thanks to Vaclav
+         Malek for the patch.
+       * logfile plugin: The new "PrintSeverity" option allows to include the
+         severity of a message in the output. Thanks to Clément Stenac for
+         his patch.
+       * memcachec plugin: The new "ExcludeRegex" allows to easily exclude
+         certain lines from the match.
+       * modbus plugin: This new plugin allows to read registers from
+         Modbus-TCP enabled devices.
+       * network plugin: The new "Interface" option allows to set the
+         interface to be used for multicast and, if supported, unicast
+         traffic. Thanks to Max Henkel for his work.
+       * openvpn plugin: The "CollectUserCount" and "CollectIndividualUsers"
+         options allow more detailed control over how to report sessions of
+         multiple users. Thanks to Fabian Schuh for his work.
+       * pinba plugin: This new plugin receives timing information from the
+         Pinba PHP extension, which can be used for profiling PHP code and
+         webserver performance. Thanks to Phoenix Kayo for his work.
+       * ping plugin: The new "MaxMissed" allows to re-resolve a hosts
+         address when it doesn't reply to a number of ping requests. Thanks
+         to Stefan Völkel for the patch.
+       * postgresql plugin: The "Interval" config option has been added. The
+         plugin has been relicensed under the 2-clause BSD license. Thanks to
+         Sebastian Harl for his work.
+       * processes plugin: Support for "code" and "data" virtual memory sizes
+         has been added. Thanks to Clément Stenac for his patch.
+       * python plugin: Support for Python 3 has been implemented. Thanks to
+         Sven Trenkel for his work.
+       * routeros plugin: Support for collecting CPU load, memory usage, used
+         and free disk space, sectors written and number of bad blocks from
+         MikroTik devices has been added.
+       * swap plugin: Support for Linux < 2.6 has been added. Thanks to Lorin
+         Scraba for his patch.
+       * tail plugin: The new "ExcludeRegex" allows to easily exclude certain
+         lines from the match. Thanks to Peter Warasin for his patch.
+       * write_http plugin: The "StoreRates" option has been added. Thanks to
+         Paul Sadauskas for his patch.
+       * regex match: The "Invert" option has been added. Thanks to Julien
+         Ammous for his patch.
+
+2011-03-26, Version 4.9.5
+       * Documentation: Several updates and additions. Thanks to Sebastian Harl.
+       * collectd: Build issues (compiler warnings) have been fixed. Thanks to
+         Bruno Prémont.
+       * collectd: Threshold subsection: Handling of NAN values in the
+         percentage calculation has been fixed.
+       * collectd, java plugin, ntpd plugin: Several diagnostic messages have
+         been improved.
+       * libvirt plugin: A bug in reading the virtual CPU statistics has been
+         fixed. Thanks to “JLPC” for reporting this problem.
+       * processes plugin: Potentially erroneous behavior has been fixed in an
+         error handling case.
+       * python plugin: Fix dispatching of values from Python scripts to
+         collectd. Thanks to Gregory Szorc for finding and fixing this
+         problem.
+
+2010-11-27, Version 4.9.4
+       * Documentation: Various documentation fixes.
+       * collectd: If including one configuration file fails, continue with
+         the rest of the configuration if possible.
+       * collectd: Fix a bug in the read function scheduling. In rare cases
+         read functions may not have been called as often as requested.
+       * collectd: Concurrency issues with errno(3) under AIX have been
+         fixed: A thread-safe version of errno has to be requested under AIX.
+         Thanks to Aurélien Reynaud for his patch.
+       * curl, memcachec, tail plugins: Fix handling of "DERIVE" data
+         sources. Matching the end of a string has been improved; thanks to
+         Sebastian Harl for the patch.
+       * curl_json plugin: Fix a problem when parsing 64bit integers. Reading
+         JSON data from non-HTTP sources has been fixed.
+       * netapp plugin: Pass the interval setting to the dispatch function.
+         Restore compatibility to NetApp Release 7.3. Thanks to Sven Trenkel
+         for the patch.
+       * network plugin: Be less verbose about unchecked signatures, in order
+         to prevent spamming the logs.
+       * notify_email plugin: Concurrency problems have been fixed.
+       * python plugin: Set "sys.argv", since many scripts don't expect that
+         it may not be set. Thanks to Sven Trenkel for the patch.
+       * rrdtool, rrdcached plugin: Fix a too strict assertion when creating
+         RRD files.
+       * value match: A minor memory leak has been fixed. Thanks to Sven
+         Trenkel for the patch.
+
+2010-07-09, Version 4.9.3
+       * Build system: Checking for "strtok_r" under Solaris has been fixed.
+       * Portability: Fixes for Solaris 8 have been applied. Thanks to
+         Aurélien Reynaud and Alexander Wuerstlein for their patches.
+       * collectd: The shutdown speed when terminating the read threads has
+         been improved.
+       * collectd-nagios: The format of the performance data has been fixed.
+       * libcollectdclient: A format error in the PUTVAL command has been
+         removed. Thanks to Johan Van den Brande for fixing this.
+       * df plugin: An error message shown when "cu_mount_getlist" fails has
+         been added.
+       * processes plugin: Missing initialization code for IO members of a
+         struct has been added. Thanks to Aurélien Reynaud for fixing this.
+       * python plugin: Memory leaks in the write and notification callbacks
+         have been fixed. A possible crash when the plugin was loaded but not
+         configured has been fixed. Thanks to Sven Trenkel for his patches.
+       * rrdcached plugin: A build issue has been resolved. Thanks to
+         Thorsten von Eicken for the patch.
+       * snmp plugin: Verbosity with regard to unknown ASN types has been
+         increased. A build problem on PowerPC and ARM processors has been
+         fixed by Aurélien Reynaud; thanks!
+       * powerdns plugin: Compatibility changes for PowerDNS 2.9.22 and above
+         have been applied. Thanks to Luke Heberling for his changes.
+
+2010-04-22, Version 4.9.2
+       * Build system, various plugins: Fixes for AIX compatibility have been
+         added. Thanks to Manuel Sanmartin for his patches.
+       * Build system: Checking for "nanosleep" on old Solaris machines has
+         been fixed. Thanks to Vincent McIntyre and Sebastian Harl for
+         figuring out a way to make this work.
+       * collectd: Append a newline to messages written to STDERR.
+       * collectd: Serialization of NANs in JSON format has been fixed.
+         Thanks to Chris Buben for pointing out the resulting syntax error.
+       * collectd: Checks whether a "sleep" returned early have been added;
+         the cases are now handled correctly. Thanks to Michael Stapelberg
+         for the patch.
+       * collectd: Continue reading files in a directory when parsing one
+         file fails.
+       * apache plugin: Collection of the number of active connections has
+         been fixed for Apache 2.*.
+       * contextswitch plugin: Handle large counter/derive values correctly.
+         Thanks to Martin Merkel for reporting the bug.
+       * exec plugin: Error messages have been improved. The "running" flag
+         is now cleared correctly when forking a child fails.
+       * iptables plugin: Fix a violation of aliasing rules. This resolves a
+         warning / error with new GCC versions. Thanks to Jan Engelhardt for
+         the work-around.
+       * java plugin: The Java API files are now packaged into a .jar file.
+         Thanks to Amit Gupta for his patch.
+       * network plugin: Fix a segmentation fault when receiving packets with
+         an unknown data source type.
+       * network plugin: A memory leak when receiving encrypted network
+         packets has been fixed.
+       * openvpn plugin: Fix naming schema when reading "MULTI1" type status
+         files.
+       * oracle plugin: Fix checking for lost connections and reconnect in
+         this case. Thanks to Sven Trenkel for pointing out the problem.
+       * unixsock plugin: A memory leak in the "LISTVAL" command has been
+         fixed. Thanks to Peter Warasin for pointing it out.
+       * write_http plugin: Use the "any" authentication schema. This used to
+         be "digest". Thanks to Paul Sadauskas for the patch.
+
+2010-01-14, Version 4.9.1
+       * Documentation: Some manpage fixes.
+       * Default config: Added sample configuration for missing plugins.
+       * apache plugin: Fix a segmentation fault in the config handling of
+         VerifyPeer / VerifyHost. Thanks to "plazmus" for his or her patch.
+       * processes plugin: Fix handling of derive data sources.
+       * rrdtool plugin: Fix a bug with random write timeouts. Due to an
+         incorrect initialization some files may be suspended basically
+         indefinitely. After flushing the files they were written regularly
+         again.
+       * routeros plugin: Use the node name for the "host" field.
+       * Monitorus.pm: Put the plugin into the "Collectd::Plugins" namespace.
+       * Perl bindings: Fix a warning that was printed when building
+         debugging output.
+
+2009-12-21, Version 4.9.0
+       * contextswitch plugin: The new ContextSwitch plugin gathers the
+         number of context switches done by the CPU. Thanks to Patrik
+         Weiskircher for the patch.
+       * cpu plugin: Support for SMP (multiple processors) under FreeBSD has
+         been added. Thanks to Doug MacEachern for the patch.
+       * curl plugin: The “MeasureResponseTime” option has been added. Thanks
+         to Aman Gupta for the patch.
+       * df plugin: Collecting the inode count and reserved space has been
+         added. Thanks to Patrik Weiskircher for the patch.
+       * exec plugin: The environment variables “COLLECTD_INTERVAL” and
+         “COLLECTD_HOSTNAME” are now set before executing the application.
+       * Monitorus plugin: This Perl-based plugin to query statistics from
+         mon.itor.us has been added. Thanks to Jeff Green for the patch.
+       * netapp plugin: New plugin to collect statistics from NetApp filers.
+         Thanks to Sven Trenkel of the noris network AG for the patch.
+       * network plugin: Statistics collection about the plugin itself has
+         been implemented.
+       * openvpn plugin: Add support for more versions of the “status file”.
+         Thanks to Marco Chiappero for the patch.
+       * OpenVZ plugin: This Perl-based plugin to gather OpenVZ statistics
+         has been added. Thanks to Jonathan Kolb for the patch.
+       * ping plugin: The config options "SourceAddress" and "Device"
+         have been added. Thanks to Sebastian Harl for the patch.
+       * processes plugin: Collection of IO-metrics has been added. Thanks to
+         Andrés J. Díaz for the patch.
+       * python plugin: The new Python plugin integrates a Python interpreter
+         into collectd and allows to execute plugins written in the scripting
+         language. Thanks to Sven Trenkel for his work.
+       * routeros plugin: The new RouterOS plugin queries interface and
+         wireless registration statistics from RouterOS.
+       * Various plugins: AIX support has been added to the cpu, disk,
+         interface, load, memory, processes, and swap plugins. Thanks to
+         Manuel Sanmartin for his patches.
+       * hashed match: This match for simple load balancing and redundant
+         storage has been added.
+       * scale target: This target to scale (multiply) values by an arbitrary
+         value has been added.
+
+2010-04-22, Version 4.8.5
+       * collectd: Append a newline to messages written to STDERR.
+       * network plugin: Fix a segmentation fault when receiving packets with
+         an unknown data source type.
+
+2010-04-07, Version 4.8.4
+       * Build system, various plugins: Fixes for AIX compatibility have been
+         added. Thanks to Manuel Sanmartin for his patches.
+       * Build system: Checking for "nanosleep" on old Solaris machines has
+         been fixed. Thanks to Vincent McIntyre and Sebastian Harl for
+         figuring out a way to make this work.
+       * collectd: Serialization of NANs in JSON format has been fixed.
+         Thanks to Chris Buben for pointing out the resulting syntax error.
+       * collectd: Checks whether a "sleep" returned early have been added;
+         the cases are now handled correctly. Thanks to Michael Stapelberg
+         for the patch.
+       * collectd: Continue reading files in a directory when parsing one
+         file fails.
+       * apache plugin: Collection of the number of active connections has
+         been fixed for Apache 2.*.
+       * exec plugin: Error messages have been improved. The "running" flag
+         is now cleared correctly when forking a child fails.
+       * iptables plugin: Fix a violation of aliasing rules. This resolves a
+         warning / error with new GCC versions. Thanks to Jan Engelhardt for
+         the work-around.
+       * java plugin: The Java API files are now packaged into a .jar file.
+         Thanks to Amit Gupta for his patch.
+       * network plugin: A memory leak when receiving encrypted network
+         packets has been fixed.
+       * oracle plugin: Fix checking for lost connections and reconnect in
+         this case. Thanks to Sven Trenkel for pointing out the problem.
+       * unixsock plugin: A memory leak in the "LISTVAL" command has been
+         fixed. Thanks to Peter Warasin for pointing it out.
+       * write_http plugin: Use the "any" authentication schema. This used to
+         be "digest". Thanks to Paul Sadauskas for the patch.
+
+2010-01-14, Version 4.8.3
+       * Documentation: Some manpage fixes.
+       * rrdtool plugin: Fix a bug with random write timeouts. Due to an
+         incorrect initialization some files may be suspended basically
+         indefinitely. After flushing the files they were written regularly
+         again.
+
+2009-12-18, Version 4.8.2
+       * Build system, java plugin: Don't use “find -L” to search for Java
+         headers, because it's a GNU extension.
+       * Build system: Support for parallel builds has been improved. Thanks
+         Sebastian Harl and Stefan Völkel for looking into this.
+       * collectd: Print error messages to STDERR if no log plugin has been
+         loaded.
+       * genericjmx plugin: Close and re-open the connection upon I/O-errors.
+       * gmond plugin: Fix typos which caused syntax errors.
+       * memory plugin: Handling of >4 Gbyte of memory has been fixed.
+       * network plugin: The license has been changed to LGPL 2.1.
+       * oracle plugin: Reconnect to the database if the connection dies.
+       * rrdcached plugin: Work-around for a bug in RRDtool 1.4rc2 has been
+         added.
+       * snmp plugin: Handling of negative values has been fixed. Strings
+         containing control characters are now interpreted as hex-strings.
+       * unixsock plugin: A memory leak in the LISTVAL command has been
+         fixed. Thanks to Ben Knight for his patch.
+
+2009-10-04, Version 4.8.1
+       * Build system: Issues when building the iptables plugin have been
+         fixed.
+       * exec plugin: Clear the signal block mask before calling exec(2).
+       * perl plugin: Declare the “environ” variable. This solves build
+         issues on some platforms.
+       * processes plugin: Remove unnecessary call of realloc(3). Thanks to
+         Andrés J. Díaz for the patch.
+       * unixsock plugin: Fix a (well hidden) race condition related to file
+         descriptor handling.
+
+2009-09-13, Version 4.8.0
+       * collectd: Two new data source types, “DERIVE” and “ABSOLUTE”, have
+         been added. “DERIVE” can be used for counters that are reset
+         occasionally. Thanks to Mariusz Gronczewski for implementing this.
+       * thresholds: The advanced threshold options “Percentage”, “Hits”, and
+         “Hysteresis” have been added. Thanks to Andrés J. Díaz for his
+         patches.
+       * curl_json plugin: The new cURL-JSON plugin reads JSON files using
+         the cURL library and parses the contents according to user
+         specification. Among other things, this allows to read statistics
+         from a CouchDB instance. Thanks to Doug MacEachern for the patch.
+       * df plugin: Using the new “ReportByDevice” option the device rather
+         than the mount point can be used to identify partitions. Thanks to
+         Paul Sadauskas for the patch.
+       * dns plugin: The possibility to ignore numeric QTypes has been added.
+         Thanks to Mirko Buffoni for the patch.
+       * GenericJMX plugin: The new, Java-based GenericJMX plugin allows to
+         query arbitrary data from a Java process using the “Java Management
+         Extensions” (JMX).
+       * madwifi plugin: The new MadWifi plugin collects information about
+         Atheros wireless LAN chipsets from the MadWifi driver. Thanks to
+         Ondrej Zajicek for his patches.
+       * network plugin: The receive- and send-buffer-sizes have been made
+         configurable, allowing for bigger and smaller packets. Thanks to
+         Aman Gupta for the patch.
+       * olsrd plugin: The new OLSRd plugin queries routing information from
+         the “Optimized Link State Routing” daemon.
+       * rrdtool plugin: A new configuration option allows to define a random
+         write delay when writing RRD files. This spreads the load created by
+         writing RRD files more evenly. Thanks to Mariusz Gronczewski for the
+         patch.
+       * swap plugin: The possibility to collect swapped in/out pages has
+         been added to the Swap plugin. Thanks to Stefan Völkel for the
+         patch.
+       * tokyotyrant plugin: The new TokyoTyrant plugin reads the number of
+         records and file size from a running Tokyo Tyrant server. Thanks to
+         Paul Sadauskas for the patch.
+       * unixsock plugin: Add the “GETTHRESHOLD” command. This command can be
+         used to query the thresholds configured for a particular identifier.
+       * write_http plugin: The new Write HTTP plugin sends the values
+         collected by collectd to a web-server using HTTP POST requests.
+         Thanks to Paul Sadauskas for the patch.
+       * zfs_arc plugin: The new ZFS ARC plugin collects information about
+         the “Adaptive Replacement Cache” (ARC) of the “Zeta File-System”
+         (ZFS). Thanks to Anthony Dewhurst for the patch.
+       * empty_counter match: The new Empty Counter match matches value
+         lists, where at least one data source is of type COUNTER and the
+         counter value of all counter data sources is zero.
+
+2009-12-18, Version 4.7.5
+       * Build system, java plugin: Don't use “find -L” to search for Java
+         headers, because it's a GNU extension.
+       * Build system: Support for parallel builds has been improved. Thanks
+         Sebastian Harl and Stefan Völkel for looking into this.
+       * collectd: Print error messages to STDERR if no log plugin has been
+         loaded.
+       * memory plugin: Handling of >4 Gbyte of memory has been fixed.
+       * network plugin: The license has been changed to LGPL 2.1.
+       * oracle plugin: Reconnect to the database if the connection dies.
+       * rrdcached plugin: Work-around for a bug in RRDtool 1.4rc2 has been
+         added.
+       * snmp plugin: Handling of negative values has been fixed. Strings
+         containing control characters are now interpreted as hex-strings.
+       * unixsock plugin: A memory leak in the LISTVAL command has been
+         fixed. Thanks to Ben Knight for his patch.
+
+2009-10-03, Version 4.7.4
+       * Build system: Issues when building the iptables plugin have been
+         fixed.
+       * exec plugin: Clear the signal block mask before calling exec(2).
+       * perl plugin: Declare the “environ” variable. This solves build
+         issues on some platforms.
+       * processes plugin: Remove unnecessary call of realloc(3). Thanks to
+         Andrés J. Díaz for the patch.
+       * unixsock plugin: Fix a (well hidden) race condition related to file
+         descriptor handling.
+
+2009-09-13, Version 4.7.3
+       * collectd: Fix a possible but very rare invalid “free” in the caching
+         code. Thanks to Sebastian Harl for the patch.
+       * collectd: Remove old values when a cache entry is marked as missing.
+         This way the “GETVAL” command of the UnixSock plugin doesn't return
+         old, no longer valid values when this happens. Thanks to Andrés J.
+         Díaz for the patch.
+       * collectd: The “plugin_unregister_read” function has been fixed.
+       * apache, ascent, bind, curl, nginx plugins: Advise the cURL library
+         to follow redirects. Thanks to Joey Hess for reporting this bug.
+       * df plugin: Check the ignorelist before stating the file system,
+         possibly reducing the number of stats considerably. Thanks to Joey
+         Hess for reporting this bug.
+       * iptables plugin: Support for the new libiptc API has been added.
+         Thanks to Sebastian Harl for the patch. The build system has been
+         updated to the plugin only includes the shipped header files when it
+         is linked with the shipped library, too.
+       * java plugin: Delay creating the JVM until after the daemon has
+         forked. The JVM internally creates threads that are lost when
+         forking. This means that Java-based plugins are now configured
+         during the init-phase, i. e. later than other plugins.
+       * libvirt plugin: Re-connect to libvirtd if connecting fails. Thanks
+         to Alan Pevec for the patch.
+       * network plugin: Fix the handling of the “CacheFlush” option: The
+         value was assigned to a wrong variable. The initialization of the
+         gcrypt library, which is used for signing / encrypting traffic, has
+         been fixed. Thanks to Luke Heberling for the patch.
+       * powerdns plugin: Set a timeout when reading data from the datagram
+         socket. Handling of the “LocalSocket” option has been fixed.  An
+         incorrectly used “type” has been corrected. Thanks to Luke Heberling
+         for his patches.
+
+2009-07-19, Version 4.7.2
+       * Build system: Support for `DESTDIR' has been fixed in the Java
+         bindings.
+       * collectd: Okay-notifications have been fixed. Thanks to Andrés J.
+         Díaz for fixing this bug.
+       * collectd: A programming error has been fixed in the notification
+         code. The bug may result in an assertion failure.
+       * memcached plugin: Portability fix for Solaris. Thanks to Amit Gupta
+         for reporting the bug.
+       * ping plugin: Link the plugin with libm.
+
+2009-06-02, Version 4.7.1
+       * Build system: Detection of Java has been improved and missing
+         details have been added to the configuration summary. Support for
+         libtool 2.2 has been added.
+       * collectd: Two bugs with the threshold checking have been fixed. The
+         first one prevented thresholds to be checked at all, the second one
+         caused wrong behavior with the persistency option. Thanks to Andrés
+         J. Díaz for fixing these problems.
+       * collectd: Handling of the `Include' configuration option has been
+         fixed.
+       * rrdtool plugin: Make sure initialization is run only once. This
+         resolves problems under Solaris and potentially other systems.
+         Thanks to Amit Gupta for reporting this bug.
+       * java plugin: Make it possible to use dots ('.') instead of slashes
+         ('/') as the class separator. Thanks to Randy Rizun for pointing
+         this out.
+       * swap plugin: A work-around for 32-bit Solaris has been added. Thanks
+         to Doug MacEachern for the patch.
+
+2009-05-11, Version 4.7.0
+       * apache plugin: Support to query multiple servers has been added.
+         Thanks to Amit Gupta for the patch.
+       * apache plugin: Handling of lighttpd's scoreboard statistics has been
+         improved. Thanks to Amit Gupta for the patch.
+       * conntrack plugin: The new conntrack plugin collects the connection
+         tracking table size. Thanks to Tomasz Pala for the patch.
+       * fscache plugin: The new fscache plugin collects statistics about
+         Linux' file-system based caching framework. Thanks to Edward
+         Konetzko for the patch.
+       * gmond plugin: The new gmond plugin can receive and interpret
+         multicast traffic from Ganglia's gmond daemon.
+       * java plugin: The new java plugin exports the collectd API to Java,
+         making it possible to write extensions to collectd in Java.
+       * memcachec plugin: The new memcachec plugin queries data from a
+         memcached daemon and parses it similar to the cURL plugin. Thanks to
+         Doug MacEachern for the initial code.
+       * memcached plugin: Support for connections over UNIX domain sockets
+         has been added. Thanks to Franck Lombardi for the patch.
+       * memory plugin: Support for OpenBSD and possibly other *BSDs has been
+         added. Thanks to Simon Kuhnle for the patch.
+       * mysql plugin: Support to query multiple databases has been added.
+         Thanks to Doug MacEachern for the patch.
+       * mysql plugin: Master/slave statistics have been added.
+       * mysql plugin: Lock statistics have been added. Thanks to Rodolphe
+         Quiédeville for the patch.
+       * network plugin: The possibility to sign or encrypt network traffic
+         has been added.
+       * protocols plugin: The new protocols plugin provides information
+         about network protocols, such as IP, TCP and UDP.
+       * snmp plugin: The intervals given in the configuration of the SNMP
+         plugin must no longer be a multiple of the global interval.
+       * table plugin: The new Table plugin provides parsing for table-like
+         structured files, such as many files beneath /proc.
+       * ted plugin: The new TED plugin reads power consumption measurements
+         from “The Energy Detective” (TED). Thanks to Eric Reed for this
+         plugin.
+       * onewire plugin: The new `Interval' option allows collecting
+         information from OneWire sensors at arbitrary intervals.
+       * ping plugin: Support for collecting the drop rate and standard
+         deviation of round-trip times has been added.
+       * uptime plugin: The new uptime plugin can collect the server's
+         uptime. Thanks to Marco Chiappero for the patch.
+
+2009-09-10, Version 4.6.5
+       * collectd: Remove old values when a cache entry is marked as missing.
+         This way the “GETVAL” command of the UnixSock plugin doesn't return
+         old, no longer valid values when this happens. Thanks to Andrés J.
+         Díaz for the patch.
+       * apache, ascent, bind, curl, nginx plugins: Advise the cURL library
+         to follow redirects. Thanks to Joey Hess for reporting this bug.
+       * df plugin: Check the ignorelist before stating the file system,
+         possibly reducing the number of stats considerably. Thanks to Joey
+         Hess for reporting this bug.
+       * iptables plugin: Support for the new libiptc API has been added.
+         Thanks to Sebastian Harl for the patch. The build system has been
+         updated to the plugin only includes the shipped header files when it
+         is linked with the shipped library, too.
+       * libvirt plugin: Re-connect to libvirtd if connecting fails. Thanks
+         to Alan Pevec for the patch.
+       * powerdns plugin: Set a timeout when reading data from the datagram
+         socket. Handling of the “LocalSocket” option has been fixed.  An
+         incorrectly used “type” has been corrected. Thanks to Luke Heberling
+         for his patches.
+
+2009-07-18, Version 4.6.4
+       * collectd: Okay-notifications have been fixed. Thanks to Andrés J.
+         Díaz for fixing this bug.
+       * collectd: A programming error has been fixed in the notification
+         code. The bug may result in an assertion failure.
+       * memcached plugin: Portability fix for Solaris. Thanks to Amit Gupta
+         for reporting the bug.
+
+2009-06-02, Version 4.6.3
+       * Build system, various plugins: Many build fixes for FreeBSD,
+         OpenBSD, NetBSD, Solaris and Mac OS X. Big thanks to Doug MacEachern
+         for many fixes and providing a build system for many platforms,
+         Ulf Zimmermann for providing a FreeBSD system and Simon Kuhnle for
+         providing an OpenBSD system.
+       * collectd: Two bugs with the threshold checking have been fixed. The
+         first one prevented thresholds to be checked at all, the second one
+         caused wrong behavior with the persistency option. Thanks to Andrés
+         J. Díaz for fixing these problems.
+       * collectd: Handling of the `Include' configuration option has been
+         fixed.
+       * battery plugin: Don't complain about a missing directory every
+         interval.
+       * exec plugin: Allow executed programs to close STDERR. Thanks to
+         Thorsten von Eicken for reporting this problem.
+       * irq plugin: Fix handling of overflowing 32-bit counters. Thanks to
+         Tomasz Pala for the patch.
+       * perl plugin: Portability build-fixes. Thanks to Doug MacEachern for
+         the patch.
+       * memory plugin: Fix a potential problem under Solaris.
+       * swap plugin: A work-around for 32-bit Solaris has been added. Thanks
+         to Doug MacEachern for the patch.
+
+2009-03-18, Version 4.6.2
+       * collectd: Some Solaris utility code has been improved.
+       * filter subsystem: Allow `Chains' without default targets.
+       * liboping: A patch to comply with strict aliasing rules has been
+         added.
+       * timediff match: Fix a typo: The match was registered with a wrong
+         name which prevented this match to be used as documented. Thanks to
+         Bruno Prémont for finding this problem.
+       * bind plugin: Fix collection of the cached RR sets. The number of RR
+         sets currently in the cache was collected as a counter value, which
+         is nonsense. Thanks to Bruno Prémont for implementing this.
+       * dns plugin: Don't pass NULL to `pcap_open_live': Some systems,
+         primarily BSDs, don't take it well and crash.
+       * oracle plugin: Portability to 64 bit systems has been improved.
+       * postgresql plugin: The default configuration has been improved.
+       * rrdtool plugin: Fix a possible race condition: If the network plugin
+         is brought and dispatches a value before the rrdtool plugin is
+         initialized, the daemon may crash.
+
+2009-02-22, Version 4.6.1
+       * collectd: Many documentation fixes.
+       * Collectd::Unixsock: Error handling has been improved.
+       * regex match: Don't link with the PCRE library.
+       * bind plugin: Various bugs have been fixed. Thanks to Bruno Prémont
+         for finding and fixing most of them.
+       * ipmi plugin: Fix an off-by-one error which could cause segmentation
+         faults. Thanks to Peter Holik for his patch.
+
+2009-02-16, Version 4.6.0
+       * collectd: Added the `filter chain' infrastructure, which allows the
+         user to use `matches' and `targets' to control value processing.
+       * collectd: The new `-T' command line argument allows more in-depth
+         testing of a configuration. Thanks to Doug MacEachern for the patch.
+       * collectd-nagios: The Nagios integration command has been updated to
+         use libcollectdclient. The `percentage' aggregation function has
+         been added. Thanks to Fabian Linzberger for the patch.
+       * libcollectdclient: A library which abstracts communication with the
+         unixsock plugin for clients has been added.
+       * regex match: Match values by their identifies using regular
+         expressions.
+       * timediff match: Match for values with an invalid timestamp.
+       * value match: Select values by their data sources' values.
+       * notification target: Create and dispatch a notification.
+       * replace target: Replace parts of an identifier using regular
+         expressions.
+       * set target: Set (overwrite) entire parts of an identifier.
+       * bind plugin: This new plugin uses the new HTTP/XML interface to BIND
+         statistics, allowing very detailed name server statistics. Thanks to
+         Bruno Prémont for this plugin.
+       * cpu plugin: Report `interrupt' separately when using
+         sysctlbyname(3) (used under *BSD). Support for sysctl(3), for
+         example for native OpenBSD support, has been added. Thanks to Simon
+         Kuhnle for the patch.
+       * csv plugin: Make it possible to write values to STDOUT instead of
+         files. This is meant for testing purposes mostly. The output written
+         to STDOUT is compatible with the exec plugin. Thanks to Doug
+         MacEachern for the patch.
+       * curl plugin: This new plugin can be used to read web pages and parse
+         them using the same mechanism that's used in the tail plugin.
+       * dbi plugin: This new plugin allows you to connect to a variety of
+         relational databases and use SQL to gather custom statistics from
+         it. It is similar to the already existing PostgreSQL plugin but uses
+         libdbi to communicate with the database(s).
+       * interface plugin: Use the ignorelist framework when selecting /
+         ignoring interfaces. This allows one to use regular expressions to
+         select interfaces, too.
+       * ipmi plugin: Handle temporary IPMI error conditions more gracefully.
+         Thanks to Bruno Prémont for this patch.
+       * memcached plugin: Add hit-ratio metric. Thanks to Doug MacEachern
+         for the patch.
+       * mysql plugin: Allow connecting to a database via the UNIX domain
+         socket, too. Thanks to Mirko Buffoni for the patch.
+       * network plugin: Further performance improvements for the receive
+         code. This hopefully will help very large setups.
+       * openvpn plugin: This new plugin collects statistics provided by the
+         OpenVPN daemon. Thanks to Doug MacEachern for the patch.
+       * oracle plugin: This new plugin allows you to connect to an Oracle
+         database and use SQL to gather custom statistics from it. It is
+         similar to the already existing PostgreSQL plugin.
+       * perl plugin: Compatibility fixes for broken versions of Perl 5.10
+         have been added.
+       * perl plugin: Export the newly added plugin_write() to Perl plugins.
+       * perl plugin: Added support for `notification meta data'.
+       * perl plugin: Added support for the `filter chain' infrastructure by
+         allowing plugins to register `matches' and `targets'.
+       * postgresql plugin: The preferred configuration syntax has been
+         updated to be in line with the syntax used by the new dbi and oracle
+         plugins. The compatibility code for the old syntax is present.
+         Support for the new `Result' blocks and the interval parameter has
+         been added.
+       * processes plugin: Stacksize and virtual memory usage statistics have
+         been added. Portability fixes.
+       * rrdcached plugin: This new plugin uses the (still in development)
+         RRD accelerator daemon, rrdcached. This daemon works very similar to
+         the original rrdtool plugin of collectd, but adds some more nice
+         features.
+       * swap plugin: Code for OpenBSD (and possibly other *BSDs) has been
+         added.
+
+2009-05-09, Version 4.5.4
+       * Build system, various plugins: Many build fixes for FreeBSD,
+         OpenBSD, NetBSD, Solaris and Mac OS X. Big thanks to Doug MacEachern
+         for many fixes and providing a build system for many platforms,
+         Ulf Zimmermann for providing a FreeBSD system and Simon Kuhnle for
+         providing an OpenBSD system.
+       * collectd: Fix a potential race condition when creating directories.
+       * battery plugin: Don't complain about a missing directory every
+         interval.
+       * dns plugin: Slight portability fixes.
+       * exec plugin: Allow executed programs to close STDERR. Thanks to
+         Thorsten von Eicken for reporting this problem.
+       * irq plugin: Fix handling of overflowing 32-bit counters. Thanks to
+         Tomasz Pala for the patch.
+       * perl plugin: Portability build-fixes. Thanks to Doug MacEachern for
+         the patch.
+       * rrdtool plugin: Fix a possible race condition: If the network plugin
+         is initialized and dispatches a value before the rrdtool plugin is
+         initialized, the daemon may crash.
+       * memory plugin: Fix a potential problem under Solaris.
+
+2009-02-22, Version 4.5.3
+       * build system: The check for libupsclient even when `pkg-config' is
+         not available.
+       * collectd: Fix error handling in the global cache.
+       * Collectd::Unixsock: Error handling has been improved.
+       * ascent plugin: Fix a memory leak. Thanks to Bruno Prémont for his
+         patch.
+       * ipmi plugin: Fix an off-by-one error which could cause segmentation
+         faults. Thanks to Peter Holik for his patch.
+       * tcpconns plugin: An endianness problem has been fixed in the *BSD
+         code. Thanks to "thated" for reporting this.
+
+2009-01-02, Version 4.5.2
+       * build system: Check for `mysql.h' and `mysql/mysql.h', since the
+         file may be in both locations, especially when the database was
+         installed in a non-standard path. Thanks to Dusty Doris for
+         reporting this.
+       * build system: Handle the _POSIX_PTHREAD_SEMANTICS defined, needed by
+         Solaris, in the configure script automatically.
+       * build system, tcpconns plugin: Check for `kvm_nlist' and
+         `kvm_openfiles' before enabling the plugin: Solaris provides a KVM
+         library with similar functions to the BSD variant, but doesn't
+         provide these necessary functions.
+       * collectd.conf(5): Various fixes and clarifications.
+       * collectd: Remove a GNUism (unnamed unions), thus improving
+         portability.
+       * collectd, apcups plugin: Include "collectd.h" before <stdlib.h>.
+         This solves portability problems, especially for Solaris.
+       * dns plugin: Fix a portability problem with NetBSD.
+       * filecount plugin: Fix an off-by-one error. This error may cause a
+         segmentation fault.
+       * network plugin: Fix the handling of `type' in the network protocol.
+         Due to a programming mistake, only 4 or 8 bytes would be copied to a
+         much larger buffer. This caused the `type' to be transferred much
+         more often than necessary. In some cases, e. g. the `cpu' and
+         `cpufreq' plugins being used at the same time, data may be corrupted
+         in those files. Thanks to Bruno Prémont for debugging and reporting
+         this issue.
+       * processes plugin: Fix a possible segmentation fault when specifying
+         invalid configuration options.
+       * unixsock plugin: Make sure the initialization function is run only
+         once. This resolves a file descriptor leak under systems which run
+         the initialization more than once, such as Solaris.
+
+2008-10-16, Version 4.5.1
+       * build system: Change `--enable-<plugin>' to abort with an error if
+         dependencies are not met. Thanks to Bruno Prémont for the patch.
+         Also, the poisoning of various string functions has been restricted
+         to debug builds.
+       * collectd: Fix a memory leak in the global value cache. With every
+         *missing* value a couple of bytes would be leaked. Another memory
+         leak in the configuration handling code has been fixed. Thanks to
+         Niraj Tolia for reporting these issues.
+       * collectd: Fix an off-by-one error in the ignorelist functionality.
+         When using regular expressions, the last character would be missing,
+         possibly matching differently from what one would expect.
+       * collectdmon: Don't block SIGCHLD. This fixes a potential portability
+         problem.
+       * collectd-nagios: Fix handling of the `-d' option. Thanks to Fabian
+         Linzberger for reporting the bug.
+       * iptables plugin: Fix an off-by-one error. If a string was just one
+         character too long, it was truncated instead of reporting an error.
+       * network plugin: Fix a memory leak in the configuration handling
+         code. Thanks to Niraj Tolia for reporting this issue.
+       * perl plugin: Log an error message if bootstrapping `Collectd' fails.
+       * postgresql plugin: Don't reopen connection during reinitialization.
+         This fixes a bug under Solaris and potentially other platforms.
+         Missing calls to `PQclear' have been added, too. This fixes memory
+         leaks. Thanks to ``Admin'' for reporting these bugs.
+       * snmp plugin: Don't expect null-terminated strings from the Net-SNMP
+         library.
+       * tail plugin: Call `clearerr(3)' after reading an EOF. This fixes
+         problems with some `libc's. Thanks to Matthias Lay for reporting the
+         bug.
+
+2008-09-04, Version 4.5.0
+       * collectd: Added the ability to flush certain identifiers.
+       * collectd: The concept of `notification meta data' has been
+         introduced.
+       * filecount plugin: The new filecount plugin counts the number of
+         files in a directory and its subdirectories.
+       * ipmi plugin: Sensor names have been changed to ensure unique names.
+         Notifications upon added and removed sensors can now be generated.
+       * notify_desktop plugin: This new plugin sends notifications to the
+         X desktop using the structure defined in the `Desktop Notification
+         Specification'.
+       * notify_email plugin: This new plugin sends out notifications via
+         email, using the `esmtp' library.
+       * onewire plugin: The new experimental(!) onewire plugin reads values,
+         such as temperatures, from sensors connected to the computer via the
+         onewire bus.
+       * perl plugin: Improved synchronized access to internal data structures
+         and fixed a possible dead-lock.
+       * perl plugin: Added the ability to flush certain identifiers and marked
+         plugin_flush_all() and plugin_flush_one() as deprecated in favor of
+         plugin_flush().
+       * perl plugin: Added the ability to configure Perl plugins.
+       * postgresql plugin: The new postgresql plugin collects statistics
+         about or from a PostgreSQL database.
+       * processes plugin: The `ProcessMatch' option has been added.
+       * rrdtool plugin: Implement throttling of the `update queue' to lessen
+         IO load.
+       * tcpconns plugin: This plugin has been ported to OpenBSD.
+       * thermal plugin: The new thermal plugin collects system temperatures
+         using Linux ACPI thermal zone data.
+
+2009-01-02, Version 4.4.5
+       * build system: Check for `mysql.h' and `mysql/mysql.h', since the
+         file may be in both locations, especially when the database was
+         installed in a non-standard path. Thanks to Dusty Doris for
+         reporting this.
+       * build system: Handle the _POSIX_PTHREAD_SEMANTICS defined, needed by
+         Solaris, in the configure script automatically.
+       * collectd.conf(5): Various fixes and clarifications.
+       * apcups plugin: Include "collectd.h" before <stdlib.h>. This solves
+         portability problems, especially for Solaris.
+       * dns plugin: Fix a portability problem with NetBSD.
+       * network plugin: Fix the handling of `type' in the network protocol.
+         Due to a programming mistake, only 4 or 8 bytes would be copied to a
+         much larger buffer. This caused the `type' to be transferred much
+         more often than necessary. In some cases, e. g. the `cpu' and
+         `cpufreq' plugins being used at the same time, data may be corrupted
+         in those files. Thanks to Bruno Prémont for debugging and reporting
+         this issue.
+       * unixsock plugin: Make sure the initialization function is run only
+         once. This resolves a file descriptor leak under systems which run
+         the initialization more than once, such as Solaris.
+
+2008-10-16, Version 4.4.4
+       * build system: Change `--enable-<plugin>' to abort with an error if
+         dependencies are not met. Thanks to Bruno Prémont for the patch.
+         Also, the poisoning of various string functions has been restricted
+         to debug builds.
+       * collectd: Fix a memory leak in the global value cache. With every
+         *missing* value a couple of bytes would be leaked. Another memory
+         leak in the configuration handling code has been fixed. Thanks to
+         Niraj Tolia for reporting these issues.
+       * collectd: Fix an off-by-one error in the ignorelist functionality.
+         When using regular expressions, the last character would be missing,
+         possibly matching differently from what one would expect.
+       * collectdmon: Don't block SIGCHLD. This fixes a potential portability
+         problem.
+       * collectd-nagios: Fix handling of the `-d' option. Thanks to Fabian
+         Linzberger for reporting the bug.
+       * network plugin: Fix a memory leak in the configuration handling
+         code. Thanks to Niraj Tolia for reporting this issue.
+       * perl plugin: Log an error message if bootstrapping `Collectd' fails.
+       * tail plugin: Call `clearerr(3)' after reading an EOF. This fixes
+         problems with some `libc's. Thanks to Matthias Lay for reporting the
+         bug.
+
+2008-09-01, Version 4.4.3
+       * collectd: Fix a memory leak in the threshold checking code.
+       * memcached plugin: Fix a too short timeout and a related file
+         descriptor leak.
+       * memory plugin: A typo in the libstatgrab code has been fixed.
+       * snmp plugin: Fix a possible memory leak.
+
+2008-07-15, Version 4.4.2
+       * build system: Use pkg-config to detect the upsclient library.
+       * collectd: Try even harder to determine the endianness of the
+         architecture collectd is being built on.
+       * disk plugin: Fix for Linux 2.4: A wrong field was used as the name
+         of disks.
+       * dns plugin: Fix compilation errors with BIND versions 19991001
+         through 19991005.
+       * network plugin: Bugfix in the init routine: The init function
+         cleared a buffer regardless of its contents. This could lead to lost
+         values under Solaris.
+       * nginx plugin: Remove usage of the thread-unsafe `strtok' function.
+       * vserver plugin: Remove usage of the thread-unsafe `readdir'
+         function.
+       * wireless plugin: Work around incorrect noise and power values
+         returned by some broken drivers.
+
+2008-06-03, Version 4.4.1
+       * collectd: Fix the `DataSource' option within `Type' blocks. Thanks
+         to kyrone for reporting this.
+       * collectd: Fixed min/max output in notifications generated by
+         threshold checking.
+       * collectd-nagios: Fix the protocol used to communicate with the
+         daemon.
+       * perl plugin: Fail noisily, but don't shutdown the daemon, if
+         initialization has errors. An issue with Perl 5.10 has been fixed.
+       * teamspeak2 plugin: Fixed an out of bound array access. Thanks to
+         René Rebe and Siegmund Gorr for reporting this.
+
+2008-05-06, Version 4.4.0
+       * collectd: Internal code cleanups.
+       * collectd: Added support for a `Flush' command in the unixsock and
+         exec plugins. This command can be used to force a plugin (or all) to
+         flush its values to disk.
+       * collectd: Thresholds can now be configured to apply to one data
+         source only, making it possible to configure different thresholds
+         for each data source.
+       * apache, nginx plugins: Added the possibility to disable host and/or
+         peer verification.
+       * ascent plugin: The new ascent plugin reads and parses the statistics
+         page of an Ascent server.
+       * cpu plugin: Support for the statgrab library has been added.
+       * disk plugin: The possibility to ignore certain disks or collect only
+         specific disks has been added.
+       * disk plugin: Support for the statgrab library has been added.
+       * ipmi plugin: The new ipmi plugin uses the OpenIPMI library to read
+         sensor values via IPMI, the intelligent platform management
+         interface.
+       * iptables plugin: The iptc library that is used by the iptables
+         plugin has been added to the distribution, because it is not
+         provided by all distributions and removed from at least one.
+       * powerdns plugin: The new powerdns plugin reads statistics from an
+         authoritative or a recursing PowerDNS name server.
+       * rrdtool plugin: The size of the files generated with the default
+         configuration has been decreased.
+       * tail plugin: The new tail plugin can be used to gather statistics by
+         continuously reading from log files.
+       * teamspeak2 plugin: The new teamspeak2 plugin connects to a
+         TeamSpeak2 server and collects statistics about the number of users
+         and number of channels.
+       * users plugin: Support for the statgrab library has been added.
+       * vmem plugin: The new vmem plugin collects very detailed statistics
+         about the virtual memory subsystem of Linux.
+
+2008-08-30, Version 4.3.4
+       * Build system: Improved detection of and linking with the statgrab
+         library.
+       * collectd: Portability fixes, especially to determine endianness more
+         reliable.
+       * Various plugins: Fix format strings.
+       * disk plugin: A fix for giving disks under Linux 2.4 the right names
+         again has been applied.
+       * memcached plugin: Fix a too short timeout and a related file
+         descriptor leak.
+       * memory plugin: A typo in the libstatgrab code has been fixed.
+       * network plugin: A fix in the initialization function solves problems
+         under Solaris.
+       * nginx plugin: A thread-unsafe function has been replaced.
+       * vserver plugin: A thread-unsafe function has been replaced.
+       * wireless plugin: A work-around for broken wireless drivers has been
+         added.
+
+2008-04-22, Version 4.3.3
+       * build system: Improved detection of several libraries, especially if
+         they are in non-standard paths.
+       * build system: Portability fixes: Automatically define "_REENTRANT"
+         if the libc expects it.
+       * collectd: Error and warning messages have been improved.
+       * collectd: Check for the BYTE_ORDER and BIG_ENDIAN defines before
+         using them.
+       * apache plugin: Allocate new memory when reading a webpage instead of
+         using a buffer of static size.
+       * exec plugin: Close (almost) all filedescriptors before exec(2)ing
+         the program.
+       * hddtemp plugin: Error and warning messages have been improved.
+       * sensors plugin: Fix sensor collection for some chip types.
+
+2008-03-29, Version 4.3.2
+       * collectd: Fix configuration of the `FailureMax', `WarningMax', and
+         `Persist' threshold options.
+       * collectd: Fix handling of missing values in the global value cache.
+       * collectd: Improved error messages when parsing the configuration.
+       * sensors plugin: Fix temperature collection with libsensors4.
+       * unixsock plugin: Fix mixed input and output operation on streams.
+       * wireless plugin: Fix reading noise value.
+
+2008-03-05, Version 4.3.1
+       * exec plugin: Set supplementary group IDs.
+       * network plugin:
+         + Use `memcpy' when constructing/parsing a package to avoid
+           alignment problems on weird architectures, such as Sparc.
+         + Translate doubles to/from the x86 byte representation to ensure
+           cross-platform compatibility.
+       * ping plugin: Correct the handling of the `TTL' setting.
+       * swap plugin: Reapply a patch for Solaris.
+       * tcpconns plugin: Portability improvements.
+
+2008-02-18, Version 4.3.0
+       * collectd: Notifications have been added to the daemon. Notifications
+         are status messages that may be associated with a data instance.
+       * collectd: Threshold checking has been added to the daemon. This
+         means that you can configure threshold values for each data
+         instance. If this threshold is exceeded a notification will be
+         created.
+       * collectd: The new `FQDNLookup' option tells the daemon to use the
+         full qualified domain name as the hostname, not just the host part
+         es returned by `gethostname(2)'.
+       * collectd: Support for more than one `TypesDB' file has been added.
+         This is useful when one such file is included in a package but one
+         wants to add custom type definitions.
+       * collectd: The `Include' config option has been expanded to handle
+         entire directories and shell wildcards.
+       * collectdmon: The new `collectdmon' binary detects when collectd
+         terminates and automatically restarts it again.
+       * csv plugin: The CSV plugin is now able to store counter values as a
+         rate, using the `StoreRates' configuration option.
+       * exec plugin: Handling of notifications has been added and the
+         ability to pass arguments to the executed programs has been added.
+       * hddtemp plugin: The new `TranslateDevicename' option lets you
+         disable the translation from device names to major-minor-numbers.
+       * logfile plugin: Handling of notifications has been added.
+       * ntpd plugin: The new `ReverseLookups' can be used to disable reverse
+         domain name lookups in this plugin.
+       * perl plugin: Many internal changes added support for handling multiple
+         threads making the plugin reasonably usable inside collectd. The API has
+         been extended to support notifications and export global variables to
+         Perl plugins; callbacks now have to be identified by name rather than a
+         pointer to a subroutine. The plugin is no longer experimental.
+       * uuid plugin: The new UUID plugin sets the hostname to an unique
+         identifier for this host. This is meant for setups where each client
+         may migrate to another physical host, possibly going through one or
+         more name changes in the process. Thanks to Richard Jones from
+         Red Hat's Emerging Technology group for this plugin.
+       * libvirt: The new libvirt plugin uses the `libvirt' library to query
+         CPU, disk and network statistics about guest systems on the same
+         physical server. Thanks to Richard Jones from Red Hat's Emerging
+         Technology group for this plugin.
+
+2008-04-22, Version 4.2.7
+       * build system: Improved detection of several libraries, especially if
+         they are in non-standard paths.
+       * build system: Portability fixes: Automatically define "_REENTRANT"
+         if the libc expects it.
+       * collectd: Error and warning messages have been improved.
+       * collectd: Check for the BYTE_ORDER and BIG_ENDIAN defines before
+         using them.
+       * apache plugin: Allocate new memory when reading a webpage instead of
+         using a buffer of static size.
+       * exec plugin: Close (almost) all filedescriptors before exec(2)ing
+         the program.
+       * hddtemp plugin: Error and warning messages have been improved.
+       * sensors plugin: Fix sensor collection for some chip types.
+
+2008-03-29, Version 4.2.6
+       * collectd: Improved error messages when parsing the configuration.
+       * sensors plugin: Fix temperature collection with libsensors4.
+       * unixsock plugin: Fix mixed input and output operation on streams.
+       * wireless plugin: Fix reading noise value.
+
+2008-03-04, Version 4.2.5
+       * apache plugin: Improved initialization and error messages.
+       * exec plugin: Set supplementary group IDs.
+       * network plugin:
+         + Create separate threads for reading from the socket and parsing
+           and dispatching incoming packets. Versions prior to this may have
+           problems in high-load situations, where the socket receive buffers
+           overflows, resulting in gaps in the data.
+         + Use `memcpy' when constructing/parsing a package to avoid
+           alignment problems on weird architectures, such as Sparc.
+         + Translate doubles to/from the x86 byte representation to ensure
+           cross-platform compatibility.
+       * ping plugin: Correct the handling of the `TTL' setting.
+       * rrdtool plugin: Ensure correct handling of the `RRATimespan' option.
+       * swap plugin: Reapply a patch for Solaris.
+       * tcpconns plugin: Portability improvements.
+
+2008-01-21, Version 4.2.4
+       * unixsock plugin: A bug in the unixsock plugin caused it not to set
+         the permission on the socket as documented in the manpage. Thanks to
+         Evgeny Chukreev for fixing this issue.
+       * collectd: The documentation has been improved.
+
+2007-12-28, Version 4.2.3
+       * sensors plugin: Updated the plugin to build and work with version 3
+         of the libsensors library.
+
+2007-12-15, Version 4.2.2
+       * nginx plugin: Incorrect comparison of strings lead to a segfault
+         when using the plugin. Thanks to Saulius Grigaliunas for fixing
+         this.
+       * logfile plugin: The config option `Timestamp' was handled
+         incorrectly and basically always active. Thanks to Luke Heberling
+         for fixing this.
+
+2007-11-08, Version 4.2.1
+       * tcpconns plugin: Don't complain about a missing file if IPv6 is not
+         enabled on the host.
+       * snmp plugin: Fix a memory leak.
+
+2007-10-27, Version 4.2.0
+       * collectd: The new config option `Include' lets you include other
+         configfiles and thus split up your config into smaller parts. This
+         may be especially interesting for the snmp plugin to keep the data
+         definitions separate from the host definitions.
+       * ipvs plugin: The new `ipvs' plugin collects IPVS connection statistics
+         (number of connections, octets and packets for each service and
+         destination). Thanks to Sebastian Harl for this plugin.
+       * memcached plugin: The new `memcached' plugin connects to a memcached
+         daemon process and collects statistics of this distributed caching
+         system. Thanks to Antony Dovgal for contributing this plugin.
+       * nginx plugin: The new `nginx' plugin reads the status page of an
+         nginx daemon and saves the handled connections and requests.
+       * perl plugin: Many changes, including the added `EnableDebugger'
+         config option which lets you debug your Perl plugins more easily.
+       * rrdtool plugin: Use the thread-safe RRD-library if available. Try to
+         be more thread-safe otherwise by locking calls to the library.
+       * snmp plugin: Added the options `Scale' and `Shift' to Data-blocks to
+         correct the values returned by SNMP-agents. If a <data> block is
+         defined as `table' the instance is now optional. The sequence number
+         is used as the type-instance in this case. The new `InstancePrefix'
+         option allows to add arbitrary prefixes to the type-instance.
+       * tcpconns plugin: The new `tcpconns' plugin collects the number of
+         certain TCP connections and what state they're in. This can be used
+         to see how many connections your FTP server has to handle or how
+         many outgoing connections your mailserver has open.
+
+2008-01-11, Version 4.1.6
+       * unixsock plugin: A bug in the unixsock plugin caused it not to set
+         the permission on the socket as documented in the manpage. Thanks to
+         Evgeny Chukreev for fixing this issue.
+       * collectd: The documentation has been improved.
+
+2007-12-27, Version 4.1.5
+       * rrdtool plugin: Fix a memory leak that only occurred in very-low-
+         memory situations.
+       * sensors plugin: Updated the plugin to build and work with version 3
+         of the libsensors library.
+
+2007-11-08, Version 4.1.4
+       * Build system: Improve detection of the rrd library, especially if
+         it's in a non-standard location.
+       * Build system: A bug when parsing the argument for
+         `--with-libnetsnmp' has been fixed.
+       * collectd: Implement `strerror_r' if the libc doesn't provide it.
+       * rrdtool plugin: Fix a bug in the shutdown sequence that might cause
+         a deadlock or delay when shutting down the daemon.
+       * snmp plugin: Fix a memory leak.
+
+2007-10-24, Version 4.1.3
+       * collectd: A build issue under Solaris has been resolved by renaming
+         data types.
+       * rrdtool plugin: Use the thread-safe RRD-library if available. Try to
+         be more thread-safe otherwise by locking calls to the library.
+
+2007-09-28, Version 4.1.2
+       * apcups plugin: Fix reporting of the `load percent' data.
+       * wireless plugin: Correct the handling of cards returning signal and
+         noise quality as percentage.
+       * perl plugin: Fix a possible buffer overflow in get_module_name().
+       * build system: Further improve the detection of libraries.
+       * netlink plugin: Build issues under some older versions of the Linux
+         includes (i. e. Debian Sarge) have been fixed.
+       * snmp plugin: Fix a potential segfault when a host times out. Add
+         support for the `timeticks' type. 
+
+2007-09-12, Version 4.1.1
+       * Build system: The detection of `libnetlink' has been improved.
+       * collectd: The documentation has been fixed in numerous places.
+       * exec plugin: Setting the group under which to run a program has been
+         fixed.
+       * collectd: The `sstrerror' function was improved to work correctly
+         with the broken GNU version of `strerror_r'.
+       * collectd: Write an error message to STDERR when loading of a plugin
+         fails.
+       * apcups plugin: Fix the `types' used to submit the values: They still
+         has an `apcups_' prefix which doesn't work anymore.
+       * rrdtool plugin: Create new RRD-files with the `begin' time set to
+         whatever the client thinks is `now'..
+
+2007-09-01, Version 4.1.0
+       * Build system: The build system has been changed to automatically
+         disable all plugins, which are missing dependencies. The dependency
+         checking has been removed from the plugins themselves to remove
+         redundancy.
+       * Flexible interval: The interval of collected data is now sent along
+         with the data itself over the network, so that the interval-settings
+         of server and clients no longer needs to match.
+       * netlink plugin: The new `netlink' plugin connects to the Linux
+         kernel using a netlink socket and uses it to query information about
+         interfaces, qdiscs and classes.
+       * rrdtool plugin: The cache is now dumped to disk in an extra thread
+         to not block data collection.
+       * snmp plugin: The new `snmp' plugin can read values from SNMP enabled
+         network devices, such as switches, routers, thermometers, rack
+         monitoring servers, etc. The collectd-snmp(5) manpage documents this
+         plugin.
+       * unixsock plugin: Added the `LISTVAL' command.
+       * xmms plugin: The new `xmms' plugin graphs the bitrate and frequency
+         of music played with xmms.
+
+2007-09-28, Version 4.0.9
+       * apcups plugin: Fix reporting of the `load percent' data.
+       * wireless plugin: Correct the handling of cards returning signal and
+         noise quality as percentage.
+       * perl plugin: Fix a possible buffer overflow in get_module_name().
+
+2007-09-12, Version 4.0.8
+       * collectd: The `sstrerror' function was improved to work correctly
+         with the broken GNU version of `strerror_r'.
+       * collectd: Write an error message to STDERR when loading of a plugin
+         fails.
+       * apcups plugin: Fix the `types' used to submit the values: They still
+         has an `apcups_' prefix which doesn't work anymore.
+       * rrdtool plugin: Create new RRD-files with the `begin' time set to
+         whatever the client thinks is `now'..
+
+2007-08-26, Version 4.0.7
+       * documentation: Some typos have been fixed and some information has
+         been improved.
+       * build system: Many fixes for detecting libraries in unusual places,
+         such as on RedHat systems. The affected libraries are `libcurl',
+         `libmysql', and `libupsclient'.
+       * network plugin: Allow the `Port' option to be specified as a number
+         (i. e. without quotes).
+       * nut plugin: A fix allows linking the nut plugin against
+         libupsclient, version >= 2.2.0.
+       * processes plugin: Fix a potential segmentation fault.
+
+2007-07-30, Version 4.0.6
+       * sensors plugin: Fix the ignorelist functionality: Only the `type
+         instance' was used to match against the list, but the documentation
+         told otherwise. This release fixes the code, so it complies with the
+         documentation.
+       * syslog plugin: Call `openlog' right when the plugin is loaded, so
+         configuration messages will end up in the logging facility.
+       * conrtib/fedora: The contributed specfile for Fedora has been
+         updated.
+
+2007-07-05, Version 4.0.5
+       * Portability: More fixes for OpenBSD have been included.
+
+2007-06-24, Version 4.0.4
+       * cpu plugin: Fixed the Solaris code.
+       * dns plugin: Fixed a build issue for OpenBSD.
+       * interface plugin: Fixed the Solaris code.
+       * load plugin: Fixed the alternative `/proc' Linux code.
+       * memory plugin: Fixed the Solaris code.
+       * oconfig: Don't require `-lfl' anymore.
+
+2007-06-19, Version 4.0.3
+       * cpu plugin: Fix the Darwin / Mac OS X code.
+       * ping plugin: Use the return value of `getpid', not its address.
+       * csv, rrdtool plugin: Fixed a bug that prevented an buffer to be
+         initialized correctly.
+       * configure: Added `--with-nan-emulation' to aid cross compilation.
+
+2007-06-12, Version 4.0.2
+       * hddtemp and ntpd plugin: Corrected the parsing of port numbers when
+         they're given in numerically form.
+
+2007-06-07, Version 4.0.1
+       * iptables plugin: A bug in the configuration routine has been fixed.
+         Setting a comment in the configfile will no longer cause a
+         segmentation fault.
+
+2007-06-03, Version 4.0.0
+       * collectd: The plugin-infrastructure has been changed to allow for
+         more types of plugins, namely `write' and `log' plugins.
+       * collectd: The read-function has been changed to read many plugins in
+         parallel, using threads. Thus, plugins generally need to use
+         thread-safe functions from now on.
+       * collectd: The '-t' command line options allows to perform syntax tests
+         of the configuration file and exit immediately.
+       * csv plugin: The new `csv' plugin handles output to `comma separated
+         values'-files.
+       * rrdtool plugin: The new `rrdtool' plugin handles output to
+         RRD-files. Data can be cached to combine multiple updates into one
+         write to increase IO-performance.
+       * network plugin: The new `network' plugin handles IO via the network.
+         It implements a different, much more extensible protocol which can
+         combine many values in one packet, decreasing the number of UDP-
+         packets being sent. It can read from and send to the network and
+         with the appropriate configuration even forward packets to other
+         networks.
+       * unixsock plugin: The new `unixsock' plugin provides an interface to
+         communicate with the daemon while it is running. Right now the
+         commands `GETVAL' and `PUTVAL' are implemented, but more are to
+         come.
+       * perl plugin: The new `perl' plugin allows you to write extensions
+         for collectd in the scripting-language Perl.
+       * logfile plugin: The new `logfile' plugin writes logmessages to files
+         or STDOUT or STDERR.
+       * syslog plugin: The new `syslog' plugin sends logmessages to the
+         system's syslog daemon.
+       * entropy plugin: The new `entropy' plugin collects the amount of
+         entropy currently being available to the system.
+       * exec plugin: The new `exec' plugin forks child processes and reads
+         back values provided by the forked processes.
+       * iptables plugin: The new `iptables' plugin reads counters from
+         iptables rules. Thanks to Sjoerd van der Berg for contributing this
+         plugin.
+       * irq plugin: The new `irq' plugin collects the IRQ-counters. Thanks
+         to Peter Holik for contributing this plugin.
+       * nut plugin: The new `nut' plugin connects the upsd of the `network
+         ups tools' and reads information about the connected UPS.
+       * apache plugin: Support for lighttpd's `BusyServers' (aka.
+         connections) field was added by Florent Monbillard.
+       * collectd-nagios: The new `collectd-nagios' binary queries values
+         from collectd, parses them and exits according to Nagios-standards.
+       * manpages: The manpages have been improved a lot.
+
+2007-09-28, Version 3.11.7
+       * wireless plugin: Correct the handling of cards returning signal and
+         noise quality as percentage.
+
+2007-08-31, Version 3.11.6
+       * processes plugin: Fix a potential segmentation fault.
+
+2007-05-29, Version 3.11.5
+       * configure: Added `AC_SYS_LARGEFILE' for LFS.
+       * ntpd plugin: Fix a potential buffer overflow.
+       * processes plugin: Fix a bug when run under Linux 2.4. All processes
+         were accounted as `zombies'.
+
+2007-04-10, Version 3.11.4
+       * dns plugin: Change the order of includes to make the plugin compile
+         under FreeBSD.
+
+2007-03-30, Version 3.11.3
+       * configure: Have the configure-script define `HAVE_LIBKSTAT' instead
+         of the unused `COLLECT_KSTAT'.
+
+2007-02-11, Version 3.11.2
+       * plugin: Catch NULL-pointer and try to fix them. Otherwise the
+         NULL-pointer may have been passed to `printf' which causes a
+         segfault with some libcs.
+
+2007-02-10, Version 3.11.1
+       * df plugin: Some wrong defines have been fixed so the plugin works
+         under Solaris again.
+       * dns plugin: The usage of a struct has been fixed to work with
+         non-GNU libcs.
+       * processes plugin: Some missing defines have been added so the plugin
+         compiles cleanly under FreeBSD and presumably other UNIXes.
+
+2006-12-22, Version 3.11.0
+       * collectd: The new command line option `-P' makes it easier for
+         distributors to change the location of PID-files.
+       * collectd: The daemon shuts down faster now which makes it easier to
+         write init.d-scripts for it.
+       * apache plugin: Increase the buffersize to 16k, because the 4k buffer
+         caused problems every now and then.
+       * df plugin: New config options allow to ignore certain mountpoints,
+         filesystem types or devices.
+       * dns plugin: The new dns plugin uses `libpcap' to capture DNS traffic
+         and interprets it. It collects traffic as well as qtype, opcode and
+         rcode counts.
+       * email plugin: Sebastian Harl has contributed this plugin which
+         counts received mails in categories (e. g. ham, spam, virus), spam
+         score (as given by SpamAssassin) and check types.
+       * mbmon plugin: Flavio Stanchina has contributed this plugin which
+         uses `mbmon' to gather information from sensors on the motherboard.
+       * processes plugin: Collect detailed statistics for configured
+         processes, that's process and thread count, CPU usage, resident
+         segment size and pagefaults.
+       * multimeter plugin: Peter Holik contributed a new plugin which
+         queries multimeters.
+       * sensors plugin: Lubos Stanek has put much effort into improving this
+         plugin, including `extended naming', collection of voltage values
+         and the possibility to ignore certain values.
+
+2006-12-21, Version 3.10.4
+       * Max Kellermann has identified a bug in the server routine: When
+         opening a socket fails the daemon will (re)try opening the socket in
+         an endless loop, ultimately leading to a `EMFILE' error.
+
+2006-11-04, Version 3.10.3
+       * Lubos Stanek has identified a bug in the ntpd-plugin: When the
+         ntpd's reply was sent in more than one packet, the buffer size was
+         calculated incorrectly, resulting in the reading of uninitialized or
+         freed memory.
+
+2006-11-01, Version 3.10.2
+       * The sample config file has been improved.
+       * Errors in the manpages have been corrected.
+       * The ping-plugin now adds hosts during initialization, not during
+         startup. This speeds up startup when no network connectivity is
+         available. Also, the hosts are being added later when the network is
+         available.
+       * Improved BSD-support for the df-plugin.
+       * Fixed syntax errors in the swap-plugin for Mac OS X.
+       * Fix a wrong structure being passed to `getnameinfo' in the ntpd-
+         plugin.
+       * Don't disable the mysql-plugin if connecting to the database fails
+         during initialization. Instead, try again in increasing intervals.
+
+2006-07-19, Version 3.10.1
+       * A bug in the apcups plugin was fixed: Is the plugin is loaded, but
+         the apcups cannot be reached, unconnected sockets will pile up and
+         eventually lead to `Too many open files' errors.
+
+2006-07-09, Version 3.10.0
+       * The `disk' plugin has been ported to Darwin.
+       * The `battery' plugin should work on many Apple computers now.
+       * The `traffic' plugin can now ignore certain interfaces. Also,
+         statistics for sent/received packets and errors have been added.
+       * A plugin to monitor APC UPSes using `apcupsd' has been added. Thanks
+         to Anthony Gialluca for contributing this plugin and providing me
+         with a test environment :)
+       * A plugin for monitoring an NTP instance and the local clock drift
+         has been added.
+
+2006-06-25, Version 3.9.4
+       * The Solaris code in the `swap' plugin has been changed to reflect
+         the numbers returned by `swap -s'. Thanks to Christophe Kalt for
+         working this out.
+       * The debugging system has been fixed to work with the Sun libc.
+       * When built without librrd the variable `operating_mode' could be
+         uninitialized. Thanks to David Elliot for reporting the bug.
+
+2006-06-01, Version 3.9.3
+       * Fixed the ping-plugin under FreeBSD and Mac OS X. Potentially other
+         operating systems also profit from the changes, but I wasn't able to
+         check that.
+       * Changed the build system to find the netinet-includes under FreeBSD
+         and therefore successfully build the `liboping' library there.
+
+2006-05-09, Version 3.9.2
+       * Applied a patch to the `liboping' library. Due to a bug in the
+         sequence checking the `ping' plugin stopped working after
+         approximately 7.6 days.
+
+2006-05-09, Version 3.8.5
+       * Applied a patch to the `liboping' library. Due to a bug in the
+         sequence checking the `ping' plugin stopped working after
+         approximately 7.6 days.
+
+2006-04-21, Version 3.9.1
+       * Build issues with Solaris and possible other architectures have been
+         resolved.
+       * Problems when building the `apache'-plugin without `libcurl' have
+         been resolved.
+       * A bug in the `ping' plugin has been fixed. Sorry folks.
+
+2006-04-02, Version 3.9.0
+       * A plugin to monitor the Apache webserver has been added.
+         <http://httpd.apache.org/>
+       * A plugin to collect statistics about virtual servers using VServer.
+         <http://linux-vserver.org/> Thanks to Sebastian Harl for writing
+         this plugin :)
+       * A plugin for wireless LAN cards has been added. It monitors signal
+         strength, link quality and noise ratio..
+       * A plugin for Apple hardware sensors has been added.
+       * An option to compile collectd with different `step' and `heartbeat'
+         settings has been added. The size of RRAs is no longer static but
+         calculated based on the settings for `step' and `width'.
+       * The `ping' plugin can now be configured to use a certain TTL.
+       * A plugin to monitor the hardware sensors of Apple computers has been
+         added.
+       * The plugins `cpu', `memory', `processes' and `traffic' have been
+         ported to Mach/Darwin (Mac OS X).
+       * The `log mode' has been contributed by Christophe Kalt. It writes
+         the data into text files rather than RRD files.
+
+2006-04-09, Version 3.8.4
+       * Applied patch by Vincent Stehlé which improves the disk-name
+         resolution in the `hddtemp' plugin for Linux systems.
+
+2006-04-02, Version 3.8.3
+       * Applied a patch by James Byers: The MySQL plugin was not working
+         with MySQL 5.0.2 or later.
+
+2006-03-14, Version 3.8.2
+       * `utils_mount.c' has been changed to not use the `MNTTAB' defined by
+         the GNU libc, because it points to `/etc/fstab' rather than
+         `/etc/mtab'.
+
+2006-03-13, Version 3.8.1
+       * Fixes for building collectd under FreeBSD, Mac OS X and Solaris.
+       * Fixes in the debian `postinst' and `init.d' scripts.
+
+2006-03-09, Version 3.8.0
+       * The `ping' plugin no longer uses `libping' but a self written
+         library named `liboping'. With this library it's possible to ping
+         multiple IPv4 and IPv6 addresses and hostnames - in parallel.
+
+2006-02-18, Version 3.7.2
+       * A simple bug in the `battery' plugin has been fixed. It should now
+         work with ACPI based batteries as well. Thanks to Sebastian for
+         fixing this.
+       * Fixing a bug that prevented collectd to be built without librrd.
+         Thanks to Werner Heuser for reporting it.
+
+2006-02-04, Version 3.7.1
+       * The new network code has been improved to build with older versions
+         of glibc.
+       * Fix in `libping' sets the ICMP sequence on outgoing packets. Thanks
+         to Tommie Gannert for this patch.
+
+2006-01-30, Version 3.7.0
+       * The `battery' plugin has been added. It collects information about
+         laptop batteries..
+       * The MySQL plugin has been improved: It now writes two more RRD
+         files, `mysql_qcache.rrd' and `mysql_threads.rrd'.
+       * The `cpufreq' plugin now reads another file since the file it did
+         read so far causes much overhead in the kernel. Also, you need root
+         to read the old file, but not to read the new one.
+       * The `hddtemp' plugin can now be configured to connect to another
+         address and/or port than localhost.
+       * The `df' plugin now prefers `statvfs' over `statfs'.
+       * The network code has been rewritten. collectd now supports unicast
+         and multicast, and IPv4 and IPv6. Also, the TTL of sent packages can
+         be set in the configfile.
+
+2006-01-24, Version 3.6.2
+       * Due to a bug in the configfile handling collectd wouldn't start in
+         client mode. This released fixes this.
+
+2006-01-20, Version 3.6.1
+       * Due to a bug in `configure.in' all modules and the binary were
+         linked against `libmysqlclient'. This issue is solved by this
+         release.
+
+2006-01-17, Version 3.6.0
+       * A config file has been added. This allows for loading only specific
+         plugins.
+       * A `df' plugin has been added.
+       * A `mysql' plugin has been added.
+       * The `ping' plugin doesn't entirely give up hope when a socket error
+         occurred, but will back of and increase the intervals between tries.
+
+2006-01-21, Version 3.5.2
+       * Fixed yet another bug in the signal handling.. Stupid typo..
+       * Improved the ping plugin to not give up on socket errors (backport
+         from 3.6.0).
+
+2005-12-18, Version 3.5.1
+       * The PID-file is now deleted correctly when shutting down the daemon.
+       * SIGINT and SIGTERM are now handled correctly.
+
+2005-12-16, Version 3.5.0 (Revision 326)
+       * A bug in the `load' module under Solaris has been fixed.
+       * The `users' module has been contributed by Sebastian Harl. It counts
+         currently logged in users.
+       * The CPU module now works under FreeBSD without the use of
+         `libstatgrab', however SMP support is missing.
+       * The default directories for the RRD files and the PID file now
+         depend on the compile time setting of `localstatedir'.
+
+2005-11-15, Version 3.4.0 (Revision 236)
+       * A PID-file is written to /var/run upon startup. Thanks to `Tommie'
+         from gentoo's bugzilla for writing the patch.
+       * The build dependency for librrd has been removed. Binaries built
+         without librrd are client-only and will multicast their value as
+         with the `-c' argument.
+       * A patch by Peter Holik adds a module for monitoring CPU frequencies.
+       * The newly introduced `-f' switch prevents daemon initialization
+         (forking, closing standard filehandles, etc.) Thanks to Alvaro
+         Barcellos for this patch.
+
+2005-11-04, Version 3.3.0 (Revision 216)
+       * New modules have been added:
+         - `serial', for monitoring traffic on the serial interfaces
+         - `nfs', for graphing NFS procedure calls
+         - `tape', traffic from/to tape devices
+       * The memory.rrd now accepts more than 4Gig of memory.
+
+2005-10-26, Version 3.2.0 (Revision 200)
+       * Support for graphing the processes has been added (thanks to Lyonel
+         Vincent)
+       * If reading from hddtemp fails collectd will increase the time
+         between polls up to one day.
+       * The init.d files have been improved.
+       * Problems with the spec file have been fixed.
+
+2005-10-16, Version 3.1.0 (Revision 194)
+       * Added the `setsid' syscall to the startup code.
+       * Support for hddtemp has been added (thanks to Vincent Stehlé)
+
+2005-09-30, Version 3.0.0 (Revision 184)
+       * The ability to send/receive data to/from the network (think
+         multicast) has been added.
+       * Modules have been split up into shared libraries can be loaded at
+         runtime. The biggest advantage is that the core program doesn't need
+         to be linked against an external library.
+       * A patch by George Kargiotakis has been applied: It fixes the sensors
+         behaviour then more than one sensor is being queried.
+
+2005-09-16, Version 2.1.0 (Revision 172)
+       * A module for swap statistics has been added.
+
+2005-09-09, Version 2.0.0 (Revision 135)
+       * Filenames can no longer be configured at program startup. The only
+         options as of this version are the directory and ping hosts.
+       * CPU statistics now include Wait-IO. If provided under Linux IRQ and
+         Soft-IRQ statistics are added to `System'. 
+       * Diskstats now collect read and write bytes, not sectors.
+       * Ping statistics can now be collected for more than one host. There
+         is no default any more: If no host is given no host will be pinged.
+       * A self-written patch for libping has been applied so it builds
+         cleanly.
+
+2005-09-01, Version 1.8.1 (Revision 123)
+       * Much improved configure-script: libraries and features may now be
+         disabled.
+       * More detailed warnings/error messages when RRD update fails.
+
+2005-08-29, Version 1.8.0:
+       * Support for collecting disk statistics under Solaris.
+
+2005-08-25, Version 1.7.0:
+       * Support for libstatgrab[1] for load, memory usage and network
+         traffic. CPU- and disk-usage are not (yet) supported, since
+         libstatgrab returns insufficient information. I will contact the
+         authors.
+       * Improved the CPU-initialization code for Solaris. Apparently CPUs
+         aren't necessarily counted linear which is now handled correctly.
+       [1]: http://www.i-scream.org/libstatgrab/
+
+2005-08-21, Version 1.6.0:
+       * Basic support for Solaris: System load and cpu-usage can be
+         collected under Solaris, too. Other stats will follow later.
+       * Many fixes in the autoconf-script
+       * Collection/Museum scripts have been added under contrib/museum
+       * collectd may now be started in unprivileged mode, though ping
+         statistics will not work.
+
+2005-07-17, Version 1.5.1:
+       * Diskstats-RRDs now use major/minor for naming. Some systems have
+         weird strings as disk-names..
+
+2005-07-17, Version 1.5:
+       * A new module, diskstats, has been added. It collects information
+         about the disks and partitions.
+
+2005-07-11, Version 1.4.2:
+       * The meminfo module has been changed to work with more platforms
+         and/or kernel versions.
+
+2005-07-10, Version 1.4.1: Correct traffic stats
+       * The traffic rrd-file is now created with DS-type `COUNTER' which I
+         forgot to correct when I changed that module.
+
+2005-07-09, Version 1.4: More traffic stats
+       * Traffic is now collected for all interfaces that can be found
+       * Temperature-statistics are read from lm-sensors if available
+
+2005-07-08, Version 1.3: CPU stats
+       * Collecting CPU statistics now
+
+2005-07-12, Version 1.2: Using syslog
+       * collectd is now using the syslog facility to report errors, warnings
+         and the like..
+       * The default directory is now /var/db/collectd
+
+2005-07-10, Version 1.1: Minor changes
+       * Nothing really useful to say ;)
+
+2005-07-09, Version 1.0: Initial Version
+       * The following modules are provided:
+         * Load average
+         * Ping time
+         * Traffic
+         * Memory info
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..a1e89e1
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,370 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
+Inc.
+
+   Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+   Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.  Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below.  The lack of an optional feature in a given package is not
+necessarily a bug.  More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+   The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package, generally using the just-built uninstalled binaries.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.  When installing into a prefix owned by root, it is
+     recommended that the package be configured and built as a regular
+     user, and only the `make install' phase executed with root
+     privileges.
+
+  5. Optionally, type `make installcheck' to repeat any self-tests, but
+     this time using the binaries in their final installed location.
+     This target does not install anything.  Running this target as a
+     regular user, particularly if the prior `make install' required
+     root privileges, verifies that the installation completed
+     correctly.
+
+  6. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  7. Often, you can also type `make uninstall' to remove the installed
+     files again.  In practice, not all packages have tested that
+     uninstallation works correctly, even though it is required by the
+     GNU Coding Standards.
+
+  8. Some packages, particularly those that use Automake, provide `make
+     distcheck', which can by used by developers to test that all other
+     targets like `make install' and `make uninstall' work correctly.
+     This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.  This
+is known as a "VPATH" build.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.  In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+   The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+   The first method involves providing an override variable for each
+affected directory.  For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'.  Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated.  The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+   The second method involves providing the `DESTDIR' variable.  For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names.  The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters.  On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+   Some packages offer the ability to configure how verbose the
+execution of `make' will be.  For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved.  Use GNU `make'
+instead.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+   On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
+
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..35f24cb
--- /dev/null
@@ -0,0 +1,17 @@
+ACLOCAL_AMFLAGS = -I libltdl/m4
+
+SUBDIRS = libltdl src bindings .
+
+AM_CPPFLAGS = $(LTDLINCL)
+
+EXTRA_DIST = contrib version-gen.sh
+
+install-exec-hook:
+       $(mkinstalldirs) $(DESTDIR)$(localstatedir)/run
+       $(mkinstalldirs) $(DESTDIR)$(localstatedir)/lib/$(PACKAGE_NAME)
+       $(mkinstalldirs) $(DESTDIR)$(localstatedir)/log
+
+maintainer-clean-local:
+       -rm -f -r libltdl
+       -rm -f INSTALL
+       -rm -f aclocal.m4
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..dea870a
--- /dev/null
@@ -0,0 +1,960 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = .
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+       $(top_srcdir)/configure $(am__configure_deps) \
+       $(top_srcdir)/src/libcollectdclient/collectd/lcc_features.h.in \
+       AUTHORS COPYING ChangeLog INSTALL NEWS README TODO compile \
+       libltdl/config/compile config.guess \
+       libltdl/config/config.guess config.sub \
+       libltdl/config/config.sub depcomp libltdl/config/depcomp \
+       install-sh libltdl/config/install-sh missing \
+       libltdl/config/missing ylwrap libltdl/config/ylwrap ltmain.sh \
+       libltdl/config/ltmain.sh $(top_srcdir)/libltdl/config/compile \
+       $(top_srcdir)/libltdl/config/config.guess \
+       $(top_srcdir)/libltdl/config/config.sub \
+       $(top_srcdir)/libltdl/config/install-sh \
+       $(top_srcdir)/libltdl/config/ltmain.sh \
+       $(top_srcdir)/libltdl/config/missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = src/libcollectdclient/collectd/lcc_features.h
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+       ctags-recursive dvi-recursive html-recursive info-recursive \
+       install-data-recursive install-dvi-recursive \
+       install-exec-recursive install-html-recursive \
+       install-info-recursive install-pdf-recursive \
+       install-ps-recursive install-recursive installcheck-recursive \
+       installdirs-recursive pdf-recursive ps-recursive \
+       tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+       cscope distdir dist dist-all distcheck
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  if test -d "$(distdir)"; then \
+    find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+      && rm -rf "$(distdir)" \
+      || { sleep 5 && rm -rf "$(distdir)"; }; \
+  else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
+GZIP_ENV = --best
+DIST_TARGETS = dist-bzip2 dist-gzip
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+  | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_WITH_LIBAQUAERO5_CFLAGS = @BUILD_WITH_LIBAQUAERO5_CFLAGS@
+BUILD_WITH_LIBAQUAERO5_LDFLAGS = @BUILD_WITH_LIBAQUAERO5_LDFLAGS@
+BUILD_WITH_LIBATASMART_CPPFLAGS = @BUILD_WITH_LIBATASMART_CPPFLAGS@
+BUILD_WITH_LIBATASMART_LDFLAGS = @BUILD_WITH_LIBATASMART_LDFLAGS@
+BUILD_WITH_LIBATASMART_LIBS = @BUILD_WITH_LIBATASMART_LIBS@
+BUILD_WITH_LIBCURL_CFLAGS = @BUILD_WITH_LIBCURL_CFLAGS@
+BUILD_WITH_LIBCURL_LIBS = @BUILD_WITH_LIBCURL_LIBS@
+BUILD_WITH_LIBDBI_CPPFLAGS = @BUILD_WITH_LIBDBI_CPPFLAGS@
+BUILD_WITH_LIBDBI_LDFLAGS = @BUILD_WITH_LIBDBI_LDFLAGS@
+BUILD_WITH_LIBDBI_LIBS = @BUILD_WITH_LIBDBI_LIBS@
+BUILD_WITH_LIBHAL_CFLAGS = @BUILD_WITH_LIBHAL_CFLAGS@
+BUILD_WITH_LIBHAL_LIBS = @BUILD_WITH_LIBHAL_LIBS@
+BUILD_WITH_LIBHIREDIS_CPPFLAGS = @BUILD_WITH_LIBHIREDIS_CPPFLAGS@
+BUILD_WITH_LIBHIREDIS_LDFLAGS = @BUILD_WITH_LIBHIREDIS_LDFLAGS@
+BUILD_WITH_LIBIPTC_CPPFLAGS = @BUILD_WITH_LIBIPTC_CPPFLAGS@
+BUILD_WITH_LIBIPTC_LDFLAGS = @BUILD_WITH_LIBIPTC_LDFLAGS@
+BUILD_WITH_LIBLDAP_CPPFLAGS = @BUILD_WITH_LIBLDAP_CPPFLAGS@
+BUILD_WITH_LIBLDAP_LDFLAGS = @BUILD_WITH_LIBLDAP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_CPPFLAGS = @BUILD_WITH_LIBLVM2APP_CPPFLAGS@
+BUILD_WITH_LIBLVM2APP_LDFLAGS = @BUILD_WITH_LIBLVM2APP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_LIBS = @BUILD_WITH_LIBLVM2APP_LIBS@
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS = @BUILD_WITH_LIBMEMCACHED_CPPFLAGS@
+BUILD_WITH_LIBMEMCACHED_LDFLAGS = @BUILD_WITH_LIBMEMCACHED_LDFLAGS@
+BUILD_WITH_LIBMEMCACHED_LIBS = @BUILD_WITH_LIBMEMCACHED_LIBS@
+BUILD_WITH_LIBMNL_CFLAGS = @BUILD_WITH_LIBMNL_CFLAGS@
+BUILD_WITH_LIBMNL_LIBS = @BUILD_WITH_LIBMNL_LIBS@
+BUILD_WITH_LIBMODBUS_CFLAGS = @BUILD_WITH_LIBMODBUS_CFLAGS@
+BUILD_WITH_LIBMODBUS_LIBS = @BUILD_WITH_LIBMODBUS_LIBS@
+BUILD_WITH_LIBMONGOC_CPPFLAGS = @BUILD_WITH_LIBMONGOC_CPPFLAGS@
+BUILD_WITH_LIBMONGOC_LDFLAGS = @BUILD_WITH_LIBMONGOC_LDFLAGS@
+BUILD_WITH_LIBMYSQL_CFLAGS = @BUILD_WITH_LIBMYSQL_CFLAGS@
+BUILD_WITH_LIBMYSQL_LIBS = @BUILD_WITH_LIBMYSQL_LIBS@
+BUILD_WITH_LIBOPING_CPPFLAGS = @BUILD_WITH_LIBOPING_CPPFLAGS@
+BUILD_WITH_LIBOPING_LDFLAGS = @BUILD_WITH_LIBOPING_LDFLAGS@
+BUILD_WITH_LIBOWCAPI_CPPFLAGS = @BUILD_WITH_LIBOWCAPI_CPPFLAGS@
+BUILD_WITH_LIBOWCAPI_LIBS = @BUILD_WITH_LIBOWCAPI_LIBS@
+BUILD_WITH_LIBPQ_CPPFLAGS = @BUILD_WITH_LIBPQ_CPPFLAGS@
+BUILD_WITH_LIBPQ_LDFLAGS = @BUILD_WITH_LIBPQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS = @BUILD_WITH_LIBRABBITMQ_CPPFLAGS@
+BUILD_WITH_LIBRABBITMQ_LDFLAGS = @BUILD_WITH_LIBRABBITMQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_LIBS = @BUILD_WITH_LIBRABBITMQ_LIBS@
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS = @BUILD_WITH_LIBRDKAFKA_CPPFLAGS@
+BUILD_WITH_LIBRDKAFKA_LDFLAGS = @BUILD_WITH_LIBRDKAFKA_LDFLAGS@
+BUILD_WITH_LIBRDKAFKA_LIBS = @BUILD_WITH_LIBRDKAFKA_LIBS@
+BUILD_WITH_LIBROUTEROS_CPPFLAGS = @BUILD_WITH_LIBROUTEROS_CPPFLAGS@
+BUILD_WITH_LIBROUTEROS_LDFLAGS = @BUILD_WITH_LIBROUTEROS_LDFLAGS@
+BUILD_WITH_LIBRRD_CFLAGS = @BUILD_WITH_LIBRRD_CFLAGS@
+BUILD_WITH_LIBRRD_LDFLAGS = @BUILD_WITH_LIBRRD_LDFLAGS@
+BUILD_WITH_LIBSENSORS_CFLAGS = @BUILD_WITH_LIBSENSORS_CFLAGS@
+BUILD_WITH_LIBSENSORS_LDFLAGS = @BUILD_WITH_LIBSENSORS_LDFLAGS@
+BUILD_WITH_LIBSIGROK_CFLAGS = @BUILD_WITH_LIBSIGROK_CFLAGS@
+BUILD_WITH_LIBSIGROK_LDFLAGS = @BUILD_WITH_LIBSIGROK_LDFLAGS@
+BUILD_WITH_LIBSNMP_CFLAGS = @BUILD_WITH_LIBSNMP_CFLAGS@
+BUILD_WITH_LIBSNMP_LIBS = @BUILD_WITH_LIBSNMP_LIBS@
+BUILD_WITH_LIBSTATGRAB_CFLAGS = @BUILD_WITH_LIBSTATGRAB_CFLAGS@
+BUILD_WITH_LIBSTATGRAB_LDFLAGS = @BUILD_WITH_LIBSTATGRAB_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LIBS = @BUILD_WITH_LIBTOKYOTYRANT_LIBS@
+BUILD_WITH_LIBUDEV_CFLAGS = @BUILD_WITH_LIBUDEV_CFLAGS@
+BUILD_WITH_LIBUDEV_LDFLAGS = @BUILD_WITH_LIBUDEV_LDFLAGS@
+BUILD_WITH_LIBUPSCLIENT_CFLAGS = @BUILD_WITH_LIBUPSCLIENT_CFLAGS@
+BUILD_WITH_LIBUPSCLIENT_LIBS = @BUILD_WITH_LIBUPSCLIENT_LIBS@
+BUILD_WITH_LIBVARNISH_CFLAGS = @BUILD_WITH_LIBVARNISH_CFLAGS@
+BUILD_WITH_LIBVARNISH_LIBS = @BUILD_WITH_LIBVARNISH_LIBS@
+BUILD_WITH_LIBVIRT_CFLAGS = @BUILD_WITH_LIBVIRT_CFLAGS@
+BUILD_WITH_LIBVIRT_LIBS = @BUILD_WITH_LIBVIRT_LIBS@
+BUILD_WITH_LIBXML2_CFLAGS = @BUILD_WITH_LIBXML2_CFLAGS@
+BUILD_WITH_LIBXML2_LIBS = @BUILD_WITH_LIBXML2_LIBS@
+BUILD_WITH_LIBXMMS_CFLAGS = @BUILD_WITH_LIBXMMS_CFLAGS@
+BUILD_WITH_LIBXMMS_LIBS = @BUILD_WITH_LIBXMMS_LIBS@
+BUILD_WITH_LIBYAJL_CPPFLAGS = @BUILD_WITH_LIBYAJL_CPPFLAGS@
+BUILD_WITH_LIBYAJL_LDFLAGS = @BUILD_WITH_LIBYAJL_LDFLAGS@
+BUILD_WITH_LIBYAJL_LIBS = @BUILD_WITH_LIBYAJL_LIBS@
+BUILD_WITH_MIC_CPPFLAGS = @BUILD_WITH_MIC_CPPFLAGS@
+BUILD_WITH_MIC_LDADD = @BUILD_WITH_MIC_LDADD@
+BUILD_WITH_MIC_LIBPATH = @BUILD_WITH_MIC_LIBPATH@
+BUILD_WITH_OPENIPMI_CFLAGS = @BUILD_WITH_OPENIPMI_CFLAGS@
+BUILD_WITH_OPENIPMI_LIBS = @BUILD_WITH_OPENIPMI_LIBS@
+BUILD_WITH_ORACLE_CFLAGS = @BUILD_WITH_ORACLE_CFLAGS@
+BUILD_WITH_ORACLE_LIBS = @BUILD_WITH_ORACLE_LIBS@
+BUILD_WITH_PYTHON_CPPFLAGS = @BUILD_WITH_PYTHON_CPPFLAGS@
+BUILD_WITH_PYTHON_LDFLAGS = @BUILD_WITH_PYTHON_LDFLAGS@
+BUILD_WITH_PYTHON_LIBS = @BUILD_WITH_PYTHON_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_LOG_LEVEL = @DEFAULT_LOG_LEVEL@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GANGLIA_CPPFLAGS = @GANGLIA_CPPFLAGS@
+GANGLIA_LDFLAGS = @GANGLIA_LDFLAGS@
+GANGLIA_LIBS = @GANGLIA_LIBS@
+GCRYPT_CPPFLAGS = @GCRYPT_CPPFLAGS@
+GCRYPT_LDFLAGS = @GCRYPT_LDFLAGS@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVA_CFLAGS = @JAVA_CFLAGS@
+JAVA_CPPFLAGS = @JAVA_CPPFLAGS@
+JAVA_LDFLAGS = @JAVA_LDFLAGS@
+JAVA_LIBS = @JAVA_LIBS@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_DIR = @KERNEL_DIR@
+LCC_VERSION_EXTRA = @LCC_VERSION_EXTRA@
+LCC_VERSION_MAJOR = @LCC_VERSION_MAJOR@
+LCC_VERSION_MINOR = @LCC_VERSION_MINOR@
+LCC_VERSION_PATCH = @LCC_VERSION_PATCH@
+LCC_VERSION_STRING = @LCC_VERSION_STRING@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBNETAPP_CPPFLAGS = @LIBNETAPP_CPPFLAGS@
+LIBNETAPP_LDFLAGS = @LIBNETAPP_LDFLAGS@
+LIBNETAPP_LIBS = @LIBNETAPP_LIBS@
+LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
+LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOAD_PLUGIN_CSV = @LOAD_PLUGIN_CSV@
+LOAD_PLUGIN_LOGFILE = @LOAD_PLUGIN_LOGFILE@
+LOAD_PLUGIN_LOG_LOGSTASH = @LOAD_PLUGIN_LOG_LOGSTASH@
+LOAD_PLUGIN_NETWORK = @LOAD_PLUGIN_NETWORK@
+LOAD_PLUGIN_RRDTOOL = @LOAD_PLUGIN_RRDTOOL@
+LOAD_PLUGIN_SYSLOG = @LOAD_PLUGIN_SYSLOG@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_BINDINGS = @PERL_BINDINGS@
+PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_LIBS = @PERL_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_protoc_c = @have_protoc_c@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I libltdl/m4
+SUBDIRS = libltdl src bindings .
+AM_CPPFLAGS = $(LTDLINCL)
+EXTRA_DIST = contrib version-gen.sh
+all: all-recursive
+
+.SUFFIXES:
+am--refresh: Makefile
+       @:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+             $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+src/libcollectdclient/collectd/lcc_features.h: $(top_builddir)/config.status $(top_srcdir)/src/libcollectdclient/collectd/lcc_features.h.in
+       cd $(top_builddir) && $(SHELL) ./config.status $@
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool config.lt
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+       @fail=; \
+       if $(am__make_keepgoing); then \
+         failcom='fail=yes'; \
+       else \
+         failcom='exit 1'; \
+       fi; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+       test ! -s cscope.files \
+         || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+       -rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+       -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       test -d "$(distdir)" || mkdir "$(distdir)"
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           $(am__make_dryrun) \
+             || test -d "$(distdir)/$$subdir" \
+             || $(MKDIR_P) "$(distdir)/$$subdir" \
+             || exit 1; \
+           dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+           $(am__relativize); \
+           new_distdir=$$reldir; \
+           dir1=$$subdir; dir2="$(top_distdir)"; \
+           $(am__relativize); \
+           new_top_distdir=$$reldir; \
+           echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+           echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+           ($(am__cd) $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$new_top_distdir" \
+               distdir="$$new_distdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               am__skip_mode_fix=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+       -test -n "$(am__skip_mode_fix)" \
+       || find "$(distdir)" -type d ! -perm -755 \
+               -exec chmod u+rwx,go+rx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__post_remove_distdir)
+dist-bzip2: distdir
+       tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+       $(am__post_remove_distdir)
+
+dist-lzip: distdir
+       tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+       $(am__post_remove_distdir)
+
+dist-xz: distdir
+       tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+       $(am__post_remove_distdir)
+
+dist-tarZ: distdir
+       @echo WARNING: "Support for shar distribution archives is" \
+                      "deprecated." >&2
+       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       $(am__post_remove_distdir)
+
+dist-shar: distdir
+       @echo WARNING: "Support for distribution archives compressed with" \
+                      "legacy program 'compress' is deprecated." >&2
+       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__post_remove_distdir)
+
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__post_remove_distdir)
+
+dist dist-all:
+       $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+       $(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+       *.tar.bz2*) \
+         bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+       *.tar.lz*) \
+         lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+       *.tar.xz*) \
+         xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir)
+       chmod u+w $(distdir)
+       mkdir $(distdir)/_build $(distdir)/_inst
+       chmod a-w $(distdir)
+       test -d $(distdir)/_build || exit 0; \
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && am__cwd=`pwd` \
+         && $(am__cd) $(distdir)/_build \
+         && ../configure \
+           $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+           --srcdir=.. --prefix="$$dc_install_base" \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+         && cd "$$am__cwd" \
+         || exit 1
+       $(am__post_remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+       @test -n '$(distuninstallcheck_dir)' || { \
+         echo 'ERROR: trying to run $@ with an empty' \
+              '$$(distuninstallcheck_dir)' >&2; \
+         exit 1; \
+       }; \
+       $(am__cd) '$(distuninstallcheck_dir)' || { \
+         echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+         exit 1; \
+       }; \
+       test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+       distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+       maintainer-clean-local
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) install-am install-exec-am \
+       install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+       am--refresh check check-am clean clean-cscope clean-generic \
+       clean-libtool cscope cscopelist-am ctags ctags-am dist \
+       dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \
+       dist-xz dist-zip distcheck distclean distclean-generic \
+       distclean-libtool distclean-tags distcleancheck distdir \
+       distuninstallcheck dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-exec-hook \
+       install-html install-html-am install-info install-info-am \
+       install-man install-pdf install-pdf-am install-ps \
+       install-ps-am install-strip installcheck installcheck-am \
+       installdirs installdirs-am maintainer-clean \
+       maintainer-clean-generic maintainer-clean-local mostlyclean \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags tags-am uninstall uninstall-am
+
+
+install-exec-hook:
+       $(mkinstalldirs) $(DESTDIR)$(localstatedir)/run
+       $(mkinstalldirs) $(DESTDIR)$(localstatedir)/lib/$(PACKAGE_NAME)
+       $(mkinstalldirs) $(DESTDIR)$(localstatedir)/log
+
+maintainer-clean-local:
+       -rm -f -r libltdl
+       -rm -f INSTALL
+       -rm -f aclocal.m4
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..9604fda
--- /dev/null
+++ b/README
@@ -0,0 +1,974 @@
+ collectd - System information collection daemon
+=================================================
+http://collectd.org/
+
+About
+-----
+
+  collectd is a small daemon which collects system information periodically
+  and provides mechanisms to store and monitor the values in a variety of
+  ways.
+
+
+Features
+--------
+
+  * collectd is able to collect the following data:
+
+    - apache
+      Apache server utilization: Number of bytes transferred, number of
+      requests handled and detailed scoreboard statistics
+
+    - apcups
+      APC UPS Daemon: UPS charge, load, input/output/battery voltage, etc.
+
+    - apple_sensors
+      Sensors in Macs running Mac OS X / Darwin: Temperature, fan speed and
+      voltage sensors.
+
+    - aquaero
+      Various sensors in the Aquaero 5 water cooling board made by Aquacomputer.
+
+    - ascent
+      Statistics about Ascent, a free server for the game `World of Warcraft'.
+
+    - barometer
+      Reads absolute barometric pressure, air pressure reduced to sea level and
+      temperature.  Supported sensors are MPL115A2 and MPL3115 from Freescale
+      and BMP085 from Bosch.
+
+    - battery
+      Batterycharge, -current and voltage of ACPI and PMU based laptop
+      batteries.
+
+    - bind
+      Name server and resolver statistics from the `statistics-channel'
+      interface of BIND 9.5, 9,6 and later.
+
+    - ceph
+      Statistics from the Ceph distributed storage system.
+
+    - cgroups
+      CPU accounting information for process groups under Linux.
+
+    - conntrack
+      Number of nf_conntrack entries.
+
+    - contextswitch
+      Number of context switches done by the operating system.
+
+    - cpu
+      CPU utilization: Time spent in the system, user, nice, idle, and related
+      states.
+
+    - cpufreq
+      CPU frequency (For laptops with speed step or a similar technology)
+
+    - curl
+      Parse statistics from websites using regular expressions.
+
+    - curl_json
+      Retrieves JSON data via cURL and parses it according to user
+      configuration.
+
+    - curl_xml
+      Retrieves XML data via cURL and parses it according to user
+      configuration.
+
+    - dbi
+      Executes SQL statements on various databases and interprets the returned
+      data.
+
+    - df
+      Mountpoint usage (Basically the values `df(1)' delivers)
+
+    - disk
+      Disk utilization: Sectors read/written, number of read/write actions,
+      average time an IO-operation took to complete.
+
+    - dns
+      DNS traffic: Query types, response codes, opcodes and traffic/octets
+      transferred.
+
+    - drbd
+      Collect individual drbd resource statistics.
+
+    - email
+      Email statistics: Count, traffic, spam scores and checks.
+      See collectd-email(5).
+
+    - entropy
+      Amount of entropy available to the system.
+
+    - ethstat
+      Network interface card statistics.
+
+    - exec
+      Values gathered by a custom program or script.
+      See collectd-exec(5).
+
+    - fhcount
+      File handles statistics.
+
+    - filecount
+      Count the number of files in directories.
+
+    - fscache
+      Linux file-system based caching framework statistics.
+
+    - gmond
+      Receive multicast traffic from Ganglia instances.
+
+    - hddtemp
+      Hard disk temperatures using hddtempd.
+
+    - interface
+      Interface traffic: Number of octets, packets and errors for each
+      interface.
+
+    - ipc
+      IPC counters: semaphores used, number of allocated segments in shared
+      memory and more.
+
+    - ipmi
+      IPMI (Intelligent Platform Management Interface) sensors information.
+
+    - iptables
+      Iptables' counters: Number of bytes that were matched by a certain
+      iptables rule.
+
+    - ipvs
+      IPVS connection statistics (number of connections, octets and packets
+      for each service and destination).
+      See http://www.linuxvirtualserver.org/software/index.html.
+
+    - irq
+      IRQ counters: Frequency in which certain interrupts occur.
+
+    - java
+      Integrates a `Java Virtual Machine' (JVM) to execute plugins in Java
+      bytecode. See “Configuring with libjvm” below.
+
+    - load
+      System load average over the last 1, 5 and 15 minutes.
+
+    - lpar
+      Detailed CPU statistics of the “Logical Partitions” virtualization
+      technique built into IBM's POWER processors.
+
+    - 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.
+
+    - mbmon
+      Motherboard sensors: temperature, fan speed and voltage information,
+      using mbmon(1).
+
+    - md
+      Linux software-RAID device information (number of active, failed, spare
+      and missing disks).
+
+    - memcachec
+      Query and parse data from a memcache daemon (memcached).
+
+    - memcached
+      Statistics of the memcached distributed caching system.
+      <http://www.danga.com/memcached/>
+
+    - memory
+      Memory utilization: Memory occupied by running processes, page cache,
+      buffer cache and free.
+
+    - mic
+      Collects CPU usage, memory usage, temperatures and power consumption from
+      Intel Many Integrated Core (MIC) CPUs.
+
+    - modbus
+      Reads values from Modbus/TCP enabled devices. Supports reading values
+      from multiple "slaves" so gateway devices can be used.
+
+    - multimeter
+      Information provided by serial multimeters, such as the `Metex
+      M-4650CR'.
+
+    - mysql
+      MySQL server statistics: Commands issued, handlers triggered, thread
+      usage, query cache utilization and traffic/octets sent and received.
+
+    - netapp
+      Plugin to query performance values from a NetApp storage system using the
+      “Manage ONTAP” SDK provided by NetApp.
+
+    - netlink
+      Very detailed Linux network interface and routing statistics. You can get
+      (detailed) information on interfaces, qdiscs, classes, and, if you can
+      make use of it, filters.
+
+    - network
+      Receive values that were collected by other hosts. Large setups will
+      want to collect the data on one dedicated machine, and this is the
+      plugin of choice for that.
+
+    - nfs
+      NFS Procedures: Which NFS command were called how often. Only NFSv2 and
+      NFSv3 right now.
+
+    - nginx
+      Collects statistics from `nginx' (speak: engine X), a HTTP and mail
+      server/proxy.
+
+    - ntpd
+      NTP daemon statistics: Local clock drift, offset to peers, etc.
+
+    - numa
+      Information about Non-Uniform Memory Access (NUMA).
+
+    - nut
+      Network UPS tools: UPS current, voltage, power, charge, utilisation,
+      temperature, etc. See upsd(8).
+
+    - olsrd
+      Queries routing information from the “Optimized Link State Routing”
+      daemon.
+
+    - onewire (EXPERIMENTAL!)
+      Read onewire sensors using the owcapu library of the owfs project.
+      Please read in collectd.conf(5) why this plugin is experimental.
+
+    - openldap
+      Read monitoring information from OpenLDAP's cn=Monitor subtree.
+
+    - openvpn
+      RX and TX of each client in openvpn-status.log (status-version 2).
+      <http://openvpn.net/index.php/documentation/howto.html>
+
+    - oracle
+      Query data from an Oracle database.
+
+    - perl
+      The perl plugin implements a Perl-interpreter into collectd. You can
+      write your own plugins in Perl and return arbitrary values using this
+      API. See collectd-perl(5).
+
+    - pf
+      Query statistics from BSD's packet filter "pf".
+
+    - pinba
+      Receive and dispatch timing values from Pinba, a profiling extension for
+      PHP.
+
+    - ping
+      Network latency: Time to reach the default gateway or another given
+      host.
+
+    - postgresql
+      PostgreSQL database statistics: active server connections, transaction
+      numbers, block IO, table row manipulations.
+
+    - powerdns
+      PowerDNS name server statistics.
+
+    - processes
+      Process counts: Number of running, sleeping, zombie, ... processes.
+
+    - protocols
+      Counts various aspects of network protocols such as IP, TCP, UDP, etc.
+
+    - python
+      The python plugin implements a Python interpreter into collectd. This
+      makes it possible to write plugins in Python which are executed by
+      collectd without the need to start a heavy interpreter every interval.
+      See collectd-python(5) for details.
+
+    - redis
+      The redis plugin gathers information from a Redis server, including:
+      uptime, used memory, total connections etc.
+
+    - routeros
+      Query interface and wireless registration statistics from RouterOS.
+
+    - rrdcached
+      RRDtool caching daemon (RRDcacheD) statistics.
+
+    - sensors
+      System sensors, accessed using lm_sensors: Voltages, temperatures and
+      fan rotation speeds.
+
+    - serial
+      RX and TX of serial interfaces. Linux only; needs root privileges.
+
+    - sigrok
+      Uses libsigrok as a backend, allowing any sigrok-supported device
+      to have its measurements fed to collectd. This includes multimeters,
+      sound level meters, thermometers, and much more.
+
+    - smart
+      Collect SMART statistics, notably load cycle count, temperature
+      and bad sectors.
+
+    - snmp
+      Read values from SNMP (Simple Network Management Protocol) enabled
+      network devices such as switches, routers, thermometers, rack monitoring
+      servers, etc. See collectd-snmp(5).
+
+    - statsd
+      Acts as a StatsD server, reading values sent over the network from StatsD
+      clients and calculating rates and other aggregates out of these values.
+
+    - swap
+      Pages swapped out onto hard disk or whatever is called `swap' by the OS..
+
+    - table
+      Parse table-like structured files.
+
+    - tail
+      Follows (tails) log files, parses them by lines and submits matched
+      values.
+
+    - tail_csv
+      Follows (tails) files in CSV format, parses each line and submits
+      extracted values.
+
+    - tape
+      Bytes and operations read and written on tape devices. Solaris only.
+
+    - tcpconns
+      Number of TCP connections to specific local and remote ports.
+
+    - teamspeak2
+      TeamSpeak2 server statistics.
+
+    - ted
+      Plugin to read values from `The Energy Detective' (TED).
+
+    - thermal
+      Linux ACPI thermal zone information.
+
+    - tokyotyrant
+      Reads the number of records and file size from a running Tokyo Tyrant
+      server.
+
+    - turbostat
+      Reads CPU frequency and C-state residency on modern Intel
+      turbo-capable processors.
+
+    - uptime
+      System uptime statistics.
+
+    - users
+      Users currently logged in.
+
+    - varnish
+      Various statistics from Varnish, an HTTP accelerator.
+
+    - virt
+      CPU, memory, disk and network I/O statistics from virtual machines.
+
+    - vmem
+      Virtual memory statistics, e. g. the number of page-ins/-outs or the
+      number of pagefaults.
+
+    - vserver
+      System resources used by Linux VServers.
+      See <http://linux-vserver.org/>.
+
+    - wireless
+      Link quality of wireless cards. Linux only.
+
+    - xmms
+      Bitrate and frequency of music played with XMMS.
+
+    - zfs_arc
+      Statistics for ZFS' “Adaptive Replacement Cache” (ARC).
+
+    - zookeeper
+      Read data from Zookeeper's MNTR command.
+
+  * Output can be written or sent to various destinations by the following
+    plugins:
+
+    - amqp
+      Sends JSON-encoded data to an Advanced Message Queuing Protocol (AMQP)
+      server, such as RabbitMQ.
+
+    - csv
+      Write to comma separated values (CSV) files. This needs lots of
+      diskspace but is extremely portable and can be analysed with almost
+      every program that can analyse anything. Even Microsoft's Excel..
+
+    - network
+      Send the data to a remote host to save the data somehow. This is useful
+      for large setups where the data should be saved by a dedicated machine.
+
+    - perl
+      Of course the values are propagated to plugins written in Perl, too, so
+      you can easily do weird stuff with the plugins we didn't dare think of
+      ;) See collectd-perl(5).
+
+    - python
+      It's possible to implement write plugins in Python using the python
+      plugin. See collectd-python(5) for details.
+
+    - rrdcached
+      Output to round-robin-database (RRD) files using the RRDtool caching
+      daemon (RRDcacheD) - see rrdcached(1). That daemon provides a general
+      implementation of the caching done by the `rrdtool' plugin.
+
+    - rrdtool
+      Output to round-robin-database (RRD) files using librrd. See rrdtool(1).
+      This is likely the most popular destination for such values. Since
+      updates to RRD-files are somewhat expensive this plugin can cache
+      updates to the files and write a bunch of updates at once, which lessens
+      system load a lot.
+
+    - unixsock
+      One can query the values from the unixsock plugin whenever they're
+      needed. Please read collectd-unixsock(5) for a description on how that's
+      done.
+
+    - write_graphite
+      Sends data to Carbon, the storage layer of Graphite using TCP or UDP. It
+      can be configured to avoid logging send errors (especially useful when
+      using UDP).
+
+    - write_http
+      Sends the values collected by collectd to a web-server using HTTP POST
+      requests. The transmitted data is either in a form understood by the
+      Exec plugin or formatted in JSON.
+
+    - write_kafka
+      Sends data to Apache Kafka, a distributed queue.
+
+    - write_log
+      Writes data to the log
+
+    - write_mongodb
+      Sends data to MongoDB, a NoSQL database.
+
+    - write_redis
+      Sends the values to a Redis key-value database server.
+
+    - write_riemann
+      Sends data to Riemann, a stream processing and monitoring system.
+
+    - write_sensu
+      Sends data to Sensu, a stream processing and monitoring system, via the
+      Sensu client local TCP socket.
+
+    - write_tsdb
+      Sends data OpenTSDB, a scalable no master, no shared state time series
+      database.
+
+  * Logging is, as everything in collectd, provided by plugins. The following
+    plugins keep up informed about what's going on:
+
+    - logfile
+      Writes log messages to a file or STDOUT/STDERR.
+
+    - perl
+      Log messages are propagated to plugins written in Perl as well.
+      See collectd-perl(5).
+
+    - python
+      It's possible to implement log plugins in Python using the python plugin.
+      See collectd-python(5) for details.
+
+    - syslog
+      Logs to the standard UNIX logging mechanism, syslog.
+
+    - log_logstash
+      Writes log messages formatted as logstash JSON events.
+
+  * Notifications can be handled by the following plugins:
+
+    - notify_desktop
+      Send a desktop notification to a notification daemon, as defined in
+      the Desktop Notification Specification. To actually display the
+      notifications, notification-daemon is required.
+      See http://www.galago-project.org/specs/notification/.
+
+    - notify_email
+      Send an E-mail with the notification message to the configured
+      recipients.
+
+    - exec
+      Execute a program or script to handle the notification.
+      See collectd-exec(5).
+
+    - logfile
+      Writes the notification message to a file or STDOUT/STDERR.
+
+    - network
+      Send the notification to a remote host to handle it somehow.
+
+    - perl
+      Notifications are propagated to plugins written in Perl as well.
+      See collectd-perl(5).
+
+    - python
+      It's possible to implement notification plugins in Python using the
+      python plugin. See collectd-python(5) for details.
+
+  * Value processing can be controlled using the "filter chain" infrastructure
+    and "matches" and "targets". The following plugins are available:
+
+    - match_empty_counter
+      Match counter values which are currently zero.
+
+    - match_hashed
+      Match values using a hash function of the hostname.
+
+    - match_regex
+      Match values by their identifier based on regular expressions.
+
+    - match_timediff
+      Match values with an invalid timestamp.
+
+    - match_value
+      Select values by their data sources' values.
+
+    - target_notification
+      Create and dispatch a notification.
+
+    - target_replace
+      Replace parts of an identifier using regular expressions.
+
+    - target_scale
+      Scale (multiply) values by an arbitrary value.
+
+    - target_set
+      Set (overwrite) entire parts of an identifier.
+
+  * Miscellaneous plugins:
+
+    - aggregation
+      Selects multiple value lists based on patterns or regular expressions
+      and creates new aggregated values lists from those.
+
+    - threshold
+      Checks values against configured thresholds and creates notifications if
+      values are out of bounds. See collectd-threshold(5) for details.
+
+    - uuid
+      Sets the hostname to a unique identifier. This is meant for setups
+      where each client may migrate to another physical host, possibly going
+      through one or more name changes in the process.
+
+  * Performance: Since collectd is running as a daemon it doesn't spend much
+    time starting up again and again. With the exception of the exec plugin no
+    processes are forked. Caching in output plugins, such as the rrdtool and
+    network plugins, makes sure your resources are used efficiently. Also,
+    since collectd is programmed multithreaded it benefits from hyper-threading
+    and multicore processors and makes sure that the daemon isn't idle if only
+    one plugin waits for an IO-operation to complete.
+
+  * Once set up, hardly any maintenance is necessary. Setup is kept as easy
+    as possible and the default values should be okay for most users.
+
+
+Operation
+---------
+
+  * collectd's configuration file can be found at `sysconfdir'/collectd.conf.
+    Run `collectd -h' for a list of built-in defaults. See `collectd.conf(5)'
+    for a list of options and a syntax description.
+
+  * When the `csv' or `rrdtool' plugins are loaded they'll write the values to
+    files. The usual place for these files is beneath `/var/lib/collectd'.
+
+  * When using some of the plugins, collectd needs to run as user root, since
+    only root can do certain things, such as craft ICMP packages needed to ping
+    other hosts. collectd should NOT be installed setuid root since it can be
+    used to overwrite valuable files!
+
+  * Sample scripts to generate graphs reside in `contrib/' in the source
+    package or somewhere near `/usr/share/doc/collectd' in most distributions.
+    Please be aware that those script are meant as a starting point for your
+    own experiments.. Some of them require the `RRDs' Perl module.
+    (`librrds-perl' on Debian) If you have written a more sophisticated
+    solution please share it with us.
+
+  * The RRAs of the automatically created RRD files depend on the `step'
+    and `heartbeat' settings given. If change these settings you may need to
+    re-create the files, losing all data. Please be aware of that when changing
+    the values and read the rrdtool(1) manpage thoroughly.
+
+
+collectd and chkrootkit
+-----------------------
+
+  If you are using the `dns' plugin chkrootkit(1) will report collectd as a
+  packet sniffer ("<iface>: PACKET SNIFFER(/usr/sbin/collectd[<pid>])"). The
+  plugin captures all UDP packets on port 53 to analyze the DNS traffic. In
+  this case, collectd is a legitimate sniffer and the report should be
+  considered to be a false positive. However, you might want to check that
+  this really is collectd and not some other, illegitimate sniffer.
+
+
+Prerequisites
+-------------
+
+  To compile collectd from source you will need:
+
+  * Usual suspects: C compiler, linker, preprocessor, make, ...
+
+  * A POSIX-threads (pthread) implementation.
+    Since gathering some statistics is slow (network connections, slow devices,
+    etc) collectd is parallelized. The POSIX threads interface is being
+    used and should be found in various implementations for hopefully all
+    platforms.
+
+  * aerotools-ng (optional)
+    Used by the `aquaero' plugin. Currently, the `libaquaero5' library, which
+    is used by the `aerotools-ng' toolkit, is not compiled as a shared object
+    nor does it feature an installation routine. Therefore, you need to point
+    collectd's configure script at the source directory of the `aerotools-ng'
+    project.
+    <https://github.com/lynix/aerotools-ng>
+
+  * CoreFoundation.framework and IOKit.framework (optional)
+    For compiling on Darwin in general and the `apple_sensors' plugin in
+    particular.
+    <http://developer.apple.com/corefoundation/>
+
+  * libatasmart (optional)
+    Used by the `smart' plugin.
+    <http://git.0pointer.de/?p=libatasmart.git>
+
+  * libcap (optional)
+    The `turbostat' plugin can optionally build Linux Capabilities support,
+    which avoids full privileges requirement (aka. running as root) to read
+    values.
+    <http://sites.google.com/site/fullycapable/>
+
+  * libclntsh (optional)
+    Used by the `oracle' plugin.
+
+  * libhiredis (optional)
+    Used by the redis plugin. Please note that you require a 0.10.0 version
+    or higher. <https://github.com/redis/hiredis>
+
+  * libcurl (optional)
+    If you want to use the `apache', `ascent', `bind', `curl', `curl_json',
+    `curl_xml', `nginx', or `write_http' plugin.
+    <http://curl.haxx.se/>
+
+  * libdbi (optional)
+    Used by the `dbi' plugin to connect to various databases.
+    <http://libdbi.sourceforge.net/>
+
+  * libesmtp (optional)
+    For the `notify_email' plugin.
+    <http://www.stafford.uklinux.net/libesmtp/>
+
+  * libganglia (optional)
+    Used by the `gmond' plugin to process data received from Ganglia.
+    <http://ganglia.info/>
+
+  * libgcrypt (optional)
+    Used by the `network' plugin for encryption and authentication.
+    <http://www.gnupg.org/>
+
+  * libhal (optional)
+    If present, the `uuid' plugin will check for UUID from HAL.
+    <http://hal.freedesktop.org/>
+
+  * libi2c-dev (optional)
+    Used for the plugin `barometer', provides just the i2c-dev.h header file
+    for user space i2c development.
+
+  * libiptc (optional)
+    For querying iptables counters.
+    <http://netfilter.org/>
+
+  * libjvm (optional)
+    Library that encapsulates the `Java Virtual Machine' (JVM). This library is
+    used by the `java' plugin to execute Java bytecode. See “Configuring with
+    libjvm” below.
+    <http://openjdk.java.net/> (and others)
+
+  * libldap (optional)
+    Used by the `openldap' plugin.
+    <http://www.openldap.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>
+
+  * libmnl (optional)
+    Used by the `netlink' plugin.
+    <http://www.netfilter.org/projects/libmnl/>
+
+  * libmodbus (optional)
+    Used by the `modbus' plugin to communicate with Modbus/TCP devices. The
+    `modbus' plugin works with version 2.0.3 of the library – due to frequent
+    API changes other versions may or may not compile cleanly.
+    <http://www.libmodbus.org/>
+
+  * libmysqlclient (optional)
+    Unsurprisingly used by the `mysql' plugin.
+    <http://dev.mysql.com/>
+
+  * libnetapp (optional)
+    Required for the `netapp' plugin.
+    This library is part of the “Manage ONTAP SDK” published by NetApp.
+
+  * libnetsnmp (optional)
+    For the `snmp' plugin.
+    <http://www.net-snmp.org/>
+
+  * libnotify (optional)
+    For the `notify_desktop' plugin.
+    <http://www.galago-project.org/>
+
+  * libopenipmi (optional)
+    Used by the `ipmi' plugin to prove IPMI devices.
+    <http://openipmi.sourceforge.net/>
+
+  * liboping (optional)
+    Used by the `ping' plugin to send and receive ICMP packets.
+    <http://octo.it/liboping/>
+
+  * libowcapi (optional)
+    Used by the `onewire' plugin to read values from onewire sensors (or the
+    owserver(1) daemon).
+    <http://www.owfs.org/>
+
+  * libpcap (optional)
+    Used to capture packets by the `dns' plugin.
+    <http://www.tcpdump.org/>
+
+  * libperfstat (optional)
+    Used by various plugins to gather statistics under AIX.
+
+  * libperl (optional)
+    Obviously used by the `perl' plugin. The library has to be compiled with
+    ithread support (introduced in Perl 5.6.0).
+    <http://www.perl.org/>
+
+  * libpq (optional)
+    The PostgreSQL C client library used by the `postgresql' plugin.
+    <http://www.postgresql.org/>
+
+  * libprotobuf-c, protoc-c (optional)
+    Used by the `pinba' plugin to generate a parser for the network packets
+    sent by the Pinba PHP extension, and by the `write_riemann' plugin to
+    generate events to be sent to a Riemann server.
+    <http://code.google.com/p/protobuf-c/>
+
+  * libpython (optional)
+    Used by the `python' plugin. Currently, Python 2.3 and later and Python 3
+    are supported.
+    <http://www.python.org/>
+
+  * librabbitmq (optional; also called “rabbitmq-c”)
+    Used by the `amqp' plugin for AMQP connections, for example to RabbitMQ.
+    <http://hg.rabbitmq.com/rabbitmq-c/>
+
+  * librdkafka (optional; also called “rdkafka”)
+    Used by the `write_kafka' plugin for producing messages and sending them
+    to a Kafka broker.
+    <https://github.com/edenhill/librdkafka>
+
+  * librouteros (optional)
+    Used by the `routeros' plugin to connect to a device running `RouterOS'.
+    <http://octo.it/librouteros/>
+
+  * librrd (optional)
+    Used by the `rrdtool' and `rrdcached' plugins. The latter requires RRDtool
+    client support which was added after version 1.3 of RRDtool. Versions 1.0,
+    1.2 and 1.3 are known to work with the `rrdtool' plugin.
+    <http://oss.oetiker.ch/rrdtool/>
+
+  * librt, libsocket, libkstat, libdevinfo (optional)
+    Various standard Solaris libraries which provide system functions.
+    <http://developers.sun.com/solaris/>
+
+  * libsensors (optional)
+    To read from `lm_sensors', see the `sensors' plugin.
+    <http://www.lm-sensors.org/>
+
+  * libsigrok (optional)
+    Used by the `sigrok' plugin. In addition, libsigrok depends on glib,
+    libzip, and optionally (depending on which drivers are enabled) on
+    libusb, libftdi and libudev.
+
+  * libstatgrab (optional)
+    Used by various plugins to collect statistics on systems other than Linux
+    and/or Solaris.
+    <http://www.i-scream.org/libstatgrab/>
+
+  * libtokyotyrant (optional)
+    Used by the `tokyotyrant' plugin.
+    <http://1978th.net/tokyotyrant/>
+
+  * libupsclient/nut (optional)
+    For the `nut' plugin which queries nut's `upsd'.
+    <http://networkupstools.org/>
+
+  * libvirt (optional)
+    Collect statistics from virtual machines.
+    <http://libvirt.org/>
+
+  * libxml2 (optional)
+    Parse XML data. This is needed for the `ascent', `bind', `curl_xml' and
+    `virt' plugins.
+    <http://xmlsoft.org/>
+
+  * libxmms (optional)
+    <http://www.xmms.org/>
+
+  * libyajl (optional)
+    Parse JSON data. This is needed for the `ceph', `curl_json' and
+    `log_logstash' plugins.
+    <http://github.com/lloyd/yajl>
+
+  * libvarnish (optional)
+     Fetches statistics from a Varnish instance. This is needed for the
+     `varnish' plugin.
+     <http://varnish-cache.org>
+
+Configuring / Compiling / Installing
+------------------------------------
+
+  To configure, build and install collectd with the default settings, run
+  `./configure && make && make install'.  For detailed, generic instructions
+  see INSTALL. For a complete list of configure options and their description,
+  run `./configure --help'.
+
+  By default, the configure script will check for all build dependencies and
+  disable all plugins whose requirements cannot be fulfilled (any other plugin
+  will be enabled). To enable a plugin, install missing dependencies (see
+  section `Prerequisites' above) and rerun `configure'. If you specify the
+  `--enable-<plugin>' configure option, the script will fail if the depen-
+  dencies for the specified plugin are not met. In that case you can force the
+  plugin to be built using the `--enable-<plugin>=force' configure option.
+  This will most likely fail though unless you're working in a very unusual
+  setup and you really know what you're doing. If you specify the
+  `--disable-<plugin>' configure option, the plugin will not be built. If you
+  specify the `--enable-all-plugins' or `--disable-all-plugins' configure
+  options, all plugins will be enabled or disabled respectively by default.
+  Explicitly enabling or disabling a plugin overwrites the default for the
+  specified plugin. These options are meant for package maintainers and should
+  not be used in everyday situations.
+
+  By default, collectd will be installed into `/opt/collectd'. You can adjust
+  this setting by specifying the `--prefix' configure option - see INSTALL for
+  details. If you pass DESTDIR=<path> to `make install', <path> will be
+  prefixed to all installation directories. This might be useful when creating
+  packages for collectd.
+
+Configuring with libjvm
+-----------------------
+
+  To determine the location of the required files of a Java installation is not
+  an easy task, because the locations vary with your kernel (Linux, SunOS, …)
+  and with your architecture (x86, SPARC, …) and there is no ‘java-config’
+  script we could use. Configuration of the JVM library is therefore a bit
+  tricky.
+
+  The easiest way to use the `--with-java=$JAVA_HOME' option, where
+  `$JAVA_HOME' is usually something like:
+    /usr/lib/jvm/java-1.5.0-sun-1.5.0.14
+
+  The configure script will then use find(1) to look for the following files:
+
+    - jni.h
+    - jni_md.h
+    - libjvm.so
+
+  If found, appropriate CPP-flags and LD-flags are set and the following
+  library checks succeed.
+
+  If this doesn't work for you, you have the possibility to specify CPP-flags,
+  C-flags and LD-flags for the ‘Java’ plugin by hand, using the following three
+  (environment) variables:
+
+    - JAVA_CPPFLAGS
+    - JAVA_CFLAGS
+    - JAVA_LDFLAGS
+
+  For example (shortened for demonstration purposes):
+
+    ./configure JAVA_CPPFLAGS="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
+
+  Adding "-ljvm" to the JAVA_LDFLAGS is done automatically, you don't have to
+  do that.
+
+Generating the configure script
+-------------------------------
+
+Collectd ships with a `build.sh' script to generate the `configure'
+script shipped with releases.
+
+To generate the `configure` script, you'll need the following dependencies:
+
+- autoconf
+- automake
+- flex
+- bison
+- libtool
+- libtool-ltdl
+
+The `build.sh' script takes no arguments.
+
+Crosscompiling
+--------------
+
+  To compile correctly collectd needs to be able to initialize static
+  variables to NAN (Not A Number). Some C libraries, especially the GNU
+  libc, have a problem with that.
+
+  Luckily, with GCC it's possible to work around that problem: One can define
+  NAN as being (0.0 / 0.0) and `isnan' as `f != f'. However, to test this
+  ``implementation'' the configure script needs to compile and run a short
+  test program. Obviously running a test program when doing a cross-
+  compilation is, well, challenging.
+
+  If you run into this problem, you can use the `--with-nan-emulation'
+  configure option to force the use of this implementation. We can't promise
+  that the compiled binary actually behaves as it should, but since NANs
+  are likely never passed to the libm you have a good chance to be lucky.
+
+  Likewise, collectd needs to know the layout of doubles in memory, in order
+  to craft uniform network packets over different architectures. For this, it
+  needs to know how to convert doubles into the memory layout used by x86. The
+  configure script tries to figure this out by compiling and running a few
+  small test programs. This is of course not possible when cross-compiling.
+  You can use the `--with-fp-layout' option to tell the configure script which
+  conversion method to assume. Valid arguments are:
+
+    * `nothing'    (12345678 -> 12345678)
+    * `endianflip' (12345678 -> 87654321)
+    * `intswap'    (12345678 -> 56781234)
+
+
+Contact
+-------
+
+  For questions, bug reports, development information and basically all other
+  concerns please send an email to collectd's mailing list at
+  <list at collectd.org>.
+
+  For live discussion and more personal contact visit us in IRC, we're in
+  channel #collectd on freenode.
+
+
+Author
+------
+
+  Florian octo Forster <octo at collectd.org>,
+  Sebastian tokkee Harl <sh at tokkee.org>,
+  and many contributors (see `AUTHORS').
+
+  Please send bug reports and patches to the mailing list, see `Contact'
+  above.
+
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..009eb7f
--- /dev/null
+++ b/TODO
@@ -0,0 +1,21 @@
+* Finalize the onewire plugin.
+* Custom notification messages?
+* Implement moving-average calculation for the threshold stuff.
+
+src/battery.c: commend not working code.
+
+Wishlist:
+* Port nfs module to solaris
+* Port tape module to Linux
+* Port the apple_sensors plugin to Linux/PPC.
+* Maybe look into porting the serial module
+* Build Darwin package
+* Maybe let the network plugin configure whether or not notifications should be
+  sent/received.
+* Maybe find a way for processes connected to the unixsock plugin to receive
+  notifications, too.
+
+http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_IOKitLib_API/chapter_5_section_1.html
+http://developer.apple.com/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/index.html#//apple_ref/doc/uid/TP0000011
+http://www.gauchosoft.com/Software/X%20Resource%20Graph/
+http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification/
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..040412e
--- /dev/null
@@ -0,0 +1,11145 @@
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# Portability macros for glibc argz.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+#   Written by Gary V. Vaughan <gary@gnu.org>
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 argz.m4
+
+AC_DEFUN([gl_FUNC_ARGZ],
+[gl_PREREQ_ARGZ
+
+AC_CHECK_HEADERS([argz.h], [], [], [AC_INCLUDES_DEFAULT])
+
+AC_CHECK_TYPES([error_t],
+  [],
+  [AC_DEFINE([error_t], [int],
+   [Define to a type to use for `error_t' if it is not otherwise available.])
+   AC_DEFINE([__error_t_defined], [1], [Define so that glibc/gnulib argp.h
+    does not typedef error_t.])],
+  [#if defined(HAVE_ARGZ_H)
+#  include <argz.h>
+#endif])
+
+ARGZ_H=
+AC_CHECK_FUNCS([argz_add argz_append argz_count argz_create_sep argz_insert \
+       argz_next argz_stringify], [], [ARGZ_H=argz.h; AC_LIBOBJ([argz])])
+
+dnl if have system argz functions, allow forced use of
+dnl libltdl-supplied implementation (and default to do so
+dnl on "known bad" systems). Could use a runtime check, but
+dnl (a) detecting malloc issues is notoriously unreliable
+dnl (b) only known system that declares argz functions,
+dnl     provides them, yet they are broken, is cygwin
+dnl     releases prior to 16-Mar-2007 (1.5.24 and earlier)
+dnl So, it's more straightforward simply to special case
+dnl this for known bad systems.
+AS_IF([test -z "$ARGZ_H"],
+    [AC_CACHE_CHECK(
+        [if argz actually works],
+        [lt_cv_sys_argz_works],
+        [[case $host_os in #(
+        *cygwin*)
+          lt_cv_sys_argz_works=no
+          if test "$cross_compiling" != no; then
+            lt_cv_sys_argz_works="guessing no"
+          else
+            lt_sed_extract_leading_digits='s/^\([0-9\.]*\).*/\1/'
+            save_IFS=$IFS
+            IFS=-.
+            set x `uname -r | sed -e "$lt_sed_extract_leading_digits"`
+            IFS=$save_IFS
+            lt_os_major=${2-0}
+            lt_os_minor=${3-0}
+            lt_os_micro=${4-0}
+            if test "$lt_os_major" -gt 1 \
+               || { test "$lt_os_major" -eq 1 \
+                 && { test "$lt_os_minor" -gt 5 \
+                   || { test "$lt_os_minor" -eq 5 \
+                     && test "$lt_os_micro" -gt 24; }; }; }; then
+              lt_cv_sys_argz_works=yes
+            fi
+          fi
+          ;; #(
+        *) lt_cv_sys_argz_works=yes ;;
+        esac]])
+     AS_IF([test "$lt_cv_sys_argz_works" = yes],
+        [AC_DEFINE([HAVE_WORKING_ARGZ], 1,
+                   [This value is set to 1 to indicate that the system argz facility works])],
+        [ARGZ_H=argz.h
+        AC_LIBOBJ([argz])])])
+
+AC_SUBST([ARGZ_H])
+])
+
+# Prerequisites of lib/argz.c.
+AC_DEFUN([gl_PREREQ_ARGZ], [:])
+
+# Configure paths for GLIB
+# Owen Taylor     1997-2001
+
+dnl AM_PATH_GLIB_2_0([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]])
+dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if gmodule, gobject,
+dnl gthread, or gio is specified in MODULES, pass to pkg-config
+dnl
+AC_DEFUN([AM_PATH_GLIB_2_0],
+[dnl 
+dnl Get the cflags and libraries from pkg-config
+dnl
+AC_ARG_ENABLE(glibtest, [  --disable-glibtest      do not try to compile and run a test GLIB program],
+                   , enable_glibtest=yes)
+
+  pkg_config_args=glib-2.0
+  for module in . $4
+  do
+      case "$module" in
+         gmodule) 
+             pkg_config_args="$pkg_config_args gmodule-2.0"
+         ;;
+         gmodule-no-export) 
+             pkg_config_args="$pkg_config_args gmodule-no-export-2.0"
+         ;;
+         gobject) 
+             pkg_config_args="$pkg_config_args gobject-2.0"
+         ;;
+         gthread) 
+             pkg_config_args="$pkg_config_args gthread-2.0"
+         ;;
+         gio*) 
+             pkg_config_args="$pkg_config_args $module-2.0"
+         ;;
+      esac
+  done
+
+  PKG_PROG_PKG_CONFIG([0.16])
+
+  no_glib=""
+
+  if test "x$PKG_CONFIG" = x ; then
+    no_glib=yes
+    PKG_CONFIG=no
+  fi
+
+  min_glib_version=ifelse([$1], ,2.0.0,$1)
+  AC_MSG_CHECKING(for GLIB - version >= $min_glib_version)
+
+  if test x$PKG_CONFIG != xno ; then
+    ## don't try to run the test against uninstalled libtool libs
+    if $PKG_CONFIG --uninstalled $pkg_config_args; then
+         echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH"
+         enable_glibtest=no
+    fi
+
+    if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then
+         :
+    else
+         no_glib=yes
+    fi
+  fi
+
+  if test x"$no_glib" = x ; then
+    GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
+    GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0`
+    GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
+    GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0`
+
+    GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args`
+    GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args`
+    glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_glibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GLIB_CFLAGS"
+      LIBS="$GLIB_LIBS $LIBS"
+dnl
+dnl Now check if the installed GLIB is sufficiently new. (Also sanity
+dnl checks the results of pkg-config to some extent)
+dnl
+      rm -f conf.glibtest
+      AC_TRY_RUN([
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main ()
+{
+  unsigned int major, minor, micro;
+
+  fclose (fopen ("conf.glibtest", "w"));
+
+  if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_glib_version");
+     exit(1);
+   }
+
+  if ((glib_major_version != $glib_config_major_version) ||
+      (glib_minor_version != $glib_config_minor_version) ||
+      (glib_micro_version != $glib_config_micro_version))
+    {
+      printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", 
+             $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+             glib_major_version, glib_minor_version, glib_micro_version);
+      printf ("*** was found! If pkg-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GLib. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n");
+      printf("*** to point to the correct configuration files\n");
+    } 
+  else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+          (glib_minor_version != GLIB_MINOR_VERSION) ||
+           (glib_micro_version != GLIB_MICRO_VERSION))
+    {
+      printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+            GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+            glib_major_version, glib_minor_version, glib_micro_version);
+    }
+  else
+    {
+      if ((glib_major_version > major) ||
+        ((glib_major_version == major) && (glib_minor_version > minor)) ||
+        ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n",
+               glib_major_version, glib_minor_version, glib_micro_version);
+        printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n",
+              major, minor, micro);
+        printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the pkg-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n");
+        printf("*** correct copy of pkg-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_glib" = x ; then
+     AC_MSG_RESULT(yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version))
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$PKG_CONFIG" = "no" ; then
+       echo "*** A new enough version of pkg-config was not found."
+       echo "*** See http://www.freedesktop.org/software/pkgconfig/"
+     else
+       if test -f conf.glibtest ; then
+        :
+       else
+          echo "*** Could not run GLIB test program, checking why..."
+          ac_save_CFLAGS="$CFLAGS"
+          ac_save_LIBS="$LIBS"
+          CFLAGS="$CFLAGS $GLIB_CFLAGS"
+          LIBS="$LIBS $GLIB_LIBS"
+          AC_TRY_LINK([
+#include <glib.h>
+#include <stdio.h>
+],      [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+          echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+         echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GLIB is incorrectly installed."])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GLIB_CFLAGS=""
+     GLIB_LIBS=""
+     GLIB_GENMARSHAL=""
+     GOBJECT_QUERY=""
+     GLIB_MKENUMS=""
+     GLIB_COMPILE_RESOURCES=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GLIB_CFLAGS)
+  AC_SUBST(GLIB_LIBS)
+  AC_SUBST(GLIB_GENMARSHAL)
+  AC_SUBST(GOBJECT_QUERY)
+  AC_SUBST(GLIB_MKENUMS)
+  AC_SUBST(GLIB_COMPILE_RESOURCES)
+  rm -f conf.glibtest
+])
+
+dnl Autoconf macros for libgcrypt
+dnl       Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+dnl
+dnl This file is free software; as a special exception the author gives
+dnl unlimited permission to copy and/or distribute it, with or without
+dnl modifications, as long as this notice is preserved.
+dnl
+dnl This file is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+dnl implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+
+dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION,
+dnl                   [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]])
+dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS.
+dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed
+dnl with the API version to also check the API compatibility. Example:
+dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed
+dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1.  Using
+dnl this features allows to prevent build against newer versions of libgcrypt
+dnl with a changed API.
+dnl
+AC_DEFUN([AM_PATH_LIBGCRYPT],
+[ AC_ARG_WITH(libgcrypt-prefix,
+            AC_HELP_STRING([--with-libgcrypt-prefix=PFX],
+                           [prefix where LIBGCRYPT is installed (optional)]),
+     libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="")
+  if test x$libgcrypt_config_prefix != x ; then
+     if test x${LIBGCRYPT_CONFIG+set} != xset ; then
+        LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config
+     fi
+  fi
+
+  AC_PATH_TOOL(LIBGCRYPT_CONFIG, libgcrypt-config, no)
+  tmp=ifelse([$1], ,1:1.2.0,$1)
+  if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
+     req_libgcrypt_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
+     min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
+  else
+     req_libgcrypt_api=0
+     min_libgcrypt_version="$tmp"
+  fi
+
+  AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version)
+  ok=no
+  if test "$LIBGCRYPT_CONFIG" != "no" ; then
+    req_major=`echo $min_libgcrypt_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
+    req_minor=`echo $min_libgcrypt_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
+    req_micro=`echo $min_libgcrypt_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
+    libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+    major=`echo $libgcrypt_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
+    minor=`echo $libgcrypt_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
+    micro=`echo $libgcrypt_config_version | \
+               sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
+    if test "$major" -gt "$req_major"; then
+        ok=yes
+    else
+        if test "$major" -eq "$req_major"; then
+            if test "$minor" -gt "$req_minor"; then
+               ok=yes
+            else
+               if test "$minor" -eq "$req_minor"; then
+                   if test "$micro" -ge "$req_micro"; then
+                     ok=yes
+                   fi
+               fi
+            fi
+        fi
+    fi
+  fi
+  if test $ok = yes; then
+    AC_MSG_RESULT([yes ($libgcrypt_config_version)])
+  else
+    AC_MSG_RESULT(no)
+  fi
+  if test $ok = yes; then
+     # If we have a recent libgcrypt, we should also check that the
+     # API is compatible
+     if test "$req_libgcrypt_api" -gt 0 ; then
+        tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+        if test "$tmp" -gt 0 ; then
+           AC_MSG_CHECKING([LIBGCRYPT API version])
+           if test "$req_libgcrypt_api" -eq "$tmp" ; then
+             AC_MSG_RESULT([okay])
+           else
+             ok=no
+             AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp])
+           fi
+        fi
+     fi
+  fi
+  if test $ok = yes; then
+    LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
+    LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
+    ifelse([$2], , :, [$2])
+    if test x"$host" != x ; then
+      libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+      if test x"$libgcrypt_config_host" != xnone ; then
+        if test x"$libgcrypt_config_host" != x"$host" ; then
+  AC_MSG_WARN([[
+***
+*** The config script $LIBGCRYPT_CONFIG was
+*** built for $libgcrypt_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-libgcrypt-prefix
+*** to specify a matching config script.
+***]])
+        fi
+      fi
+    fi
+  else
+    LIBGCRYPT_CFLAGS=""
+    LIBGCRYPT_LIBS=""
+    ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(LIBGCRYPT_CFLAGS)
+  AC_SUBST(LIBGCRYPT_LIBS)
+])
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 57 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+                  [m4_fatal([Libtool version $1 or higher is required],
+                            63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\    *)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+       [m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+       [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+       [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+          m4_quote(lt_decl_varnames),
+       m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+                       lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+                                          [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+       dnl If the libtool generation code has been placed in $CONFIG_LT,
+       dnl instead of duplicating it all over again into config.status,
+       dnl then we will have config.status run $CONFIG_LT later, so it
+       dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable.  If COMMENT is supplied, it is inserted after the
+# `#!' sequence but before initialization text begins.  After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script.  The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test $lt_write_fail = 0 && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test "$silent" = yes &&
+  lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+  _LT_PROG_REPLACE_SHELLFNS
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],                 [_LT_LANG(C)],
+  [C++],               [_LT_LANG(CXX)],
+  [Go],                        [_LT_LANG(GO)],
+  [Java],              [_LT_LANG(GCJ)],
+  [Fortran 77],                [_LT_LANG(F77)],
+  [Fortran],           [_LT_LANG(FC)],
+  [Windows Resource],  [_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_GO.  When it is available in    #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC],     [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+  fi
+fi
+if test -z "$GOC"; then
+  AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+       [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+       [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+       [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+  [LT_LANG(GO)],
+  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+       # By default we will add the -single_module flag. You can override
+       # by either setting the environment variable LT_MULTI_MODULE
+       # non-empty at configure time, or by adding -multi_module to the
+       # link flags.
+       rm -rf libconftest.dylib*
+       echo "int foo(void){return 1;}" > conftest.c
+       echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+       $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+         -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+       # If there is a non-empty error log, and "single_module"
+       # appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+         cat conftest.err >&AS_MESSAGE_LOG_FD
+       # Otherwise, if the output was created with a 0 exit code from
+       # the compiler, it worked.
+       elif test -f libconftest.dylib && test $_lt_result -eq 0; then
+         lt_cv_apple_cc_single_mod=yes
+       else
+         cat conftest.err >&AS_MESSAGE_LOG_FD
+       fi
+       rm -rf libconftest.dylib*
+       rm -f conftest.*
+      fi])
+
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+       [lt_cv_ld_exported_symbols_list=yes],
+       [lt_cv_ld_exported_symbols_list=no])
+       LDFLAGS="$save_LDFLAGS"
+    ])
+
+    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+      [lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+      echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+       cat conftest.err >&AS_MESSAGE_LOG_FD
+      elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then
+       lt_cv_ld_force_load=yes
+      else
+       cat conftest.err >&AS_MESSAGE_LOG_FD
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+       10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+       10.[[012]]*)
+         _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+       10.*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+    m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+                  [FC],  [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+  else
+    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  fi
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+    m4_if([$1], [CXX],
+[   if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+  lt_aix_libpath_sed='[
+      /Import File Strings/,/^$/ {
+         /^0/ {
+             s/^0  *\([^ ]*\) *$/\1/
+             p
+         }
+      }]'
+  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi],[])
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib"
+  fi
+  ])
+  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script which will find a shell with a builtin
+# printf (which we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*" 
+}
+
+case "$ECHO" in
+  printf*) AC_MSG_RESULT([printf]) ;;
+  print*) AC_MSG_RESULT([print -r]) ;;
+  *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test "X`printf %s $ECHO`" = "X$ECHO" \
+      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[  --with-sysroot[=DIR] Search for dependent libraries within DIR
+                        (or the compiler's sysroot if not specified).],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted.  We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+   if test "$GCC" = yes; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   AC_MSG_RESULT([${with_sysroot}])
+   AC_MSG_ERROR([The sysroot must be an absolute path.])
+   ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and in which our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+       HPUX_IA64_MODE="32"
+       ;;
+      *ELF-64*)
+       HPUX_IA64_MODE="64"
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -melf32bsmip"
+         ;;
+       *N32*)
+         LD="${LD-ld} -melf32bmipn32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -melf64bmip"
+       ;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -32"
+         ;;
+       *N32*)
+         LD="${LD-ld} -n32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -64"
+         ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_i386_fbsd"
+           ;;
+         x86_64-*linux*)
+           case `/usr/bin/file conftest.o` in
+             *x86-64*)
+               LD="${LD-ld} -m elf32_x86_64"
+               ;;
+             *)
+               LD="${LD-ld} -m elf_i386"
+               ;;
+           esac
+           ;;
+         powerpc64le-*)
+           LD="${LD-ld} -m elf32lppclinux"
+           ;;
+         powerpc64-*)
+           LD="${LD-ld} -m elf32ppclinux"
+           ;;
+         s390x-*linux*)
+           LD="${LD-ld} -m elf_s390"
+           ;;
+         sparc64-*linux*)
+           LD="${LD-ld} -m elf32_sparc"
+           ;;
+       esac
+       ;;
+      *64-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_x86_64_fbsd"
+           ;;
+         x86_64-*linux*)
+           LD="${LD-ld} -m elf_x86_64"
+           ;;
+         powerpcle-*)
+           LD="${LD-ld} -m elf64lppc"
+           ;;
+         powerpc-*)
+           LD="${LD-ld} -m elf64ppc"
+           ;;
+         s390*-*linux*|s390*-*tpf*)
+           LD="${LD-ld} -m elf64_s390"
+           ;;
+         sparc*-*linux*)
+           LD="${LD-ld} -m elf64_sparc"
+           ;;
+       esac
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD="${LD-ld}_sol2"
+        fi
+        ;;
+      *)
+       if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+         LD="${LD-ld} -64"
+       fi
+       ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+  [lt_cv_ar_at_file=no
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+     [echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+      AC_TRY_EVAL([lt_ar_try])
+      if test "$ac_status" -eq 0; then
+       # Ensure the archiver fails upon bogus file names.
+       rm -f conftest.$ac_objext libconftest.a
+       AC_TRY_EVAL([lt_ar_try])
+       if test "$ac_status" -ne 0; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+     ])
+  ])
+
+if test "x$lt_cv_ar_at_file" = xno; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+  [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+    [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#              [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[        ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \
+                = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+         [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+           [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+       [AC_CHECK_FUNC([dlopen],
+             [lt_cv_dlopen="dlopen"],
+         [AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+           [AC_CHECK_LIB([svld], [dlopen],
+                 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+             [AC_CHECK_LIB([dld], [dld_link],
+                   [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+             ])
+           ])
+         ])
+       ])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+         lt_cv_dlopen_self, [dnl
+         _LT_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+           lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+         lt_cv_dlopen_self_static, [dnl
+         _LT_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+           lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+        [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+        [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+        [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+       [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+  [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+   test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+       [], [
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([[A-Za-z]]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+m4_if([$1], [],[
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[23]].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux # correct to gnu/linux during the next big refactor
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+    [lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+        LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+        [lt_cv_shlibpath_overrides_runpath=yes])])
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+    ])
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[  ]*hwcap[        ]/d;s/[:,      ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+    [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+    [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+        [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+       [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test "$GCC" != yes; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+    [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+  AC_SUBST([DUMPBIN])
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+  ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+    [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+  [lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*])
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+  MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+  esac
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+       [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[    ]]\($symcode$symcode*\)[[       ]][[    ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+       if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT@&t@_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT@&t@_DLSYM_CONST
+#else
+# define LT@&t@_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+         cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT@&t@_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+         cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_globsym_save_LIBS=$LIBS
+         lt_globsym_save_CFLAGS=$CFLAGS
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+         if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS=$lt_globsym_save_LIBS
+         CFLAGS=$lt_globsym_save_CFLAGS
+       else
+         echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([], [nm_file_list_spec], [1],
+    [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+       # All AIX code is PIC.
+       if test "$host_cpu" = ia64; then
+         # AIX 5 now supports IA64 processor
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       else
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68*)
+         # Green Hills C++ Compiler
+         # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+      mingw* | cygwin* | os2* | pw32* | cegcc*)
+       # This hack is so that the source file can tell whether it is being
+       # built for inclusion in a dll (and should export symbols for example).
+       m4_if([$1], [GCJ], [],
+         [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++*)
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         ghcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | dragonfly*)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           if test "$host_cpu" != ia64; then
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+           fi
+           ;;
+         aCC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           case $host_cpu in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      interix*)
+       # This is c89, which is MS Visual C++ (no shared libs)
+       # Anyone wants to do a port?
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+       case $cc_basename in
+         KCC*)
+           # KAI C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           ;;
+         ecpc* )
+           # old Intel C++ for x86_64 which still supported -KPIC.
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         icpc* )
+           # Intel C++, used to be incompatible with GCC.
+           # ICC 10 doesn't accept -KPIC any more.
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         pgCC* | pgcpp*)
+           # Portland Group C++ compiler
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         cxx*)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+           # IBM XL 8.0, 9.0 on PPC and BlueGene
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+             _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+             _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx*)
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd* | netbsdelf*-gnu)
+       ;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           ;;
+         RCC*)
+           # Rational C++ 2.4.1
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         cxx*)
+           # Digital/Compaq C++
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC* | sunCC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+           ;;
+         gcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.x
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         lcc*)
+           # Lucid
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC*)
+           # NonStop-UX NCC 3.20
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      vxworks*)
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+       ;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+      if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+       ;;
+      nagfor*)
+       # NAG Fortran compiler
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       ;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+       # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+         ;;
+       *Sun\ F* | *Sun*Fortran*)
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+         ;;
+       *Sun\ C*)
+         # Sun C 5.9
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+        *Intel*\ [[CF]]*Compiler*)
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+         ;;
+       *Portland\ Group*)
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+       [Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+       [How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+       [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    # Also, AIX nm treats weak defined symbols like other global defined
+    # symbols, whereas GNU nm marks them as "W".
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+    ;;
+  cygwin* | mingw* | cegcc*)
+    case $cc_basename in
+    cl*)
+      _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+      ;;
+    *)
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+      ;;
+    esac
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    _LT_TAGVAR(link_all_deplibs, $1)=no
+    ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+    ;;
+  esac
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    _LT_TAGVAR(link_all_deplibs, $1)=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+       # The AIX port of GNU ld has always aspired to compatibility
+       # with the native linker.  However, as the warning in the GNU ld
+       # block says, versions before 2.19.5* couldn't really create working
+       # shared libraries, regardless of the interface used.
+       case `$LD -v 2>&1` in
+         *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+         *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+         *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+         *)
+           lt_use_gnu_ld_interface=yes
+           ;;
+       esac
+       ;;
+      *)
+       lt_use_gnu_ld_interface=yes
+       ;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    haiku*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+       case $cc_basename in
+         diet\ *) tmp_diet=yes;;       # linux-dietlibc with static linking (!diet-dyn)
+       esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+        && test "$tmp_diet" = no
+      then
+       tmp_addflag=' $pic_flag'
+       tmp_sharedflag='-shared'
+       case $cc_basename,$host_cpu in
+        pgcc*)                         # Portland Group C compiler
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95* | pgfortran*)
+                                       # Portland Group f77 and f90 compilers
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)        # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       lf95*)                          # Lahey Fortran 8.1
+         _LT_TAGVAR(whole_archive_flag_spec, $1)=
+         tmp_sharedflag='--shared' ;;
+       xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+         tmp_sharedflag='-qmkshrobj'
+         tmp_addflag= ;;
+       nvcc*)  # Cuda Compiler Driver 2.2
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         _LT_TAGVAR(compiler_needs_object, $1)=yes
+         ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         _LT_TAGVAR(compiler_needs_object, $1)=yes
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       esac
+       _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+           cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+           echo "local: *; };" >> $output_objdir/$libname.ver~
+           $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+       case $cc_basename in
+       xlf* | bgf* | bgxlf* | mpixlf*)
+         # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+         if test "x$supports_anon_versioning" = xyes; then
+           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+             cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+             echo "local: *; };" >> $output_objdir/$libname.ver~
+             $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+         fi
+         ;;
+       esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         # For security reasons, it is highly recommended that you always
+         # use absolute paths for naming shared libraries, and exclude the
+         # DT_RUNPATH tag from executables and libraries.  But doing so
+         # requires that you compile everything twice, which is a pain.
+         if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         else
+           _LT_TAGVAR(ld_shlibs, $1)=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       _LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       # Also, AIX nm treats weak defined symbols like other global
+       # defined symbols, whereas GNU nm marks them as "W".
+       if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+         _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       else
+         _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[[012]]|aix4.[[012]].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+          strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         _LT_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+       _LT_TAGVAR(link_all_deplibs, $1)=no
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX([$1])
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+       if test "$host_cpu" = ia64; then
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+         _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+         _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX([$1])
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+         _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+         if test "$with_gnu_ld" = yes; then
+           # We only use this code for GNU lds that support --whole-archive.
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+         else
+           # Exported symbols can be pulled into shared objects from archives
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+         fi
+         _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl*)
+       # Native MSVC
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       _LT_TAGVAR(always_export_symbols, $1)=yes
+       _LT_TAGVAR(file_list_spec, $1)='@'
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+       _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+           sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+         else
+           sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+         fi~
+         $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+         linknames='
+       # The linker will not automatically build a static lib if we build a DLL.
+       # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+       _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+       # Don't use ranlib
+       _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+       _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+         lt_tool_outputfile="@TOOL_OUTPUT@"~
+         case $lt_outputfile in
+           *.exe|*.EXE) ;;
+           *)
+             lt_outputfile="$lt_outputfile.exe"
+             lt_tool_outputfile="$lt_tool_outputfile.exe"
+             ;;
+         esac~
+         if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+           $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+           $RM "$lt_outputfile.manifest";
+         fi'
+       ;;
+      *)
+       # Assume MSVC wrapper
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+       # The linker will automatically build a .lib file if we build a DLL.
+       _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+       # FIXME: Should let the user specify the lib program.
+       _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       ;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+       _LT_TAGVAR(hardcode_direct, $1)=yes
+       _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+       m4_if($1, [], [
+         # Older versions of the 11.00 compiler do not understand -b yet
+         # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+         _LT_LINKER_OPTION([if $CC understands -b],
+           _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+           [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+           [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+         [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         _LT_TAGVAR(hardcode_direct, $1)=no
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+         ;;
+       *)
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         _LT_TAGVAR(hardcode_minus_L, $1)=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       # Try to use the -exported_symbol ld option, if it does not
+       # work, assume that -exports_file does not work either and
+       # implicitly export all symbols.
+       # This should be the same for all languages, so no per-tag cache variable.
+       AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+         [lt_cv_irix_exported_symbol],
+         [save_LDFLAGS="$LDFLAGS"
+          LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+          AC_LINK_IFELSE(
+            [AC_LANG_SOURCE(
+               [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+                             [C++], [[int foo (void) { return 0; }]],
+                             [Fortran 77], [[
+      subroutine foo
+      end]],
+                             [Fortran], [[
+      subroutine foo
+      end]])])],
+             [lt_cv_irix_exported_symbol=yes],
+             [lt_cv_irix_exported_symbol=no])
+           LDFLAGS="$save_LDFLAGS"])
+       if test "$lt_cv_irix_exported_symbol" = yes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+       fi
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       _LT_TAGVAR(hardcode_direct, $1)=yes
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+       if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       else
+         case $host_os in
+          openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+            _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+            ;;
+          *)
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+            ;;
+         esac
+       fi
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+       _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+       $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+       case `$CC -V 2>&1` in
+       *"Compilers 5.0"*)
+         wlarc=''
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+         ;;
+       *)
+         wlarc='${wl}'
+         _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+         ;;
+       esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+         _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+       motorola)
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       _LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+       ;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+       [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+       [$RM conftest*
+       echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+       if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+         soname=conftest
+         lib=conftest
+         libobjs=conftest.$ac_objext
+         deplibs=
+         wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+         pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+         compiler_flags=-v
+         linker_flags=-v
+         verstring=
+         output_objdir=.
+         libname=conftest
+         lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+         _LT_TAGVAR(allow_undefined_flag, $1)=
+         if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+         then
+           lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+         else
+           lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+         fi
+         _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+       else
+         cat conftest.err 1>&5
+       fi
+       $RM conftest*
+       ])
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+    [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report which library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_CFLAGS=$CFLAGS
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  CFLAGS=$CXXFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test "$GXX" = yes; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test "$GXX" = yes; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test "$with_gnu_ld" = yes; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='${wl}'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+         $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test "$host_cpu" = ia64; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=""
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # need to do runtime linking.
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+           for ld_flag in $LDFLAGS; do
+             case $ld_flag in
+             *-brtl*)
+               aix_use_runtimelinking=yes
+               break
+               ;;
+             esac
+           done
+           ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+        if test "$GXX" = yes; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+            strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+           # We have reworked collect2
+           :
+         else
+           # We have old collect2
+           _LT_TAGVAR(hardcode_direct, $1)=unsupported
+           # It fails to find uninstalled libraries when the uninstalled
+           # path is not listed in the libpath.  Setting hardcode_minus_L
+           # to unsupported forces relinking
+           _LT_TAGVAR(hardcode_minus_L, $1)=yes
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+          esac
+          shared_flag='-shared'
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag="$shared_flag "'${wl}-G'
+         fi
+        else
+          # not using gcc
+          if test "$host_cpu" = ia64; then
+         # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+         # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+          else
+           if test "$aix_use_runtimelinking" = yes; then
+             shared_flag='${wl}-G'
+           else
+             shared_flag='${wl}-bM:SRE'
+           fi
+          fi
+        fi
+
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+       # export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+        if test "$aix_use_runtimelinking" = yes; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX([$1])
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        else
+          if test "$host_cpu" = ia64; then
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+           _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+           _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+          else
+           # Determine the default libpath from the value encoded in an
+           # empty executable.
+           _LT_SYS_MODULE_PATH_AIX([$1])
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+           # Warning - without using the other run time loading flags,
+           # -berok will link without error, but may produce a broken library.
+           _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+           _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+           if test "$with_gnu_ld" = yes; then
+             # We only use this code for GNU lds that support --whole-archive.
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+           else
+             # Exported symbols can be pulled into shared objects from archives
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+           fi
+           _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+           # This is similar to how AIX traditionally builds its shared
+           # libraries.
+           _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+          fi
+        fi
+        ;;
+
+      beos*)
+       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+         # support --undefined.  This deserves some investigation.  FIXME
+         _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       else
+         _LT_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+         # FIXME: insert proper C++ library support
+         _LT_TAGVAR(ld_shlibs, $1)=no
+         ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+       case $GXX,$cc_basename in
+       ,cl* | no,cl*)
+         # Native MSVC
+         # hardcode_libdir_flag_spec is actually meaningless, as there is
+         # no search path for DLLs.
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         _LT_TAGVAR(always_export_symbols, $1)=yes
+         _LT_TAGVAR(file_list_spec, $1)='@'
+         # Tell ltmain to make .lib files, not .a files.
+         libext=lib
+         # Tell ltmain to make .dll files, not .so files.
+         shrext_cmds=".dll"
+         # FIXME: Setting linknames here is a bad hack.
+         _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+         _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+             $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+           else
+             $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+           fi~
+           $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+           linknames='
+         # The linker will not automatically build a static lib if we build a DLL.
+         # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+         _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+         # Don't use ranlib
+         _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+         _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+           lt_tool_outputfile="@TOOL_OUTPUT@"~
+           case $lt_outputfile in
+             *.exe|*.EXE) ;;
+             *)
+               lt_outputfile="$lt_outputfile.exe"
+               lt_tool_outputfile="$lt_tool_outputfile.exe"
+               ;;
+           esac~
+           func_to_tool_file "$lt_outputfile"~
+           if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+             $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+             $RM "$lt_outputfile.manifest";
+           fi'
+         ;;
+       *)
+         # g++
+         # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+         # as there is no search path for DLLs.
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         _LT_TAGVAR(always_export_symbols, $1)=no
+         _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+         if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+           # If the export-symbols file already is a .def file (1st line
+           # is EXPORTS), use it as is; otherwise, prepend...
+           _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+             cp $export_symbols $output_objdir/$soname.def;
+           else
+             echo EXPORTS > $output_objdir/$soname.def;
+             cat $export_symbols >> $output_objdir/$soname.def;
+           fi~
+           $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+         else
+           _LT_TAGVAR(ld_shlibs, $1)=no
+         fi
+         ;;
+       esac
+       ;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+       ;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          ghcx*)
+           # Green Hills C++ Compiler
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      freebsd2.*)
+        # C++ shared libraries reported to be fairly broken before
+       # switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      haiku*)
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                            # but as the default
+                                            # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+            ;;
+          *)
+            if test "$GXX" = yes; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test $with_gnu_ld = no; then
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+         _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+             _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                                # but as the default
+                                                # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          aCC*)
+           case $host_cpu in
+             hppa*64*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+             ia64*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+             *)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+           esac
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+           ;;
+          *)
+           if test "$GXX" = yes; then
+             if test $with_gnu_ld = no; then
+               case $host_cpu in
+                 hppa*64*)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+                 ia64*)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+                 *)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+               esac
+             fi
+           else
+             # FIXME: insert proper C++ library support
+             _LT_TAGVAR(ld_shlibs, $1)=no
+           fi
+           ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+       _LT_TAGVAR(hardcode_direct, $1)=no
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+       # Instead, shared libraries are loaded at an image base (0x10000000 by
+       # default) and relocated if they conflict, which is a slow very memory
+       # consuming and fragmenting process.  To avoid this, we pick a random,
+       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+       ;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+           # SGI C++
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+
+           # Archives containing C++ object files must be created using
+           # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+           # necessary to make sure instantiated templates are included
+           # in the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+           ;;
+          *)
+           if test "$GXX" = yes; then
+             if test "$with_gnu_ld" = no; then
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+             else
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
+             fi
+           fi
+           _LT_TAGVAR(link_all_deplibs, $1)=yes
+           ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+        case $cc_basename in
+          KCC*)
+           # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+           # KCC will only create a shared library if the output file
+           # ends with ".so" (or ".sl" for HP-UX), so rename the library
+           # to its proper name (with version) after linking.
+           _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+           # Archives containing C++ object files must be created using
+           # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+           ;;
+         icpc* | ecpc* )
+           # Intel C++
+           with_gnu_ld=yes
+           # version 8.0 and above of icpc choke on multiply defined symbols
+           # if we add $predep_objects and $postdep_objects, however 7.1 and
+           # earlier do not add the objects themselves.
+           case `$CC -V 2>&1` in
+             *"Version 7."*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+               ;;
+             *)  # Version 8.0 or newer
+               tmp_idyn=
+               case $host_cpu in
+                 ia64*) tmp_idyn=' -i_dynamic';;
+               esac
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+               ;;
+           esac
+           _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+           ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+           case `$CC -V` in
+           *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+             _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+             _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+               $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+               $RANLIB $oldlib'
+             _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+               $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+               $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+             ;;
+           *) # Version 6 and above use weak symbols
+             _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+             ;;
+           esac
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+            ;;
+         cxx*)
+           # Compaq C++
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+           runpath_var=LD_RUN_PATH
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+           ;;
+         xl* | mpixl* | bgxl*)
+           # IBM XL 8.0 on PPC, with GNU ld
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           if test "x$supports_anon_versioning" = xyes; then
+             _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+               cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+               echo "local: *; };" >> $output_objdir/$libname.ver~
+               $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+           fi
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+             _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+             _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+             # Not sure whether something based on
+             # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+             # would be better.
+             output_verbose_link_cmd='func_echo_all'
+
+             # Archives containing C++ object files must be created using
+             # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+             # necessary to make sure instantiated templates are included
+             # in the archive.
+             _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+         *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+       esac
+       ;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+         _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+         wlarc=
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       fi
+       # Workaround some broken pre-1.5 toolchains
+       output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+       ;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+       ;;
+
+      openbsd2*)
+        # C++ shared libraries are fairly broken
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      openbsd*)
+       if test -f /usr/libexec/ld.so; then
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+         _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+         if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+         fi
+         output_verbose_link_cmd=func_echo_all
+       else
+         _LT_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+           # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+           # KCC will only create a shared library if the output file
+           # ends with ".so" (or ".sl" for HP-UX), so rename the library
+           # to its proper name (with version) after linking.
+           _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Archives containing C++ object files must be created using
+           # the KAI C++ compiler.
+           case $host in
+             osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+             *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+           esac
+           ;;
+          RCC*)
+           # Rational C++ 2.4.1
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          cxx*)
+           case $host in
+             osf3*)
+               _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+               _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+               ;;
+             *)
+               _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+                 echo "-hidden">> $lib.exp~
+                 $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
+                 $RM $lib.exp'
+               _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+               ;;
+           esac
+
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+           ;;
+         *)
+           if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+             _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+             case $host in
+               osf3*)
+                 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+                 ;;
+               *)
+                 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+                 ;;
+             esac
+
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+             _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+             # Commands to make compiler produce verbose output that lists
+             # what "hidden" libraries, object files and flags are used when
+             # linking a shared library.
+             output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+           else
+             # FIXME: insert proper C++ library support
+             _LT_TAGVAR(ld_shlibs, $1)=no
+           fi
+           ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+           # Sun C++ 4.x
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          lcc*)
+           # Lucid
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC* | sunCC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+           _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+             $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+           _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+           case $host_os in
+             solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+             *)
+               # The compiler driver will combine and reorder linker options,
+               # but understands `-z linker_flag'.
+               # Supported since Solaris 2.6 (maybe 2.5.1?)
+               _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+               ;;
+           esac
+           _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+           output_verbose_link_cmd='func_echo_all'
+
+           # Archives containing C++ object files must be created using
+           # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+           # necessary to make sure instantiated templates are included
+           # in the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+           ;;
+          gcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+           # The C++ compiler must be used to create the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+           ;;
+          *)
+           # GNU C++ compiler with Solaris linker
+           if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+             _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+             if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                 $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+               # Commands to make compiler produce verbose output that lists
+               # what "hidden" libraries, object files and flags are used when
+               # linking a shared library.
+               output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+             else
+               # g++ 2.7 appears to require `-G' NOT `-shared' on this
+               # platform.
+               _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                 $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+               # Commands to make compiler produce verbose output that lists
+               # what "hidden" libraries, object files and flags are used when
+               # linking a shared library.
+               output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+             fi
+
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+             case $host_os in
+               solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+               *)
+                 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+                 ;;
+             esac
+           fi
+           ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+       # Note: We can NOT use -z defs as we might desire, because we do not
+       # link with -lc, and that would cause any symbols used from libc to
+       # always be unresolved, which means just about no library would
+       # ever link correctly.  If we're not using GNU ld we use -z text
+       # though, which does catch some bad symbols but isn't as heavy-handed
+       # as -z defs.
+       _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+       _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+       _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+       _LT_TAGVAR(link_all_deplibs, $1)=yes
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+       runpath_var='LD_RUN_PATH'
+
+       case $cc_basename in
+          CC*)
+           _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+             '"$_LT_TAGVAR(old_archive_cmds, $1)"
+           _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+             '"$_LT_TAGVAR(reload_cmds, $1)"
+           ;;
+         *)
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           ;;
+       esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+           # NonStop-UX NCC 3.20
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)="$GXX"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+  case ${2} in
+  .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+  *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case ${prev}${p} in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" ||
+          test $p = "-R"; then
+        prev=$p
+        continue
+       fi
+
+       # Expand the sysroot to ease extracting the directories later.
+       if test -z "$prev"; then
+         case $p in
+         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+         esac
+       fi
+       case $p in
+       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+       esac
+       if test "$pre_test_object_deps_done" = no; then
+        case ${prev} in
+        -L | -R)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+            _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+          else
+            _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+          _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+        else
+          _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+        fi
+       fi
+       prev=
+       ;;
+
+    *.lto.$objext) ;; # Ignore GCC LTO objects
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+          _LT_TAGVAR(predep_objects, $1)="$p"
+        else
+          _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+        fi
+       else
+        if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+          _LT_TAGVAR(postdep_objects, $1)="$p"
+        else
+          _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC* | sunCC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test "X$F77" = "Xno"; then
+  _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${F77-"f77"}
+  CFLAGS=$FFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+       if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+         test "$enable_shared" = yes && enable_static=no
+       fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$G77"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+  CFLAGS="$lt_save_CFLAGS"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test "X$FC" = "Xno"; then
+  _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${FC-"f95"}
+  CFLAGS=$FCFLAGS
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+       if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+         test "$enable_shared" = yes && enable_static=no
+       fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,b/c, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY)
+# ------------------------------------------------------
+# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and
+# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY.
+m4_defun([_LT_PROG_FUNCTION_REPLACE],
+[dnl {
+sed -e '/^$1 ()$/,/^} # $1 /c\
+$1 ()\
+{\
+m4_bpatsubsts([$2], [$], [\\], [^\([    ]\)], [\\\1])
+} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+])
+
+
+# _LT_PROG_REPLACE_SHELLFNS
+# -------------------------
+# Replace existing portable implementations of several shell functions with
+# equivalent extended shell implementations where those features are available..
+m4_defun([_LT_PROG_REPLACE_SHELLFNS],
+[if test x"$xsi_shell" = xyes; then
+  _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac])
+
+  _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl
+    func_basename_result="${1##*/}"])
+
+  _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac
+    func_basename_result="${1##*/}"])
+
+  _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl
+    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+    # positional parameters, so assign one to ordinary parameter first.
+    func_stripname_result=${3}
+    func_stripname_result=${func_stripname_result#"${1}"}
+    func_stripname_result=${func_stripname_result%"${2}"}])
+
+  _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl
+    func_split_long_opt_name=${1%%=*}
+    func_split_long_opt_arg=${1#*=}])
+
+  _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl
+    func_split_short_opt_arg=${1#??}
+    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}])
+
+  _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl
+    case ${1} in
+      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+      *)    func_lo2o_result=${1} ;;
+    esac])
+
+  _LT_PROG_FUNCTION_REPLACE([func_xform], [    func_xform_result=${1%.*}.lo])
+
+  _LT_PROG_FUNCTION_REPLACE([func_arith], [    func_arith_result=$(( $[*] ))])
+
+  _LT_PROG_FUNCTION_REPLACE([func_len], [    func_len_result=${#1}])
+fi
+
+if test x"$lt_shell_append" = xyes; then
+  _LT_PROG_FUNCTION_REPLACE([func_append], [    eval "${1}+=\\${2}"])
+
+  _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl
+    func_quote_for_eval "${2}"
+dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \
+    eval "${1}+=\\\\ \\$func_quote_for_eval_result"])
+
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+  AC_MSG_WARN([Unable to substitute extended shell functions in $ofile])
+fi
+])
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine which file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+         [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+         [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
+
+# ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*-
+#
+#   Copyright (C) 1999-2006, 2007, 2008, 2011 Free Software Foundation, Inc.
+#   Written by Thomas Tanner, 1999
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 18 LTDL_INIT
+
+# LT_CONFIG_LTDL_DIR(DIRECTORY, [LTDL-MODE])
+# ------------------------------------------
+# DIRECTORY contains the libltdl sources.  It is okay to call this
+# function multiple times, as long as the same DIRECTORY is always given.
+AC_DEFUN([LT_CONFIG_LTDL_DIR],
+[AC_BEFORE([$0], [LTDL_INIT])
+_$0($*)
+])# LT_CONFIG_LTDL_DIR
+
+# We break this out into a separate macro, so that we can call it safely
+# internally without being caught accidentally by the sed scan in libtoolize.
+m4_defun([_LT_CONFIG_LTDL_DIR],
+[dnl remove trailing slashes
+m4_pushdef([_ARG_DIR], m4_bpatsubst([$1], [/*$]))
+m4_case(_LTDL_DIR,
+       [], [dnl only set lt_ltdl_dir if _ARG_DIR is not simply `.'
+            m4_if(_ARG_DIR, [.],
+                    [],
+                [m4_define([_LTDL_DIR], _ARG_DIR)
+                 _LT_SHELL_INIT([lt_ltdl_dir=']_ARG_DIR['])])],
+    [m4_if(_ARG_DIR, _LTDL_DIR,
+           [],
+       [m4_fatal([multiple libltdl directories: `]_LTDL_DIR[', `]_ARG_DIR['])])])
+m4_popdef([_ARG_DIR])
+])# _LT_CONFIG_LTDL_DIR
+
+# Initialise:
+m4_define([_LTDL_DIR], [])
+
+
+# _LT_BUILD_PREFIX
+# ----------------
+# If Autoconf is new enough, expand to `${top_build_prefix}', otherwise
+# to `${top_builddir}/'.
+m4_define([_LT_BUILD_PREFIX],
+[m4_ifdef([AC_AUTOCONF_VERSION],
+   [m4_if(m4_version_compare(m4_defn([AC_AUTOCONF_VERSION]), [2.62]),
+         [-1], [m4_ifdef([_AC_HAVE_TOP_BUILD_PREFIX],
+                         [${top_build_prefix}],
+                         [${top_builddir}/])],
+         [${top_build_prefix}])],
+   [${top_builddir}/])[]dnl
+])
+
+
+# LTDL_CONVENIENCE
+# ----------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  LIBLTDL will be prefixed with
+# '${top_build_prefix}' if available, otherwise with '${top_builddir}/',
+# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
+# quotes!).  If your package is not flat and you're not using automake,
+# define top_build_prefix, top_builddir, and top_srcdir appropriately
+# in your Makefiles.
+AC_DEFUN([LTDL_CONVENIENCE],
+[AC_BEFORE([$0], [LTDL_INIT])dnl
+dnl Although the argument is deprecated and no longer documented,
+dnl LTDL_CONVENIENCE used to take a DIRECTORY orgument, if we have one
+dnl here make sure it is the same as any other declaration of libltdl's
+dnl location!  This also ensures lt_ltdl_dir is set when configure.ac is
+dnl not yet using an explicit LT_CONFIG_LTDL_DIR.
+m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl
+_$0()
+])# LTDL_CONVENIENCE
+
+# AC_LIBLTDL_CONVENIENCE accepted a directory argument in older libtools,
+# now we have LT_CONFIG_LTDL_DIR:
+AU_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])])
+_LTDL_CONVENIENCE])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [])
+
+
+# _LTDL_CONVENIENCE
+# -----------------
+# Code shared by LTDL_CONVENIENCE and LTDL_INIT([convenience]).
+m4_defun([_LTDL_CONVENIENCE],
+[case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+esac
+LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdlc.la"
+LTDLDEPS=$LIBLTDL
+LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}"
+
+AC_SUBST([LIBLTDL])
+AC_SUBST([LTDLDEPS])
+AC_SUBST([LTDLINCL])
+
+# For backwards non-gettext consistent compatibility...
+INCLTDL="$LTDLINCL"
+AC_SUBST([INCLTDL])
+])# _LTDL_CONVENIENCE
+
+
+# LTDL_INSTALLABLE
+# ----------------
+# sets LIBLTDL to the link flags for the libltdl installable library
+# and LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called from here.  If an installed libltdl
+# is not found, LIBLTDL will be prefixed with '${top_build_prefix}' if
+# available, otherwise with '${top_builddir}/', and LTDLINCL will be
+# prefixed with '${top_srcdir}/' (note the single quotes!).  If your
+# package is not flat and you're not using automake, define top_build_prefix,
+# top_builddir, and top_srcdir appropriately in your Makefiles.
+# In the future, this macro may have to be called after LT_INIT.
+AC_DEFUN([LTDL_INSTALLABLE],
+[AC_BEFORE([$0], [LTDL_INIT])dnl
+dnl Although the argument is deprecated and no longer documented,
+dnl LTDL_INSTALLABLE used to take a DIRECTORY orgument, if we have one
+dnl here make sure it is the same as any other declaration of libltdl's
+dnl location!  This also ensures lt_ltdl_dir is set when configure.ac is
+dnl not yet using an explicit LT_CONFIG_LTDL_DIR.
+m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl
+_$0()
+])# LTDL_INSTALLABLE
+
+# AC_LIBLTDL_INSTALLABLE accepted a directory argument in older libtools,
+# now we have LT_CONFIG_LTDL_DIR:
+AU_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])])
+_LTDL_INSTALLABLE])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [])
+
+
+# _LTDL_INSTALLABLE
+# -----------------
+# Code shared by LTDL_INSTALLABLE and LTDL_INIT([installable]).
+m4_defun([_LTDL_INSTALLABLE],
+[if test -f $prefix/lib/libltdl.la; then
+  lt_save_LDFLAGS="$LDFLAGS"
+  LDFLAGS="-L$prefix/lib $LDFLAGS"
+  AC_CHECK_LIB([ltdl], [lt_dlinit], [lt_lib_ltdl=yes])
+  LDFLAGS="$lt_save_LDFLAGS"
+  if test x"${lt_lib_ltdl-no}" = xyes; then
+    if test x"$enable_ltdl_install" != xyes; then
+      # Don't overwrite $prefix/lib/libltdl.la without --enable-ltdl-install
+      AC_MSG_WARN([not overwriting libltdl at $prefix, force with `--enable-ltdl-install'])
+      enable_ltdl_install=no
+    fi
+  elif test x"$enable_ltdl_install" = xno; then
+    AC_MSG_WARN([libltdl not installed, but installation disabled])
+  fi
+fi
+
+# If configure.ac declared an installable ltdl, and the user didn't override
+# with --disable-ltdl-install, we will install the shipped libltdl.
+case $enable_ltdl_install in
+  no) ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+      LIBLTDL="-lltdl"
+      LTDLDEPS=
+      LTDLINCL=
+      ;;
+  *)  enable_ltdl_install=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-install"
+      LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdl.la"
+      LTDLDEPS=$LIBLTDL
+      LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}"
+      ;;
+esac
+
+AC_SUBST([LIBLTDL])
+AC_SUBST([LTDLDEPS])
+AC_SUBST([LTDLINCL])
+
+# For backwards non-gettext consistent compatibility...
+INCLTDL="$LTDLINCL"
+AC_SUBST([INCLTDL])
+])# LTDL_INSTALLABLE
+
+
+# _LTDL_MODE_DISPATCH
+# -------------------
+m4_define([_LTDL_MODE_DISPATCH],
+[dnl If _LTDL_DIR is `.', then we are configuring libltdl itself:
+m4_if(_LTDL_DIR, [],
+       [],
+    dnl if _LTDL_MODE was not set already, the default value is `subproject':
+    [m4_case(m4_default(_LTDL_MODE, [subproject]),
+         [subproject], [AC_CONFIG_SUBDIRS(_LTDL_DIR)
+                         _LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"])],
+         [nonrecursive], [_LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"; lt_libobj_prefix="$lt_ltdl_dir/"])],
+         [recursive], [],
+       [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])])dnl
+dnl Be careful not to expand twice:
+m4_define([$0], [])
+])# _LTDL_MODE_DISPATCH
+
+
+# _LT_LIBOBJ(MODULE_NAME)
+# -----------------------
+# Like AC_LIBOBJ, except that MODULE_NAME goes into _LT_LIBOBJS instead
+# of into LIBOBJS.
+AC_DEFUN([_LT_LIBOBJ], [
+  m4_pattern_allow([^_LT_LIBOBJS$])
+  _LT_LIBOBJS="$_LT_LIBOBJS $1.$ac_objext"
+])# _LT_LIBOBJS
+
+
+# LTDL_INIT([OPTIONS])
+# --------------------
+# Clients of libltdl can use this macro to allow the installer to
+# choose between a shipped copy of the ltdl sources or a preinstalled
+# version of the library.  If the shipped ltdl sources are not in a
+# subdirectory named libltdl, the directory name must be given by
+# LT_CONFIG_LTDL_DIR.
+AC_DEFUN([LTDL_INIT],
+[dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+dnl We need to keep our own list of libobjs separate from our parent project,
+dnl and the easiest way to do that is redefine the AC_LIBOBJs macro while
+dnl we look for our own LIBOBJs.
+m4_pushdef([AC_LIBOBJ], m4_defn([_LT_LIBOBJ]))
+m4_pushdef([AC_LIBSOURCES])
+
+dnl If not otherwise defined, default to the 1.5.x compatible subproject mode:
+m4_if(_LTDL_MODE, [],
+        [m4_define([_LTDL_MODE], m4_default([$2], [subproject]))
+        m4_if([-1], [m4_bregexp(_LTDL_MODE, [\(subproject\|\(non\)?recursive\)])],
+                [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])])
+
+AC_ARG_WITH([included_ltdl],
+    [AS_HELP_STRING([--with-included-ltdl],
+                    [use the GNU ltdl sources included here])])
+
+if test "x$with_included_ltdl" != xyes; then
+  # We are not being forced to use the included libltdl sources, so
+  # decide whether there is a useful installed version we can use.
+  AC_CHECK_HEADER([ltdl.h],
+      [AC_CHECK_DECL([lt_dlinterface_register],
+          [AC_CHECK_LIB([ltdl], [lt_dladvise_preload],
+              [with_included_ltdl=no],
+              [with_included_ltdl=yes])],
+          [with_included_ltdl=yes],
+          [AC_INCLUDES_DEFAULT
+           #include <ltdl.h>])],
+      [with_included_ltdl=yes],
+      [AC_INCLUDES_DEFAULT]
+  )
+fi
+
+dnl If neither LT_CONFIG_LTDL_DIR, LTDL_CONVENIENCE nor LTDL_INSTALLABLE
+dnl was called yet, then for old times' sake, we assume libltdl is in an
+dnl eponymous directory:
+AC_PROVIDE_IFELSE([LT_CONFIG_LTDL_DIR], [], [_LT_CONFIG_LTDL_DIR([libltdl])])
+
+AC_ARG_WITH([ltdl_include],
+    [AS_HELP_STRING([--with-ltdl-include=DIR],
+                    [use the ltdl headers installed in DIR])])
+
+if test -n "$with_ltdl_include"; then
+  if test -f "$with_ltdl_include/ltdl.h"; then :
+  else
+    AC_MSG_ERROR([invalid ltdl include directory: `$with_ltdl_include'])
+  fi
+else
+  with_ltdl_include=no
+fi
+
+AC_ARG_WITH([ltdl_lib],
+    [AS_HELP_STRING([--with-ltdl-lib=DIR],
+                    [use the libltdl.la installed in DIR])])
+
+if test -n "$with_ltdl_lib"; then
+  if test -f "$with_ltdl_lib/libltdl.la"; then :
+  else
+    AC_MSG_ERROR([invalid ltdl library directory: `$with_ltdl_lib'])
+  fi
+else
+  with_ltdl_lib=no
+fi
+
+case ,$with_included_ltdl,$with_ltdl_include,$with_ltdl_lib, in
+  ,yes,no,no,)
+       m4_case(m4_default(_LTDL_TYPE, [convenience]),
+           [convenience], [_LTDL_CONVENIENCE],
+           [installable], [_LTDL_INSTALLABLE],
+         [m4_fatal([unknown libltdl build type: ]_LTDL_TYPE)])
+       ;;
+  ,no,no,no,)
+       # If the included ltdl is not to be used, then use the
+       # preinstalled libltdl we found.
+       AC_DEFINE([HAVE_LTDL], [1],
+         [Define this if a modern libltdl is already installed])
+       LIBLTDL=-lltdl
+       LTDLDEPS=
+       LTDLINCL=
+       ;;
+  ,no*,no,*)
+       AC_MSG_ERROR([`--with-ltdl-include' and `--with-ltdl-lib' options must be used together])
+       ;;
+  *)   with_included_ltdl=no
+       LIBLTDL="-L$with_ltdl_lib -lltdl"
+       LTDLDEPS=
+       LTDLINCL="-I$with_ltdl_include"
+       ;;
+esac
+INCLTDL="$LTDLINCL"
+
+# Report our decision...
+AC_MSG_CHECKING([where to find libltdl headers])
+AC_MSG_RESULT([$LTDLINCL])
+AC_MSG_CHECKING([where to find libltdl library])
+AC_MSG_RESULT([$LIBLTDL])
+
+_LTDL_SETUP
+
+dnl restore autoconf definition.
+m4_popdef([AC_LIBOBJ])
+m4_popdef([AC_LIBSOURCES])
+
+AC_CONFIG_COMMANDS_PRE([
+    _ltdl_libobjs=
+    _ltdl_ltlibobjs=
+    if test -n "$_LT_LIBOBJS"; then
+      # Remove the extension.
+      _lt_sed_drop_objext='s/\.o$//;s/\.obj$//'
+      for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | sed "$_lt_sed_drop_objext" | sort -u`; do
+        _ltdl_libobjs="$_ltdl_libobjs $lt_libobj_prefix$i.$ac_objext"
+        _ltdl_ltlibobjs="$_ltdl_ltlibobjs $lt_libobj_prefix$i.lo"
+      done
+    fi
+    AC_SUBST([ltdl_LIBOBJS], [$_ltdl_libobjs])
+    AC_SUBST([ltdl_LTLIBOBJS], [$_ltdl_ltlibobjs])
+])
+
+# Only expand once:
+m4_define([LTDL_INIT])
+])# LTDL_INIT
+
+# Old names:
+AU_DEFUN([AC_LIB_LTDL], [LTDL_INIT($@)])
+AU_DEFUN([AC_WITH_LTDL], [LTDL_INIT($@)])
+AU_DEFUN([LT_WITH_LTDL], [LTDL_INIT($@)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIB_LTDL], [])
+dnl AC_DEFUN([AC_WITH_LTDL], [])
+dnl AC_DEFUN([LT_WITH_LTDL], [])
+
+
+# _LTDL_SETUP
+# -----------
+# Perform all the checks necessary for compilation of the ltdl objects
+#  -- including compiler checks and header checks.  This is a public
+# interface  mainly for the benefit of libltdl's own configure.ac, most
+# other users should call LTDL_INIT instead.
+AC_DEFUN([_LTDL_SETUP],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_SYS_MODULE_EXT])dnl
+AC_REQUIRE([LT_SYS_MODULE_PATH])dnl
+AC_REQUIRE([LT_SYS_DLSEARCH_PATH])dnl
+AC_REQUIRE([LT_LIB_DLLOAD])dnl
+AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl
+AC_REQUIRE([LT_FUNC_DLSYM_USCORE])dnl
+AC_REQUIRE([LT_SYS_DLOPEN_DEPLIBS])dnl
+AC_REQUIRE([gl_FUNC_ARGZ])dnl
+
+m4_require([_LT_CHECK_OBJDIR])dnl
+m4_require([_LT_HEADER_DLFCN])dnl
+m4_require([_LT_CHECK_DLPREOPEN])dnl
+m4_require([_LT_DECL_SED])dnl
+
+dnl Don't require this, or it will be expanded earlier than the code
+dnl that sets the variables it relies on:
+_LT_ENABLE_INSTALL
+
+dnl _LTDL_MODE specific code must be called at least once:
+_LTDL_MODE_DISPATCH
+
+# In order that ltdl.c can compile, find out the first AC_CONFIG_HEADERS
+# the user used.  This is so that ltdl.h can pick up the parent projects
+# config.h file, The first file in AC_CONFIG_HEADERS must contain the
+# definitions required by ltdl.c.
+# FIXME: Remove use of undocumented AC_LIST_HEADERS (2.59 compatibility).
+AC_CONFIG_COMMANDS_PRE([dnl
+m4_pattern_allow([^LT_CONFIG_H$])dnl
+m4_ifset([AH_HEADER],
+    [LT_CONFIG_H=AH_HEADER],
+    [m4_ifset([AC_LIST_HEADERS],
+           [LT_CONFIG_H=`echo "AC_LIST_HEADERS" | $SED 's,^[[      ]]*,,;s,[[ :]].*$,,'`],
+       [])])])
+AC_SUBST([LT_CONFIG_H])
+
+AC_CHECK_HEADERS([unistd.h dl.h sys/dl.h dld.h mach-o/dyld.h dirent.h],
+       [], [], [AC_INCLUDES_DEFAULT])
+
+AC_CHECK_FUNCS([closedir opendir readdir], [], [AC_LIBOBJ([lt__dirent])])
+AC_CHECK_FUNCS([strlcat strlcpy], [], [AC_LIBOBJ([lt__strl])])
+
+m4_pattern_allow([LT_LIBEXT])dnl
+AC_DEFINE_UNQUOTED([LT_LIBEXT],["$libext"],[The archive extension])
+
+name=
+eval "lt_libprefix=\"$libname_spec\""
+m4_pattern_allow([LT_LIBPREFIX])dnl
+AC_DEFINE_UNQUOTED([LT_LIBPREFIX],["$lt_libprefix"],[The archive prefix])
+
+name=ltdl
+eval "LTDLOPEN=\"$libname_spec\""
+AC_SUBST([LTDLOPEN])
+])# _LTDL_SETUP
+
+
+# _LT_ENABLE_INSTALL
+# ------------------
+m4_define([_LT_ENABLE_INSTALL],
+[AC_ARG_ENABLE([ltdl-install],
+    [AS_HELP_STRING([--enable-ltdl-install], [install libltdl])])
+
+case ,${enable_ltdl_install},${enable_ltdl_convenience} in
+  *yes*) ;;
+  *) enable_ltdl_convenience=yes ;;
+esac
+
+m4_ifdef([AM_CONDITIONAL],
+[AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno)
+ AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno)])
+])# _LT_ENABLE_INSTALL
+
+
+# LT_SYS_DLOPEN_DEPLIBS
+# ---------------------
+AC_DEFUN([LT_SYS_DLOPEN_DEPLIBS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_CACHE_CHECK([whether deplibs are loaded by dlopen],
+  [lt_cv_sys_dlopen_deplibs],
+  [# PORTME does your system automatically load deplibs for dlopen?
+  # or its logical equivalent (e.g. shl_load for HP-UX < 11)
+  # For now, we just catch OSes we know something about -- in the
+  # future, we'll try test this programmatically.
+  lt_cv_sys_dlopen_deplibs=unknown
+  case $host_os in
+  aix3*|aix4.1.*|aix4.2.*)
+    # Unknown whether this is true for these versions of AIX, but
+    # we want this `case' here to explicitly catch those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  aix[[4-9]]*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  amigaos*)
+    case $host_cpu in
+    powerpc)
+      lt_cv_sys_dlopen_deplibs=no
+      ;;
+    esac
+    ;;
+  darwin*)
+    # Assuming the user has installed a libdl from somewhere, this is true
+    # If you are looking for one http://www.opendarwin.org/projects/dlcompat
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  freebsd* | dragonfly*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  gnu* | linux* | k*bsd*-gnu | kopensolaris*-gnu)
+    # GNU and its variants, using gnu ld.so (Glibc)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  hpux10*|hpux11*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  interix*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  irix[[12345]]*|irix6.[[01]]*)
+    # Catch all versions of IRIX before 6.2, and indicate that we don't
+    # know how it worked for any of those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  irix*)
+    # The case above catches anything before 6.2, and it's known that
+    # at 6.2 and later dlopen does load deplibs.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  openbsd*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  osf[[1234]]*)
+    # dlopen did load deplibs (at least at 4.x), but until the 5.x series,
+    # it did *not* use an RPATH in a shared library to find objects the
+    # library depends on, so we explicitly say `no'.
+    lt_cv_sys_dlopen_deplibs=no
+    ;;
+  osf5.0|osf5.0a|osf5.1)
+    # dlopen *does* load deplibs and with the right loader patch applied
+    # it even uses RPATH in a shared library to search for shared objects
+    # that the library depends on, but there's no easy way to know if that
+    # patch is installed.  Since this is the case, all we can really
+    # say is unknown -- it depends on the patch being installed.  If
+    # it is, this changes to `yes'.  Without it, it would be `no'.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  osf*)
+    # the two cases above should catch all versions of osf <= 5.1.  Read
+    # the comments above for what we know about them.
+    # At > 5.1, deplibs are loaded *and* any RPATH in a shared library
+    # is used to find them so we can finally say `yes'.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  qnx*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  solaris*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  esac
+  ])
+if test "$lt_cv_sys_dlopen_deplibs" != yes; then
+ AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1],
+    [Define if the OS needs help to load dependent libraries for dlopen().])
+fi
+])# LT_SYS_DLOPEN_DEPLIBS
+
+# Old name:
+AU_ALIAS([AC_LTDL_SYS_DLOPEN_DEPLIBS], [LT_SYS_DLOPEN_DEPLIBS])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], [])
+
+
+# LT_SYS_MODULE_EXT
+# -----------------
+AC_DEFUN([LT_SYS_MODULE_EXT],
+[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl
+AC_CACHE_CHECK([which extension is used for runtime loadable modules],
+  [libltdl_cv_shlibext],
+[
+module=yes
+eval libltdl_cv_shlibext=$shrext_cmds
+module=no
+eval libltdl_cv_shrext=$shrext_cmds
+  ])
+if test -n "$libltdl_cv_shlibext"; then
+  m4_pattern_allow([LT_MODULE_EXT])dnl
+  AC_DEFINE_UNQUOTED([LT_MODULE_EXT], ["$libltdl_cv_shlibext"],
+    [Define to the extension used for runtime loadable modules, say, ".so".])
+fi
+if test "$libltdl_cv_shrext" != "$libltdl_cv_shlibext"; then
+  m4_pattern_allow([LT_SHARED_EXT])dnl
+  AC_DEFINE_UNQUOTED([LT_SHARED_EXT], ["$libltdl_cv_shrext"],
+    [Define to the shared library suffix, say, ".dylib".])
+fi
+])# LT_SYS_MODULE_EXT
+
+# Old name:
+AU_ALIAS([AC_LTDL_SHLIBEXT], [LT_SYS_MODULE_EXT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SHLIBEXT], [])
+
+
+# LT_SYS_MODULE_PATH
+# ------------------
+AC_DEFUN([LT_SYS_MODULE_PATH],
+[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl
+AC_CACHE_CHECK([which variable specifies run-time module search path],
+  [lt_cv_module_path_var], [lt_cv_module_path_var="$shlibpath_var"])
+if test -n "$lt_cv_module_path_var"; then
+  m4_pattern_allow([LT_MODULE_PATH_VAR])dnl
+  AC_DEFINE_UNQUOTED([LT_MODULE_PATH_VAR], ["$lt_cv_module_path_var"],
+    [Define to the name of the environment variable that determines the run-time module search path.])
+fi
+])# LT_SYS_MODULE_PATH
+
+# Old name:
+AU_ALIAS([AC_LTDL_SHLIBPATH], [LT_SYS_MODULE_PATH])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SHLIBPATH], [])
+
+
+# LT_SYS_DLSEARCH_PATH
+# --------------------
+AC_DEFUN([LT_SYS_DLSEARCH_PATH],
+[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl
+AC_CACHE_CHECK([for the default library search path],
+  [lt_cv_sys_dlsearch_path],
+  [lt_cv_sys_dlsearch_path="$sys_lib_dlsearch_path_spec"])
+if test -n "$lt_cv_sys_dlsearch_path"; then
+  sys_dlsearch_path=
+  for dir in $lt_cv_sys_dlsearch_path; do
+    if test -z "$sys_dlsearch_path"; then
+      sys_dlsearch_path="$dir"
+    else
+      sys_dlsearch_path="$sys_dlsearch_path$PATH_SEPARATOR$dir"
+    fi
+  done
+  m4_pattern_allow([LT_DLSEARCH_PATH])dnl
+  AC_DEFINE_UNQUOTED([LT_DLSEARCH_PATH], ["$sys_dlsearch_path"],
+    [Define to the system default library search path.])
+fi
+])# LT_SYS_DLSEARCH_PATH
+
+# Old name:
+AU_ALIAS([AC_LTDL_SYSSEARCHPATH], [LT_SYS_DLSEARCH_PATH])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SYSSEARCHPATH], [])
+
+
+# _LT_CHECK_DLPREOPEN
+# -------------------
+m4_defun([_LT_CHECK_DLPREOPEN],
+[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen],
+  [libltdl_cv_preloaded_symbols],
+  [if test -n "$lt_cv_sys_global_symbol_pipe"; then
+    libltdl_cv_preloaded_symbols=yes
+  else
+    libltdl_cv_preloaded_symbols=no
+  fi
+  ])
+if test x"$libltdl_cv_preloaded_symbols" = xyes; then
+  AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1],
+    [Define if libtool can extract symbol lists from object files.])
+fi
+])# _LT_CHECK_DLPREOPEN
+
+
+# LT_LIB_DLLOAD
+# -------------
+AC_DEFUN([LT_LIB_DLLOAD],
+[m4_pattern_allow([^LT_DLLOADERS$])
+LT_DLLOADERS=
+AC_SUBST([LT_DLLOADERS])
+
+AC_LANG_PUSH([C])
+
+LIBADD_DLOPEN=
+AC_SEARCH_LIBS([dlopen], [dl],
+       [AC_DEFINE([HAVE_LIBDL], [1],
+                  [Define if you have the libdl library or equivalent.])
+       if test "$ac_cv_search_dlopen" != "none required" ; then
+         LIBADD_DLOPEN="-ldl"
+       fi
+       libltdl_cv_lib_dl_dlopen="yes"
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"],
+    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H
+#  include <dlfcn.h>
+#endif
+    ]], [[dlopen(0, 0);]])],
+           [AC_DEFINE([HAVE_LIBDL], [1],
+                      [Define if you have the libdl library or equivalent.])
+           libltdl_cv_func_dlopen="yes"
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"],
+       [AC_CHECK_LIB([svld], [dlopen],
+               [AC_DEFINE([HAVE_LIBDL], [1],
+                        [Define if you have the libdl library or equivalent.])
+               LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes"
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"])])])
+if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes
+then
+  lt_save_LIBS="$LIBS"
+  LIBS="$LIBS $LIBADD_DLOPEN"
+  AC_CHECK_FUNCS([dlerror])
+  LIBS="$lt_save_LIBS"
+fi
+AC_SUBST([LIBADD_DLOPEN])
+
+LIBADD_SHL_LOAD=
+AC_CHECK_FUNC([shl_load],
+       [AC_DEFINE([HAVE_SHL_LOAD], [1],
+                  [Define if you have the shl_load function.])
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"],
+    [AC_CHECK_LIB([dld], [shl_load],
+           [AC_DEFINE([HAVE_SHL_LOAD], [1],
+                      [Define if you have the shl_load function.])
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"
+           LIBADD_SHL_LOAD="-ldld"])])
+AC_SUBST([LIBADD_SHL_LOAD])
+
+case $host_os in
+darwin[[1567]].*)
+# We only want this for pre-Mac OS X 10.4.
+  AC_CHECK_FUNC([_dyld_func_lookup],
+       [AC_DEFINE([HAVE_DYLD], [1],
+                  [Define if you have the _dyld_func_lookup function.])
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dyld.la"])
+  ;;
+beos*)
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}load_add_on.la"
+  ;;
+cygwin* | mingw* | os2* | pw32*)
+  AC_CHECK_DECLS([cygwin_conv_path], [], [], [[#include <sys/cygwin.h>]])
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}loadlibrary.la"
+  ;;
+esac
+
+AC_CHECK_LIB([dld], [dld_link],
+       [AC_DEFINE([HAVE_DLD], [1],
+                  [Define if you have the GNU dld library.])
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dld_link.la"])
+AC_SUBST([LIBADD_DLD_LINK])
+
+m4_pattern_allow([^LT_DLPREOPEN$])
+LT_DLPREOPEN=
+if test -n "$LT_DLLOADERS"
+then
+  for lt_loader in $LT_DLLOADERS; do
+    LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen $lt_loader "
+  done
+  AC_DEFINE([HAVE_LIBDLLOADER], [1],
+            [Define if libdlloader will be built on this platform])
+fi
+AC_SUBST([LT_DLPREOPEN])
+
+dnl This isn't used anymore, but set it for backwards compatibility
+LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD"
+AC_SUBST([LIBADD_DL])
+
+AC_LANG_POP
+])# LT_LIB_DLLOAD
+
+# Old name:
+AU_ALIAS([AC_LTDL_DLLIB], [LT_LIB_DLLOAD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_DLLIB], [])
+
+
+# LT_SYS_SYMBOL_USCORE
+# --------------------
+# does the compiler prefix global symbols with an underscore?
+AC_DEFUN([LT_SYS_SYMBOL_USCORE],
+[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+AC_CACHE_CHECK([for _ prefix in compiled symbols],
+  [lt_cv_sys_symbol_underscore],
+  [lt_cv_sys_symbol_underscore=no
+  cat > conftest.$ac_ext <<_LT_EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+_LT_EOF
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
+      # See whether the symbols have a leading underscore.
+      if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+        lt_cv_sys_symbol_underscore=yes
+      else
+        if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+         :
+        else
+         echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD
+        fi
+      fi
+    else
+      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.c >&AS_MESSAGE_LOG_FD
+  fi
+  rm -rf conftest*
+  ])
+  sys_symbol_underscore=$lt_cv_sys_symbol_underscore
+  AC_SUBST([sys_symbol_underscore])
+])# LT_SYS_SYMBOL_USCORE
+
+# Old name:
+AU_ALIAS([AC_LTDL_SYMBOL_USCORE], [LT_SYS_SYMBOL_USCORE])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SYMBOL_USCORE], [])
+
+
+# LT_FUNC_DLSYM_USCORE
+# --------------------
+AC_DEFUN([LT_FUNC_DLSYM_USCORE],
+[AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl
+if test x"$lt_cv_sys_symbol_underscore" = xyes; then
+  if test x"$libltdl_cv_func_dlopen" = xyes ||
+     test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then
+       AC_CACHE_CHECK([whether we have to add an underscore for dlsym],
+         [libltdl_cv_need_uscore],
+         [libltdl_cv_need_uscore=unknown
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $LIBADD_DLOPEN"
+         _LT_TRY_DLOPEN_SELF(
+           [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes],
+           [],                          [libltdl_cv_need_uscore=cross])
+         LIBS="$save_LIBS"
+       ])
+  fi
+fi
+
+if test x"$libltdl_cv_need_uscore" = xyes; then
+  AC_DEFINE([NEED_USCORE], [1],
+    [Define if dlsym() requires a leading underscore in symbol names.])
+fi
+])# LT_FUNC_DLSYM_USCORE
+
+# Old name:
+AU_ALIAS([AC_LTDL_DLSYM_USCORE], [LT_FUNC_DLSYM_USCORE])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_DLSYM_USCORE], [])
+
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
+#   Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 7 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+           [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+                     [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl `shared' nor `disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+                  [_LT_ENABLE_FAST_INSTALL])
+  ])
+])# _LT_SET_OPTIONS
+
+
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+       [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+       [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+       [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+       [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+        [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+       [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for lt_pkg in $withval; do
+       IFS="$lt_save_ifs"
+       if test "X$lt_pkg" = "X$lt_p"; then
+         pic_mode=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+                [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+                [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+                [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+                [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+                [m4_define([_LTDL_TYPE], [convenience])])
+
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+          m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+            [m4_foreach([_Lt_suffix],
+               ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+       [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+         [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+                [lt_append([$1], [$2], [$3])$4],
+                [$5])],
+         [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+       m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+       [$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+                     [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
+
+# ltversion.m4 -- version numbers                      -*- Autoconf -*-
+#
+#   Copyright (C) 2004 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 3337 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.2])
+m4_define([LT_PACKAGE_REVISION], [1.3337])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.2'
+macro_revision='1.3337'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
+
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],  [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],             [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],        [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],         [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],    [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],           [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],             [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],    [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],           [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],       [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],               [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],        [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],    [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],    [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],         [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],            [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],  [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],             [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],            [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],    [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],   [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],          [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],            [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],           [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],  [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],    [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],          [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],          [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],                [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],     [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],          [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],   [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],           [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],           [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],           [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],  [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],      [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],    [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],    [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],    [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],     [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],         [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],       [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],        [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP],                [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],        [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH],   [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77],              [AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC],               [AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX],              [AC_DEFUN([_LT_PROG_CXX])])
+
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+# 
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_default([$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes ],
+                    [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+       AC_MSG_RESULT([no])
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+        else 
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+        ])
+elif test $pkg_failed = untried; then
+       AC_MSG_RESULT([no])
+       m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+        ])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.14'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.14.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.14.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
+      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
+      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
+      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                    [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+  [--enable-dependency-tracking],
+  [do not reject slow dependency extractors])
+AS_HELP_STRING(
+  [--disable-dependency-tracking],
+  [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each '.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+             [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+  [ok:ok],,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+             [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+                            [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                 [_AM_DEPENDENCIES([CC])],
+                 [m4_define([AC_PROG_CC],
+                            m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                 [_AM_DEPENDENCIES([CXX])],
+                 [m4_define([AC_PROG_CXX],
+                            m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+                 [_AM_DEPENDENCIES([OBJC])],
+                 [m4_define([AC_PROG_OBJC],
+                            m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+                 [_AM_DEPENDENCIES([OBJCXX])],
+                 [m4_define([AC_PROG_OBJCXX],
+                            m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.                 -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \   ]]*)
+    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$[*]" = "X"; then
+       # -L didn't work.
+       set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$[*]" != "X $srcdir/configure conftest.file" \
+       && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+       # If neither matched, then we have a broken ls.  This can happen
+       # if, for instance, CONFIG_SHELL is bash and it inherits a
+       # broken ls alias from the environment.  This has actually
+       # happened.  Such a system could not be considered "sane".
+       AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment])
+     fi
+     if test "$[2]" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+  [AC_MSG_CHECKING([that generated files are newer than configure])
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+       @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/bindings/Makefile.am b/bindings/Makefile.am
new file mode 100644 (file)
index 0000000..07373e8
--- /dev/null
@@ -0,0 +1,69 @@
+SUBDIRS =
+
+if BUILD_WITH_JAVA
+SUBDIRS += java
+endif
+
+EXTRA_DIST = perl/Makefile.PL \
+            perl/uninstall_mod.pl \
+            perl/lib/Collectd.pm \
+            perl/lib/Collectd/Unixsock.pm \
+            perl/lib/Collectd/Plugins/Monitorus.pm \
+            perl/lib/Collectd/Plugins/OpenVZ.pm
+
+CLEANFILES = \
+       buildperl/Collectd.pm \
+       buildperl/Collectd/Plugins/OpenVZ.pm \
+       buildperl/Collectd/Unixsock.pm \
+       buildperl/Makefile.PL \
+       .perl-directory-stamp
+
+DISTCLEANFILES = \
+       buildperl/Collectd.pm \
+       buildperl/Collectd/Plugins/OpenVZ.pm \
+       buildperl/Collectd/Unixsock.pm \
+       buildperl/Makefile.PL \
+       .perl-directory-stamp
+
+all-local: @PERL_BINDINGS@
+
+
+install-exec-local:
+       [ ! -f buildperl/Makefile ] || ( cd buildperl && $(MAKE) install )
+
+# Perl 'make uninstall' does not work as well as wanted.
+# So we do the work here.
+uninstall-local:
+       @PERL@ -I$(DESTDIR)$(prefix) $(srcdir)/perl/uninstall_mod.pl Collectd
+       find $(DESTDIR)$(prefix) -name "perllocal.pod" -exec rm {} \;
+
+clean-local:
+       rm -rf buildperl
+
+perl: buildperl/Makefile
+       cd buildperl && $(MAKE)
+
+buildperl/Makefile: .perl-directory-stamp buildperl/Makefile.PL \
+       $(top_builddir)/config.status
+       @# beautify the output a bit
+       @echo 'cd buildperl && @PERL@ Makefile.PL @PERL_BINDINGS_OPTIONS@'
+       @cd buildperl && ( if ! @PERL@ Makefile.PL @PERL_BINDINGS_OPTIONS@; then \
+                       echo ""; \
+                       echo 'Check whether you have set $$PERL_MM_OPT in your environment and try using ./configure --with-perl-bindings=""'; \
+                       echo ""; \
+               fi )
+
+buildperl/Makefile.PL: .perl-directory-stamp $(top_builddir)/config.status
+
+.perl-directory-stamp:
+       if test ! -d buildperl; then \
+         mkdir -p buildperl/Collectd/Plugins; \
+         cp $(srcdir)/perl/lib/Collectd.pm buildperl/; \
+         cp $(srcdir)/perl/Makefile.PL buildperl/; \
+         cp $(srcdir)/perl/lib/Collectd/Unixsock.pm buildperl/Collectd/; \
+         cp $(srcdir)/perl/lib/Collectd/Plugins/OpenVZ.pm buildperl/Collectd/Plugins/; \
+       fi
+       touch $@
+
+.PHONY: perl
+
diff --git a/bindings/Makefile.in b/bindings/Makefile.in
new file mode 100644 (file)
index 0000000..4e4265d
--- /dev/null
@@ -0,0 +1,821 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@BUILD_WITH_JAVA_TRUE@am__append_1 = java
+subdir = bindings
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+       ctags-recursive dvi-recursive html-recursive info-recursive \
+       install-data-recursive install-dvi-recursive \
+       install-exec-recursive install-html-recursive \
+       install-info-recursive install-pdf-recursive \
+       install-ps-recursive install-recursive installcheck-recursive \
+       installdirs-recursive pdf-recursive ps-recursive \
+       tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+       distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = java
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_WITH_LIBAQUAERO5_CFLAGS = @BUILD_WITH_LIBAQUAERO5_CFLAGS@
+BUILD_WITH_LIBAQUAERO5_LDFLAGS = @BUILD_WITH_LIBAQUAERO5_LDFLAGS@
+BUILD_WITH_LIBATASMART_CPPFLAGS = @BUILD_WITH_LIBATASMART_CPPFLAGS@
+BUILD_WITH_LIBATASMART_LDFLAGS = @BUILD_WITH_LIBATASMART_LDFLAGS@
+BUILD_WITH_LIBATASMART_LIBS = @BUILD_WITH_LIBATASMART_LIBS@
+BUILD_WITH_LIBCURL_CFLAGS = @BUILD_WITH_LIBCURL_CFLAGS@
+BUILD_WITH_LIBCURL_LIBS = @BUILD_WITH_LIBCURL_LIBS@
+BUILD_WITH_LIBDBI_CPPFLAGS = @BUILD_WITH_LIBDBI_CPPFLAGS@
+BUILD_WITH_LIBDBI_LDFLAGS = @BUILD_WITH_LIBDBI_LDFLAGS@
+BUILD_WITH_LIBDBI_LIBS = @BUILD_WITH_LIBDBI_LIBS@
+BUILD_WITH_LIBHAL_CFLAGS = @BUILD_WITH_LIBHAL_CFLAGS@
+BUILD_WITH_LIBHAL_LIBS = @BUILD_WITH_LIBHAL_LIBS@
+BUILD_WITH_LIBHIREDIS_CPPFLAGS = @BUILD_WITH_LIBHIREDIS_CPPFLAGS@
+BUILD_WITH_LIBHIREDIS_LDFLAGS = @BUILD_WITH_LIBHIREDIS_LDFLAGS@
+BUILD_WITH_LIBIPTC_CPPFLAGS = @BUILD_WITH_LIBIPTC_CPPFLAGS@
+BUILD_WITH_LIBIPTC_LDFLAGS = @BUILD_WITH_LIBIPTC_LDFLAGS@
+BUILD_WITH_LIBLDAP_CPPFLAGS = @BUILD_WITH_LIBLDAP_CPPFLAGS@
+BUILD_WITH_LIBLDAP_LDFLAGS = @BUILD_WITH_LIBLDAP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_CPPFLAGS = @BUILD_WITH_LIBLVM2APP_CPPFLAGS@
+BUILD_WITH_LIBLVM2APP_LDFLAGS = @BUILD_WITH_LIBLVM2APP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_LIBS = @BUILD_WITH_LIBLVM2APP_LIBS@
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS = @BUILD_WITH_LIBMEMCACHED_CPPFLAGS@
+BUILD_WITH_LIBMEMCACHED_LDFLAGS = @BUILD_WITH_LIBMEMCACHED_LDFLAGS@
+BUILD_WITH_LIBMEMCACHED_LIBS = @BUILD_WITH_LIBMEMCACHED_LIBS@
+BUILD_WITH_LIBMNL_CFLAGS = @BUILD_WITH_LIBMNL_CFLAGS@
+BUILD_WITH_LIBMNL_LIBS = @BUILD_WITH_LIBMNL_LIBS@
+BUILD_WITH_LIBMODBUS_CFLAGS = @BUILD_WITH_LIBMODBUS_CFLAGS@
+BUILD_WITH_LIBMODBUS_LIBS = @BUILD_WITH_LIBMODBUS_LIBS@
+BUILD_WITH_LIBMONGOC_CPPFLAGS = @BUILD_WITH_LIBMONGOC_CPPFLAGS@
+BUILD_WITH_LIBMONGOC_LDFLAGS = @BUILD_WITH_LIBMONGOC_LDFLAGS@
+BUILD_WITH_LIBMYSQL_CFLAGS = @BUILD_WITH_LIBMYSQL_CFLAGS@
+BUILD_WITH_LIBMYSQL_LIBS = @BUILD_WITH_LIBMYSQL_LIBS@
+BUILD_WITH_LIBOPING_CPPFLAGS = @BUILD_WITH_LIBOPING_CPPFLAGS@
+BUILD_WITH_LIBOPING_LDFLAGS = @BUILD_WITH_LIBOPING_LDFLAGS@
+BUILD_WITH_LIBOWCAPI_CPPFLAGS = @BUILD_WITH_LIBOWCAPI_CPPFLAGS@
+BUILD_WITH_LIBOWCAPI_LIBS = @BUILD_WITH_LIBOWCAPI_LIBS@
+BUILD_WITH_LIBPQ_CPPFLAGS = @BUILD_WITH_LIBPQ_CPPFLAGS@
+BUILD_WITH_LIBPQ_LDFLAGS = @BUILD_WITH_LIBPQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS = @BUILD_WITH_LIBRABBITMQ_CPPFLAGS@
+BUILD_WITH_LIBRABBITMQ_LDFLAGS = @BUILD_WITH_LIBRABBITMQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_LIBS = @BUILD_WITH_LIBRABBITMQ_LIBS@
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS = @BUILD_WITH_LIBRDKAFKA_CPPFLAGS@
+BUILD_WITH_LIBRDKAFKA_LDFLAGS = @BUILD_WITH_LIBRDKAFKA_LDFLAGS@
+BUILD_WITH_LIBRDKAFKA_LIBS = @BUILD_WITH_LIBRDKAFKA_LIBS@
+BUILD_WITH_LIBROUTEROS_CPPFLAGS = @BUILD_WITH_LIBROUTEROS_CPPFLAGS@
+BUILD_WITH_LIBROUTEROS_LDFLAGS = @BUILD_WITH_LIBROUTEROS_LDFLAGS@
+BUILD_WITH_LIBRRD_CFLAGS = @BUILD_WITH_LIBRRD_CFLAGS@
+BUILD_WITH_LIBRRD_LDFLAGS = @BUILD_WITH_LIBRRD_LDFLAGS@
+BUILD_WITH_LIBSENSORS_CFLAGS = @BUILD_WITH_LIBSENSORS_CFLAGS@
+BUILD_WITH_LIBSENSORS_LDFLAGS = @BUILD_WITH_LIBSENSORS_LDFLAGS@
+BUILD_WITH_LIBSIGROK_CFLAGS = @BUILD_WITH_LIBSIGROK_CFLAGS@
+BUILD_WITH_LIBSIGROK_LDFLAGS = @BUILD_WITH_LIBSIGROK_LDFLAGS@
+BUILD_WITH_LIBSNMP_CFLAGS = @BUILD_WITH_LIBSNMP_CFLAGS@
+BUILD_WITH_LIBSNMP_LIBS = @BUILD_WITH_LIBSNMP_LIBS@
+BUILD_WITH_LIBSTATGRAB_CFLAGS = @BUILD_WITH_LIBSTATGRAB_CFLAGS@
+BUILD_WITH_LIBSTATGRAB_LDFLAGS = @BUILD_WITH_LIBSTATGRAB_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LIBS = @BUILD_WITH_LIBTOKYOTYRANT_LIBS@
+BUILD_WITH_LIBUDEV_CFLAGS = @BUILD_WITH_LIBUDEV_CFLAGS@
+BUILD_WITH_LIBUDEV_LDFLAGS = @BUILD_WITH_LIBUDEV_LDFLAGS@
+BUILD_WITH_LIBUPSCLIENT_CFLAGS = @BUILD_WITH_LIBUPSCLIENT_CFLAGS@
+BUILD_WITH_LIBUPSCLIENT_LIBS = @BUILD_WITH_LIBUPSCLIENT_LIBS@
+BUILD_WITH_LIBVARNISH_CFLAGS = @BUILD_WITH_LIBVARNISH_CFLAGS@
+BUILD_WITH_LIBVARNISH_LIBS = @BUILD_WITH_LIBVARNISH_LIBS@
+BUILD_WITH_LIBVIRT_CFLAGS = @BUILD_WITH_LIBVIRT_CFLAGS@
+BUILD_WITH_LIBVIRT_LIBS = @BUILD_WITH_LIBVIRT_LIBS@
+BUILD_WITH_LIBXML2_CFLAGS = @BUILD_WITH_LIBXML2_CFLAGS@
+BUILD_WITH_LIBXML2_LIBS = @BUILD_WITH_LIBXML2_LIBS@
+BUILD_WITH_LIBXMMS_CFLAGS = @BUILD_WITH_LIBXMMS_CFLAGS@
+BUILD_WITH_LIBXMMS_LIBS = @BUILD_WITH_LIBXMMS_LIBS@
+BUILD_WITH_LIBYAJL_CPPFLAGS = @BUILD_WITH_LIBYAJL_CPPFLAGS@
+BUILD_WITH_LIBYAJL_LDFLAGS = @BUILD_WITH_LIBYAJL_LDFLAGS@
+BUILD_WITH_LIBYAJL_LIBS = @BUILD_WITH_LIBYAJL_LIBS@
+BUILD_WITH_MIC_CPPFLAGS = @BUILD_WITH_MIC_CPPFLAGS@
+BUILD_WITH_MIC_LDADD = @BUILD_WITH_MIC_LDADD@
+BUILD_WITH_MIC_LIBPATH = @BUILD_WITH_MIC_LIBPATH@
+BUILD_WITH_OPENIPMI_CFLAGS = @BUILD_WITH_OPENIPMI_CFLAGS@
+BUILD_WITH_OPENIPMI_LIBS = @BUILD_WITH_OPENIPMI_LIBS@
+BUILD_WITH_ORACLE_CFLAGS = @BUILD_WITH_ORACLE_CFLAGS@
+BUILD_WITH_ORACLE_LIBS = @BUILD_WITH_ORACLE_LIBS@
+BUILD_WITH_PYTHON_CPPFLAGS = @BUILD_WITH_PYTHON_CPPFLAGS@
+BUILD_WITH_PYTHON_LDFLAGS = @BUILD_WITH_PYTHON_LDFLAGS@
+BUILD_WITH_PYTHON_LIBS = @BUILD_WITH_PYTHON_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_LOG_LEVEL = @DEFAULT_LOG_LEVEL@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GANGLIA_CPPFLAGS = @GANGLIA_CPPFLAGS@
+GANGLIA_LDFLAGS = @GANGLIA_LDFLAGS@
+GANGLIA_LIBS = @GANGLIA_LIBS@
+GCRYPT_CPPFLAGS = @GCRYPT_CPPFLAGS@
+GCRYPT_LDFLAGS = @GCRYPT_LDFLAGS@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVA_CFLAGS = @JAVA_CFLAGS@
+JAVA_CPPFLAGS = @JAVA_CPPFLAGS@
+JAVA_LDFLAGS = @JAVA_LDFLAGS@
+JAVA_LIBS = @JAVA_LIBS@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_DIR = @KERNEL_DIR@
+LCC_VERSION_EXTRA = @LCC_VERSION_EXTRA@
+LCC_VERSION_MAJOR = @LCC_VERSION_MAJOR@
+LCC_VERSION_MINOR = @LCC_VERSION_MINOR@
+LCC_VERSION_PATCH = @LCC_VERSION_PATCH@
+LCC_VERSION_STRING = @LCC_VERSION_STRING@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBNETAPP_CPPFLAGS = @LIBNETAPP_CPPFLAGS@
+LIBNETAPP_LDFLAGS = @LIBNETAPP_LDFLAGS@
+LIBNETAPP_LIBS = @LIBNETAPP_LIBS@
+LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
+LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOAD_PLUGIN_CSV = @LOAD_PLUGIN_CSV@
+LOAD_PLUGIN_LOGFILE = @LOAD_PLUGIN_LOGFILE@
+LOAD_PLUGIN_LOG_LOGSTASH = @LOAD_PLUGIN_LOG_LOGSTASH@
+LOAD_PLUGIN_NETWORK = @LOAD_PLUGIN_NETWORK@
+LOAD_PLUGIN_RRDTOOL = @LOAD_PLUGIN_RRDTOOL@
+LOAD_PLUGIN_SYSLOG = @LOAD_PLUGIN_SYSLOG@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_BINDINGS = @PERL_BINDINGS@
+PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_LIBS = @PERL_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_protoc_c = @have_protoc_c@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = $(am__append_1)
+EXTRA_DIST = perl/Makefile.PL \
+            perl/uninstall_mod.pl \
+            perl/lib/Collectd.pm \
+            perl/lib/Collectd/Unixsock.pm \
+            perl/lib/Collectd/Plugins/Monitorus.pm \
+            perl/lib/Collectd/Plugins/OpenVZ.pm
+
+CLEANFILES = \
+       buildperl/Collectd.pm \
+       buildperl/Collectd/Plugins/OpenVZ.pm \
+       buildperl/Collectd/Unixsock.pm \
+       buildperl/Makefile.PL \
+       .perl-directory-stamp
+
+DISTCLEANFILES = \
+       buildperl/Collectd.pm \
+       buildperl/Collectd/Plugins/OpenVZ.pm \
+       buildperl/Collectd/Unixsock.pm \
+       buildperl/Makefile.PL \
+       .perl-directory-stamp
+
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bindings/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign bindings/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+       @fail=; \
+       if $(am__make_keepgoing); then \
+         failcom='fail=yes'; \
+       else \
+         failcom='exit 1'; \
+       fi; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           $(am__make_dryrun) \
+             || test -d "$(distdir)/$$subdir" \
+             || $(MKDIR_P) "$(distdir)/$$subdir" \
+             || exit 1; \
+           dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+           $(am__relativize); \
+           new_distdir=$$reldir; \
+           dir1=$$subdir; dir2="$(top_distdir)"; \
+           $(am__relativize); \
+           new_top_distdir=$$reldir; \
+           echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+           echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+           ($(am__cd) $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$new_top_distdir" \
+               distdir="$$new_distdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               am__skip_mode_fix=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-recursive
+all-am: Makefile all-local
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-exec-local
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-local
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \
+       check check-am clean clean-generic clean-libtool clean-local \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-exec-local install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       installdirs-am maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+       ps ps-am tags tags-am uninstall uninstall-am uninstall-local
+
+
+all-local: @PERL_BINDINGS@
+
+install-exec-local:
+       [ ! -f buildperl/Makefile ] || ( cd buildperl && $(MAKE) install )
+
+# Perl 'make uninstall' does not work as well as wanted.
+# So we do the work here.
+uninstall-local:
+       @PERL@ -I$(DESTDIR)$(prefix) $(srcdir)/perl/uninstall_mod.pl Collectd
+       find $(DESTDIR)$(prefix) -name "perllocal.pod" -exec rm {} \;
+
+clean-local:
+       rm -rf buildperl
+
+perl: buildperl/Makefile
+       cd buildperl && $(MAKE)
+
+buildperl/Makefile: .perl-directory-stamp buildperl/Makefile.PL \
+       $(top_builddir)/config.status
+       @# beautify the output a bit
+       @echo 'cd buildperl && @PERL@ Makefile.PL @PERL_BINDINGS_OPTIONS@'
+       @cd buildperl && ( if ! @PERL@ Makefile.PL @PERL_BINDINGS_OPTIONS@; then \
+                       echo ""; \
+                       echo 'Check whether you have set $$PERL_MM_OPT in your environment and try using ./configure --with-perl-bindings=""'; \
+                       echo ""; \
+               fi )
+
+buildperl/Makefile.PL: .perl-directory-stamp $(top_builddir)/config.status
+
+.perl-directory-stamp:
+       if test ! -d buildperl; then \
+         mkdir -p buildperl/Collectd/Plugins; \
+         cp $(srcdir)/perl/lib/Collectd.pm buildperl/; \
+         cp $(srcdir)/perl/Makefile.PL buildperl/; \
+         cp $(srcdir)/perl/lib/Collectd/Unixsock.pm buildperl/Collectd/; \
+         cp $(srcdir)/perl/lib/Collectd/Plugins/OpenVZ.pm buildperl/Collectd/Plugins/; \
+       fi
+       touch $@
+
+.PHONY: perl
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bindings/java/Makefile.am b/bindings/java/Makefile.am
new file mode 100644 (file)
index 0000000..8d2e49d
--- /dev/null
@@ -0,0 +1,53 @@
+EXTRA_DIST = org/collectd/api/CollectdConfigInterface.java \
+            org/collectd/api/CollectdFlushInterface.java \
+            org/collectd/api/CollectdInitInterface.java \
+            org/collectd/api/Collectd.java \
+            org/collectd/api/CollectdLogInterface.java \
+            org/collectd/api/CollectdMatchFactoryInterface.java \
+            org/collectd/api/CollectdMatchInterface.java \
+            org/collectd/api/CollectdNotificationInterface.java \
+            org/collectd/api/CollectdReadInterface.java \
+            org/collectd/api/CollectdShutdownInterface.java \
+            org/collectd/api/CollectdTargetFactoryInterface.java \
+            org/collectd/api/CollectdTargetInterface.java \
+            org/collectd/api/CollectdWriteInterface.java \
+            org/collectd/api/DataSet.java \
+            org/collectd/api/DataSource.java \
+            org/collectd/api/Notification.java \
+            org/collectd/api/OConfigItem.java \
+            org/collectd/api/OConfigValue.java \
+            org/collectd/api/PluginData.java \
+            org/collectd/api/ValueList.java \
+            org/collectd/java/GenericJMXConfConnection.java \
+            org/collectd/java/GenericJMXConfMBean.java \
+            org/collectd/java/GenericJMXConfValue.java \
+            org/collectd/java/GenericJMX.java \
+            org/collectd/java/JMXMemory.java
+
+java-build-stamp: $(srcdir)/org/collectd/api/*.java $(srcdir)/org/collectd/java/*.java
+       $(JAVAC) -d "." "$(srcdir)/org/collectd/api"/*.java
+       $(JAVAC) -d "." "$(srcdir)/org/collectd/java"/*.java
+       mkdir -p .libs
+       $(JAR) cf .libs/collectd-api.jar "org/collectd/api"/*.class
+       $(JAR) cf .libs/generic-jmx.jar "org/collectd/java"/*.class
+       touch "$@"
+
+all-local: java-build-stamp
+
+install-exec-local: java-build-stamp
+       mkdir -p "$(DESTDIR)$(pkgdatadir)/java"
+       $(INSTALL) -m 644 .libs/collectd-api.jar \
+               "$(DESTDIR)$(pkgdatadir)/java"
+       $(INSTALL) -m 644 .libs/generic-jmx.jar \
+               "$(DESTDIR)$(pkgdatadir)/java"
+
+uninstall-local:
+       rm -f "$(DESTDIR)$(pkgdatadir)/java/collectd-api.jar"
+       rm -f "$(DESTDIR)$(pkgdatadir)/java/generic-jmx.jar"
+       rmdir "$(DESTDIR)$(pkgdatadir)/java" || true
+
+clean-local:
+       rm -f "org/collectd/api"/*.class
+       rm -f "org/collectd/java"/*.class
+       rm -f .libs
+       rm -f "java-build-stamp"
diff --git a/bindings/java/Makefile.in b/bindings/java/Makefile.in
new file mode 100644 (file)
index 0000000..1c57558
--- /dev/null
@@ -0,0 +1,629 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = bindings/java
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_WITH_LIBAQUAERO5_CFLAGS = @BUILD_WITH_LIBAQUAERO5_CFLAGS@
+BUILD_WITH_LIBAQUAERO5_LDFLAGS = @BUILD_WITH_LIBAQUAERO5_LDFLAGS@
+BUILD_WITH_LIBATASMART_CPPFLAGS = @BUILD_WITH_LIBATASMART_CPPFLAGS@
+BUILD_WITH_LIBATASMART_LDFLAGS = @BUILD_WITH_LIBATASMART_LDFLAGS@
+BUILD_WITH_LIBATASMART_LIBS = @BUILD_WITH_LIBATASMART_LIBS@
+BUILD_WITH_LIBCURL_CFLAGS = @BUILD_WITH_LIBCURL_CFLAGS@
+BUILD_WITH_LIBCURL_LIBS = @BUILD_WITH_LIBCURL_LIBS@
+BUILD_WITH_LIBDBI_CPPFLAGS = @BUILD_WITH_LIBDBI_CPPFLAGS@
+BUILD_WITH_LIBDBI_LDFLAGS = @BUILD_WITH_LIBDBI_LDFLAGS@
+BUILD_WITH_LIBDBI_LIBS = @BUILD_WITH_LIBDBI_LIBS@
+BUILD_WITH_LIBHAL_CFLAGS = @BUILD_WITH_LIBHAL_CFLAGS@
+BUILD_WITH_LIBHAL_LIBS = @BUILD_WITH_LIBHAL_LIBS@
+BUILD_WITH_LIBHIREDIS_CPPFLAGS = @BUILD_WITH_LIBHIREDIS_CPPFLAGS@
+BUILD_WITH_LIBHIREDIS_LDFLAGS = @BUILD_WITH_LIBHIREDIS_LDFLAGS@
+BUILD_WITH_LIBIPTC_CPPFLAGS = @BUILD_WITH_LIBIPTC_CPPFLAGS@
+BUILD_WITH_LIBIPTC_LDFLAGS = @BUILD_WITH_LIBIPTC_LDFLAGS@
+BUILD_WITH_LIBLDAP_CPPFLAGS = @BUILD_WITH_LIBLDAP_CPPFLAGS@
+BUILD_WITH_LIBLDAP_LDFLAGS = @BUILD_WITH_LIBLDAP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_CPPFLAGS = @BUILD_WITH_LIBLVM2APP_CPPFLAGS@
+BUILD_WITH_LIBLVM2APP_LDFLAGS = @BUILD_WITH_LIBLVM2APP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_LIBS = @BUILD_WITH_LIBLVM2APP_LIBS@
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS = @BUILD_WITH_LIBMEMCACHED_CPPFLAGS@
+BUILD_WITH_LIBMEMCACHED_LDFLAGS = @BUILD_WITH_LIBMEMCACHED_LDFLAGS@
+BUILD_WITH_LIBMEMCACHED_LIBS = @BUILD_WITH_LIBMEMCACHED_LIBS@
+BUILD_WITH_LIBMNL_CFLAGS = @BUILD_WITH_LIBMNL_CFLAGS@
+BUILD_WITH_LIBMNL_LIBS = @BUILD_WITH_LIBMNL_LIBS@
+BUILD_WITH_LIBMODBUS_CFLAGS = @BUILD_WITH_LIBMODBUS_CFLAGS@
+BUILD_WITH_LIBMODBUS_LIBS = @BUILD_WITH_LIBMODBUS_LIBS@
+BUILD_WITH_LIBMONGOC_CPPFLAGS = @BUILD_WITH_LIBMONGOC_CPPFLAGS@
+BUILD_WITH_LIBMONGOC_LDFLAGS = @BUILD_WITH_LIBMONGOC_LDFLAGS@
+BUILD_WITH_LIBMYSQL_CFLAGS = @BUILD_WITH_LIBMYSQL_CFLAGS@
+BUILD_WITH_LIBMYSQL_LIBS = @BUILD_WITH_LIBMYSQL_LIBS@
+BUILD_WITH_LIBOPING_CPPFLAGS = @BUILD_WITH_LIBOPING_CPPFLAGS@
+BUILD_WITH_LIBOPING_LDFLAGS = @BUILD_WITH_LIBOPING_LDFLAGS@
+BUILD_WITH_LIBOWCAPI_CPPFLAGS = @BUILD_WITH_LIBOWCAPI_CPPFLAGS@
+BUILD_WITH_LIBOWCAPI_LIBS = @BUILD_WITH_LIBOWCAPI_LIBS@
+BUILD_WITH_LIBPQ_CPPFLAGS = @BUILD_WITH_LIBPQ_CPPFLAGS@
+BUILD_WITH_LIBPQ_LDFLAGS = @BUILD_WITH_LIBPQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS = @BUILD_WITH_LIBRABBITMQ_CPPFLAGS@
+BUILD_WITH_LIBRABBITMQ_LDFLAGS = @BUILD_WITH_LIBRABBITMQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_LIBS = @BUILD_WITH_LIBRABBITMQ_LIBS@
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS = @BUILD_WITH_LIBRDKAFKA_CPPFLAGS@
+BUILD_WITH_LIBRDKAFKA_LDFLAGS = @BUILD_WITH_LIBRDKAFKA_LDFLAGS@
+BUILD_WITH_LIBRDKAFKA_LIBS = @BUILD_WITH_LIBRDKAFKA_LIBS@
+BUILD_WITH_LIBROUTEROS_CPPFLAGS = @BUILD_WITH_LIBROUTEROS_CPPFLAGS@
+BUILD_WITH_LIBROUTEROS_LDFLAGS = @BUILD_WITH_LIBROUTEROS_LDFLAGS@
+BUILD_WITH_LIBRRD_CFLAGS = @BUILD_WITH_LIBRRD_CFLAGS@
+BUILD_WITH_LIBRRD_LDFLAGS = @BUILD_WITH_LIBRRD_LDFLAGS@
+BUILD_WITH_LIBSENSORS_CFLAGS = @BUILD_WITH_LIBSENSORS_CFLAGS@
+BUILD_WITH_LIBSENSORS_LDFLAGS = @BUILD_WITH_LIBSENSORS_LDFLAGS@
+BUILD_WITH_LIBSIGROK_CFLAGS = @BUILD_WITH_LIBSIGROK_CFLAGS@
+BUILD_WITH_LIBSIGROK_LDFLAGS = @BUILD_WITH_LIBSIGROK_LDFLAGS@
+BUILD_WITH_LIBSNMP_CFLAGS = @BUILD_WITH_LIBSNMP_CFLAGS@
+BUILD_WITH_LIBSNMP_LIBS = @BUILD_WITH_LIBSNMP_LIBS@
+BUILD_WITH_LIBSTATGRAB_CFLAGS = @BUILD_WITH_LIBSTATGRAB_CFLAGS@
+BUILD_WITH_LIBSTATGRAB_LDFLAGS = @BUILD_WITH_LIBSTATGRAB_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LIBS = @BUILD_WITH_LIBTOKYOTYRANT_LIBS@
+BUILD_WITH_LIBUDEV_CFLAGS = @BUILD_WITH_LIBUDEV_CFLAGS@
+BUILD_WITH_LIBUDEV_LDFLAGS = @BUILD_WITH_LIBUDEV_LDFLAGS@
+BUILD_WITH_LIBUPSCLIENT_CFLAGS = @BUILD_WITH_LIBUPSCLIENT_CFLAGS@
+BUILD_WITH_LIBUPSCLIENT_LIBS = @BUILD_WITH_LIBUPSCLIENT_LIBS@
+BUILD_WITH_LIBVARNISH_CFLAGS = @BUILD_WITH_LIBVARNISH_CFLAGS@
+BUILD_WITH_LIBVARNISH_LIBS = @BUILD_WITH_LIBVARNISH_LIBS@
+BUILD_WITH_LIBVIRT_CFLAGS = @BUILD_WITH_LIBVIRT_CFLAGS@
+BUILD_WITH_LIBVIRT_LIBS = @BUILD_WITH_LIBVIRT_LIBS@
+BUILD_WITH_LIBXML2_CFLAGS = @BUILD_WITH_LIBXML2_CFLAGS@
+BUILD_WITH_LIBXML2_LIBS = @BUILD_WITH_LIBXML2_LIBS@
+BUILD_WITH_LIBXMMS_CFLAGS = @BUILD_WITH_LIBXMMS_CFLAGS@
+BUILD_WITH_LIBXMMS_LIBS = @BUILD_WITH_LIBXMMS_LIBS@
+BUILD_WITH_LIBYAJL_CPPFLAGS = @BUILD_WITH_LIBYAJL_CPPFLAGS@
+BUILD_WITH_LIBYAJL_LDFLAGS = @BUILD_WITH_LIBYAJL_LDFLAGS@
+BUILD_WITH_LIBYAJL_LIBS = @BUILD_WITH_LIBYAJL_LIBS@
+BUILD_WITH_MIC_CPPFLAGS = @BUILD_WITH_MIC_CPPFLAGS@
+BUILD_WITH_MIC_LDADD = @BUILD_WITH_MIC_LDADD@
+BUILD_WITH_MIC_LIBPATH = @BUILD_WITH_MIC_LIBPATH@
+BUILD_WITH_OPENIPMI_CFLAGS = @BUILD_WITH_OPENIPMI_CFLAGS@
+BUILD_WITH_OPENIPMI_LIBS = @BUILD_WITH_OPENIPMI_LIBS@
+BUILD_WITH_ORACLE_CFLAGS = @BUILD_WITH_ORACLE_CFLAGS@
+BUILD_WITH_ORACLE_LIBS = @BUILD_WITH_ORACLE_LIBS@
+BUILD_WITH_PYTHON_CPPFLAGS = @BUILD_WITH_PYTHON_CPPFLAGS@
+BUILD_WITH_PYTHON_LDFLAGS = @BUILD_WITH_PYTHON_LDFLAGS@
+BUILD_WITH_PYTHON_LIBS = @BUILD_WITH_PYTHON_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_LOG_LEVEL = @DEFAULT_LOG_LEVEL@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GANGLIA_CPPFLAGS = @GANGLIA_CPPFLAGS@
+GANGLIA_LDFLAGS = @GANGLIA_LDFLAGS@
+GANGLIA_LIBS = @GANGLIA_LIBS@
+GCRYPT_CPPFLAGS = @GCRYPT_CPPFLAGS@
+GCRYPT_LDFLAGS = @GCRYPT_LDFLAGS@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVA_CFLAGS = @JAVA_CFLAGS@
+JAVA_CPPFLAGS = @JAVA_CPPFLAGS@
+JAVA_LDFLAGS = @JAVA_LDFLAGS@
+JAVA_LIBS = @JAVA_LIBS@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_DIR = @KERNEL_DIR@
+LCC_VERSION_EXTRA = @LCC_VERSION_EXTRA@
+LCC_VERSION_MAJOR = @LCC_VERSION_MAJOR@
+LCC_VERSION_MINOR = @LCC_VERSION_MINOR@
+LCC_VERSION_PATCH = @LCC_VERSION_PATCH@
+LCC_VERSION_STRING = @LCC_VERSION_STRING@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBNETAPP_CPPFLAGS = @LIBNETAPP_CPPFLAGS@
+LIBNETAPP_LDFLAGS = @LIBNETAPP_LDFLAGS@
+LIBNETAPP_LIBS = @LIBNETAPP_LIBS@
+LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
+LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOAD_PLUGIN_CSV = @LOAD_PLUGIN_CSV@
+LOAD_PLUGIN_LOGFILE = @LOAD_PLUGIN_LOGFILE@
+LOAD_PLUGIN_LOG_LOGSTASH = @LOAD_PLUGIN_LOG_LOGSTASH@
+LOAD_PLUGIN_NETWORK = @LOAD_PLUGIN_NETWORK@
+LOAD_PLUGIN_RRDTOOL = @LOAD_PLUGIN_RRDTOOL@
+LOAD_PLUGIN_SYSLOG = @LOAD_PLUGIN_SYSLOG@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_BINDINGS = @PERL_BINDINGS@
+PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_LIBS = @PERL_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_protoc_c = @have_protoc_c@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = org/collectd/api/CollectdConfigInterface.java \
+            org/collectd/api/CollectdFlushInterface.java \
+            org/collectd/api/CollectdInitInterface.java \
+            org/collectd/api/Collectd.java \
+            org/collectd/api/CollectdLogInterface.java \
+            org/collectd/api/CollectdMatchFactoryInterface.java \
+            org/collectd/api/CollectdMatchInterface.java \
+            org/collectd/api/CollectdNotificationInterface.java \
+            org/collectd/api/CollectdReadInterface.java \
+            org/collectd/api/CollectdShutdownInterface.java \
+            org/collectd/api/CollectdTargetFactoryInterface.java \
+            org/collectd/api/CollectdTargetInterface.java \
+            org/collectd/api/CollectdWriteInterface.java \
+            org/collectd/api/DataSet.java \
+            org/collectd/api/DataSource.java \
+            org/collectd/api/Notification.java \
+            org/collectd/api/OConfigItem.java \
+            org/collectd/api/OConfigValue.java \
+            org/collectd/api/PluginData.java \
+            org/collectd/api/ValueList.java \
+            org/collectd/java/GenericJMXConfConnection.java \
+            org/collectd/java/GenericJMXConfMBean.java \
+            org/collectd/java/GenericJMXConfValue.java \
+            org/collectd/java/GenericJMX.java \
+            org/collectd/java/JMXMemory.java
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign bindings/java/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign bindings/java/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-exec-local
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-local
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am all-local check check-am clean clean-generic \
+       clean-libtool clean-local cscopelist-am ctags-am distclean \
+       distclean-generic distclean-libtool distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-exec-local install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags-am uninstall uninstall-am uninstall-local
+
+
+java-build-stamp: $(srcdir)/org/collectd/api/*.java $(srcdir)/org/collectd/java/*.java
+       $(JAVAC) -d "." "$(srcdir)/org/collectd/api"/*.java
+       $(JAVAC) -d "." "$(srcdir)/org/collectd/java"/*.java
+       mkdir -p .libs
+       $(JAR) cf .libs/collectd-api.jar "org/collectd/api"/*.class
+       $(JAR) cf .libs/generic-jmx.jar "org/collectd/java"/*.class
+       touch "$@"
+
+all-local: java-build-stamp
+
+install-exec-local: java-build-stamp
+       mkdir -p "$(DESTDIR)$(pkgdatadir)/java"
+       $(INSTALL) -m 644 .libs/collectd-api.jar \
+               "$(DESTDIR)$(pkgdatadir)/java"
+       $(INSTALL) -m 644 .libs/generic-jmx.jar \
+               "$(DESTDIR)$(pkgdatadir)/java"
+
+uninstall-local:
+       rm -f "$(DESTDIR)$(pkgdatadir)/java/collectd-api.jar"
+       rm -f "$(DESTDIR)$(pkgdatadir)/java/generic-jmx.jar"
+       rmdir "$(DESTDIR)$(pkgdatadir)/java" || true
+
+clean-local:
+       rm -f "org/collectd/api"/*.class
+       rm -f "org/collectd/java"/*.class
+       rm -f .libs
+       rm -f "java-build-stamp"
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bindings/java/org/collectd/api/Collectd.java b/bindings/java/org/collectd/api/Collectd.java
new file mode 100644 (file)
index 0000000..450f87a
--- /dev/null
@@ -0,0 +1,307 @@
+/**
+ * collectd - bindings/java/org/collectd/api/Collectd.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Java API to internal functions of collectd.
+ *
+ * All functions in this class are {@code static}. You don't need to create an
+ * object of this class (in fact, you can't). Just call these functions
+ * directly.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ */
+public class Collectd
+{
+
+  /**
+   * Constant for severity (log level) "error".
+   *
+   * @see CollectdLogInterface
+   */
+  public static final int LOG_ERR     = 3;
+
+  /**
+   * Constant for severity (log level) "warning".
+   *
+   * @see CollectdLogInterface
+   */
+  public static final int LOG_WARNING = 4;
+
+  /**
+   * Constant for severity (log level) "notice".
+   *
+   * @see CollectdLogInterface
+   */
+  public static final int LOG_NOTICE  = 5;
+
+  /**
+   * Constant for severity (log level) "info".
+   *
+   * @see CollectdLogInterface
+   */
+  public static final int LOG_INFO    = 6;
+
+  /**
+   * Constant for severity (log level) "debug".
+   *
+   * @see CollectdLogInterface
+   */
+  public static final int LOG_DEBUG   = 7;
+
+  /**
+   * Return value of match methods: No match.
+   *
+   * This is one of two valid return values from match callbacks, indicating
+   * that the passed {@link DataSet} and {@link ValueList} did not match.
+   *
+   * Do not use the numeric value directly, it is subject to change without
+   * notice!
+   *
+   * @see CollectdMatchInterface
+   */
+  public static final int FC_MATCH_NO_MATCH  = 0;
+
+  /**
+   * Return value of match methods: Match.
+   *
+   * This is one of two valid return values from match callbacks, indicating
+   * that the passed {@link DataSet} and {@link ValueList} did match.
+   *
+   * Do not use the numeric value directly, it is subject to change without
+   * notice!
+   *
+   * @see CollectdMatchInterface
+   */
+  public static final int FC_MATCH_MATCHES   = 1;
+
+  /**
+   * Return value of target methods: Continue.
+   *
+   * This is one of three valid return values from target callbacks, indicating
+   * that processing of the {@link ValueList} should continue.
+   *
+   * Do not use the numeric value directly, it is subject to change without
+   * notice!
+   *
+   * @see CollectdTargetInterface
+   */
+  public static final int FC_TARGET_CONTINUE = 0;
+
+  /**
+   * Return value of target methods: Stop.
+   *
+   * This is one of three valid return values from target callbacks, indicating
+   * that processing of the {@link ValueList} should stop immediately.
+   *
+   * Do not use the numeric value directly, it is subject to change without
+   * notice!
+   *
+   * @see CollectdTargetInterface
+   */
+  public static final int FC_TARGET_STOP     = 1;
+
+  /**
+   * Return value of target methods: Return.
+   *
+   * This is one of three valid return values from target callbacks, indicating
+   * that processing of the current chain should be stopped and processing of
+   * the {@link ValueList} should continue in the calling chain.
+   *
+   * Do not use the numeric value directly, it is subject to change without
+   * notice!
+   *
+   * @see CollectdTargetInterface
+   */
+  public static final int FC_TARGET_RETURN   = 2;
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_config
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdConfigInterface
+   */
+  native public static int registerConfig (String name,
+      CollectdConfigInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_init
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdInitInterface
+   */
+  native public static int registerInit (String name,
+      CollectdInitInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_read
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdReadInterface
+   */
+  native public static int registerRead (String name,
+      CollectdReadInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_write
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdWriteInterface
+   */
+  native public static int registerWrite (String name,
+      CollectdWriteInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_flush
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdFlushInterface
+   */
+  native public static int registerFlush (String name,
+      CollectdFlushInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_shutdown
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdShutdownInterface
+   */
+  native public static int registerShutdown (String name,
+      CollectdShutdownInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_log
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdLogInterface
+   */
+  native public static int registerLog (String name,
+      CollectdLogInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_register_notification
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdNotificationInterface
+   */
+  native public static int registerNotification (String name,
+      CollectdNotificationInterface object);
+
+  /**
+   * Java representation of collectd/src/filter_chain.h:fc_register_match
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdMatchFactoryInterface
+   */
+  native public static int registerMatch (String name,
+      CollectdMatchFactoryInterface object);
+
+  /**
+   * Java representation of collectd/src/filter_chain.h:fc_register_target
+   *
+   * @return Zero when successful, non-zero otherwise.
+   * @see CollectdTargetFactoryInterface
+   */
+  native public static int registerTarget (String name,
+      CollectdTargetFactoryInterface object);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_dispatch_values
+   *
+   * @return Zero when successful, non-zero otherwise.
+   */
+  native public static int dispatchValues (ValueList vl);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_dispatch_notification
+   *
+   * @return Zero when successful, non-zero otherwise.
+   */
+  native public static int dispatchNotification (Notification n);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_get_ds
+   *
+   * @return The appropriate {@link DataSet} object or {@code null} if no such
+   * type is registered.
+   */
+  native public static DataSet getDS (String type);
+
+  /**
+   * Java representation of collectd/src/plugin.h:plugin_log
+   */
+  native private static void log (int severity, String message);
+
+  /**
+   * Yield contents of collectd/src/collectd.h:hostname_g
+   *
+   * @return The hostname as set in the collectd configuration.
+   */
+  native public static java.lang.String getHostname ();
+
+  /**
+   * Prints an error message.
+   */
+  public static void logError (String message)
+  {
+    log (LOG_ERR, message);
+  } /* void logError */
+
+  /**
+   * Prints a warning message.
+   */
+  public static void logWarning (String message)
+  {
+    log (LOG_WARNING, message);
+  } /* void logWarning */
+
+  /**
+   * Prints a notice.
+   */
+  public static void logNotice (String message)
+  {
+    log (LOG_NOTICE, message);
+  } /* void logNotice */
+
+  /**
+   * Prints an info message.
+   */
+  public static void logInfo (String message)
+  {
+    log (LOG_INFO, message);
+  } /* void logInfo */
+
+  /**
+   * Prints a debug message.
+   */
+  public static void logDebug (String message)
+  {
+    log (LOG_DEBUG, message);
+  } /* void logDebug */
+} /* class Collectd */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/java/org/collectd/api/CollectdConfigInterface.java b/bindings/java/org/collectd/api/CollectdConfigInterface.java
new file mode 100644 (file)
index 0000000..4b66097
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdConfigInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a config method.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerConfig(String, CollectdConfigInterface)
+ */
+public interface CollectdConfigInterface
+{
+       public int config (OConfigItem ci);
+}
diff --git a/bindings/java/org/collectd/api/CollectdFlushInterface.java b/bindings/java/org/collectd/api/CollectdFlushInterface.java
new file mode 100644 (file)
index 0000000..ea7bd64
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdFlushInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a flush method.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerFlush
+ */
+public interface CollectdFlushInterface
+{
+       public int flush (Number timeout, String identifier);
+}
diff --git a/bindings/java/org/collectd/api/CollectdInitInterface.java b/bindings/java/org/collectd/api/CollectdInitInterface.java
new file mode 100644 (file)
index 0000000..545f41e
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdInitInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing an init method.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerInit
+ */
+public interface CollectdInitInterface
+{
+       public int init ();
+}
diff --git a/bindings/java/org/collectd/api/CollectdLogInterface.java b/bindings/java/org/collectd/api/CollectdLogInterface.java
new file mode 100644 (file)
index 0000000..a516df5
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdLogInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a log method.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerLog
+ */
+public interface CollectdLogInterface
+{
+       public void log (int severity, String message);
+}
diff --git a/bindings/java/org/collectd/api/CollectdMatchFactoryInterface.java b/bindings/java/org/collectd/api/CollectdMatchFactoryInterface.java
new file mode 100644 (file)
index 0000000..b19c779
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdMatchFactoryInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a "match factory".
+ *
+ * Objects implementing this interface are used to create objects implementing
+ * the CollectdMatchInterface interface.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see CollectdMatchInterface
+ * @see Collectd#registerMatch
+ */
+public interface CollectdMatchFactoryInterface
+{
+       /**
+        * Create a new "match" object.
+        *
+        * This method uses the configuration provided as argument to create a
+        * new object which must implement the {@link CollectdMatchInterface}
+        * interface.
+        *
+        * This function corresponds to the <code>create</code> member of the
+        * <code>src/filter_chain.h:match_proc_t</code> struct.
+        *
+        * @return New {@link CollectdMatchInterface} object.
+        */
+       public CollectdMatchInterface createMatch (OConfigItem ci);
+}
diff --git a/bindings/java/org/collectd/api/CollectdMatchInterface.java b/bindings/java/org/collectd/api/CollectdMatchInterface.java
new file mode 100644 (file)
index 0000000..20a03d2
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdMatchInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a match method.
+ *
+ * These objects are instantiated using objects which implement the
+ * CollectdMatchFactoryInterface interface. They are not instantiated by the
+ * daemon directly!
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see CollectdMatchFactoryInterface
+ * @see Collectd#registerMatch
+ */
+public interface CollectdMatchInterface
+{
+       /**
+        * Callback method for matches.
+        *
+        * This method is called to decide whether or not a given ValueList
+        * matches or not. How this is determined is the is the main part of
+        * this function.
+        *
+        * @return One of {@link Collectd#FC_MATCH_NO_MATCH} and {@link Collectd#FC_MATCH_MATCHES}.
+        * @see CollectdMatchFactoryInterface
+        */
+       public int match (DataSet ds, ValueList vl);
+} /* public interface CollectdMatchInterface */
diff --git a/bindings/java/org/collectd/api/CollectdNotificationInterface.java b/bindings/java/org/collectd/api/CollectdNotificationInterface.java
new file mode 100644 (file)
index 0000000..ddff6cd
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdNotificationInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a notification method.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerNotification
+ */
+public interface CollectdNotificationInterface
+{
+       public int notification (Notification n);
+}
diff --git a/bindings/java/org/collectd/api/CollectdReadInterface.java b/bindings/java/org/collectd/api/CollectdReadInterface.java
new file mode 100644 (file)
index 0000000..996841a
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdReadInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a read method.
+ *
+ * Objects implementing this interface can be registered with the daemon. Their
+ * read method is then called periodically to acquire and submit values.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerRead
+ */
+public interface CollectdReadInterface
+{
+       /**
+        * Callback method for read plugins.
+        *
+        * This method is called once every few seconds (depends on the
+        * configuration of the daemon). It is supposed to gather values in
+        * some way and submit them to the daemon using
+        * {@link Collectd#dispatchValues}.
+        *
+        * @return zero when successful, non-zero when an error occurred.
+        * @see Collectd#dispatchValues
+        */
+       public int read ();
+}
diff --git a/bindings/java/org/collectd/api/CollectdShutdownInterface.java b/bindings/java/org/collectd/api/CollectdShutdownInterface.java
new file mode 100644 (file)
index 0000000..e496d3c
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdShutdownInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a shutdown method.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerShutdown
+ */
+public interface CollectdShutdownInterface
+{
+       public int shutdown ();
+}
diff --git a/bindings/java/org/collectd/api/CollectdTargetFactoryInterface.java b/bindings/java/org/collectd/api/CollectdTargetFactoryInterface.java
new file mode 100644 (file)
index 0000000..b4c2321
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdTargetFactoryInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a "target factory".
+ *
+ * Objects implementing this interface are used to create objects implementing
+ * the CollectdTargetInterface interface.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see CollectdTargetInterface
+ * @see Collectd#registerTarget
+ */
+public interface CollectdTargetFactoryInterface
+{
+       /**
+        * Create a new "target" object.
+        *
+        * This method uses the configuration provided as argument to create a
+        * new object which must implement the {@link CollectdTargetInterface}
+        * interface.
+        *
+        * This function corresponds to the {@code create} member of the
+        * {@code src/filter_chain.h:target_proc_t} struct.
+        *
+        * @return New {@link CollectdTargetInterface} object.
+        */
+       public CollectdTargetInterface createTarget (OConfigItem ci);
+}
diff --git a/bindings/java/org/collectd/api/CollectdTargetInterface.java b/bindings/java/org/collectd/api/CollectdTargetInterface.java
new file mode 100644 (file)
index 0000000..1f5ece1
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdTargetInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a target method.
+ *
+ * These objects are instantiated using objects which implement the
+ * CollectdTargetFactoryInterface interface. They are not instantiated by the
+ * daemon directly!
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see CollectdTargetFactoryInterface
+ * @see Collectd#registerTarget
+ */
+public interface CollectdTargetInterface
+{
+       /**
+        * Callback method for targets.
+        *
+        * This method is called to perform some action on the given ValueList.
+        * What precisely is done depends entirely on the implementing class.
+        *
+        * @return One of: {@link Collectd#FC_TARGET_CONTINUE},
+        * {@link Collectd#FC_TARGET_STOP}, {@link Collectd#FC_TARGET_RETURN}
+        * @see CollectdTargetFactoryInterface
+        */
+       public int invoke (DataSet ds, ValueList vl);
+} /* public interface CollectdTargetInterface */
diff --git a/bindings/java/org/collectd/api/CollectdWriteInterface.java b/bindings/java/org/collectd/api/CollectdWriteInterface.java
new file mode 100644 (file)
index 0000000..f95169a
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - bindings/java/org/collectd/api/CollectdWriteInterface.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Interface for objects implementing a write method.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ * @see Collectd#registerWrite
+ */
+public interface CollectdWriteInterface
+{
+       public int write (ValueList vl);
+}
diff --git a/bindings/java/org/collectd/api/DataSet.java b/bindings/java/org/collectd/api/DataSet.java
new file mode 100644 (file)
index 0000000..3cba5eb
--- /dev/null
@@ -0,0 +1,142 @@
+/**
+ * collectd - bindings/java/org/collectd/api/DataSet.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Java representation of collectd/src/plugin.h:data_set_t structure.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ */
+public class DataSet
+{
+    private String _type;
+    private List<DataSource> _ds;
+
+    private DataSet ()
+    {
+        this._type = null;
+        this._ds = new ArrayList<DataSource> ();
+    }
+
+    public DataSet (String type)
+    {
+        this._type = type;
+        this._ds = new ArrayList<DataSource> ();
+    }
+
+    public DataSet (String type, DataSource dsrc)
+    {
+        this._type = type;
+        this._ds = new ArrayList<DataSource> ();
+        this._ds.add (dsrc);
+    }
+
+    public DataSet (String type, List<DataSource> ds)
+    {
+        this._type = type;
+        this._ds = ds;
+    }
+
+    public void setType (String type)
+    {
+        this._type = type;
+    }
+
+    public String getType ()
+    {
+        return (this._type);
+    }
+
+    public void addDataSource (DataSource dsrc)
+    {
+        this._ds.add (dsrc);
+    }
+
+    public List<DataSource> getDataSources ()
+    {
+        return (this._ds);
+    }
+
+    public String toString ()
+    {
+        StringBuffer sb = new StringBuffer ();
+        int i;
+
+        sb.append (this._type);
+        for (i = 0; i < this._ds.size (); i++)
+        {
+            if (i == 0)
+                sb.append ("\t");
+            else
+                sb.append (", ");
+            sb.append (this._ds.get (i).toString ());
+        }
+
+        return (sb.toString ());
+    }
+
+    static public DataSet parseDataSet (String str)
+    {
+        DataSet ds = new DataSet ();
+        String[] fields;
+        int i;
+
+        str = str.trim();
+        if (str.length() == 0) {
+            return (null);
+        }
+        if (str.charAt(0) == '#') {
+            return (null);
+        }
+
+        fields = str.split ("\\s+");
+        if (fields.length < 2)
+            return (null);
+
+        ds._type = fields[0];
+
+        for (i = 1; i < fields.length; i++) {
+            DataSource dsrc;
+
+            dsrc = DataSource.parseDataSource (fields[i]);
+            if (dsrc == null)
+                break;
+
+            ds._ds.add (dsrc);
+        }
+
+        if (i < fields.length)
+            return (null);
+
+        return (ds);
+    } /* DataSet parseDataSet */
+} /* class DataSet */
+
+/* vim: set sw=4 sts=4 et : */
diff --git a/bindings/java/org/collectd/api/DataSource.java b/bindings/java/org/collectd/api/DataSource.java
new file mode 100644 (file)
index 0000000..ba132d3
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ * 
+ * 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
+ */
+
+package org.collectd.api;
+
+/**
+ * Java representation of collectd/src/plugin.h:data_source_t structure. 
+ */
+public class DataSource {
+    public static final int TYPE_COUNTER  = 0;
+    public static final int TYPE_GAUGE    = 1;
+    public static final int TYPE_DERIVE   = 2;
+    public static final int TYPE_ABSOLUTE = 3;
+
+    static final String COUNTER  = "COUNTER";
+    static final String GAUGE    = "GAUGE";
+    static final String DERIVE   = "DERIVE";
+    static final String ABSOLUTE = "ABSOLUTE";
+
+    static final String NAN = "U";
+    private static final String[] TYPES = { COUNTER, GAUGE, DERIVE, ABSOLUTE };
+
+    String _name;
+    int _type;
+    double _min;
+    double _max;
+
+    public DataSource (String name, int type, double min, double max) {
+        this._name = name;
+        this._type = TYPE_GAUGE;
+        if (type == TYPE_COUNTER)
+            this._type = TYPE_COUNTER;
+        else if (type == TYPE_DERIVE)
+            this._type = TYPE_DERIVE;
+        else if (type == TYPE_ABSOLUTE)
+            this._type = TYPE_ABSOLUTE;
+        this._min = min;
+        this._max = max;
+    }
+
+    /* Needed in parseDataSource below. Other code should use the above
+     * constructor or `parseDataSource'. */
+    private DataSource () {
+        this._type = TYPE_GAUGE;
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public void setName(String name) {
+        _name = name;
+    }
+
+    public int getType() {
+        return _type;
+    }
+
+    public void setType(int type) {
+        _type = type;
+    }
+
+    public double getMin() {
+        return _min;
+    }
+
+    public void setMin(double min) {
+        _min = min;
+    }
+
+    public double getMax() {
+        return _max;
+    }
+
+    public void setMax(double max) {
+        _max = max;
+    }
+
+    static double toDouble(String val) {
+        if (val.equals(NAN)) {
+            return Double.NaN;
+        }
+        else {
+            return Double.parseDouble(val);
+        }
+    }
+
+    private String asString(double val) {
+        if (Double.isNaN(val)) {
+            return NAN;
+        }
+        else {
+            return String.valueOf(val);
+        }
+    }
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        final char DLM = ':';
+        sb.append(_name).append(DLM);
+        sb.append(TYPES[_type]).append(DLM);
+        sb.append(asString(_min)).append(DLM);
+        sb.append(asString(_max));
+        return sb.toString();
+    }
+
+    static public DataSource parseDataSource (String str)
+    {
+        String[] fields;
+        int str_len = str.length ();
+        DataSource dsrc = new DataSource ();
+
+        /* Ignore trailing commas. This makes it easier for parsing code. */
+        if (str.charAt (str_len - 1) == ',') {
+            str = str.substring (0, str_len - 1);
+        }
+
+        fields = str.split(":");
+        if (fields.length != 4)
+            return (null);
+
+        dsrc._name = fields[0];
+
+        if (fields[1].equals (DataSource.GAUGE)) {
+            dsrc._type  = TYPE_GAUGE;
+        }
+        else {
+            dsrc._type  = TYPE_COUNTER;
+        }
+
+        dsrc._min =  toDouble (fields[2]);
+        dsrc._max =  toDouble (fields[3]);
+
+        return (dsrc);
+    } /* DataSource parseDataSource */
+}
+
+/* vim: set sw=4 sts=4 et : */
diff --git a/bindings/java/org/collectd/api/Notification.java b/bindings/java/org/collectd/api/Notification.java
new file mode 100644 (file)
index 0000000..cfc2186
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ * 
+ * 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
+ */
+
+package org.collectd.api;
+
+/**
+ * Java representation of collectd/src/plugin.h:notfication_t structure.
+ */
+public class Notification extends PluginData {
+    public static final int FAILURE = 1;
+    public static final int WARNING = 2;
+    public static final int OKAY    = 4;
+
+    public static String[] SEVERITY = {
+        "FAILURE",
+        "WARNING",
+        "OKAY",
+        "UNKNOWN"
+    };
+
+    private int _severity;
+    private String _message;
+
+    public Notification () {
+        _severity = 0;
+        _message = "Initial notification message";
+    }
+
+    public Notification (PluginData pd) {
+        super (pd);
+        _severity = 0;
+        _message = "Initial notification message";
+    }
+
+    public void setSeverity (int severity) {
+        if ((severity == FAILURE)
+                || (severity == WARNING)
+                || (severity == OKAY))
+            this._severity = severity;
+    }
+
+    public int getSeverity() {
+        return _severity;
+    }
+
+    public String getSeverityString() {
+        switch (_severity) {
+            case FAILURE:
+                return SEVERITY[0];
+            case WARNING:
+                return SEVERITY[1];
+            case OKAY:
+                return SEVERITY[2];
+            default:
+                return SEVERITY[3];
+        }
+    }
+
+    public void setMessage (String message) {
+        this._message = message;
+    }
+
+    public String getMessage() {
+        return _message;
+    }
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer(super.toString());
+        sb.append(" [").append(getSeverityString()).append("] ");
+        sb.append(_message);
+        return sb.toString();
+    }
+}
diff --git a/bindings/java/org/collectd/api/OConfigItem.java b/bindings/java/org/collectd/api/OConfigItem.java
new file mode 100644 (file)
index 0000000..08d8b70
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * collectd - bindings/java/org/collectd/api/OConfigItem.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Java representation of collectd/src/liboconfig/oconfig.h:oconfig_item_t structure.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ */
+public class OConfigItem
+{
+  private String _key = null;
+  private List<OConfigValue> _values   = new ArrayList<OConfigValue> ();
+  private List<OConfigItem>  _children = new ArrayList<OConfigItem> ();
+
+  public OConfigItem (String key)
+  {
+    _key = key;
+  } /* OConfigItem (String key) */
+
+  public String getKey ()
+  {
+    return (_key);
+  } /* String getKey () */
+
+  public void addValue (OConfigValue cv)
+  {
+    _values.add (cv);
+  } /* void addValue (OConfigValue cv) */
+
+  public void addValue (String s)
+  {
+    _values.add (new OConfigValue (s));
+  } /* void addValue (String s) */
+
+  public void addValue (Number n)
+  {
+    _values.add (new OConfigValue (n));
+  } /* void addValue (String s) */
+
+  public void addValue (boolean b)
+  {
+    _values.add (new OConfigValue (b));
+  } /* void addValue (String s) */
+
+  public List<OConfigValue> getValues ()
+  {
+    return (_values);
+  } /* List<OConfigValue> getValues () */
+
+  public void addChild (OConfigItem ci)
+  {
+    _children.add (ci);
+  } /* void addChild (OConfigItem ci) */
+
+  public List<OConfigItem> getChildren ()
+  {
+    return (_children);
+  } /* List<OConfigItem> getChildren () */
+
+  public String toString ()
+  {
+    return (new String ("{ key: " + _key + "; "
+          + "values: " + _values.toString () + "; "
+          + "children: " + _children.toString () + "; }"));
+  } /* String toString () */
+} /* class OConfigItem */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/java/org/collectd/api/OConfigValue.java b/bindings/java/org/collectd/api/OConfigValue.java
new file mode 100644 (file)
index 0000000..0a33773
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * collectd - bindings/java/org/collectd/api/OConfigValue.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.api;
+
+/**
+ * Java representation of collectd/src/liboconfig/oconfig.h:oconfig_value_t structure.
+ *
+ * @author Florian Forster &lt;octo at collectd.org&gt;
+ */
+public class OConfigValue
+{
+  public static final int OCONFIG_TYPE_STRING  = 0;
+  public static final int OCONFIG_TYPE_NUMBER  = 1;
+  public static final int OCONFIG_TYPE_BOOLEAN = 2;
+
+  private int     _type;
+  private String  _value_string;
+  private Number  _value_number;
+  private boolean _value_boolean;
+
+  public OConfigValue (String s)
+  {
+    _type = OCONFIG_TYPE_STRING;
+    _value_string  = s;
+    _value_number  = null;
+    _value_boolean = false;
+  } /* OConfigValue (String s) */
+
+  public OConfigValue (Number n)
+  {
+    _type = OCONFIG_TYPE_NUMBER;
+    _value_string  = null;
+    _value_number  = n;
+    _value_boolean = false;
+  } /* OConfigValue (String s) */
+
+  public OConfigValue (boolean b)
+  {
+    _type = OCONFIG_TYPE_BOOLEAN;
+    _value_string  = null;
+    _value_number  = null;
+    _value_boolean = b;
+  } /* OConfigValue (String s) */
+
+  public int getType ()
+  {
+    return (_type);
+  } /* int getType */
+
+  public String getString ()
+  {
+    return (_value_string);
+  } /* String getString */
+
+  public Number getNumber ()
+  {
+    return (_value_number);
+  } /* String getString */
+
+  public boolean getBoolean ()
+  {
+    return (_value_boolean);
+  } /* String getString */
+
+  public String toString ()
+  {
+    if (_type == OCONFIG_TYPE_STRING)
+      return (_value_string);
+    else if (_type == OCONFIG_TYPE_NUMBER)
+      return (_value_number.toString ());
+    else if (_type == OCONFIG_TYPE_BOOLEAN)
+      return (Boolean.toString (_value_boolean));
+    return (null);
+  } /* String toString () */
+} /* class OConfigValue */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/java/org/collectd/api/PluginData.java b/bindings/java/org/collectd/api/PluginData.java
new file mode 100644 (file)
index 0000000..26b0206
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ * 
+ * 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
+ */
+
+package org.collectd.api;
+
+import java.util.Date;
+
+/**
+ * Shared members of value_list_t and notification_t structures.
+ */
+public class PluginData {
+
+    protected long _time = 0;
+    protected String _host;
+    protected String _plugin;
+    protected String _pluginInstance = "";
+    protected String _type = "";
+    protected String _typeInstance = "";
+
+    public PluginData() {
+        
+    }
+
+    public PluginData(PluginData pd) {
+        _time = pd._time;
+        _host = pd._host;
+        _plugin = pd._plugin;
+        _pluginInstance = pd._pluginInstance;
+        _type = pd._type;
+        _typeInstance = pd._typeInstance;
+    }
+
+    public long getTime() {
+        return _time;
+    }
+
+    public void setTime(long time) {
+        _time = time;
+    }
+
+    public String getHost() {
+        return _host;
+    }
+
+    public void setHost(String host) {
+        _host = host;
+    }
+
+    public String getPlugin() {
+        return _plugin;
+    }
+
+    public void setPlugin(String plugin) {
+        _plugin = plugin;
+    }
+
+    public String getPluginInstance() {
+        return _pluginInstance;
+    }
+
+    public void setPluginInstance(String pluginInstance) {
+        _pluginInstance = pluginInstance;
+    }
+
+    public String getType() {
+        return _type;
+    }
+
+    public void setType(String type) {
+        _type = type;
+    }
+
+    public String getTypeInstance() {
+        return _typeInstance;
+    }
+
+    public void setTypeInstance(String typeInstance) {
+        _typeInstance = typeInstance;
+    }
+
+    public boolean defined(String val) {
+        return (val != null) && (val.length() > 0);
+    }
+
+    public String getSource() {
+        final char DLM = '/';
+        StringBuffer sb = new StringBuffer();
+        if (defined(_host)) {
+            sb.append(_host);
+        }
+        if (defined(_plugin)) {
+            sb.append(DLM).append(_plugin);
+        }
+        if (defined(_pluginInstance)) {
+            sb.append(DLM).append(_pluginInstance);
+        }
+        if (defined(_type)) {
+            sb.append(DLM).append(_type);
+        }
+        if (defined(_typeInstance)) {
+            sb.append(DLM).append(_typeInstance);
+        }
+        return sb.toString();        
+    }
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append('[').append(new Date(_time)).append("] ");
+        sb.append(getSource());
+        return sb.toString();
+    }
+}
diff --git a/bindings/java/org/collectd/api/ValueList.java b/bindings/java/org/collectd/api/ValueList.java
new file mode 100644 (file)
index 0000000..b8d6f40
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * jcollectd
+ * Copyright (C) 2009 Hyperic, Inc.
+ * 
+ * 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
+ */
+
+package org.collectd.api;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Java representation of collectd/src/plugin.h:value_list_t structure.
+ */
+public class ValueList extends PluginData {
+
+    private List<Number> _values = new ArrayList<Number>();
+    private DataSet _ds;
+
+    private long _interval = 0;
+
+    public ValueList() {
+        
+    }
+
+    public ValueList(PluginData pd) {
+        super(pd);
+    }
+
+    public ValueList(ValueList vl) {
+        this((PluginData)vl);
+        _interval = vl._interval;
+        _values.addAll(vl.getValues());
+       _ds = vl._ds;
+    }
+
+    public List<Number> getValues() {
+        return _values;
+    }
+
+    public void setValues(List<Number> values) {
+        _values = values;
+    }
+
+    public void addValue(Number value) {
+        _values.add(value);
+    }
+
+    /* Used by the network parsing code */
+    public void clearValues () {
+        _values.clear ();
+    }
+
+    /**
+     * @deprecated Use {@link #getDataSet()} instead.
+     */
+    public List<DataSource> getDataSource() {
+        if (_ds == null)
+            return null;
+        return _ds.getDataSources ();
+    }
+
+    public DataSet getDataSet () {
+        return _ds;
+    }
+
+    public void setDataSet (DataSet ds) {
+        _ds = ds;
+    }
+
+    /**
+     * @deprecated Use {@link #setDataSet(DataSet)} instead.
+     */
+    public void setDataSource(List<DataSource> dsrc) {
+        _ds = new DataSet (_type, dsrc);
+    }
+
+    /**
+     * Returns the interval (in milliseconds) of the value list.
+     */
+    public long getInterval() {
+        return _interval;
+    }
+
+    /**
+     * Sets the interval (in milliseconds) of the value list.
+     */
+    public void setInterval(long interval) {
+        _interval = interval;
+    }
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer(super.toString());
+        sb.append("=[");
+        List<DataSource> ds = getDataSource();
+        int size = _values.size();
+        for (int i=0; i<size; i++) {
+            Number val = _values.get(i);
+            String name;
+            if (ds == null) {
+                name = "unknown" + i;
+            }
+            else {
+                name = ds.get(i).getName();
+            }
+            sb.append(name).append('=').append(val);
+            if (i < size-1) {
+                sb.append(',');
+            }
+        }
+        sb.append("]");
+        return sb.toString();
+    }
+}
+
+/* vim: set sw=4 sts=4 et : */
diff --git a/bindings/java/org/collectd/java/GenericJMX.java b/bindings/java/org/collectd/java/GenericJMX.java
new file mode 100644 (file)
index 0000000..a678d5f
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ * collectd - bindings/java/org/collectd/java/GenericJMX.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.java;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.collectd.api.Collectd;
+import org.collectd.api.CollectdConfigInterface;
+import org.collectd.api.CollectdInitInterface;
+import org.collectd.api.CollectdReadInterface;
+import org.collectd.api.CollectdShutdownInterface;
+import org.collectd.api.OConfigValue;
+import org.collectd.api.OConfigItem;
+
+public class GenericJMX implements CollectdConfigInterface,
+       CollectdReadInterface,
+       CollectdShutdownInterface
+{
+  static private Map<String,GenericJMXConfMBean> _mbeans
+    = new TreeMap<String,GenericJMXConfMBean> ();
+
+  private List<GenericJMXConfConnection> _connections = null;
+
+  public GenericJMX ()
+  {
+    Collectd.registerConfig   ("GenericJMX", this);
+    Collectd.registerRead     ("GenericJMX", this);
+    Collectd.registerShutdown ("GenericJMX", this);
+
+    this._connections = new ArrayList<GenericJMXConfConnection> ();
+  }
+
+  public int config (OConfigItem ci) /* {{{ */
+  {
+    List<OConfigItem> children;
+    int i;
+
+    Collectd.logDebug ("GenericJMX plugin: config: ci = " + ci + ";");
+
+    children = ci.getChildren ();
+    for (i = 0; i < children.size (); i++)
+    {
+      OConfigItem child;
+      String key;
+
+      child = children.get (i);
+      key = child.getKey ();
+      if (key.equalsIgnoreCase ("MBean"))
+      {
+        try
+        {
+          GenericJMXConfMBean mbean = new GenericJMXConfMBean (child);
+          putMBean (mbean);
+        }
+        catch (IllegalArgumentException e)
+        {
+          Collectd.logError ("GenericJMX plugin: "
+              + "Evaluating `MBean' block failed: " + e);
+        }
+      }
+      else if (key.equalsIgnoreCase ("Connection"))
+      {
+        try
+        {
+          GenericJMXConfConnection conn = new GenericJMXConfConnection (child);
+          this._connections.add (conn);
+        }
+        catch (IllegalArgumentException e)
+        {
+          Collectd.logError ("GenericJMX plugin: "
+              + "Evaluating `Connection' block failed: " + e);
+        }
+      }
+      else
+      {
+        Collectd.logError ("GenericJMX plugin: Unknown config option: " + key);
+      }
+    } /* for (i = 0; i < children.size (); i++) */
+
+    return (0);
+  } /* }}} int config */
+
+  public int read () /* {{{ */
+  {
+    for (int i = 0; i < this._connections.size (); i++)
+    {
+      try
+      {
+        this._connections.get (i).query ();
+      }
+      catch (Exception e)
+      {
+        Collectd.logError ("GenericJMX: Caught unexpected exception: " + e);
+        e.printStackTrace ();
+      }
+    }
+
+    return (0);
+  } /* }}} int read */
+
+  public int shutdown () /* {{{ */
+  {
+    System.out.print ("org.collectd.java.GenericJMX.Shutdown ();\n");
+    this._connections = null;
+    return (0);
+  } /* }}} int shutdown */
+
+  /*
+   * static functions
+   */
+  static public GenericJMXConfMBean getMBean (String alias)
+  {
+    return (_mbeans.get (alias));
+  }
+
+  static private void putMBean (GenericJMXConfMBean mbean)
+  {
+    Collectd.logDebug ("GenericJMX.putMBean: Adding " + mbean.getName ());
+    _mbeans.put (mbean.getName (), mbean);
+  }
+} /* class GenericJMX */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/java/org/collectd/java/GenericJMXConfConnection.java b/bindings/java/org/collectd/java/GenericJMXConfConnection.java
new file mode 100644 (file)
index 0000000..ea0f2fa
--- /dev/null
@@ -0,0 +1,254 @@
+/**
+ * collectd - bindings/java/org/collectd/java/GenericJMXConfConnection.java
+ * Copyright (C) 2009-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.java;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import javax.management.MBeanServerConnection;
+
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+
+import org.collectd.api.Collectd;
+import org.collectd.api.PluginData;
+import org.collectd.api.OConfigValue;
+import org.collectd.api.OConfigItem;
+
+class GenericJMXConfConnection
+{
+  private String _username = null;
+  private String _password = null;
+  private String _host = null;
+  private String _instance_prefix = null;
+  private String _service_url = null;
+  private MBeanServerConnection _jmx_connection = null;
+  private List<GenericJMXConfMBean> _mbeans = null;
+
+  /*
+   * private methods
+   */
+  private String getConfigString (OConfigItem ci) /* {{{ */
+  {
+    List<OConfigValue> values;
+    OConfigValue v;
+
+    values = ci.getValues ();
+    if (values.size () != 1)
+    {
+      Collectd.logError ("GenericJMXConfConnection: The " + ci.getKey ()
+          + " configuration option needs exactly one string argument.");
+      return (null);
+    }
+
+    v = values.get (0);
+    if (v.getType () != OConfigValue.OCONFIG_TYPE_STRING)
+    {
+      Collectd.logError ("GenericJMXConfConnection: The " + ci.getKey ()
+          + " configuration option needs exactly one string argument.");
+      return (null);
+    }
+
+    return (v.getString ());
+  } /* }}} String getConfigString */
+
+  private String getHost () /* {{{ */
+  {
+    if (this._host != null)
+    {
+      return (this._host);
+    }
+
+    return Collectd.getHostname();
+  } /* }}} String getHost */
+
+private void connect () /* {{{ */
+{
+  JMXServiceURL service_url;
+  JMXConnector connector;
+  Map environment;
+
+  if (_jmx_connection != null)
+    return;
+
+  environment = null;
+  if (this._password != null)
+  {
+    String[] credentials;
+
+    if (this._username == null)
+      this._username = new String ("monitorRole");
+
+    credentials = new String[] { this._username, this._password };
+
+    environment = new HashMap ();
+    environment.put (JMXConnector.CREDENTIALS, credentials);
+    environment.put(JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
+  }
+
+  try
+  {
+    service_url = new JMXServiceURL (this._service_url);
+    connector = JMXConnectorFactory.connect (service_url, environment);
+    _jmx_connection = connector.getMBeanServerConnection ();
+  }
+  catch (Exception e)
+  {
+    Collectd.logError ("GenericJMXConfConnection: "
+        + "Creating MBean server connection failed: " + e);
+    return;
+  }
+} /* }}} void connect */
+
+/*
+ * public methods
+ *
+ * <Connection>
+ *   Host "tomcat0.mycompany"
+ *   ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
+ *   Collect "java.lang:type=GarbageCollector,name=Copy"
+ *   Collect "java.lang:type=Memory"
+ * </Connection>
+ *
+ */
+  public GenericJMXConfConnection (OConfigItem ci) /* {{{ */
+    throws IllegalArgumentException
+  {
+    List<OConfigItem> children;
+    Iterator<OConfigItem> iter;
+
+    this._mbeans = new ArrayList<GenericJMXConfMBean> ();
+
+    children = ci.getChildren ();
+    iter = children.iterator ();
+    while (iter.hasNext ())
+    {
+      OConfigItem child = iter.next ();
+
+      if (child.getKey ().equalsIgnoreCase ("Host"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._host = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("User"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._username = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("Password"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._password = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("ServiceURL"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._service_url = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("InstancePrefix"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._instance_prefix = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("Collect"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+        {
+          GenericJMXConfMBean mbean;
+
+          mbean = GenericJMX.getMBean (tmp);
+          if (mbean == null)
+            throw (new IllegalArgumentException ("No such MBean defined: "
+                  + tmp + ". Please make sure all `MBean' blocks appear "
+                  + "before (above) all `Connection' blocks."));
+          Collectd.logDebug ("GenericJMXConfConnection: " + this._host + ": Add " + tmp);
+          this._mbeans.add (mbean);
+        }
+      }
+      else
+        throw (new IllegalArgumentException ("Unknown option: "
+              + child.getKey ()));
+    }
+
+    if (this._service_url == null)
+      throw (new IllegalArgumentException ("No service URL was defined."));
+    if (this._mbeans.size () == 0)
+      throw (new IllegalArgumentException ("No valid collect statement "
+            + "present."));
+  } /* }}} GenericJMXConfConnection (OConfigItem ci) */
+
+  public void query () /* {{{ */
+  {
+    PluginData pd;
+
+    connect ();
+
+    if (this._jmx_connection == null)
+      return;
+
+    Collectd.logDebug ("GenericJMXConfConnection.query: "
+        + "Reading " + this._mbeans.size () + " mbeans from "
+        + ((this._host != null) ? this._host : "(null)"));
+
+    pd = new PluginData ();
+    pd.setHost (this.getHost ());
+    pd.setPlugin ("GenericJMX");
+
+    for (int i = 0; i < this._mbeans.size (); i++)
+    {
+      int status;
+
+      status = this._mbeans.get (i).query (this._jmx_connection, pd,
+          this._instance_prefix);
+      if (status != 0)
+      {
+        this._jmx_connection = null;
+        return;
+      }
+    } /* for */
+  } /* }}} void query */
+
+  public String toString ()
+  {
+    return (new String ("host = " + this._host + "; "
+          + "url = " + this._service_url));
+  }
+}
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/java/org/collectd/java/GenericJMXConfMBean.java b/bindings/java/org/collectd/java/GenericJMXConfMBean.java
new file mode 100644 (file)
index 0000000..64a53ac
--- /dev/null
@@ -0,0 +1,243 @@
+/**
+ * collectd - bindings/java/org/collectd/java/GenericJMXConfMBean.java
+ * Copyright (C) 2009,2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.java;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.ArrayList;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.MalformedObjectNameException;
+
+import org.collectd.api.Collectd;
+import org.collectd.api.PluginData;
+import org.collectd.api.OConfigValue;
+import org.collectd.api.OConfigItem;
+
+class GenericJMXConfMBean
+{
+  private String _name; /* name by which this mapping is referenced */
+  private ObjectName _obj_name;
+  private String _instance_prefix;
+  private List<String> _instance_from;
+  private List<GenericJMXConfValue> _values;
+
+  private String getConfigString (OConfigItem ci) /* {{{ */
+  {
+    List<OConfigValue> values;
+    OConfigValue v;
+
+    values = ci.getValues ();
+    if (values.size () != 1)
+    {
+      Collectd.logError ("GenericJMXConfMBean: The " + ci.getKey ()
+          + " configuration option needs exactly one string argument.");
+      return (null);
+    }
+
+    v = values.get (0);
+    if (v.getType () != OConfigValue.OCONFIG_TYPE_STRING)
+    {
+      Collectd.logError ("GenericJMXConfMBean: The " + ci.getKey ()
+          + " configuration option needs exactly one string argument.");
+      return (null);
+    }
+
+    return (v.getString ());
+  } /* }}} String getConfigString */
+
+/*
+ * <MBean "alias name">
+ *   ObjectName "object name"
+ *   InstancePrefix "foobar"
+ *   InstanceFrom "name"
+ *   <Value />
+ *   <Value />
+ *   :
+ * </MBean>
+ */
+  public GenericJMXConfMBean (OConfigItem ci) /* {{{ */
+    throws IllegalArgumentException
+  {
+    List<OConfigItem> children;
+    Iterator<OConfigItem> iter;
+
+    this._name = getConfigString (ci);
+    if (this._name == null)
+      throw (new IllegalArgumentException ("No alias name was defined. "
+            + "MBean blocks need exactly one string argument."));
+
+    this._obj_name = null;
+    this._instance_prefix = null;
+    this._instance_from = new ArrayList<String> ();
+    this._values = new ArrayList<GenericJMXConfValue> ();
+
+    children = ci.getChildren ();
+    iter = children.iterator ();
+    while (iter.hasNext ())
+    {
+      OConfigItem child = iter.next ();
+
+      Collectd.logDebug ("GenericJMXConfMBean: child.getKey () = "
+          + child.getKey ());
+      if (child.getKey ().equalsIgnoreCase ("ObjectName"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp == null)
+          continue;
+
+        try
+        {
+          this._obj_name = new ObjectName (tmp);
+        }
+        catch (MalformedObjectNameException e)
+        {
+          throw (new IllegalArgumentException ("Not a valid object name: "
+                + tmp, e));
+        }
+      }
+      else if (child.getKey ().equalsIgnoreCase ("InstancePrefix"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._instance_prefix = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("InstanceFrom"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._instance_from.add (tmp);
+      }
+      else if (child.getKey ().equalsIgnoreCase ("Value"))
+      {
+        GenericJMXConfValue cv;
+
+        cv = new GenericJMXConfValue (child);
+        this._values.add (cv);
+      }
+      else
+        throw (new IllegalArgumentException ("Unknown option: "
+              + child.getKey ()));
+    }
+
+    if (this._obj_name == null)
+      throw (new IllegalArgumentException ("No object name was defined."));
+
+    if (this._values.size () == 0)
+      throw (new IllegalArgumentException ("No value block was defined."));
+
+  } /* }}} GenericJMXConfMBean (OConfigItem ci) */
+
+  public String getName () /* {{{ */
+  {
+    return (this._name);
+  } /* }}} */
+
+  public int query (MBeanServerConnection conn, PluginData pd, /* {{{ */
+      String instance_prefix)
+  {
+    Set<ObjectName> names;
+    Iterator<ObjectName> iter;
+
+    try
+    {
+      names = conn.queryNames (this._obj_name, /* query = */ null);
+    }
+    catch (Exception e)
+    {
+      Collectd.logError ("GenericJMXConfMBean: queryNames failed: " + e);
+      return (-1);
+    }
+
+    if (names.size () == 0)
+    {
+      Collectd.logWarning ("GenericJMXConfMBean: No MBean matched "
+          + "the ObjectName " + this._obj_name);
+    }
+
+    iter = names.iterator ();
+    while (iter.hasNext ())
+    {
+      ObjectName   objName;
+      PluginData   pd_tmp;
+      List<String> instanceList;
+      StringBuffer instance;
+
+      objName      = iter.next ();
+      pd_tmp       = new PluginData (pd);
+      instanceList = new ArrayList<String> ();
+      instance     = new StringBuffer ();
+
+      Collectd.logDebug ("GenericJMXConfMBean: objName = "
+          + objName.toString ());
+
+      for (int i = 0; i < this._instance_from.size (); i++)
+      {
+        String propertyName;
+        String propertyValue;
+
+        propertyName = this._instance_from.get (i);
+        propertyValue = objName.getKeyProperty (propertyName);
+        if (propertyValue == null)
+        {
+          Collectd.logError ("GenericJMXConfMBean: "
+              + "No such property in object name: " + propertyName);
+        }
+        else
+        {
+          instanceList.add (propertyValue);
+        }
+      }
+
+      if (instance_prefix != null)
+        instance.append (instance_prefix);
+
+      if (this._instance_prefix != null)
+        instance.append (this._instance_prefix);
+
+      for (int i = 0; i < instanceList.size (); i++)
+      {
+        if (i > 0)
+          instance.append ("-");
+        instance.append (instanceList.get (i));
+      }
+
+      pd_tmp.setPluginInstance (instance.toString ());
+
+      Collectd.logDebug ("GenericJMXConfMBean: instance = " + instance.toString ());
+
+      for (int i = 0; i < this._values.size (); i++)
+        this._values.get (i).query (conn, objName, pd_tmp);
+    }
+
+    return (0);
+  } /* }}} void query */
+}
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/java/org/collectd/java/GenericJMXConfValue.java b/bindings/java/org/collectd/java/GenericJMXConfValue.java
new file mode 100644 (file)
index 0000000..4b42c91
--- /dev/null
@@ -0,0 +1,599 @@
+/**
+ * collectd - bindings/java/org/collectd/java/GenericJMXConfValue.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.java;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.ArrayList;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.InvalidKeyException;
+
+import org.collectd.api.Collectd;
+import org.collectd.api.DataSet;
+import org.collectd.api.DataSource;
+import org.collectd.api.ValueList;
+import org.collectd.api.PluginData;
+import org.collectd.api.OConfigValue;
+import org.collectd.api.OConfigItem;
+
+/**
+ * Representation of a &lt;value&nbsp;/&gt; block and query functionality.
+ *
+ * This class represents a &lt;value&nbsp;/&gt; block in the configuration. As
+ * such, the constructor takes an {@link org.collectd.api.OConfigValue} to
+ * construct an object of this class.
+ *
+ * The object can then be asked to query data from JMX and dispatch it to
+ * collectd.
+ *
+ * @see GenericJMXConfMBean
+ */
+class GenericJMXConfValue
+{
+  private String _ds_name;
+  private DataSet _ds;
+  private List<String> _attributes;
+  private String _instance_prefix;
+  private List<String> _instance_from;
+  private boolean _is_table;
+
+  /**
+   * Converts a generic (OpenType) object to a number.
+   *
+   * Returns null if a conversion is not possible or not implemented.
+   */
+  private Number genericObjectToNumber (Object obj, int ds_type) /* {{{ */
+  {
+    if (obj instanceof String)
+    {
+      String str = (String) obj;
+      
+      try
+      {
+        if (ds_type == DataSource.TYPE_GAUGE)
+          return (new Double (str));
+        else
+          return (new Long (str));
+      }
+      catch (NumberFormatException e)
+      {
+        return (null);
+      }
+    }
+    else if (obj instanceof Byte)
+    {
+      return (new Byte ((Byte) obj));
+    }
+    else if (obj instanceof Short)
+    {
+      return (new Short ((Short) obj));
+    }
+    else if (obj instanceof Integer)
+    {
+      return (new Integer ((Integer) obj));
+    }
+    else if (obj instanceof Long)
+    {
+      return (new Long ((Long) obj));
+    }
+    else if (obj instanceof Float)
+    {
+      return (new Float ((Float) obj));
+    }
+    else if (obj instanceof Double)
+    {
+      return (new Double ((Double) obj));
+    }
+    else if (obj instanceof BigDecimal)
+    {
+      return (BigDecimal.ZERO.add ((BigDecimal) obj));
+    }
+    else if (obj instanceof BigInteger)
+    {
+      return (BigInteger.ZERO.add ((BigInteger) obj));
+    }
+
+    return (null);
+  } /* }}} Number genericObjectToNumber */
+
+  /**
+   * Converts a generic list to a list of numbers.
+   *
+   * Returns null if one or more objects could not be converted.
+   */
+  private List<Number> genericListToNumber (List<Object> objects) /* {{{ */
+  {
+    List<Number> ret = new ArrayList<Number> ();
+    List<DataSource> dsrc = this._ds.getDataSources ();
+
+    assert (objects.size () == dsrc.size ());
+
+    for (int i = 0; i < objects.size (); i++)
+    {
+      Number n;
+
+      n = genericObjectToNumber (objects.get (i), dsrc.get (i).getType ());
+      if (n == null)
+        return (null);
+      ret.add (n);
+    }
+
+    return (ret);
+  } /* }}} List<Number> genericListToNumber */
+
+  /**
+   * Converts a list of CompositeData to a list of numbers.
+   *
+   * From each <em>CompositeData </em> the key <em>key</em> is received and all
+   * those values are converted to a number. If one of the
+   * <em>CompositeData</em> doesn't have the specified key or one returned
+   * object cannot converted to a number then the function will return null.
+   */
+  private List<Number> genericCompositeToNumber (List<CompositeData> cdlist, /* {{{ */
+      String key)
+  {
+    List<Object> objects = new ArrayList<Object> ();
+
+    for (int i = 0; i < cdlist.size (); i++)
+    {
+      CompositeData cd;
+      Object value;
+
+      cd = cdlist.get (i);
+      try
+      {
+        value = cd.get (key);
+      }
+      catch (InvalidKeyException e)
+      {
+        return (null);
+      }
+      objects.add (value);
+    }
+
+    return (genericListToNumber (objects));
+  } /* }}} List<Number> genericCompositeToNumber */
+
+  private void submitTable (List<Object> objects, ValueList vl, /* {{{ */
+      String instancePrefix)
+  {
+    List<CompositeData> cdlist;
+    Set<String> keySet = null;
+    Iterator<String> keyIter;
+
+    cdlist = new ArrayList<CompositeData> ();
+    for (int i = 0; i < objects.size (); i++)
+    {
+      Object obj;
+
+      obj = objects.get (i);
+      if (obj instanceof CompositeData)
+      {
+        CompositeData cd;
+
+        cd = (CompositeData) obj;
+
+        if (i == 0)
+          keySet = cd.getCompositeType ().keySet ();
+
+        cdlist.add (cd);
+      }
+      else
+      {
+        Collectd.logError ("GenericJMXConfValue: At least one of the "
+            + "attributes was not of type `CompositeData', as required "
+            + "when table is set to `true'.");
+        return;
+      }
+    }
+
+    assert (keySet != null);
+
+    keyIter = keySet.iterator ();
+    while (keyIter.hasNext ())
+    {
+      String key;
+      List<Number> values;
+
+      key = keyIter.next ();
+      values = genericCompositeToNumber (cdlist, key);
+      if (values == null)
+      {
+        Collectd.logError ("GenericJMXConfValue: Cannot build a list of "
+            + "numbers for key " + key + ". Most likely not all attributes "
+            + "have this key.");
+        continue;
+      }
+
+      if (instancePrefix == null)
+        vl.setTypeInstance (key);
+      else
+        vl.setTypeInstance (instancePrefix + key);
+      vl.setValues (values);
+
+      Collectd.dispatchValues (vl);
+    }
+  } /* }}} void submitTable */
+
+  private void submitScalar (List<Object> objects, ValueList vl, /* {{{ */
+      String instancePrefix)
+  {
+    List<Number> values;
+
+    values = genericListToNumber (objects);
+    if (values == null)
+    {
+      Collectd.logError ("GenericJMXConfValue: Cannot convert list of "
+          + "objects to numbers.");
+      return;
+    }
+
+    if (instancePrefix == null)
+      vl.setTypeInstance ("");
+    else
+      vl.setTypeInstance (instancePrefix);
+    vl.setValues (values);
+
+    Collectd.dispatchValues (vl);
+  } /* }}} void submitScalar */
+
+  private Object queryAttributeRecursive (CompositeData parent, /* {{{ */
+      List<String> attrName)
+  {
+    String key;
+    Object value;
+
+    key = attrName.remove (0);
+
+    try
+    {
+      value = parent.get (key);
+    }
+    catch (InvalidKeyException e)
+    {
+      return (null);
+    }
+
+    if (attrName.size () == 0)
+    {
+      return (value);
+    }
+    else
+    {
+      if (value instanceof CompositeData)
+        return (queryAttributeRecursive ((CompositeData) value, attrName));
+      else
+        return (null);
+    }
+  } /* }}} queryAttributeRecursive */
+
+  private Object queryAttribute (MBeanServerConnection conn, /* {{{ */
+      ObjectName objName, String attrName)
+  {
+    List<String> attrNameList;
+    String key;
+    Object value;
+    String[] attrNameArray;
+
+    attrNameList = new ArrayList<String> ();
+
+    attrNameArray = attrName.split ("\\.");
+    key = attrNameArray[0];
+    for (int i = 1; i < attrNameArray.length; i++)
+      attrNameList.add (attrNameArray[i]);
+
+    try
+    {
+      try
+      {
+        value = conn.getAttribute (objName, key);
+      }
+      catch (javax.management.AttributeNotFoundException e)
+      {
+        value = conn.invoke (objName, key, /* args = */ null, /* types = */ null);
+      }
+    }
+    catch (Exception e)
+    {
+      Collectd.logError ("GenericJMXConfValue.query: getAttribute failed: "
+          + e);
+      return (null);
+    }
+
+    if (attrNameList.size () == 0)
+    {
+      return (value);
+    }
+    else
+    {
+      if (value instanceof CompositeData)
+        return (queryAttributeRecursive((CompositeData) value, attrNameList));
+      else if (value instanceof OpenType)
+      {
+        OpenType ot = (OpenType) value;
+        Collectd.logNotice ("GenericJMXConfValue: Handling of OpenType \""
+            + ot.getTypeName () + "\" is not yet implemented.");
+        return (null);
+      }
+      else
+      {
+        Collectd.logError ("GenericJMXConfValue: Received object of "
+            + "unknown class.");
+        return (null);
+      }
+    }
+  } /* }}} Object queryAttribute */
+
+  private String join (String separator, List<String> list) /* {{{ */
+  {
+    StringBuffer sb;
+
+    sb = new StringBuffer ();
+
+    for (int i = 0; i < list.size (); i++)
+    {
+      if (i > 0)
+        sb.append ("-");
+      sb.append (list.get (i));
+    }
+
+    return (sb.toString ());
+  } /* }}} String join */
+
+  private String getConfigString (OConfigItem ci) /* {{{ */
+  {
+    List<OConfigValue> values;
+    OConfigValue v;
+
+    values = ci.getValues ();
+    if (values.size () != 1)
+    {
+      Collectd.logError ("GenericJMXConfValue: The " + ci.getKey ()
+          + " configuration option needs exactly one string argument.");
+      return (null);
+    }
+
+    v = values.get (0);
+    if (v.getType () != OConfigValue.OCONFIG_TYPE_STRING)
+    {
+      Collectd.logError ("GenericJMXConfValue: The " + ci.getKey ()
+          + " configuration option needs exactly one string argument.");
+      return (null);
+    }
+
+    return (v.getString ());
+  } /* }}} String getConfigString */
+
+  private Boolean getConfigBoolean (OConfigItem ci) /* {{{ */
+  {
+    List<OConfigValue> values;
+    OConfigValue v;
+    Boolean b;
+
+    values = ci.getValues ();
+    if (values.size () != 1)
+    {
+      Collectd.logError ("GenericJMXConfValue: The " + ci.getKey ()
+          + " configuration option needs exactly one boolean argument.");
+      return (null);
+    }
+
+    v = values.get (0);
+    if (v.getType () != OConfigValue.OCONFIG_TYPE_BOOLEAN)
+    {
+      Collectd.logError ("GenericJMXConfValue: The " + ci.getKey ()
+          + " configuration option needs exactly one boolean argument.");
+      return (null);
+    }
+
+    return (new Boolean (v.getBoolean ()));
+  } /* }}} String getConfigBoolean */
+
+  /**
+   * Constructs a new value with the configured properties.
+   */
+  public GenericJMXConfValue (OConfigItem ci) /* {{{ */
+    throws IllegalArgumentException
+  {
+    List<OConfigItem> children;
+    Iterator<OConfigItem> iter;
+
+    this._ds_name = null;
+    this._ds = null;
+    this._attributes = new ArrayList<String> ();
+    this._instance_prefix = null;
+    this._instance_from = new ArrayList<String> ();
+    this._is_table = false;
+
+    /*
+     * <Value>
+     *   Type "memory"
+     *   Table true|false
+     *   Attribute "HeapMemoryUsage"
+     *   Attribute "..."
+     *   :
+     *   # Type instance:
+     *   InstancePrefix "heap-"
+     * </Value>
+     */
+    children = ci.getChildren ();
+    iter = children.iterator ();
+    while (iter.hasNext ())
+    {
+      OConfigItem child = iter.next ();
+
+      if (child.getKey ().equalsIgnoreCase ("Type"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._ds_name = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("Table"))
+      {
+        Boolean tmp = getConfigBoolean (child);
+        if (tmp != null)
+          this._is_table = tmp.booleanValue ();
+      }
+      else if (child.getKey ().equalsIgnoreCase ("Attribute"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._attributes.add (tmp);
+      }
+      else if (child.getKey ().equalsIgnoreCase ("InstancePrefix"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._instance_prefix = tmp;
+      }
+      else if (child.getKey ().equalsIgnoreCase ("InstanceFrom"))
+      {
+        String tmp = getConfigString (child);
+        if (tmp != null)
+          this._instance_from.add (tmp);
+      }
+      else
+        throw (new IllegalArgumentException ("Unknown option: "
+              + child.getKey ()));
+    }
+
+    if (this._ds_name == null)
+      throw (new IllegalArgumentException ("No data set was defined."));
+    else if (this._attributes.size () == 0)
+      throw (new IllegalArgumentException ("No attribute was defined."));
+  } /* }}} GenericJMXConfValue (OConfigItem ci) */
+
+  /**
+   * Query values via JMX according to the object's configuration and dispatch
+   * them to collectd.
+   *
+   * @param conn    Connection to the MBeanServer.
+   * @param objName Object name of the MBean to query.
+   * @param pd      Preset naming components. The members host, plugin and
+   *                plugin instance will be used.
+   */
+  public void query (MBeanServerConnection conn, ObjectName objName, /* {{{ */
+      PluginData pd)
+  {
+    ValueList vl;
+    List<DataSource> dsrc;
+    List<Object> values;
+    List<String> instanceList;
+    String instancePrefix;
+
+    if (this._ds == null)
+    {
+      this._ds = Collectd.getDS (this._ds_name);
+      if (this._ds == null)
+      {
+        Collectd.logError ("GenericJMXConfValue: Unknown type: "
+            + this._ds_name);
+        return;
+      }
+    }
+
+    dsrc = this._ds.getDataSources ();
+    if (dsrc.size () != this._attributes.size ())
+    {
+      Collectd.logError ("GenericJMXConfValue.query: The data set "
+          + this._ds_name + " has " + this._ds.getDataSources ().size ()
+          + " data sources, but there were " + this._attributes.size ()
+          + " attributes configured. This doesn't match!");
+      this._ds = null;
+      return;
+    }
+
+    vl = new ValueList (pd);
+    vl.setType (this._ds_name);
+
+    /*
+     * Build the instnace prefix from the fixed string prefix and the
+     * properties of the objName.
+     */
+    instanceList = new ArrayList<String> ();
+    for (int i = 0; i < this._instance_from.size (); i++)
+    {
+      String propertyName;
+      String propertyValue;
+
+      propertyName = this._instance_from.get (i);
+      propertyValue = objName.getKeyProperty (propertyName);
+      if (propertyValue == null)
+      {
+        Collectd.logError ("GenericJMXConfMBean: "
+            + "No such property in object name: " + propertyName);
+      }
+      else
+      {
+        instanceList.add (propertyValue);
+      }
+    }
+
+    if (this._instance_prefix != null)
+      instancePrefix = new String (this._instance_prefix
+          + join ("-", instanceList));
+    else
+      instancePrefix = join ("-", instanceList);
+
+    /*
+     * Build a list of `Object's which is then passed to `submitTable' and
+     * `submitScalar'.
+     */
+    values = new ArrayList<Object> ();
+    assert (dsrc.size () == this._attributes.size ());
+    for (int i = 0; i < this._attributes.size (); i++)
+    {
+      Object v;
+
+      v = queryAttribute (conn, objName, this._attributes.get (i));
+      if (v == null)
+      {
+        Collectd.logError ("GenericJMXConfValue.query: "
+            + "Querying attribute " + this._attributes.get (i) + " failed.");
+        return;
+      }
+
+      values.add (v);
+    }
+
+    if (this._is_table)
+      submitTable (values, vl, instancePrefix);
+    else
+      submitScalar (values, vl, instancePrefix);
+  } /* }}} void query */
+} /* class GenericJMXConfValue */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/java/org/collectd/java/JMXMemory.java b/bindings/java/org/collectd/java/JMXMemory.java
new file mode 100644 (file)
index 0000000..050d893
--- /dev/null
@@ -0,0 +1,237 @@
+/**
+ * collectd - bindings/java/org/collectd/java/JMXMemory.java
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+package org.collectd.java;
+
+import java.util.List;
+import java.util.Date;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryUsage;
+import java.lang.management.MemoryMXBean;
+
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import org.collectd.api.Collectd;
+import org.collectd.api.DataSet;
+import org.collectd.api.ValueList;
+import org.collectd.api.Notification;
+import org.collectd.api.OConfigItem;
+
+import org.collectd.api.CollectdConfigInterface;
+import org.collectd.api.CollectdInitInterface;
+import org.collectd.api.CollectdReadInterface;
+import org.collectd.api.CollectdShutdownInterface;
+
+import org.collectd.api.OConfigValue;
+import org.collectd.api.OConfigItem;
+
+public class JMXMemory implements CollectdConfigInterface,
+       CollectdInitInterface,
+       CollectdReadInterface,
+       CollectdShutdownInterface
+{
+  private String _jmx_service_url = null;
+  private MemoryMXBean _mbean = null;
+
+  public JMXMemory ()
+  {
+    Collectd.registerConfig   ("JMXMemory", this);
+    Collectd.registerInit     ("JMXMemory", this);
+    Collectd.registerRead     ("JMXMemory", this);
+    Collectd.registerShutdown ("JMXMemory", this);
+  }
+
+  private void submit (String plugin_instance, MemoryUsage usage) /* {{{ */
+  {
+    ValueList vl;
+
+    long mem_init;
+    long mem_used;
+    long mem_committed;
+    long mem_max;
+
+    mem_init = usage.getInit ();
+    mem_used = usage.getUsed ();
+    mem_committed = usage.getCommitted ();
+    mem_max = usage.getMax ();
+
+    Collectd.logDebug ("JMXMemory plugin: plugin_instance = " + plugin_instance + "; "
+        + "mem_init = " + mem_init + "; "
+        + "mem_used = " + mem_used + "; "
+        + "mem_committed = " + mem_committed + "; "
+        + "mem_max = " + mem_max + ";");
+
+    vl = new ValueList ();
+
+    vl.setHost ("localhost");
+    vl.setPlugin ("JMXMemory");
+    vl.setPluginInstance (plugin_instance);
+    vl.setType ("memory");
+
+    if (mem_init >= 0)
+    {
+      vl.addValue (mem_init);
+      vl.setTypeInstance ("init");
+      Collectd.dispatchValues (vl);
+      vl.clearValues ();
+    }
+
+    if (mem_used >= 0)
+    {
+      vl.addValue (mem_used);
+      vl.setTypeInstance ("used");
+      Collectd.dispatchValues (vl);
+      vl.clearValues ();
+    }
+
+    if (mem_committed >= 0)
+    {
+      vl.addValue (mem_committed);
+      vl.setTypeInstance ("committed");
+      Collectd.dispatchValues (vl);
+      vl.clearValues ();
+    }
+
+    if (mem_max >= 0)
+    {
+      vl.addValue (mem_max);
+      vl.setTypeInstance ("max");
+      Collectd.dispatchValues (vl);
+      vl.clearValues ();
+    }
+  } /* }}} void submit */
+
+  private int configServiceURL (OConfigItem ci) /* {{{ */
+  {
+    List<OConfigValue> values;
+    OConfigValue cv;
+
+    values = ci.getValues ();
+    if (values.size () != 1)
+    {
+      Collectd.logError ("JMXMemory plugin: The JMXServiceURL option needs "
+          + "exactly one string argument.");
+      return (-1);
+    }
+
+    cv = values.get (0);
+    if (cv.getType () != OConfigValue.OCONFIG_TYPE_STRING)
+    {
+      Collectd.logError ("JMXMemory plugin: The JMXServiceURL option needs "
+          + "exactly one string argument.");
+      return (-1);
+    }
+
+    _jmx_service_url = cv.getString ();
+    return (0);
+  } /* }}} int configServiceURL */
+
+  public int config (OConfigItem ci) /* {{{ */
+  {
+    List<OConfigItem> children;
+    int i;
+
+    Collectd.logDebug ("JMXMemory plugin: config: ci = " + ci + ";");
+
+    children = ci.getChildren ();
+    for (i = 0; i < children.size (); i++)
+    {
+      OConfigItem child;
+      String key;
+
+      child = children.get (i);
+      key = child.getKey ();
+      if (key.equalsIgnoreCase ("JMXServiceURL"))
+      {
+        configServiceURL (child);
+      }
+      else
+      {
+        Collectd.logError ("JMXMemory plugin: Unknown config option: " + key);
+      }
+    }
+
+    return (0);
+  } /* }}} int config */
+
+  public int init () /* {{{ */
+  {
+    JMXServiceURL service_url;
+    JMXConnector connector;
+    MBeanServerConnection connection;
+
+    if (_jmx_service_url == null)
+    {
+      Collectd.logError ("JMXMemory: _jmx_service_url == null");
+      return (-1);
+    }
+
+    try
+    {
+      service_url = new JMXServiceURL (_jmx_service_url);
+      connector = JMXConnectorFactory.connect (service_url);
+      connection = connector.getMBeanServerConnection ();
+      _mbean = ManagementFactory.newPlatformMXBeanProxy (connection,
+          ManagementFactory.MEMORY_MXBEAN_NAME,
+          MemoryMXBean.class);
+    }
+    catch (Exception e)
+    {
+      Collectd.logError ("JMXMemory: Creating MBean failed: " + e);
+      return (-1);
+    }
+
+    return (0);
+  } /* }}} int init */
+
+  public int read () /* {{{ */
+  {
+    if (_mbean == null)
+    {
+      Collectd.logError ("JMXMemory: _mbean == null");
+      return (-1);
+    }
+
+    submit ("heap", _mbean.getHeapMemoryUsage ());
+    submit ("non_heap", _mbean.getNonHeapMemoryUsage ());
+
+    return (0);
+  } /* }}} int read */
+
+  public int shutdown () /* {{{ */
+  {
+    System.out.print ("org.collectd.java.JMXMemory.Shutdown ();\n");
+    _jmx_service_url = null;
+    _mbean = null;
+    return (0);
+  } /* }}} int shutdown */
+} /* class JMXMemory */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/bindings/perl/Makefile.PL b/bindings/perl/Makefile.PL
new file mode 100644 (file)
index 0000000..68fb260
--- /dev/null
@@ -0,0 +1,9 @@
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+       NAME                    => 'Collectd',
+       AUTHOR                  => 'Sebastian Harl <sh@tokkee.org>',
+       TEST_REQUIRES   => { 'YAML::Any' => 0 },
+);
+
+# vim: set sw=4 ts=4 tw=78 noexpandtab :
diff --git a/bindings/perl/lib/Collectd.pm b/bindings/perl/lib/Collectd.pm
new file mode 100644 (file)
index 0000000..c1adf44
--- /dev/null
@@ -0,0 +1,637 @@
+# collectd - Collectd.pm
+# Copyright (C) 2007-2009  Sebastian Harl
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# 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:
+#   Sebastian Harl <sh at tokkee.org>
+
+package Collectd;
+
+use strict;
+use warnings;
+
+use Config;
+
+use threads;
+use threads::shared;
+
+BEGIN {
+       if (! $Config{'useithreads'}) {
+               die "Perl does not support ithreads!";
+       }
+}
+
+require Exporter;
+
+our @ISA = qw( Exporter );
+
+our %EXPORT_TAGS = (
+       'plugin' => [ qw(
+                       plugin_register
+                       plugin_unregister
+                       plugin_dispatch_values
+                       plugin_get_interval
+                       plugin_write
+                       plugin_flush
+                       plugin_flush_one
+                       plugin_flush_all
+                       plugin_dispatch_notification
+                       plugin_log
+       ) ],
+       'types' => [ qw(
+                       TYPE_INIT
+                       TYPE_READ
+                       TYPE_WRITE
+                       TYPE_SHUTDOWN
+                       TYPE_LOG
+                       TYPE_NOTIF
+                       TYPE_FLUSH
+                       TYPE_CONFIG
+                       TYPE_DATASET
+       ) ],
+       'ds_types' => [ qw(
+                       DS_TYPE_COUNTER
+                       DS_TYPE_GAUGE
+       ) ],
+       'log' => [ qw(
+                       ERROR
+                       WARNING
+                       NOTICE
+                       INFO
+                       DEBUG
+                       LOG_ERR
+                       LOG_WARNING
+                       LOG_NOTICE
+                       LOG_INFO
+                       LOG_DEBUG
+       ) ],
+       'filter_chain' => [ qw(
+                       fc_register
+                       FC_MATCH_NO_MATCH
+                       FC_MATCH_MATCHES
+                       FC_TARGET_CONTINUE
+                       FC_TARGET_STOP
+                       FC_TARGET_RETURN
+       ) ],
+       'fc_types' => [ qw(
+                       FC_MATCH
+                       FC_TARGET
+       ) ],
+       'notif' => [ qw(
+                       NOTIF_FAILURE
+                       NOTIF_WARNING
+                       NOTIF_OKAY
+       ) ],
+       'globals' => [ qw(
+                       $hostname_g
+                       $interval_g
+       ) ],
+);
+
+{
+       my %seen;
+       push @{$EXPORT_TAGS{'all'}}, grep {! $seen{$_}++ } @{$EXPORT_TAGS{$_}}
+               foreach keys %EXPORT_TAGS;
+}
+
+# global variables
+our $hostname_g;
+our $interval_g;
+
+Exporter::export_ok_tags ('all');
+
+my @plugins : shared = ();
+my @fc_plugins : shared = ();
+my %cf_callbacks : shared = ();
+
+my %types = (
+       TYPE_CONFIG,   "config",
+       TYPE_INIT,     "init",
+       TYPE_READ,     "read",
+       TYPE_WRITE,    "write",
+       TYPE_SHUTDOWN, "shutdown",
+       TYPE_LOG,      "log",
+       TYPE_NOTIF,    "notify",
+       TYPE_FLUSH,    "flush"
+);
+
+my %fc_types = (
+       FC_MATCH,  "match",
+       FC_TARGET, "target"
+);
+
+my %fc_exec_names = (
+       FC_MATCH,  "match",
+       FC_TARGET, "invoke"
+);
+
+my %fc_cb_types = (
+       FC_CB_EXEC, "exec",
+       FC_CB_CREATE, "create",
+       FC_CB_DESTROY, "destroy"
+);
+
+foreach my $type (keys %types) {
+       $plugins[$type] = &share ({});
+}
+
+foreach my $type (keys %fc_types) {
+       $fc_plugins[$type] = &share ({});
+}
+
+sub _log {
+       my $caller = shift;
+       my $lvl    = shift;
+       my $msg    = shift;
+
+       if ("Collectd" eq $caller) {
+               $msg = "perl: $msg";
+       }
+       return plugin_log ($lvl, $msg);
+}
+
+sub ERROR   { _log (scalar caller, LOG_ERR,     shift); }
+sub WARNING { _log (scalar caller, LOG_WARNING, shift); }
+sub NOTICE  { _log (scalar caller, LOG_NOTICE,  shift); }
+sub INFO    { _log (scalar caller, LOG_INFO,    shift); }
+sub DEBUG   { _log (scalar caller, LOG_DEBUG,   shift); }
+
+sub plugin_call_all {
+       my $type = shift;
+
+       my %plugins;
+       my $interval;
+
+       our $cb_name = undef;
+
+       if (! defined $type) {
+               return;
+       }
+
+       if (TYPE_LOG != $type) {
+               DEBUG ("Collectd::plugin_call: type = \"$type\" ("
+                       . $types{$type} . "), args=\""
+                       . join(', ', map { defined($_) ? $_ : '<undef>' } @_) . "\"");
+       }
+
+       if (! defined $plugins[$type]) {
+               ERROR ("Collectd::plugin_call: unknown type \"$type\"");
+               return;
+       }
+
+       {
+               lock %{$plugins[$type]};
+               %plugins = %{$plugins[$type]};
+       }
+
+       $interval = plugin_get_interval ();
+
+       foreach my $plugin (keys %plugins) {
+               my $p = $plugins{$plugin};
+
+               my $status = 0;
+
+               if ($p->{'wait_left'} > 0) {
+                       $p->{'wait_left'} -= $interval;
+               }
+
+               next if ($p->{'wait_left'} > 0);
+
+               $cb_name = $p->{'cb_name'};
+               $status = call_by_name (@_);
+
+               if (! $status) {
+                       my $err = undef;
+
+                       if ($@) {
+                               $err = $@;
+                       }
+                       else {
+                               $err = "callback returned false";
+                       }
+
+                       if (TYPE_LOG != $type) {
+                               ERROR ("Execution of callback \"$cb_name\" failed: $err");
+                       }
+
+                       $status = 0;
+               }
+
+               if ($status) {
+                       $p->{'wait_left'} = 0;
+                       $p->{'wait_time'} = $interval;
+               }
+               elsif (TYPE_READ == $type) {
+                       if ($p->{'wait_time'} < $interval) {
+                               $p->{'wait_time'} = $interval;
+                       }
+
+                       $p->{'wait_left'} = $p->{'wait_time'};
+                       $p->{'wait_time'} *= 2;
+
+                       if ($p->{'wait_time'} > 86400) {
+                               $p->{'wait_time'} = 86400;
+                       }
+
+                       WARNING ("${plugin}->read() failed with status $status. "
+                               . "Will suspend it for $p->{'wait_left'} seconds.");
+               }
+               elsif (TYPE_INIT == $type) {
+                       ERROR ("${plugin}->init() failed with status $status. "
+                               . "Plugin will be disabled.");
+
+                       foreach my $type (keys %types) {
+                               plugin_unregister ($type, $plugin);
+                       }
+               }
+               elsif (TYPE_LOG != $type) {
+                       WARNING ("${plugin}->$types{$type}() failed with status $status.");
+               }
+       }
+       return 1;
+}
+
+# Collectd::plugin_register (type, name, data).
+#
+# type:
+#   init, read, write, shutdown, data set
+#
+# name:
+#   name of the plugin
+#
+# data:
+#   reference to the plugin's subroutine that does the work or the data set
+#   definition
+sub plugin_register {
+       my $type = shift;
+       my $name = shift;
+       my $data = shift;
+
+       DEBUG ("Collectd::plugin_register: "
+               . "type = \"$type\" (" . $types{$type}
+               . "), name = \"$name\", data = \"$data\"");
+
+       if (! ((defined $type) && (defined $name) && (defined $data))) {
+               ERROR ("Usage: Collectd::plugin_register (type, name, data)");
+               return;
+       }
+
+       if ((! defined $plugins[$type]) && (TYPE_DATASET != $type)
+                       && (TYPE_CONFIG != $type)) {
+               ERROR ("Collectd::plugin_register: Invalid type \"$type\"");
+               return;
+       }
+
+       if ((TYPE_DATASET == $type) && ("ARRAY" eq ref $data)) {
+               return plugin_register_data_set ($name, $data);
+       }
+       elsif ((TYPE_CONFIG == $type) && (! ref $data)) {
+               my $pkg = scalar caller;
+
+               if ($data !~ m/^$pkg\:\:/) {
+                       $data = $pkg . "::" . $data;
+               }
+
+               lock %cf_callbacks;
+               $cf_callbacks{$name} = $data;
+       }
+       elsif ((TYPE_DATASET != $type) && (! ref $data)) {
+               my $pkg = scalar caller;
+
+               my %p : shared;
+
+               if ($data !~ m/^$pkg\:\:/) {
+                       $data = $pkg . "::" . $data;
+               }
+
+               %p = (
+                       wait_time => plugin_get_interval (),
+                       wait_left => 0,
+                       cb_name   => $data,
+               );
+
+               lock %{$plugins[$type]};
+               $plugins[$type]->{$name} = \%p;
+       }
+       else {
+               ERROR ("Collectd::plugin_register: Invalid data.");
+               return;
+       }
+       return 1;
+}
+
+sub plugin_unregister {
+       my $type = shift;
+       my $name = shift;
+
+       DEBUG ("Collectd::plugin_unregister: type = \"$type\" ("
+               . $types{$type} . "), name = \"$name\"");
+
+       if (! ((defined $type) && (defined $name))) {
+               ERROR ("Usage: Collectd::plugin_unregister (type, name)");
+               return;
+       }
+
+       if (TYPE_DATASET == $type) {
+               return plugin_unregister_data_set ($name);
+       }
+       elsif (TYPE_CONFIG == $type) {
+               lock %cf_callbacks;
+               delete $cf_callbacks{$name};
+       }
+       elsif (defined $plugins[$type]) {
+               lock %{$plugins[$type]};
+               delete $plugins[$type]->{$name};
+       }
+       else {
+               ERROR ("Collectd::plugin_unregister: Invalid type.");
+               return;
+       }
+}
+
+sub plugin_write {
+       my %args = @_;
+
+       my @plugins    = ();
+       my @datasets   = ();
+       my @valuelists = ();
+
+       if (! defined $args{'valuelists'}) {
+               ERROR ("Collectd::plugin_write: Missing 'valuelists' argument.");
+               return;
+       }
+
+       DEBUG ("Collectd::plugin_write:"
+               . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "")
+               . (defined ($args{'datasets'}) ? " datasets = $args{'datasets'}" : "")
+               . " valueslists = $args{'valuelists'}");
+
+       if (defined ($args{'plugins'})) {
+               if ("ARRAY" eq ref ($args{'plugins'})) {
+                       @plugins = @{$args{'plugins'}};
+               }
+               else {
+                       @plugins = ($args{'plugins'});
+               }
+       }
+       else {
+               @plugins = (undef);
+       }
+
+       if ("ARRAY" eq ref ($args{'valuelists'})) {
+               @valuelists = @{$args{'valuelists'}};
+       }
+       else {
+               @valuelists = ($args{'valuelists'});
+       }
+
+       if (defined ($args{'datasets'})) {
+               if ("ARRAY" eq ref ($args{'datasets'})) {
+                       @datasets = @{$args{'datasets'}};
+               }
+               else {
+                       @datasets = ($args{'datasets'});
+               }
+       }
+       else {
+               @datasets = (undef) x scalar (@valuelists);
+       }
+
+       if ($#datasets != $#valuelists) {
+               ERROR ("Collectd::plugin_write: Invalid number of datasets.");
+               return;
+       }
+
+       foreach my $plugin (@plugins) {
+               for (my $i = 0; $i < scalar (@valuelists); ++$i) {
+                       _plugin_write ($plugin, $datasets[$i], $valuelists[$i]);
+               }
+       }
+}
+
+sub plugin_flush {
+       my %args = @_;
+
+       my $timeout = -1;
+       my @plugins = ();
+       my @ids     = ();
+
+       DEBUG ("Collectd::plugin_flush:"
+               . (defined ($args{'timeout'}) ? " timeout = $args{'timeout'}" : "")
+               . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "")
+               . (defined ($args{'identifiers'})
+                       ? " identifiers = $args{'identifiers'}" : ""));
+
+       if (defined ($args{'timeout'}) && ($args{'timeout'} > 0)) {
+               $timeout = $args{'timeout'};
+       }
+
+       if (defined ($args{'plugins'})) {
+               if ("ARRAY" eq ref ($args{'plugins'})) {
+                       @plugins = @{$args{'plugins'}};
+               }
+               else {
+                       @plugins = ($args{'plugins'});
+               }
+       }
+       else {
+               @plugins = (undef);
+       }
+
+       if (defined ($args{'identifiers'})) {
+               if ("ARRAY" eq ref ($args{'identifiers'})) {
+                       @ids = @{$args{'identifiers'}};
+               }
+               else {
+                       @ids = ($args{'identifiers'});
+               }
+       }
+       else {
+               @ids = (undef);
+       }
+
+       foreach my $plugin (@plugins) {
+               foreach my $id (@ids) {
+                       _plugin_flush($plugin, $timeout, $id);
+               }
+       }
+}
+
+sub fc_call {
+       my $type    = shift;
+       my $name    = shift;
+       my $cb_type = shift;
+
+       my %proc;
+
+       our $cb_name = undef;
+       my  $status;
+
+       if (! ((defined $type) && (defined $name) && (defined $cb_type))) {
+               ERROR ("Usage: Collectd::fc_call(type, name, cb_type, ...)");
+               return;
+       }
+
+       if (! defined $fc_plugins[$type]) {
+               ERROR ("Collectd::fc_call: Invalid type \"$type\"");
+               return;
+       }
+
+       if (! defined $fc_plugins[$type]->{$name}) {
+               ERROR ("Collectd::fc_call: Unknown "
+                       . ($type == FC_MATCH ? "match" : "target")
+                       . " \"$name\"");
+               return;
+       }
+
+       DEBUG ("Collectd::fc_call: "
+               . "type = \"$type\" (" . $fc_types{$type}
+               . "), name = \"$name\", cb_type = \"$cb_type\" ("
+               . $fc_cb_types{$cb_type} . ")");
+
+       {
+               lock %{$fc_plugins[$type]};
+               %proc = %{$fc_plugins[$type]->{$name}};
+       }
+
+       if (FC_CB_EXEC == $cb_type) {
+               $cb_name = $proc{$fc_exec_names{$type}};
+       }
+       elsif (FC_CB_CREATE == $cb_type) {
+               if (defined $proc{'create'}) {
+                       $cb_name = $proc{'create'};
+               }
+               else {
+                       return 1;
+               }
+       }
+       elsif (FC_CB_DESTROY == $cb_type) {
+               if (defined $proc{'destroy'}) {
+                       $cb_name = $proc{'destroy'};
+               }
+               else {
+                       return 1;
+               }
+       }
+
+       $status = call_by_name (@_);
+
+       if ($status < 0) {
+               my $err = undef;
+
+               if ($@) {
+                       $err = $@;
+               }
+               else {
+                       $err = "callback returned false";
+               }
+
+               ERROR ("Execution of fc callback \"$cb_name\" failed: $err");
+               return;
+       }
+       return $status;
+}
+
+sub fc_register {
+       my $type = shift;
+       my $name = shift;
+       my $proc = shift;
+
+       my %fc : shared;
+
+       DEBUG ("Collectd::fc_register: "
+               . "type = \"$type\" (" . $fc_types{$type}
+               . "), name = \"$name\", proc = \"$proc\"");
+
+       if (! ((defined $type) && (defined $name) && (defined $proc))) {
+               ERROR ("Usage: Collectd::fc_register(type, name, proc)");
+               return;
+       }
+
+       if (! defined $fc_plugins[$type]) {
+               ERROR ("Collectd::fc_register: Invalid type \"$type\"");
+               return;
+       }
+
+       if (("HASH" ne ref ($proc)) || (! defined $proc->{$fc_exec_names{$type}})
+                       || ("" ne ref ($proc->{$fc_exec_names{$type}}))) {
+               ERROR ("Collectd::fc_register: Invalid proc.");
+               return;
+       }
+
+       for my $p (qw( create destroy )) {
+               if ((defined $proc->{$p}) && ("" ne ref ($proc->{$p}))) {
+                       ERROR ("Collectd::fc_register: Invalid proc.");
+                       return;
+               }
+       }
+
+       %fc = %$proc;
+
+       foreach my $p (keys %fc) {
+               my $pkg = scalar caller;
+
+               if ($p !~ m/^(create|destroy|$fc_exec_names{$type})$/) {
+                       next;
+               }
+
+               if ($fc{$p} !~ m/^$pkg\:\:/) {
+                       $fc{$p} = $pkg . "::" . $fc{$p};
+               }
+       }
+
+       lock %{$fc_plugins[$type]};
+       if (defined $fc_plugins[$type]->{$name}) {
+               WARNING ("Collectd::fc_register: Overwriting previous "
+                       . "definition of match \"$name\".");
+       }
+
+       if (! _fc_register ($type, $name)) {
+               ERROR ("Collectd::fc_register: Failed to register \"$name\".");
+               return;
+       }
+
+       $fc_plugins[$type]->{$name} = \%fc;
+       return 1;
+}
+
+sub _plugin_dispatch_config {
+       my $plugin = shift;
+       my $config = shift;
+
+       our $cb_name = undef;
+
+       if (! (defined ($plugin) && defined ($config))) {
+               return;
+       }
+
+       if (! defined $cf_callbacks{$plugin}) {
+               WARNING ("Found a configuration for the \"$plugin\" plugin, but "
+                       . "the plugin isn't loaded or didn't register "
+                       . "a configuration callback.");
+               return;
+       }
+
+       {
+               lock %cf_callbacks;
+               $cb_name = $cf_callbacks{$plugin};
+       }
+       call_by_name ($config);
+}
+
+1;
+
+# vim: set sw=4 ts=4 tw=78 noexpandtab :
+
diff --git a/bindings/perl/lib/Collectd/Plugins/Monitorus.pm b/bindings/perl/lib/Collectd/Plugins/Monitorus.pm
new file mode 100644 (file)
index 0000000..7054fbf
--- /dev/null
@@ -0,0 +1,104 @@
+#
+# collectd - mon.itor.us collectd plugin
+# Copyright (C) 2009  Jeff Green
+#
+# 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:
+#   Jeff Green <jeff at kikisoso.org>
+#
+
+package Collectd::Plugins::Monitorus;
+
+use strict;
+use warnings;
+
+use Collectd qw( :all );
+use LWP;
+use threads::shared;
+
+use constant NUM_OF_INTERVALS => 90;
+
+my $intervalcnt :shared;
+$intervalcnt=NUM_OF_INTERVALS;
+my $prev_value :shared;
+$prev_value=0;
+
+plugin_register (TYPE_READ, "monitorus", "monitorus_read");
+
+sub monitorus_read
+{
+        my $vl = { plugin => 'monitorus', type => 'gauge' };
+
+        # Only retrieve a value occasionally in order to not overload mon.itor.us
+        if (++$intervalcnt<NUM_OF_INTERVALS) { # e.g. 180 * 10 secs / 60 seconds/min = 30 minutes
+                $vl->{'values'} = [ $prev_value ];
+                plugin_dispatch_values ($vl);
+                return 1;
+        }
+
+        $intervalcnt=0;
+
+        my $site = 'http://mon.itor.us';
+        my $username = 'me@example.org';
+        my $target = $site.'/user/api/'.$username.'/secretpassword';
+
+        my $ua = LWP::UserAgent->new;
+        my $req = HTTP::Request->new(GET => "$target");
+        $req->header('Accept' => 'text/html');          #Accept HTML Page
+
+        my $key;
+        my $res = $ua->get($target);
+        if ($res->is_success) {# Success....all content of page has been received
+                $res->content() =~ m/\[CDATA\[(.*)\]\]/;
+                $key = $1;
+        } else {
+                INFO("monitorus: Error in retrieving login page.");
+        }
+
+        $target = $site.'/test/api/'.$key.'/testNames';
+        my $testid;
+        $res = $ua->get($target);
+        if ($res->is_success) {# Success....all content of page has been received
+                $res->content() =~ m/<test id='(.*)'><!\[CDATA\[sitetest_http\]\]/;
+                $testid = $1;
+        } else {
+                INFO("monitorus: Error in retrieving testNames page.");
+        }
+
+        #$target = $site.'/test/api/'.$key.'/testinfo/'.$testid.'/-240';
+        #$target = $site.'/test/api/'.$key.'/test/'.$testid.'/27/5/2009/1/3/-240';
+        $target = $site.'/test/api/'.$key.'/testsLastValues/1/3';
+
+        my $result;
+        my $value;
+        $res = $ua->get($target);
+        if ($res->is_success) {# Success....all content of page has been received
+                $res->content() =~ m/\<\/row\>\s*(\<row\>.*?sitetest_http.*?\<\/row\>)/s;
+                $result = $1;
+                $result =~ s/\<cell\>.*?CDATA.*?\<\/cell\>//g;
+                $result =~ m|\<cell\>([0-9]*)\<\/cell\>|;
+                $value = $1;
+        } else {
+                INFO("monitorus: Error in retrieving testsLastValues page.");
+        }
+
+        $prev_value = $value;
+        $vl->{'values'} = [ $value ];
+        plugin_dispatch_values ($vl);
+
+        return 1;
+}
+
+1;
diff --git a/bindings/perl/lib/Collectd/Plugins/OpenVZ.pm b/bindings/perl/lib/Collectd/Plugins/OpenVZ.pm
new file mode 100644 (file)
index 0000000..4c7c3fe
--- /dev/null
@@ -0,0 +1,247 @@
+#
+# collectd - OpenVZ collectd plugin
+# Copyright (C) 2009  Jonathan Kolb
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#
+# Author:
+#   Jonathan Kolb <jon at b0g.us>
+#
+
+package Collectd::Plugins::OpenVZ;
+
+use strict;
+use warnings;
+
+use Collectd qw( :all );
+
+my $vzctl = '/usr/sbin/vzctl';
+my $vzlist = '/usr/sbin/vzlist';
+
+# Since OpenVZ is container based, all guests see all the host's CPUs,
+# and would report the same data. So we disable CPU by default.
+my $enable_interface = 1;
+my $enable_cpu       = 0;
+my $enable_df        = 1;
+my $enable_load      = 1;
+my $enable_processes = 1;
+my $enable_users     = 1;
+
+# We probably don't care about loopback transfer
+my @ignored_interfaces = ( "lo" );
+
+sub interface_read {
+    my ($veid, $name) = @_;
+    my @rx_fields = qw(if_octets if_packets if_errors drop fifo frame compressed multicast);
+    my @tx_fields = qw(if_octets if_packets if_errors drop fifo frame compressed);
+    my %v = _build_report_hash($name);
+
+    my @lines = `$vzctl exec $veid cat /proc/net/dev`;
+
+    for my $line (@lines) {
+        # skip explanatory text
+        next if $line !~ /:/;
+
+        $line =~ s/^\s+|\s+$//g;
+
+        my ($iface, %rx, %tx);
+
+        # read /proc/net/dev fields
+        ($iface, @rx{@rx_fields}, @tx{@tx_fields}) = split /[: ]+/, $line;
+
+        # Skip this interface if it is in the ignored list
+        next if grep { $iface eq $_ } @ignored_interfaces;
+
+        for my $instance (qw(if_octets if_packets if_errors)) {
+            plugin_dispatch_values({
+                'plugin'          => 'interface',
+                'plugin_instance' => $iface,
+                'type'            => $instance,
+                'values'          => [ $rx{$instance}, $tx{$instance} ],
+                %v,
+            });
+        }
+    }
+}
+
+sub cpu_read {
+    my $veid = shift;
+    my $name = shift;
+    my ($key, $val, $i, @lines, @counters);
+    my @cpu_instances = ('user', 'nice', 'system', 'idle', 'wait', 'interrupt', 'softirq', 'steal');
+    my $last_stat = {};
+    my %v = _build_report_hash($name);
+
+    $v{'plugin'} = 'cpu';
+    $v{'type'} = 'cpu';
+
+    $i = 0;
+    @lines = split(/\n/, `$vzctl exec $veid cat /proc/stat`);
+    foreach (@lines) {
+        next if (!/^cpu[0-9]/);
+
+        @counters = split(/ +/);
+        shift(@counters);
+
+        # Remove once OpenVZ bug 1376 is resolved
+        if (48485 == $counters[3]) {
+            $counters[3] = $last_stat->{"$veid-$i-idle"};
+            $counters[4] = $last_stat->{"$veid-$i-wait"};
+        }
+        else {
+            $last_stat->{"$veid-$i-idle"} = $counters[3];
+            $last_stat->{"$veid-$i-wait"} = $counters[4];
+        }
+
+        $v{'plugin_instance'} = $i++;
+        for ($key = 0; $key <= $#counters; ++$key) {
+            $v{'type_instance'} = $cpu_instances[$key];
+            $v{'values'} = [ $counters[$key] ];
+            plugin_dispatch_values(\%v);
+    }
+}
+}
+
+sub df_read {
+    my $veid = shift;
+    my $name = shift;
+    my ($key, $val, @lines, @parts);
+    my %v = _build_report_hash($name);
+
+    $v{'plugin'} = 'df';
+    delete $v{'plugin_instance'};
+    $v{'type'} = 'df';
+
+    $val = join(' ', map { (split)[1] } split(/\n/, `$vzctl exec $veid cat /proc/mounts`));
+    @lines = split(/\n/, `$vzctl exec $veid stat -tf $val`);
+    foreach (@lines) {
+        @parts = split(/ /);
+        next if (0 == $parts[7]);
+
+        $val = substr($parts[0], 1);
+        $val = 'root' if ($val =~ /^$/);
+        $val =~ s#/#-#g;
+
+        $v{'type_instance'} = $val;
+        $v{'values'} = [ $parts[5] * ($parts[6] - $parts[7]), $parts[5] * $parts[7] ];
+        plugin_dispatch_values(\%v);
+}
+}
+
+sub load_read {
+    my $veid = shift;
+    my $name = shift;
+    my ($key, $val, @lines, @parts);
+    my %v = _build_report_hash($name);
+
+    $v{'plugin'} = 'load';
+    delete $v{'plugin_instance'};
+    $v{'type'} = 'load';
+    delete $v{'type_instance'};
+
+    @parts = split(/ +/, `$vzctl exec $veid cat /proc/loadavg`);
+    $v{'values'} = [ $parts[0], $parts[1], $parts[2] ];
+    plugin_dispatch_values(\%v);
+}
+
+sub processes_read {
+    my $veid = shift;
+    my $name = shift;
+    my ($key, $val, @lines);
+    my %v = _build_report_hash($name);
+
+    my $ps_states = { 'paging' => 0, 'blocked' => 0, 'zombies' => 0, 'stopped' => 0,
+        'running' => 0, 'sleeping' => 0 };
+    my $state_map = { 'R' => 'running', 'S' => 'sleeping', 'D' => 'blocked',
+        'Z' => 'zombies', 'T' => 'stopped', 'W' => 'paging' };
+
+    $v{'plugin'} = 'processes';
+    delete $v{'plugin_instance'};
+    $v{'type'} = 'ps_state';
+
+    @lines = map { (split)[2] } split(/\n/, `$vzctl exec $veid cat '/proc/[0-9]*/stat'`);
+    foreach $key (@lines) {
+        ++$ps_states->{$state_map->{$key}};
+    }
+
+    foreach $key (keys %{$ps_states}) {
+        $v{'type_instance'} = $key;
+        $v{'values'} = [ $ps_states->{$key} ];
+        plugin_dispatch_values(\%v);
+}
+}
+
+sub users_read {
+    my $veid = shift;
+    my $name = shift;
+    my ($key, $val, @lines);
+    my %v = _build_report_hash($name);
+
+    $v{'plugin'} = 'users';
+    delete $v{'plugin_instance'};
+    $v{'type'} = 'users';
+    delete $v{'type_instance'};
+
+    @lines = split(/\n/, `$vzctl exec $veid w -h`);
+    $v{'values'} = [ scalar(@lines) ];
+    plugin_dispatch_values(\%v);
+}
+
+sub _build_report_hash {
+    my $name = shift;
+    return (time => time(), interval => plugin_get_interval(), host => $name);
+}
+
+sub openvz_read {
+    my (@veids, $veid, $name);
+
+    @veids = map { s/ //g; $_; } split(/\n/, `$vzlist -Ho veid`);
+
+    foreach $veid (@veids) {
+        ($name = `$vzlist -Ho name $veid`) =~ s/^\s*(.*?)\s*$/$1/;
+        ($name = `$vzlist -Ho hostname $veid`) =~ s/^\s*(.*?)\s*$/$1/ if($name =~ /^-$/);
+        $name = $veid if ($name =~ /^-$/);
+
+        if($enable_interface) {
+            interface_read($veid, $name);
+        }
+
+        if($enable_cpu) {
+            cpu_read($veid, $name);
+        }
+
+        if($enable_df) {
+            df_read($veid, $name);
+        }
+
+        if($enable_load) {
+            load_read($veid, $name);
+        }
+
+        if($enable_processes) {
+            processes_read($veid, $name);
+        }
+
+        if($enable_users) {
+            users_read($veid, $name);
+        }
+
+        return 1;
+    }
+}
+
+plugin_register(TYPE_READ, 'OpenVZ', 'openvz_read');
+
+return 1;
diff --git a/bindings/perl/lib/Collectd/Unixsock.pm b/bindings/perl/lib/Collectd/Unixsock.pm
new file mode 100644 (file)
index 0000000..5c6a5f9
--- /dev/null
@@ -0,0 +1,640 @@
+#
+# collectd - bindings/buildperl/Collectd/Unixsock.pm
+# Copyright (C) 2007,2008  Florian octo Forster
+#
+# 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:
+#   Florian Forster <octo at collectd.org>
+#
+
+package Collectd::Unixsock;
+
+=head1 NAME
+
+Collectd::Unixsock - Abstraction layer for accessing the functionality by
+collectd's unixsock plugin.
+
+=head1 SYNOPSIS
+
+  use Collectd::Unixsock;
+
+  my $sock = Collectd::Unixsock->new ($path);
+
+  my $value = $sock->getval (%identifier);
+  $sock->putval (%identifier,
+                 time => time (),
+                values => [123, 234, 345]);
+
+  $sock->destroy ();
+
+=head1 DESCRIPTION
+
+collectd's unixsock plugin allows external programs to access the values it has
+collected or received and to submit own values. This Perl-module is simply a
+little abstraction layer over this interface to make it even easier for
+programmers to interact with the daemon.
+
+=cut
+
+use strict;
+use warnings;
+
+use Carp qw(cluck confess carp croak);
+use IO::Socket::UNIX;
+use Scalar::Util qw( looks_like_number );
+
+our $Debug = 0;
+
+sub _debug
+{
+       print @_ if $Debug;
+}
+
+sub _create_socket
+{
+       my $path = shift;
+       my $sock = IO::Socket::UNIX->new (Type => SOCK_STREAM, Peer => $path);
+       if (!$sock)
+       {
+               cluck ("Cannot open UNIX-socket $path: $!");
+               return;
+       }
+       return ($sock);
+} # _create_socket
+
+=head1 VALUE IDENTIFIERS
+
+The values in the collectd are identified using a five-tuple (host, plugin,
+plugin-instance, type, type-instance) where only plugin instance and type
+instance may be undef. Many functions expect an I<%identifier> hash that has at
+least the members B<host>, B<plugin>, and B<type>, possibly completed by
+B<plugin_instance> and B<type_instance>.
+
+Usually you can pass this hash as follows:
+
+  $self->method (host => $host, plugin => $plugin, type => $type, %other_args);
+
+=cut
+
+sub _create_identifier
+{
+       my $args = shift;
+       my ($host, $plugin, $type);
+
+       if (!$args->{host} || !$args->{plugin} || !$args->{type})
+       {
+               cluck ("Need `host', `plugin' and `type'");
+               return;
+       }
+
+       $host = $args->{host};
+       $plugin = $args->{plugin};
+       $plugin .= '-' . $args->{plugin_instance} if defined $args->{plugin_instance};
+       $type = $args->{type};
+       $type .= '-' . $args->{type_instance} if defined $args->{type_instance};
+
+       return "$host/$plugin/$type";
+} # _create_identifier
+
+sub _parse_identifier
+{
+       my $string = shift;
+       my ($plugin_instance, $type_instance);
+
+       my ($host, $plugin, $type) = split /\//, $string;
+
+       ($plugin, $plugin_instance) = split /-/, $plugin, 2;
+       ($type, $type_instance) = split /-/, $type, 2;
+
+       my $ident =
+       {
+               host => $host,
+               plugin => $plugin,
+               type => $type
+       };
+       $ident->{plugin_instance} = $plugin_instance if defined $plugin_instance;
+       $ident->{type_instance} = $type_instance if defined $type_instance;
+
+       return $ident;
+} # _parse_identifier
+
+sub _escape_argument
+{
+       local $_ = shift;
+
+       return $_ if /^\w+$/;
+
+       s#\\#\\\\#g;
+       s#"#\\"#g;
+       return "\"$_\"";
+}
+
+# Send a command on a socket, including any required argument escaping.
+# Return a single line of result.
+sub _socket_command {
+       my ($self, $command, $args) = @_;
+
+       my $fh = $self->{sock} or confess ('object has no filehandle');
+
+    if($args) {
+        my $identifier = _create_identifier ($args) or return;
+           $command .= ' ' . _escape_argument ($identifier) . "\n";
+    } else {
+        $command .= "\n";
+    }
+       _debug "-> $command";
+       $fh->print($command);
+
+       my $response = $fh->getline;
+       chomp $response;
+       _debug "<- $response\n";
+    return $response;
+}
+
+# Read any remaining results from a socket and pass them to
+# a callback for caller-defined mangling.
+sub _socket_chat
+{
+       my ($self, $msg, $callback, $cbdata) = @_;
+       my ($nresults, $ret);
+       my $fh = $self->{sock} or confess ('object has no filehandle');
+
+       ($nresults, $msg) = split / /, $msg, 2;
+       if ($nresults <= 0)
+       {
+               $self->{error} = $msg;
+               return;
+       }
+
+       for (1 .. $nresults)
+       {
+               my $entry = $fh->getline;
+               chomp $entry;
+               _debug "<- $entry\n";
+        $callback->($entry, $cbdata);
+       }
+       return $cbdata;
+}
+
+
+=head1 PUBLIC METHODS
+
+=over 4
+
+=item I<$self> = Collectd::Unixsock->B<new> ([I<$path>]);
+
+Creates a new connection to the daemon. The optional I<$path> argument gives
+the path to the UNIX socket of the C<unixsock plugin> and defaults to
+F</var/run/collectd-unixsock>. Returns the newly created object on success and
+false on error.
+
+=cut
+
+sub new
+{
+       my $class = shift;
+       my $path = shift || '/var/run/collectd-unixsock';
+       my $sock = _create_socket ($path) or return;
+       return bless
+               {
+                       path => $path,
+                       sock => $sock,
+                       error => 'No error'
+               }, $class;
+} # new
+
+=item I<$res> = I<$self>-E<gt>B<getval> (I<%identifier>);
+
+Requests a value-list from the daemon. On success a hash-ref is returned with
+the name of each data-source as the key and the according value as, well, the
+value. On error false is returned.
+
+=cut
+
+sub getval # {{{
+{
+       my $self = shift;
+       my %args = @_;
+       my $ret = {};
+
+    my $msg = $self->_socket_command('GETVAL', \%args) or return;
+    $self->_socket_chat($msg, sub {
+            local $_ = shift;
+            my $ret = shift;
+            /^(\w+)=NaN$/ and $ret->{$1} = undef, return;
+            /^(\w+)=(.*)$/ and looks_like_number($2) and $ret->{$1} = 0 + $2, return;
+        }, $ret
+    );
+       return $ret;
+} # }}} sub getval
+
+=item I<$res> = I<$self>-E<gt>B<getthreshold> (I<%identifier>);
+
+Requests a threshold from the daemon. On success a hash-ref is returned with
+the threshold data. On error false is returned.
+
+=cut
+
+sub getthreshold # {{{
+{
+       my $self = shift;
+       my %args = @_;
+       my $ret = {};
+
+    my $msg = $self->_socket_command('GETTHRESHOLD', \%args) or return;
+    $self->_socket_chat($msg, sub {
+            local $_ = shift;
+            my $ret = shift;
+                   /^\s*([^:]+):\s*(.*)/ and do {
+                           $1 =~ s/\s*$//;
+                           $ret->{$1} = $2;
+                   };
+        }, $ret
+    );
+       return $ret;
+} # }}} sub getthreshold
+
+=item I<$self>-E<gt>B<putval> (I<%identifier>, B<time> =E<gt> I<$time>, B<values> =E<gt> [...]);
+
+Submits a value-list to the daemon. If the B<time> argument is omitted
+C<time()> is used. The required argument B<values> is a reference to an array
+of values that is to be submitted. The number of values must match the number
+of values expected for the given B<type> (see L<VALUE IDENTIFIERS>), though
+this is checked by the daemon, not the Perl module. Also, gauge data-sources
+(e.E<nbsp>g. system-load) may be C<undef>. Returns true upon success and false
+otherwise.
+
+=cut
+
+sub putval
+{
+       my $self = shift;
+       my %args = @_;
+
+       my ($status, $msg, $identifier, $values);
+       my $fh = $self->{sock} or confess;
+
+       my $interval = defined $args{interval} ?
+    ' interval=' . _escape_argument ($args{interval}) : '';
+
+       $identifier = _create_identifier (\%args) or return;
+       if (!$args{values})
+       {
+               cluck ("Need argument `values'");
+               return;
+       }
+
+       if (ref ($args{values}))
+       {
+               my $time;
+
+               if ("ARRAY" ne ref ($args{values}))
+               {
+                       cluck ("Invalid `values' argument (expected an array ref)");
+                       return;
+               }
+
+               if (! scalar @{$args{values}})
+               {
+                       cluck ("Empty `values' array");
+                       return;
+               }
+
+               $time = $args{time} || time;
+               $values = join (':', $time, map { defined $_ ? $_ : 'U' } @{$args{values}});
+       }
+       else
+       {
+               $values = $args{values};
+       }
+
+       $msg = 'PUTVAL '
+       . _escape_argument ($identifier)
+       . $interval
+       . ' ' . _escape_argument ($values) . "\n";
+       _debug "-> $msg";
+       $fh->print($msg);
+
+       $msg = <$fh>;
+       chomp $msg;
+       _debug "<- $msg\n";
+
+       ($status, $msg) = split / /, $msg, 2;
+       return 1 if $status == 0;
+
+       $self->{error} = $msg;
+       return;
+} # putval
+
+=item I<$res> = I<$self>-E<gt>B<listval_filter> ( C<%identifier> )
+
+Queries a list of values from the daemon while restricting the results to
+certain hosts, plugins etc. The argument may be anything that passes for an
+identifier (cf. L<VALUE IDENTIFIERS>), although all fields are optional.
+The returned data is in the same format as from C<listval>.
+
+=cut
+
+sub listval_filter
+{
+       my $self = shift;
+    my %args = @_;
+       my @ret;
+       my $nresults;
+       my $fh = $self->{sock} or confess;
+
+    my $pattern =
+    (exists $args{host}              ? "$args{host}"             : '[^/]+') .
+    (exists $args{plugin}            ? "/$args{plugin}"          : '/[^/-]+') .
+       (exists $args{plugin_instance}   ? "-$args{plugin_instance}" : '(?:-[^/]+)?') .
+       (exists $args{type}              ? "/$args{type}"            : '/[^/-]+') .
+       (exists $args{type_instance}     ? "-$args{type_instance}"   : '(?:-[^/]+)?');
+    $pattern = qr/^\d+ $pattern$/;
+
+    my $msg = $self->_socket_command('LISTVAL') or return;
+       ($nresults, $msg) = split / /, $msg, 2;
+
+    # This could use _socket_chat() but doesn't for speed reasons
+       if ($nresults < 0)
+       {
+               $self->{error} = $msg;
+               return;
+       }
+
+       for (1 .. $nresults)
+       {
+               $msg = <$fh>;
+               chomp $msg;
+               _debug "<- $msg\n";
+               next unless $msg =~ $pattern;
+               my ($time, $ident) = split / /, $msg, 2;
+
+               $ident = _parse_identifier ($ident);
+               $ident->{time} = int $time;
+
+               push (@ret, $ident);
+       } # for (i = 0 .. $status)
+
+       return @ret;
+} # listval
+
+=item I<$res> = I<$self>-E<gt>B<listval> ()
+
+Queries a list of values from the daemon. The list is returned as an array of
+hash references, where each hash reference is a valid identifier. The C<time>
+member of each hash holds the epoch value of the last update of that value.
+
+=cut
+
+sub listval
+{
+       my $self = shift;
+       my $nresults;
+       my @ret;
+       my $fh = $self->{sock} or confess;
+
+    my $msg = $self->_socket_command('LISTVAL') or return;
+       ($nresults, $msg) = split / /, $msg, 2;
+
+    # This could use _socket_chat() but doesn't for speed reasons
+       if ($nresults < 0)
+       {
+               $self->{error} = $msg;
+               return;
+       }
+
+       for (1 .. $nresults)
+       {
+               $msg = <$fh>;
+               chomp $msg;
+               _debug "<- $msg\n";
+
+               my ($time, $ident) = split / /, $msg, 2;
+
+               $ident = _parse_identifier ($ident);
+               $ident->{time} = int $time;
+
+               push (@ret, $ident);
+       } # for (i = 0 .. $status)
+
+       return @ret;
+} # listval
+
+=item I<$res> = I<$self>-E<gt>B<putnotif> (B<severity> =E<gt> I<$severity>, B<message> =E<gt> I<$message>, ...);
+
+Submits a notification to the daemon.
+
+Valid options are:
+
+=over 4
+
+=item B<severity>
+
+Sets the severity of the notification. The value must be one of the following
+strings: C<failure>, C<warning>, or C<okay>. Case does not matter. This option
+is mandatory.
+
+=item B<message>
+
+Sets the message of the notification. This option is mandatory.
+
+=item B<time>
+
+Sets the time. If omitted, C<time()> is used.
+
+=item I<Value identifier>
+
+All the other fields of the value identifiers, B<host>, B<plugin>,
+B<plugin_instance>, B<type>, and B<type_instance>, are optional. When given,
+the notification is associated with the performance data of that identifier.
+For more details, please see L<collectd-unixsock(5)>.
+
+=back
+
+=cut
+
+sub putnotif
+{
+       my $self = shift;
+       my %args = @_;
+
+       my $status;
+       my $fh = $self->{sock} or confess;
+
+       my $msg; # message sent to the socket
+       
+    for my $arg (qw( message severity ))
+    {
+        cluck ("Need argument `$arg'"), return unless $args{$arg};
+    }
+       $args{severity} = lc $args{severity};
+       if (($args{severity} ne 'failure')
+               && ($args{severity} ne 'warning')
+               && ($args{severity} ne 'okay'))
+       {
+               cluck ("Invalid `severity: " . $args{severity});
+               return;
+       }
+
+       $args{time} ||= time;
+       
+       $msg = 'PUTNOTIF '
+       . join (' ', map { $_ . '=' . _escape_argument ($args{$_}) } keys %args)
+       . "\n";
+
+       _debug "-> $msg";
+       $fh->print($msg);
+
+       $msg = <$fh>;
+       chomp $msg;
+       _debug "<- $msg\n";
+
+       ($status, $msg) = split / /, $msg, 2;
+       return 1 if $status == 0;
+
+       $self->{error} = $msg;
+       return;
+} # putnotif
+
+=item I<$self>-E<gt>B<flush> (B<timeout> =E<gt> I<$timeout>, B<plugins> =E<gt> [...], B<identifier>  =E<gt> [...]);
+
+Flush cached data.
+
+Valid options are:
+
+=over 4
+
+=item B<timeout>
+
+If this option is specified, only data older than I<$timeout> seconds is
+flushed.
+
+=item B<plugins>
+
+If this option is specified, only the selected plugins will be flushed. The
+argument is a reference to an array of strings.
+
+=item B<identifier>
+
+If this option is specified, only the given identifier(s) will be flushed. The
+argument is a reference to an array of identifiers. Identifiers, in this case,
+are hash references and have the members as outlined in L<VALUE IDENTIFIERS>.
+
+=back
+
+=cut
+
+sub flush
+{
+       my $self  = shift;
+       my %args = @_;
+
+       my $fh = $self->{sock} or confess;
+
+       my $status = 0;
+       my $msg    = "FLUSH";
+
+    $msg .= " timeout=$args{timeout}" if defined $args{timeout};
+
+       if ($args{plugins})
+       {
+               foreach my $plugin (@{$args{plugins}})
+               {
+                       $msg .= " plugin=" . $plugin;
+               }
+       }
+
+       if ($args{identifier})
+       {
+               for my $identifier (@{$args{identifier}})
+               {
+                       my $ident_str;
+
+                       if (ref ($identifier) ne 'HASH')
+                       {
+                               cluck ("The argument of the `identifier' "
+                                       . "option must be an array of hashrefs.");
+                               return;
+                       }
+
+                       $ident_str = _create_identifier ($identifier) or return;
+                       $msg .= ' identifier=' . _escape_argument ($ident_str);
+               }
+       }
+
+       $msg .= "\n";
+
+       _debug "-> $msg";
+       $fh->print($msg);
+
+       $msg = <$fh>;
+       chomp ($msg);
+       _debug "<- $msg\n";
+
+       ($status, $msg) = split / /, $msg, 2;
+       return 1 if $status == 0;
+
+       $self->{error} = $msg;
+       return;
+}
+
+sub error
+{
+       return shift->{error};
+}
+
+=item I<$self>-E<gt>destroy ();
+
+Closes the socket before the object is destroyed. This function is also
+automatically called then the object goes out of scope.
+
+=back
+
+=cut
+
+sub destroy
+{
+       my $self = shift;
+       if ($self->{sock})
+       {
+               close $self->{sock};
+               delete $self->{sock};
+       }
+}
+
+sub DESTROY
+{
+       my $self = shift;
+       $self->destroy ();
+}
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-unixsock(5)>
+
+=head1 AUTHOR
+
+Florian octo Forster E<lt>octo@collectd.orgE<gt>
+
+=cut
+1;
+# vim: set fdm=marker :
diff --git a/bindings/perl/uninstall_mod.pl b/bindings/perl/uninstall_mod.pl
new file mode 100644 (file)
index 0000000..f8083af
--- /dev/null
@@ -0,0 +1,8 @@
+#! /usr/bin/perl
+
+use strict;
+use ExtUtils::Installed;
+
+my $mod = $ARGV[0] || die "Usage : $0 Module\n";
+my $inst = ExtUtils::Installed->new();
+unlink $inst->files($mod), $inst->packlist($mod)->packlist_file();
diff --git a/compile b/compile
new file mode 100755 (executable)
index 0000000..c0096a7
--- /dev/null
+++ b/compile
@@ -0,0 +1,143 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2009-10-06.20; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009  Free Software
+# Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand `-c -o'.
+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file `INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+esac
+
+ofile=
+cfile=
+eat=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+       # configure might choose to run compile as `compile cc -o foo foo.c'.
+       # So we strip `-o arg' only if arg is an object.
+       eat=1
+       case $2 in
+         *.o | *.obj)
+           ofile=$2
+           ;;
+         *)
+           set x "$@" -o "$2"
+           shift
+           ;;
+       esac
+       ;;
+      *.c)
+       cfile=$1
+       set x "$@" "$1"
+       shift
+       ;;
+      *)
+       set x "$@" "$1"
+       shift
+       ;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no `-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # `.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/config.guess b/config.guess
new file mode 100755 (executable)
index 0000000..e3a2116
--- /dev/null
@@ -0,0 +1,1533 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+#   Free Software Foundation, Inc.
+
+timestamp='2009-06-10'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep -q __ELF__
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    s390x:SunOS:*:*)
+       echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+       eval $set_cc_for_build
+       SUN_ARCH="i386"
+       # If there is a compiler, see if it is configured for 64-bit objects.
+       # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+       # This test works for both compilers.
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               SUN_ARCH="x86_64"
+           fi
+       fi
+       echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[456])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep -q __LP64__
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:[3456]*)
+       case ${UNAME_MACHINE} in
+           x86)
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           EM64T | authenticamd | genuineintel)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+           IA64)
+               echo ia64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    8664:Windows_NT:*)
+       echo x86_64-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    arm*:Linux:*:*)
+       eval $set_cc_for_build
+       if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+           | grep -q __ARM_EABI__
+       then
+           echo ${UNAME_MACHINE}-unknown-linux-gnu
+       else
+           echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+       fi
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef ${UNAME_MACHINE}
+       #undef ${UNAME_MACHINE}el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=${UNAME_MACHINE}el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=${UNAME_MACHINE}
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^CPU/{
+               s: ::g
+               p
+           }'`"
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    or32:Linux:*:*)
+       echo or32-unknown-linux-gnu
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep -q ld.so.1
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit ;;
+    padre:Linux:*:*)
+       echo sparc-unknown-linux-gnu
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit ;;
+    xtensa*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    i*86:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us. cd to the root directory to prevent
+       # problems with other programs or directories called `ld' in the path.
+       # Set LC_ALL=C to ensure ld outputs messages in English.
+       ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+                        | sed -ne '/supported targets:/!d
+                                   s/[         ][      ]*/ /g
+                                   s/.*supported targets: *//
+                                   s/ .*//
+                                   p'`
+        case "$ld_supported_targets" in
+         elf32-i386)
+               TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+               ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+           /^LIBC/{
+               s: ::g
+               p
+           }'`"
+       test x"${LIBC}" != x && {
+               echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+               exit
+       }
+       test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+       ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i586.
+       # Note: whatever this is, it MUST be the same as what config.sub
+       # prints for the "djgpp" host, or else GDB configury will decide that
+       # this is a cross-build.
+       echo i586-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+       OS_REL='.3'
+       test -r /etc/.relid \
+           && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+           && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    BePC:Haiku:*:*)    # Haiku running on Intel PC compatible.
+       echo i586-pc-haiku
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
+           unknown) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+    i*86:AROS:*:*)
+       echo ${UNAME_MACHINE}-pc-aros
+       exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.sub b/config.sub
new file mode 100755 (executable)
index 0000000..eb0389a
--- /dev/null
@@ -0,0 +1,1693 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+#   Free Software Foundation, Inc.
+
+timestamp='2009-06-11'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis | -knuth | -cray)
+               os=
+               basic_machine=$1
+               ;;
+        -bluegene*)
+               os=-cnk
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+       | bfin \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | lm32 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | mcore | mep | metag \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64octeon | mips64octeonel \
+       | mips64orion | mips64orionel \
+       | mips64r5900 | mips64r5900el \
+       | mips64vr | mips64vrel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | moxie \
+       | mt \
+       | msp430 \
+       | nios | nios2 \
+       | ns16k | ns32k \
+       | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+       | z8k | z80)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* | avr32-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | lm32-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64octeon-* | mips64octeonel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64r5900-* | mips64r5900el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nios-* | nios2-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+       | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+       | xstormy16-* | xtensa*-* \
+       | ymp-* \
+       | z8k-* | z80-*)
+               ;;
+       # Recognize the basic CPU types without company name, with glob match.
+       xtensa*)
+               basic_machine=$basic_machine-unknown
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aros)
+               basic_machine=i386-pc
+               os=-aros
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       blackfin)
+               basic_machine=bfin-unknown
+               os=-linux
+               ;;
+       blackfin-*)
+               basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       bluegene*)
+               basic_machine=powerpc-ibm
+               os=-cnk
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+        cegcc)
+               basic_machine=arm-unknown
+               os=-cegcc
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16)
+               basic_machine=cr16-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dicos)
+               basic_machine=i686-pc
+               os=-dicos
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m68knommu)
+               basic_machine=m68k-unknown
+               os=-linux
+               ;;
+       m68knommu-*)
+               basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       mingw32ce)
+               basic_machine=arm-unknown
+               os=-mingw32ce
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       parisc)
+               basic_machine=hppa-unknown
+               os=-linux
+               ;;
+       parisc-*)
+               basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rdos)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
+       tile*)
+               basic_machine=tile-unknown
+               os=-linux-gnu
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       z80-*-coff)
+               basic_machine=z80-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -kopensolaris* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* | -aros* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* | -cegcc* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+        -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+        -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -dicos*)
+               os=-dicos
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+               os=-elf
+               ;;
+        spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+        mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -cnk*|-aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..e54ef3f
--- /dev/null
+++ b/configure
@@ -0,0 +1,39688 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for collectd 5.5.0.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+        /*)
+          for as_base in sh bash ksh sh5; do
+            # Try only shells that exist, to save several forks.
+            as_shell=$as_dir/$as_base
+            if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+                   { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+                  if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+          done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+             { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+lt_ltdl_dir='libltdl'
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+lt_dlopen_dir="$lt_ltdl_dir"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='collectd'
+PACKAGE_TARNAME='collectd'
+PACKAGE_VERSION='5.5.0'
+PACKAGE_STRING='collectd 5.5.0'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="src/"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+enable_option_checking=no
+ac_default_prefix="/opt/collectd"
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+ltdl_LTLIBOBJS
+ltdl_LIBOBJS
+LTLIBOBJS
+LIBOBJS
+LCC_VERSION_STRING
+LCC_VERSION_EXTRA
+LCC_VERSION_PATCH
+LCC_VERSION_MINOR
+LCC_VERSION_MAJOR
+PERL_BINDINGS_OPTIONS
+PERL_BINDINGS
+LOAD_PLUGIN_CSV
+LOAD_PLUGIN_NETWORK
+LOAD_PLUGIN_RRDTOOL
+DEFAULT_LOG_LEVEL
+LOAD_PLUGIN_LOG_LOGSTASH
+LOAD_PLUGIN_LOGFILE
+LOAD_PLUGIN_SYSLOG
+BUILD_PLUGIN_ZOOKEEPER_FALSE
+BUILD_PLUGIN_ZOOKEEPER_TRUE
+BUILD_PLUGIN_ZFS_ARC_FALSE
+BUILD_PLUGIN_ZFS_ARC_TRUE
+BUILD_PLUGIN_XMMS_FALSE
+BUILD_PLUGIN_XMMS_TRUE
+BUILD_PLUGIN_WRITE_TSDB_FALSE
+BUILD_PLUGIN_WRITE_TSDB_TRUE
+BUILD_PLUGIN_WRITE_SENSU_FALSE
+BUILD_PLUGIN_WRITE_SENSU_TRUE
+BUILD_PLUGIN_WRITE_RIEMANN_FALSE
+BUILD_PLUGIN_WRITE_RIEMANN_TRUE
+BUILD_PLUGIN_WRITE_REDIS_FALSE
+BUILD_PLUGIN_WRITE_REDIS_TRUE
+BUILD_PLUGIN_WRITE_MONGODB_FALSE
+BUILD_PLUGIN_WRITE_MONGODB_TRUE
+BUILD_PLUGIN_WRITE_LOG_FALSE
+BUILD_PLUGIN_WRITE_LOG_TRUE
+BUILD_PLUGIN_WRITE_KAFKA_FALSE
+BUILD_PLUGIN_WRITE_KAFKA_TRUE
+BUILD_PLUGIN_WRITE_HTTP_FALSE
+BUILD_PLUGIN_WRITE_HTTP_TRUE
+BUILD_PLUGIN_WRITE_GRAPHITE_FALSE
+BUILD_PLUGIN_WRITE_GRAPHITE_TRUE
+BUILD_PLUGIN_WIRELESS_FALSE
+BUILD_PLUGIN_WIRELESS_TRUE
+BUILD_PLUGIN_VSERVER_FALSE
+BUILD_PLUGIN_VSERVER_TRUE
+BUILD_PLUGIN_VMEM_FALSE
+BUILD_PLUGIN_VMEM_TRUE
+BUILD_PLUGIN_VIRT_FALSE
+BUILD_PLUGIN_VIRT_TRUE
+BUILD_PLUGIN_VARNISH_FALSE
+BUILD_PLUGIN_VARNISH_TRUE
+BUILD_PLUGIN_UUID_FALSE
+BUILD_PLUGIN_UUID_TRUE
+BUILD_PLUGIN_USERS_FALSE
+BUILD_PLUGIN_USERS_TRUE
+BUILD_PLUGIN_UPTIME_FALSE
+BUILD_PLUGIN_UPTIME_TRUE
+BUILD_PLUGIN_UNIXSOCK_FALSE
+BUILD_PLUGIN_UNIXSOCK_TRUE
+BUILD_PLUGIN_TURBOSTAT_FALSE
+BUILD_PLUGIN_TURBOSTAT_TRUE
+BUILD_PLUGIN_TOKYOTYRANT_FALSE
+BUILD_PLUGIN_TOKYOTYRANT_TRUE
+BUILD_PLUGIN_THRESHOLD_FALSE
+BUILD_PLUGIN_THRESHOLD_TRUE
+BUILD_PLUGIN_THERMAL_FALSE
+BUILD_PLUGIN_THERMAL_TRUE
+BUILD_PLUGIN_TED_FALSE
+BUILD_PLUGIN_TED_TRUE
+BUILD_PLUGIN_TEAMSPEAK2_FALSE
+BUILD_PLUGIN_TEAMSPEAK2_TRUE
+BUILD_PLUGIN_TCPCONNS_FALSE
+BUILD_PLUGIN_TCPCONNS_TRUE
+BUILD_PLUGIN_TARGET_V5UPGRADE_FALSE
+BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE
+BUILD_PLUGIN_TARGET_SET_FALSE
+BUILD_PLUGIN_TARGET_SET_TRUE
+BUILD_PLUGIN_TARGET_SCALE_FALSE
+BUILD_PLUGIN_TARGET_SCALE_TRUE
+BUILD_PLUGIN_TARGET_REPLACE_FALSE
+BUILD_PLUGIN_TARGET_REPLACE_TRUE
+BUILD_PLUGIN_TARGET_NOTIFICATION_FALSE
+BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE
+BUILD_PLUGIN_TAPE_FALSE
+BUILD_PLUGIN_TAPE_TRUE
+BUILD_PLUGIN_TAIL_CSV_FALSE
+BUILD_PLUGIN_TAIL_CSV_TRUE
+BUILD_PLUGIN_TAIL_FALSE
+BUILD_PLUGIN_TAIL_TRUE
+BUILD_PLUGIN_TABLE_FALSE
+BUILD_PLUGIN_TABLE_TRUE
+BUILD_PLUGIN_SYSLOG_FALSE
+BUILD_PLUGIN_SYSLOG_TRUE
+BUILD_PLUGIN_SWAP_FALSE
+BUILD_PLUGIN_SWAP_TRUE
+BUILD_PLUGIN_STATSD_FALSE
+BUILD_PLUGIN_STATSD_TRUE
+BUILD_PLUGIN_SNMP_FALSE
+BUILD_PLUGIN_SNMP_TRUE
+BUILD_PLUGIN_SMART_FALSE
+BUILD_PLUGIN_SMART_TRUE
+BUILD_PLUGIN_SIGROK_FALSE
+BUILD_PLUGIN_SIGROK_TRUE
+BUILD_PLUGIN_SERIAL_FALSE
+BUILD_PLUGIN_SERIAL_TRUE
+BUILD_PLUGIN_SENSORS_FALSE
+BUILD_PLUGIN_SENSORS_TRUE
+BUILD_PLUGIN_RRDTOOL_FALSE
+BUILD_PLUGIN_RRDTOOL_TRUE
+BUILD_PLUGIN_RRDCACHED_FALSE
+BUILD_PLUGIN_RRDCACHED_TRUE
+BUILD_PLUGIN_ROUTEROS_FALSE
+BUILD_PLUGIN_ROUTEROS_TRUE
+BUILD_PLUGIN_REDIS_FALSE
+BUILD_PLUGIN_REDIS_TRUE
+BUILD_PLUGIN_PYTHON_FALSE
+BUILD_PLUGIN_PYTHON_TRUE
+BUILD_PLUGIN_PROTOCOLS_FALSE
+BUILD_PLUGIN_PROTOCOLS_TRUE
+BUILD_PLUGIN_PROCESSES_FALSE
+BUILD_PLUGIN_PROCESSES_TRUE
+BUILD_PLUGIN_POWERDNS_FALSE
+BUILD_PLUGIN_POWERDNS_TRUE
+BUILD_PLUGIN_POSTGRESQL_FALSE
+BUILD_PLUGIN_POSTGRESQL_TRUE
+BUILD_PLUGIN_PING_FALSE
+BUILD_PLUGIN_PING_TRUE
+BUILD_PLUGIN_PINBA_FALSE
+BUILD_PLUGIN_PINBA_TRUE
+BUILD_PLUGIN_PF_FALSE
+BUILD_PLUGIN_PF_TRUE
+BUILD_PLUGIN_PERL_FALSE
+BUILD_PLUGIN_PERL_TRUE
+BUILD_PLUGIN_ORACLE_FALSE
+BUILD_PLUGIN_ORACLE_TRUE
+BUILD_PLUGIN_OPENVPN_FALSE
+BUILD_PLUGIN_OPENVPN_TRUE
+BUILD_PLUGIN_OPENLDAP_FALSE
+BUILD_PLUGIN_OPENLDAP_TRUE
+BUILD_PLUGIN_ONEWIRE_FALSE
+BUILD_PLUGIN_ONEWIRE_TRUE
+BUILD_PLUGIN_OLSRD_FALSE
+BUILD_PLUGIN_OLSRD_TRUE
+BUILD_PLUGIN_NUT_FALSE
+BUILD_PLUGIN_NUT_TRUE
+BUILD_PLUGIN_NUMA_FALSE
+BUILD_PLUGIN_NUMA_TRUE
+BUILD_PLUGIN_NTPD_FALSE
+BUILD_PLUGIN_NTPD_TRUE
+BUILD_PLUGIN_NOTIFY_EMAIL_FALSE
+BUILD_PLUGIN_NOTIFY_EMAIL_TRUE
+BUILD_PLUGIN_NOTIFY_DESKTOP_FALSE
+BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE
+BUILD_PLUGIN_NGINX_FALSE
+BUILD_PLUGIN_NGINX_TRUE
+BUILD_PLUGIN_NFS_FALSE
+BUILD_PLUGIN_NFS_TRUE
+BUILD_PLUGIN_NETWORK_FALSE
+BUILD_PLUGIN_NETWORK_TRUE
+BUILD_PLUGIN_NETLINK_FALSE
+BUILD_PLUGIN_NETLINK_TRUE
+BUILD_PLUGIN_NETAPP_FALSE
+BUILD_PLUGIN_NETAPP_TRUE
+BUILD_PLUGIN_MYSQL_FALSE
+BUILD_PLUGIN_MYSQL_TRUE
+BUILD_PLUGIN_MULTIMETER_FALSE
+BUILD_PLUGIN_MULTIMETER_TRUE
+BUILD_PLUGIN_MODBUS_FALSE
+BUILD_PLUGIN_MODBUS_TRUE
+BUILD_PLUGIN_MIC_FALSE
+BUILD_PLUGIN_MIC_TRUE
+BUILD_PLUGIN_MEMORY_FALSE
+BUILD_PLUGIN_MEMORY_TRUE
+BUILD_PLUGIN_MEMCACHED_FALSE
+BUILD_PLUGIN_MEMCACHED_TRUE
+BUILD_PLUGIN_MEMCACHEC_FALSE
+BUILD_PLUGIN_MEMCACHEC_TRUE
+BUILD_PLUGIN_MD_FALSE
+BUILD_PLUGIN_MD_TRUE
+BUILD_PLUGIN_MBMON_FALSE
+BUILD_PLUGIN_MBMON_TRUE
+BUILD_PLUGIN_MATCH_VALUE_FALSE
+BUILD_PLUGIN_MATCH_VALUE_TRUE
+BUILD_PLUGIN_MATCH_TIMEDIFF_FALSE
+BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE
+BUILD_PLUGIN_MATCH_REGEX_FALSE
+BUILD_PLUGIN_MATCH_REGEX_TRUE
+BUILD_PLUGIN_MATCH_HASHED_FALSE
+BUILD_PLUGIN_MATCH_HASHED_TRUE
+BUILD_PLUGIN_MATCH_EMPTY_COUNTER_FALSE
+BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE
+BUILD_PLUGIN_MADWIFI_FALSE
+BUILD_PLUGIN_MADWIFI_TRUE
+BUILD_PLUGIN_LVM_FALSE
+BUILD_PLUGIN_LVM_TRUE
+BUILD_PLUGIN_LPAR_FALSE
+BUILD_PLUGIN_LPAR_TRUE
+BUILD_PLUGIN_LOG_LOGSTASH_FALSE
+BUILD_PLUGIN_LOG_LOGSTASH_TRUE
+BUILD_PLUGIN_LOGFILE_FALSE
+BUILD_PLUGIN_LOGFILE_TRUE
+BUILD_PLUGIN_LOAD_FALSE
+BUILD_PLUGIN_LOAD_TRUE
+BUILD_PLUGIN_JAVA_FALSE
+BUILD_PLUGIN_JAVA_TRUE
+BUILD_PLUGIN_IRQ_FALSE
+BUILD_PLUGIN_IRQ_TRUE
+BUILD_PLUGIN_IPVS_FALSE
+BUILD_PLUGIN_IPVS_TRUE
+BUILD_PLUGIN_IPTABLES_FALSE
+BUILD_PLUGIN_IPTABLES_TRUE
+BUILD_PLUGIN_IPMI_FALSE
+BUILD_PLUGIN_IPMI_TRUE
+BUILD_PLUGIN_IPC_FALSE
+BUILD_PLUGIN_IPC_TRUE
+BUILD_PLUGIN_INTERFACE_FALSE
+BUILD_PLUGIN_INTERFACE_TRUE
+BUILD_PLUGIN_HDDTEMP_FALSE
+BUILD_PLUGIN_HDDTEMP_TRUE
+BUILD_PLUGIN_GMOND_FALSE
+BUILD_PLUGIN_GMOND_TRUE
+BUILD_PLUGIN_FSCACHE_FALSE
+BUILD_PLUGIN_FSCACHE_TRUE
+BUILD_PLUGIN_FILECOUNT_FALSE
+BUILD_PLUGIN_FILECOUNT_TRUE
+BUILD_PLUGIN_FHCOUNT_FALSE
+BUILD_PLUGIN_FHCOUNT_TRUE
+BUILD_PLUGIN_EXEC_FALSE
+BUILD_PLUGIN_EXEC_TRUE
+BUILD_PLUGIN_ETHSTAT_FALSE
+BUILD_PLUGIN_ETHSTAT_TRUE
+BUILD_PLUGIN_ENTROPY_FALSE
+BUILD_PLUGIN_ENTROPY_TRUE
+BUILD_PLUGIN_EMAIL_FALSE
+BUILD_PLUGIN_EMAIL_TRUE
+BUILD_PLUGIN_DNS_FALSE
+BUILD_PLUGIN_DNS_TRUE
+BUILD_PLUGIN_DRBD_FALSE
+BUILD_PLUGIN_DRBD_TRUE
+BUILD_PLUGIN_DISK_FALSE
+BUILD_PLUGIN_DISK_TRUE
+BUILD_PLUGIN_DF_FALSE
+BUILD_PLUGIN_DF_TRUE
+BUILD_PLUGIN_DBI_FALSE
+BUILD_PLUGIN_DBI_TRUE
+BUILD_PLUGIN_CGROUPS_FALSE
+BUILD_PLUGIN_CGROUPS_TRUE
+BUILD_PLUGIN_CURL_XML_FALSE
+BUILD_PLUGIN_CURL_XML_TRUE
+BUILD_PLUGIN_CURL_JSON_FALSE
+BUILD_PLUGIN_CURL_JSON_TRUE
+BUILD_PLUGIN_CURL_FALSE
+BUILD_PLUGIN_CURL_TRUE
+BUILD_PLUGIN_CSV_FALSE
+BUILD_PLUGIN_CSV_TRUE
+BUILD_PLUGIN_CPU_FALSE
+BUILD_PLUGIN_CPU_TRUE
+BUILD_PLUGIN_CPUFREQ_FALSE
+BUILD_PLUGIN_CPUFREQ_TRUE
+BUILD_PLUGIN_CONTEXTSWITCH_FALSE
+BUILD_PLUGIN_CONTEXTSWITCH_TRUE
+BUILD_PLUGIN_CONNTRACK_FALSE
+BUILD_PLUGIN_CONNTRACK_TRUE
+BUILD_PLUGIN_CEPH_FALSE
+BUILD_PLUGIN_CEPH_TRUE
+BUILD_PLUGIN_BIND_FALSE
+BUILD_PLUGIN_BIND_TRUE
+BUILD_PLUGIN_BATTERY_FALSE
+BUILD_PLUGIN_BATTERY_TRUE
+BUILD_PLUGIN_BAROMETER_FALSE
+BUILD_PLUGIN_BAROMETER_TRUE
+BUILD_PLUGIN_ASCENT_FALSE
+BUILD_PLUGIN_ASCENT_TRUE
+BUILD_PLUGIN_AQUAERO_FALSE
+BUILD_PLUGIN_AQUAERO_TRUE
+BUILD_PLUGIN_APPLE_SENSORS_FALSE
+BUILD_PLUGIN_APPLE_SENSORS_TRUE
+BUILD_PLUGIN_APCUPS_FALSE
+BUILD_PLUGIN_APCUPS_TRUE
+BUILD_PLUGIN_APACHE_FALSE
+BUILD_PLUGIN_APACHE_TRUE
+BUILD_PLUGIN_AMQP_FALSE
+BUILD_PLUGIN_AMQP_TRUE
+BUILD_PLUGIN_AGGREGATION_FALSE
+BUILD_PLUGIN_AGGREGATION_TRUE
+BUILD_FEATURE_GETIFADDRS_FALSE
+BUILD_FEATURE_GETIFADDRS_TRUE
+BUILD_FEATURE_DAEMON_FALSE
+BUILD_FEATURE_DAEMON_TRUE
+BUILD_FEATURE_DEBUG_FALSE
+BUILD_FEATURE_DEBUG_TRUE
+LIBNOTIFY_LIBS
+LIBNOTIFY_CFLAGS
+BUILD_WITH_LIBATASMART_FALSE
+BUILD_WITH_LIBATASMART_TRUE
+BUILD_WITH_LIBATASMART_LIBS
+BUILD_WITH_LIBATASMART_LDFLAGS
+BUILD_WITH_LIBATASMART_CPPFLAGS
+BUILD_WITH_OPENIPMI_LIBS
+BUILD_WITH_OPENIPMI_CFLAGS
+BUILD_WITH_LIBVIRT_LIBS
+BUILD_WITH_LIBVIRT_CFLAGS
+BUILD_WITH_LIBXML2_LIBS
+BUILD_WITH_LIBXML2_CFLAGS
+BUILD_WITH_LIBVARNISH_LIBS
+BUILD_WITH_LIBVARNISH_CFLAGS
+BUILD_WITH_MIC_LDADD
+BUILD_WITH_MIC_LIBPATH
+BUILD_WITH_MIC_CPPFLAGS
+BUILD_WITH_LIBYAJL_FALSE
+BUILD_WITH_LIBYAJL_TRUE
+BUILD_WITH_LIBYAJL_LIBS
+BUILD_WITH_LIBYAJL_LDFLAGS
+BUILD_WITH_LIBYAJL_CPPFLAGS
+BUILD_WITH_LIBXMMS_FALSE
+BUILD_WITH_LIBXMMS_TRUE
+BUILD_WITH_LIBXMMS_LIBS
+BUILD_WITH_LIBXMMS_CFLAGS
+BUILD_WITH_LIBUPSCLIENT_LIBS
+BUILD_WITH_LIBUPSCLIENT_CFLAGS
+BUILD_WITH_LIBUDEV_FALSE
+BUILD_WITH_LIBUDEV_TRUE
+BUILD_WITH_LIBUDEV_LDFLAGS
+BUILD_WITH_LIBUDEV_CFLAGS
+BUILD_WITH_LIBTOKYOTYRANT_FALSE
+BUILD_WITH_LIBTOKYOTYRANT_TRUE
+BUILD_WITH_LIBTOKYOTYRANT_LIBS
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS
+BUILD_WITH_LIBSTATGRAB_LDFLAGS
+BUILD_WITH_LIBSTATGRAB_CFLAGS
+BUILD_WITH_LIBSTATGRAB_FALSE
+BUILD_WITH_LIBSTATGRAB_TRUE
+BUILD_WITH_LIBSIGROK_FALSE
+BUILD_WITH_LIBSIGROK_TRUE
+BUILD_WITH_LIBSIGROK_LDFLAGS
+BUILD_WITH_LIBSIGROK_CFLAGS
+GLIB_COMPILE_RESOURCES
+GLIB_MKENUMS
+GOBJECT_QUERY
+GLIB_GENMARSHAL
+GLIB_LIBS
+GLIB_CFLAGS
+BUILD_WITH_LM_SENSORS_FALSE
+BUILD_WITH_LM_SENSORS_TRUE
+BUILD_WITH_LIBSENSORS_LDFLAGS
+BUILD_WITH_LIBSENSORS_CFLAGS
+BUILD_WITH_LIBRRD_LDFLAGS
+BUILD_WITH_LIBRRD_CFLAGS
+BUILD_WITH_LIBROUTEROS_FALSE
+BUILD_WITH_LIBROUTEROS_TRUE
+BUILD_WITH_LIBROUTEROS_LDFLAGS
+BUILD_WITH_LIBROUTEROS_CPPFLAGS
+BUILD_WITH_LIBRDKAFKA_FALSE
+BUILD_WITH_LIBRDKAFKA_TRUE
+BUILD_WITH_LIBRDKAFKA_LIBS
+BUILD_WITH_LIBRDKAFKA_LDFLAGS
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS
+BUILD_WITH_LIBRABBITMQ_FALSE
+BUILD_WITH_LIBRABBITMQ_TRUE
+BUILD_WITH_LIBRABBITMQ_LIBS
+BUILD_WITH_LIBRABBITMQ_LDFLAGS
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS
+BUILD_WITH_PYTHON_LIBS
+BUILD_WITH_PYTHON_LDFLAGS
+BUILD_WITH_PYTHON_CPPFLAGS
+BUILD_WITH_LIBPTHREAD_FALSE
+BUILD_WITH_LIBPTHREAD_TRUE
+BUILD_WITH_LIBPQ_FALSE
+BUILD_WITH_LIBPQ_TRUE
+BUILD_WITH_LIBPQ_LDFLAGS
+BUILD_WITH_LIBPQ_CPPFLAGS
+HAVE_BROKEN_PERL_LOAD_MODULE_FALSE
+HAVE_BROKEN_PERL_LOAD_MODULE_TRUE
+BUILD_WITH_LIBPERL_FALSE
+BUILD_WITH_LIBPERL_TRUE
+PERL_LIBS
+PERL_CFLAGS
+PERL
+BUILD_WITH_LIBPCAP_FALSE
+BUILD_WITH_LIBPCAP_TRUE
+BUILD_WITH_LIBOWCAPI_LIBS
+BUILD_WITH_LIBOWCAPI_CPPFLAGS
+BUILD_WITH_ORACLE_LIBS
+BUILD_WITH_ORACLE_CFLAGS
+BUILD_WITH_LIBOPING_FALSE
+BUILD_WITH_LIBOPING_TRUE
+BUILD_WITH_LIBOPING_LDFLAGS
+BUILD_WITH_LIBOPING_CPPFLAGS
+BUILD_WITH_OWN_LIBOCONFIG_FALSE
+BUILD_WITH_OWN_LIBOCONFIG_TRUE
+BUILD_WITH_LIBNETSNMP_FALSE
+BUILD_WITH_LIBNETSNMP_TRUE
+BUILD_WITH_LIBSNMP_LIBS
+BUILD_WITH_LIBSNMP_CFLAGS
+BUILD_WITH_LIBNETAPP_FALSE
+BUILD_WITH_LIBNETAPP_TRUE
+LIBNETAPP_LIBS
+LIBNETAPP_LDFLAGS
+LIBNETAPP_CPPFLAGS
+BUILD_WITH_LIBMNL_FALSE
+BUILD_WITH_LIBMNL_TRUE
+BUILD_WITH_LIBMNL_LIBS
+BUILD_WITH_LIBMNL_CFLAGS
+BUILD_WITH_LIBMYSQL_FALSE
+BUILD_WITH_LIBMYSQL_TRUE
+BUILD_WITH_LIBMYSQL_LIBS
+BUILD_WITH_LIBMYSQL_CFLAGS
+BUILD_WITH_LIBMONGOC_FALSE
+BUILD_WITH_LIBMONGOC_TRUE
+BUILD_WITH_LIBMONGOC_LDFLAGS
+BUILD_WITH_LIBMONGOC_CPPFLAGS
+BUILD_WITH_LIBMODBUS_LIBS
+BUILD_WITH_LIBMODBUS_CFLAGS
+BUILD_WITH_LIBMEMCACHED_FALSE
+BUILD_WITH_LIBMEMCACHED_TRUE
+BUILD_WITH_LIBMEMCACHED_LIBS
+BUILD_WITH_LIBMEMCACHED_LDFLAGS
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS
+BUILD_WITH_LIBLVM2APP_FALSE
+BUILD_WITH_LIBLVM2APP_TRUE
+BUILD_WITH_LIBLVM2APP_LIBS
+BUILD_WITH_LIBLVM2APP_LDFLAGS
+BUILD_WITH_LIBLVM2APP_CPPFLAGS
+BUILD_WITH_LIBLDAP_FALSE
+BUILD_WITH_LIBLDAP_TRUE
+BUILD_WITH_LIBLDAP_LDFLAGS
+BUILD_WITH_LIBLDAP_CPPFLAGS
+BUILD_WITH_JAVA_FALSE
+BUILD_WITH_JAVA_TRUE
+JAVA_LIBS
+JAVA_LDFLAGS
+JAVA_CFLAGS
+JAVA_CPPFLAGS
+JAR
+JAVAC
+BUILD_WITH_LIBIPTC_LDFLAGS
+BUILD_WITH_LIBIPTC_CPPFLAGS
+BUILD_WITH_LIBIPTC_FALSE
+BUILD_WITH_LIBIPTC_TRUE
+BUILD_WITH_LIBGCRYPT_FALSE
+BUILD_WITH_LIBGCRYPT_TRUE
+GCRYPT_LIBS
+GCRYPT_LDFLAGS
+GCRYPT_CPPFLAGS
+LIBGCRYPT_LIBS
+LIBGCRYPT_CFLAGS
+LIBGCRYPT_CONFIG
+BUILD_WITH_LIBGANGLIA_FALSE
+BUILD_WITH_LIBGANGLIA_TRUE
+GANGLIA_LIBS
+GANGLIA_LDFLAGS
+GANGLIA_CPPFLAGS
+BUILD_WITH_LIBESMTP_FALSE
+BUILD_WITH_LIBESMTP_TRUE
+BUILD_WITH_LIBDBI_FALSE
+BUILD_WITH_LIBDBI_TRUE
+BUILD_WITH_LIBDBI_LIBS
+BUILD_WITH_LIBDBI_LDFLAGS
+BUILD_WITH_LIBDBI_CPPFLAGS
+BUILD_WITH_LIBCURL_FALSE
+BUILD_WITH_LIBCURL_TRUE
+BUILD_WITH_LIBCURL_LIBS
+BUILD_WITH_LIBCURL_CFLAGS
+BUILD_WITH_LIBHIREDIS_FALSE
+BUILD_WITH_LIBHIREDIS_TRUE
+BUILD_WITH_LIBHIREDIS_LDFLAGS
+BUILD_WITH_LIBHIREDIS_CPPFLAGS
+BUILD_WITH_LIBAQUAERO5_FALSE
+BUILD_WITH_LIBAQUAERO5_TRUE
+BUILD_WITH_LIBAQUAERO5_LDFLAGS
+BUILD_WITH_LIBAQUAERO5_CFLAGS
+BUILD_WITH_LIBKVM_OPENFILES_FALSE
+BUILD_WITH_LIBKVM_OPENFILES_TRUE
+BUILD_WITH_LIBKVM_NLIST_FALSE
+BUILD_WITH_LIBKVM_NLIST_TRUE
+BUILD_WITH_LIBKVM_GETSWAPINFO_FALSE
+BUILD_WITH_LIBKVM_GETSWAPINFO_TRUE
+BUILD_WITH_LIBKVM_GETPROCS_FALSE
+BUILD_WITH_LIBKVM_GETPROCS_TRUE
+BUILD_WITH_LIBIOKIT_FALSE
+BUILD_WITH_LIBIOKIT_TRUE
+BUILD_WITH_LIBDEVINFO_FALSE
+BUILD_WITH_LIBDEVINFO_TRUE
+BUILD_WITH_LIBKSTAT_FALSE
+BUILD_WITH_LIBKSTAT_TRUE
+BUILD_WITH_PERFSTAT_FALSE
+BUILD_WITH_PERFSTAT_TRUE
+BUILD_WITH_LIBHAL_LIBS
+BUILD_WITH_LIBHAL_CFLAGS
+BUILD_WITH_LIBRESOLV_FALSE
+BUILD_WITH_LIBRESOLV_TRUE
+BUILD_WITH_LIBPOSIX4_FALSE
+BUILD_WITH_LIBPOSIX4_TRUE
+BUILD_WITH_LIBRT_FALSE
+BUILD_WITH_LIBRT_TRUE
+BUILD_WITH_LIBSOCKET_FALSE
+BUILD_WITH_LIBSOCKET_TRUE
+IP_VS_H_NEEDS_KERNEL_CFLAGS_FALSE
+IP_VS_H_NEEDS_KERNEL_CFLAGS_TRUE
+BUILD_FEATURE_STANDARDS_FALSE
+BUILD_FEATURE_STANDARDS_TRUE
+pkgconfigdir
+KERNEL_CFLAGS
+KERNEL_DIR
+BUILD_FREEBSD_FALSE
+BUILD_FREEBSD_TRUE
+BUILD_AIX_FALSE
+BUILD_AIX_TRUE
+BUILD_OPENBSD_FALSE
+BUILD_OPENBSD_TRUE
+BUILD_DARWIN_FALSE
+BUILD_DARWIN_TRUE
+BUILD_SOLARIS_FALSE
+BUILD_SOLARIS_TRUE
+BUILD_LINUX_FALSE
+BUILD_LINUX_TRUE
+HAVE_PROTOC_C_FALSE
+HAVE_PROTOC_C_TRUE
+have_protoc_c
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+YFLAGS
+YACC
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
+COMPILER_IS_GCC_FALSE
+COMPILER_IS_GCC_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+LTDLOPEN
+LT_CONFIG_H
+subdirs
+CONVENIENCE_LTDL_FALSE
+CONVENIENCE_LTDL_TRUE
+INSTALL_LTDL_FALSE
+INSTALL_LTDL_TRUE
+ARGZ_H
+sys_symbol_underscore
+LIBADD_DL
+LT_DLPREOPEN
+LIBADD_DLD_LINK
+LIBADD_SHL_LOAD
+LIBADD_DLOPEN
+LT_DLLOADERS
+INCLTDL
+LTDLINCL
+LTDLDEPS
+LIBLTDL
+CPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+AWK
+RANLIB
+STRIP
+ac_ct_AR
+AR
+DLLTOOL
+OBJDUMP
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+with_included_ltdl
+with_ltdl_include
+with_ltdl_lib
+enable_ltdl_install
+enable_dependency_tracking
+enable_silent_rules
+enable_largefile
+enable_standards
+with_nan_emulation
+with_fp_layout
+with_useragent
+with_libaquaero5
+with_libhiredis
+with_libcurl
+with_libdbi
+with_libesmtp
+with_libganglia
+with_libgcrypt
+with_libgcrypt_prefix
+with_libiptc
+with_java
+with_libldap
+with_liblvm2app
+with_libmemcached
+with_libmodbus
+with_libmongoc
+with_libmysql
+with_libmnl
+with_libnetapp
+with_libnetsnmp
+with_liboconfig
+with_liboping
+with_oracle
+with_libowcapi
+with_libpcap
+with_libperl
+with_libpq
+with_libpthread
+with_python
+with_librabbitmq
+with_librdkafka
+with_librouteros
+with_librrd
+with_libsensors
+with_libsigrok
+enable_glibtest
+with_libstatgrab
+with_libtokyotyrant
+with_libudev
+with_libupsclient
+with_libxmms
+with_libyajl
+with_mic
+with_libvarnish
+with_libatasmart
+enable_debug
+enable_daemon
+enable_getifaddrs
+enable_all_plugins
+enable_aggregation
+enable_amqp
+enable_apache
+enable_apcups
+enable_apple_sensors
+enable_aquaero
+enable_ascent
+enable_barometer
+enable_battery
+enable_bind
+enable_ceph
+enable_conntrack
+enable_contextswitch
+enable_cpufreq
+enable_cpu
+enable_csv
+enable_curl
+enable_curl_json
+enable_curl_xml
+enable_cgroups
+enable_dbi
+enable_df
+enable_disk
+enable_drbd
+enable_dns
+enable_email
+enable_entropy
+enable_ethstat
+enable_exec
+enable_fhcount
+enable_filecount
+enable_fscache
+enable_gmond
+enable_hddtemp
+enable_interface
+enable_ipc
+enable_ipmi
+enable_iptables
+enable_ipvs
+enable_irq
+enable_java
+enable_load
+enable_logfile
+enable_log_logstash
+enable_lpar
+enable_lvm
+enable_madwifi
+enable_match_empty_counter
+enable_match_hashed
+enable_match_regex
+enable_match_timediff
+enable_match_value
+enable_mbmon
+enable_md
+enable_memcachec
+enable_memcached
+enable_memory
+enable_mic
+enable_modbus
+enable_multimeter
+enable_mysql
+enable_netapp
+enable_netlink
+enable_network
+enable_nfs
+enable_nginx
+enable_notify_desktop
+enable_notify_email
+enable_ntpd
+enable_numa
+enable_nut
+enable_olsrd
+enable_onewire
+enable_openldap
+enable_openvpn
+enable_oracle
+enable_perl
+enable_pf
+enable_pinba
+enable_ping
+enable_postgresql
+enable_powerdns
+enable_processes
+enable_protocols
+enable_python
+enable_redis
+enable_routeros
+enable_rrdcached
+enable_rrdtool
+enable_sensors
+enable_serial
+enable_sigrok
+enable_smart
+enable_snmp
+enable_statsd
+enable_swap
+enable_syslog
+enable_table
+enable_tail
+enable_tail_csv
+enable_tape
+enable_target_notification
+enable_target_replace
+enable_target_scale
+enable_target_set
+enable_target_v5upgrade
+enable_tcpconns
+enable_teamspeak2
+enable_ted
+enable_thermal
+enable_threshold
+enable_tokyotyrant
+enable_turbostat
+enable_unixsock
+enable_uptime
+enable_users
+enable_uuid
+enable_varnish
+enable_virt
+enable_vmem
+enable_vserver
+enable_wireless
+enable_write_graphite
+enable_write_http
+enable_write_kafka
+enable_write_log
+enable_write_mongodb
+enable_write_redis
+enable_write_riemann
+enable_write_sensu
+enable_write_tsdb
+enable_xmms
+enable_zfs_arc
+enable_zookeeper
+with_perl_bindings
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+YACC
+YFLAGS
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+KERNEL_DIR
+LIBNETAPP_CPPFLAGS
+LIBNETAPP_LDFLAGS
+LIBNETAPP_LIBS
+LIBNOTIFY_CFLAGS
+LIBNOTIFY_LIBS'
+ac_subdirs_all='libltdl'
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_myself" : 'X\(//\)[^/]' \| \
+        X"$as_myself" : 'X\(//\)$' \| \
+        X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures collectd 5.5.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/collectd]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of collectd 5.5.0:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-ltdl-install   install libltdl
+  --enable-dependency-tracking
+                          do not reject slow dependency extractors
+  --disable-dependency-tracking
+                          speeds up one-time build
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
+  --disable-largefile     omit support for large files
+  --enable-standards      Enable standards compliance mode
+  --disable-glibtest      do not try to compile and run a test GLIB program
+
+collectd features:
+  --enable-debug          enable debugging (disabled by def)
+  --disable-daemon        disable daemon mode (enabled by def)
+  --enable-getifaddrs     enable getifaddrs under Linux (disabled by def)
+
+collectd plugins:
+  --enable-all-plugins    enable all plugins (auto by def)
+
+  --enable-aggregation    Aggregation plugin
+  --enable-amqp           AMQP output plugin
+  --enable-apache         Apache httpd statistics
+  --enable-apcups         Statistics of UPSes by APC
+  --enable-apple_sensors  Apple's hardware sensors
+  --enable-aquaero        Aquaero's hardware sensors
+  --enable-ascent         AscentEmu player statistics
+  --enable-barometer      Barometer sensor on I2C
+  --enable-battery        Battery statistics
+  --enable-bind           ISC Bind nameserver statistics
+  --enable-ceph           Ceph daemon statistics
+  --enable-conntrack      nf_conntrack statistics
+  --enable-contextswitch  context switch statistics
+  --enable-cpufreq        CPU frequency statistics
+  --enable-cpu            CPU usage statistics
+  --enable-csv            CSV output plugin
+  --enable-curl           CURL generic web statistics
+  --enable-curl_json      CouchDB statistics
+  --enable-curl_xml       CURL generic xml statistics
+  --enable-cgroups        CGroups CPU usage accounting
+  --enable-dbi            General database statistics
+  --enable-df             Filesystem usage statistics
+  --enable-disk           Disk usage statistics
+  --enable-drbd           DRBD statistics
+  --enable-dns            DNS traffic analysis
+  --enable-email          EMail statistics
+  --enable-entropy        Entropy statistics
+  --enable-ethstat        Stats from NIC driver
+  --enable-exec           Execution of external programs
+  --enable-fhcount        File handles statistics
+  --enable-filecount      Count files in directories
+  --enable-fscache        fscache statistics
+  --enable-gmond          Ganglia plugin
+  --enable-hddtemp        Query hddtempd
+  --enable-interface      Interface traffic statistics
+  --enable-ipc            IPC statistics
+  --enable-ipmi           IPMI sensor statistics
+  --enable-iptables       IPTables rule counters
+  --enable-ipvs           IPVS connection statistics
+  --enable-irq            IRQ statistics
+  --enable-java           Embed the Java Virtual Machine
+  --enable-load           System load
+  --enable-logfile        File logging plugin
+  --enable-log_logstash   Logstash json_event compatible logging
+  --enable-lpar           AIX logical partitions statistics
+  --enable-lvm            LVM statistics
+  --enable-madwifi        Madwifi wireless statistics
+  --enable-match_empty_counter
+                          The empty counter match
+  --enable-match_hashed   The hashed match
+  --enable-match_regex    The regex match
+  --enable-match_timediff The timediff match
+  --enable-match_value    The value match
+  --enable-mbmon          Query mbmond
+  --enable-md             md (Linux software RAID) devices
+  --enable-memcachec      memcachec statistics
+  --enable-memcached      memcached statistics
+  --enable-memory         Memory usage
+  --enable-mic            Intel Many Integrated Core stats
+  --enable-modbus         Modbus plugin
+  --enable-multimeter     Read multimeter values
+  --enable-mysql          MySQL statistics
+  --enable-netapp         NetApp plugin
+  --enable-netlink        Enhanced Linux network statistics
+  --enable-network        Network communication plugin
+  --enable-nfs            NFS statistics
+  --enable-nginx          nginx statistics
+  --enable-notify_desktop Desktop notifications
+  --enable-notify_email   Email notifier
+  --enable-ntpd           NTPd statistics
+  --enable-numa           NUMA virtual memory statistics
+  --enable-nut            Network UPS tools statistics
+  --enable-olsrd          olsrd statistics
+  --enable-onewire        OneWire sensor statistics
+  --enable-openldap       OpenLDAP statistics
+  --enable-openvpn        OpenVPN client statistics
+  --enable-oracle         Oracle plugin
+  --enable-perl           Embed a Perl interpreter
+  --enable-pf             BSD packet filter (PF) statistics
+  --enable-pinba          Pinba statistics
+  --enable-ping           Network latency statistics
+  --enable-postgresql     PostgreSQL database statistics
+  --enable-powerdns       PowerDNS statistics
+  --enable-processes      Process statistics
+  --enable-protocols      Protocol (IP, TCP, ...) statistics
+  --enable-python         Embed a Python interpreter
+  --enable-redis          Redis plugin
+  --enable-routeros       RouterOS plugin
+  --enable-rrdcached      RRDTool output plugin
+  --enable-rrdtool        RRDTool output plugin
+  --enable-sensors        lm_sensors statistics
+  --enable-serial         serial port traffic
+  --enable-sigrok         sigrok acquisition sources
+  --enable-smart          SMART statistics
+  --enable-snmp           SNMP querying plugin
+  --enable-statsd         StatsD plugin
+  --enable-swap           Swap usage statistics
+  --enable-syslog         Syslog logging plugin
+  --enable-table          Parsing of tabular data
+  --enable-tail           Parsing of logfiles
+  --enable-tail_csv       Parsing of CSV files
+  --enable-tape           Tape drive statistics
+  --enable-target_notification
+                          The notification target
+  --enable-target_replace The replace target
+  --enable-target_scale   The scale target
+  --enable-target_set     The set target
+  --enable-target_v5upgrade
+                          The v5upgrade target
+  --enable-tcpconns       TCP connection statistics
+  --enable-teamspeak2     TeamSpeak2 server statistics
+  --enable-ted            Read The Energy Detective values
+  --enable-thermal        Linux ACPI thermal zone statistics
+  --enable-threshold      Threshold checking plugin
+  --enable-tokyotyrant    TokyoTyrant database statistics
+  --enable-turbostat      Advanced statistic on Intel cpu states
+  --enable-unixsock       Unixsock communication plugin
+  --enable-uptime         Uptime statistics
+  --enable-users          User statistics
+  --enable-uuid           UUID as hostname plugin
+  --enable-varnish        Varnish cache statistics
+  --enable-virt           Virtual machine statistics
+  --enable-vmem           Virtual memory statistics
+  --enable-vserver        Linux VServer statistics
+  --enable-wireless       Wireless statistics
+  --enable-write_graphite Graphite / Carbon output plugin
+  --enable-write_http     HTTP output plugin
+  --enable-write_kafka    Kafka output plugin
+  --enable-write_log      Log output plugin
+  --enable-write_mongodb  MongoDB output plugin
+  --enable-write_redis    Redis output plugin
+  --enable-write_riemann  Riemann output plugin
+  --enable-write_sensu    Sensu output plugin
+  --enable-write_tsdb     TSDB output plugin
+  --enable-xmms           XMMS statistics
+  --enable-zfs_arc        ZFS ARC statistics
+  --enable-zookeeper      Zookeeper statistics
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-sysroot=DIR Search for dependent libraries within DIR
+                        (or the compiler's sysroot if not specified).
+  --with-included-ltdl    use the GNU ltdl sources included here
+  --with-ltdl-include=DIR use the ltdl headers installed in DIR
+  --with-ltdl-lib=DIR     use the libltdl.la installed in DIR
+  --with-nan-emulation    use emulated NAN. For crosscompiling only.
+  --with-fp-layout        set the memory layout of doubles. For crosscompiling
+                          only.
+  --with-useragent[=AGENT]
+                          User agent to use on http requests
+
+collectd additional packages:
+  --with-libaquaero5[=PREFIX]
+                          Path to aquatools-ng source code.
+  --with-libhiredis[=PREFIX]
+                          Path to libhiredis.
+  --with-libcurl[=PREFIX] Path to libcurl.
+  --with-libdbi[=PREFIX]  Path to libdbi.
+  --with-libesmtp[=PREFIX]
+                          Path to libesmtp.
+  --with-libganglia[=PREFIX]
+                          Path to libganglia.
+  --with-libgcrypt[=PREFIX]
+                          Path to libgcrypt.
+  --with-libgcrypt-prefix=PFX
+                          prefix where LIBGCRYPT is installed (optional)
+  --with-libiptc[=PREFIX] Path to libiptc.
+  --with-java[=PREFIX]    Path to Java home.
+  --with-libldap[=PREFIX] Path to libldap.
+  --with-liblvm2app[=PREFIX]
+                          Path to liblvm2app.
+  --with-libmemcached[=PREFIX]
+                          Path to libmemcached.
+  --with-libmodbus[=PREFIX]
+                          Path to the modbus library.
+  --with-libmongoc[=PREFIX]
+                          Path to libmongoc.
+  --with-libmysql[=PREFIX]
+                          Path to libmysql.
+  --with-libmnl[=PREFIX]  Path to libmnl.
+  --with-libnetapp[=PREFIX]
+                          Path to libnetapp.
+  --with-libnetsnmp[=PREFIX]
+                          Path to the Net-SNMPD library.
+  --with-liboconfig[=PREFIX]
+                          Path to liboconfig.
+  --with-liboping[=PREFIX]
+                          Path to liboping.
+  --with-oracle[=ORACLE_HOME]
+                          Path to Oracle.
+  --with-libowcapi[=PREFIX]
+                          Path to libowcapi.
+  --with-libpcap[=PREFIX] Path to libpcap.
+  --with-libperl[=PREFIX] Path to libperl.
+  --with-libpq[=PREFIX]   Path to libpq.
+  --with-libpthread=[=PREFIX]
+                          Path to libpthread.
+  --with-python[=PREFIX]  Path to the python interpreter.
+  --with-librabbitmq[=PREFIX]
+                          Path to librabbitmq.
+  --with-librdkafka[=PREFIX]
+                          Path to librdkafka.
+  --with-librouteros[=PREFIX]
+                          Path to librouteros.
+  --with-librrd[=PREFIX]  Path to rrdtool.
+  --with-libsensors[=PREFIX]
+                          Path to lm_sensors.
+  --with-libsigrok[=PREFIX]
+                          Path to libsigrok.
+  --with-libstatgrab[=PREFIX]
+                          Path to libstatgrab.
+  --with-libtokyotyrant[=PREFIX]
+                          Path to libtokyotyrant.
+  --with-libudev[=PREFIX] Path to libudev.
+  --with-libupsclient[=PREFIX]
+                          Path to the upsclient library.
+  --with-libxmms[=PREFIX] Path to libxmms.
+  --with-libyajl[=PREFIX] Path to libyajl.
+  --with-mic[=PREFIX]     Path to Intel MIC Access API.
+  --with-libvarnish[=PREFIX]
+                          Path to libvarnish.
+  --with-libatasmart[=PREFIX]
+                          Path to libatasmart.
+  --with-perl-bindings[=OPTIONS]
+                          Options passed to "perl Makefile.PL".
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+  YACC        The `Yet Another Compiler Compiler' implementation to use.
+              Defaults to the first program found out of: `bison -y', `byacc',
+              `yacc'.
+  YFLAGS      The list of arguments that will be passed by default to $YACC.
+              This script will default YFLAGS to the empty string to avoid a
+              default value of `-d' given by some make applications.
+  PKG_CONFIG  path to pkg-config utility
+  PKG_CONFIG_PATH
+              directories to add to pkg-config's search path
+  PKG_CONFIG_LIBDIR
+              path overriding pkg-config's built-in search path
+  KERNEL_DIR  path to Linux kernel sources
+  LIBNETAPP_CPPFLAGS
+              C preprocessor flags required to build with libnetapp
+  LIBNETAPP_LDFLAGS
+              Linker flags required to build with libnetapp
+  LIBNETAPP_LIBS
+              Other libraries required to link against libnetapp
+  LIBNOTIFY_CFLAGS
+              C compiler flags for LIBNOTIFY, overriding pkg-config
+  LIBNOTIFY_LIBS
+              linker flags for LIBNOTIFY, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+collectd configure 5.5.0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+        return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+           return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_find_uintX_t LINENO BITS VAR
+# ------------------------------------
+# Finds an unsigned integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_uintX_t ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+$as_echo_n "checking for uint$2_t... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+     # Order is important - never check a type that is potentially smaller
+     # than half of the expected target width.
+     for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+        'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  case $ac_type in #(
+  uint$2_t) :
+    eval "$3=yes" ;; #(
+  *) :
+    eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       if eval test \"x\$"$3"\" = x"no"; then :
+
+else
+  break
+fi
+     done
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_uintX_t
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by collectd $as_me 5.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       $as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       # differences in whitespace do not lead to failure.
+       ac_old_val_w=`echo x $ac_old_val`
+       ac_new_val_w=`echo x $ac_new_val`
+       if test "$ac_old_val_w" != "$ac_new_val_w"; then
+         { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+         ac_cache_corrupted=:
+       else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+         eval $ac_var=\$ac_old_val
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers src/config.h"
+
+ac_aux_dir=
+for ac_dir in libltdl/config "$srcdir"/libltdl/config; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in libltdl/config \"$srcdir\"/libltdl/config" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+
+# libtool >= 2.2
+
+
+
+
+
+
+
+
+        case `pwd` in
+  *\ * | *\    *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.2'
+macro_revision='1.3337'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case "$ECHO" in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if ${ac_cv_path_FGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if ${lt_cv_path_NM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if ${lt_cv_nm_interface+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if ${lt_cv_sys_max_cmd_len+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[         ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \
+                = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,b/c, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+$as_echo_n "checking how to convert $build file names to $host format... " >&6; }
+if ${lt_cv_to_host_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+$as_echo "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
+if ${lt_cv_to_tool_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+$as_echo "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if ${lt_cv_ld_reload_flag+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test "$GCC" != yes; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if ${lt_cv_deplibs_check_method+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DLLTOOL=$ac_ct_DLLTOOL
+  fi
+else
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+$as_echo_n "checking how to associate runtime and link libraries... " >&6; }
+if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in ar
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$AR" && break
+  done
+fi
+if test -z "$AR"; then
+  ac_ct_AR=$AR
+  for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_AR" && break
+done
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+fi
+
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+$as_echo_n "checking for archiver @FILE support... " >&6; }
+if ${lt_cv_ar_at_file+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ar_at_file=no
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+      if test "$ac_status" -eq 0; then
+       # Ensure the archiver fails upon bogus file names.
+       rm -f conftest.$ac_objext libconftest.a
+       { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+       if test "$ac_status" -ne 0; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+$as_echo "$lt_cv_ar_at_file" >&6; }
+
+if test "x$lt_cv_ar_at_file" = xno; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if ${lt_cv_sys_global_symbol_pipe+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[     ]\($symcode$symcode*\)[         ][      ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+       if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+         cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+         cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_globsym_save_LIBS=$LIBS
+         lt_globsym_save_CFLAGS=$CFLAGS
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS=$lt_globsym_save_LIBS
+         CFLAGS=$lt_globsym_save_CFLAGS
+       else
+         echo "cannot find nm_test_func in $nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+$as_echo_n "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+  withval=$with_sysroot;
+else
+  with_sysroot=no
+fi
+
+
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+   if test "$GCC" = yes; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5
+$as_echo "${with_sysroot}" >&6; }
+   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+   ;;
+esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+$as_echo "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+       HPUX_IA64_MODE="32"
+       ;;
+      *ELF-64*)
+       HPUX_IA64_MODE="64"
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -melf32bsmip"
+         ;;
+       *N32*)
+         LD="${LD-ld} -melf32bmipn32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -melf64bmip"
+       ;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -32"
+         ;;
+       *N32*)
+         LD="${LD-ld} -n32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -64"
+         ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_i386_fbsd"
+           ;;
+         x86_64-*linux*)
+           case `/usr/bin/file conftest.o` in
+             *x86-64*)
+               LD="${LD-ld} -m elf32_x86_64"
+               ;;
+             *)
+               LD="${LD-ld} -m elf_i386"
+               ;;
+           esac
+           ;;
+         powerpc64le-*)
+           LD="${LD-ld} -m elf32lppclinux"
+           ;;
+         powerpc64-*)
+           LD="${LD-ld} -m elf32ppclinux"
+           ;;
+         s390x-*linux*)
+           LD="${LD-ld} -m elf_s390"
+           ;;
+         sparc64-*linux*)
+           LD="${LD-ld} -m elf32_sparc"
+           ;;
+       esac
+       ;;
+      *64-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_x86_64_fbsd"
+           ;;
+         x86_64-*linux*)
+           LD="${LD-ld} -m elf_x86_64"
+           ;;
+         powerpcle-*)
+           LD="${LD-ld} -m elf64lppc"
+           ;;
+         powerpc-*)
+           LD="${LD-ld} -m elf64ppc"
+           ;;
+         s390*-*linux*|s390*-*tpf*)
+           LD="${LD-ld} -m elf64_s390"
+           ;;
+         sparc*-*linux*)
+           LD="${LD-ld} -m elf64_sparc"
+           ;;
+       esac
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if ${lt_cv_cc_needs_belf+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD="${LD-ld}_sol2"
+        fi
+        ;;
+      *)
+       if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+         LD="${LD-ld} -64"
+       fi
+       ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$MANIFEST_TOOL"; then
+  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+$as_echo "$MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+  # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_MANIFEST_TOOL"; then
+  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+$as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_MANIFEST_TOOL" = x; then
+    MANIFEST_TOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+  fi
+else
+  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if ${lt_cv_path_mainfest_tool+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&5
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+$as_echo "$lt_cv_path_mainfest_tool" >&6; }
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+  MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if ${lt_cv_apple_cc_single_mod+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+       # By default we will add the -single_module flag. You can override
+       # by either setting the environment variable LT_MULTI_MODULE
+       # non-empty at configure time, or by adding -multi_module to the
+       # link flags.
+       rm -rf libconftest.dylib*
+       echo "int foo(void){return 1;}" > conftest.c
+       echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+       $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+         -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+       # If there is a non-empty error log, and "single_module"
+       # appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+         cat conftest.err >&5
+       # Otherwise, if the output was created with a 0 exit code from
+       # the compiler, it worked.
+       elif test -f libconftest.dylib && test $_lt_result -eq 0; then
+         lt_cv_apple_cc_single_mod=yes
+       else
+         cat conftest.err >&5
+       fi
+       rm -rf libconftest.dylib*
+       rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if ${lt_cv_ld_exported_symbols_list+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+       LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if ${lt_cv_ld_force_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cru libconftest.a conftest.o" >&5
+      $AR cru libconftest.a conftest.o 2>&5
+      echo "$RANLIB libconftest.a" >&5
+      $RANLIB libconftest.a 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+       cat conftest.err >&5
+      elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then
+       lt_cv_ld_force_load=yes
+      else
+       cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+       10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+       10.[012]*)
+         _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+       10.*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+# Set options
+enable_dlopen=yes
+
+
+
+
+  enable_win32_dll=no
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for lt_pkg in $withval; do
+       IFS="$lt_save_ifs"
+       if test "X$lt_pkg" = "X$lt_p"; then
+         pic_mode=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if ${lt_cv_objdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='-fPIC'
+       ;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      if test -n "$lt_prog_compiler_pic"; then
+        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      else
+       lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-KPIC'
+       lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-fPIC'
+       lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='--shared'
+       lt_prog_compiler_static='--static'
+       ;;
+      nagfor*)
+       # NAG Fortran compiler
+       lt_prog_compiler_wl='-Wl,-Wl,,'
+       lt_prog_compiler_pic='-PIC'
+       lt_prog_compiler_static='-Bstatic'
+       ;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-fpic'
+       lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+       # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-qpic'
+       lt_prog_compiler_static='-qstaticlink'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl=''
+         ;;
+       *Sun\ F* | *Sun*Fortran*)
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl='-Qoption ld '
+         ;;
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl='-Wl,'
+         ;;
+        *Intel*\ [CF]*Compiler*)
+         lt_prog_compiler_wl='-Wl,'
+         lt_prog_compiler_pic='-fPIC'
+         lt_prog_compiler_static='-static'
+         ;;
+       *Portland\ Group*)
+         lt_prog_compiler_wl='-Wl,'
+         lt_prog_compiler_pic='-fpic'
+         lt_prog_compiler_static='-Bstatic'
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+       lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic='-Kconform_pic'
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+$as_echo "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    link_all_deplibs=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+       # The AIX port of GNU ld has always aspired to compatibility
+       # with the native linker.  However, as the warning in the GNU ld
+       # block says, versions before 2.19.5* couldn't really create working
+       # shared libraries, regardless of the interface used.
+       case `$LD -v 2>&1` in
+         *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+         *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+         *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+         *)
+           lt_use_gnu_ld_interface=yes
+           ;;
+       esac
+       ;;
+      *)
+       lt_use_gnu_ld_interface=yes
+       ;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='${wl}--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+       case $cc_basename in
+         diet\ *) tmp_diet=yes;;       # linux-dietlibc with static linking (!diet-dyn)
+       esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+        && test "$tmp_diet" = no
+      then
+       tmp_addflag=' $pic_flag'
+       tmp_sharedflag='-shared'
+       case $cc_basename,$host_cpu in
+        pgcc*)                         # Portland Group C compiler
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95* | pgfortran*)
+                                       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)        # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       lf95*)                          # Lahey Fortran 8.1
+         whole_archive_flag_spec=
+         tmp_sharedflag='--shared' ;;
+       xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+         tmp_sharedflag='-qmkshrobj'
+         tmp_addflag= ;;
+       nvcc*)  # Cuda Compiler Driver 2.2
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         compiler_needs_object=yes
+         ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         compiler_needs_object=yes
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       esac
+       archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+           cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+           echo "local: *; };" >> $output_objdir/$libname.ver~
+           $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+       case $cc_basename in
+       xlf* | bgf* | bgxlf* | mpixlf*)
+         # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+         whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+         hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+         archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+         if test "x$supports_anon_versioning" = xyes; then
+           archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+             cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+             echo "local: *; };" >> $output_objdir/$libname.ver~
+             $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+         fi
+         ;;
+       esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         # For security reasons, it is highly recommended that you always
+         # use absolute paths for naming shared libraries, and exclude the
+         # DT_RUNPATH tag from executables and libraries.  But doing so
+         # requires that you compile everything twice, which is a pain.
+         if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+           archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         else
+           ld_shlibs=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       # Also, AIX nm treats weak defined symbols like other global
+       # defined symbols, whereas GNU nm marks them as "W".
+       if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+         export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+          strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L=yes
+         hardcode_libdir_flag_spec='-L$libdir'
+         hardcode_libdir_separator=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+       link_all_deplibs=no
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      export_dynamic_flag_spec='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+         /^0/ {
+             s/^0  *\([^ ]*\) *$/\1/
+             p
+         }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag="-z nodefs"
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+         /^0/ {
+             s/^0  *\([^ ]*\) *$/\1/
+             p
+         }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag=' ${wl}-bernotok'
+         allow_undefined_flag=' ${wl}-berok'
+         if test "$with_gnu_ld" = yes; then
+           # We only use this code for GNU lds that support --whole-archive.
+           whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+         else
+           # Exported symbols can be pulled into shared objects from archives
+           whole_archive_flag_spec='$convenience'
+         fi
+         archive_cmds_need_lc=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl*)
+       # Native MSVC
+       hardcode_libdir_flag_spec=' '
+       allow_undefined_flag=unsupported
+       always_export_symbols=yes
+       file_list_spec='@'
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+       archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+           sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+         else
+           sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+         fi~
+         $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+         linknames='
+       # The linker will not automatically build a static lib if we build a DLL.
+       # _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+       enable_shared_with_static_runtimes=yes
+       exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+       export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+       # Don't use ranlib
+       old_postinstall_cmds='chmod 644 $oldlib'
+       postlink_cmds='lt_outputfile="@OUTPUT@"~
+         lt_tool_outputfile="@TOOL_OUTPUT@"~
+         case $lt_outputfile in
+           *.exe|*.EXE) ;;
+           *)
+             lt_outputfile="$lt_outputfile.exe"
+             lt_tool_outputfile="$lt_tool_outputfile.exe"
+             ;;
+         esac~
+         if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+           $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+           $RM "$lt_outputfile.manifest";
+         fi'
+       ;;
+      *)
+       # Assume MSVC wrapper
+       hardcode_libdir_flag_spec=' '
+       allow_undefined_flag=unsupported
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+       # The linker will automatically build a .lib file if we build a DLL.
+       old_archive_from_new_cmds='true'
+       # FIXME: Should let the user specify the lib program.
+       old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+       enable_shared_with_static_runtimes=yes
+       ;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+       hardcode_direct=yes
+       hardcode_direct_absolute=yes
+       export_dynamic_flag_spec='${wl}-E'
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+
+         # Older versions of the 11.00 compiler do not understand -b yet
+         # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if ${lt_cv_prog_compiler__b+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_direct=no
+         hardcode_shlibpath_var=no
+         ;;
+       *)
+         hardcode_direct=yes
+         hardcode_direct_absolute=yes
+         export_dynamic_flag_spec='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       # Try to use the -exported_symbol ld option, if it does not
+       # work, assume that -exports_file does not work either and
+       # implicitly export all symbols.
+       # This should be the same for all languages, so no per-tag cache variable.
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if ${lt_cv_irix_exported_symbol+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  save_LDFLAGS="$LDFLAGS"
+          LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_irix_exported_symbol=yes
+else
+  lt_cv_irix_exported_symbol=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+           LDFLAGS="$save_LDFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+$as_echo "$lt_cv_irix_exported_symbol" >&6; }
+       if test "$lt_cv_irix_exported_symbol" = yes; then
+          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+       fi
+      else
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct=yes
+       hardcode_shlibpath_var=no
+       hardcode_direct_absolute=yes
+       if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec='-R$libdir'
+            ;;
+          *)
+            archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+            ;;
+         esac
+       fi
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+       $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+       case `$CC -V 2>&1` in
+       *"Compilers 5.0"*)
+         wlarc=''
+         archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+         ;;
+       *)
+         wlarc='${wl}'
+         archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+         ;;
+       esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds='$CC -r -o $output$reload_objs'
+         hardcode_direct=no
+        ;;
+       motorola)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+       export_dynamic_flag_spec='${wl}-Blargedynsym'
+       ;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+       echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+       if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+         soname=conftest
+         lib=conftest
+         libobjs=conftest.$ac_objext
+         deplibs=
+         wl=$lt_prog_compiler_wl
+         pic_flag=$lt_prog_compiler_pic
+         compiler_flags=-v
+         linker_flags=-v
+         verstring=
+         output_objdir=.
+         libname=conftest
+         lt_save_allow_undefined_flag=$allow_undefined_flag
+         allow_undefined_flag=
+         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+         then
+           lt_cv_archive_cmds_need_lc=no
+         else
+           lt_cv_archive_cmds_need_lc=yes
+         fi
+         allow_undefined_flag=$lt_save_allow_undefined_flag
+       else
+         cat conftest.err 1>&5
+       fi
+       $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux # correct to gnu/linux during the next big refactor
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+        LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[      ]*hwcap[        ]/d;s/[:,      ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self_static+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking which extension is used for runtime loadable modules" >&5
+$as_echo_n "checking which extension is used for runtime loadable modules... " >&6; }
+if ${libltdl_cv_shlibext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+module=yes
+eval libltdl_cv_shlibext=$shrext_cmds
+module=no
+eval libltdl_cv_shrext=$shrext_cmds
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_shlibext" >&5
+$as_echo "$libltdl_cv_shlibext" >&6; }
+if test -n "$libltdl_cv_shlibext"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LT_MODULE_EXT "$libltdl_cv_shlibext"
+_ACEOF
+
+fi
+if test "$libltdl_cv_shrext" != "$libltdl_cv_shlibext"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LT_SHARED_EXT "$libltdl_cv_shrext"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which variable specifies run-time module search path" >&5
+$as_echo_n "checking which variable specifies run-time module search path... " >&6; }
+if ${lt_cv_module_path_var+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_module_path_var="$shlibpath_var"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_module_path_var" >&5
+$as_echo "$lt_cv_module_path_var" >&6; }
+if test -n "$lt_cv_module_path_var"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LT_MODULE_PATH_VAR "$lt_cv_module_path_var"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the default library search path" >&5
+$as_echo_n "checking for the default library search path... " >&6; }
+if ${lt_cv_sys_dlsearch_path+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sys_dlsearch_path="$sys_lib_dlsearch_path_spec"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_dlsearch_path" >&5
+$as_echo "$lt_cv_sys_dlsearch_path" >&6; }
+if test -n "$lt_cv_sys_dlsearch_path"; then
+  sys_dlsearch_path=
+  for dir in $lt_cv_sys_dlsearch_path; do
+    if test -z "$sys_dlsearch_path"; then
+      sys_dlsearch_path="$dir"
+    else
+      sys_dlsearch_path="$sys_dlsearch_path$PATH_SEPARATOR$dir"
+    fi
+  done
+
+cat >>confdefs.h <<_ACEOF
+#define LT_DLSEARCH_PATH "$sys_dlsearch_path"
+_ACEOF
+
+fi
+
+
+LT_DLLOADERS=
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+LIBADD_DLOPEN=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dlopen+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_LIBDL 1" >>confdefs.h
+
+       if test "$ac_cv_search_dlopen" != "none required" ; then
+         LIBADD_DLOPEN="-ldl"
+       fi
+       libltdl_cv_lib_dl_dlopen="yes"
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if HAVE_DLFCN_H
+#  include <dlfcn.h>
+#endif
+
+int
+main ()
+{
+dlopen(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_LIBDL 1" >>confdefs.h
+
+           libltdl_cv_func_dlopen="yes"
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+
+$as_echo "#define HAVE_LIBDL 1" >>confdefs.h
+
+               LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes"
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"
+fi
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes
+then
+  lt_save_LIBS="$LIBS"
+  LIBS="$LIBS $LIBADD_DLOPEN"
+  for ac_func in dlerror
+do :
+  ac_fn_c_check_func "$LINENO" "dlerror" "ac_cv_func_dlerror"
+if test "x$ac_cv_func_dlerror" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLERROR 1
+_ACEOF
+
+fi
+done
+
+  LIBS="$lt_save_LIBS"
+fi
+
+
+LIBADD_SHL_LOAD=
+ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+
+$as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h
+
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+
+$as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h
+
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"
+           LIBADD_SHL_LOAD="-ldld"
+fi
+
+fi
+
+
+
+case $host_os in
+darwin[1567].*)
+# We only want this for pre-Mac OS X 10.4.
+  ac_fn_c_check_func "$LINENO" "_dyld_func_lookup" "ac_cv_func__dyld_func_lookup"
+if test "x$ac_cv_func__dyld_func_lookup" = xyes; then :
+
+$as_echo "#define HAVE_DYLD 1" >>confdefs.h
+
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dyld.la"
+fi
+
+  ;;
+beos*)
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}load_add_on.la"
+  ;;
+cygwin* | mingw* | os2* | pw32*)
+  ac_fn_c_check_decl "$LINENO" "cygwin_conv_path" "ac_cv_have_decl_cygwin_conv_path" "#include <sys/cygwin.h>
+"
+if test "x$ac_cv_have_decl_cygwin_conv_path" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_CYGWIN_CONV_PATH $ac_have_decl
+_ACEOF
+
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}loadlibrary.la"
+  ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+
+$as_echo "#define HAVE_DLD 1" >>confdefs.h
+
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dld_link.la"
+fi
+
+
+
+
+LT_DLPREOPEN=
+if test -n "$LT_DLLOADERS"
+then
+  for lt_loader in $LT_DLLOADERS; do
+    LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen $lt_loader "
+  done
+
+$as_echo "#define HAVE_LIBDLLOADER 1" >>confdefs.h
+
+fi
+
+
+LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ prefix in compiled symbols" >&5
+$as_echo_n "checking for _ prefix in compiled symbols... " >&6; }
+if ${lt_cv_sys_symbol_underscore+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sys_symbol_underscore=no
+  cat > conftest.$ac_ext <<_LT_EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$ac_nlist"; then
+      # See whether the symbols have a leading underscore.
+      if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+        lt_cv_sys_symbol_underscore=yes
+      else
+        if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+         :
+        else
+         echo "configure: cannot find nm_test_func in $ac_nlist" >&5
+        fi
+      fi
+    else
+      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "configure: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  rm -rf conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_symbol_underscore" >&5
+$as_echo "$lt_cv_sys_symbol_underscore" >&6; }
+  sys_symbol_underscore=$lt_cv_sys_symbol_underscore
+
+
+if test x"$lt_cv_sys_symbol_underscore" = xyes; then
+  if test x"$libltdl_cv_func_dlopen" = xyes ||
+     test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have to add an underscore for dlsym" >&5
+$as_echo_n "checking whether we have to add an underscore for dlsym... " >&6; }
+if ${libltdl_cv_need_uscore+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  libltdl_cv_need_uscore=unknown
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $LIBADD_DLOPEN"
+         if test "$cross_compiling" = yes; then :
+  libltdl_cv_need_uscore=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;;
+      x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;;
+      x$lt_dlunknown|x*)  ;;
+    esac
+  else :
+    # compilation failed
+
+  fi
+fi
+rm -fr conftest*
+
+         LIBS="$save_LIBS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_need_uscore" >&5
+$as_echo "$libltdl_cv_need_uscore" >&6; }
+  fi
+fi
+
+if test x"$libltdl_cv_need_uscore" = xyes; then
+
+$as_echo "#define NEED_USCORE 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether deplibs are loaded by dlopen" >&5
+$as_echo_n "checking whether deplibs are loaded by dlopen... " >&6; }
+if ${lt_cv_sys_dlopen_deplibs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # PORTME does your system automatically load deplibs for dlopen?
+  # or its logical equivalent (e.g. shl_load for HP-UX < 11)
+  # For now, we just catch OSes we know something about -- in the
+  # future, we'll try test this programmatically.
+  lt_cv_sys_dlopen_deplibs=unknown
+  case $host_os in
+  aix3*|aix4.1.*|aix4.2.*)
+    # Unknown whether this is true for these versions of AIX, but
+    # we want this `case' here to explicitly catch those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  aix[4-9]*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  amigaos*)
+    case $host_cpu in
+    powerpc)
+      lt_cv_sys_dlopen_deplibs=no
+      ;;
+    esac
+    ;;
+  darwin*)
+    # Assuming the user has installed a libdl from somewhere, this is true
+    # If you are looking for one http://www.opendarwin.org/projects/dlcompat
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  freebsd* | dragonfly*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  gnu* | linux* | k*bsd*-gnu | kopensolaris*-gnu)
+    # GNU and its variants, using gnu ld.so (Glibc)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  hpux10*|hpux11*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  interix*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  irix[12345]*|irix6.[01]*)
+    # Catch all versions of IRIX before 6.2, and indicate that we don't
+    # know how it worked for any of those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  irix*)
+    # The case above catches anything before 6.2, and it's known that
+    # at 6.2 and later dlopen does load deplibs.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  openbsd*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  osf[1234]*)
+    # dlopen did load deplibs (at least at 4.x), but until the 5.x series,
+    # it did *not* use an RPATH in a shared library to find objects the
+    # library depends on, so we explicitly say `no'.
+    lt_cv_sys_dlopen_deplibs=no
+    ;;
+  osf5.0|osf5.0a|osf5.1)
+    # dlopen *does* load deplibs and with the right loader patch applied
+    # it even uses RPATH in a shared library to search for shared objects
+    # that the library depends on, but there's no easy way to know if that
+    # patch is installed.  Since this is the case, all we can really
+    # say is unknown -- it depends on the patch being installed.  If
+    # it is, this changes to `yes'.  Without it, it would be `no'.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  osf*)
+    # the two cases above should catch all versions of osf <= 5.1.  Read
+    # the comments above for what we know about them.
+    # At > 5.1, deplibs are loaded *and* any RPATH in a shared library
+    # is used to find them so we can finally say `yes'.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  qnx*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  solaris*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_dlopen_deplibs" >&5
+$as_echo "$lt_cv_sys_dlopen_deplibs" >&6; }
+if test "$lt_cv_sys_dlopen_deplibs" != yes; then
+
+$as_echo "#define LTDL_DLOPEN_DEPLIBS 1" >>confdefs.h
+
+fi
+
+:
+
+for ac_header in argz.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "argz.h" "ac_cv_header_argz_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_argz_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ARGZ_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_fn_c_check_type "$LINENO" "error_t" "ac_cv_type_error_t" "#if defined(HAVE_ARGZ_H)
+#  include <argz.h>
+#endif
+"
+if test "x$ac_cv_type_error_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ERROR_T 1
+_ACEOF
+
+
+else
+
+$as_echo "#define error_t int" >>confdefs.h
+
+
+$as_echo "#define __error_t_defined 1" >>confdefs.h
+
+fi
+
+
+ARGZ_H=
+for ac_func in argz_add argz_append argz_count argz_create_sep argz_insert \
+       argz_next argz_stringify
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  ARGZ_H=argz.h;
+
+  _LT_LIBOBJS="$_LT_LIBOBJS argz.$ac_objext"
+
+fi
+done
+
+
+if test -z "$ARGZ_H"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if argz actually works" >&5
+$as_echo_n "checking if argz actually works... " >&6; }
+if ${lt_cv_sys_argz_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $host_os in #(
+        *cygwin*)
+          lt_cv_sys_argz_works=no
+          if test "$cross_compiling" != no; then
+            lt_cv_sys_argz_works="guessing no"
+          else
+            lt_sed_extract_leading_digits='s/^\([0-9\.]*\).*/\1/'
+            save_IFS=$IFS
+            IFS=-.
+            set x `uname -r | sed -e "$lt_sed_extract_leading_digits"`
+            IFS=$save_IFS
+            lt_os_major=${2-0}
+            lt_os_minor=${3-0}
+            lt_os_micro=${4-0}
+            if test "$lt_os_major" -gt 1 \
+               || { test "$lt_os_major" -eq 1 \
+                 && { test "$lt_os_minor" -gt 5 \
+                   || { test "$lt_os_minor" -eq 5 \
+                     && test "$lt_os_micro" -gt 24; }; }; }; then
+              lt_cv_sys_argz_works=yes
+            fi
+          fi
+          ;; #(
+        *) lt_cv_sys_argz_works=yes ;;
+        esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_argz_works" >&5
+$as_echo "$lt_cv_sys_argz_works" >&6; }
+     if test "$lt_cv_sys_argz_works" = yes; then :
+
+$as_echo "#define HAVE_WORKING_ARGZ 1" >>confdefs.h
+
+else
+  ARGZ_H=argz.h
+
+
+  _LT_LIBOBJS="$_LT_LIBOBJS argz.$ac_objext"
+
+fi
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libtool supports -dlopen/-dlpreopen" >&5
+$as_echo_n "checking whether libtool supports -dlopen/-dlpreopen... " >&6; }
+if ${libltdl_cv_preloaded_symbols+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$lt_cv_sys_global_symbol_pipe"; then
+    libltdl_cv_preloaded_symbols=yes
+  else
+    libltdl_cv_preloaded_symbols=no
+  fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_preloaded_symbols" >&5
+$as_echo "$libltdl_cv_preloaded_symbols" >&6; }
+if test x"$libltdl_cv_preloaded_symbols" = xyes; then
+
+$as_echo "#define HAVE_PRELOADED_SYMBOLS 1" >>confdefs.h
+
+fi
+
+
+
+# Set options
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-included_ltdl was given.
+if test "${with_included_ltdl+set}" = set; then :
+  withval=$with_included_ltdl;
+fi
+
+
+if test "x$with_included_ltdl" != xyes; then
+  # We are not being forced to use the included libltdl sources, so
+  # decide whether there is a useful installed version we can use.
+  ac_fn_c_check_header_compile "$LINENO" "ltdl.h" "ac_cv_header_ltdl_h" "$ac_includes_default
+
+"
+if test "x$ac_cv_header_ltdl_h" = xyes; then :
+  ac_fn_c_check_decl "$LINENO" "lt_dlinterface_register" "ac_cv_have_decl_lt_dlinterface_register" "$ac_includes_default
+           #include <ltdl.h>
+"
+if test "x$ac_cv_have_decl_lt_dlinterface_register" = xyes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lt_dladvise_preload in -lltdl" >&5
+$as_echo_n "checking for lt_dladvise_preload in -lltdl... " >&6; }
+if ${ac_cv_lib_ltdl_lt_dladvise_preload+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lltdl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char lt_dladvise_preload ();
+int
+main ()
+{
+return lt_dladvise_preload ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ltdl_lt_dladvise_preload=yes
+else
+  ac_cv_lib_ltdl_lt_dladvise_preload=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ltdl_lt_dladvise_preload" >&5
+$as_echo "$ac_cv_lib_ltdl_lt_dladvise_preload" >&6; }
+if test "x$ac_cv_lib_ltdl_lt_dladvise_preload" = xyes; then :
+  with_included_ltdl=no
+else
+  with_included_ltdl=yes
+fi
+
+else
+  with_included_ltdl=yes
+fi
+
+else
+  with_included_ltdl=yes
+fi
+
+
+fi
+
+
+
+
+# Check whether --with-ltdl_include was given.
+if test "${with_ltdl_include+set}" = set; then :
+  withval=$with_ltdl_include;
+fi
+
+
+if test -n "$with_ltdl_include"; then
+  if test -f "$with_ltdl_include/ltdl.h"; then :
+  else
+    as_fn_error $? "invalid ltdl include directory: \`$with_ltdl_include'" "$LINENO" 5
+  fi
+else
+  with_ltdl_include=no
+fi
+
+
+# Check whether --with-ltdl_lib was given.
+if test "${with_ltdl_lib+set}" = set; then :
+  withval=$with_ltdl_lib;
+fi
+
+
+if test -n "$with_ltdl_lib"; then
+  if test -f "$with_ltdl_lib/libltdl.la"; then :
+  else
+    as_fn_error $? "invalid ltdl library directory: \`$with_ltdl_lib'" "$LINENO" 5
+  fi
+else
+  with_ltdl_lib=no
+fi
+
+case ,$with_included_ltdl,$with_ltdl_include,$with_ltdl_lib, in
+  ,yes,no,no,)
+       case $enable_ltdl_convenience in
+  no) as_fn_error $? "this package needs a convenience libltdl" "$LINENO" 5 ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+esac
+LIBLTDL='${top_build_prefix}'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdlc.la"
+LTDLDEPS=$LIBLTDL
+LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}"
+
+
+
+
+
+# For backwards non-gettext consistent compatibility...
+INCLTDL="$LTDLINCL"
+
+
+       ;;
+  ,no,no,no,)
+       # If the included ltdl is not to be used, then use the
+       # preinstalled libltdl we found.
+
+$as_echo "#define HAVE_LTDL 1" >>confdefs.h
+
+       LIBLTDL=-lltdl
+       LTDLDEPS=
+       LTDLINCL=
+       ;;
+  ,no*,no,*)
+       as_fn_error $? "\`--with-ltdl-include' and \`--with-ltdl-lib' options must be used together" "$LINENO" 5
+       ;;
+  *)   with_included_ltdl=no
+       LIBLTDL="-L$with_ltdl_lib -lltdl"
+       LTDLDEPS=
+       LTDLINCL="-I$with_ltdl_include"
+       ;;
+esac
+INCLTDL="$LTDLINCL"
+
+# Report our decision...
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find libltdl headers" >&5
+$as_echo_n "checking where to find libltdl headers... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LTDLINCL" >&5
+$as_echo "$LTDLINCL" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find libltdl library" >&5
+$as_echo_n "checking where to find libltdl library... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBLTDL" >&5
+$as_echo "$LIBLTDL" >&6; }
+
+
+
+# Check whether --enable-ltdl-install was given.
+if test "${enable_ltdl_install+set}" = set; then :
+  enableval=$enable_ltdl_install;
+fi
+
+
+case ,${enable_ltdl_install},${enable_ltdl_convenience} in
+  *yes*) ;;
+  *) enable_ltdl_convenience=yes ;;
+esac
+
+ if test x"${enable_ltdl_install-no}" != xno; then
+  INSTALL_LTDL_TRUE=
+  INSTALL_LTDL_FALSE='#'
+else
+  INSTALL_LTDL_TRUE='#'
+  INSTALL_LTDL_FALSE=
+fi
+
+  if test x"${enable_ltdl_convenience-no}" != xno; then
+  CONVENIENCE_LTDL_TRUE=
+  CONVENIENCE_LTDL_FALSE='#'
+else
+  CONVENIENCE_LTDL_TRUE='#'
+  CONVENIENCE_LTDL_FALSE=
+fi
+
+
+
+    subdirs="$subdirs libltdl"
+
+
+
+
+# In order that ltdl.c can compile, find out the first AC_CONFIG_HEADERS
+# the user used.  This is so that ltdl.h can pick up the parent projects
+# config.h file, The first file in AC_CONFIG_HEADERS must contain the
+# definitions required by ltdl.c.
+# FIXME: Remove use of undocumented AC_LIST_HEADERS (2.59 compatibility).
+
+
+
+for ac_header in unistd.h dl.h sys/dl.h dld.h mach-o/dyld.h dirent.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in closedir opendir readdir
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+
+  _LT_LIBOBJS="$_LT_LIBOBJS lt__dirent.$ac_objext"
+
+fi
+done
+
+for ac_func in strlcat strlcpy
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+
+
+  _LT_LIBOBJS="$_LT_LIBOBJS lt__strl.$ac_objext"
+
+fi
+done
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_LIBEXT "$libext"
+_ACEOF
+
+
+name=
+eval "lt_libprefix=\"$libname_spec\""
+
+cat >>confdefs.h <<_ACEOF
+#define LT_LIBPREFIX "$lt_libprefix"
+_ACEOF
+
+
+name=ltdl
+eval "LTDLOPEN=\"$libname_spec\""
+
+
+
+
+
+
+
+
+# Only expand once:
+
+
+
+$as_echo "#define LIBTOOL_VERSION 2" >>confdefs.h
+
+
+
+
+am__api_version='1.14'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           rm -rf conftest.one conftest.two conftest.dir
+           echo one > conftest.one
+           echo two > conftest.two
+           mkdir conftest.dir
+           if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+             test -s conftest.one && test -s conftest.two &&
+             test -s conftest.dir/conftest.one &&
+             test -s conftest.dir/conftest.two
+           then
+             ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+             break 3
+           fi
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \    ]*)
+    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$*" = "X"; then
+       # -L didn't work.
+       set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$*" != "X $srcdir/configure conftest.file" \
+       && test "$*" != "X conftest.file $srcdir/configure"; then
+
+       # If neither matched, then we have a broken ls.  This can happen
+       # if, for instance, CONFIG_SHELL is bash and it inherits a
+       # broken ls alias from the environment.  This has actually
+       # happened.  Such a system could not be considered "sane".
+       as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment" "$LINENO" 5
+     fi
+     if test "$2" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if ${ac_cv_path_mkdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+        for ac_exec_ext in '' $ac_executable_extensions; do
+          as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+          case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+            'mkdir (GNU coreutils) '* | \
+            'mkdir (coreutils) '* | \
+            'mkdir (fileutils) '4.1*)
+              ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+              break 3;;
+          esac
+        done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+       @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='collectd'
+ VERSION='5.5.0'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a pax tar archive" >&5
+$as_echo_n "checking how to create a pax tar archive... " >&6; }
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_pax-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        { echo "$as_me:$LINENO: $_am_tar --version" >&5
+   ($_am_tar --version) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } && break
+      done
+      am__tar="$_am_tar --format=posix -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=posix -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x pax -w "$$tardir"'
+      am__tar_='pax -L -x pax -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H pax -L'
+      am__tar_='find "$tardir" -print | cpio -o -H pax -L'
+      am__untar='cpio -i -H pax -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_pax}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5
+   (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      { echo "$as_me:$LINENO: $am__untar <conftest.tar" >&5
+   ($am__untar <conftest.tar) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+      { echo "$as_me:$LINENO: cat conftest.dir/file" >&5
+   (cat conftest.dir/file) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  if ${am_cv_prog_tar_pax+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  am_cv_prog_tar_pax=$_am_tool
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_pax" >&5
+$as_echo "$am_cv_prog_tar_pax" >&6; }
+
+
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=0;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+       @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+  enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+        if ac_fn_c_try_compile "$LINENO"; then :
+  break
+fi
+rm -f core conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_file_offset_bits=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  if test $ac_cv_sys_file_offset_bits = unknown; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  while :; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  ac_cv_sys_large_files=unknown
+  break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+  no | unknown) ;;
+  *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+  fi
+
+
+fi
+
+
+#
+# Checks for programs.
+#
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+ if test "x$GCC" = "xyes"; then
+  COMPILER_IS_GCC_TRUE=
+  COMPILER_IS_GCC_FALSE='#'
+else
+  COMPILER_IS_GCC_TRUE='#'
+  COMPILER_IS_GCC_FALSE=
+fi
+
+
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=no
+fi
+
+
+
+
+
+
+
+for ac_prog in flex lex
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LEX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LEX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
+$as_echo "$LEX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test "x$LEX" != "x:"; then
+  cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument.  */
+    yyless ((input () != 0)); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+  return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ { ac_try="$LEX conftest.l"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$LEX conftest.l") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5
+$as_echo_n "checking lex output file root... " >&6; }
+if ${ac_cv_prog_lex_root+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
+$as_echo "$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+if test -z "${LEXLIB+set}"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5
+$as_echo_n "checking lex library... " >&6; }
+if ${ac_cv_lib_lex+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS=$LIBS
+    ac_cv_lib_lex='none needed'
+    for ac_lib in '' -lfl -ll; do
+      LIBS="$ac_lib $ac_save_LIBS"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_lex=$ac_lib
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+      test "$ac_cv_lib_lex" != 'none needed' && break
+    done
+    LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
+$as_echo "$ac_cv_lib_lex" >&6; }
+  test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
+$as_echo_n "checking whether yytext is a pointer... " >&6; }
+if ${ac_cv_prog_lex_yytext_pointer+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent.  Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+  #define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_prog_lex_yytext_pointer=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
+$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_YACC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+$as_echo "$YACC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=0.9.0
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               PKG_CONFIG=""
+       fi
+fi
+
+# Extract the first word of "protoc-c", so it can be a program name with args.
+set dummy protoc-c; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_have_protoc_c+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$have_protoc_c"; then
+  ac_cv_prog_have_protoc_c="$have_protoc_c" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_have_protoc_c="yes"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_prog_have_protoc_c" && ac_cv_prog_have_protoc_c="no"
+fi
+fi
+have_protoc_c=$ac_cv_prog_have_protoc_c
+if test -n "$have_protoc_c"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_protoc_c" >&5
+$as_echo "$have_protoc_c" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+for ac_header in google/protobuf-c/protobuf-c.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "google/protobuf-c/protobuf-c.h" "ac_cv_header_google_protobuf_c_protobuf_c_h" "$ac_includes_default"
+if test "x$ac_cv_header_google_protobuf_c_protobuf_c_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GOOGLE_PROTOBUF_C_PROTOBUF_C_H 1
+_ACEOF
+ have_protobuf_c_h="yes"
+else
+  have_protobuf_c_h="no"
+fi
+
+done
+
+if test "x$have_protoc_c" = "xyes" && test "x$have_protobuf_c_h" != "xyes"
+then
+       have_protoc_c="no (unable to find <google/protobuf-c/protobuf-c.h>)"
+fi
+ if test "x$have_protoc_c" = "xyes"; then
+  HAVE_PROTOC_C_TRUE=
+  HAVE_PROTOC_C_FALSE='#'
+else
+  HAVE_PROTOC_C_TRUE='#'
+  HAVE_PROTOC_C_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kernel type ($host_os)" >&5
+$as_echo_n "checking for kernel type ($host_os)... " >&6; }
+case $host_os in
+       *linux*)
+
+$as_echo "#define KERNEL_LINUX 1" >>confdefs.h
+
+       ac_system="Linux"
+       ;;
+       *solaris*)
+
+$as_echo "#define KERNEL_SOLARIS 1" >>confdefs.h
+
+       ac_system="Solaris"
+       ;;
+       *darwin*)
+
+$as_echo "#define KERNEL_DARWIN 1" >>confdefs.h
+
+       ac_system="Darwin"
+       ;;
+       *openbsd*)
+
+$as_echo "#define KERNEL_OPENBSD 1" >>confdefs.h
+
+       ac_system="OpenBSD"
+       ;;
+       *aix*)
+
+$as_echo "#define KERNEL_AIX 1" >>confdefs.h
+
+       ac_system="AIX"
+       ;;
+       *freebsd*)
+
+$as_echo "#define KERNEL_FREEBSD 1" >>confdefs.h
+
+       ac_system="FreeBSD"
+       ;;
+       *)
+       ac_system="unknown"
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_system" >&5
+$as_echo "$ac_system" >&6; }
+
+ if test "x$x$ac_system" = "xLinux"; then
+  BUILD_LINUX_TRUE=
+  BUILD_LINUX_FALSE='#'
+else
+  BUILD_LINUX_TRUE='#'
+  BUILD_LINUX_FALSE=
+fi
+
+ if test "x$x$ac_system" = "xSolaris"; then
+  BUILD_SOLARIS_TRUE=
+  BUILD_SOLARIS_FALSE='#'
+else
+  BUILD_SOLARIS_TRUE='#'
+  BUILD_SOLARIS_FALSE=
+fi
+
+ if test "x$x$ac_system" = "xDarwin"; then
+  BUILD_DARWIN_TRUE=
+  BUILD_DARWIN_FALSE='#'
+else
+  BUILD_DARWIN_TRUE='#'
+  BUILD_DARWIN_FALSE=
+fi
+
+ if test "x$x$ac_system" = "xOpenBSD"; then
+  BUILD_OPENBSD_TRUE=
+  BUILD_OPENBSD_FALSE='#'
+else
+  BUILD_OPENBSD_TRUE='#'
+  BUILD_OPENBSD_FALSE=
+fi
+
+ if test "x$x$ac_system" = "xAIX"; then
+  BUILD_AIX_TRUE=
+  BUILD_AIX_FALSE='#'
+else
+  BUILD_AIX_TRUE='#'
+  BUILD_AIX_FALSE=
+fi
+
+ if test "x$x$ac_system" = "xFreeBSD"; then
+  BUILD_FREEBSD_TRUE=
+  BUILD_FREEBSD_FALSE='#'
+else
+  BUILD_FREEBSD_TRUE='#'
+  BUILD_FREEBSD_FALSE=
+fi
+
+
+if test "x$ac_system" = "xLinux"
+then
+
+       if test -z "$KERNEL_DIR"
+       then
+               KERNEL_DIR="/lib/modules/`uname -r`/source"
+       fi
+
+       KERNEL_CFLAGS="-I$KERNEL_DIR/include"
+
+fi
+
+if test "x$ac_system" = "xSolaris"
+then
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+fi
+if test "x$ac_system" = "xAIX"
+then
+
+$as_echo "#define _THREAD_SAFE_ERRNO 1" >>confdefs.h
+
+fi
+
+# Where to install .pc files.
+pkgconfigdir="${libdir}/pkgconfig"
+
+
+# Check for standards compliance mode
+# Check whether --enable-standards was given.
+if test "${enable_standards+set}" = set; then :
+  enableval=$enable_standards; enable_standards="$enableval"
+else
+  enable_standards="no"
+fi
+
+if test "x$enable_standards" = "xyes"
+then
+
+$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_C_SOURCE 200809L" >>confdefs.h
+
+
+$as_echo "#define _XOPEN_SOURCE 700" >>confdefs.h
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+       if test "x$GCC" = "xyes"
+       then
+               CFLAGS="$CFLAGS -std=c99"
+       fi
+fi
+ if test "x$enable_standards" = "xyes"; then
+  BUILD_FEATURE_STANDARDS_TRUE=
+  BUILD_FEATURE_STANDARDS_FALSE='#'
+else
+  BUILD_FEATURE_STANDARDS_TRUE='#'
+  BUILD_FEATURE_STANDARDS_FALSE=
+fi
+
+
+#
+# Checks for header files.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
+$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
+if ${ac_cv_header_sys_wait_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+int
+main ()
+{
+  int s;
+  wait (&s);
+  s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_sys_wait_h=yes
+else
+  ac_cv_header_sys_wait_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
+$as_echo "$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
+
+$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+
+fi
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5
+$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; }
+if eval \${$as_ac_Header+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_ac_Header=yes"
+else
+  eval "$as_ac_Header=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$as_ac_Header
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if ${ac_cv_search_opendir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dir; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_opendir+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_opendir+:} false; then :
+
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5
+$as_echo_n "checking for library containing opendir... " >&6; }
+if ${ac_cv_search_opendir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char opendir ();
+int
+main ()
+{
+return opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' x; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_opendir=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_opendir+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_opendir+:} false; then :
+
+else
+  ac_cv_search_opendir=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5
+$as_echo "$ac_cv_search_opendir" >&6; }
+ac_res=$ac_cv_search_opendir
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+             #include <stdbool.h>
+             #ifndef bool
+              "error: bool is not defined"
+             #endif
+             #ifndef false
+              "error: false is not defined"
+             #endif
+             #if false
+              "error: false is not 0"
+             #endif
+             #ifndef true
+              "error: true is not defined"
+             #endif
+             #if true != 1
+              "error: true is not 1"
+             #endif
+             #ifndef __bool_true_false_are_defined
+              "error: __bool_true_false_are_defined is not defined"
+             #endif
+
+             struct s { _Bool s: 1; _Bool t; } s;
+
+             char a[true == 1 ? 1 : -1];
+             char b[false == 0 ? 1 : -1];
+             char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+             char d[(bool) 0.5 == true ? 1 : -1];
+             /* See body of main program for 'e'.  */
+             char f[(_Bool) 0.0 == false ? 1 : -1];
+             char g[true];
+             char h[sizeof (_Bool)];
+             char i[sizeof s.t];
+             enum { j = false, k = true, l = false * true, m = true * 256 };
+             /* The following fails for
+                HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+             _Bool n[m];
+             char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+             /* Catch a bug in an HP-UX C compiler.  See
+                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+              */
+             _Bool q = true;
+             _Bool *pq = &q;
+
+int
+main ()
+{
+
+             bool e = &s;
+             *pq |= q;
+             *pq |= ! q;
+             /* Refer to every declared value, to avoid compiler optimizations.  */
+             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+                     + !m + !n + !o + !p + !q + !pq);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdbool_h=yes
+else
+  ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+   ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+
+for ac_header in stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h fnmatch.h libgen.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# For ping library
+for ac_header in netinet/in_systm.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/in_systm.h" "ac_cv_header_netinet_in_systm_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_in_systm_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IN_SYSTM_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/in.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_in_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IN_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/ip.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/ip.h" "ac_cv_header_netinet_ip_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_ip_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IP_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/ip_icmp.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/ip_icmp.h" "ac_cv_header_netinet_ip_icmp_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_ip_icmp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IP_ICMP_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/ip_var.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/ip_var.h" "ac_cv_header_netinet_ip_var_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_ip_var_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IP_VAR_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/ip6.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/ip6.h" "ac_cv_header_netinet_ip6_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_ip6_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IP6_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/icmp6.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/icmp6.h" "ac_cv_header_netinet_icmp6_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP6_H
+# include <netinet/ip6.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_icmp6_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_ICMP6_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/tcp.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/tcp.h" "ac_cv_header_netinet_tcp_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_tcp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_TCP_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/udp.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/udp.h" "ac_cv_header_netinet_udp_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_udp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_UDP_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# For cpu modules
+for ac_header in sys/dkstat.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/dkstat.h" "ac_cv_header_sys_dkstat_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_dkstat_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_DKSTAT_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "x$ac_system" = "xDarwin"
+then
+       for ac_header in mach/mach_init.h mach/host_priv.h mach/mach_error.h mach/mach_host.h mach/mach_port.h mach/mach_types.h mach/message.h mach/processor_set.h mach/processor.h mach/processor_info.h mach/task.h mach/thread_act.h mach/vm_region.h mach/vm_map.h mach/vm_prot.h mach/vm_statistics.h mach/kern_return.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+       for ac_header in CoreFoundation/CoreFoundation.h IOKit/IOKitLib.h IOKit/IOTypes.h IOKit/ps/IOPSKeys.h IOKit/IOBSD.h IOKit/storage/IOBlockStorageDriver.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+       # For the battery plugin
+       for ac_header in IOKit/ps/IOPowerSources.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "IOKit/ps/IOPowerSources.h" "ac_cv_header_IOKit_ps_IOPowerSources_h" "
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+
+"
+if test "x$ac_cv_header_IOKit_ps_IOPowerSources_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_IOKIT_PS_IOPOWERSOURCES_H 1
+_ACEOF
+
+fi
+
+done
+
+
+fi
+
+for ac_header in sys/sysctl.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "sys/sysctl.h" "ac_cv_header_sys_sysctl_h" "
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+"
+if test "x$ac_cv_header_sys_sysctl_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_SYSCTL_H 1
+_ACEOF
+
+fi
+
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysctl kern.cp_times" >&5
+$as_echo_n "checking for sysctl kern.cp_times... " >&6; }
+if test -x /sbin/sysctl
+then
+       /sbin/sysctl kern.cp_times 2>/dev/null
+       if test $? -eq 0
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SYSCTL_KERN_CP_TIMES 1" >>confdefs.h
+
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       fi
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+# For hddtemp module
+for ac_header in linux/major.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/major.h" "ac_cv_header_linux_major_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_major_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_MAJOR_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# For md module (Linux only)
+if test "x$ac_system" = "xLinux"
+then
+       for ac_header in linux/raid/md_u.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/raid/md_u.h" "ac_cv_header_linux_raid_md_u_h" "
+#include <sys/ioctl.h>
+#include <linux/major.h>
+#include <linux/types.h>
+
+"
+if test "x$ac_cv_header_linux_raid_md_u_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_RAID_MD_U_H 1
+_ACEOF
+ have_linux_raid_md_u_h="yes"
+else
+  have_linux_raid_md_u_h="no"
+fi
+
+done
+
+else
+       have_linux_raid_md_u_h="no"
+fi
+
+# For the swap module
+have_linux_wireless_h="no"
+if test "x$ac_system" = "xLinux"
+then
+  for ac_header in linux/wireless.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/wireless.h" "ac_cv_header_linux_wireless_h" "
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+"
+if test "x$ac_cv_header_linux_wireless_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_WIRELESS_H 1
+_ACEOF
+ have_linux_wireless_h="yes"
+else
+  have_linux_wireless_h="no"
+fi
+
+done
+
+fi
+
+# For the swap module
+have_sys_swap_h="yes"
+for ac_header in sys/swap.h vm/anon.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
+#undef _FILE_OFFSET_BITS
+#undef _LARGEFILE64_SOURCE
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  have_sys_swap_h="no"
+fi
+
+done
+
+
+if test "x$have_sys_swap_h$ac_system" = "xnoSolaris"
+then
+       hint_64=""
+       if test "x$GCC" = "xyes"
+       then
+               hint_64="CFLAGS='-m64'"
+       else
+               hint_64="CFLAGS='-xarch=v9'"
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Solaris detected and sys/swap.h not usable. Try building a 64-bit binary ($hint_64 ./configure)." >&5
+$as_echo "$as_me: Solaris detected and sys/swap.h not usable. Try building a 64-bit binary ($hint_64 ./configure)." >&6;}
+fi
+
+# For load module
+# For the processes plugin
+# For users module
+for ac_header in sys/loadavg.h linux/config.h utmp.h utmpx.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# For interface plugin
+for ac_header in ifaddrs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default"
+if test "x$ac_cv_header_ifaddrs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_IFADDRS_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in net/if.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" "
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+
+"
+if test "x$ac_cv_header_net_if_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IF_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in linux/if.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/if.h" "ac_cv_header_linux_if_h" "
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+
+"
+if test "x$ac_cv_header_linux_if_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_IF_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in linux/inet_diag.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/inet_diag.h" "ac_cv_header_linux_inet_diag_h" "
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#if HAVE_LINUX_INET_DIAG_H
+# include <linux/inet_diag.h>
+#endif
+
+"
+if test "x$ac_cv_header_linux_inet_diag_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_INET_DIAG_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in linux/netdevice.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/netdevice.h" "ac_cv_header_linux_netdevice_h" "
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#if HAVE_LINUX_IF_H
+# include <linux/if.h>
+#endif
+
+"
+if test "x$ac_cv_header_linux_netdevice_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_NETDEVICE_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# For ethstat module
+for ac_header in linux/sockios.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/sockios.h" "ac_cv_header_linux_sockios_h" "
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+"
+if test "x$ac_cv_header_linux_sockios_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_SOCKIOS_H 1
+_ACEOF
+ have_linux_sockios_h="yes"
+else
+  have_linux_sockios_h="no"
+fi
+
+done
+
+for ac_header in linux/ethtool.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/ethtool.h" "ac_cv_header_linux_ethtool_h" "
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_LINUX_SOCKIOS_H
+# include <linux/sockios.h>
+#endif
+
+"
+if test "x$ac_cv_header_linux_ethtool_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_ETHTOOL_H 1
+_ACEOF
+ have_linux_ethtool_h="yes"
+else
+  have_linux_ethtool_h="no"
+fi
+
+done
+
+
+# For ipvs module
+have_linux_ip_vs_h="no"
+have_net_ip_vs_h="no"
+have_ip_vs_h="no"
+ip_vs_h_needs_kernel_cflags="no"
+if test "x$ac_system" = "xLinux"
+then
+       for ac_header in linux/ip_vs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/ip_vs.h" "ac_cv_header_linux_ip_vs_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_ip_vs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_IP_VS_H 1
+_ACEOF
+ have_linux_ip_vs_h="yes"
+fi
+
+done
+
+       for ac_header in net/ip_vs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "net/ip_vs.h" "ac_cv_header_net_ip_vs_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_ip_vs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IP_VS_H 1
+_ACEOF
+ have_net_ip_vs_h="yes"
+fi
+
+done
+
+       for ac_header in ip_vs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "ip_vs.h" "ac_cv_header_ip_vs_h" "$ac_includes_default"
+if test "x$ac_cv_header_ip_vs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_IP_VS_H 1
+_ACEOF
+ have_ip_vs_h="yes"
+fi
+
+done
+
+
+       if test "x$have_linux_ip_vs_h$have_net_ip_vs_h$have_ip_vs_h" = "xnonono" && test -d "$KERNEL_DIR"
+       then
+               SAVE_CFLAGS="$CFLAGS"
+               CFLAGS="$CFLAGS $KERNEL_CFLAGS"
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: Did not find ip_vs.h. Trying again using headers from $KERNEL_DIR." >&5
+$as_echo "$as_me: Did not find ip_vs.h. Trying again using headers from $KERNEL_DIR." >&6;}
+
+               for ac_header in linux/ip_vs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "linux/ip_vs.h" "ac_cv_header_linux_ip_vs_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_ip_vs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_IP_VS_H 1
+_ACEOF
+ have_linux_ip_vs_h="yes"
+fi
+
+done
+
+               for ac_header in net/ip_vs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "net/ip_vs.h" "ac_cv_header_net_ip_vs_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_ip_vs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IP_VS_H 1
+_ACEOF
+ have_net_ip_vs_h="yes"
+fi
+
+done
+
+               for ac_header in ip_vs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "ip_vs.h" "ac_cv_header_ip_vs_h" "$ac_includes_default"
+if test "x$ac_cv_header_ip_vs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_IP_VS_H 1
+_ACEOF
+ have_ip_vs_h="yes"
+fi
+
+done
+
+
+               if test "x$have_linux_ip_vs_h" = "xyes" || test "x$have_net_ip_vs_h" = "xyes" || test "x$have_ip_vs_h" = "xyes"
+               then
+                       ip_vs_h_needs_kernel_cflags="yes"
+               fi
+
+               CFLAGS="$SAVE_CFLAGS"
+       fi
+fi
+ if test "x$ip_vs_h_needs_kernel_cflags" = "xyes"; then
+  IP_VS_H_NEEDS_KERNEL_CFLAGS_TRUE=
+  IP_VS_H_NEEDS_KERNEL_CFLAGS_FALSE='#'
+else
+  IP_VS_H_NEEDS_KERNEL_CFLAGS_TRUE='#'
+  IP_VS_H_NEEDS_KERNEL_CFLAGS_FALSE=
+fi
+
+
+# For quota module
+for ac_header in sys/ucred.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "sys/ucred.h" "ac_cv_header_sys_ucred_h" "
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+"
+if test "x$ac_cv_header_sys_ucred_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_UCRED_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# For mount interface
+for ac_header in sys/mount.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" "
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+"
+if test "x$ac_cv_header_sys_mount_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_MOUNT_H 1
+_ACEOF
+
+fi
+
+done
+
+
+# For the email plugin
+for ac_header in linux/un.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "linux/un.h" "ac_cv_header_linux_un_h" "
+#if HAVE_SYS_SOCKET_H
+#      include <sys/socket.h>
+#endif
+
+"
+if test "x$ac_cv_header_linux_un_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_UN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in pwd.h grp.h sys/un.h ctype.h limits.h xfs/xqm.h fs_info.h fshelp.h paths.h mntent.h mnttab.h sys/fstyp.h sys/fs_types.h sys/mntent.h sys/mnttab.h sys/statfs.h sys/statvfs.h sys/vfs.h sys/vfstab.h sys/vmmeter.h kvm.h wordexp.h locale.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# For the dns plugin
+for ac_header in arpa/nameser.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "arpa/nameser.h" "ac_cv_header_arpa_nameser_h" "$ac_includes_default"
+if test "x$ac_cv_header_arpa_nameser_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ARPA_NAMESER_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in arpa/nameser_compat.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "arpa/nameser_compat.h" "ac_cv_header_arpa_nameser_compat_h" "
+#if HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+
+"
+if test "x$ac_cv_header_arpa_nameser_compat_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ARPA_NAMESER_COMPAT_H 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in net/if_arp.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "net/if_arp.h" "ac_cv_header_net_if_arp_h" "#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+"
+if test "x$ac_cv_header_net_if_arp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IF_ARP_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in net/ppp_defs.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "net/ppp_defs.h" "ac_cv_header_net_ppp_defs_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_ppp_defs_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_PPP_DEFS_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in net/if_ppp.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "net/if_ppp.h" "ac_cv_header_net_if_ppp_h" "#if HAVE_NET_PPP_DEFS_H
+# include <net/ppp_defs.h>
+#endif
+
+"
+if test "x$ac_cv_header_net_if_ppp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IF_PPP_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netinet/if_ether.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+"
+if test "x$ac_cv_header_netinet_if_ether_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IF_ETHER_H 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in netinet/ip_compat.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "netinet/ip_compat.h" "ac_cv_header_netinet_ip_compat_h" "$ac_includes_default"
+if test "x$ac_cv_header_netinet_ip_compat_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETINET_IP_COMPAT_H 1
+_ACEOF
+
+fi
+
+done
+
+
+have_net_pfvar_h="no"
+for ac_header in net/pfvar.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+"
+if test "x$ac_cv_header_net_pfvar_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_PFVAR_H 1
+_ACEOF
+ have_net_pfvar_h="yes"
+else
+  have_net_pfvar_h="no"
+fi
+
+done
+
+
+# For the multimeter plugin
+have_termios_h="no"
+for ac_header in termios.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default"
+if test "x$ac_cv_header_termios_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_TERMIOS_H 1
+_ACEOF
+ have_termios_h="yes"
+fi
+
+done
+
+
+# For the turbostat plugin
+have_asm_msrindex_h="no"
+for ac_header in asm/msr-index.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "asm/msr-index.h" "ac_cv_header_asm_msr_index_h" "$ac_includes_default"
+if test "x$ac_cv_header_asm_msr_index_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ASM_MSR_INDEX_H 1
+_ACEOF
+ have_asm_msrindex_h="yes"
+fi
+
+done
+
+
+if test "x$have_asm_msrindex_h" = "xyes"
+then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether asm/msr-index.h has MSR_CORE_C3_RESIDENCY" >&5
+$as_echo_n "checking whether asm/msr-index.h has MSR_CORE_C3_RESIDENCY... " >&6; }
+if ${c_cv_have_usable_asm_msrindex_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include<asm/msr-index.h>
+
+int
+main ()
+{
+
+int y = MSR_CORE_C3_RESIDENCY;
+return(y);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_usable_asm_msrindex_h="yes"
+else
+  c_cv_have_usable_asm_msrindex_h="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_usable_asm_msrindex_h" >&5
+$as_echo "$c_cv_have_usable_asm_msrindex_h" >&6; }
+fi
+
+have_cpuid_h="no"
+for ac_header in cpuid.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "cpuid.h" "ac_cv_header_cpuid_h" "$ac_includes_default"
+if test "x$ac_cv_header_cpuid_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CPUID_H 1
+_ACEOF
+ have_cpuid_h="yes"
+fi
+
+done
+
+
+for ac_header in sys/capability.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/capability.h" "ac_cv_header_sys_capability_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_capability_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_CAPABILITY_H 1
+_ACEOF
+
+fi
+
+done
+
+#
+# Checks for typedefs, structures, and compiler characteristics.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
+if ${ac_cv_c_const+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this sort of thing.  */
+  typedef int charset[2];
+  const charset cs = { 0, 0 };
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this sort of thing.  */
+    char tx;
+    char *t = &tx;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; } bx;
+    struct s *b = &bx; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_const=yes
+else
+  ac_cv_c_const=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+$as_echo "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+$as_echo "#define const /**/" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default"
+if test "x$ac_cv_type_off_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define off_t long int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default"
+if test "x$ac_cv_type_ssize_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
+$as_echo_n "checking for uid_t in sys/types.h... " >&6; }
+if ${ac_cv_type_uid_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "uid_t" >/dev/null 2>&1; then :
+  ac_cv_type_uid_t=yes
+else
+  ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5
+$as_echo "$ac_cv_type_uid_t" >&6; }
+if test $ac_cv_type_uid_t = no; then
+
+$as_echo "#define uid_t int" >>confdefs.h
+
+
+$as_echo "#define gid_t int" >>confdefs.h
+
+fi
+
+ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
+case $ac_cv_c_uint32_t in #(
+  no|yes) ;; #(
+  *)
+
+$as_echo "#define _UINT32_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint32_t $ac_cv_c_uint32_t
+_ACEOF
+;;
+  esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
+$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
+if ${ac_cv_header_time+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_time=yes
+else
+  ac_cv_header_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
+$as_echo "$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+fi
+
+
+#
+# Checks for library functions.
+#
+if test $ac_cv_c_compiler_gnu = yes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5
+$as_echo_n "checking whether $CC needs -traditional... " >&6; }
+if ${ac_cv_prog_gcc_traditional+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+  ac_cv_prog_gcc_traditional=yes
+else
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then :
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5
+$as_echo "$ac_cv_prog_gcc_traditional" >&6; }
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+for ac_func in gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+ac_fn_c_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default"
+if test "x$ac_cv_have_decl_strerror_r" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRERROR_R $ac_have_decl
+_ACEOF
+
+for ac_func in strerror_r
+do :
+  ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r"
+if test "x$ac_cv_func_strerror_r" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRERROR_R 1
+_ACEOF
+
+fi
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5
+$as_echo_n "checking whether strerror_r returns char *... " >&6; }
+if ${ac_cv_func_strerror_r_char_p+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_cv_func_strerror_r_char_p=no
+    if test $ac_cv_have_decl_strerror_r = yes; then
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+         char buf[100];
+         char x = *strerror_r (0, buf, sizeof buf);
+         char *p = strerror_r (0, buf, sizeof buf);
+         return !p || x;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_func_strerror_r_char_p=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    else
+      # strerror_r is not declared.  Choose between
+      # systems that have relatively inaccessible declarations for the
+      # function.  BeOS and DEC UNIX 4.0 fall in this category, but the
+      # former has a strerror_r that returns char*, while the latter
+      # has a strerror_r that returns `int'.
+      # This test should segfault on the DEC system.
+      if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+       extern char *strerror_r ();
+int
+main ()
+{
+char buf[100];
+         char x = *strerror_r (0, buf, sizeof buf);
+         return ! isalpha (x);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_strerror_r_char_p=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+    fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5
+$as_echo "$ac_cv_func_strerror_r_char_p" >&6; }
+if test $ac_cv_func_strerror_r_char_p = yes; then
+
+$as_echo "#define STRERROR_R_CHAR_P 1" >>confdefs.h
+
+fi
+
+
+SAVE_CFLAGS="$CFLAGS"
+# Emulate behavior of src/Makefile.am
+if test "x$GCC" = "xyes"
+then
+       CFLAGS="$CFLAGS -Wall -Werror"
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strtok_r" >&5
+$as_echo_n "checking for strtok_r... " >&6; }
+if ${c_cv_have_strtok_r_default+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main ()
+{
+
+      char buffer[] = "foo,bar,baz";
+      char *token;
+      char *dummy;
+      char *saveptr;
+
+      dummy = buffer;
+      saveptr = NULL;
+      while ((token = strtok_r (dummy, ",", &saveptr)) != NULL)
+      {
+        dummy = NULL;
+        printf ("token = %s;\n", token);
+      }
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  c_cv_have_strtok_r_default="yes"
+else
+  c_cv_have_strtok_r_default="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_strtok_r_default" >&5
+$as_echo "$c_cv_have_strtok_r_default" >&6; }
+
+if test "x$c_cv_have_strtok_r_default" = "xno"
+then
+  CFLAGS="$CFLAGS -D_REENTRANT=1"
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if strtok_r needs _REENTRANT" >&5
+$as_echo_n "checking if strtok_r needs _REENTRANT... " >&6; }
+if ${c_cv_have_strtok_r_reentrant+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main ()
+{
+
+        char buffer[] = "foo,bar,baz";
+        char *token;
+        char *dummy;
+        char *saveptr;
+
+        dummy = buffer;
+        saveptr = NULL;
+        while ((token = strtok_r (dummy, ",", &saveptr)) != NULL)
+        {
+          dummy = NULL;
+          printf ("token = %s;\n", token);
+        }
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  c_cv_have_strtok_r_reentrant="yes"
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "strtok_r isn't available. Please file a bugreport!
+See \`config.log' for more details" "$LINENO" 5; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_strtok_r_reentrant" >&5
+$as_echo "$c_cv_have_strtok_r_reentrant" >&6; }
+fi
+
+CFLAGS="$SAVE_CFLAGS"
+if test "x$c_cv_have_strtok_r_reentrant" = "xyes"
+then
+       CFLAGS="$CFLAGS -D_REENTRANT=1"
+fi
+
+for ac_func in getpwnam_r getgrnam_r setgroups regcomp regerror regexec regfree
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+socket_needs_socket="no"
+for ac_func in socket
+do :
+  ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket"
+if test "x$ac_cv_func_socket" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SOCKET 1
+_ACEOF
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
+$as_echo_n "checking for socket in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_socket+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_socket_socket=yes
+else
+  ac_cv_lib_socket_socket=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
+$as_echo "$ac_cv_lib_socket_socket" >&6; }
+if test "x$ac_cv_lib_socket_socket" = xyes; then :
+  socket_needs_socket="yes"
+else
+  as_fn_error $? "cannot find socket" "$LINENO" 5
+fi
+
+fi
+done
+
+ if test "x$socket_needs_socket" = "xyes"; then
+  BUILD_WITH_LIBSOCKET_TRUE=
+  BUILD_WITH_LIBSOCKET_FALSE='#'
+else
+  BUILD_WITH_LIBSOCKET_TRUE='#'
+  BUILD_WITH_LIBSOCKET_FALSE=
+fi
+
+
+clock_gettime_needs_rt="no"
+clock_gettime_needs_posix4="no"
+have_clock_gettime="no"
+for ac_func in clock_gettime
+do :
+  ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime"
+if test "x$ac_cv_func_clock_gettime" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CLOCK_GETTIME 1
+_ACEOF
+ have_clock_gettime="yes"
+fi
+done
+
+if test "x$have_clock_gettime" = "xno"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
+if ${ac_cv_lib_rt_clock_gettime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rt_clock_gettime=yes
+else
+  ac_cv_lib_rt_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+  clock_gettime_needs_rt="yes"
+                                        have_clock_gettime="yes"
+fi
+
+fi
+if test "x$have_clock_gettime" = "xno"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lposix4" >&5
+$as_echo_n "checking for clock_gettime in -lposix4... " >&6; }
+if ${ac_cv_lib_posix4_clock_gettime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lposix4  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_posix4_clock_gettime=yes
+else
+  ac_cv_lib_posix4_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix4_clock_gettime" >&5
+$as_echo "$ac_cv_lib_posix4_clock_gettime" >&6; }
+if test "x$ac_cv_lib_posix4_clock_gettime" = xyes; then :
+  clock_gettime_needs_posix4="yes"
+                                            have_clock_gettime="yes"
+fi
+
+fi
+if test "x$have_clock_gettime" = "xyes"
+then
+
+$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find clock_gettime" >&5
+$as_echo "$as_me: WARNING: cannot find clock_gettime" >&2;}
+fi
+
+nanosleep_needs_rt="no"
+nanosleep_needs_posix4="no"
+for ac_func in nanosleep
+do :
+  ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep"
+if test "x$ac_cv_func_nanosleep" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NANOSLEEP 1
+_ACEOF
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanosleep in -lrt" >&5
+$as_echo_n "checking for nanosleep in -lrt... " >&6; }
+if ${ac_cv_lib_rt_nanosleep+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nanosleep ();
+int
+main ()
+{
+return nanosleep ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rt_nanosleep=yes
+else
+  ac_cv_lib_rt_nanosleep=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_nanosleep" >&5
+$as_echo "$ac_cv_lib_rt_nanosleep" >&6; }
+if test "x$ac_cv_lib_rt_nanosleep" = xyes; then :
+  nanosleep_needs_rt="yes"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanosleep in -lposix4" >&5
+$as_echo_n "checking for nanosleep in -lposix4... " >&6; }
+if ${ac_cv_lib_posix4_nanosleep+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lposix4  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nanosleep ();
+int
+main ()
+{
+return nanosleep ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_posix4_nanosleep=yes
+else
+  ac_cv_lib_posix4_nanosleep=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix4_nanosleep" >&5
+$as_echo "$ac_cv_lib_posix4_nanosleep" >&6; }
+if test "x$ac_cv_lib_posix4_nanosleep" = xyes; then :
+  nanosleep_needs_posix4="yes"
+else
+  as_fn_error $? "cannot find nanosleep" "$LINENO" 5
+fi
+
+fi
+
+fi
+done
+
+
+ if test "x$clock_gettime_needs_rt" = "xyes" || test "x$nanosleep_needs_rt" = "xyes"; then
+  BUILD_WITH_LIBRT_TRUE=
+  BUILD_WITH_LIBRT_FALSE='#'
+else
+  BUILD_WITH_LIBRT_TRUE='#'
+  BUILD_WITH_LIBRT_FALSE=
+fi
+
+ if test "x$clock_gettime_needs_posix4" = "xyes" || test "x$nanosleep_needs_posix4" = "xyes"; then
+  BUILD_WITH_LIBPOSIX4_TRUE=
+  BUILD_WITH_LIBPOSIX4_FALSE='#'
+else
+  BUILD_WITH_LIBPOSIX4_TRUE='#'
+  BUILD_WITH_LIBPOSIX4_FALSE=
+fi
+
+
+for ac_func in sysctl
+do :
+  ac_fn_c_check_func "$LINENO" "sysctl" "ac_cv_func_sysctl"
+if test "x$ac_cv_func_sysctl" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYSCTL 1
+_ACEOF
+ have_sysctl="yes"
+else
+  have_sysctl="no"
+fi
+done
+
+for ac_func in sysctlbyname
+do :
+  ac_fn_c_check_func "$LINENO" "sysctlbyname" "ac_cv_func_sysctlbyname"
+if test "x$ac_cv_func_sysctlbyname" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYSCTLBYNAME 1
+_ACEOF
+ have_sysctlbyname="yes"
+else
+  have_sysctlbyname="no"
+fi
+done
+
+for ac_func in host_statistics
+do :
+  ac_fn_c_check_func "$LINENO" "host_statistics" "ac_cv_func_host_statistics"
+if test "x$ac_cv_func_host_statistics" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_HOST_STATISTICS 1
+_ACEOF
+ have_host_statistics="yes"
+else
+  have_host_statistics="no"
+fi
+done
+
+for ac_func in processor_info
+do :
+  ac_fn_c_check_func "$LINENO" "processor_info" "ac_cv_func_processor_info"
+if test "x$ac_cv_func_processor_info" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PROCESSOR_INFO 1
+_ACEOF
+ have_processor_info="yes"
+else
+  have_processor_info="no"
+fi
+done
+
+for ac_func in thread_info
+do :
+  ac_fn_c_check_func "$LINENO" "thread_info" "ac_cv_func_thread_info"
+if test "x$ac_cv_func_thread_info" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_THREAD_INFO 1
+_ACEOF
+ have_thread_info="yes"
+else
+  have_thread_info="no"
+fi
+done
+
+for ac_func in statfs
+do :
+  ac_fn_c_check_func "$LINENO" "statfs" "ac_cv_func_statfs"
+if test "x$ac_cv_func_statfs" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STATFS 1
+_ACEOF
+ have_statfs="yes"
+else
+  have_statfs="no"
+fi
+done
+
+for ac_func in statvfs
+do :
+  ac_fn_c_check_func "$LINENO" "statvfs" "ac_cv_func_statvfs"
+if test "x$ac_cv_func_statvfs" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STATVFS 1
+_ACEOF
+ have_statvfs="yes"
+else
+  have_statvfs="no"
+fi
+done
+
+for ac_func in getifaddrs
+do :
+  ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
+if test "x$ac_cv_func_getifaddrs" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETIFADDRS 1
+_ACEOF
+ have_getifaddrs="yes"
+else
+  have_getifaddrs="no"
+fi
+done
+
+for ac_func in getloadavg
+do :
+  ac_fn_c_check_func "$LINENO" "getloadavg" "ac_cv_func_getloadavg"
+if test "x$ac_cv_func_getloadavg" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETLOADAVG 1
+_ACEOF
+ have_getloadavg="yes"
+else
+  have_getloadavg="no"
+fi
+done
+
+for ac_func in syslog
+do :
+  ac_fn_c_check_func "$LINENO" "syslog" "ac_cv_func_syslog"
+if test "x$ac_cv_func_syslog" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYSLOG 1
+_ACEOF
+ have_syslog="yes"
+else
+  have_syslog="no"
+fi
+done
+
+for ac_func in getutent
+do :
+  ac_fn_c_check_func "$LINENO" "getutent" "ac_cv_func_getutent"
+if test "x$ac_cv_func_getutent" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETUTENT 1
+_ACEOF
+ have_getutent="yes"
+else
+  have_getutent="no"
+fi
+done
+
+for ac_func in getutxent
+do :
+  ac_fn_c_check_func "$LINENO" "getutxent" "ac_cv_func_getutxent"
+if test "x$ac_cv_func_getutxent" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETUTXENT 1
+_ACEOF
+ have_getutxent="yes"
+else
+  have_getutxent="no"
+fi
+done
+
+
+# Check for strptime {{{
+if test "x$GCC" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wall -Wextra -Werror"
+fi
+
+for ac_func in strptime
+do :
+  ac_fn_c_check_func "$LINENO" "strptime" "ac_cv_func_strptime"
+if test "x$ac_cv_func_strptime" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STRPTIME 1
+_ACEOF
+ have_strptime="yes"
+else
+  have_strptime="no"
+fi
+done
+
+if test "x$have_strptime" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strptime is exported by default" >&5
+$as_echo_n "checking whether strptime is exported by default... " >&6; }
+if ${c_cv_have_strptime_default+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <time.h>
+
+int
+main ()
+{
+
+ struct tm stm;
+ (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_strptime_default="yes"
+else
+  c_cv_have_strptime_default="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_strptime_default" >&5
+$as_echo "$c_cv_have_strptime_default" >&6; }
+fi
+if test "x$have_strptime" = "xyes" && test "x$c_cv_have_strptime_default" = "xno"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strptime needs standards mode" >&5
+$as_echo_n "checking whether strptime needs standards mode... " >&6; }
+if ${c_cv_have_strptime_standards+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifndef _ISOC99_SOURCE
+# define _ISOC99_SOURCE 1
+#endif
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200112L
+#endif
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 500
+#endif
+#include <time.h>
+
+int
+main ()
+{
+
+ struct tm stm;
+ (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_strptime_standards="yes"
+else
+  c_cv_have_strptime_standards="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_strptime_standards" >&5
+$as_echo "$c_cv_have_strptime_standards" >&6; }
+
+       if test "x$c_cv_have_strptime_standards" = "xyes"
+       then
+
+$as_echo "#define STRPTIME_NEEDS_STANDARDS 1" >>confdefs.h
+
+       else
+               have_strptime="no"
+       fi
+fi
+
+if test "x$GCC" = "xyes"
+then
+       CFLAGS="$SAVE_CFLAGS"
+fi
+# }}} Check for strptime
+
+for ac_func in swapctl
+do :
+  ac_fn_c_check_func "$LINENO" "swapctl" "ac_cv_func_swapctl"
+if test "x$ac_cv_func_swapctl" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SWAPCTL 1
+_ACEOF
+ have_swapctl="yes"
+else
+  have_swapctl="no"
+fi
+done
+
+if test "x$have_swapctl" = "xyes"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether swapctl takes two arguments" >&5
+$as_echo_n "checking whether swapctl takes two arguments... " >&6; }
+if ${c_cv_have_swapctl_two_args+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  undef _FILE_OFFSET_BITS
+#  undef _LARGEFILE64_SOURCE
+#endif
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/swap.h>
+#include <unistd.h>
+
+int
+main ()
+{
+
+int num = swapctl(0, NULL);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_swapctl_two_args="yes"
+else
+  c_cv_have_swapctl_two_args="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_swapctl_two_args" >&5
+$as_echo "$c_cv_have_swapctl_two_args" >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether swapctl takes three arguments" >&5
+$as_echo_n "checking whether swapctl takes three arguments... " >&6; }
+if ${c_cv_have_swapctl_three_args+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  undef _FILE_OFFSET_BITS
+#  undef _LARGEFILE64_SOURCE
+#endif
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/swap.h>
+#include <unistd.h>
+
+int
+main ()
+{
+
+int num = swapctl(0, NULL, 0);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_swapctl_three_args="yes"
+else
+  c_cv_have_swapctl_three_args="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_swapctl_three_args" >&5
+$as_echo "$c_cv_have_swapctl_three_args" >&6; }
+fi
+# Check for different versions of `swapctl' here..
+if test "x$have_swapctl" = "xyes"; then
+        if test "x$c_cv_have_swapctl_two_args" = "xyes"; then
+
+$as_echo "#define HAVE_SWAPCTL_TWO_ARGS 1" >>confdefs.h
+
+        fi
+        if test "x$c_cv_have_swapctl_three_args" = "xyes"; then
+
+$as_echo "#define HAVE_SWAPCTL_THREE_ARGS 1" >>confdefs.h
+
+        fi
+fi
+
+# Check for NAN
+
+# Check whether --with-nan-emulation was given.
+if test "${with_nan_emulation+set}" = set; then :
+  withval=$with_nan_emulation;
+ if test "x$withval" = "xno"; then
+        nan_type="none"
+ else if test "x$withval" = "xyes"; then
+        nan_type="zero"
+ else
+        nan_type="$withval"
+ fi; fi
+
+else
+  nan_type="none"
+fi
+
+if test "x$nan_type" = "xnone"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NAN is defined by default" >&5
+$as_echo_n "checking whether NAN is defined by default... " >&6; }
+if ${c_cv_have_nan_default+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <math.h>
+static double foo = NAN;
+
+int
+main ()
+{
+
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_nan_default="yes"
+else
+  c_cv_have_nan_default="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_nan_default" >&5
+$as_echo "$c_cv_have_nan_default" >&6; }
+  if test "x$c_cv_have_nan_default" = "xyes"
+  then
+    nan_type="default"
+  fi
+fi
+if test "x$nan_type" = "xnone"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NAN is defined by __USE_ISOC99" >&5
+$as_echo_n "checking whether NAN is defined by __USE_ISOC99... " >&6; }
+if ${c_cv_have_nan_isoc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#define __USE_ISOC99 1
+#include <math.h>
+static double foo = NAN;
+
+int
+main ()
+{
+
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_nan_isoc="yes"
+else
+  c_cv_have_nan_isoc="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_nan_isoc" >&5
+$as_echo "$c_cv_have_nan_isoc" >&6; }
+  if test "x$c_cv_have_nan_isoc" = "xyes"
+  then
+    nan_type="isoc99"
+  fi
+fi
+if test "x$nan_type" = "xnone"; then
+  SAVE_LDFLAGS=$LDFLAGS
+  LDFLAGS="$LDFLAGS -lm"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NAN can be defined by 0/0" >&5
+$as_echo_n "checking whether NAN can be defined by 0/0... " >&6; }
+if ${c_cv_have_nan_zero+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <math.h>
+#ifdef NAN
+# undef NAN
+#endif
+#define NAN (0.0 / 0.0)
+#ifndef isnan
+# define isnan(f) ((f) != (f))
+#endif
+static double foo = NAN;
+
+int
+main ()
+{
+
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  c_cv_have_nan_zero="yes"
+else
+  c_cv_have_nan_zero="no"
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_nan_zero" >&5
+$as_echo "$c_cv_have_nan_zero" >&6; }
+  LDFLAGS=$SAVE_LDFLAGS
+  if test "x$c_cv_have_nan_zero" = "xyes"
+  then
+    nan_type="zero"
+  fi
+fi
+
+if test "x$nan_type" = "xdefault"; then
+
+$as_echo "#define NAN_STATIC_DEFAULT 1" >>confdefs.h
+
+else if test "x$nan_type" = "xisoc99"; then
+
+$as_echo "#define NAN_STATIC_ISOC 1" >>confdefs.h
+
+else if test "x$nan_type" = "xzero"; then
+
+$as_echo "#define NAN_ZERO_ZERO 1" >>confdefs.h
+
+else
+  as_fn_error $? "Didn't find out how to statically initialize variables to NAN. Sorry." "$LINENO" 5
+fi; fi; fi
+
+
+# Check whether --with-fp-layout was given.
+if test "${with_fp_layout+set}" = set; then :
+  withval=$with_fp_layout;
+ if test "x$withval" = "xnothing"; then
+       fp_layout_type="nothing"
+ else if test "x$withval" = "xendianflip"; then
+       fp_layout_type="endianflip"
+ else if test "x$withval" = "xintswap"; then
+       fp_layout_type="intswap"
+ else
+       as_fn_error $? "Invalid argument for --with-fp-layout. Valid arguments are: nothing, endianflip, intswap" "$LINENO" 5;
+fi; fi; fi
+
+else
+  fp_layout_type="unknown"
+fi
+
+
+if test "x$fp_layout_type" = "xunknown"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if doubles are stored in x86 representation" >&5
+$as_echo_n "checking if doubles are stored in x86 representation... " >&6; }
+if ${c_cv_fp_layout_need_nothing+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+
+int
+main ()
+{
+
+       uint64_t i0;
+       uint64_t i1;
+       uint8_t c[8];
+       double d;
+
+       d = 8.642135e130;
+       memcpy ((void *) &i0, (void *) &d, 8);
+
+       i1 = i0;
+       memcpy ((void *) c, (void *) &i1, 8);
+
+       if ((c[0] == 0x2f) && (c[1] == 0x25)
+                       && (c[2] == 0xc0) && (c[3] == 0xc7)
+                       && (c[4] == 0x43) && (c[5] == 0x2b)
+                       && (c[6] == 0x1f) && (c[7] == 0x5b))
+               return (0);
+       else
+               return (1);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  c_cv_fp_layout_need_nothing="yes"
+else
+  c_cv_fp_layout_need_nothing="no"
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_fp_layout_need_nothing" >&5
+$as_echo "$c_cv_fp_layout_need_nothing" >&6; }
+  if test "x$c_cv_fp_layout_need_nothing" = "xyes"; then
+    fp_layout_type="nothing"
+  fi
+fi
+if test "x$fp_layout_type" = "xunknown"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if endianflip converts to x86 representation" >&5
+$as_echo_n "checking if endianflip converts to x86 representation... " >&6; }
+if ${c_cv_fp_layout_need_endianflip+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+#define endianflip(A) ((((uint64_t)(A) & 0xff00000000000000LL) >> 56) | \
+                       (((uint64_t)(A) & 0x00ff000000000000LL) >> 40) | \
+                       (((uint64_t)(A) & 0x0000ff0000000000LL) >> 24) | \
+                       (((uint64_t)(A) & 0x000000ff00000000LL) >> 8)  | \
+                       (((uint64_t)(A) & 0x00000000ff000000LL) << 8)  | \
+                       (((uint64_t)(A) & 0x0000000000ff0000LL) << 24) | \
+                       (((uint64_t)(A) & 0x000000000000ff00LL) << 40) | \
+                       (((uint64_t)(A) & 0x00000000000000ffLL) << 56))
+
+int
+main ()
+{
+
+       uint64_t i0;
+       uint64_t i1;
+       uint8_t c[8];
+       double d;
+
+       d = 8.642135e130;
+       memcpy ((void *) &i0, (void *) &d, 8);
+
+       i1 = endianflip (i0);
+       memcpy ((void *) c, (void *) &i1, 8);
+
+       if ((c[0] == 0x2f) && (c[1] == 0x25)
+                       && (c[2] == 0xc0) && (c[3] == 0xc7)
+                       && (c[4] == 0x43) && (c[5] == 0x2b)
+                       && (c[6] == 0x1f) && (c[7] == 0x5b))
+               return (0);
+       else
+               return (1);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  c_cv_fp_layout_need_endianflip="yes"
+else
+  c_cv_fp_layout_need_endianflip="no"
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_fp_layout_need_endianflip" >&5
+$as_echo "$c_cv_fp_layout_need_endianflip" >&6; }
+  if test "x$c_cv_fp_layout_need_endianflip" = "xyes"; then
+    fp_layout_type="endianflip"
+  fi
+fi
+if test "x$fp_layout_type" = "xunknown"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if intswap converts to x86 representation" >&5
+$as_echo_n "checking if intswap converts to x86 representation... " >&6; }
+if ${c_cv_fp_layout_need_intswap+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+#define intswap(A)    ((((uint64_t)(A) & 0xffffffff00000000LL) >> 32) | \
+                       (((uint64_t)(A) & 0x00000000ffffffffLL) << 32))
+
+int
+main ()
+{
+
+       uint64_t i0;
+       uint64_t i1;
+       uint8_t c[8];
+       double d;
+
+       d = 8.642135e130;
+       memcpy ((void *) &i0, (void *) &d, 8);
+
+       i1 = intswap (i0);
+       memcpy ((void *) c, (void *) &i1, 8);
+
+       if ((c[0] == 0x2f) && (c[1] == 0x25)
+                       && (c[2] == 0xc0) && (c[3] == 0xc7)
+                       && (c[4] == 0x43) && (c[5] == 0x2b)
+                       && (c[6] == 0x1f) && (c[7] == 0x5b))
+               return (0);
+       else
+               return (1);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  c_cv_fp_layout_need_intswap="yes"
+else
+  c_cv_fp_layout_need_intswap="no"
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_fp_layout_need_intswap" >&5
+$as_echo "$c_cv_fp_layout_need_intswap" >&6; }
+  if test "x$c_cv_fp_layout_need_intswap" = "xyes"; then
+    fp_layout_type="intswap"
+  fi
+fi
+
+if test "x$fp_layout_type" = "xnothing"; then
+
+$as_echo "#define FP_LAYOUT_NEED_NOTHING 1" >>confdefs.h
+
+else if test "x$fp_layout_type" = "xendianflip"; then
+
+$as_echo "#define FP_LAYOUT_NEED_ENDIANFLIP 1" >>confdefs.h
+
+else if test "x$fp_layout_type" = "xintswap"; then
+
+$as_echo "#define FP_LAYOUT_NEED_INTSWAP 1" >>confdefs.h
+
+else
+  as_fn_error $? "Didn't find out how doubles are stored in memory. Sorry." "$LINENO" 5
+fi; fi; fi
+
+# --with-useragent {{{
+
+# Check whether --with-useragent was given.
+if test "${with_useragent+set}" = set; then :
+  withval=$with_useragent;
+    if test "x$withval" != "xno" && test "x$withval" != "xyes"
+    then
+
+cat >>confdefs.h <<_ACEOF
+#define COLLECTD_USERAGENT "$withval"
+_ACEOF
+
+    fi
+
+fi
+
+
+# }}}
+
+have_getfsstat="no"
+for ac_func in getfsstat
+do :
+  ac_fn_c_check_func "$LINENO" "getfsstat" "ac_cv_func_getfsstat"
+if test "x$ac_cv_func_getfsstat" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETFSSTAT 1
+_ACEOF
+ have_getfsstat="yes"
+fi
+done
+
+have_getvfsstat="no"
+for ac_func in getvfsstat
+do :
+  ac_fn_c_check_func "$LINENO" "getvfsstat" "ac_cv_func_getvfsstat"
+if test "x$ac_cv_func_getvfsstat" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETVFSSTAT 1
+_ACEOF
+ have_getvfsstat="yes"
+fi
+done
+
+have_listmntent="no"
+for ac_func in listmntent
+do :
+  ac_fn_c_check_func "$LINENO" "listmntent" "ac_cv_func_listmntent"
+if test "x$ac_cv_func_listmntent" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LISTMNTENT 1
+_ACEOF
+ have_listmntent="yes"
+fi
+done
+
+
+have_getmntent="no"
+for ac_func in getmntent
+do :
+  ac_fn_c_check_func "$LINENO" "getmntent" "ac_cv_func_getmntent"
+if test "x$ac_cv_func_getmntent" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETMNTENT 1
+_ACEOF
+ have_getmntent="c"
+fi
+done
+
+if test "x$have_getmntent" = "xno"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getmntent in -lsun" >&5
+$as_echo_n "checking for getmntent in -lsun... " >&6; }
+if ${ac_cv_lib_sun_getmntent+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsun  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getmntent ();
+int
+main ()
+{
+return getmntent ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_sun_getmntent=yes
+else
+  ac_cv_lib_sun_getmntent=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sun_getmntent" >&5
+$as_echo "$ac_cv_lib_sun_getmntent" >&6; }
+if test "x$ac_cv_lib_sun_getmntent" = xyes; then :
+  have_getmntent="sun"
+fi
+
+fi
+if test "x$have_getmntent" = "xno"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getmntent in -lseq" >&5
+$as_echo_n "checking for getmntent in -lseq... " >&6; }
+if ${ac_cv_lib_seq_getmntent+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lseq  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getmntent ();
+int
+main ()
+{
+return getmntent ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_seq_getmntent=yes
+else
+  ac_cv_lib_seq_getmntent=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_seq_getmntent" >&5
+$as_echo "$ac_cv_lib_seq_getmntent" >&6; }
+if test "x$ac_cv_lib_seq_getmntent" = xyes; then :
+  have_getmntent="seq"
+fi
+
+fi
+if test "x$have_getmntent" = "xno"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getmntent in -lgen" >&5
+$as_echo_n "checking for getmntent in -lgen... " >&6; }
+if ${ac_cv_lib_gen_getmntent+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgen  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getmntent ();
+int
+main ()
+{
+return getmntent ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_gen_getmntent=yes
+else
+  ac_cv_lib_gen_getmntent=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_getmntent" >&5
+$as_echo "$ac_cv_lib_gen_getmntent" >&6; }
+if test "x$ac_cv_lib_gen_getmntent" = xyes; then :
+  have_getmntent="gen"
+fi
+
+fi
+
+if test "x$have_getmntent" = "xc"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getmntent takes one argument" >&5
+$as_echo_n "checking whether getmntent takes one argument... " >&6; }
+if ${c_cv_have_one_getmntent+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include "$srcdir/src/utils_mount.h"
+
+int
+main ()
+{
+
+FILE *fh;
+struct mntent *me;
+fh = setmntent ("/etc/mtab", "r");
+me = getmntent (fh);
+return(me->mnt_passno);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_one_getmntent="yes"
+else
+  c_cv_have_one_getmntent="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_one_getmntent" >&5
+$as_echo "$c_cv_have_one_getmntent" >&6; }
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getmntent takes two arguments" >&5
+$as_echo_n "checking whether getmntent takes two arguments... " >&6; }
+if ${c_cv_have_two_getmntent+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include "$srcdir/src/utils_mount.h"
+
+int
+main ()
+{
+
+                                FILE *fh;
+                                struct mnttab mt;
+                                int status;
+                                fh = fopen ("/etc/mnttab", "r");
+                                status = getmntent (fh, &mt);
+                                return(status);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_have_two_getmntent="yes"
+else
+  c_cv_have_two_getmntent="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_two_getmntent" >&5
+$as_echo "$c_cv_have_two_getmntent" >&6; }
+fi
+
+# Check for different versions of `getmntent' here..
+
+if test "x$have_getmntent" = "xc"; then
+       if test "x$c_cv_have_one_getmntent" = "xyes"; then
+
+$as_echo "#define HAVE_ONE_GETMNTENT 1" >>confdefs.h
+
+       fi
+       if test "x$c_cv_have_two_getmntent" = "xyes"; then
+
+$as_echo "#define HAVE_TWO_GETMNTENT 1" >>confdefs.h
+
+       fi
+fi
+if test "x$have_getmntent" = "xsun"; then
+
+$as_echo "#define HAVE_SUN_GETMNTENT 1" >>confdefs.h
+
+fi
+if test "x$have_getmntent" = "xseq"; then
+
+$as_echo "#define HAVE_SEQ_GETMNTENT 1" >>confdefs.h
+
+fi
+if test "x$have_getmntent" = "xgen"; then
+
+$as_echo "#define HAVE_GEN_GETMNTENT 1" >>confdefs.h
+
+fi
+
+# Check for htonll
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if have htonll defined" >&5
+$as_echo_n "checking if have htonll defined... " >&6; }
+if ${c_cv_have_htonll+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+int
+main ()
+{
+
+          return htonll(0);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  c_cv_have_htonll="yes"
+else
+  c_cv_have_htonll="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_htonll" >&5
+$as_echo "$c_cv_have_htonll" >&6; }
+if test "x$c_cv_have_htonll" = "xyes"
+then
+
+$as_echo "#define HAVE_HTONLL 1" >>confdefs.h
+
+fi
+
+# Check for structures
+ac_fn_c_check_member "$LINENO" "struct if_data" "ifi_ibytes" "ac_cv_member_struct_if_data_ifi_ibytes" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <net/if.h>
+
+"
+if test "x$ac_cv_member_struct_if_data_ifi_ibytes" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_IF_DATA_IFI_IBYTES 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_IF_DATA 1" >>confdefs.h
+
+fi
+ac_fn_c_check_member "$LINENO" "struct if_data" "ifi_opackets" "ac_cv_member_struct_if_data_ifi_opackets" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <net/if.h>
+
+"
+if test "x$ac_cv_member_struct_if_data_ifi_opackets" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_IF_DATA_IFI_OPACKETS 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_IF_DATA 1" >>confdefs.h
+
+fi
+ac_fn_c_check_member "$LINENO" "struct if_data" "ifi_ierrors" "ac_cv_member_struct_if_data_ifi_ierrors" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <net/if.h>
+
+"
+if test "x$ac_cv_member_struct_if_data_ifi_ierrors" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_IF_DATA_IFI_IERRORS 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_IF_DATA 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct net_device_stats" "rx_bytes" "ac_cv_member_struct_net_device_stats_rx_bytes" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <linux/if.h>
+       #include <linux/netdevice.h>
+
+"
+if test "x$ac_cv_member_struct_net_device_stats_rx_bytes" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_NET_DEVICE_STATS_RX_BYTES 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_NET_DEVICE_STATS 1" >>confdefs.h
+
+fi
+ac_fn_c_check_member "$LINENO" "struct net_device_stats" "tx_packets" "ac_cv_member_struct_net_device_stats_tx_packets" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <linux/if.h>
+       #include <linux/netdevice.h>
+
+"
+if test "x$ac_cv_member_struct_net_device_stats_tx_packets" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_NET_DEVICE_STATS_TX_PACKETS 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_NET_DEVICE_STATS 1" >>confdefs.h
+
+fi
+ac_fn_c_check_member "$LINENO" "struct net_device_stats" "rx_errors" "ac_cv_member_struct_net_device_stats_rx_errors" "
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <linux/if.h>
+       #include <linux/netdevice.h>
+
+"
+if test "x$ac_cv_member_struct_net_device_stats_rx_errors" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_NET_DEVICE_STATS_RX_ERRORS 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_NET_DEVICE_STATS 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct inet_diag_req" "id" "ac_cv_member_struct_inet_diag_req_id" "
+       #include <linux/inet_diag.h>
+
+"
+if test "x$ac_cv_member_struct_inet_diag_req_id" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_INET_DIAG_REQ_ID 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_LINUX_INET_DIAG_REQ 1" >>confdefs.h
+
+fi
+ac_fn_c_check_member "$LINENO" "struct inet_diag_req" "idiag_states" "ac_cv_member_struct_inet_diag_req_idiag_states" "
+       #include <linux/inet_diag.h>
+
+"
+if test "x$ac_cv_member_struct_inet_diag_req_idiag_states" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_INET_DIAG_REQ_IDIAG_STATES 1
+_ACEOF
+
+
+$as_echo "#define HAVE_STRUCT_LINUX_INET_DIAG_REQ 1" >>confdefs.h
+
+fi
+
+
+
+ac_fn_c_check_member "$LINENO" "struct ip_mreqn" "imr_ifindex" "ac_cv_member_struct_ip_mreqn_imr_ifindex" "
+       #include <netinet/in.h>
+       #include <net/if.h>
+
+"
+if test "x$ac_cv_member_struct_ip_mreqn_imr_ifindex" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_IP_MREQN_IMR_IFINDEX 1
+_ACEOF
+
+
+fi
+
+
+ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "ki_pid" "ac_cv_member_struct_kinfo_proc_ki_pid" "
+#include <kvm.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_ki_pid" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_KINFO_PROC_KI_PID 1
+_ACEOF
+
+
+
+$as_echo "#define HAVE_STRUCT_KINFO_PROC_FREEBSD 1" >>confdefs.h
+
+               have_struct_kinfo_proc_freebsd="yes"
+
+else
+
+               have_struct_kinfo_proc_freebsd="no"
+
+fi
+ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "ki_rssize" "ac_cv_member_struct_kinfo_proc_ki_rssize" "
+#include <kvm.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_ki_rssize" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_KINFO_PROC_KI_RSSIZE 1
+_ACEOF
+
+
+
+$as_echo "#define HAVE_STRUCT_KINFO_PROC_FREEBSD 1" >>confdefs.h
+
+               have_struct_kinfo_proc_freebsd="yes"
+
+else
+
+               have_struct_kinfo_proc_freebsd="no"
+
+fi
+ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "ki_rusage" "ac_cv_member_struct_kinfo_proc_ki_rusage" "
+#include <kvm.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_ki_rusage" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_KINFO_PROC_KI_RUSAGE 1
+_ACEOF
+
+
+
+$as_echo "#define HAVE_STRUCT_KINFO_PROC_FREEBSD 1" >>confdefs.h
+
+               have_struct_kinfo_proc_freebsd="yes"
+
+else
+
+               have_struct_kinfo_proc_freebsd="no"
+
+fi
+
+
+ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "p_pid" "ac_cv_member_struct_kinfo_proc_p_pid" "
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <kvm.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_p_pid" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_KINFO_PROC_P_PID 1
+_ACEOF
+
+
+
+$as_echo "#define HAVE_STRUCT_KINFO_PROC_OPENBSD 1" >>confdefs.h
+
+               have_struct_kinfo_proc_openbsd="yes"
+
+else
+
+               have_struct_kinfo_proc_openbsd="no"
+
+fi
+ac_fn_c_check_member "$LINENO" "struct kinfo_proc" "p_vm_rssize" "ac_cv_member_struct_kinfo_proc_p_vm_rssize" "
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <kvm.h>
+
+"
+if test "x$ac_cv_member_struct_kinfo_proc_p_vm_rssize" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_KINFO_PROC_P_VM_RSSIZE 1
+_ACEOF
+
+
+
+$as_echo "#define HAVE_STRUCT_KINFO_PROC_OPENBSD 1" >>confdefs.h
+
+               have_struct_kinfo_proc_openbsd="yes"
+
+else
+
+               have_struct_kinfo_proc_openbsd="no"
+
+fi
+
+
+ac_fn_c_check_member "$LINENO" "struct udphdr" "uh_dport" "ac_cv_member_struct_udphdr_uh_dport" "#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+#if HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+
+"
+if test "x$ac_cv_member_struct_udphdr_uh_dport" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_UDPHDR_UH_DPORT 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "struct udphdr" "uh_sport" "ac_cv_member_struct_udphdr_uh_sport" "#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+#if HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+
+"
+if test "x$ac_cv_member_struct_udphdr_uh_sport" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_UDPHDR_UH_SPORT 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct udphdr" "dest" "ac_cv_member_struct_udphdr_dest" "#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+#if HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+
+"
+if test "x$ac_cv_member_struct_udphdr_dest" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_UDPHDR_DEST 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "struct udphdr" "source" "ac_cv_member_struct_udphdr_source" "#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+#if HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+
+"
+if test "x$ac_cv_member_struct_udphdr_source" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_UDPHDR_SOURCE 1
+_ACEOF
+
+
+fi
+
+
+ac_fn_c_check_member "$LINENO" "kstat_io_t" "nwritten" "ac_cv_member_kstat_io_t_nwritten" "
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
+"
+if test "x$ac_cv_member_kstat_io_t_nwritten" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_KSTAT_IO_T_NWRITTEN 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "kstat_io_t" "writes" "ac_cv_member_kstat_io_t_writes" "
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
+"
+if test "x$ac_cv_member_kstat_io_t_writes" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_KSTAT_IO_T_WRITES 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "kstat_io_t" "nwrites" "ac_cv_member_kstat_io_t_nwrites" "
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
+"
+if test "x$ac_cv_member_kstat_io_t_nwrites" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_KSTAT_IO_T_NWRITES 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_member "$LINENO" "kstat_io_t" "wtime" "ac_cv_member_kstat_io_t_wtime" "
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
+"
+if test "x$ac_cv_member_kstat_io_t_wtime" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_KSTAT_IO_T_WTIME 1
+_ACEOF
+
+
+fi
+
+
+#
+# Checks for libraries begin here
+#
+
+with_libresolv="yes"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_search in -lresolv" >&5
+$as_echo_n "checking for res_search in -lresolv... " >&6; }
+if ${ac_cv_lib_resolv_res_search+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char res_search ();
+int
+main ()
+{
+return res_search ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_resolv_res_search=yes
+else
+  ac_cv_lib_resolv_res_search=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_search" >&5
+$as_echo "$ac_cv_lib_resolv_res_search" >&6; }
+if test "x$ac_cv_lib_resolv_res_search" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBRESOLV 1" >>confdefs.h
+
+
+else
+  with_libresolv="no"
+fi
+
+ if test "x$with_libresolv" = "xyes"; then
+  BUILD_WITH_LIBRESOLV_TRUE=
+  BUILD_WITH_LIBRESOLV_FALSE='#'
+else
+  BUILD_WITH_LIBRESOLV_TRUE='#'
+  BUILD_WITH_LIBRESOLV_FALSE=
+fi
+
+
+with_libhal="yes"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libhal_device_property_exists in -lhal" >&5
+$as_echo_n "checking for libhal_device_property_exists in -lhal... " >&6; }
+if ${ac_cv_lib_hal_libhal_device_property_exists+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lhal  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char libhal_device_property_exists ();
+int
+main ()
+{
+return libhal_device_property_exists ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_hal_libhal_device_property_exists=yes
+else
+  ac_cv_lib_hal_libhal_device_property_exists=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hal_libhal_device_property_exists" >&5
+$as_echo "$ac_cv_lib_hal_libhal_device_property_exists" >&6; }
+if test "x$ac_cv_lib_hal_libhal_device_property_exists" = xyes; then :
+
+$as_echo "#define HAVE_LIBHAL 1" >>confdefs.h
+
+else
+  with_libhal="no"
+fi
+
+if test "x$with_libhal" = "xyes"; then
+       if test "x$PKG_CONFIG" != "x"; then
+               BUILD_WITH_LIBHAL_CFLAGS="`$PKG_CONFIG --cflags hal`"
+               BUILD_WITH_LIBHAL_LIBS="`$PKG_CONFIG --libs hal`"
+
+
+       fi
+fi
+
+
+
+if test "x$ac_system" = "xAIX"
+then
+       with_perfstat="yes"
+       with_procinfo="yes"
+else
+       with_perfstat="no (AIX only)"
+       with_procinfo="no (AIX only)"
+fi
+
+if test "x$with_perfstat" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perfstat_reset in -lperfstat" >&5
+$as_echo_n "checking for perfstat_reset in -lperfstat... " >&6; }
+if ${ac_cv_lib_perfstat_perfstat_reset+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lperfstat  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char perfstat_reset ();
+int
+main ()
+{
+return perfstat_reset ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_perfstat_perfstat_reset=yes
+else
+  ac_cv_lib_perfstat_perfstat_reset=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_perfstat_perfstat_reset" >&5
+$as_echo "$ac_cv_lib_perfstat_perfstat_reset" >&6; }
+if test "x$ac_cv_lib_perfstat_perfstat_reset" = xyes; then :
+  with_perfstat="yes"
+else
+  with_perfstat="no (perfstat not found)"
+fi
+
+#      AC_CHECK_HEADERS(sys/protosw.h libperfstat.h,, [with_perfstat="no (perfstat not found)"])
+fi
+if test "x$with_perfstat" = "xyes"
+then
+
+$as_echo "#define HAVE_PERFSTAT 1" >>confdefs.h
+
+        # struct members pertaining to donation have been added to libperfstat somewhere between AIX5.3ML5 and AIX5.3ML9
+        ac_fn_c_check_member "$LINENO" "perfstat_partition_type_t" "b.donate_enabled" "ac_cv_member_perfstat_partition_type_t_b_donate_enabled" "#include <libperfstat.h
+"
+if test "x$ac_cv_member_perfstat_partition_type_t_b_donate_enabled" = xyes; then :
+
+fi
+
+        if test "x$av_cv_member_perfstat_partition_type_t_b_donate_enabled" = "xyes"
+        then
+
+$as_echo "#define PERFSTAT_SUPPORTS_DONATION 1" >>confdefs.h
+
+        fi
+fi
+ if test "x$with_perfstat" = "xyes"; then
+  BUILD_WITH_PERFSTAT_TRUE=
+  BUILD_WITH_PERFSTAT_FALSE='#'
+else
+  BUILD_WITH_PERFSTAT_TRUE='#'
+  BUILD_WITH_PERFSTAT_FALSE=
+fi
+
+
+# Processes plugin under AIX.
+if test "x$with_procinfo" = "xyes"
+then
+       for ac_header in procinfo.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "procinfo.h" "ac_cv_header_procinfo_h" "$ac_includes_default"
+if test "x$ac_cv_header_procinfo_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PROCINFO_H 1
+_ACEOF
+
+else
+  with_procinfo="no (procinfo.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_procinfo" = "xyes"
+then
+
+$as_echo "#define HAVE_PROCINFO_H 1" >>confdefs.h
+
+fi
+
+if test "x$ac_system" = "xSolaris"
+then
+       with_kstat="yes"
+       with_devinfo="yes"
+else
+       with_kstat="no (Solaris only)"
+       with_devinfo="no (Solaris only)"
+fi
+
+if test "x$with_kstat" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kstat_open in -lkstat" >&5
+$as_echo_n "checking for kstat_open in -lkstat... " >&6; }
+if ${ac_cv_lib_kstat_kstat_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkstat  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kstat_open ();
+int
+main ()
+{
+return kstat_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_kstat_kstat_open=yes
+else
+  ac_cv_lib_kstat_kstat_open=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kstat_kstat_open" >&5
+$as_echo "$ac_cv_lib_kstat_kstat_open" >&6; }
+if test "x$ac_cv_lib_kstat_kstat_open" = xyes; then :
+  with_kstat="yes"
+else
+  with_kstat="no (libkstat not found)"
+fi
+
+fi
+if test "x$with_kstat" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for di_init in -ldevinfo" >&5
+$as_echo_n "checking for di_init in -ldevinfo... " >&6; }
+if ${ac_cv_lib_devinfo_di_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldevinfo  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char di_init ();
+int
+main ()
+{
+return di_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_devinfo_di_init=yes
+else
+  ac_cv_lib_devinfo_di_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_devinfo_di_init" >&5
+$as_echo "$ac_cv_lib_devinfo_di_init" >&6; }
+if test "x$ac_cv_lib_devinfo_di_init" = xyes; then :
+  with_devinfo="yes"
+else
+  with_devinfo="no (not found)"
+fi
+
+       for ac_header in kstat.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "kstat.h" "ac_cv_header_kstat_h" "$ac_includes_default"
+if test "x$ac_cv_header_kstat_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_KSTAT_H 1
+_ACEOF
+
+else
+  with_kstat="no (kstat.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_kstat" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBKSTAT 1" >>confdefs.h
+
+fi
+ if test "x$with_kstat" = "xyes"; then
+  BUILD_WITH_LIBKSTAT_TRUE=
+  BUILD_WITH_LIBKSTAT_FALSE='#'
+else
+  BUILD_WITH_LIBKSTAT_TRUE='#'
+  BUILD_WITH_LIBKSTAT_FALSE=
+fi
+
+ if test "x$with_devinfo" = "xyes"; then
+  BUILD_WITH_LIBDEVINFO_TRUE=
+  BUILD_WITH_LIBDEVINFO_FALSE='#'
+else
+  BUILD_WITH_LIBDEVINFO_TRUE='#'
+  BUILD_WITH_LIBDEVINFO_FALSE=
+fi
+
+
+with_libiokit="no"
+if test "x$ac_system" = "xDarwin"
+then
+       with_libiokit="yes"
+else
+       with_libiokit="no"
+fi
+ if test "x$with_libiokit" = "xyes"; then
+  BUILD_WITH_LIBIOKIT_TRUE=
+  BUILD_WITH_LIBIOKIT_FALSE='#'
+else
+  BUILD_WITH_LIBIOKIT_TRUE='#'
+  BUILD_WITH_LIBIOKIT_FALSE=
+fi
+
+
+with_libkvm="no"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kvm_getprocs in -lkvm" >&5
+$as_echo_n "checking for kvm_getprocs in -lkvm... " >&6; }
+if ${ac_cv_lib_kvm_kvm_getprocs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkvm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kvm_getprocs ();
+int
+main ()
+{
+return kvm_getprocs ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_kvm_kvm_getprocs=yes
+else
+  ac_cv_lib_kvm_kvm_getprocs=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_getprocs" >&5
+$as_echo "$ac_cv_lib_kvm_kvm_getprocs" >&6; }
+if test "x$ac_cv_lib_kvm_kvm_getprocs" = xyes; then :
+  with_kvm_getprocs="yes"
+else
+  with_kvm_getprocs="no"
+fi
+
+if test "x$with_kvm_getprocs" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBKVM_GETPROCS 1" >>confdefs.h
+
+       with_libkvm="yes"
+fi
+ if test "x$with_kvm_getprocs" = "xyes"; then
+  BUILD_WITH_LIBKVM_GETPROCS_TRUE=
+  BUILD_WITH_LIBKVM_GETPROCS_FALSE='#'
+else
+  BUILD_WITH_LIBKVM_GETPROCS_TRUE='#'
+  BUILD_WITH_LIBKVM_GETPROCS_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kvm_getswapinfo in -lkvm" >&5
+$as_echo_n "checking for kvm_getswapinfo in -lkvm... " >&6; }
+if ${ac_cv_lib_kvm_kvm_getswapinfo+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkvm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kvm_getswapinfo ();
+int
+main ()
+{
+return kvm_getswapinfo ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_kvm_kvm_getswapinfo=yes
+else
+  ac_cv_lib_kvm_kvm_getswapinfo=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_getswapinfo" >&5
+$as_echo "$ac_cv_lib_kvm_kvm_getswapinfo" >&6; }
+if test "x$ac_cv_lib_kvm_kvm_getswapinfo" = xyes; then :
+  with_kvm_getswapinfo="yes"
+else
+  with_kvm_getswapinfo="no"
+fi
+
+if test "x$with_kvm_getswapinfo" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBKVM_GETSWAPINFO 1" >>confdefs.h
+
+       with_libkvm="yes"
+fi
+ if test "x$with_kvm_getswapinfo" = "xyes"; then
+  BUILD_WITH_LIBKVM_GETSWAPINFO_TRUE=
+  BUILD_WITH_LIBKVM_GETSWAPINFO_FALSE='#'
+else
+  BUILD_WITH_LIBKVM_GETSWAPINFO_TRUE='#'
+  BUILD_WITH_LIBKVM_GETSWAPINFO_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kvm_nlist in -lkvm" >&5
+$as_echo_n "checking for kvm_nlist in -lkvm... " >&6; }
+if ${ac_cv_lib_kvm_kvm_nlist+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkvm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kvm_nlist ();
+int
+main ()
+{
+return kvm_nlist ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_kvm_kvm_nlist=yes
+else
+  ac_cv_lib_kvm_kvm_nlist=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_nlist" >&5
+$as_echo "$ac_cv_lib_kvm_kvm_nlist" >&6; }
+if test "x$ac_cv_lib_kvm_kvm_nlist" = xyes; then :
+  with_kvm_nlist="yes"
+else
+  with_kvm_nlist="no"
+fi
+
+if test "x$with_kvm_nlist" = "xyes"
+then
+       for ac_header in bsd/nlist.h nlist.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+$as_echo "#define HAVE_LIBKVM_NLIST 1" >>confdefs.h
+
+       with_libkvm="yes"
+fi
+ if test "x$with_kvm_nlist" = "xyes"; then
+  BUILD_WITH_LIBKVM_NLIST_TRUE=
+  BUILD_WITH_LIBKVM_NLIST_FALSE='#'
+else
+  BUILD_WITH_LIBKVM_NLIST_TRUE='#'
+  BUILD_WITH_LIBKVM_NLIST_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for kvm_openfiles in -lkvm" >&5
+$as_echo_n "checking for kvm_openfiles in -lkvm... " >&6; }
+if ${ac_cv_lib_kvm_kvm_openfiles+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lkvm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kvm_openfiles ();
+int
+main ()
+{
+return kvm_openfiles ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_kvm_kvm_openfiles=yes
+else
+  ac_cv_lib_kvm_kvm_openfiles=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_kvm_kvm_openfiles" >&5
+$as_echo "$ac_cv_lib_kvm_kvm_openfiles" >&6; }
+if test "x$ac_cv_lib_kvm_kvm_openfiles" = xyes; then :
+  with_kvm_openfiles="yes"
+else
+  with_kvm_openfiles="no"
+fi
+
+if test "x$with_kvm_openfiles" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBKVM_NLIST 1" >>confdefs.h
+
+       with_libkvm="yes"
+fi
+ if test "x$with_kvm_openfiles" = "xyes"; then
+  BUILD_WITH_LIBKVM_OPENFILES_TRUE=
+  BUILD_WITH_LIBKVM_OPENFILES_FALSE='#'
+else
+  BUILD_WITH_LIBKVM_OPENFILES_TRUE='#'
+  BUILD_WITH_LIBKVM_OPENFILES_FALSE=
+fi
+
+
+# --with-libaquaero5 {{{
+
+# Check whether --with-libaquaero5 was given.
+if test "${with_libaquaero5+set}" = set; then :
+  withval=$with_libaquaero5;
+ if test "x$withval" = "xyes"
+ then
+        with_libaquaero5="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libaquaero5="no"
+ else
+        with_libaquaero5="yes"
+        LIBAQUAERO5_CFLAGS="$LIBAQUAERO5_CFLAGS -I$withval/src"
+        LIBAQUAERO5_LDFLAGS="$LIBAQUAERO5_LDFLAGS -L$withval/obj"
+ fi; fi
+
+else
+  with_libaquaero5="yes"
+fi
+
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBAQUAERO5_CFLAGS"
+LDFLAGS="$LDFLAGS $LIBAQUAERO5_LDFLAGS"
+
+if test "x$with_libaquaero5" = "xyes"
+then
+       if test "x$LIBAQUAERO5_CFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libaquaero5 CPPFLAGS: $LIBAQUAERO5_CFLAGS" >&5
+$as_echo "$as_me: libaquaero5 CPPFLAGS: $LIBAQUAERO5_CFLAGS" >&6;}
+       fi
+       for ac_header in libaquaero5.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libaquaero5.h" "ac_cv_header_libaquaero5_h" "$ac_includes_default"
+if test "x$ac_cv_header_libaquaero5_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBAQUAERO5_H 1
+_ACEOF
+ with_libaquaero5="yes"
+else
+  with_libaquaero5="no (libaquaero5.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_libaquaero5" = "xyes"
+then
+       if test "x$LIBAQUAERO5_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libaquaero5 LDFLAGS: $LIBAQUAERO5_LDFLAGS" >&5
+$as_echo "$as_me: libaquaero5 LDFLAGS: $LIBAQUAERO5_LDFLAGS" >&6;}
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libaquaero5_poll in -laquaero5" >&5
+$as_echo_n "checking for libaquaero5_poll in -laquaero5... " >&6; }
+if ${ac_cv_lib_aquaero5_libaquaero5_poll+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-laquaero5  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char libaquaero5_poll ();
+int
+main ()
+{
+return libaquaero5_poll ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_aquaero5_libaquaero5_poll=yes
+else
+  ac_cv_lib_aquaero5_libaquaero5_poll=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_aquaero5_libaquaero5_poll" >&5
+$as_echo "$ac_cv_lib_aquaero5_libaquaero5_poll" >&6; }
+if test "x$ac_cv_lib_aquaero5_libaquaero5_poll" = xyes; then :
+  with_libaquaero5="yes"
+else
+  with_libaquaero5="no (symbol 'libaquaero5_poll' not found)"
+fi
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libaquaero5" = "xyes"
+then
+       BUILD_WITH_LIBAQUAERO5_CFLAGS="$LIBAQUAERO5_CFLAGS"
+       BUILD_WITH_LIBAQUAERO5_LDFLAGS="$LIBAQUAERO5_LDFLAGS"
+
+
+fi
+ if test "x$with_libaquaero5" = "xyes"; then
+  BUILD_WITH_LIBAQUAERO5_TRUE=
+  BUILD_WITH_LIBAQUAERO5_FALSE='#'
+else
+  BUILD_WITH_LIBAQUAERO5_TRUE='#'
+  BUILD_WITH_LIBAQUAERO5_FALSE=
+fi
+
+# }}}
+
+# --with-libhiredis {{{
+
+# Check whether --with-libhiredis was given.
+if test "${with_libhiredis+set}" = set; then :
+  withval=$with_libhiredis;
+ if test "x$withval" = "xyes"
+ then
+        with_libhiredis="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libhiredis="no"
+ else
+        with_libhiredis="yes"
+        LIBHIREDIS_CPPFLAGS="$LIBHIREDIS_CPPFLAGS -I$withval/include"
+        LIBHIREDIS_LDFLAGS="$LIBHIREDIS_LDFLAGS -L$withval/lib"
+ fi; fi
+
+else
+  with_libhiredis="yes"
+fi
+
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBHIREDIS_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBHIREDIS_LDFLAGS"
+
+if test "x$with_libhiredis" = "xyes"
+then
+       if test "x$LIBHIREDIS_CPPFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libhiredis CPPFLAGS: $LIBHIREDIS_CPPFLAGS" >&5
+$as_echo "$as_me: libhiredis CPPFLAGS: $LIBHIREDIS_CPPFLAGS" >&6;}
+       fi
+       for ac_header in hiredis/hiredis.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "hiredis/hiredis.h" "ac_cv_header_hiredis_hiredis_h" "$ac_includes_default"
+if test "x$ac_cv_header_hiredis_hiredis_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_HIREDIS_HIREDIS_H 1
+_ACEOF
+ with_libhiredis="yes"
+else
+  with_libhiredis="no (hiredis.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_libhiredis" = "xyes"
+then
+       if test "x$LIBHIREDIS_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libhiredis LDFLAGS: $LIBHIREDIS_LDFLAGS" >&5
+$as_echo "$as_me: libhiredis LDFLAGS: $LIBHIREDIS_LDFLAGS" >&6;}
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for redisCommand in -lhiredis" >&5
+$as_echo_n "checking for redisCommand in -lhiredis... " >&6; }
+if ${ac_cv_lib_hiredis_redisCommand+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lhiredis  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char redisCommand ();
+int
+main ()
+{
+return redisCommand ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_hiredis_redisCommand=yes
+else
+  ac_cv_lib_hiredis_redisCommand=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hiredis_redisCommand" >&5
+$as_echo "$ac_cv_lib_hiredis_redisCommand" >&6; }
+if test "x$ac_cv_lib_hiredis_redisCommand" = xyes; then :
+  with_libhiredis="yes"
+else
+  with_libhiredis="no (symbol 'redisCommand' not found)"
+fi
+
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libhiredis" = "xyes"
+then
+       BUILD_WITH_LIBHIREDIS_CPPFLAGS="$LIBHIREDIS_CPPFLAGS"
+       BUILD_WITH_LIBHIREDIS_LDFLAGS="$LIBHIREDIS_LDFLAGS"
+
+
+fi
+ if test "x$with_libhiredis" = "xyes"; then
+  BUILD_WITH_LIBHIREDIS_TRUE=
+  BUILD_WITH_LIBHIREDIS_FALSE='#'
+else
+  BUILD_WITH_LIBHIREDIS_TRUE='#'
+  BUILD_WITH_LIBHIREDIS_FALSE=
+fi
+
+# }}}
+
+# --with-libcurl {{{
+with_curl_config="curl-config"
+with_curl_cflags=""
+with_curl_libs=""
+
+# Check whether --with-libcurl was given.
+if test "${with_libcurl+set}" = set; then :
+  withval=$with_libcurl;
+       if test "x$withval" = "xno"
+       then
+               with_libcurl="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libcurl="yes"
+       else
+               if test -f "$withval" && test -x "$withval"
+               then
+                       with_curl_config="$withval"
+                       with_libcurl="yes"
+               else if test -x "$withval/bin/curl-config"
+               then
+                       with_curl_config="$withval/bin/curl-config"
+                       with_libcurl="yes"
+               fi; fi
+               with_libcurl="yes"
+       fi; fi
+
+else
+
+       with_libcurl="yes"
+
+fi
+
+if test "x$with_libcurl" = "xyes"
+then
+       with_curl_cflags=`$with_curl_config --cflags 2>/dev/null`
+       curl_config_status=$?
+
+       if test $curl_config_status -ne 0
+       then
+               with_libcurl="no ($with_curl_config failed)"
+       else
+               SAVE_CPPFLAGS="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $with_curl_cflags"
+
+               for ac_header in curl/curl.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "curl/curl.h" "ac_cv_header_curl_curl_h" "$ac_includes_default"
+if test "x$ac_cv_header_curl_curl_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CURL_CURL_H 1
+_ACEOF
+
+else
+  with_libcurl="no (curl/curl.h not found)"
+fi
+
+done
+
+
+               CPPFLAGS="$SAVE_CPPFLAGS"
+       fi
+fi
+if test "x$with_libcurl" = "xyes"
+then
+       with_curl_libs=`$with_curl_config --libs 2>/dev/null`
+       curl_config_status=$?
+
+       if test $curl_config_status -ne 0
+       then
+               with_libcurl="no ($with_curl_config failed)"
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_easy_init in -lcurl" >&5
+$as_echo_n "checking for curl_easy_init in -lcurl... " >&6; }
+if ${ac_cv_lib_curl_curl_easy_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurl $with_curl_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char curl_easy_init ();
+int
+main ()
+{
+return curl_easy_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_curl_curl_easy_init=yes
+else
+  ac_cv_lib_curl_curl_easy_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_easy_init" >&5
+$as_echo "$ac_cv_lib_curl_curl_easy_init" >&6; }
+if test "x$ac_cv_lib_curl_curl_easy_init" = xyes; then :
+  with_libcurl="yes"
+else
+  with_libcurl="no (symbol 'curl_easy_init' not found)"
+fi
+
+               ac_fn_c_check_decl "$LINENO" "CURLOPT_USERNAME" "ac_cv_have_decl_CURLOPT_USERNAME" "#include <curl/curl.h>
+"
+if test "x$ac_cv_have_decl_CURLOPT_USERNAME" = xyes; then :
+  have_curlopt_username="yes"
+else
+  have_curlopt_username="no"
+fi
+
+               ac_fn_c_check_decl "$LINENO" "CURLOPT_TIMEOUT_MS" "ac_cv_have_decl_CURLOPT_TIMEOUT_MS" "#include <curl/curl.h>
+"
+if test "x$ac_cv_have_decl_CURLOPT_TIMEOUT_MS" = xyes; then :
+  have_curlopt_timeout="yes"
+else
+  have_curlopt_timeout="no"
+fi
+
+       fi
+fi
+if test "x$with_libcurl" = "xyes"
+then
+       BUILD_WITH_LIBCURL_CFLAGS="$with_curl_cflags"
+       BUILD_WITH_LIBCURL_LIBS="$with_curl_libs"
+
+
+
+       if test "x$have_curlopt_username" = "xyes"
+       then
+
+$as_echo "#define HAVE_CURLOPT_USERNAME 1" >>confdefs.h
+
+       fi
+
+       if test "x$have_curlopt_timeout" = "xyes"
+       then
+
+$as_echo "#define HAVE_CURLOPT_TIMEOUT_MS 1" >>confdefs.h
+
+       fi
+fi
+ if test "x$with_libcurl" = "xyes"; then
+  BUILD_WITH_LIBCURL_TRUE=
+  BUILD_WITH_LIBCURL_FALSE='#'
+else
+  BUILD_WITH_LIBCURL_TRUE='#'
+  BUILD_WITH_LIBCURL_FALSE=
+fi
+
+# }}}
+
+# --with-libdbi {{{
+with_libdbi_cppflags=""
+with_libdbi_ldflags=""
+
+# Check whether --with-libdbi was given.
+if test "${with_libdbi+set}" = set; then :
+  withval=$with_libdbi;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libdbi_cppflags="-I$withval/include"
+               with_libdbi_ldflags="-L$withval/lib"
+               with_libdbi="yes"
+       else
+               with_libdbi="$withval"
+       fi
+
+else
+
+       with_libdbi="yes"
+
+fi
+
+if test "x$with_libdbi" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags"
+
+       for ac_header in dbi/dbi.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "dbi/dbi.h" "ac_cv_header_dbi_dbi_h" "$ac_includes_default"
+if test "x$ac_cv_header_dbi_dbi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DBI_DBI_H 1
+_ACEOF
+ with_libdbi="yes"
+else
+  with_libdbi="no (dbi/dbi.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libdbi" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags"
+       LDFLAGS="$LDFLAGS $with_libdbi_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbi_initialize in -ldbi" >&5
+$as_echo_n "checking for dbi_initialize in -ldbi... " >&6; }
+if ${ac_cv_lib_dbi_dbi_initialize+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldbi  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dbi_initialize ();
+int
+main ()
+{
+return dbi_initialize ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dbi_dbi_initialize=yes
+else
+  ac_cv_lib_dbi_dbi_initialize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dbi_dbi_initialize" >&5
+$as_echo "$ac_cv_lib_dbi_dbi_initialize" >&6; }
+if test "x$ac_cv_lib_dbi_dbi_initialize" = xyes; then :
+  with_libdbi="yes"
+else
+  with_libdbi="no (Symbol 'dbi_initialize' not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libdbi" = "xyes"
+then
+       BUILD_WITH_LIBDBI_CPPFLAGS="$with_libdbi_cppflags"
+       BUILD_WITH_LIBDBI_LDFLAGS="$with_libdbi_ldflags"
+       BUILD_WITH_LIBDBI_LIBS="-ldbi"
+
+
+
+fi
+ if test "x$with_libdbi" = "xyes"; then
+  BUILD_WITH_LIBDBI_TRUE=
+  BUILD_WITH_LIBDBI_FALSE='#'
+else
+  BUILD_WITH_LIBDBI_TRUE='#'
+  BUILD_WITH_LIBDBI_FALSE=
+fi
+
+# }}}
+
+# --with-libesmtp {{{
+
+# Check whether --with-libesmtp was given.
+if test "${with_libesmtp+set}" = set; then :
+  withval=$with_libesmtp;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE"
+               with_libesmtp="yes"
+       else
+               with_libesmtp="$withval"
+       fi
+
+else
+
+       with_libesmtp="yes"
+
+fi
+
+if test "x$with_libesmtp" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for smtp_create_session in -lesmtp" >&5
+$as_echo_n "checking for smtp_create_session in -lesmtp... " >&6; }
+if ${ac_cv_lib_esmtp_smtp_create_session+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lesmtp  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char smtp_create_session ();
+int
+main ()
+{
+return smtp_create_session ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_esmtp_smtp_create_session=yes
+else
+  ac_cv_lib_esmtp_smtp_create_session=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_esmtp_smtp_create_session" >&5
+$as_echo "$ac_cv_lib_esmtp_smtp_create_session" >&6; }
+if test "x$ac_cv_lib_esmtp_smtp_create_session" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBESMTP 1" >>confdefs.h
+
+
+else
+  with_libesmtp="no (libesmtp not found)"
+fi
+
+fi
+if test "x$with_libesmtp" = "xyes"
+then
+       for ac_header in libesmtp.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libesmtp.h" "ac_cv_header_libesmtp_h" "$ac_includes_default"
+if test "x$ac_cv_header_libesmtp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBESMTP_H 1
+_ACEOF
+
+
+$as_echo "#define HAVE_LIBESMTP_H 1" >>confdefs.h
+
+
+else
+  with_libesmtp="no (libesmtp.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_libesmtp" = "xyes"
+then
+       collect_libesmtp=1
+else
+       collect_libesmtp=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define COLLECT_LIBESMTP $collect_libesmtp
+_ACEOF
+
+ if test "x$with_libesmtp" = "xyes"; then
+  BUILD_WITH_LIBESMTP_TRUE=
+  BUILD_WITH_LIBESMTP_FALSE='#'
+else
+  BUILD_WITH_LIBESMTP_TRUE='#'
+  BUILD_WITH_LIBESMTP_FALSE=
+fi
+
+# }}}
+
+# --with-libganglia {{{
+
+# Check whether --with-libganglia was given.
+if test "${with_libganglia+set}" = set; then :
+  withval=$with_libganglia;
+ if test -f "$withval" && test -x "$withval"
+ then
+        with_libganglia_config="$withval"
+        with_libganglia="yes"
+ else if test -f "$withval/bin/ganglia-config" && test -x "$withval/bin/ganglia-config"
+ then
+        with_libganglia_config="$withval/bin/ganglia-config"
+        with_libganglia="yes"
+ else if test -d "$withval"
+ then
+        GANGLIA_CPPFLAGS="-I$withval/include"
+        GANGLIA_LDFLAGS="-L$withval/lib"
+        with_libganglia="yes"
+ else
+        with_libganglia_config="ganglia-config"
+        with_libganglia="$withval"
+ fi; fi; fi
+
+else
+
+ with_libganglia_config="ganglia-config"
+ with_libganglia="yes"
+
+fi
+
+
+if test "x$with_libganglia" = "xyes" && test "x$with_libganglia_config" != "x"
+then
+       if test "x$GANGLIA_CPPFLAGS" = "x"
+       then
+               GANGLIA_CPPFLAGS=`"$with_libganglia_config" --cflags 2>/dev/null`
+       fi
+
+       if test "x$GANGLIA_LDFLAGS" = "x"
+       then
+               GANGLIA_LDFLAGS=`"$with_libganglia_config" --ldflags 2>/dev/null`
+       fi
+
+       if test "x$GANGLIA_LIBS" = "x"
+       then
+               GANGLIA_LIBS=`"$with_libganglia_config" --libs 2>/dev/null`
+       fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $GANGLIA_CPPFLAGS"
+LDFLAGS="$LDFLAGS $GANGLIA_LDFLAGS"
+
+if test "x$with_libganglia" = "xyes"
+then
+       for ac_header in gm_protocol.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "gm_protocol.h" "ac_cv_header_gm_protocol_h" "$ac_includes_default"
+if test "x$ac_cv_header_gm_protocol_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GM_PROTOCOL_H 1
+_ACEOF
+
+
+$as_echo "#define HAVE_GM_PROTOCOL_H 1" >>confdefs.h
+
+
+else
+  with_libganglia="no (gm_protocol.h not found)"
+fi
+
+done
+
+fi
+
+if test "x$with_libganglia" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xdr_Ganglia_value_msg in -lganglia" >&5
+$as_echo_n "checking for xdr_Ganglia_value_msg in -lganglia... " >&6; }
+if ${ac_cv_lib_ganglia_xdr_Ganglia_value_msg+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lganglia  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char xdr_Ganglia_value_msg ();
+int
+main ()
+{
+return xdr_Ganglia_value_msg ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ganglia_xdr_Ganglia_value_msg=yes
+else
+  ac_cv_lib_ganglia_xdr_Ganglia_value_msg=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ganglia_xdr_Ganglia_value_msg" >&5
+$as_echo "$ac_cv_lib_ganglia_xdr_Ganglia_value_msg" >&6; }
+if test "x$ac_cv_lib_ganglia_xdr_Ganglia_value_msg" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBGANGLIA 1" >>confdefs.h
+
+
+else
+  with_libganglia="no (symbol xdr_Ganglia_value_msg not found)"
+fi
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+
+
+
+ if test "x$with_libganglia" = "xyes"; then
+  BUILD_WITH_LIBGANGLIA_TRUE=
+  BUILD_WITH_LIBGANGLIA_FALSE='#'
+else
+  BUILD_WITH_LIBGANGLIA_TRUE='#'
+  BUILD_WITH_LIBGANGLIA_FALSE=
+fi
+
+# }}}
+
+# --with-libgcrypt {{{
+GCRYPT_CPPFLAGS="$GCRYPT_CPPFLAGS"
+GCRYPT_LDFLAGS="$GCRYPT_LDFLAGS"
+GCRYPT_LIBS="$GCRYPT_LIBS"
+
+# Check whether --with-libgcrypt was given.
+if test "${with_libgcrypt+set}" = set; then :
+  withval=$with_libgcrypt;
+ if test -f "$withval" && test -x "$withval"
+ then
+        with_libgcrypt_config="$withval"
+        with_libgcrypt="yes"
+ else if test -f "$withval/bin/gcrypt-config" && test -x "$withval/bin/gcrypt-config"
+ then
+        with_libgcrypt_config="$withval/bin/gcrypt-config"
+        with_libgcrypt="yes"
+ else if test -d "$withval"
+ then
+        GCRYPT_CPPFLAGS="$GCRYPT_CPPFLAGS -I$withval/include"
+        GCRYPT_LDFLAGS="$GCRYPT_LDFLAGS -L$withval/lib"
+        with_libgcrypt="yes"
+ else
+        with_libgcrypt_config="gcrypt-config"
+        with_libgcrypt="$withval"
+ fi; fi; fi
+
+else
+
+ with_libgcrypt_config="libgcrypt-config"
+ with_libgcrypt="yes"
+
+fi
+
+
+if test "x$with_libgcrypt" = "xyes" && test "x$with_libgcrypt_config" != "x"
+then
+       if test "x$GCRYPT_CPPFLAGS" = "x"
+       then
+               GCRYPT_CPPFLAGS=`"$with_libgcrypt_config" --cflags 2>/dev/null`
+       fi
+
+       if test "x$GCRYPT_LDFLAGS" = "x"
+       then
+               gcrypt_exec_prefix=`"$with_libgcrypt_config" --exec-prefix 2>/dev/null`
+               GCRYPT_LDFLAGS="-L$gcrypt_exec_prefix/lib"
+       fi
+
+       if test "x$GCRYPT_LIBS" = "x"
+       then
+               GCRYPT_LIBS=`"$with_libgcrypt_config" --libs 2>/dev/null`
+       fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $GCRYPT_CPPFLAGS"
+LDFLAGS="$LDFLAGS $GCRYPT_LDFLAGS"
+
+if test "x$with_libgcrypt" = "xyes"
+then
+       if test "x$GCRYPT_CPPFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: gcrypt CPPFLAGS: $GCRYPT_CPPFLAGS" >&5
+$as_echo "$as_me: gcrypt CPPFLAGS: $GCRYPT_CPPFLAGS" >&6;}
+       fi
+       for ac_header in gcrypt.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "gcrypt.h" "ac_cv_header_gcrypt_h" "$ac_includes_default"
+if test "x$ac_cv_header_gcrypt_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GCRYPT_H 1
+_ACEOF
+ with_libgcrypt="yes"
+else
+  with_libgcrypt="no (gcrypt.h not found)"
+fi
+
+done
+
+fi
+
+if test "x$with_libgcrypt" = "xyes"
+then
+       if test "x$GCRYPT_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: gcrypt LDFLAGS: $GCRYPT_LDFLAGS" >&5
+$as_echo "$as_me: gcrypt LDFLAGS: $GCRYPT_LDFLAGS" >&6;}
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_md_hash_buffer in -lgcrypt" >&5
+$as_echo_n "checking for gcry_md_hash_buffer in -lgcrypt... " >&6; }
+if ${ac_cv_lib_gcrypt_gcry_md_hash_buffer+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lgcrypt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gcry_md_hash_buffer ();
+int
+main ()
+{
+return gcry_md_hash_buffer ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_gcrypt_gcry_md_hash_buffer=yes
+else
+  ac_cv_lib_gcrypt_gcry_md_hash_buffer=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcrypt_gcry_md_hash_buffer" >&5
+$as_echo "$ac_cv_lib_gcrypt_gcry_md_hash_buffer" >&6; }
+if test "x$ac_cv_lib_gcrypt_gcry_md_hash_buffer" = xyes; then :
+  with_libgcrypt="yes"
+else
+  with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"
+fi
+
+
+       if test "$with_libgcrypt" != "no"; then
+
+# Check whether --with-libgcrypt-prefix was given.
+if test "${with_libgcrypt_prefix+set}" = set; then :
+  withval=$with_libgcrypt_prefix; libgcrypt_config_prefix="$withval"
+else
+  libgcrypt_config_prefix=""
+fi
+
+  if test x$libgcrypt_config_prefix != x ; then
+     if test x${LIBGCRYPT_CONFIG+set} != xset ; then
+        LIBGCRYPT_CONFIG=$libgcrypt_config_prefix/bin/libgcrypt-config
+     fi
+  fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}libgcrypt-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}libgcrypt-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_LIBGCRYPT_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $LIBGCRYPT_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_LIBGCRYPT_CONFIG="$LIBGCRYPT_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+LIBGCRYPT_CONFIG=$ac_cv_path_LIBGCRYPT_CONFIG
+if test -n "$LIBGCRYPT_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBGCRYPT_CONFIG" >&5
+$as_echo "$LIBGCRYPT_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_LIBGCRYPT_CONFIG"; then
+  ac_pt_LIBGCRYPT_CONFIG=$LIBGCRYPT_CONFIG
+  # Extract the first word of "libgcrypt-config", so it can be a program name with args.
+set dummy libgcrypt-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_LIBGCRYPT_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_LIBGCRYPT_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$ac_pt_LIBGCRYPT_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_LIBGCRYPT_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_LIBGCRYPT_CONFIG=$ac_cv_path_ac_pt_LIBGCRYPT_CONFIG
+if test -n "$ac_pt_LIBGCRYPT_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LIBGCRYPT_CONFIG" >&5
+$as_echo "$ac_pt_LIBGCRYPT_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_LIBGCRYPT_CONFIG" = x; then
+    LIBGCRYPT_CONFIG="no"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIBGCRYPT_CONFIG=$ac_pt_LIBGCRYPT_CONFIG
+  fi
+else
+  LIBGCRYPT_CONFIG="$ac_cv_path_LIBGCRYPT_CONFIG"
+fi
+
+  tmp=1:1.2.0
+  if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then
+     req_libgcrypt_api=`echo "$tmp"     | sed 's/\(.*\):\(.*\)/\1/'`
+     min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'`
+  else
+     req_libgcrypt_api=0
+     min_libgcrypt_version="$tmp"
+  fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBGCRYPT - version >= $min_libgcrypt_version" >&5
+$as_echo_n "checking for LIBGCRYPT - version >= $min_libgcrypt_version... " >&6; }
+  ok=no
+  if test "$LIBGCRYPT_CONFIG" != "no" ; then
+    req_major=`echo $min_libgcrypt_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'`
+    req_minor=`echo $min_libgcrypt_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'`
+    req_micro=`echo $min_libgcrypt_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'`
+    libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version`
+    major=`echo $libgcrypt_config_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'`
+    minor=`echo $libgcrypt_config_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'`
+    micro=`echo $libgcrypt_config_version | \
+               sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'`
+    if test "$major" -gt "$req_major"; then
+        ok=yes
+    else
+        if test "$major" -eq "$req_major"; then
+            if test "$minor" -gt "$req_minor"; then
+               ok=yes
+            else
+               if test "$minor" -eq "$req_minor"; then
+                   if test "$micro" -ge "$req_micro"; then
+                     ok=yes
+                   fi
+               fi
+            fi
+        fi
+    fi
+  fi
+  if test $ok = yes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($libgcrypt_config_version)" >&5
+$as_echo "yes ($libgcrypt_config_version)" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  fi
+  if test $ok = yes; then
+     # If we have a recent libgcrypt, we should also check that the
+     # API is compatible
+     if test "$req_libgcrypt_api" -gt 0 ; then
+        tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0`
+        if test "$tmp" -gt 0 ; then
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBGCRYPT API version" >&5
+$as_echo_n "checking LIBGCRYPT API version... " >&6; }
+           if test "$req_libgcrypt_api" -eq "$tmp" ; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: okay" >&5
+$as_echo "okay" >&6; }
+           else
+             ok=no
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: does not match. want=$req_libgcrypt_api got=$tmp" >&5
+$as_echo "does not match. want=$req_libgcrypt_api got=$tmp" >&6; }
+           fi
+        fi
+     fi
+  fi
+  if test $ok = yes; then
+    LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags`
+    LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs`
+    :
+    if test x"$host" != x ; then
+      libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none`
+      if test x"$libgcrypt_config_host" != xnone ; then
+        if test x"$libgcrypt_config_host" != x"$host" ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+***
+*** The config script $LIBGCRYPT_CONFIG was
+*** built for $libgcrypt_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-libgcrypt-prefix
+*** to specify a matching config script.
+***" >&5
+$as_echo "$as_me: WARNING:
+***
+*** The config script $LIBGCRYPT_CONFIG was
+*** built for $libgcrypt_config_host and thus may not match the
+*** used host $host.
+*** You may want to use the configure option --with-libgcrypt-prefix
+*** to specify a matching config script.
+***" >&2;}
+        fi
+      fi
+    fi
+  else
+    LIBGCRYPT_CFLAGS=""
+    LIBGCRYPT_LIBS=""
+    with_libgcrypt="no (version 1.2.0+ required)"
+  fi
+
+
+
+               GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
+               GCRYPT_LIBS="$LIBGCRYPT_LIBS"
+       fi
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libgcrypt" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBGCRYPT 1" >>confdefs.h
+
+fi
+
+
+
+
+ if test "x$with_libgcrypt" = "xyes"; then
+  BUILD_WITH_LIBGCRYPT_TRUE=
+  BUILD_WITH_LIBGCRYPT_FALSE='#'
+else
+  BUILD_WITH_LIBGCRYPT_TRUE='#'
+  BUILD_WITH_LIBGCRYPT_FALSE=
+fi
+
+# }}}
+
+# --with-libiptc {{{
+
+# Check whether --with-libiptc was given.
+if test "${with_libiptc+set}" = set; then :
+  withval=$with_libiptc;
+       if test "x$withval" = "xyes"
+       then
+               with_libiptc="pkgconfig"
+       else if test "x$withval" = "xno"
+       then
+               with_libiptc="no"
+       else
+               with_libiptc="yes"
+               with_libiptc_cflags="-I$withval/include"
+               with_libiptc_libs="-L$withval/lib"
+       fi; fi
+
+else
+
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libiptc="pkgconfig"
+       else
+               with_libiptc="no (Linux only)"
+       fi
+
+fi
+
+
+if test "x$with_libiptc" = "xpkgconfig" && test "x$PKG_CONFIG" = "x"
+then
+       with_libiptc="no (Don't have pkg-config)"
+fi
+
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       $PKG_CONFIG --exists 'libiptc' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libiptc="no (pkg-config doesn't know libiptc)"
+       fi
+fi
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       with_libiptc_cflags="`$PKG_CONFIG --cflags 'libiptc'`"
+       if test $? -ne 0
+       then
+               with_libiptc="no ($PKG_CONFIG failed)"
+       fi
+       with_libiptc_libs="`$PKG_CONFIG --libs 'libiptc'`"
+       if test $? -ne 0
+       then
+               with_libiptc="no ($PKG_CONFIG failed)"
+       fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $with_libiptc_cflags"
+
+# check whether the header file for libiptc is available.
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       for ac_header in libiptc/libiptc.h libiptc/libip6tc.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  with_libiptc="no (header file missing)"
+fi
+
+done
+
+fi
+# If the header file is available, check for the required type declaractions.
+# They may be missing in old versions of libiptc. In that case, they will be
+# declared in the iptables plugin.
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       ac_fn_c_check_type "$LINENO" "iptc_handle_t" "ac_cv_type_iptc_handle_t" "$ac_includes_default"
+if test "x$ac_cv_type_iptc_handle_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_IPTC_HANDLE_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "ip6tc_handle_t" "ac_cv_type_ip6tc_handle_t" "$ac_includes_default"
+if test "x$ac_cv_type_ip6tc_handle_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_IP6TC_HANDLE_T 1
+_ACEOF
+
+
+fi
+
+fi
+# Check for the iptc_init symbol in the library.
+# This could be in iptc or ip4tc
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       SAVE_LIBS="$LIBS"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing iptc_init" >&5
+$as_echo_n "checking for library containing iptc_init... " >&6; }
+if ${ac_cv_search_iptc_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char iptc_init ();
+int
+main ()
+{
+return iptc_init ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' iptc ip4tc; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib $with_libiptc_libs $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_iptc_init=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_iptc_init+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_iptc_init+:} false; then :
+
+else
+  ac_cv_search_iptc_init=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_iptc_init" >&5
+$as_echo "$ac_cv_search_iptc_init" >&6; }
+ac_res=$ac_cv_search_iptc_init
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  with_libiptc="pkgconfig"
+else
+  with_libiptc="no"
+fi
+
+       LIBS="$SAVE_LIBS"
+fi
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       with_libiptc="yes"
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+
+ if test "x$with_libiptc" = "xyes"; then
+  BUILD_WITH_LIBIPTC_TRUE=
+  BUILD_WITH_LIBIPTC_FALSE='#'
+else
+  BUILD_WITH_LIBIPTC_TRUE='#'
+  BUILD_WITH_LIBIPTC_FALSE=
+fi
+
+if test "x$with_libiptc" = "xyes"
+then
+       BUILD_WITH_LIBIPTC_CPPFLAGS="$with_libiptc_cflags"
+       BUILD_WITH_LIBIPTC_LDFLAGS="$with_libiptc_libs"
+
+
+fi
+# }}}
+
+# --with-java {{{
+with_java_home="$JAVA_HOME"
+if test "x$with_java_home" = "x"
+then
+       with_java_home="/usr/lib/jvm"
+fi
+with_java_vmtype="client"
+with_java_cflags=""
+with_java_libs=""
+JAVAC="$JAVAC"
+JAR="$JAR"
+
+# Check whether --with-java was given.
+if test "${with_java+set}" = set; then :
+  withval=$with_java;
+       if test "x$withval" = "xno"
+       then
+               with_java="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_java="yes"
+       else
+               with_java_home="$withval"
+               with_java="yes"
+       fi; fi
+
+else
+  with_java="yes"
+fi
+
+if test "x$with_java" = "xyes"
+then
+       if test -d "$with_java_home"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jni.h" >&5
+$as_echo_n "checking for jni.h... " >&6; }
+               TMPVAR=`find -L "$with_java_home" -name jni.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
+               if test "x$TMPVAR" != "x"
+               then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $TMPVAR" >&5
+$as_echo "found in $TMPVAR" >&6; }
+                       JAVA_CPPFLAGS="$JAVA_CPPFLAGS -I$TMPVAR"
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+               fi
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jni_md.h" >&5
+$as_echo_n "checking for jni_md.h... " >&6; }
+               TMPVAR=`find -L "$with_java_home" -name jni_md.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
+               if test "x$TMPVAR" != "x"
+               then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $TMPVAR" >&5
+$as_echo "found in $TMPVAR" >&6; }
+                       JAVA_CPPFLAGS="$JAVA_CPPFLAGS -I$TMPVAR"
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+               fi
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libjvm.so" >&5
+$as_echo_n "checking for libjvm.so... " >&6; }
+               TMPVAR=`find -L "$with_java_home" -name libjvm.so -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
+               if test "x$TMPVAR" != "x"
+               then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $TMPVAR" >&5
+$as_echo "found in $TMPVAR" >&6; }
+                       JAVA_LDFLAGS="$JAVA_LDFLAGS -L$TMPVAR -Wl,-rpath -Wl,$TMPVAR"
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+               fi
+
+               if test "x$JAVAC" = "x"
+               then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for javac" >&5
+$as_echo_n "checking for javac... " >&6; }
+                       TMPVAR=`find -L "$with_java_home" -name javac -type f 2>/dev/null | head -n 1`
+                       if test "x$TMPVAR" != "x"
+                       then
+                               JAVAC="$TMPVAR"
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+                       else
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+                       fi
+               fi
+               if test "x$JAR" = "x"
+               then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jar" >&5
+$as_echo_n "checking for jar... " >&6; }
+                       TMPVAR=`find -L "$with_java_home" -name jar -type f 2>/dev/null | head -n 1`
+                       if test "x$TMPVAR" != "x"
+                       then
+                               JAR="$TMPVAR"
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAR" >&5
+$as_echo "$JAR" >&6; }
+                       else
+                               { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+                       fi
+               fi
+       else if test "x$with_java_home" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: JAVA_HOME: No such directory: $with_java_home" >&5
+$as_echo "$as_me: WARNING: JAVA_HOME: No such directory: $with_java_home" >&2;}
+       fi; fi
+fi
+
+if test "x$JAVA_CPPFLAGS" != "x"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Building with JAVA_CPPFLAGS set to: $JAVA_CPPFLAGS" >&5
+$as_echo "$as_me: Building with JAVA_CPPFLAGS set to: $JAVA_CPPFLAGS" >&6;}
+fi
+if test "x$JAVA_CFLAGS" != "x"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Building with JAVA_CFLAGS set to: $JAVA_CFLAGS" >&5
+$as_echo "$as_me: Building with JAVA_CFLAGS set to: $JAVA_CFLAGS" >&6;}
+fi
+if test "x$JAVA_LDFLAGS" != "x"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Building with JAVA_LDFLAGS set to: $JAVA_LDFLAGS" >&5
+$as_echo "$as_me: Building with JAVA_LDFLAGS set to: $JAVA_LDFLAGS" >&6;}
+fi
+if test "x$JAVAC" = "x"
+then
+       with_javac_path="$PATH"
+       if test "x$with_java_home" != "x"
+       then
+               with_javac_path="$with_java_home:with_javac_path"
+               if test -d "$with_java_home/bin"
+               then
+                       with_javac_path="$with_java_home/bin:with_javac_path"
+               fi
+       fi
+
+       # Extract the first word of "javac", so it can be a program name with args.
+set dummy javac; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAVAC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAVAC in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAVAC="$JAVAC" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in "$with_javac_path"
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_JAVAC="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAVAC=$ac_cv_path_JAVAC
+if test -n "$JAVAC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5
+$as_echo "$JAVAC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test "x$JAVAC" = "x"
+then
+       with_java="no (javac not found)"
+fi
+if test "x$JAR" = "x"
+then
+       with_jar_path="$PATH"
+       if test "x$with_java_home" != "x"
+       then
+               with_jar_path="$with_java_home:$with_jar_path"
+               if test -d "$with_java_home/bin"
+               then
+                       with_jar_path="$with_java_home/bin:$with_jar_path"
+               fi
+       fi
+
+       # Extract the first word of "jar", so it can be a program name with args.
+set dummy jar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_JAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $JAR in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_JAR="$JAR" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in "$with_jar_path"
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_JAR="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+JAR=$ac_cv_path_JAR
+if test -n "$JAR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAR" >&5
+$as_echo "$JAR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test "x$JAR" = "x"
+then
+       with_java="no (jar not found)"
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_CFLAGS="$CFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $JAVA_CPPFLAGS"
+CFLAGS="$CFLAGS $JAVA_CFLAGS"
+LDFLAGS="$LDFLAGS $JAVA_LDFLAGS"
+
+if test "x$with_java" = "xyes"
+then
+       for ac_header in jni.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "jni.h" "ac_cv_header_jni_h" "$ac_includes_default"
+if test "x$ac_cv_header_jni_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_JNI_H 1
+_ACEOF
+
+else
+  with_java="no (jni.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_java" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -ljvm" >&5
+$as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
+if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljvm $JAVA_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JNI_CreateJavaVM ();
+int
+main ()
+{
+return JNI_CreateJavaVM ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_jvm_JNI_CreateJavaVM=yes
+else
+  ac_cv_lib_jvm_JNI_CreateJavaVM=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jvm_JNI_CreateJavaVM" >&5
+$as_echo "$ac_cv_lib_jvm_JNI_CreateJavaVM" >&6; }
+if test "x$ac_cv_lib_jvm_JNI_CreateJavaVM" = xyes; then :
+  with_java="yes"
+else
+  with_java="no (libjvm not found)"
+fi
+
+fi
+if test "x$with_java" = "xyes"
+then
+       JAVA_LIBS="$JAVA_LIBS -ljvm"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Building with JAVA_LIBS set to: $JAVA_LIBS" >&5
+$as_echo "$as_me: Building with JAVA_LIBS set to: $JAVA_LIBS" >&6;}
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+CFLAGS="$SAVE_CFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+
+
+
+
+ if test "x$with_java" = "xyes"; then
+  BUILD_WITH_JAVA_TRUE=
+  BUILD_WITH_JAVA_FALSE='#'
+else
+  BUILD_WITH_JAVA_TRUE='#'
+  BUILD_WITH_JAVA_FALSE=
+fi
+
+# }}}
+
+# --with-libldap {{{
+
+# Check whether --with-libldap was given.
+if test "${with_libldap+set}" = set; then :
+  withval=$with_libldap;
+ if test "x$withval" = "xyes"
+ then
+        with_libldap="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libldap="no"
+ else
+        with_libldap="yes"
+        LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS -I$withval/include"
+        LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS -L$withval/lib"
+ fi; fi
+
+else
+  with_libldap="yes"
+fi
+
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBLDAP_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBLDAP_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+       if test "x$LIBLDAP_CPPFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libldap CPPFLAGS: $LIBLDAP_CPPFLAGS" >&5
+$as_echo "$as_me: libldap CPPFLAGS: $LIBLDAP_CPPFLAGS" >&6;}
+       fi
+       for ac_header in ldap.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "ldap.h" "ac_cv_header_ldap_h" "$ac_includes_default"
+if test "x$ac_cv_header_ldap_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LDAP_H 1
+_ACEOF
+ with_libldap="yes"
+else
+  with_libldap="no ('ldap.h' not found)"
+fi
+
+done
+
+fi
+if test "x$with_libldap" = "xyes"
+then
+       if test "x$LIBLDAP_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libldap LDFLAGS: $LIBLDAP_LDFLAGS" >&5
+$as_echo "$as_me: libldap LDFLAGS: $LIBLDAP_LDFLAGS" >&6;}
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldap_initialize in -lldap" >&5
+$as_echo_n "checking for ldap_initialize in -lldap... " >&6; }
+if ${ac_cv_lib_ldap_ldap_initialize+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lldap  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldap_initialize ();
+int
+main ()
+{
+return ldap_initialize ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ldap_ldap_initialize=yes
+else
+  ac_cv_lib_ldap_ldap_initialize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_initialize" >&5
+$as_echo "$ac_cv_lib_ldap_ldap_initialize" >&6; }
+if test "x$ac_cv_lib_ldap_ldap_initialize" = xyes; then :
+  with_libldap="yes"
+else
+  with_libldap="no (symbol 'ldap_initialize' not found)"
+fi
+
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+       BUILD_WITH_LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS"
+       BUILD_WITH_LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS"
+
+
+fi
+ if test "x$with_libldap" = "xyes"; then
+  BUILD_WITH_LIBLDAP_TRUE=
+  BUILD_WITH_LIBLDAP_FALSE='#'
+else
+  BUILD_WITH_LIBLDAP_TRUE='#'
+  BUILD_WITH_LIBLDAP_FALSE=
+fi
+
+# }}}
+
+# --with-liblvm2app {{{
+with_liblvm2app_cppflags=""
+with_liblvm2app_ldflags=""
+
+# Check whether --with-liblvm2app was given.
+if test "${with_liblvm2app+set}" = set; then :
+  withval=$with_liblvm2app;
+        if test "x$withval" != "xno" && test "x$withval" != "xyes"
+        then
+                with_liblvm2app_cppflags="-I$withval/include"
+                with_liblvm2app_ldflags="-L$withval/lib"
+                with_liblvm2app="yes"
+        else
+                with_liblvm2app="$withval"
+        fi
+
+else
+
+        with_liblvm2app="yes"
+
+fi
+
+if test "x$with_liblvm2app" = "xyes"
+then
+        SAVE_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $with_liblvm2app_cppflags"
+
+        for ac_header in lvm2app.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "lvm2app.h" "ac_cv_header_lvm2app_h" "$ac_includes_default"
+if test "x$ac_cv_header_lvm2app_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LVM2APP_H 1
+_ACEOF
+ with_liblvm2app="yes"
+else
+  with_liblvm2app="no (lvm2app.h not found)"
+fi
+
+done
+
+
+        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"
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lvm_lv_get_property in -llvm2app" >&5
+$as_echo_n "checking for lvm_lv_get_property in -llvm2app... " >&6; }
+if ${ac_cv_lib_lvm2app_lvm_lv_get_property+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-llvm2app  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char lvm_lv_get_property ();
+int
+main ()
+{
+return lvm_lv_get_property ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_lvm2app_lvm_lv_get_property=yes
+else
+  ac_cv_lib_lvm2app_lvm_lv_get_property=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lvm2app_lvm_lv_get_property" >&5
+$as_echo "$ac_cv_lib_lvm2app_lvm_lv_get_property" >&6; }
+if test "x$ac_cv_lib_lvm2app_lvm_lv_get_property" = xyes; then :
+  with_liblvm2app="yes"
+else
+  with_liblvm2app="no (Symbol 'lvm_lv_get_property' not found)"
+fi
+
+
+        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"
+
+
+
+
+$as_echo "#define HAVE_LIBLVM2APP 1" >>confdefs.h
+
+fi
+ if test "x$with_liblvm2app" = "xyes"; then
+  BUILD_WITH_LIBLVM2APP_TRUE=
+  BUILD_WITH_LIBLVM2APP_FALSE='#'
+else
+  BUILD_WITH_LIBLVM2APP_TRUE='#'
+  BUILD_WITH_LIBLVM2APP_FALSE=
+fi
+
+# }}}
+
+# --with-libmemcached {{{
+with_libmemcached_cppflags=""
+with_libmemcached_ldflags=""
+
+# Check whether --with-libmemcached was given.
+if test "${with_libmemcached+set}" = set; then :
+  withval=$with_libmemcached;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libmemcached_cppflags="-I$withval/include"
+               with_libmemcached_ldflags="-L$withval/lib"
+               with_libmemcached="yes"
+       else
+               with_libmemcached="$withval"
+       fi
+
+else
+
+       with_libmemcached="yes"
+
+fi
+
+if test "x$with_libmemcached" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libmemcached_cppflags"
+
+       for ac_header in libmemcached/memcached.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libmemcached/memcached.h" "ac_cv_header_libmemcached_memcached_h" "$ac_includes_default"
+if test "x$ac_cv_header_libmemcached_memcached_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBMEMCACHED_MEMCACHED_H 1
+_ACEOF
+ with_libmemcached="yes"
+else
+  with_libmemcached="no (libmemcached/memcached.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmemcached" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libmemcached_cppflags"
+       LDFLAGS="$LDFLAGS $with_libmemcached_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for memcached_create in -lmemcached" >&5
+$as_echo_n "checking for memcached_create in -lmemcached... " >&6; }
+if ${ac_cv_lib_memcached_memcached_create+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmemcached  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char memcached_create ();
+int
+main ()
+{
+return memcached_create ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_memcached_memcached_create=yes
+else
+  ac_cv_lib_memcached_memcached_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_memcached_memcached_create" >&5
+$as_echo "$ac_cv_lib_memcached_memcached_create" >&6; }
+if test "x$ac_cv_lib_memcached_memcached_create" = xyes; then :
+  with_libmemcached="yes"
+else
+  with_libmemcached="no (Symbol 'memcached_create' not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libmemcached" = "xyes"
+then
+       BUILD_WITH_LIBMEMCACHED_CPPFLAGS="$with_libmemcached_cppflags"
+       BUILD_WITH_LIBMEMCACHED_LDFLAGS="$with_libmemcached_ldflags"
+       BUILD_WITH_LIBMEMCACHED_LIBS="-lmemcached"
+
+
+
+
+$as_echo "#define HAVE_LIBMEMCACHED 1" >>confdefs.h
+
+fi
+ if test "x$with_libmemcached" = "xyes"; then
+  BUILD_WITH_LIBMEMCACHED_TRUE=
+  BUILD_WITH_LIBMEMCACHED_FALSE='#'
+else
+  BUILD_WITH_LIBMEMCACHED_TRUE='#'
+  BUILD_WITH_LIBMEMCACHED_FALSE=
+fi
+
+# }}}
+
+# --with-libmodbus {{{
+with_libmodbus_config=""
+with_libmodbus_cflags=""
+with_libmodbus_libs=""
+
+# Check whether --with-libmodbus was given.
+if test "${with_libmodbus+set}" = set; then :
+  withval=$with_libmodbus;
+       if test "x$withval" = "xno"
+       then
+               with_libmodbus="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libmodbus="use_pkgconfig"
+       else if test -d "$with_libmodbus/lib"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: Not checking for libmodbus: Manually configured" >&5
+$as_echo "$as_me: Not checking for libmodbus: Manually configured" >&6;}
+               with_libmodbus_cflags="-I$withval/include"
+               with_libmodbus_libs="-L$withval/lib -lmodbus"
+               with_libmodbus="yes"
+       fi; fi; fi
+
+else
+  with_libmodbus="use_pkgconfig"
+fi
+
+
+# configure using pkg-config
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       if test "x$PKG_CONFIG" = "x"
+       then
+               with_libmodbus="no (Don't have pkg-config)"
+       fi
+fi
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Checking for libmodbus using $PKG_CONFIG" >&5
+$as_echo "$as_me: Checking for libmodbus using $PKG_CONFIG" >&6;}
+       $PKG_CONFIG --exists 'libmodbus' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libmodbus="no (pkg-config doesn't know libmodbus)"
+       fi
+fi
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       with_libmodbus_cflags="`$PKG_CONFIG --cflags 'libmodbus'`"
+       if test $? -ne 0
+       then
+               with_libmodbus="no ($PKG_CONFIG failed)"
+       fi
+       with_libmodbus_libs="`$PKG_CONFIG --libs 'libmodbus'`"
+       if test $? -ne 0
+       then
+               with_libmodbus="no ($PKG_CONFIG failed)"
+       fi
+fi
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       with_libmodbus="yes"
+fi
+
+# with_libmodbus_cflags and with_libmodbus_libs are set up now, let's do
+# the actual checks.
+if test "x$with_libmodbus" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags"
+
+       for ac_header in modbus/modbus.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "modbus/modbus.h" "ac_cv_header_modbus_modbus_h" "$ac_includes_default"
+if test "x$ac_cv_header_modbus_modbus_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MODBUS_MODBUS_H 1
+_ACEOF
+
+else
+  with_libmodbus="no (modbus/modbus.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmodbus" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags"
+       LDFLAGS="$LDFLAGS $with_libmodbus_libs"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for modbus_connect in -lmodbus" >&5
+$as_echo_n "checking for modbus_connect in -lmodbus... " >&6; }
+if ${ac_cv_lib_modbus_modbus_connect+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmodbus  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char modbus_connect ();
+int
+main ()
+{
+return modbus_connect ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_modbus_modbus_connect=yes
+else
+  ac_cv_lib_modbus_modbus_connect=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_modbus_modbus_connect" >&5
+$as_echo "$ac_cv_lib_modbus_modbus_connect" >&6; }
+if test "x$ac_cv_lib_modbus_modbus_connect" = xyes; then :
+  with_libmodbus="yes"
+else
+  with_libmodbus="no (symbol modbus_connect not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libmodbus" = "xyes"
+then
+       BUILD_WITH_LIBMODBUS_CFLAGS="$with_libmodbus_cflags"
+       BUILD_WITH_LIBMODBUS_LIBS="$with_libmodbus_libs"
+
+
+fi
+# }}}
+
+# --with-libmongoc {{{
+
+# Check whether --with-libmongoc was given.
+if test "${with_libmongoc+set}" = set; then :
+  withval=$with_libmongoc;
+ if test "x$withval" = "xyes"
+ then
+        with_libmongoc="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libmongoc="no"
+ else
+        with_libmongoc="yes"
+        LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS -I$withval/include"
+        LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS -L$withval/lib"
+ fi; fi
+
+else
+  with_libmongoc="yes"
+fi
+
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBMONGOC_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS"
+
+if test "x$with_libmongoc" = "xyes"
+then
+       if test "x$LIBMONGOC_CPPFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libmongoc CPPFLAGS: $LIBMONGOC_CPPFLAGS" >&5
+$as_echo "$as_me: libmongoc CPPFLAGS: $LIBMONGOC_CPPFLAGS" >&6;}
+       fi
+       for ac_header in mongo.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "mongo.h" "ac_cv_header_mongo_h" "#if HAVE_STDINT_H
+# define MONGO_HAVE_STDINT 1
+#else
+# define MONGO_USE_LONG_LONG_INT 1
+#endif
+
+"
+if test "x$ac_cv_header_mongo_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MONGO_H 1
+_ACEOF
+ with_libmongoc="yes"
+else
+  with_libmongoc="no ('mongo.h' not found)"
+fi
+
+done
+
+fi
+if test "x$with_libmongoc" = "xyes"
+then
+       if test "x$LIBMONGOC_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS" >&5
+$as_echo "$as_me: libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS" >&6;}
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mongo_run_command in -lmongoc" >&5
+$as_echo_n "checking for mongo_run_command in -lmongoc... " >&6; }
+if ${ac_cv_lib_mongoc_mongo_run_command+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmongoc  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char mongo_run_command ();
+int
+main ()
+{
+return mongo_run_command ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_mongoc_mongo_run_command=yes
+else
+  ac_cv_lib_mongoc_mongo_run_command=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mongoc_mongo_run_command" >&5
+$as_echo "$ac_cv_lib_mongoc_mongo_run_command" >&6; }
+if test "x$ac_cv_lib_mongoc_mongo_run_command" = xyes; then :
+  with_libmongoc="yes"
+else
+  with_libmongoc="no (symbol 'mongo_run_command' not found)"
+fi
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libmongoc" = "xyes"
+then
+       BUILD_WITH_LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS"
+       BUILD_WITH_LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS"
+
+
+fi
+ if test "x$with_libmongoc" = "xyes"; then
+  BUILD_WITH_LIBMONGOC_TRUE=
+  BUILD_WITH_LIBMONGOC_FALSE='#'
+else
+  BUILD_WITH_LIBMONGOC_TRUE='#'
+  BUILD_WITH_LIBMONGOC_FALSE=
+fi
+
+# }}}
+
+# --with-libmysql {{{
+with_mysql_config="mysql_config"
+with_mysql_cflags=""
+with_mysql_libs=""
+
+# Check whether --with-libmysql was given.
+if test "${with_libmysql+set}" = set; then :
+  withval=$with_libmysql;
+       if test "x$withval" = "xno"
+       then
+               with_libmysql="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libmysql="yes"
+       else
+               if test -f "$withval" && test -x "$withval";
+               then
+                       with_mysql_config="$withval"
+               else if test -x "$withval/bin/mysql_config"
+               then
+                       with_mysql_config="$withval/bin/mysql_config"
+               fi; fi
+               with_libmysql="yes"
+       fi; fi
+
+else
+
+       with_libmysql="yes"
+
+fi
+
+if test "x$with_libmysql" = "xyes"
+then
+       with_mysql_cflags=`$with_mysql_config --cflags 2>/dev/null`
+       mysql_config_status=$?
+
+       if test $mysql_config_status -ne 0
+       then
+               with_libmysql="no ($with_mysql_config failed)"
+       else
+               SAVE_CPPFLAGS="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $with_mysql_cflags"
+
+               have_mysql_h="no"
+               have_mysql_mysql_h="no"
+               for ac_header in mysql.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "mysql.h" "ac_cv_header_mysql_h" "$ac_includes_default"
+if test "x$ac_cv_header_mysql_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MYSQL_H 1
+_ACEOF
+ have_mysql_h="yes"
+fi
+
+done
+
+
+               if test "x$have_mysql_h" = "xno"
+               then
+                       for ac_header in mysql/mysql.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "mysql/mysql.h" "ac_cv_header_mysql_mysql_h" "$ac_includes_default"
+if test "x$ac_cv_header_mysql_mysql_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MYSQL_MYSQL_H 1
+_ACEOF
+ have_mysql_mysql_h="yes"
+fi
+
+done
+
+               fi
+
+               if test "x$have_mysql_h$have_mysql_mysql_h" = "xnono"
+               then
+                       with_libmysql="no (mysql.h not found)"
+               fi
+
+               CPPFLAGS="$SAVE_CPPFLAGS"
+       fi
+fi
+if test "x$with_libmysql" = "xyes"
+then
+       with_mysql_libs=`$with_mysql_config --libs_r 2>/dev/null`
+       mysql_config_status=$?
+
+       if test $mysql_config_status -ne 0
+       then
+               with_libmysql="no ($with_mysql_config failed)"
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5
+$as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; }
+if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmysqlclient $with_mysql_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char mysql_init ();
+int
+main ()
+{
+return mysql_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_mysqlclient_mysql_init=yes
+else
+  ac_cv_lib_mysqlclient_mysql_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5
+$as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; }
+if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then :
+  with_libmysql="yes"
+else
+  with_libmysql="no (symbol 'mysql_init' not found)"
+fi
+
+
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_get_server_version in -lmysqlclient" >&5
+$as_echo_n "checking for mysql_get_server_version in -lmysqlclient... " >&6; }
+if ${ac_cv_lib_mysqlclient_mysql_get_server_version+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmysqlclient $with_mysql_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char mysql_get_server_version ();
+int
+main ()
+{
+return mysql_get_server_version ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_mysqlclient_mysql_get_server_version=yes
+else
+  ac_cv_lib_mysqlclient_mysql_get_server_version=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_get_server_version" >&5
+$as_echo "$ac_cv_lib_mysqlclient_mysql_get_server_version" >&6; }
+if test "x$ac_cv_lib_mysqlclient_mysql_get_server_version" = xyes; then :
+  with_libmysql="yes"
+else
+  with_libmysql="no (symbol 'mysql_get_server_version' not found)"
+fi
+
+       fi
+fi
+if test "x$with_libmysql" = "xyes"
+then
+       BUILD_WITH_LIBMYSQL_CFLAGS="$with_mysql_cflags"
+       BUILD_WITH_LIBMYSQL_LIBS="$with_mysql_libs"
+
+
+fi
+ if test "x$with_libmysql" = "xyes"; then
+  BUILD_WITH_LIBMYSQL_TRUE=
+  BUILD_WITH_LIBMYSQL_FALSE='#'
+else
+  BUILD_WITH_LIBMYSQL_TRUE='#'
+  BUILD_WITH_LIBMYSQL_FALSE=
+fi
+
+# }}}
+
+# --with-libmnl {{{
+with_libmnl_cflags=""
+with_libmnl_libs=""
+
+# Check whether --with-libmnl was given.
+if test "${with_libmnl+set}" = set; then :
+  withval=$with_libmnl;
+ echo "libmnl: withval = $withval"
+ if test "x$withval" = "xyes"
+ then
+        with_libmnl="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libmnl="no"
+ else
+        if test -d "$withval/include"
+        then
+                with_libmnl_cflags="-I$withval/include"
+                with_libmnl_libs="-L$withval/lib -lmnl"
+                with_libmnl="yes"
+        else
+                as_fn_error $? "\"no such directory: $withval/include\"" "$LINENO" 5
+        fi
+ fi; fi
+
+else
+
+ if test "x$ac_system" = "xLinux"
+ then
+        with_libmnl="yes"
+ else
+        with_libmnl="no (Linux only library)"
+ fi
+
+fi
+
+if test "x$PKG_CONFIG" = "x"
+then
+       with_libmnl="no (Don't have pkg-config)"
+fi
+if test "x$with_libmnl" = "xyes"
+then
+       if $PKG_CONFIG --exists libmnl 2>/dev/null; then
+         with_libmnl_cflags="$with_libmnl_ldflags `$PKG_CONFIG --cflags libmnl`"
+         with_libmnl_libs="$with_libmnl_libs `$PKG_CONFIG --libs libmnl`"
+       fi
+
+       for ac_header in libmnl.h libmnl/libmnl.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+        with_libmnl="yes"
+        break
+
+fi
+
+done
+
+       for ac_header in linux/gen_stats.h linux/pkt_sched.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+int
+main ()
+{
+
+int retval = TCA_STATS2;
+return (retval);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_TCA_STATS2 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+int
+main ()
+{
+
+int retval = TCA_STATS;
+return (retval);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+$as_echo "#define HAVE_TCA_STATS 1" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+if test "x$with_libmnl" = "xyes"
+then
+       ac_fn_c_check_member "$LINENO" "struct rtnl_link_stats64" "tx_window_errors" "ac_cv_member_struct_rtnl_link_stats64_tx_window_errors" "
+       #include <linux/if_link.h>
+
+"
+if test "x$ac_cv_member_struct_rtnl_link_stats64_tx_window_errors" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_RTNL_LINK_STATS64_TX_WINDOW_ERRORS 1
+_ACEOF
+
+
+$as_echo "#define HAVE_RTNL_LINK_STATS64 1" >>confdefs.h
+
+fi
+
+fi
+if test "x$with_libmnl" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mnl_nlmsg_get_payload in -lmnl" >&5
+$as_echo_n "checking for mnl_nlmsg_get_payload in -lmnl... " >&6; }
+if ${ac_cv_lib_mnl_mnl_nlmsg_get_payload+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lmnl $with_libmnl_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char mnl_nlmsg_get_payload ();
+int
+main ()
+{
+return mnl_nlmsg_get_payload ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_mnl_mnl_nlmsg_get_payload=yes
+else
+  ac_cv_lib_mnl_mnl_nlmsg_get_payload=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mnl_mnl_nlmsg_get_payload" >&5
+$as_echo "$ac_cv_lib_mnl_mnl_nlmsg_get_payload" >&6; }
+if test "x$ac_cv_lib_mnl_mnl_nlmsg_get_payload" = xyes; then :
+  with_libmnl="yes"
+else
+  with_libmnl="no (symbol 'mnl_nlmsg_get_payload' not found)"
+fi
+
+fi
+if test "x$with_libmnl" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBMNL 1" >>confdefs.h
+
+       BUILD_WITH_LIBMNL_CFLAGS="$with_libmnl_cflags"
+       BUILD_WITH_LIBMNL_LIBS="$with_libmnl_libs"
+
+
+fi
+ if test "x$with_libmnl" = "xyes"; then
+  BUILD_WITH_LIBMNL_TRUE=
+  BUILD_WITH_LIBMNL_FALSE='#'
+else
+  BUILD_WITH_LIBMNL_TRUE='#'
+  BUILD_WITH_LIBMNL_FALSE=
+fi
+
+# }}}
+
+# --with-libnetapp {{{
+
+
+
+LIBNETAPP_CPPFLAGS="$LIBNETAPP_CPPFLAGS"
+LIBNETAPP_LDFLAGS="$LIBNETAPP_LDFLAGS"
+LIBNETAPP_LIBS="$LIBNETAPP_LIBS"
+
+# Check whether --with-libnetapp was given.
+if test "${with_libnetapp+set}" = set; then :
+  withval=$with_libnetapp;
+ if test -d "$withval"
+ then
+        LIBNETAPP_CPPFLAGS="$LIBNETAPP_CPPFLAGS -I$withval/include"
+        LIBNETAPP_LDFLAGS="$LIBNETAPP_LDFLAGS -L$withval/lib"
+        with_libnetapp="yes"
+ else
+        with_libnetapp="$withval"
+ fi
+
+else
+
+ with_libnetapp="yes"
+
+fi
+
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $LIBNETAPP_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBNETAPP_LDFLAGS"
+
+if test "x$with_libnetapp" = "xyes"
+then
+       if test "x$LIBNETAPP_CPPFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: netapp CPPFLAGS: $LIBNETAPP_CPPFLAGS" >&5
+$as_echo "$as_me: netapp CPPFLAGS: $LIBNETAPP_CPPFLAGS" >&6;}
+       fi
+       for ac_header in netapp_api.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "netapp_api.h" "ac_cv_header_netapp_api_h" "$ac_includes_default"
+if test "x$ac_cv_header_netapp_api_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NETAPP_API_H 1
+_ACEOF
+ with_libnetapp="yes"
+else
+  with_libnetapp="no (netapp_api.h not found)"
+fi
+
+done
+
+fi
+
+if test "x$with_libnetapp" = "xyes"
+then
+       if test "x$LIBNETAPP_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: netapp LDFLAGS: $LIBNETAPP_LDFLAGS" >&5
+$as_echo "$as_me: netapp LDFLAGS: $LIBNETAPP_LDFLAGS" >&6;}
+       fi
+
+       if test "x$LIBNETAPP_LIBS" = "x"
+       then
+               LIBNETAPP_LIBS="-lpthread -lxml -ladt -lssl -lm -lcrypto -lz"
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: netapp LIBS: $LIBNETAPP_LIBS" >&5
+$as_echo "$as_me: netapp LIBS: $LIBNETAPP_LIBS" >&6;}
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for na_server_invoke_elem in -lnetapp" >&5
+$as_echo_n "checking for na_server_invoke_elem in -lnetapp... " >&6; }
+if ${ac_cv_lib_netapp_na_server_invoke_elem+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetapp $LIBNETAPP_LIBS $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char na_server_invoke_elem ();
+int
+main ()
+{
+return na_server_invoke_elem ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_netapp_na_server_invoke_elem=yes
+else
+  ac_cv_lib_netapp_na_server_invoke_elem=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netapp_na_server_invoke_elem" >&5
+$as_echo "$ac_cv_lib_netapp_na_server_invoke_elem" >&6; }
+if test "x$ac_cv_lib_netapp_na_server_invoke_elem" = xyes; then :
+  with_libnetapp="yes"
+else
+  with_libnetapp="no (symbol na_server_invoke_elem not found)"
+fi
+
+       LIBNETAPP_LIBS="-lnetapp $LIBNETAPP_LIBS"
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libnetapp" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBNETAPP 1" >>confdefs.h
+
+fi
+
+
+
+
+ if test "x$with_libnetapp" = "xyes"; then
+  BUILD_WITH_LIBNETAPP_TRUE=
+  BUILD_WITH_LIBNETAPP_FALSE='#'
+else
+  BUILD_WITH_LIBNETAPP_TRUE='#'
+  BUILD_WITH_LIBNETAPP_FALSE=
+fi
+
+# }}}
+
+# --with-libnetsnmp {{{
+with_snmp_config="net-snmp-config"
+with_snmp_cflags=""
+with_snmp_libs=""
+
+# Check whether --with-libnetsnmp was given.
+if test "${with_libnetsnmp+set}" = set; then :
+  withval=$with_libnetsnmp;
+       if test "x$withval" = "xno"
+       then
+               with_libnetsnmp="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libnetsnmp="yes"
+       else
+               if test -x "$withval"
+               then
+                       with_snmp_config="$withval"
+                       with_libnetsnmp="yes"
+               else
+                       with_snmp_config="$withval/bin/net-snmp-config"
+                       with_libnetsnmp="yes"
+               fi
+       fi; fi
+
+else
+  with_libnetsnmp="yes"
+fi
+
+if test "x$with_libnetsnmp" = "xyes"
+then
+       with_snmp_cflags=`$with_snmp_config --cflags 2>/dev/null`
+       snmp_config_status=$?
+
+       if test $snmp_config_status -ne 0
+       then
+               with_libnetsnmp="no ($with_snmp_config failed)"
+       else
+               SAVE_CPPFLAGS="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $with_snmp_cflags"
+
+               for ac_header in net-snmp/net-snmp-config.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "net-snmp/net-snmp-config.h" "ac_cv_header_net_snmp_net_snmp_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_snmp_net_snmp_config_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_SNMP_NET_SNMP_CONFIG_H 1
+_ACEOF
+
+else
+  with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"
+fi
+
+done
+
+
+               CPPFLAGS="$SAVE_CPPFLAGS"
+       fi
+fi
+if test "x$with_libnetsnmp" = "xyes"
+then
+       with_snmp_libs=`$with_snmp_config --libs 2>/dev/null`
+       snmp_config_status=$?
+
+       if test $snmp_config_status -ne 0
+       then
+               with_libnetsnmp="no ($with_snmp_config failed)"
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init_snmp in -lnetsnmp" >&5
+$as_echo_n "checking for init_snmp in -lnetsnmp... " >&6; }
+if ${ac_cv_lib_netsnmp_init_snmp+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetsnmp $with_snmp_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char init_snmp ();
+int
+main ()
+{
+return init_snmp ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_netsnmp_init_snmp=yes
+else
+  ac_cv_lib_netsnmp_init_snmp=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_netsnmp_init_snmp" >&5
+$as_echo "$ac_cv_lib_netsnmp_init_snmp" >&6; }
+if test "x$ac_cv_lib_netsnmp_init_snmp" = xyes; then :
+  with_libnetsnmp="yes"
+else
+  with_libnetsnmp="no (libnetsnmp not found)"
+fi
+
+       fi
+fi
+if test "x$with_libnetsnmp" = "xyes"
+then
+       BUILD_WITH_LIBSNMP_CFLAGS="$with_snmp_cflags"
+       BUILD_WITH_LIBSNMP_LIBS="$with_snmp_libs"
+
+
+fi
+ if test "x$with_libnetsnmp" = "xyes"; then
+  BUILD_WITH_LIBNETSNMP_TRUE=
+  BUILD_WITH_LIBNETSNMP_FALSE='#'
+else
+  BUILD_WITH_LIBNETSNMP_TRUE='#'
+  BUILD_WITH_LIBNETSNMP_FALSE=
+fi
+
+# }}}
+
+# --with-liboconfig {{{
+with_own_liboconfig="no"
+liboconfig_LDFLAGS="$LDFLAGS"
+liboconfig_CPPFLAGS="$CPPFLAGS"
+
+# Check whether --with-liboconfig was given.
+if test "${with_liboconfig+set}" = set; then :
+  withval=$with_liboconfig;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               if test -d "$withval/lib"
+               then
+                       liboconfig_LDFLAGS="$LDFLAGS -L$withval/lib"
+               fi
+               if test -d "$withval/include"
+               then
+                       liboconfig_CPPFLAGS="$CPPFLAGS -I$withval/include"
+               fi
+       fi
+       if test "x$withval" = "xno"
+       then
+               as_fn_error $? "\"liboconfig is required\"" "$LINENO" 5
+       fi
+
+else
+
+       with_liboconfig="yes"
+
+fi
+
+
+save_LDFLAGS="$LDFLAGS"
+save_CPPFLAGS="$CPPFLAGS"
+LDFLAGS="$liboconfig_LDFLAGS"
+CPPFLAGS="$liboconfig_CPPFLAGS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for oconfig_parse_fh in -loconfig" >&5
+$as_echo_n "checking for oconfig_parse_fh in -loconfig... " >&6; }
+if ${ac_cv_lib_oconfig_oconfig_parse_fh+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-loconfig  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char oconfig_parse_fh ();
+int
+main ()
+{
+return oconfig_parse_fh ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_oconfig_oconfig_parse_fh=yes
+else
+  ac_cv_lib_oconfig_oconfig_parse_fh=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_oconfig_oconfig_parse_fh" >&5
+$as_echo "$ac_cv_lib_oconfig_oconfig_parse_fh" >&6; }
+if test "x$ac_cv_lib_oconfig_oconfig_parse_fh" = xyes; then :
+
+       with_liboconfig="yes"
+       with_own_liboconfig="no"
+
+else
+
+       with_liboconfig="yes"
+       with_own_liboconfig="yes"
+       LDFLAGS="$save_LDFLAGS"
+       CPPFLAGS="$save_CPPFLAGS"
+
+fi
+
+
+ if test "x$with_own_liboconfig" = "xyes"; then
+  BUILD_WITH_OWN_LIBOCONFIG_TRUE=
+  BUILD_WITH_OWN_LIBOCONFIG_FALSE='#'
+else
+  BUILD_WITH_OWN_LIBOCONFIG_TRUE='#'
+  BUILD_WITH_OWN_LIBOCONFIG_FALSE=
+fi
+
+if test "x$with_own_liboconfig" = "xyes"
+then
+       with_liboconfig="yes (shipped version)"
+fi
+# }}}
+
+# --with-liboping {{{
+
+# Check whether --with-liboping was given.
+if test "${with_liboping+set}" = set; then :
+  withval=$with_liboping;
+ if test "x$withval" = "xyes"
+ then
+        with_liboping="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_liboping="no"
+ else
+        with_liboping="yes"
+        LIBOPING_CPPFLAGS="$LIBOPING_CPPFLAGS -I$withval/include"
+        LIBOPING_LDFLAGS="$LIBOPING_LDFLAGS -L$withval/lib"
+ fi; fi
+
+else
+  with_liboping="yes"
+fi
+
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBOPING_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBOPING_LDFLAGS"
+
+if test "x$with_liboping" = "xyes"
+then
+       if test "x$LIBOPING_CPPFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: liboping CPPFLAGS: $LIBOPING_CPPFLAGS" >&5
+$as_echo "$as_me: liboping CPPFLAGS: $LIBOPING_CPPFLAGS" >&6;}
+       fi
+       for ac_header in oping.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "oping.h" "ac_cv_header_oping_h" "$ac_includes_default"
+if test "x$ac_cv_header_oping_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_OPING_H 1
+_ACEOF
+ with_liboping="yes"
+else
+  with_liboping="no (oping.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_liboping" = "xyes"
+then
+       if test "x$LIBOPING_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: liboping LDFLAGS: $LIBOPING_LDFLAGS" >&5
+$as_echo "$as_me: liboping LDFLAGS: $LIBOPING_LDFLAGS" >&6;}
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ping_construct in -loping" >&5
+$as_echo_n "checking for ping_construct in -loping... " >&6; }
+if ${ac_cv_lib_oping_ping_construct+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-loping  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ping_construct ();
+int
+main ()
+{
+return ping_construct ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_oping_ping_construct=yes
+else
+  ac_cv_lib_oping_ping_construct=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_oping_ping_construct" >&5
+$as_echo "$ac_cv_lib_oping_ping_construct" >&6; }
+if test "x$ac_cv_lib_oping_ping_construct" = xyes; then :
+  with_liboping="yes"
+else
+  with_liboping="no (symbol 'ping_construct' not found)"
+fi
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_liboping" = "xyes"
+then
+       BUILD_WITH_LIBOPING_CPPFLAGS="$LIBOPING_CPPFLAGS"
+       BUILD_WITH_LIBOPING_LDFLAGS="$LIBOPING_LDFLAGS"
+
+
+fi
+ if test "x$with_liboping" = "xyes"; then
+  BUILD_WITH_LIBOPING_TRUE=
+  BUILD_WITH_LIBOPING_FALSE='#'
+else
+  BUILD_WITH_LIBOPING_TRUE='#'
+  BUILD_WITH_LIBOPING_FALSE=
+fi
+
+# }}}
+
+# --with-oracle {{{
+with_oracle_cppflags=""
+with_oracle_libs=""
+
+# Check whether --with-oracle was given.
+if test "${with_oracle+set}" = set; then :
+  withval=$with_oracle;
+       if test "x$withval" = "xyes"
+       then
+               if test "x$ORACLE_HOME" = "x"
+               then
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Use of the Oracle library has been forced, but the environment variable ORACLE_HOME is not set." >&5
+$as_echo "$as_me: WARNING: Use of the Oracle library has been forced, but the environment variable ORACLE_HOME is not set." >&2;}
+               fi
+               with_oracle="yes"
+       else if test "x$withval" = "xno"
+       then
+               with_oracle="no"
+       else
+               with_oracle="yes"
+               ORACLE_HOME="$withval"
+       fi; fi
+
+else
+
+       if test "x$ORACLE_HOME" = "x"
+       then
+               with_oracle="no (ORACLE_HOME is not set)"
+       else
+               with_oracle="yes"
+       fi
+
+fi
+
+if test "x$ORACLE_HOME" != "x"
+then
+       with_oracle_cppflags="-I$ORACLE_HOME/rdbms/public"
+
+       if test -e "$ORACLE_HOME/lib/ldflags"
+       then
+               with_oracle_libs=`cat "$ORACLE_HOME/lib/ldflags"`
+       fi
+       #with_oracle_libs="-L$ORACLE_HOME/lib $with_oracle_libs -lclntsh"
+       with_oracle_libs="-L$ORACLE_HOME/lib -lclntsh"
+fi
+if test "x$with_oracle" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_oracle_cppflags"
+
+       for ac_header in oci.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "oci.h" "ac_cv_header_oci_h" "$ac_includes_default"
+if test "x$ac_cv_header_oci_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_OCI_H 1
+_ACEOF
+ with_oracle="yes"
+else
+  with_oracle="no (oci.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_oracle" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LIBS="$LIBS"
+       CPPFLAGS="$CPPFLAGS $with_oracle_cppflags"
+       LIBS="$LIBS $with_oracle_libs"
+
+       ac_fn_c_check_func "$LINENO" "OCIEnvCreate" "ac_cv_func_OCIEnvCreate"
+if test "x$ac_cv_func_OCIEnvCreate" = xyes; then :
+  with_oracle="yes"
+else
+  with_oracle="no (Symbol 'OCIEnvCreate' not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+if test "x$with_oracle" = "xyes"
+then
+       BUILD_WITH_ORACLE_CFLAGS="$with_oracle_cppflags"
+       BUILD_WITH_ORACLE_LIBS="$with_oracle_libs"
+
+
+fi
+# }}}
+
+# --with-libowcapi {{{
+with_libowcapi_cppflags=""
+with_libowcapi_libs="-lowcapi"
+
+# Check whether --with-libowcapi was given.
+if test "${with_libowcapi+set}" = set; then :
+  withval=$with_libowcapi;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libowcapi_cppflags="-I$withval/include"
+               with_libowcapi_libs="-L$withval/lib -lowcapi"
+               with_libowcapi="yes"
+       else
+               with_libowcapi="$withval"
+       fi
+
+else
+
+       with_libowcapi="yes"
+
+fi
+
+if test "x$with_libowcapi" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$with_libowcapi_cppflags"
+
+       for ac_header in owcapi.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "owcapi.h" "ac_cv_header_owcapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_owcapi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_OWCAPI_H 1
+_ACEOF
+ with_libowcapi="yes"
+else
+  with_libowcapi="no (owcapi.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libowcapi" = "xyes"
+then
+       SAVE_LDFLAGS="$LDFLAGS"
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       LDFLAGS="$with_libowcapi_libs"
+       CPPFLAGS="$with_libowcapi_cppflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OW_get in -lowcapi" >&5
+$as_echo_n "checking for OW_get in -lowcapi... " >&6; }
+if ${ac_cv_lib_owcapi_OW_get+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lowcapi  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char OW_get ();
+int
+main ()
+{
+return OW_get ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_owcapi_OW_get=yes
+else
+  ac_cv_lib_owcapi_OW_get=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_owcapi_OW_get" >&5
+$as_echo "$ac_cv_lib_owcapi_OW_get" >&6; }
+if test "x$ac_cv_lib_owcapi_OW_get" = xyes; then :
+  with_libowcapi="yes"
+else
+  with_libowcapi="no (libowcapi not found)"
+fi
+
+
+       LDFLAGS="$SAVE_LDFLAGS"
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libowcapi" = "xyes"
+then
+       BUILD_WITH_LIBOWCAPI_CPPFLAGS="$with_libowcapi_cppflags"
+       BUILD_WITH_LIBOWCAPI_LIBS="$with_libowcapi_libs"
+
+
+fi
+# }}}
+
+# --with-libpcap {{{
+
+# Check whether --with-libpcap was given.
+if test "${with_libpcap+set}" = set; then :
+  withval=$with_libpcap;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               with_libpcap="yes"
+       else
+               with_libpcap="$withval"
+       fi
+
+else
+
+       with_libpcap="yes"
+
+fi
+
+if test "x$with_libpcap" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_live in -lpcap" >&5
+$as_echo_n "checking for pcap_open_live in -lpcap... " >&6; }
+if ${ac_cv_lib_pcap_pcap_open_live+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcap_open_live ();
+int
+main ()
+{
+return pcap_open_live ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pcap_pcap_open_live=yes
+else
+  ac_cv_lib_pcap_pcap_open_live=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_open_live" >&5
+$as_echo "$ac_cv_lib_pcap_pcap_open_live" >&6; }
+if test "x$ac_cv_lib_pcap_pcap_open_live" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBPCAP 1" >>confdefs.h
+
+
+else
+  with_libpcap="no (libpcap not found)"
+fi
+
+fi
+if test "x$with_libpcap" = "xyes"
+then
+       for ac_header in pcap.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcap_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PCAP_H 1
+_ACEOF
+
+else
+  with_libpcap="no (pcap.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_libpcap" = "xyes"
+then
+       for ac_header in pcap-bpf.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "pcap-bpf.h" "ac_cv_header_pcap_bpf_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcap_bpf_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PCAP_BPF_H 1
+_ACEOF
+
+else
+  with_libpcap="no (pcap-bpf.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_libpcap" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libpcap has PCAP_ERROR_IFACE_NOT_UP" >&5
+$as_echo_n "checking whether libpcap has PCAP_ERROR_IFACE_NOT_UP... " >&6; }
+if ${c_cv_libpcap_have_pcap_error_iface_not_up+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <pcap.h>
+
+int
+main ()
+{
+
+  int val = PCAP_ERROR_IFACE_NOT_UP;
+  return(val);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  c_cv_libpcap_have_pcap_error_iface_not_up="yes"
+else
+  c_cv_libpcap_have_pcap_error_iface_not_up="no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_libpcap_have_pcap_error_iface_not_up" >&5
+$as_echo "$c_cv_libpcap_have_pcap_error_iface_not_up" >&6; }
+fi
+if test "x$c_cv_libpcap_have_pcap_error_iface_not_up" != "xyes"
+then
+               with_libpcap="no (pcap.h misses PCAP_ERROR_IFACE_NOT_UP)"
+fi
+ if test "x$with_libpcap" = "xyes"; then
+  BUILD_WITH_LIBPCAP_TRUE=
+  BUILD_WITH_LIBPCAP_FALSE='#'
+else
+  BUILD_WITH_LIBPCAP_TRUE='#'
+  BUILD_WITH_LIBPCAP_FALSE=
+fi
+
+# }}}
+
+# --with-libperl {{{
+perl_interpreter="perl"
+
+# Check whether --with-libperl was given.
+if test "${with_libperl+set}" = set; then :
+  withval=$with_libperl;
+       if test -f "$withval" && test -x "$withval"
+       then
+               perl_interpreter="$withval"
+               with_libperl="yes"
+       else if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               perl_interpreter="$withval/bin/perl"
+               with_libperl="yes"
+       else
+               with_libperl="$withval"
+       fi; fi
+
+else
+
+       with_libperl="yes"
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl" >&5
+$as_echo_n "checking for perl... " >&6; }
+perl_interpreter=`which "$perl_interpreter" 2> /dev/null`
+if test -x "$perl_interpreter"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($perl_interpreter)" >&5
+$as_echo "yes ($perl_interpreter)" >&6; }
+else
+       perl_interpreter=""
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+PERL="$perl_interpreter"
+
+
+if test "x$with_libperl" = "xyes" \
+       && test -n "$perl_interpreter"
+then
+  SAVE_CFLAGS="$CFLAGS"
+  SAVE_LIBS="$LIBS"
+  PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ccopts`
+  PERL_LIBS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts`
+  CFLAGS="$CFLAGS $PERL_CFLAGS"
+  LIBS="$LIBS $PERL_LIBS"
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libperl" >&5
+$as_echo_n "checking for libperl... " >&6; }
+if ${c_cv_have_libperl+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#define PERL_NO_GET_CONTEXT
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+int
+main ()
+{
+
+       dTHX;
+       load_module (PERL_LOADMOD_NOIMPORT,
+                        newSVpv ("Collectd::Plugin::FooBar", 24),
+                        Nullsv);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  c_cv_have_libperl="yes"
+else
+  c_cv_have_libperl="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_libperl" >&5
+$as_echo "$c_cv_have_libperl" >&6; }
+
+  if test "x$c_cv_have_libperl" = "xyes"
+  then
+
+$as_echo "#define HAVE_LIBPERL 1" >>confdefs.h
+
+
+
+  else
+         with_libperl="no"
+  fi
+
+  CFLAGS="$SAVE_CFLAGS"
+  LIBS="$SAVE_LIBS"
+else if test -z "$perl_interpreter"; then
+  with_libperl="no (no perl interpreter found)"
+  c_cv_have_libperl="no"
+fi; fi
+ if test "x$with_libperl" = "xyes"; then
+  BUILD_WITH_LIBPERL_TRUE=
+  BUILD_WITH_LIBPERL_FALSE='#'
+else
+  BUILD_WITH_LIBPERL_TRUE='#'
+  BUILD_WITH_LIBPERL_FALSE=
+fi
+
+
+if test "x$with_libperl" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LIBS="$LIBS"
+       CFLAGS="$CFLAGS $PERL_CFLAGS"
+       LIBS="$LIBS $PERL_LIBS"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking if perl supports ithreads" >&5
+$as_echo_n "checking if perl supports ithreads... " >&6; }
+if ${c_cv_have_perl_ithreads+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+#if !defined(USE_ITHREADS)
+# error "Perl does not support ithreads!"
+#endif /* !defined(USE_ITHREADS) */
+
+int
+main ()
+{
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  c_cv_have_perl_ithreads="yes"
+else
+  c_cv_have_perl_ithreads="no"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_perl_ithreads" >&5
+$as_echo "$c_cv_have_perl_ithreads" >&6; }
+
+       if test "x$c_cv_have_perl_ithreads" = "xyes"
+       then
+
+$as_echo "#define HAVE_PERL_ITHREADS 1" >>confdefs.h
+
+       fi
+
+       CFLAGS="$SAVE_CFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+
+if test "x$with_libperl" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LIBS="$LIBS"
+       # trigger an error if Perl_load_module*() uses __attribute__nonnull__(3)
+       # (see issues #41 and #42)
+       CFLAGS="$CFLAGS $PERL_CFLAGS -Wall -Werror"
+       LIBS="$LIBS $PERL_LIBS"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken Perl_load_module()" >&5
+$as_echo_n "checking for broken Perl_load_module()... " >&6; }
+if ${c_cv_have_broken_perl_load_module+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#define PERL_NO_GET_CONTEXT
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+int
+main ()
+{
+
+                        dTHX;
+                        load_module (PERL_LOADMOD_NOIMPORT,
+                            newSVpv ("Collectd::Plugin::FooBar", 24),
+                            Nullsv);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  c_cv_have_broken_perl_load_module="no"
+else
+  c_cv_have_broken_perl_load_module="yes"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_broken_perl_load_module" >&5
+$as_echo "$c_cv_have_broken_perl_load_module" >&6; }
+
+       CFLAGS="$SAVE_CFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+ if test "x$c_cv_have_broken_perl_load_module" = "xyes"; then
+  HAVE_BROKEN_PERL_LOAD_MODULE_TRUE=
+  HAVE_BROKEN_PERL_LOAD_MODULE_FALSE='#'
+else
+  HAVE_BROKEN_PERL_LOAD_MODULE_TRUE='#'
+  HAVE_BROKEN_PERL_LOAD_MODULE_FALSE=
+fi
+
+
+if test "x$with_libperl" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LIBS="$LIBS"
+       CFLAGS="$CFLAGS $PERL_CFLAGS"
+       LIBS="$LIBS $PERL_LIBS"
+
+       ac_fn_c_check_member "$LINENO" "struct mgvtbl" "svt_local" "ac_cv_member_struct_mgvtbl_svt_local" "
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+"
+if test "x$ac_cv_member_struct_mgvtbl_svt_local" = xyes; then :
+  have_struct_mgvtbl_svt_local="yes"
+else
+  have_struct_mgvtbl_svt_local="no"
+fi
+
+
+       if test "x$have_struct_mgvtbl_svt_local" = "xyes"
+       then
+
+$as_echo "#define HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL 1" >>confdefs.h
+
+       fi
+
+       CFLAGS="$SAVE_CFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+# }}}
+
+# --with-libpq {{{
+with_pg_config="pg_config"
+with_libpq_includedir=""
+with_libpq_libdir=""
+with_libpq_cppflags=""
+with_libpq_ldflags=""
+
+# Check whether --with-libpq was given.
+if test "${with_libpq+set}" = set; then :
+  withval=$with_libpq;
+       if test "x$withval" = "xno"
+       then
+               with_libpq="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libpq="yes"
+       else
+               if test -f "$withval" && test -x "$withval";
+               then
+                       with_pg_config="$withval"
+               else if test -x "$withval/bin/pg_config"
+               then
+                       with_pg_config="$withval/bin/pg_config"
+               fi; fi
+               with_libpq="yes"
+       fi; fi
+
+else
+
+       with_libpq="yes"
+
+fi
+
+if test "x$with_libpq" = "xyes"
+then
+       with_libpq_includedir=`$with_pg_config --includedir 2> /dev/null`
+       pg_config_status=$?
+
+       if test $pg_config_status -eq 0
+       then
+               if test -n "$with_libpq_includedir"; then
+                       for dir in $with_libpq_includedir; do
+                               with_libpq_cppflags="$with_libpq_cppflags -I$dir"
+                       done
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $with_pg_config returned with status $pg_config_status" >&5
+$as_echo "$as_me: WARNING: $with_pg_config returned with status $pg_config_status" >&2;}
+       fi
+
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libpq_cppflags"
+
+       for ac_header in libpq-fe.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libpq-fe.h" "ac_cv_header_libpq_fe_h" "$ac_includes_default"
+if test "x$ac_cv_header_libpq_fe_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPQ_FE_H 1
+_ACEOF
+
+else
+  with_libpq="no (libpq-fe.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libpq" = "xyes"
+then
+       with_libpq_libdir=`$with_pg_config --libdir 2> /dev/null`
+       pg_config_status=$?
+
+       if test $pg_config_status -eq 0
+       then
+               if test -n "$with_libpq_libdir"; then
+                       for dir in $with_libpq_libdir; do
+                               with_libpq_ldflags="$with_libpq_ldflags -L$dir"
+                       done
+               fi
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $with_pg_config returned with status $pg_config_status" >&5
+$as_echo "$as_me: WARNING: $with_pg_config returned with status $pg_config_status" >&2;}
+       fi
+
+       SAVE_LDFLAGS="$LDFLAGS"
+       LDFLAGS="$LDFLAGS $with_libpq_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQconnectdb in -lpq" >&5
+$as_echo_n "checking for PQconnectdb in -lpq... " >&6; }
+if ${ac_cv_lib_pq_PQconnectdb+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpq  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char PQconnectdb ();
+int
+main ()
+{
+return PQconnectdb ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pq_PQconnectdb=yes
+else
+  ac_cv_lib_pq_PQconnectdb=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQconnectdb" >&5
+$as_echo "$ac_cv_lib_pq_PQconnectdb" >&6; }
+if test "x$ac_cv_lib_pq_PQconnectdb" = xyes; then :
+  with_libpq="yes"
+else
+  with_libpq="no (symbol 'PQconnectdb' not found)"
+fi
+
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQserverVersion in -lpq" >&5
+$as_echo_n "checking for PQserverVersion in -lpq... " >&6; }
+if ${ac_cv_lib_pq_PQserverVersion+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpq  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char PQserverVersion ();
+int
+main ()
+{
+return PQserverVersion ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pq_PQserverVersion=yes
+else
+  ac_cv_lib_pq_PQserverVersion=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQserverVersion" >&5
+$as_echo "$ac_cv_lib_pq_PQserverVersion" >&6; }
+if test "x$ac_cv_lib_pq_PQserverVersion" = xyes; then :
+  with_libpq="yes"
+else
+  with_libpq="no (symbol 'PQserverVersion' not found)"
+fi
+
+
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libpq" = "xyes"
+then
+       BUILD_WITH_LIBPQ_CPPFLAGS="$with_libpq_cppflags"
+       BUILD_WITH_LIBPQ_LDFLAGS="$with_libpq_ldflags"
+
+
+fi
+ if test "x$with_libpq" = "xyes"; then
+  BUILD_WITH_LIBPQ_TRUE=
+  BUILD_WITH_LIBPQ_FALSE='#'
+else
+  BUILD_WITH_LIBPQ_TRUE='#'
+  BUILD_WITH_LIBPQ_FALSE=
+fi
+
+# }}}
+
+# --with-libpthread {{{
+
+# Check whether --with-libpthread was given.
+if test "${with_libpthread+set}" = set; then :
+  withval=$with_libpthread;    if test "x$withval" != "xno" \
+               && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               with_libpthread="yes"
+       else
+               if test "x$withval" = "xno"
+               then
+                       with_libpthread="no (disabled)"
+               fi
+       fi
+
+else
+  with_libpthread="yes"
+fi
+
+if test "x$with_libpthread" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_create+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_pthread_pthread_create=yes
+else
+  ac_cv_lib_pthread_pthread_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+  with_libpthread="yes"
+else
+  with_libpthread="no (libpthread not found)"
+fi
+
+fi
+
+if test "x$with_libpthread" = "xyes"
+then
+       for ac_header in pthread.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PTHREAD_H 1
+_ACEOF
+
+else
+  with_libpthread="no (pthread.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_libpthread" = "xyes"
+then
+       collect_pthread=1
+else
+       collect_pthread=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD $collect_pthread
+_ACEOF
+
+ if test "x$with_libpthread" = "xyes"; then
+  BUILD_WITH_LIBPTHREAD_TRUE=
+  BUILD_WITH_LIBPTHREAD_FALSE='#'
+else
+  BUILD_WITH_LIBPTHREAD_TRUE='#'
+  BUILD_WITH_LIBPTHREAD_FALSE=
+fi
+
+# }}}
+
+# --with-python {{{
+with_python_prog=""
+with_python_path="$PATH"
+
+# Check whether --with-python was given.
+if test "${with_python+set}" = set; then :
+  withval=$with_python;
+ if test "x$withval" = "xyes" || test "x$withval" = "xno"
+ then
+        with_python="$withval"
+ else if test -x "$withval"
+ then
+        with_python_prog="$withval"
+        with_python_path="`dirname \"$withval\"`$PATH_SEPARATOR$with_python_path"
+        with_python="yes"
+ else if test -d "$withval"
+ then
+        with_python_path="$withval$PATH_SEPARATOR$with_python_path"
+        with_python="yes"
+ else
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Argument not recognized: $withval" >&5
+$as_echo "$as_me: WARNING: Argument not recognized: $withval" >&2;}
+ fi; fi; fi
+
+else
+  with_python="yes"
+fi
+
+
+SAVE_PATH="$PATH"
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
+
+PATH="$with_python_path"
+
+if test "x$with_python" = "xyes" && test "x$with_python_prog" = "x"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for python" >&5
+$as_echo_n "checking for python... " >&6; }
+       with_python_prog="`which python 2>/dev/null`"
+       if test "x$with_python_prog" = "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+               with_python="no (interpreter not found)"
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_python_prog" >&5
+$as_echo "$with_python_prog" >&6; }
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python CPPFLAGS" >&5
+$as_echo_n "checking for Python CPPFLAGS... " >&6; }
+       python_include_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_python_inc())" | "$with_python_prog" 2>&1`
+       python_config_status=$?
+
+       if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed with status $python_config_status (output: $python_include_path)" >&5
+$as_echo "failed with status $python_config_status (output: $python_include_path)" >&6; }
+               with_python="no"
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $python_include_path" >&5
+$as_echo "$python_include_path" >&6; }
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       CPPFLAGS="-I$python_include_path $CPPFLAGS"
+       for ac_header in Python.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "Python.h" "ac_cv_header_Python_h" "$ac_includes_default"
+if test "x$ac_cv_header_Python_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PYTHON_H 1
+_ACEOF
+ with_python="yes"
+else
+  with_python="no ('Python.h' not found)"
+fi
+
+done
+
+fi
+
+if test "x$with_python" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python LDFLAGS" >&5
+$as_echo_n "checking for Python LDFLAGS... " >&6; }
+       python_library_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0))" | "$with_python_prog" 2>&1`
+       python_config_status=$?
+
+       if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed with status $python_config_status (output: $python_library_path)" >&5
+$as_echo "failed with status $python_config_status (output: $python_library_path)" >&6; }
+               with_python="no"
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $python_library_path" >&5
+$as_echo "$python_library_path" >&6; }
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python LIBS" >&5
+$as_echo_n "checking for Python LIBS... " >&6; }
+       python_library_flags=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0))" | "$with_python_prog" 2>&1`
+       python_config_status=$?
+
+       if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed with status $python_config_status (output: $python_library_flags)" >&5
+$as_echo "failed with status $python_config_status (output: $python_library_flags)" >&6; }
+               with_python="no"
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $python_library_flags" >&5
+$as_echo "$python_library_flags" >&6; }
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       LDFLAGS="-L$python_library_path $LDFLAGS"
+       LIBS="$python_library_flags $LIBS"
+
+       ac_fn_c_check_func "$LINENO" "PyObject_CallFunction" "ac_cv_func_PyObject_CallFunction"
+if test "x$ac_cv_func_PyObject_CallFunction" = xyes; then :
+  with_python="yes"
+else
+  with_python="no (Symbol 'PyObject_CallFunction' not found)"
+fi
+
+fi
+
+PATH="$SAVE_PATH"
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
+
+if test "x$with_python" = "xyes"
+then
+       BUILD_WITH_PYTHON_CPPFLAGS="-I$python_include_path"
+       BUILD_WITH_PYTHON_LDFLAGS="-L$python_library_path"
+       BUILD_WITH_PYTHON_LIBS="$python_library_flags"
+
+
+
+fi
+# }}} --with-python
+
+# --with-librabbitmq {{{
+with_librabbitmq_cppflags=""
+with_librabbitmq_ldflags=""
+
+# Check whether --with-librabbitmq was given.
+if test "${with_librabbitmq+set}" = set; then :
+  withval=$with_librabbitmq;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_librabbitmq_cppflags="-I$withval/include"
+               with_librabbitmq_ldflags="-L$withval/lib"
+               with_librabbitmq="yes"
+       else
+               with_librabbitmq="$withval"
+       fi
+
+else
+
+       with_librabbitmq="yes"
+
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags"
+LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags"
+if test "x$with_librabbitmq" = "xyes"
+then
+       for ac_header in amqp.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "amqp.h" "ac_cv_header_amqp_h" "$ac_includes_default"
+if test "x$ac_cv_header_amqp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_AMQP_H 1
+_ACEOF
+ with_librabbitmq="yes"
+else
+  with_librabbitmq="no (amqp.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_librabbitmq" = "xyes"
+then
+       # librabbitmq up to version 0.9.1 provides "library_errno", later
+       # versions use "library_error". The library does not provide a version
+       # macro :( Use "AC_CHECK_MEMBERS" (plural) for automatic defines.
+       ac_fn_c_check_member "$LINENO" "amqp_rpc_reply_t" "library_errno" "ac_cv_member_amqp_rpc_reply_t_library_errno" "
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_STDIO_H
+# include <stdio.h>
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <amqp.h>
+
+"
+if test "x$ac_cv_member_amqp_rpc_reply_t_library_errno" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO 1
+_ACEOF
+
+
+fi
+
+fi
+if test "x$with_librabbitmq" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for amqp_basic_publish in -lrabbitmq" >&5
+$as_echo_n "checking for amqp_basic_publish in -lrabbitmq... " >&6; }
+if ${ac_cv_lib_rabbitmq_amqp_basic_publish+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrabbitmq  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char amqp_basic_publish ();
+int
+main ()
+{
+return amqp_basic_publish ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rabbitmq_amqp_basic_publish=yes
+else
+  ac_cv_lib_rabbitmq_amqp_basic_publish=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rabbitmq_amqp_basic_publish" >&5
+$as_echo "$ac_cv_lib_rabbitmq_amqp_basic_publish" >&6; }
+if test "x$ac_cv_lib_rabbitmq_amqp_basic_publish" = xyes; then :
+  with_librabbitmq="yes"
+else
+  with_librabbitmq="no (Symbol 'amqp_basic_publish' not found)"
+fi
+
+fi
+if test "x$with_librabbitmq" = "xyes"
+then
+       BUILD_WITH_LIBRABBITMQ_CPPFLAGS="$with_librabbitmq_cppflags"
+       BUILD_WITH_LIBRABBITMQ_LDFLAGS="$with_librabbitmq_ldflags"
+       BUILD_WITH_LIBRABBITMQ_LIBS="-lrabbitmq"
+
+
+
+
+$as_echo "#define HAVE_LIBRABBITMQ 1" >>confdefs.h
+
+fi
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+ if test "x$with_librabbitmq" = "xyes"; then
+  BUILD_WITH_LIBRABBITMQ_TRUE=
+  BUILD_WITH_LIBRABBITMQ_FALSE='#'
+else
+  BUILD_WITH_LIBRABBITMQ_TRUE='#'
+  BUILD_WITH_LIBRABBITMQ_FALSE=
+fi
+
+
+with_amqp_tcp_socket="no"
+if test "x$with_librabbitmq" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       SAVE_LIBS="$LIBS"
+       CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags"
+       LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags"
+       LIBS="-lrabbitmq"
+
+       for ac_header in amqp_tcp_socket.h amqp_socket.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+       ac_fn_c_check_func "$LINENO" "amqp_tcp_socket_new" "ac_cv_func_amqp_tcp_socket_new"
+if test "x$ac_cv_func_amqp_tcp_socket_new" = xyes; then :
+  with_amqp_tcp_socket="yes"
+else
+  with_amqp_tcp_socket="no"
+fi
+
+       if test "x$with_amqp_tcp_socket" = "xyes"
+       then
+
+$as_echo "#define HAVE_AMQP_TCP_SOCKET 1" >>confdefs.h
+
+       fi
+
+       ac_fn_c_check_decl "$LINENO" "amqp_socket_close" "ac_cv_have_decl_amqp_socket_close" "
+#include <amqp.h>
+#ifdef HAVE_AMQP_TCP_SOCKET_H
+# include <amqp_tcp_socket.h>
+#endif
+#ifdef HAVE_AMQP_SOCKET_H
+# include <amqp_socket.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl_amqp_socket_close" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_AMQP_SOCKET_CLOSE $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+  amqp_socket_close_decl="yes"
+else
+  amqp_socket_close_decl="no"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+# }}}
+
+# --with-librdkafka {{{
+
+# Check whether --with-librdkafka was given.
+if test "${with_librdkafka+set}" = set; then :
+  withval=$with_librdkafka;
+  if test "x$withval" != "xno" && test "x$withval" != "xyes"
+  then
+    with_librdkafka_cppflags="-I$withval/include"
+    with_librdkafka_ldflags="-L$withval/lib"
+    with_librdkafka_rpath="$withval/lib"
+    with_librdkafka="yes"
+  else
+    with_librdkafka="$withval"
+  fi
+
+else
+
+  with_librdkafka="yes"
+
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $with_librdkafka_cppflags"
+LDFLAGS="$LDFLAGS $with_librdkafka_ldflags"
+
+if test "x$with_librdkafka" = "xyes"
+then
+       for ac_header in librdkafka/rdkafka.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "librdkafka/rdkafka.h" "ac_cv_header_librdkafka_rdkafka_h" "$ac_includes_default"
+if test "x$ac_cv_header_librdkafka_rdkafka_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBRDKAFKA_RDKAFKA_H 1
+_ACEOF
+ with_librdkafka="yes"
+else
+  with_librdkafka="no (librdkafka/rdkafka.h not found)"
+fi
+
+done
+
+fi
+
+if test "x$with_librdkafka" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_new in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_new in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_new+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrdkafka  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rd_kafka_new ();
+int
+main ()
+{
+return rd_kafka_new ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rdkafka_rd_kafka_new=yes
+else
+  ac_cv_lib_rdkafka_rd_kafka_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rdkafka_rd_kafka_new" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_new" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_new" = xyes; then :
+  with_librdkafka="yes"
+else
+  with_librdkafka="no (Symbol 'rd_kafka_new' not found)"
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_conf_set_log_cb in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_conf_set_log_cb in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_conf_set_log_cb+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrdkafka  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rd_kafka_conf_set_log_cb ();
+int
+main ()
+{
+return rd_kafka_conf_set_log_cb ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rdkafka_rd_kafka_conf_set_log_cb=yes
+else
+  ac_cv_lib_rdkafka_rd_kafka_conf_set_log_cb=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rdkafka_rd_kafka_conf_set_log_cb" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_conf_set_log_cb" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_conf_set_log_cb" = xyes; then :
+  with_librdkafka_log_cb="yes"
+else
+  with_librdkafka_log_cb="no"
+fi
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rd_kafka_set_logger in -lrdkafka" >&5
+$as_echo_n "checking for rd_kafka_set_logger in -lrdkafka... " >&6; }
+if ${ac_cv_lib_rdkafka_rd_kafka_set_logger+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrdkafka  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rd_kafka_set_logger ();
+int
+main ()
+{
+return rd_kafka_set_logger ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rdkafka_rd_kafka_set_logger=yes
+else
+  ac_cv_lib_rdkafka_rd_kafka_set_logger=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rdkafka_rd_kafka_set_logger" >&5
+$as_echo "$ac_cv_lib_rdkafka_rd_kafka_set_logger" >&6; }
+if test "x$ac_cv_lib_rdkafka_rd_kafka_set_logger" = xyes; then :
+  with_librdkafka_logger="yes"
+else
+  with_librdkafka_logger="no"
+fi
+
+fi
+if test "x$with_librdkafka" = "xyes"
+then
+       BUILD_WITH_LIBRDKAFKA_CPPFLAGS="$with_librdkafka_cppflags"
+       BUILD_WITH_LIBRDKAFKA_LDFLAGS="$with_librdkafka_ldflags"
+       if test "x$with_librdkafka_rpath" != "x"
+       then
+               BUILD_WITH_LIBRDKAFKA_LIBS="-Wl,-rpath,$with_librdkafka_rpath -lrdkafka"
+       else
+               BUILD_WITH_LIBRDKAFKA_LIBS="-lrdkafka"
+       fi
+
+
+
+
+$as_echo "#define HAVE_LIBRDKAFKA 1" >>confdefs.h
+
+  if test "x$with_librdkafka_log_cb" = "xyes"
+  then
+
+$as_echo "#define HAVE_LIBRDKAFKA_LOG_CB 1" >>confdefs.h
+
+  fi
+  if test "x$with_librdkafka_logger" = "xyes"
+  then
+
+$as_echo "#define HAVE_LIBRDKAFKA_LOGGER 1" >>confdefs.h
+
+  fi
+fi
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+ if test "x$with_librdkafka" = "xyes"; then
+  BUILD_WITH_LIBRDKAFKA_TRUE=
+  BUILD_WITH_LIBRDKAFKA_FALSE='#'
+else
+  BUILD_WITH_LIBRDKAFKA_TRUE='#'
+  BUILD_WITH_LIBRDKAFKA_FALSE=
+fi
+
+
+# }}}
+
+# --with-librouteros {{{
+
+# Check whether --with-librouteros was given.
+if test "${with_librouteros+set}" = set; then :
+  withval=$with_librouteros;
+ if test "x$withval" = "xyes"
+ then
+        with_librouteros="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_librouteros="no"
+ else
+        with_librouteros="yes"
+        LIBROUTEROS_CPPFLAGS="$LIBROUTEROS_CPPFLAGS -I$withval/include"
+        LIBROUTEROS_LDFLAGS="$LIBROUTEROS_LDFLAGS -L$withval/lib"
+ fi; fi
+
+else
+  with_librouteros="yes"
+fi
+
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBROUTEROS_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBROUTEROS_LDFLAGS"
+
+if test "x$with_librouteros" = "xyes"
+then
+       if test "x$LIBROUTEROS_CPPFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: librouteros CPPFLAGS: $LIBROUTEROS_CPPFLAGS" >&5
+$as_echo "$as_me: librouteros CPPFLAGS: $LIBROUTEROS_CPPFLAGS" >&6;}
+       fi
+       for ac_header in routeros_api.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "routeros_api.h" "ac_cv_header_routeros_api_h" "$ac_includes_default"
+if test "x$ac_cv_header_routeros_api_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ROUTEROS_API_H 1
+_ACEOF
+ with_librouteros="yes"
+else
+  with_librouteros="no (routeros_api.h not found)"
+fi
+
+done
+
+fi
+if test "x$with_librouteros" = "xyes"
+then
+       if test "x$LIBROUTEROS_LDFLAGS" != "x"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: librouteros LDFLAGS: $LIBROUTEROS_LDFLAGS" >&5
+$as_echo "$as_me: librouteros LDFLAGS: $LIBROUTEROS_LDFLAGS" >&6;}
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ros_interface in -lrouteros" >&5
+$as_echo_n "checking for ros_interface in -lrouteros... " >&6; }
+if ${ac_cv_lib_routeros_ros_interface+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrouteros  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ros_interface ();
+int
+main ()
+{
+return ros_interface ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_routeros_ros_interface=yes
+else
+  ac_cv_lib_routeros_ros_interface=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_routeros_ros_interface" >&5
+$as_echo "$ac_cv_lib_routeros_ros_interface" >&6; }
+if test "x$ac_cv_lib_routeros_ros_interface" = xyes; then :
+  with_librouteros="yes"
+else
+  with_librouteros="no (symbol 'ros_interface' not found)"
+fi
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_librouteros" = "xyes"
+then
+       BUILD_WITH_LIBROUTEROS_CPPFLAGS="$LIBROUTEROS_CPPFLAGS"
+       BUILD_WITH_LIBROUTEROS_LDFLAGS="$LIBROUTEROS_LDFLAGS"
+
+
+fi
+ if test "x$with_librouteros" = "xyes"; then
+  BUILD_WITH_LIBROUTEROS_TRUE=
+  BUILD_WITH_LIBROUTEROS_FALSE='#'
+else
+  BUILD_WITH_LIBROUTEROS_TRUE='#'
+  BUILD_WITH_LIBROUTEROS_FALSE=
+fi
+
+# }}}
+
+# --with-librrd {{{
+# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
+librrd_cflags=""
+librrd_ldflags=""
+librrd_threadsafe="yes"
+librrd_rrdc_update="no"
+
+# Check whether --with-librrd was given.
+if test "${with_librrd+set}" = set; then :
+  withval=$with_librrd;        if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               librrd_cflags="-I$withval/include"
+               librrd_ldflags="-L$withval/lib"
+               with_librrd="yes"
+       else
+               with_librrd="$withval"
+       fi
+
+else
+  with_librrd="yes"
+fi
+
+if test "x$with_librrd" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $librrd_cflags"
+       LDFLAGS="$LDFLAGS $librrd_ldflags"
+
+       for ac_header in rrd.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "rrd.h" "ac_cv_header_rrd_h" "$ac_includes_default"
+if test "x$ac_cv_header_rrd_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_RRD_H 1
+_ACEOF
+
+else
+  with_librrd="no (rrd.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_librrd" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $librrd_cflags"
+       LDFLAGS="$LDFLAGS $librrd_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rrd_update_r in -lrrd_th" >&5
+$as_echo_n "checking for rrd_update_r in -lrrd_th... " >&6; }
+if ${ac_cv_lib_rrd_th_rrd_update_r+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrrd_th -lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rrd_update_r ();
+int
+main ()
+{
+return rrd_update_r ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rrd_th_rrd_update_r=yes
+else
+  ac_cv_lib_rrd_th_rrd_update_r=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rrd_th_rrd_update_r" >&5
+$as_echo "$ac_cv_lib_rrd_th_rrd_update_r" >&6; }
+if test "x$ac_cv_lib_rrd_th_rrd_update_r" = xyes; then :
+  with_librrd="yes"
+        librrd_ldflags="$librrd_ldflags -lrrd_th -lm"
+
+else
+  librrd_threadsafe="no"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rrd_update in -lrrd" >&5
+$as_echo_n "checking for rrd_update in -lrrd... " >&6; }
+if ${ac_cv_lib_rrd_rrd_update+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrrd -lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rrd_update ();
+int
+main ()
+{
+return rrd_update ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rrd_rrd_update=yes
+else
+  ac_cv_lib_rrd_rrd_update=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rrd_rrd_update" >&5
+$as_echo "$ac_cv_lib_rrd_rrd_update" >&6; }
+if test "x$ac_cv_lib_rrd_rrd_update" = xyes; then :
+  with_librrd="yes"
+         librrd_ldflags="$librrd_ldflags -lrrd -lm"
+
+else
+  with_librrd="no (symbol 'rrd_update' not found)"
+fi
+
+
+fi
+
+
+       if test "x$librrd_threadsafe" = "xyes"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rrdc_update in -lrrd_th" >&5
+$as_echo_n "checking for rrdc_update in -lrrd_th... " >&6; }
+if ${ac_cv_lib_rrd_th_rrdc_update+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrrd_th  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rrdc_update ();
+int
+main ()
+{
+return rrdc_update ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rrd_th_rrdc_update=yes
+else
+  ac_cv_lib_rrd_th_rrdc_update=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rrd_th_rrdc_update" >&5
+$as_echo "$ac_cv_lib_rrd_th_rrdc_update" >&6; }
+if test "x$ac_cv_lib_rrd_th_rrdc_update" = xyes; then :
+  librrd_rrdc_update="yes"
+else
+  librrd_rrdc_update="no"
+fi
+
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rrdc_update in -lrrd" >&5
+$as_echo_n "checking for rrdc_update in -lrrd... " >&6; }
+if ${ac_cv_lib_rrd_rrdc_update+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrrd  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rrdc_update ();
+int
+main ()
+{
+return rrdc_update ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rrd_rrdc_update=yes
+else
+  ac_cv_lib_rrd_rrdc_update=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rrd_rrdc_update" >&5
+$as_echo "$ac_cv_lib_rrd_rrdc_update" >&6; }
+if test "x$ac_cv_lib_rrd_rrdc_update" = xyes; then :
+  librrd_rrdc_update="yes"
+else
+  librrd_rrdc_update="no"
+fi
+
+       fi
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_librrd" = "xyes"
+then
+       BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags"
+       BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags"
+
+
+fi
+if test "x$librrd_threadsafe" = "xyes"
+then
+
+$as_echo "#define HAVE_THREADSAFE_LIBRRD 1" >>confdefs.h
+
+fi
+# }}}
+
+# --with-libsensors {{{
+with_sensors_cflags=""
+with_sensors_ldflags=""
+
+# Check whether --with-libsensors was given.
+if test "${with_libsensors+set}" = set; then :
+  withval=$with_libsensors;
+       if test "x$withval" = "xno"
+       then
+               with_libsensors="no"
+       else
+               with_libsensors="yes"
+               if test "x$withval" != "xyes"
+               then
+                       with_sensors_cflags="-I$withval/include"
+                       with_sensors_ldflags="-L$withval/lib"
+                       with_libsensors="yes"
+               fi
+       fi
+
+else
+
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libsensors="yes"
+       else
+               with_libsensors="no (Linux only library)"
+       fi
+
+fi
+
+if test "x$with_libsensors" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
+
+#      AC_CHECK_HEADERS(sensors/sensors.h,
+#      [
+#              AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the <sensors/sensors.h> header file.])
+#      ],
+#      [with_libsensors="no (sensors/sensors.h not found)"])
+       for ac_header in sensors/sensors.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sensors/sensors.h" "ac_cv_header_sensors_sensors_h" "$ac_includes_default"
+if test "x$ac_cv_header_sensors_sensors_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SENSORS_SENSORS_H 1
+_ACEOF
+
+else
+  with_libsensors="no (sensors/sensors.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libsensors" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
+       LDFLAGS="$LDFLAGS $with_sensors_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sensors_init in -lsensors" >&5
+$as_echo_n "checking for sensors_init in -lsensors... " >&6; }
+if ${ac_cv_lib_sensors_sensors_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsensors  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sensors_init ();
+int
+main ()
+{
+return sensors_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_sensors_sensors_init=yes
+else
+  ac_cv_lib_sensors_sensors_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sensors_sensors_init" >&5
+$as_echo "$ac_cv_lib_sensors_sensors_init" >&6; }
+if test "x$ac_cv_lib_sensors_sensors_init" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBSENSORS 1" >>confdefs.h
+
+
+else
+  with_libsensors="no (libsensors not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libsensors" = "xyes"
+then
+       BUILD_WITH_LIBSENSORS_CFLAGS="$with_sensors_cflags"
+       BUILD_WITH_LIBSENSORS_LDFLAGS="$with_sensors_ldflags"
+
+
+fi
+ if test "x$with_libsensors" = "xyes"; then
+  BUILD_WITH_LM_SENSORS_TRUE=
+  BUILD_WITH_LM_SENSORS_FALSE='#'
+else
+  BUILD_WITH_LM_SENSORS_TRUE='#'
+  BUILD_WITH_LM_SENSORS_FALSE=
+fi
+
+# }}}
+
+# --with-libsigrok {{{
+with_libsigrok_cflags=""
+with_libsigrok_ldflags=""
+
+# Check whether --with-libsigrok was given.
+if test "${with_libsigrok+set}" = set; then :
+  withval=$with_libsigrok;
+       if test "x$withval" = "xno"
+       then
+               with_libsigrok="no"
+       else
+               with_libsigrok="yes"
+               if test "x$withval" != "xyes"
+               then
+                       with_libsigrok_cflags="-I$withval/include"
+                       with_libsigrok_ldflags="-L$withval/lib"
+               fi
+       fi
+
+else
+  with_libsigrok="yes"
+fi
+
+
+# libsigrok has a glib dependency
+if test "x$with_libsigrok" = "xyes"
+then
+
+        # Check whether --enable-glibtest was given.
+if test "${enable_glibtest+set}" = set; then :
+  enableval=$enable_glibtest;
+else
+  enable_glibtest=yes
+fi
+
+
+  pkg_config_args=glib-2.0
+  for module in .
+  do
+      case "$module" in
+         gmodule)
+             pkg_config_args="$pkg_config_args gmodule-2.0"
+         ;;
+         gmodule-no-export)
+             pkg_config_args="$pkg_config_args gmodule-no-export-2.0"
+         ;;
+         gobject)
+             pkg_config_args="$pkg_config_args gobject-2.0"
+         ;;
+         gthread)
+             pkg_config_args="$pkg_config_args gthread-2.0"
+         ;;
+         gio*)
+             pkg_config_args="$pkg_config_args $module-2.0"
+         ;;
+      esac
+  done
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=0.16
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+               PKG_CONFIG=""
+       fi
+fi
+
+  no_glib=""
+
+  if test "x$PKG_CONFIG" = x ; then
+    no_glib=yes
+    PKG_CONFIG=no
+  fi
+
+  min_glib_version=2.28.0
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB - version >= $min_glib_version" >&5
+$as_echo_n "checking for GLIB - version >= $min_glib_version... " >&6; }
+
+  if test x$PKG_CONFIG != xno ; then
+    ## don't try to run the test against uninstalled libtool libs
+    if $PKG_CONFIG --uninstalled $pkg_config_args; then
+         echo "Will use uninstalled version of GLib found in PKG_CONFIG_PATH"
+         enable_glibtest=no
+    fi
+
+    if $PKG_CONFIG --atleast-version $min_glib_version $pkg_config_args; then
+         :
+    else
+         no_glib=yes
+    fi
+  fi
+
+  if test x"$no_glib" = x ; then
+    GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
+    GOBJECT_QUERY=`$PKG_CONFIG --variable=gobject_query glib-2.0`
+    GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
+    GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable=glib_compile_resources gio-2.0`
+
+    GLIB_CFLAGS=`$PKG_CONFIG --cflags $pkg_config_args`
+    GLIB_LIBS=`$PKG_CONFIG --libs $pkg_config_args`
+    glib_config_major_version=`$PKG_CONFIG --modversion glib-2.0 | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+    glib_config_minor_version=`$PKG_CONFIG --modversion glib-2.0 | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+    glib_config_micro_version=`$PKG_CONFIG --modversion glib-2.0 | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+    if test "x$enable_glibtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GLIB_CFLAGS"
+      LIBS="$GLIB_LIBS $LIBS"
+      rm -f conf.glibtest
+      if test "$cross_compiling" = yes; then :
+  echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int
+main ()
+{
+  unsigned int major, minor, micro;
+
+  fclose (fopen ("conf.glibtest", "w"));
+
+  if (sscanf("$min_glib_version", "%u.%u.%u", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_glib_version");
+     exit(1);
+   }
+
+  if ((glib_major_version != $glib_config_major_version) ||
+      (glib_minor_version != $glib_config_minor_version) ||
+      (glib_micro_version != $glib_config_micro_version))
+    {
+      printf("\n*** 'pkg-config --modversion glib-2.0' returned %d.%d.%d, but GLIB (%d.%d.%d)\n",
+             $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version,
+             glib_major_version, glib_minor_version, glib_micro_version);
+      printf ("*** was found! If pkg-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GLib. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If pkg-config was wrong, set the environment variable PKG_CONFIG_PATH\n");
+      printf("*** to point to the correct configuration files\n");
+    }
+  else if ((glib_major_version != GLIB_MAJOR_VERSION) ||
+          (glib_minor_version != GLIB_MINOR_VERSION) ||
+           (glib_micro_version != GLIB_MICRO_VERSION))
+    {
+      printf("*** GLIB header files (version %d.%d.%d) do not match\n",
+            GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+            glib_major_version, glib_minor_version, glib_micro_version);
+    }
+  else
+    {
+      if ((glib_major_version > major) ||
+        ((glib_major_version == major) && (glib_minor_version > minor)) ||
+        ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GLIB (%u.%u.%u) was found.\n",
+               glib_major_version, glib_minor_version, glib_micro_version);
+        printf("*** You need a version of GLIB newer than %u.%u.%u. The latest version of\n",
+              major, minor, micro);
+        printf("*** GLIB is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the pkg-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GLIB, but you can also set the PKG_CONFIG environment to point to the\n");
+        printf("*** correct copy of pkg-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  no_glib=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_glib" = x ; then
+     { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&5
+$as_echo "yes (version $glib_config_major_version.$glib_config_minor_version.$glib_config_micro_version)" >&6; }
+     with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"
+  else
+     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+     if test "$PKG_CONFIG" = "no" ; then
+       echo "*** A new enough version of pkg-config was not found."
+       echo "*** See http://www.freedesktop.org/software/pkgconfig/"
+     else
+       if test -f conf.glibtest ; then
+        :
+       else
+          echo "*** Could not run GLIB test program, checking why..."
+          ac_save_CFLAGS="$CFLAGS"
+          ac_save_LIBS="$LIBS"
+          CFLAGS="$CFLAGS $GLIB_CFLAGS"
+          LIBS="$LIBS $GLIB_LIBS"
+          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <glib.h>
+#include <stdio.h>
+
+int
+main ()
+{
+ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version));
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GLIB or finding the wrong"
+          echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+         echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+else
+   echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GLIB is incorrectly installed."
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GLIB_CFLAGS=""
+     GLIB_LIBS=""
+     GLIB_GENMARSHAL=""
+     GOBJECT_QUERY=""
+     GLIB_MKENUMS=""
+     GLIB_COMPILE_RESOURCES=""
+     :
+  fi
+
+
+
+
+
+
+  rm -f conf.glibtest
+
+
+fi
+
+# libsigrok headers
+if test "x$with_libsigrok" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
+
+       for ac_header in libsigrok/libsigrok.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libsigrok/libsigrok.h" "ac_cv_header_libsigrok_libsigrok_h" "$ac_includes_default"
+if test "x$ac_cv_header_libsigrok_libsigrok_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSIGROK_LIBSIGROK_H 1
+_ACEOF
+
+else
+  with_libsigrok="no (libsigrok/libsigrok.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+# libsigrok library
+if test "x$with_libsigrok" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
+       LDFLAGS="$LDFLAGS $with_libsigrok_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sr_init in -lsigrok" >&5
+$as_echo_n "checking for sr_init in -lsigrok... " >&6; }
+if ${ac_cv_lib_sigrok_sr_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsigrok  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sr_init ();
+int
+main ()
+{
+return sr_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_sigrok_sr_init=yes
+else
+  ac_cv_lib_sigrok_sr_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sigrok_sr_init" >&5
+$as_echo "$ac_cv_lib_sigrok_sr_init" >&6; }
+if test "x$ac_cv_lib_sigrok_sr_init" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBSIGROK 1" >>confdefs.h
+
+
+else
+  with_libsigrok="no (libsigrok not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libsigrok" = "xyes"
+then
+       BUILD_WITH_LIBSIGROK_CFLAGS="$with_libsigrok_cflags"
+       BUILD_WITH_LIBSIGROK_LDFLAGS="$with_libsigrok_ldflags"
+
+
+fi
+ if test "x$with_libsigrok" = "xyes"; then
+  BUILD_WITH_LIBSIGROK_TRUE=
+  BUILD_WITH_LIBSIGROK_FALSE='#'
+else
+  BUILD_WITH_LIBSIGROK_TRUE='#'
+  BUILD_WITH_LIBSIGROK_FALSE=
+fi
+
+# }}}
+
+# --with-libstatgrab {{{
+with_libstatgrab_cflags=""
+with_libstatgrab_ldflags=""
+
+# Check whether --with-libstatgrab was given.
+if test "${with_libstatgrab+set}" = set; then :
+  withval=$with_libstatgrab;
+ if test "x$withval" != "xno" \
+   && test "x$withval" != "xyes"
+ then
+   with_libstatgrab_cflags="-I$withval/include"
+   with_libstatgrab_ldflags="-L$withval/lib -lstatgrab"
+   with_libstatgrab="yes"
+   with_libstatgrab_pkg_config="no"
+ else
+   with_libstatgrab="$withval"
+   with_libstatgrab_pkg_config="yes"
+ fi
+
+else
+
+ with_libstatgrab="yes"
+ with_libstatgrab_pkg_config="yes"
+
+fi
+
+
+if test "x$with_libstatgrab" = "xyes" \
+  && test "x$with_libstatgrab_pkg_config" = "xyes"
+then
+  if test "x$PKG_CONFIG" != "x"
+  then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config for libstatgrab" >&5
+$as_echo_n "checking pkg-config for libstatgrab... " >&6; }
+    temp_result="found"
+    $PKG_CONFIG --exists libstatgrab 2>/dev/null
+    if test "$?" != "0"
+    then
+      with_libstatgrab_pkg_config="no"
+      with_libstatgrab="no (pkg-config doesn't know libstatgrab)"
+      temp_result="not found"
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $temp_result" >&5
+$as_echo "$temp_result" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: pkg-config not available, trying to guess flags for the statgrab library." >&5
+$as_echo "$as_me: pkg-config not available, trying to guess flags for the statgrab library." >&6;}
+    with_libstatgrab_pkg_config="no"
+    with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab"
+  fi
+fi
+
+if test "x$with_libstatgrab" = "xyes" \
+  && test "x$with_libstatgrab_pkg_config" = "xyes" \
+  && test "x$with_libstatgrab_cflags" = "x"
+then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libstatgrab CFLAGS" >&5
+$as_echo_n "checking for libstatgrab CFLAGS... " >&6; }
+  temp_result="`$PKG_CONFIG --cflags libstatgrab`"
+  if test "$?" = "0"
+  then
+    with_libstatgrab_cflags="$temp_result"
+  else
+    with_libstatgrab="no ($PKG_CONFIG --cflags libstatgrab failed)"
+    temp_result="$PKG_CONFIG --cflags libstatgrab failed"
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $temp_result" >&5
+$as_echo "$temp_result" >&6; }
+fi
+
+if test "x$with_libstatgrab" = "xyes" \
+  && test "x$with_libstatgrab_pkg_config" = "xyes" \
+  && test "x$with_libstatgrab_ldflags" = "x"
+then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libstatgrab LDFLAGS" >&5
+$as_echo_n "checking for libstatgrab LDFLAGS... " >&6; }
+  temp_result="`$PKG_CONFIG --libs libstatgrab`"
+  if test "$?" = "0"
+  then
+    with_libstatgrab_ldflags="$temp_result"
+  else
+    with_libstatgrab="no ($PKG_CONFIG --libs libstatgrab failed)"
+    temp_result="$PKG_CONFIG --libs libstatgrab failed"
+  fi
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $temp_result" >&5
+$as_echo "$temp_result" >&6; }
+fi
+
+if test "x$with_libstatgrab" = "xyes"
+then
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $with_libstatgrab_cflags"
+
+  for ac_header in statgrab.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "statgrab.h" "ac_cv_header_statgrab_h" "$ac_includes_default"
+if test "x$ac_cv_header_statgrab_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STATGRAB_H 1
+_ACEOF
+ with_libstatgrab="yes"
+else
+  with_libstatgrab="no (statgrab.h not found)"
+fi
+
+done
+
+
+  CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+if test "x$with_libstatgrab" = "xyes"
+then
+  SAVE_CFLAGS="$CFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
+
+  CFLAGS="$CFLAGS $with_libstatgrab_cflags"
+  LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sg_init in -lstatgrab" >&5
+$as_echo_n "checking for sg_init in -lstatgrab... " >&6; }
+if ${ac_cv_lib_statgrab_sg_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lstatgrab  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sg_init ();
+int
+main ()
+{
+return sg_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_statgrab_sg_init=yes
+else
+  ac_cv_lib_statgrab_sg_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_statgrab_sg_init" >&5
+$as_echo "$ac_cv_lib_statgrab_sg_init" >&6; }
+if test "x$ac_cv_lib_statgrab_sg_init" = xyes; then :
+  with_libstatgrab="yes"
+else
+  with_libstatgrab="no (symbol sg_init not found)"
+fi
+
+
+  CFLAGS="$SAVE_CFLAGS"
+  LDFLAGS="$SAVE_LDFLAGS"
+fi
+
+if test "x$with_libstatgrab" = "xyes"
+then
+  SAVE_CFLAGS="$CFLAGS"
+  SAVE_LIBS="$LIBS"
+
+  CFLAGS="$CFLAGS $with_libstatgrab_cflags"
+  LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
+  LIBS="-lstatgrab $LIBS"
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libstatgrab >= 0.90" >&5
+$as_echo_n "checking if libstatgrab >= 0.90... " >&6; }
+if ${c_cv_have_libstatgrab_0_90+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <statgrab.h>
+
+int
+main ()
+{
+
+      if (sg_init()) return 0;
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  c_cv_have_libstatgrab_0_90="no"
+else
+  c_cv_have_libstatgrab_0_90="yes"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $c_cv_have_libstatgrab_0_90" >&5
+$as_echo "$c_cv_have_libstatgrab_0_90" >&6; }
+
+  CFLAGS="$SAVE_CFLAGS"
+  LDFLAGS="$SAVE_LDFLAGS"
+  LIBS="$SAVE_LIBS"
+fi
+
+ if test "x$with_libstatgrab" = "xyes"; then
+  BUILD_WITH_LIBSTATGRAB_TRUE=
+  BUILD_WITH_LIBSTATGRAB_FALSE='#'
+else
+  BUILD_WITH_LIBSTATGRAB_TRUE='#'
+  BUILD_WITH_LIBSTATGRAB_FALSE=
+fi
+
+if test "x$with_libstatgrab" = "xyes"
+then
+
+$as_echo "#define HAVE_LIBSTATGRAB 1" >>confdefs.h
+
+  BUILD_WITH_LIBSTATGRAB_CFLAGS="$with_libstatgrab_cflags"
+  BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags"
+
+
+  if test "x$c_cv_have_libstatgrab_0_90" = "xyes"
+  then
+
+$as_echo "#define HAVE_LIBSTATGRAB_0_90 1" >>confdefs.h
+
+  fi
+fi
+# }}}
+
+# --with-libtokyotyrant {{{
+with_libtokyotyrant_cppflags=""
+with_libtokyotyrant_ldflags=""
+with_libtokyotyrant_libs=""
+
+# Check whether --with-libtokyotyrant was given.
+if test "${with_libtokyotyrant+set}" = set; then :
+  withval=$with_libtokyotyrant;
+  if test "x$withval" = "xno"
+  then
+    with_libtokyotyrant="no"
+  else if test "x$withval" = "xyes"
+  then
+    with_libtokyotyrant="yes"
+  else
+    with_libtokyotyrant_cppflags="-I$withval/include"
+    with_libtokyotyrant_ldflags="-L$withval/include"
+    with_libtokyotyrant_libs="-ltokyotyrant"
+    with_libtokyotyrant="yes"
+  fi; fi
+
+else
+
+  with_libtokyotyrant="yes"
+
+fi
+
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  if $PKG_CONFIG --exists tokyotyrant
+  then
+    with_libtokyotyrant_cppflags="$with_libtokyotyrant_cppflags `$PKG_CONFIG --cflags tokyotyrant`"
+    with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `$PKG_CONFIG --libs-only-L tokyotyrant`"
+    with_libtokyotyrant_libs="$with_libtokyotyrant_libs `$PKG_CONFIG --libs-only-l tokyotyrant`"
+  fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $with_libtokyotyrant_cppflags"
+LDFLAGS="$LDFLAGS $with_libtokyotyrant_ldflags"
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  for ac_header in tcrdb.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "tcrdb.h" "ac_cv_header_tcrdb_h" "$ac_includes_default"
+if test "x$ac_cv_header_tcrdb_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_TCRDB_H 1
+_ACEOF
+
+
+$as_echo "#define HAVE_TCRDB_H 1" >>confdefs.h
+
+
+else
+  with_libtokyotyrant="no (tcrdb.h not found)"
+fi
+
+done
+
+fi
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tcrdbrnum in -ltokyotyrant" >&5
+$as_echo_n "checking for tcrdbrnum in -ltokyotyrant... " >&6; }
+if ${ac_cv_lib_tokyotyrant_tcrdbrnum+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ltokyotyrant $with_libtokyotyrant_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tcrdbrnum ();
+int
+main ()
+{
+return tcrdbrnum ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_tokyotyrant_tcrdbrnum=yes
+else
+  ac_cv_lib_tokyotyrant_tcrdbrnum=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tokyotyrant_tcrdbrnum" >&5
+$as_echo "$ac_cv_lib_tokyotyrant_tcrdbrnum" >&6; }
+if test "x$ac_cv_lib_tokyotyrant_tcrdbrnum" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBTOKYOTYRANT 1" >>confdefs.h
+
+
+else
+  with_libtokyotyrant="no (symbol tcrdbrnum not found)"
+fi
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS="$with_libtokyotyrant_cppflags"
+  BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS="$with_libtokyotyrant_ldflags"
+  BUILD_WITH_LIBTOKYOTYRANT_LIBS="$with_libtokyotyrant_libs"
+
+
+
+fi
+ if test "x$with_libtokyotyrant" = "xyes"; then
+  BUILD_WITH_LIBTOKYOTYRANT_TRUE=
+  BUILD_WITH_LIBTOKYOTYRANT_FALSE='#'
+else
+  BUILD_WITH_LIBTOKYOTYRANT_TRUE='#'
+  BUILD_WITH_LIBTOKYOTYRANT_FALSE=
+fi
+
+# }}}
+
+# --with-libudev {{{
+with_libudev_cflags=""
+with_libudev_ldflags=""
+
+# Check whether --with-libudev was given.
+if test "${with_libudev+set}" = set; then :
+  withval=$with_libudev;
+       if test "x$withval" = "xno"
+       then
+               with_libudev="no"
+       else
+               with_libudev="yes"
+               if test "x$withval" != "xyes"
+               then
+                       with_libudev_cflags="-I$withval/include"
+                       with_libudev_ldflags="-L$withval/lib"
+                       with_libudev="yes"
+               fi
+       fi
+
+else
+
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libudev="yes"
+       else
+               with_libudev="no (Linux only library)"
+       fi
+
+fi
+
+if test "x$with_libudev" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libudev_cflags"
+
+       for ac_header in libudev.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libudev.h" "ac_cv_header_libudev_h" "$ac_includes_default"
+if test "x$ac_cv_header_libudev_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUDEV_H 1
+_ACEOF
+
+else
+  with_libudev="no (libudev.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libudev" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libudev_cflags"
+       LDFLAGS="$LDFLAGS $with_libudev_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for udev_new in -ludev" >&5
+$as_echo_n "checking for udev_new in -ludev... " >&6; }
+if ${ac_cv_lib_udev_udev_new+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ludev  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char udev_new ();
+int
+main ()
+{
+return udev_new ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_udev_udev_new=yes
+else
+  ac_cv_lib_udev_udev_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_udev_udev_new" >&5
+$as_echo "$ac_cv_lib_udev_udev_new" >&6; }
+if test "x$ac_cv_lib_udev_udev_new" = xyes; then :
+
+
+$as_echo "#define HAVE_LIBUDEV 1" >>confdefs.h
+
+
+else
+  with_libudev="no (libudev not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libudev" = "xyes"
+then
+       BUILD_WITH_LIBUDEV_CFLAGS="$with_libudev_cflags"
+       BUILD_WITH_LIBUDEV_LDFLAGS="$with_libudev_ldflags"
+
+
+fi
+ if test "x$with_libudev" = "xyes"; then
+  BUILD_WITH_LIBUDEV_TRUE=
+  BUILD_WITH_LIBUDEV_FALSE='#'
+else
+  BUILD_WITH_LIBUDEV_TRUE='#'
+  BUILD_WITH_LIBUDEV_FALSE=
+fi
+
+# }}}
+
+# --with-libupsclient {{{
+with_libupsclient_config=""
+with_libupsclient_cflags=""
+with_libupsclient_libs=""
+
+# Check whether --with-libupsclient was given.
+if test "${with_libupsclient+set}" = set; then :
+  withval=$with_libupsclient;
+       if test "x$withval" = "xno"
+       then
+               with_libupsclient="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libupsclient="use_pkgconfig"
+       else
+               if test -x "$withval"
+               then
+                       with_libupsclient_config="$withval"
+                       with_libupsclient="use_libupsclient_config"
+               else if test -x "$withval/bin/libupsclient-config"
+               then
+                       with_libupsclient_config="$withval/bin/libupsclient-config"
+                       with_libupsclient="use_libupsclient_config"
+               else
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: Not checking for libupsclient: Manually configured" >&5
+$as_echo "$as_me: Not checking for libupsclient: Manually configured" >&6;}
+                       with_libupsclient_cflags="-I$withval/include"
+                       with_libupsclient_libs="-L$withval/lib -lupsclient"
+                       with_libupsclient="yes"
+               fi; fi
+       fi; fi
+
+else
+  with_libupsclient="use_pkgconfig"
+fi
+
+
+# configure using libupsclient-config
+if test "x$with_libupsclient" = "xuse_libupsclient_config"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Checking for libupsclient using $with_libupsclient_config" >&5
+$as_echo "$as_me: Checking for libupsclient using $with_libupsclient_config" >&6;}
+       with_libupsclient_cflags="`$with_libupsclient_config --cflags`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($with_libupsclient_config failed)"
+       fi
+       with_libupsclient_libs="`$with_libupsclient_config --libs`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($with_libupsclient_config failed)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_libupsclient_config"
+then
+       with_libupsclient="yes"
+fi
+
+# configure using pkg-config
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       if test "x$PKG_CONFIG" = "x"
+       then
+               with_libupsclient="no (Don't have pkg-config)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Checking for libupsclient using $PKG_CONFIG" >&5
+$as_echo "$as_me: Checking for libupsclient using $PKG_CONFIG" >&6;}
+       $PKG_CONFIG --exists 'libupsclient' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libupsclient="no (pkg-config doesn't know libupsclient)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       with_libupsclient_cflags="`$PKG_CONFIG --cflags 'libupsclient'`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($PKG_CONFIG failed)"
+       fi
+       with_libupsclient_libs="`$PKG_CONFIG --libs 'libupsclient'`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($PKG_CONFIG failed)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       with_libupsclient="yes"
+fi
+
+# with_libupsclient_cflags and with_libupsclient_libs are set up now, let's do
+# the actual checks.
+if test "x$with_libupsclient" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+
+       for ac_header in upsclient.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "upsclient.h" "ac_cv_header_upsclient_h" "$ac_includes_default"
+if test "x$ac_cv_header_upsclient_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_UPSCLIENT_H 1
+_ACEOF
+
+else
+  with_libupsclient="no (upsclient.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+       LDFLAGS="$LDFLAGS $with_libupsclient_libs"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for upscli_connect in -lupsclient" >&5
+$as_echo_n "checking for upscli_connect in -lupsclient... " >&6; }
+if ${ac_cv_lib_upsclient_upscli_connect+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lupsclient  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char upscli_connect ();
+int
+main ()
+{
+return upscli_connect ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_upsclient_upscli_connect=yes
+else
+  ac_cv_lib_upsclient_upscli_connect=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_upsclient_upscli_connect" >&5
+$as_echo "$ac_cv_lib_upsclient_upscli_connect" >&6; }
+if test "x$ac_cv_lib_upsclient_upscli_connect" = xyes; then :
+  with_libupsclient="yes"
+else
+  with_libupsclient="no (symbol upscli_connect not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+
+       ac_fn_c_check_type "$LINENO" "UPSCONN_t" "ac_cv_type_UPSCONN_t" "#include <stdlib.h>
+#include <stdio.h>
+#include <upsclient.h>
+"
+if test "x$ac_cv_type_UPSCONN_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UPSCONN_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "UPSCONN" "ac_cv_type_UPSCONN" "#include <stdlib.h>
+#include <stdio.h>
+#include <upsclient.h>
+"
+if test "x$ac_cv_type_UPSCONN" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UPSCONN 1
+_ACEOF
+
+
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+       BUILD_WITH_LIBUPSCLIENT_CFLAGS="$with_libupsclient_cflags"
+       BUILD_WITH_LIBUPSCLIENT_LIBS="$with_libupsclient_libs"
+
+
+fi
+# }}}
+
+# --with-libxmms {{{
+with_xmms_config="xmms-config"
+with_xmms_cflags=""
+with_xmms_libs=""
+
+# Check whether --with-libxmms was given.
+if test "${with_libxmms+set}" = set; then :
+  withval=$with_libxmms;
+       if test "x$withval" != "xno" \
+               && test "x$withval" != "xyes"
+       then
+               if test -f "$withval" && test -x "$withval";
+               then
+                       with_xmms_config="$withval"
+               else if test -x "$withval/bin/xmms-config"
+               then
+                       with_xmms_config="$withval/bin/xmms-config"
+               fi; fi
+               with_libxmms="yes"
+       else if test "x$withval" = "xno"
+       then
+               with_libxmms="no"
+       else
+               with_libxmms="yes"
+       fi; fi
+
+else
+
+       with_libxmms="yes"
+
+fi
+
+if test "x$with_libxmms" = "xyes"
+then
+       with_xmms_cflags=`$with_xmms_config --cflags 2>/dev/null`
+       xmms_config_status=$?
+
+       if test $xmms_config_status -ne 0
+       then
+               with_libxmms="no"
+       fi
+fi
+if test "x$with_libxmms" = "xyes"
+then
+       with_xmms_libs=`$with_xmms_config --libs 2>/dev/null`
+       xmms_config_status=$?
+
+       if test $xmms_config_status -ne 0
+       then
+               with_libxmms="no"
+       fi
+fi
+if test "x$with_libxmms" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmms_remote_get_info in -lxmms" >&5
+$as_echo_n "checking for xmms_remote_get_info in -lxmms... " >&6; }
+if ${ac_cv_lib_xmms_xmms_remote_get_info+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxmms $with_xmms_libs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char xmms_remote_get_info ();
+int
+main ()
+{
+return xmms_remote_get_info ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_xmms_xmms_remote_get_info=yes
+else
+  ac_cv_lib_xmms_xmms_remote_get_info=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xmms_xmms_remote_get_info" >&5
+$as_echo "$ac_cv_lib_xmms_xmms_remote_get_info" >&6; }
+if test "x$ac_cv_lib_xmms_xmms_remote_get_info" = xyes; then :
+
+               BUILD_WITH_LIBXMMS_CFLAGS="$with_xmms_cflags"
+               BUILD_WITH_LIBXMMS_LIBS="$with_xmms_libs"
+
+
+
+else
+
+               with_libxmms="no"
+
+fi
+
+fi
+with_libxmms_numeric=0
+if test "x$with_libxmms" = "xyes"
+then
+       with_libxmms_numeric=1
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXMMS $with_libxmms_numeric
+_ACEOF
+
+ if test "x$with_libxmms" = "xyes"; then
+  BUILD_WITH_LIBXMMS_TRUE=
+  BUILD_WITH_LIBXMMS_FALSE='#'
+else
+  BUILD_WITH_LIBXMMS_TRUE='#'
+  BUILD_WITH_LIBXMMS_FALSE=
+fi
+
+# }}}
+
+# --with-libyajl {{{
+with_libyajl_cppflags=""
+with_libyajl_ldflags=""
+
+# Check whether --with-libyajl was given.
+if test "${with_libyajl+set}" = set; then :
+  withval=$with_libyajl;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libyajl_cppflags="-I$withval/include"
+               with_libyajl_ldflags="-L$withval/lib"
+               with_libyajl="yes"
+       else
+               with_libyajl="$withval"
+       fi
+
+else
+
+       with_libyajl="yes"
+
+fi
+
+if test "x$with_libyajl" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+
+       for ac_header in yajl/yajl_parse.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "yajl/yajl_parse.h" "ac_cv_header_yajl_yajl_parse_h" "$ac_includes_default"
+if test "x$ac_cv_header_yajl_yajl_parse_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_YAJL_YAJL_PARSE_H 1
+_ACEOF
+ with_libyajl="yes"
+else
+  with_libyajl="no (yajl/yajl_parse.h not found)"
+fi
+
+done
+
+       for ac_header in yajl/yajl_version.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "yajl/yajl_version.h" "ac_cv_header_yajl_yajl_version_h" "$ac_includes_default"
+if test "x$ac_cv_header_yajl_yajl_version_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_YAJL_YAJL_VERSION_H 1
+_ACEOF
+
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+       LDFLAGS="$LDFLAGS $with_libyajl_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for yajl_alloc in -lyajl" >&5
+$as_echo_n "checking for yajl_alloc in -lyajl... " >&6; }
+if ${ac_cv_lib_yajl_yajl_alloc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lyajl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char yajl_alloc ();
+int
+main ()
+{
+return yajl_alloc ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_yajl_yajl_alloc=yes
+else
+  ac_cv_lib_yajl_yajl_alloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_yajl_yajl_alloc" >&5
+$as_echo "$ac_cv_lib_yajl_yajl_alloc" >&6; }
+if test "x$ac_cv_lib_yajl_yajl_alloc" = xyes; then :
+  with_libyajl="yes"
+else
+  with_libyajl="no (Symbol 'yajl_alloc' not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+       BUILD_WITH_LIBYAJL_CPPFLAGS="$with_libyajl_cppflags"
+       BUILD_WITH_LIBYAJL_LDFLAGS="$with_libyajl_ldflags"
+       BUILD_WITH_LIBYAJL_LIBS="-lyajl"
+
+
+
+
+$as_echo "#define HAVE_LIBYAJL 1" >>confdefs.h
+
+fi
+ if test "x$with_libyajl" = "xyes"; then
+  BUILD_WITH_LIBYAJL_TRUE=
+  BUILD_WITH_LIBYAJL_FALSE='#'
+else
+  BUILD_WITH_LIBYAJL_TRUE='#'
+  BUILD_WITH_LIBYAJL_FALSE=
+fi
+
+# }}}
+
+# --with-mic {{{
+with_mic_cflags="-I/opt/intel/mic/sysmgmt/sdk/include"
+with_mic_ldpath="-L/opt/intel/mic/sysmgmt/sdk/lib/Linux"
+with_mic_libs=""
+
+# Check whether --with-mic was given.
+if test "${with_mic+set}" = set; then :
+  withval=$with_mic;
+       if test "x$withval" = "xno"
+       then
+               with_mic="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_mic="yes"
+       else if test -d "$with_mic/lib"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: Not checking for Intel Mic: Manually configured" >&5
+$as_echo "$as_me: Not checking for Intel Mic: Manually configured" >&6;}
+               with_mic_cflags="-I$withval/include"
+               with_mic_ldpath="-L$withval/lib/Linux"
+               with_mic_libs="-lMicAccessSDK -lscif -lpthread"
+               with_mic="yes"
+       fi; fi; fi
+
+else
+  with_mic="yes"
+fi
+
+if test "x$with_mic" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_mic_cflags"
+       for ac_header in MicAccessApi.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "MicAccessApi.h" "ac_cv_header_MicAccessApi_h" "$ac_includes_default"
+if test "x$ac_cv_header_MicAccessApi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MICACCESSAPI_H 1
+_ACEOF
+
+else
+  with_mic="no (MicAccessApi not found)"
+fi
+
+done
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_mic" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_mic_cflags"
+       LDFLAGS="$LDFLAGS $with_mic_ldpath"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MicInitAPI in -lMicAccessSDK" >&5
+$as_echo_n "checking for MicInitAPI in -lMicAccessSDK... " >&6; }
+if ${ac_cv_lib_MicAccessSDK_MicInitAPI+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lMicAccessSDK -lscif -lpthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char MicInitAPI ();
+int
+main ()
+{
+return MicInitAPI ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_MicAccessSDK_MicInitAPI=yes
+else
+  ac_cv_lib_MicAccessSDK_MicInitAPI=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_MicAccessSDK_MicInitAPI" >&5
+$as_echo "$ac_cv_lib_MicAccessSDK_MicInitAPI" >&6; }
+if test "x$ac_cv_lib_MicAccessSDK_MicInitAPI" = xyes; then :
+  with_mic_ldpath="$with_mic_ldpath"
+                       with_mic_libs="-lMicAccessSDK -lscif -lpthread"
+else
+  with_mic="no (symbol MicInitAPI not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+
+if test "x$with_mic" = "xyes"
+then
+       BUILD_WITH_MIC_CPPFLAGS="$with_mic_cflags"
+       BUILD_WITH_MIC_LIBPATH="$with_mic_ldpath"
+       BUILD_WITH_MIC_LDADD="$with_mic_libs"
+
+
+
+fi
+#}}}
+
+# --with-libvarnish {{{
+with_libvarnish_cppflags=""
+with_libvarnish_cflags=""
+with_libvarnish_libs=""
+
+# Check whether --with-libvarnish was given.
+if test "${with_libvarnish+set}" = set; then :
+  withval=$with_libvarnish;
+       if test "x$withval" = "xno"
+       then
+               with_libvarnish="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libvarnish="use_pkgconfig"
+       else if test -d "$with_libvarnish/lib"
+       then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: Not checking for libvarnish: Manually configured" >&5
+$as_echo "$as_me: Not checking for libvarnish: Manually configured" >&6;}
+               with_libvarnish_cflags="-I$withval/include"
+               with_libvarnish_libs="-L$withval/lib -lvarnishapi"
+               with_libvarnish="yes"
+       fi; fi; fi
+
+else
+  with_libvarnish="use_pkgconfig"
+fi
+
+
+# configure using pkg-config
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       if test "x$PKG_CONFIG" = "x"
+       then
+               with_libvarnish="no (Don't have pkg-config)"
+       fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: Checking for varnishapi using $PKG_CONFIG" >&5
+$as_echo "$as_me: Checking for varnishapi using $PKG_CONFIG" >&6;}
+       $PKG_CONFIG --exists 'varnishapi' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libvarnish="no (pkg-config doesn't know varnishapi)"
+       fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       with_libvarnish_cflags="`$PKG_CONFIG --cflags 'varnishapi'`"
+       if test $? -ne 0
+       then
+               with_libvarnish="no ($PKG_CONFIG failed)"
+       fi
+       with_libvarnish_libs="`$PKG_CONFIG --libs 'varnishapi'`"
+       if test $? -ne 0
+       then
+               with_libvarnish="no ($PKG_CONFIG failed)"
+       fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       with_libvarnish="yes"
+fi
+
+# with_libvarnish_cflags and with_libvarnish_libs are set up now, let's do
+# the actual checks.
+if test "x$with_libvarnish" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
+
+       for ac_header in varnish/vapi/vsc.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "varnish/vapi/vsc.h" "ac_cv_header_varnish_vapi_vsc_h" "$ac_includes_default"
+if test "x$ac_cv_header_varnish_vapi_vsc_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VARNISH_VAPI_VSC_H 1
+_ACEOF
+
+$as_echo "#define HAVE_VARNISH_V4 1" >>confdefs.h
+
+else
+  for ac_header in varnish/vsc.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "varnish/vsc.h" "ac_cv_header_varnish_vsc_h" "$ac_includes_default"
+if test "x$ac_cv_header_varnish_vsc_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VARNISH_VSC_H 1
+_ACEOF
+
+$as_echo "#define HAVE_VARNISH_V3 1" >>confdefs.h
+
+else
+  for ac_header in varnish/varnishapi.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "varnish/varnishapi.h" "ac_cv_header_varnish_varnishapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_varnish_varnishapi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VARNISH_VARNISHAPI_H 1
+_ACEOF
+
+$as_echo "#define HAVE_VARNISH_V2 1" >>confdefs.h
+
+else
+  with_libvarnish="no (found none of the varnish header files)"
+fi
+
+done
+
+fi
+
+done
+
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libvarnish" = "xyes"
+then
+       BUILD_WITH_LIBVARNISH_CFLAGS="$with_libvarnish_cflags"
+       BUILD_WITH_LIBVARNISH_LIBS="$with_libvarnish_libs"
+
+
+fi
+# }}}
+
+# pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
+with_libxml2="no (pkg-config isn't available)"
+with_libxml2_cflags=""
+with_libxml2_ldflags=""
+with_libvirt="no (pkg-config isn't available)"
+with_libvirt_cflags=""
+with_libvirt_ldflags=""
+if test "x$PKG_CONFIG" != "x"
+then
+       $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
+       if test "$?" = "0"
+       then
+               with_libxml2="yes"
+       else
+               with_libxml2="no (pkg-config doesn't know libxml-2.0)"
+       fi
+
+       $PKG_CONFIG --exists libvirt 2>/dev/null
+       if test "$?" = "0"
+       then
+               with_libvirt="yes"
+       else
+               with_libvirt="no (pkg-config doesn't know libvirt)"
+       fi
+fi
+if test "x$with_libxml2" = "xyes"
+then
+       with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`"
+       if test $? -ne 0
+       then
+               with_libxml2="no"
+       fi
+       with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`"
+       if test $? -ne 0
+       then
+               with_libxml2="no"
+       fi
+fi
+if test "x$with_libxml2" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libxml2_cflags"
+
+       for ac_header in libxml/parser.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libxml/parser.h" "ac_cv_header_libxml_parser_h" "$ac_includes_default"
+if test "x$ac_cv_header_libxml_parser_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXML_PARSER_H 1
+_ACEOF
+
+else
+  with_libxml2="no (libxml/parser.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libxml2" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CFLAGS="$CFLAGS $with_libxml2_cflags"
+       LDFLAGS="$LDFLAGS $with_libxml2_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlXPathEval in -lxml2" >&5
+$as_echo_n "checking for xmlXPathEval in -lxml2... " >&6; }
+if ${ac_cv_lib_xml2_xmlXPathEval+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxml2  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char xmlXPathEval ();
+int
+main ()
+{
+return xmlXPathEval ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_xml2_xmlXPathEval=yes
+else
+  ac_cv_lib_xml2_xmlXPathEval=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlXPathEval" >&5
+$as_echo "$ac_cv_lib_xml2_xmlXPathEval" >&6; }
+if test "x$ac_cv_lib_xml2_xmlXPathEval" = xyes; then :
+  with_libxml2="yes"
+else
+  with_libxml2="no (symbol xmlXPathEval not found)"
+fi
+
+
+       CFLAGS="$SAVE_CFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libxml2" = "xyes"; then
+       BUILD_WITH_LIBXML2_CFLAGS="$with_libxml2_cflags"
+       BUILD_WITH_LIBXML2_LIBS="$with_libxml2_ldflags"
+
+
+fi
+if test "x$with_libvirt" = "xyes"
+then
+       with_libvirt_cflags="`$PKG_CONFIG --cflags libvirt`"
+       if test $? -ne 0
+       then
+               with_libvirt="no"
+       fi
+       with_libvirt_ldflags="`$PKG_CONFIG --libs libvirt`"
+       if test $? -ne 0
+       then
+               with_libvirt="no"
+       fi
+fi
+if test "x$with_libvirt" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libvirt_cflags"
+
+       for ac_header in libvirt/libvirt.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libvirt/libvirt.h" "ac_cv_header_libvirt_libvirt_h" "$ac_includes_default"
+if test "x$ac_cv_header_libvirt_libvirt_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBVIRT_LIBVIRT_H 1
+_ACEOF
+
+else
+  with_libvirt="no (libvirt/libvirt.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libvirt" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CFLAGS="$CFLAGS $with_libvirt_cflags"
+       LDFLAGS="$LDFLAGS $with_libvirt_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for virDomainBlockStats in -lvirt" >&5
+$as_echo_n "checking for virDomainBlockStats in -lvirt... " >&6; }
+if ${ac_cv_lib_virt_virDomainBlockStats+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lvirt  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char virDomainBlockStats ();
+int
+main ()
+{
+return virDomainBlockStats ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_virt_virDomainBlockStats=yes
+else
+  ac_cv_lib_virt_virDomainBlockStats=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_virt_virDomainBlockStats" >&5
+$as_echo "$ac_cv_lib_virt_virDomainBlockStats" >&6; }
+if test "x$ac_cv_lib_virt_virDomainBlockStats" = xyes; then :
+  with_libvirt="yes"
+else
+  with_libvirt="no (symbol virDomainBlockStats not found)"
+fi
+
+
+       CFLAGS="$SAVE_CFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libvirt" = "xyes"; then
+       BUILD_WITH_LIBVIRT_CFLAGS="$with_libvirt_cflags"
+       BUILD_WITH_LIBVIRT_LIBS="$with_libvirt_ldflags"
+
+
+fi
+# }}}
+
+# $PKG_CONFIG --exists OpenIPMIpthread {{{
+with_libopenipmipthread="yes"
+with_libopenipmipthread_cflags=""
+with_libopenipmipthread_libs=""
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pkg-config" >&5
+$as_echo_n "checking for pkg-config... " >&6; }
+temp_result="no"
+if test "x$PKG_CONFIG" = "x"
+then
+       with_libopenipmipthread="no"
+       temp_result="no"
+else
+       temp_result="$PKG_CONFIG"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $temp_result" >&5
+$as_echo "$temp_result" >&6; }
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libOpenIPMIpthread" >&5
+$as_echo_n "checking for libOpenIPMIpthread... " >&6; }
+       $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null
+       if test "$?" != "0"
+       then
+               with_libopenipmipthread="no (pkg-config doesn't know OpenIPMIpthread)"
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_libopenipmipthread" >&5
+$as_echo "$with_libopenipmipthread" >&6; }
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libOpenIPMIpthread CFLAGS" >&5
+$as_echo_n "checking for libOpenIPMIpthread CFLAGS... " >&6; }
+       temp_result="`$PKG_CONFIG --cflags OpenIPMIpthread`"
+       if test "$?" = "0"
+       then
+               with_libopenipmipthread_cflags="$temp_result"
+       else
+               with_libopenipmipthread="no ($PKG_CONFIG --cflags OpenIPMIpthread failed)"
+               temp_result="$PKG_CONFIG --cflags OpenIPMIpthread failed"
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $temp_result" >&5
+$as_echo "$temp_result" >&6; }
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libOpenIPMIpthread LDFLAGS" >&5
+$as_echo_n "checking for libOpenIPMIpthread LDFLAGS... " >&6; }
+       temp_result="`$PKG_CONFIG --libs OpenIPMIpthread`"
+       if test "$?" = "0"
+       then
+               with_libopenipmipthread_ldflags="$temp_result"
+       else
+               with_libopenipmipthread="no ($PKG_CONFIG --libs OpenIPMIpthread failed)"
+               temp_result="$PKG_CONFIG --libs OpenIPMIpthread failed"
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $temp_result" >&5
+$as_echo "$temp_result" >&6; }
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libopenipmipthread_cflags"
+
+       for ac_header in OpenIPMI/ipmi_smi.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "OpenIPMI/ipmi_smi.h" "ac_cv_header_OpenIPMI_ipmi_smi_h" "#include <OpenIPMI/ipmiif.h>
+#include <OpenIPMI/ipmi_err.h>
+#include <OpenIPMI/ipmi_posix.h>
+#include <OpenIPMI/ipmi_conn.h>
+
+"
+if test "x$ac_cv_header_OpenIPMI_ipmi_smi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENIPMI_IPMI_SMI_H 1
+_ACEOF
+ with_libopenipmipthread="yes"
+else
+  with_libopenipmipthread="no (OpenIPMI/ipmi_smi.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       BUILD_WITH_OPENIPMI_CFLAGS="$with_libopenipmipthread_cflags"
+       BUILD_WITH_OPENIPMI_LIBS="$with_libopenipmipthread_ldflags"
+
+
+fi
+# }}}
+
+# --with-libatasmart {{{
+with_libatasmart_cppflags=""
+with_libatasmart_ldflags=""
+
+# Check whether --with-libatasmart was given.
+if test "${with_libatasmart+set}" = set; then :
+  withval=$with_libatasmart;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libatasmart_cppflags="-I$withval/include"
+               with_libatasmart_ldflags="-L$withval/lib"
+               with_libatasmart="yes"
+       else
+               with_libatasmart="$withval"
+       fi
+
+else
+
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libatasmart="yes"
+       else
+               with_libatasmart="no (Linux only library)"
+       fi
+
+fi
+
+if test "x$with_libatasmart" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+
+       for ac_header in atasmart.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "atasmart.h" "ac_cv_header_atasmart_h" "$ac_includes_default"
+if test "x$ac_cv_header_atasmart_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ATASMART_H 1
+_ACEOF
+ with_libatasmart="yes"
+else
+  with_libatasmart="no (atasmart.h not found)"
+fi
+
+done
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+       LDFLAGS="$LDFLAGS $with_libatasmart_ldflags"
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sk_disk_open in -latasmart" >&5
+$as_echo_n "checking for sk_disk_open in -latasmart... " >&6; }
+if ${ac_cv_lib_atasmart_sk_disk_open+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-latasmart  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sk_disk_open ();
+int
+main ()
+{
+return sk_disk_open ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_atasmart_sk_disk_open=yes
+else
+  ac_cv_lib_atasmart_sk_disk_open=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_atasmart_sk_disk_open" >&5
+$as_echo "$ac_cv_lib_atasmart_sk_disk_open" >&6; }
+if test "x$ac_cv_lib_atasmart_sk_disk_open" = xyes; then :
+  with_libatasmart="yes"
+else
+  with_libatasmart="no (Symbol 'sk_disk_open' not found)"
+fi
+
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+       BUILD_WITH_LIBATASMART_CPPFLAGS="$with_libatasmart_cppflags"
+       BUILD_WITH_LIBATASMART_LDFLAGS="$with_libatasmart_ldflags"
+       BUILD_WITH_LIBATASMART_LIBS="-latasmart"
+
+
+
+
+$as_echo "#define HAVE_LIBATASMART 1" >>confdefs.h
+
+fi
+ if test "x$with_libatasmart" = "xyes"; then
+  BUILD_WITH_LIBATASMART_TRUE=
+  BUILD_WITH_LIBATASMART_FALSE='#'
+else
+  BUILD_WITH_LIBATASMART_TRUE='#'
+  BUILD_WITH_LIBATASMART_FALSE=
+fi
+
+# }}}
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBNOTIFY" >&5
+$as_echo_n "checking for LIBNOTIFY... " >&6; }
+
+if test -n "$LIBNOTIFY_CFLAGS"; then
+    pkg_cv_LIBNOTIFY_CFLAGS="$LIBNOTIFY_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnotify\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libnotify") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBNOTIFY_CFLAGS=`$PKG_CONFIG --cflags "libnotify" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$LIBNOTIFY_LIBS"; then
+    pkg_cv_LIBNOTIFY_LIBS="$LIBNOTIFY_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libnotify\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libnotify") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_LIBNOTIFY_LIBS=`$PKG_CONFIG --libs "libnotify" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               LIBNOTIFY_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libnotify" 2>&1`
+        else
+               LIBNOTIFY_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libnotify" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$LIBNOTIFY_PKG_ERRORS" >&5
+
+       if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
+                        with_libnotify="no"
+                else
+                        with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"
+                fi
+elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
+                        with_libnotify="no"
+                else
+                        with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"
+                fi
+else
+       LIBNOTIFY_CFLAGS=$pkg_cv_LIBNOTIFY_CFLAGS
+       LIBNOTIFY_LIBS=$pkg_cv_LIBNOTIFY_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       with_libnotify="yes"
+fi
+
+# Check for enabled/disabled features
+#
+
+# AC_COLLECTD(name, enable/disable, info-text, feature/module)
+# ------------------------------------------------------------
+
+# AC_COLLECTD(name, enable/disable, info-text, feature/module)
+
+# AC_PLUGIN(name, default, info)
+# ------------------------------------------------------------
+# AC_PLUGIN(name, default, info)
+
+
+# FIXME: Remove these calls to `AC_COLLECTD' and then remove that macro.
+
+                                                                               # Check whether --enable-debug was given.
+if test "${enable_debug+set}" = set; then :
+  enableval=$enable_debug;
+else
+  enable_debug='no'
+fi
+# AC_ARG_ENABLE
+if test "x$enable_debug" = "xno"
+then
+       collectd_debug=0
+else
+       if test "x$enable_debug" = "xyes"
+       then
+               collectd_debug=1
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: please specify either --enable-debug or --disable-debug; enabling debug." >&5
+$as_echo "$as_me: please specify either --enable-debug or --disable-debug; enabling debug." >&6;}
+               collectd_debug=1
+               enable_debug='yes'
+       fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define COLLECT_DEBUG $collectd_debug
+_ACEOF
+
+        if test "x$enable_debug" = "xyes"; then
+  BUILD_FEATURE_DEBUG_TRUE=
+  BUILD_FEATURE_DEBUG_FALSE='#'
+else
+  BUILD_FEATURE_DEBUG_TRUE='#'
+  BUILD_FEATURE_DEBUG_FALSE=
+fi
+
+
+                                                                                                                               # Check whether --enable-daemon was given.
+if test "${enable_daemon+set}" = set; then :
+  enableval=$enable_daemon;
+else
+  enable_daemon='yes'
+fi
+# AC_ARG_ENABLE
+if test "x$enable_daemon" = "xno"
+then
+       collectd_daemon=0
+else
+       if test "x$enable_daemon" = "xyes"
+       then
+               collectd_daemon=1
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: please specify either --enable-daemon or --disable-daemon; enabling daemon." >&5
+$as_echo "$as_me: please specify either --enable-daemon or --disable-daemon; enabling daemon." >&6;}
+               collectd_daemon=1
+               enable_daemon='yes'
+       fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define COLLECT_DAEMON $collectd_daemon
+_ACEOF
+
+        if test "x$enable_daemon" = "xyes"; then
+  BUILD_FEATURE_DAEMON_TRUE=
+  BUILD_FEATURE_DAEMON_FALSE='#'
+else
+  BUILD_FEATURE_DAEMON_TRUE='#'
+  BUILD_FEATURE_DAEMON_FALSE=
+fi
+
+
+                                                                               # Check whether --enable-getifaddrs was given.
+if test "${enable_getifaddrs+set}" = set; then :
+  enableval=$enable_getifaddrs;
+else
+  enable_getifaddrs='no'
+fi
+# AC_ARG_ENABLE
+if test "x$enable_getifaddrs" = "xno"
+then
+       collectd_getifaddrs=0
+else
+       if test "x$enable_getifaddrs" = "xyes"
+       then
+               collectd_getifaddrs=1
+       else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: please specify either --enable-getifaddrs or --disable-getifaddrs; enabling getifaddrs." >&5
+$as_echo "$as_me: please specify either --enable-getifaddrs or --disable-getifaddrs; enabling getifaddrs." >&6;}
+               collectd_getifaddrs=1
+               enable_getifaddrs='yes'
+       fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define COLLECT_GETIFADDRS $collectd_getifaddrs
+_ACEOF
+
+        if test "x$enable_getifaddrs" = "xyes"; then
+  BUILD_FEATURE_GETIFADDRS_TRUE=
+  BUILD_FEATURE_GETIFADDRS_FALSE='#'
+else
+  BUILD_FEATURE_GETIFADDRS_TRUE='#'
+  BUILD_FEATURE_GETIFADDRS_FALSE=
+fi
+
+
+dependency_warning="no"
+dependency_error="no"
+
+plugin_ascent="no"
+plugin_barometer="no"
+plugin_battery="no"
+plugin_bind="no"
+plugin_ceph="no"
+plugin_cgroups="no"
+plugin_conntrack="no"
+plugin_contextswitch="no"
+plugin_cpu="no"
+plugin_cpufreq="no"
+plugin_curl_json="no"
+plugin_curl_xml="no"
+plugin_df="no"
+plugin_disk="no"
+plugin_drbd="no"
+plugin_entropy="no"
+plugin_ethstat="no"
+plugin_fscache="no"
+plugin_interface="no"
+plugin_ipmi="no"
+plugin_ipvs="no"
+plugin_irq="no"
+plugin_load="no"
+plugin_log_logstash="no"
+plugin_memory="no"
+plugin_multimeter="no"
+plugin_nfs="no"
+plugin_numa="no"
+plugin_perl="no"
+plugin_processes="no"
+plugin_protocols="no"
+plugin_serial="no"
+plugin_swap="no"
+plugin_tape="no"
+plugin_tcpconns="no"
+plugin_ted="no"
+plugin_thermal="no"
+plugin_turbostat="no"
+plugin_uptime="no"
+plugin_users="no"
+plugin_virt="no"
+plugin_vmem="no"
+plugin_vserver="no"
+plugin_wireless="no"
+plugin_zfs_arc="no"
+plugin_zookeeper="no"
+
+# Linux
+if test "x$ac_system" = "xLinux"
+then
+       plugin_battery="yes"
+       plugin_conntrack="yes"
+       plugin_contextswitch="yes"
+       plugin_cgroups="yes"
+       plugin_cpu="yes"
+       plugin_cpufreq="yes"
+       plugin_disk="yes"
+       plugin_drbd="yes"
+       plugin_entropy="yes"
+       plugin_fscache="yes"
+       plugin_interface="yes"
+       plugin_ipc="yes"
+       plugin_irq="yes"
+       plugin_load="yes"
+       plugin_lvm="yes"
+       plugin_memory="yes"
+       plugin_nfs="yes"
+       plugin_numa="yes"
+       plugin_processes="yes"
+       plugin_protocols="yes"
+       plugin_serial="yes"
+       plugin_swap="yes"
+       plugin_tcpconns="yes"
+       plugin_thermal="yes"
+       plugin_uptime="yes"
+       plugin_vmem="yes"
+       plugin_vserver="yes"
+       plugin_wireless="yes"
+       plugin_zfs_arc="yes"
+
+       if test "x$have_linux_ip_vs_h" = "xyes" || test "x$have_net_ip_vs_h" = "xyes" || test "x$have_ip_vs_h" = "xyes"
+       then
+               plugin_ipvs="yes"
+       fi
+       if test "x$c_cv_have_usable_asm_msrindex_h" = "xyes" && test "x$have_cpuid_h" = "xyes"
+       then
+               plugin_turbostat="yes"
+       fi
+fi
+
+if test "x$ac_system" = "xOpenBSD"
+then
+       plugin_tcpconns="yes"
+fi
+
+# Mac OS X devices
+if test "x$with_libiokit" = "xyes"
+then
+       plugin_battery="yes"
+       plugin_disk="yes"
+fi
+
+# AIX
+
+if test "x$ac_system" = "xAIX"
+then
+        plugin_tcpconns="yes"
+        plugin_ipc="yes"
+fi
+
+# FreeBSD
+
+if test "x$ac_system" = "xFreeBSD"
+then
+        plugin_zfs_arc="yes"
+fi
+
+
+if test "x$with_perfstat" = "xyes"
+then
+       plugin_cpu="yes"
+       plugin_contextswitch="yes"
+       plugin_disk="yes"
+       plugin_memory="yes"
+       plugin_swap="yes"
+       plugin_interface="yes"
+       plugin_load="yes"
+       plugin_uptime="yes"
+fi
+
+if test "x$with_procinfo" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+# Solaris
+if test "x$with_kstat" = "xyes"
+then
+       plugin_nfs="yes"
+       plugin_processes="yes"
+       plugin_uptime="yes"
+       plugin_zfs_arc="yes"
+fi
+
+if test "x$with_devinfo$with_kstat" = "xyesyes"
+then
+       plugin_cpu="yes"
+       plugin_disk="yes"
+       plugin_interface="yes"
+       plugin_memory="yes"
+       plugin_tape="yes"
+fi
+
+# libi2c-dev
+with_libi2c="no"
+if test "x$ac_system" = "xLinux"
+then
+ac_fn_c_check_decl "$LINENO" "i2c_smbus_read_i2c_block_data" "ac_cv_have_decl_i2c_smbus_read_i2c_block_data" "#include <stdlib.h>
+       #include <linux/i2c-dev.h>
+"
+if test "x$ac_cv_have_decl_i2c_smbus_read_i2c_block_data" = xyes; then :
+  with_libi2c="yes"
+else
+  with_libi2c="no (symbol i2c_smbus_read_i2c_block_data not found - have you installed libi2c-dev ?)"
+fi
+
+fi
+
+if test "x$with_libi2c" = "xyes"
+then
+       plugin_barometer="yes"
+fi
+
+
+# libstatgrab
+if test "x$with_libstatgrab" = "xyes"
+then
+       plugin_cpu="yes"
+       plugin_disk="yes"
+       plugin_interface="yes"
+       plugin_load="yes"
+       plugin_memory="yes"
+       plugin_swap="yes"
+       plugin_users="yes"
+fi
+
+if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes"
+then
+       plugin_ascent="yes"
+       if test "x$have_strptime" = "xyes"
+       then
+               plugin_bind="yes"
+       fi
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       plugin_ipmi="yes"
+fi
+
+if test "x$with_libcurl" = "xyes" && test "x$with_libyajl" = "xyes"
+then
+       plugin_curl_json="yes"
+fi
+
+if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes"
+then
+       plugin_curl_xml="yes"
+fi
+
+if test "x$with_libyajl" = "xyes"
+then
+       plugin_ceph="yes"
+fi
+
+if test "x$have_processor_info" = "xyes"
+then
+       plugin_cpu="yes"
+fi
+if test "x$have_sysctl" = "xyes"
+then
+       plugin_cpu="yes"
+       plugin_memory="yes"
+       plugin_uptime="yes"
+       if test "x$ac_system" = "xDarwin"
+       then
+               plugin_swap="yes"
+       fi
+fi
+if test "x$have_sysctlbyname" = "xyes"
+then
+       plugin_contextswitch="yes"
+       plugin_cpu="yes"
+       plugin_memory="yes"
+       plugin_tcpconns="yes"
+fi
+
+# Df plugin: Check if we know how to determine mount points first.
+#if test "x$have_listmntent" = "xyes"; then
+#      plugin_df="yes"
+#fi
+if test "x$have_getvfsstat" = "xyes" || test "x$have_getfsstat" = "xyes"
+then
+       plugin_df="yes"
+fi
+if test "x$c_cv_have_two_getmntent" = "xyes" || test "x$have_getmntent" = "xgen" || test "x$have_getmntent" = "xsun"
+then
+       plugin_df="yes"
+fi
+#if test "x$have_getmntent" = "xseq"
+#then
+#      plugin_df="yes"
+#fi
+if test "x$c_cv_have_one_getmntent" = "xyes"
+then
+       plugin_df="yes"
+fi
+
+# Df plugin: Check if we have either `statfs' or `statvfs' second.
+if test "x$plugin_df" = "xyes"
+then
+       plugin_df="no"
+       if test "x$have_statfs" = "xyes"
+       then
+               plugin_df="yes"
+       fi
+       if test "x$have_statvfs" = "xyes"
+       then
+               plugin_df="yes"
+       fi
+fi
+
+if test "x$have_linux_sockios_h$have_linux_ethtool_h" = "xyesyes"
+then
+       plugin_ethstat="yes"
+fi
+
+if test "x$have_getifaddrs" = "xyes"
+then
+       plugin_interface="yes"
+fi
+
+if test "x$have_getloadavg" = "xyes"
+then
+       plugin_load="yes"
+fi
+
+if test "x$with_libyajl" = "xyes"
+then
+       plugin_log_logstash="yes"
+fi
+
+if test "x$c_cv_have_libperl$c_cv_have_perl_ithreads" = "xyesyes"
+then
+       plugin_perl="yes"
+fi
+
+# Mac OS X memory interface
+if test "x$have_host_statistics" = "xyes"
+then
+       plugin_memory="yes"
+fi
+
+if test "x$have_termios_h" = "xyes"
+then
+       if test "x$ac_system" != "xAIX"
+       then
+               plugin_multimeter="yes"
+       fi
+       plugin_ted="yes"
+fi
+
+if test "x$have_thread_info" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+if test "x$with_kvm_getprocs" = "xyes" && test "x$have_struct_kinfo_proc_freebsd" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+if test "x$with_kvm_getprocs" = "xyes" && test "x$have_struct_kinfo_proc_openbsd" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+if test "x$with_kvm_getswapinfo" = "xyes"
+then
+       plugin_swap="yes"
+fi
+
+if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_two_args" = "xyes"
+then
+       plugin_swap="yes"
+fi
+
+if test "x$with_kvm_openfiles$with_kvm_nlist" = "xyesyes"
+then
+       plugin_tcpconns="yes"
+fi
+
+if test "x$have_getutent" = "xyes"
+then
+       plugin_users="yes"
+fi
+if test "x$have_getutxent" = "xyes"
+then
+       plugin_users="yes"
+fi
+
+if test "x$with_libxml2" = "xyes" && test "x$with_libvirt" = "xyes"
+then
+       plugin_virt="yes"
+fi
+
+
+
+
+# Check whether --enable-all-plugins was given.
+if test "${enable_all_plugins+set}" = set; then :
+  enableval=$enable_all_plugins;
+                if test "x$enableval" = "xyes"
+                then
+                        enable_all_plugins="yes"
+                else if test "x$enableval" = "xauto"
+                then
+                        enable_all_plugins="auto"
+                else
+                        enable_all_plugins="no"
+                fi; fi
+
+else
+  enable_all_plugins="auto"
+fi
+
+
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-aggregation was given.
+if test "${enable_aggregation+set}" = set; then :
+  enableval=$enable_aggregation;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_AGGREGATION 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_AGGREGATION_TRUE=
+  BUILD_PLUGIN_AGGREGATION_FALSE='#'
+else
+  BUILD_PLUGIN_AGGREGATION_TRUE='#'
+  BUILD_PLUGIN_AGGREGATION_FALSE=
+fi
+
+    enable_aggregation="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-amqp was given.
+if test "${enable_amqp+set}" = set; then :
+  enableval=$enable_amqp;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_librabbitmq" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_librabbitmq" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_AMQP 1" >>confdefs.h
+
+                   if test "x$with_librabbitmq" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_AMQP_TRUE=
+  BUILD_PLUGIN_AMQP_FALSE='#'
+else
+  BUILD_PLUGIN_AMQP_TRUE='#'
+  BUILD_PLUGIN_AMQP_FALSE=
+fi
+
+    enable_amqp="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-apache was given.
+if test "${enable_apache+set}" = set; then :
+  enableval=$enable_apache;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libcurl" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libcurl" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_APACHE 1" >>confdefs.h
+
+                   if test "x$with_libcurl" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_APACHE_TRUE=
+  BUILD_PLUGIN_APACHE_FALSE='#'
+else
+  BUILD_PLUGIN_APACHE_TRUE='#'
+  BUILD_PLUGIN_APACHE_FALSE=
+fi
+
+    enable_apache="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-apcups was given.
+if test "${enable_apcups+set}" = set; then :
+  enableval=$enable_apcups;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_APCUPS 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_APCUPS_TRUE=
+  BUILD_PLUGIN_APCUPS_FALSE='#'
+else
+  BUILD_PLUGIN_APCUPS_TRUE='#'
+  BUILD_PLUGIN_APCUPS_FALSE=
+fi
+
+    enable_apcups="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-apple_sensors was given.
+if test "${enable_apple_sensors+set}" = set; then :
+  enableval=$enable_apple_sensors;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libiokit" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libiokit" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_APPLE_SENSORS 1" >>confdefs.h
+
+                   if test "x$with_libiokit" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_APPLE_SENSORS_TRUE=
+  BUILD_PLUGIN_APPLE_SENSORS_FALSE='#'
+else
+  BUILD_PLUGIN_APPLE_SENSORS_TRUE='#'
+  BUILD_PLUGIN_APPLE_SENSORS_FALSE=
+fi
+
+    enable_apple_sensors="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-aquaero was given.
+if test "${enable_aquaero+set}" = set; then :
+  enableval=$enable_aquaero;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libaquaero5" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libaquaero5" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_AQUAERO 1" >>confdefs.h
+
+                   if test "x$with_libaquaero5" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_AQUAERO_TRUE=
+  BUILD_PLUGIN_AQUAERO_FALSE='#'
+else
+  BUILD_PLUGIN_AQUAERO_TRUE='#'
+  BUILD_PLUGIN_AQUAERO_FALSE=
+fi
+
+    enable_aquaero="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ascent was given.
+if test "${enable_ascent+set}" = set; then :
+  enableval=$enable_ascent;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_ascent" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_ascent" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ASCENT 1" >>confdefs.h
+
+                   if test "x$plugin_ascent" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ASCENT_TRUE=
+  BUILD_PLUGIN_ASCENT_FALSE='#'
+else
+  BUILD_PLUGIN_ASCENT_TRUE='#'
+  BUILD_PLUGIN_ASCENT_FALSE=
+fi
+
+    enable_ascent="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-barometer was given.
+if test "${enable_barometer+set}" = set; then :
+  enableval=$enable_barometer;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_barometer" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_barometer" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_BAROMETER 1" >>confdefs.h
+
+                   if test "x$plugin_barometer" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_BAROMETER_TRUE=
+  BUILD_PLUGIN_BAROMETER_FALSE='#'
+else
+  BUILD_PLUGIN_BAROMETER_TRUE='#'
+  BUILD_PLUGIN_BAROMETER_FALSE=
+fi
+
+    enable_barometer="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-battery was given.
+if test "${enable_battery+set}" = set; then :
+  enableval=$enable_battery;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_battery" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_battery" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_BATTERY 1" >>confdefs.h
+
+                   if test "x$plugin_battery" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_BATTERY_TRUE=
+  BUILD_PLUGIN_BATTERY_FALSE='#'
+else
+  BUILD_PLUGIN_BATTERY_TRUE='#'
+  BUILD_PLUGIN_BATTERY_FALSE=
+fi
+
+    enable_battery="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-bind was given.
+if test "${enable_bind+set}" = set; then :
+  enableval=$enable_bind;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_bind" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_bind" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_BIND 1" >>confdefs.h
+
+                   if test "x$plugin_bind" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_BIND_TRUE=
+  BUILD_PLUGIN_BIND_FALSE='#'
+else
+  BUILD_PLUGIN_BIND_TRUE='#'
+  BUILD_PLUGIN_BIND_FALSE=
+fi
+
+    enable_bind="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ceph was given.
+if test "${enable_ceph+set}" = set; then :
+  enableval=$enable_ceph;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_ceph" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_ceph" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CEPH 1" >>confdefs.h
+
+                   if test "x$plugin_ceph" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CEPH_TRUE=
+  BUILD_PLUGIN_CEPH_FALSE='#'
+else
+  BUILD_PLUGIN_CEPH_TRUE='#'
+  BUILD_PLUGIN_CEPH_FALSE=
+fi
+
+    enable_ceph="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-conntrack was given.
+if test "${enable_conntrack+set}" = set; then :
+  enableval=$enable_conntrack;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_conntrack" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_conntrack" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CONNTRACK 1" >>confdefs.h
+
+                   if test "x$plugin_conntrack" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CONNTRACK_TRUE=
+  BUILD_PLUGIN_CONNTRACK_FALSE='#'
+else
+  BUILD_PLUGIN_CONNTRACK_TRUE='#'
+  BUILD_PLUGIN_CONNTRACK_FALSE=
+fi
+
+    enable_conntrack="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-contextswitch was given.
+if test "${enable_contextswitch+set}" = set; then :
+  enableval=$enable_contextswitch;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_contextswitch" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_contextswitch" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CONTEXTSWITCH 1" >>confdefs.h
+
+                   if test "x$plugin_contextswitch" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CONTEXTSWITCH_TRUE=
+  BUILD_PLUGIN_CONTEXTSWITCH_FALSE='#'
+else
+  BUILD_PLUGIN_CONTEXTSWITCH_TRUE='#'
+  BUILD_PLUGIN_CONTEXTSWITCH_FALSE=
+fi
+
+    enable_contextswitch="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-cpufreq was given.
+if test "${enable_cpufreq+set}" = set; then :
+  enableval=$enable_cpufreq;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_cpufreq" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_cpufreq" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CPUFREQ 1" >>confdefs.h
+
+                   if test "x$plugin_cpufreq" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CPUFREQ_TRUE=
+  BUILD_PLUGIN_CPUFREQ_FALSE='#'
+else
+  BUILD_PLUGIN_CPUFREQ_TRUE='#'
+  BUILD_PLUGIN_CPUFREQ_FALSE=
+fi
+
+    enable_cpufreq="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-cpu was given.
+if test "${enable_cpu+set}" = set; then :
+  enableval=$enable_cpu;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_cpu" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_cpu" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CPU 1" >>confdefs.h
+
+                   if test "x$plugin_cpu" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CPU_TRUE=
+  BUILD_PLUGIN_CPU_FALSE='#'
+else
+  BUILD_PLUGIN_CPU_TRUE='#'
+  BUILD_PLUGIN_CPU_FALSE=
+fi
+
+    enable_cpu="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-csv was given.
+if test "${enable_csv+set}" = set; then :
+  enableval=$enable_csv;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CSV 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CSV_TRUE=
+  BUILD_PLUGIN_CSV_FALSE='#'
+else
+  BUILD_PLUGIN_CSV_TRUE='#'
+  BUILD_PLUGIN_CSV_FALSE=
+fi
+
+    enable_csv="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-curl was given.
+if test "${enable_curl+set}" = set; then :
+  enableval=$enable_curl;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libcurl" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libcurl" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CURL 1" >>confdefs.h
+
+                   if test "x$with_libcurl" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CURL_TRUE=
+  BUILD_PLUGIN_CURL_FALSE='#'
+else
+  BUILD_PLUGIN_CURL_TRUE='#'
+  BUILD_PLUGIN_CURL_FALSE=
+fi
+
+    enable_curl="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-curl_json was given.
+if test "${enable_curl_json+set}" = set; then :
+  enableval=$enable_curl_json;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_curl_json" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_curl_json" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CURL_JSON 1" >>confdefs.h
+
+                   if test "x$plugin_curl_json" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CURL_JSON_TRUE=
+  BUILD_PLUGIN_CURL_JSON_FALSE='#'
+else
+  BUILD_PLUGIN_CURL_JSON_TRUE='#'
+  BUILD_PLUGIN_CURL_JSON_FALSE=
+fi
+
+    enable_curl_json="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-curl_xml was given.
+if test "${enable_curl_xml+set}" = set; then :
+  enableval=$enable_curl_xml;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_curl_xml" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_curl_xml" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CURL_XML 1" >>confdefs.h
+
+                   if test "x$plugin_curl_xml" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CURL_XML_TRUE=
+  BUILD_PLUGIN_CURL_XML_FALSE='#'
+else
+  BUILD_PLUGIN_CURL_XML_TRUE='#'
+  BUILD_PLUGIN_CURL_XML_FALSE=
+fi
+
+    enable_curl_xml="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-cgroups was given.
+if test "${enable_cgroups+set}" = set; then :
+  enableval=$enable_cgroups;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_cgroups" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_cgroups" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_CGROUPS 1" >>confdefs.h
+
+                   if test "x$plugin_cgroups" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_CGROUPS_TRUE=
+  BUILD_PLUGIN_CGROUPS_FALSE='#'
+else
+  BUILD_PLUGIN_CGROUPS_TRUE='#'
+  BUILD_PLUGIN_CGROUPS_FALSE=
+fi
+
+    enable_cgroups="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-dbi was given.
+if test "${enable_dbi+set}" = set; then :
+  enableval=$enable_dbi;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libdbi" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libdbi" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_DBI 1" >>confdefs.h
+
+                   if test "x$with_libdbi" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_DBI_TRUE=
+  BUILD_PLUGIN_DBI_FALSE='#'
+else
+  BUILD_PLUGIN_DBI_TRUE='#'
+  BUILD_PLUGIN_DBI_FALSE=
+fi
+
+    enable_dbi="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-df was given.
+if test "${enable_df+set}" = set; then :
+  enableval=$enable_df;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_df" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_df" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_DF 1" >>confdefs.h
+
+                   if test "x$plugin_df" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_DF_TRUE=
+  BUILD_PLUGIN_DF_FALSE='#'
+else
+  BUILD_PLUGIN_DF_TRUE='#'
+  BUILD_PLUGIN_DF_FALSE=
+fi
+
+    enable_df="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-disk was given.
+if test "${enable_disk+set}" = set; then :
+  enableval=$enable_disk;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_disk" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_disk" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_DISK 1" >>confdefs.h
+
+                   if test "x$plugin_disk" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_DISK_TRUE=
+  BUILD_PLUGIN_DISK_FALSE='#'
+else
+  BUILD_PLUGIN_DISK_TRUE='#'
+  BUILD_PLUGIN_DISK_FALSE=
+fi
+
+    enable_disk="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-drbd was given.
+if test "${enable_drbd+set}" = set; then :
+  enableval=$enable_drbd;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_drbd" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_drbd" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_DRBD 1" >>confdefs.h
+
+                   if test "x$plugin_drbd" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_DRBD_TRUE=
+  BUILD_PLUGIN_DRBD_FALSE='#'
+else
+  BUILD_PLUGIN_DRBD_TRUE='#'
+  BUILD_PLUGIN_DRBD_FALSE=
+fi
+
+    enable_drbd="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-dns was given.
+if test "${enable_dns+set}" = set; then :
+  enableval=$enable_dns;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libpcap" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libpcap" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_DNS 1" >>confdefs.h
+
+                   if test "x$with_libpcap" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_DNS_TRUE=
+  BUILD_PLUGIN_DNS_FALSE='#'
+else
+  BUILD_PLUGIN_DNS_TRUE='#'
+  BUILD_PLUGIN_DNS_FALSE=
+fi
+
+    enable_dns="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-email was given.
+if test "${enable_email+set}" = set; then :
+  enableval=$enable_email;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_EMAIL 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_EMAIL_TRUE=
+  BUILD_PLUGIN_EMAIL_FALSE='#'
+else
+  BUILD_PLUGIN_EMAIL_TRUE='#'
+  BUILD_PLUGIN_EMAIL_FALSE=
+fi
+
+    enable_email="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-entropy was given.
+if test "${enable_entropy+set}" = set; then :
+  enableval=$enable_entropy;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_entropy" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_entropy" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ENTROPY 1" >>confdefs.h
+
+                   if test "x$plugin_entropy" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ENTROPY_TRUE=
+  BUILD_PLUGIN_ENTROPY_FALSE='#'
+else
+  BUILD_PLUGIN_ENTROPY_TRUE='#'
+  BUILD_PLUGIN_ENTROPY_FALSE=
+fi
+
+    enable_entropy="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ethstat was given.
+if test "${enable_ethstat+set}" = set; then :
+  enableval=$enable_ethstat;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_ethstat" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_ethstat" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ETHSTAT 1" >>confdefs.h
+
+                   if test "x$plugin_ethstat" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ETHSTAT_TRUE=
+  BUILD_PLUGIN_ETHSTAT_FALSE='#'
+else
+  BUILD_PLUGIN_ETHSTAT_TRUE='#'
+  BUILD_PLUGIN_ETHSTAT_FALSE=
+fi
+
+    enable_ethstat="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-exec was given.
+if test "${enable_exec+set}" = set; then :
+  enableval=$enable_exec;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_EXEC 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_EXEC_TRUE=
+  BUILD_PLUGIN_EXEC_FALSE='#'
+else
+  BUILD_PLUGIN_EXEC_TRUE='#'
+  BUILD_PLUGIN_EXEC_FALSE=
+fi
+
+    enable_exec="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-fhcount was given.
+if test "${enable_fhcount+set}" = set; then :
+  enableval=$enable_fhcount;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_FHCOUNT 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_FHCOUNT_TRUE=
+  BUILD_PLUGIN_FHCOUNT_FALSE='#'
+else
+  BUILD_PLUGIN_FHCOUNT_TRUE='#'
+  BUILD_PLUGIN_FHCOUNT_FALSE=
+fi
+
+    enable_fhcount="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-filecount was given.
+if test "${enable_filecount+set}" = set; then :
+  enableval=$enable_filecount;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_FILECOUNT 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_FILECOUNT_TRUE=
+  BUILD_PLUGIN_FILECOUNT_FALSE='#'
+else
+  BUILD_PLUGIN_FILECOUNT_TRUE='#'
+  BUILD_PLUGIN_FILECOUNT_FALSE=
+fi
+
+    enable_filecount="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-fscache was given.
+if test "${enable_fscache+set}" = set; then :
+  enableval=$enable_fscache;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_fscache" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_fscache" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_FSCACHE 1" >>confdefs.h
+
+                   if test "x$plugin_fscache" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_FSCACHE_TRUE=
+  BUILD_PLUGIN_FSCACHE_FALSE='#'
+else
+  BUILD_PLUGIN_FSCACHE_TRUE='#'
+  BUILD_PLUGIN_FSCACHE_FALSE=
+fi
+
+    enable_fscache="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-gmond was given.
+if test "${enable_gmond+set}" = set; then :
+  enableval=$enable_gmond;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libganglia" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libganglia" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_GMOND 1" >>confdefs.h
+
+                   if test "x$with_libganglia" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_GMOND_TRUE=
+  BUILD_PLUGIN_GMOND_FALSE='#'
+else
+  BUILD_PLUGIN_GMOND_TRUE='#'
+  BUILD_PLUGIN_GMOND_FALSE=
+fi
+
+    enable_gmond="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-hddtemp was given.
+if test "${enable_hddtemp+set}" = set; then :
+  enableval=$enable_hddtemp;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_HDDTEMP 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_HDDTEMP_TRUE=
+  BUILD_PLUGIN_HDDTEMP_FALSE='#'
+else
+  BUILD_PLUGIN_HDDTEMP_TRUE='#'
+  BUILD_PLUGIN_HDDTEMP_FALSE=
+fi
+
+    enable_hddtemp="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-interface was given.
+if test "${enable_interface+set}" = set; then :
+  enableval=$enable_interface;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_interface" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_interface" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_INTERFACE 1" >>confdefs.h
+
+                   if test "x$plugin_interface" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_INTERFACE_TRUE=
+  BUILD_PLUGIN_INTERFACE_FALSE='#'
+else
+  BUILD_PLUGIN_INTERFACE_TRUE='#'
+  BUILD_PLUGIN_INTERFACE_FALSE=
+fi
+
+    enable_interface="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ipc was given.
+if test "${enable_ipc+set}" = set; then :
+  enableval=$enable_ipc;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_ipc" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_ipc" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_IPC 1" >>confdefs.h
+
+                   if test "x$plugin_ipc" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_IPC_TRUE=
+  BUILD_PLUGIN_IPC_FALSE='#'
+else
+  BUILD_PLUGIN_IPC_TRUE='#'
+  BUILD_PLUGIN_IPC_FALSE=
+fi
+
+    enable_ipc="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ipmi was given.
+if test "${enable_ipmi+set}" = set; then :
+  enableval=$enable_ipmi;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_ipmi" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_ipmi" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_IPMI 1" >>confdefs.h
+
+                   if test "x$plugin_ipmi" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_IPMI_TRUE=
+  BUILD_PLUGIN_IPMI_FALSE='#'
+else
+  BUILD_PLUGIN_IPMI_TRUE='#'
+  BUILD_PLUGIN_IPMI_FALSE=
+fi
+
+    enable_ipmi="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-iptables was given.
+if test "${enable_iptables+set}" = set; then :
+  enableval=$enable_iptables;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libiptc" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libiptc" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_IPTABLES 1" >>confdefs.h
+
+                   if test "x$with_libiptc" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_IPTABLES_TRUE=
+  BUILD_PLUGIN_IPTABLES_FALSE='#'
+else
+  BUILD_PLUGIN_IPTABLES_TRUE='#'
+  BUILD_PLUGIN_IPTABLES_FALSE=
+fi
+
+    enable_iptables="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ipvs was given.
+if test "${enable_ipvs+set}" = set; then :
+  enableval=$enable_ipvs;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_ipvs" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_ipvs" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_IPVS 1" >>confdefs.h
+
+                   if test "x$plugin_ipvs" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_IPVS_TRUE=
+  BUILD_PLUGIN_IPVS_FALSE='#'
+else
+  BUILD_PLUGIN_IPVS_TRUE='#'
+  BUILD_PLUGIN_IPVS_FALSE=
+fi
+
+    enable_ipvs="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-irq was given.
+if test "${enable_irq+set}" = set; then :
+  enableval=$enable_irq;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_irq" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_irq" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_IRQ 1" >>confdefs.h
+
+                   if test "x$plugin_irq" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_IRQ_TRUE=
+  BUILD_PLUGIN_IRQ_FALSE='#'
+else
+  BUILD_PLUGIN_IRQ_TRUE='#'
+  BUILD_PLUGIN_IRQ_FALSE=
+fi
+
+    enable_irq="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-java was given.
+if test "${enable_java+set}" = set; then :
+  enableval=$enable_java;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_java" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_java" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_JAVA 1" >>confdefs.h
+
+                   if test "x$with_java" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_JAVA_TRUE=
+  BUILD_PLUGIN_JAVA_FALSE='#'
+else
+  BUILD_PLUGIN_JAVA_TRUE='#'
+  BUILD_PLUGIN_JAVA_FALSE=
+fi
+
+    enable_java="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-load was given.
+if test "${enable_load+set}" = set; then :
+  enableval=$enable_load;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_load" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_load" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_LOAD 1" >>confdefs.h
+
+                   if test "x$plugin_load" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_LOAD_TRUE=
+  BUILD_PLUGIN_LOAD_FALSE='#'
+else
+  BUILD_PLUGIN_LOAD_TRUE='#'
+  BUILD_PLUGIN_LOAD_FALSE=
+fi
+
+    enable_load="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-logfile was given.
+if test "${enable_logfile+set}" = set; then :
+  enableval=$enable_logfile;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_LOGFILE 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_LOGFILE_TRUE=
+  BUILD_PLUGIN_LOGFILE_FALSE='#'
+else
+  BUILD_PLUGIN_LOGFILE_TRUE='#'
+  BUILD_PLUGIN_LOGFILE_FALSE=
+fi
+
+    enable_logfile="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-log_logstash was given.
+if test "${enable_log_logstash+set}" = set; then :
+  enableval=$enable_log_logstash;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_log_logstash" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_log_logstash" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_LOG_LOGSTASH 1" >>confdefs.h
+
+                   if test "x$plugin_log_logstash" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_LOG_LOGSTASH_TRUE=
+  BUILD_PLUGIN_LOG_LOGSTASH_FALSE='#'
+else
+  BUILD_PLUGIN_LOG_LOGSTASH_TRUE='#'
+  BUILD_PLUGIN_LOG_LOGSTASH_FALSE=
+fi
+
+    enable_log_logstash="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-lpar was given.
+if test "${enable_lpar+set}" = set; then :
+  enableval=$enable_lpar;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_perfstat" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_perfstat" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_LPAR 1" >>confdefs.h
+
+                   if test "x$with_perfstat" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_LPAR_TRUE=
+  BUILD_PLUGIN_LPAR_FALSE='#'
+else
+  BUILD_PLUGIN_LPAR_TRUE='#'
+  BUILD_PLUGIN_LPAR_FALSE=
+fi
+
+    enable_lpar="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-lvm was given.
+if test "${enable_lvm+set}" = set; then :
+  enableval=$enable_lvm;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_liblvm2app" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_liblvm2app" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_LVM 1" >>confdefs.h
+
+                   if test "x$with_liblvm2app" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_LVM_TRUE=
+  BUILD_PLUGIN_LVM_FALSE='#'
+else
+  BUILD_PLUGIN_LVM_TRUE='#'
+  BUILD_PLUGIN_LVM_FALSE=
+fi
+
+    enable_lvm="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-madwifi was given.
+if test "${enable_madwifi+set}" = set; then :
+  enableval=$enable_madwifi;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$have_linux_wireless_h" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$have_linux_wireless_h" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MADWIFI 1" >>confdefs.h
+
+                   if test "x$have_linux_wireless_h" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MADWIFI_TRUE=
+  BUILD_PLUGIN_MADWIFI_FALSE='#'
+else
+  BUILD_PLUGIN_MADWIFI_TRUE='#'
+  BUILD_PLUGIN_MADWIFI_FALSE=
+fi
+
+    enable_madwifi="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-match_empty_counter was given.
+if test "${enable_match_empty_counter+set}" = set; then :
+  enableval=$enable_match_empty_counter;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MATCH_EMPTY_COUNTER 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE=
+  BUILD_PLUGIN_MATCH_EMPTY_COUNTER_FALSE='#'
+else
+  BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE='#'
+  BUILD_PLUGIN_MATCH_EMPTY_COUNTER_FALSE=
+fi
+
+    enable_match_empty_counter="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-match_hashed was given.
+if test "${enable_match_hashed+set}" = set; then :
+  enableval=$enable_match_hashed;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MATCH_HASHED 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MATCH_HASHED_TRUE=
+  BUILD_PLUGIN_MATCH_HASHED_FALSE='#'
+else
+  BUILD_PLUGIN_MATCH_HASHED_TRUE='#'
+  BUILD_PLUGIN_MATCH_HASHED_FALSE=
+fi
+
+    enable_match_hashed="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-match_regex was given.
+if test "${enable_match_regex+set}" = set; then :
+  enableval=$enable_match_regex;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MATCH_REGEX 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MATCH_REGEX_TRUE=
+  BUILD_PLUGIN_MATCH_REGEX_FALSE='#'
+else
+  BUILD_PLUGIN_MATCH_REGEX_TRUE='#'
+  BUILD_PLUGIN_MATCH_REGEX_FALSE=
+fi
+
+    enable_match_regex="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-match_timediff was given.
+if test "${enable_match_timediff+set}" = set; then :
+  enableval=$enable_match_timediff;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MATCH_TIMEDIFF 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE=
+  BUILD_PLUGIN_MATCH_TIMEDIFF_FALSE='#'
+else
+  BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE='#'
+  BUILD_PLUGIN_MATCH_TIMEDIFF_FALSE=
+fi
+
+    enable_match_timediff="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-match_value was given.
+if test "${enable_match_value+set}" = set; then :
+  enableval=$enable_match_value;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MATCH_VALUE 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MATCH_VALUE_TRUE=
+  BUILD_PLUGIN_MATCH_VALUE_FALSE='#'
+else
+  BUILD_PLUGIN_MATCH_VALUE_TRUE='#'
+  BUILD_PLUGIN_MATCH_VALUE_FALSE=
+fi
+
+    enable_match_value="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-mbmon was given.
+if test "${enable_mbmon+set}" = set; then :
+  enableval=$enable_mbmon;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MBMON 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MBMON_TRUE=
+  BUILD_PLUGIN_MBMON_FALSE='#'
+else
+  BUILD_PLUGIN_MBMON_TRUE='#'
+  BUILD_PLUGIN_MBMON_FALSE=
+fi
+
+    enable_mbmon="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-md was given.
+if test "${enable_md+set}" = set; then :
+  enableval=$enable_md;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$have_linux_raid_md_u_h" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$have_linux_raid_md_u_h" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MD 1" >>confdefs.h
+
+                   if test "x$have_linux_raid_md_u_h" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MD_TRUE=
+  BUILD_PLUGIN_MD_FALSE='#'
+else
+  BUILD_PLUGIN_MD_TRUE='#'
+  BUILD_PLUGIN_MD_FALSE=
+fi
+
+    enable_md="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-memcachec was given.
+if test "${enable_memcachec+set}" = set; then :
+  enableval=$enable_memcachec;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libmemcached" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libmemcached" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MEMCACHEC 1" >>confdefs.h
+
+                   if test "x$with_libmemcached" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MEMCACHEC_TRUE=
+  BUILD_PLUGIN_MEMCACHEC_FALSE='#'
+else
+  BUILD_PLUGIN_MEMCACHEC_TRUE='#'
+  BUILD_PLUGIN_MEMCACHEC_FALSE=
+fi
+
+    enable_memcachec="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-memcached was given.
+if test "${enable_memcached+set}" = set; then :
+  enableval=$enable_memcached;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MEMCACHED 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MEMCACHED_TRUE=
+  BUILD_PLUGIN_MEMCACHED_FALSE='#'
+else
+  BUILD_PLUGIN_MEMCACHED_TRUE='#'
+  BUILD_PLUGIN_MEMCACHED_FALSE=
+fi
+
+    enable_memcached="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-memory was given.
+if test "${enable_memory+set}" = set; then :
+  enableval=$enable_memory;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_memory" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_memory" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MEMORY 1" >>confdefs.h
+
+                   if test "x$plugin_memory" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MEMORY_TRUE=
+  BUILD_PLUGIN_MEMORY_FALSE='#'
+else
+  BUILD_PLUGIN_MEMORY_TRUE='#'
+  BUILD_PLUGIN_MEMORY_FALSE=
+fi
+
+    enable_memory="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-mic was given.
+if test "${enable_mic+set}" = set; then :
+  enableval=$enable_mic;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_mic" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_mic" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MIC 1" >>confdefs.h
+
+                   if test "x$with_mic" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MIC_TRUE=
+  BUILD_PLUGIN_MIC_FALSE='#'
+else
+  BUILD_PLUGIN_MIC_TRUE='#'
+  BUILD_PLUGIN_MIC_FALSE=
+fi
+
+    enable_mic="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-modbus was given.
+if test "${enable_modbus+set}" = set; then :
+  enableval=$enable_modbus;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libmodbus" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libmodbus" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MODBUS 1" >>confdefs.h
+
+                   if test "x$with_libmodbus" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MODBUS_TRUE=
+  BUILD_PLUGIN_MODBUS_FALSE='#'
+else
+  BUILD_PLUGIN_MODBUS_TRUE='#'
+  BUILD_PLUGIN_MODBUS_FALSE=
+fi
+
+    enable_modbus="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-multimeter was given.
+if test "${enable_multimeter+set}" = set; then :
+  enableval=$enable_multimeter;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_multimeter" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_multimeter" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MULTIMETER 1" >>confdefs.h
+
+                   if test "x$plugin_multimeter" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MULTIMETER_TRUE=
+  BUILD_PLUGIN_MULTIMETER_FALSE='#'
+else
+  BUILD_PLUGIN_MULTIMETER_TRUE='#'
+  BUILD_PLUGIN_MULTIMETER_FALSE=
+fi
+
+    enable_multimeter="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-mysql was given.
+if test "${enable_mysql+set}" = set; then :
+  enableval=$enable_mysql;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libmysql" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libmysql" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_MYSQL 1" >>confdefs.h
+
+                   if test "x$with_libmysql" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_MYSQL_TRUE=
+  BUILD_PLUGIN_MYSQL_FALSE='#'
+else
+  BUILD_PLUGIN_MYSQL_TRUE='#'
+  BUILD_PLUGIN_MYSQL_FALSE=
+fi
+
+    enable_mysql="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-netapp was given.
+if test "${enable_netapp+set}" = set; then :
+  enableval=$enable_netapp;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libnetapp" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libnetapp" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NETAPP 1" >>confdefs.h
+
+                   if test "x$with_libnetapp" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NETAPP_TRUE=
+  BUILD_PLUGIN_NETAPP_FALSE='#'
+else
+  BUILD_PLUGIN_NETAPP_TRUE='#'
+  BUILD_PLUGIN_NETAPP_FALSE=
+fi
+
+    enable_netapp="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-netlink was given.
+if test "${enable_netlink+set}" = set; then :
+  enableval=$enable_netlink;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libmnl" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libmnl" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NETLINK 1" >>confdefs.h
+
+                   if test "x$with_libmnl" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NETLINK_TRUE=
+  BUILD_PLUGIN_NETLINK_FALSE='#'
+else
+  BUILD_PLUGIN_NETLINK_TRUE='#'
+  BUILD_PLUGIN_NETLINK_FALSE=
+fi
+
+    enable_netlink="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-network was given.
+if test "${enable_network+set}" = set; then :
+  enableval=$enable_network;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NETWORK 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NETWORK_TRUE=
+  BUILD_PLUGIN_NETWORK_FALSE='#'
+else
+  BUILD_PLUGIN_NETWORK_TRUE='#'
+  BUILD_PLUGIN_NETWORK_FALSE=
+fi
+
+    enable_network="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-nfs was given.
+if test "${enable_nfs+set}" = set; then :
+  enableval=$enable_nfs;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_nfs" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_nfs" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NFS 1" >>confdefs.h
+
+                   if test "x$plugin_nfs" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NFS_TRUE=
+  BUILD_PLUGIN_NFS_FALSE='#'
+else
+  BUILD_PLUGIN_NFS_TRUE='#'
+  BUILD_PLUGIN_NFS_FALSE=
+fi
+
+    enable_nfs="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-nginx was given.
+if test "${enable_nginx+set}" = set; then :
+  enableval=$enable_nginx;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libcurl" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libcurl" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NGINX 1" >>confdefs.h
+
+                   if test "x$with_libcurl" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NGINX_TRUE=
+  BUILD_PLUGIN_NGINX_FALSE='#'
+else
+  BUILD_PLUGIN_NGINX_TRUE='#'
+  BUILD_PLUGIN_NGINX_FALSE=
+fi
+
+    enable_nginx="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-notify_desktop was given.
+if test "${enable_notify_desktop+set}" = set; then :
+  enableval=$enable_notify_desktop;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libnotify" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libnotify" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NOTIFY_DESKTOP 1" >>confdefs.h
+
+                   if test "x$with_libnotify" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE=
+  BUILD_PLUGIN_NOTIFY_DESKTOP_FALSE='#'
+else
+  BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE='#'
+  BUILD_PLUGIN_NOTIFY_DESKTOP_FALSE=
+fi
+
+    enable_notify_desktop="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-notify_email was given.
+if test "${enable_notify_email+set}" = set; then :
+  enableval=$enable_notify_email;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libesmtp" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libesmtp" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NOTIFY_EMAIL 1" >>confdefs.h
+
+                   if test "x$with_libesmtp" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NOTIFY_EMAIL_TRUE=
+  BUILD_PLUGIN_NOTIFY_EMAIL_FALSE='#'
+else
+  BUILD_PLUGIN_NOTIFY_EMAIL_TRUE='#'
+  BUILD_PLUGIN_NOTIFY_EMAIL_FALSE=
+fi
+
+    enable_notify_email="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ntpd was given.
+if test "${enable_ntpd+set}" = set; then :
+  enableval=$enable_ntpd;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NTPD 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NTPD_TRUE=
+  BUILD_PLUGIN_NTPD_FALSE='#'
+else
+  BUILD_PLUGIN_NTPD_TRUE='#'
+  BUILD_PLUGIN_NTPD_FALSE=
+fi
+
+    enable_ntpd="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-numa was given.
+if test "${enable_numa+set}" = set; then :
+  enableval=$enable_numa;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_numa" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_numa" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NUMA 1" >>confdefs.h
+
+                   if test "x$plugin_numa" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NUMA_TRUE=
+  BUILD_PLUGIN_NUMA_FALSE='#'
+else
+  BUILD_PLUGIN_NUMA_TRUE='#'
+  BUILD_PLUGIN_NUMA_FALSE=
+fi
+
+    enable_numa="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-nut was given.
+if test "${enable_nut+set}" = set; then :
+  enableval=$enable_nut;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libupsclient" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libupsclient" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_NUT 1" >>confdefs.h
+
+                   if test "x$with_libupsclient" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_NUT_TRUE=
+  BUILD_PLUGIN_NUT_FALSE='#'
+else
+  BUILD_PLUGIN_NUT_TRUE='#'
+  BUILD_PLUGIN_NUT_FALSE=
+fi
+
+    enable_nut="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-olsrd was given.
+if test "${enable_olsrd+set}" = set; then :
+  enableval=$enable_olsrd;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_OLSRD 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_OLSRD_TRUE=
+  BUILD_PLUGIN_OLSRD_FALSE='#'
+else
+  BUILD_PLUGIN_OLSRD_TRUE='#'
+  BUILD_PLUGIN_OLSRD_FALSE=
+fi
+
+    enable_olsrd="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-onewire was given.
+if test "${enable_onewire+set}" = set; then :
+  enableval=$enable_onewire;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libowcapi" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libowcapi" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ONEWIRE 1" >>confdefs.h
+
+                   if test "x$with_libowcapi" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ONEWIRE_TRUE=
+  BUILD_PLUGIN_ONEWIRE_FALSE='#'
+else
+  BUILD_PLUGIN_ONEWIRE_TRUE='#'
+  BUILD_PLUGIN_ONEWIRE_FALSE=
+fi
+
+    enable_onewire="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-openldap was given.
+if test "${enable_openldap+set}" = set; then :
+  enableval=$enable_openldap;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libldap" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libldap" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_OPENLDAP 1" >>confdefs.h
+
+                   if test "x$with_libldap" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_OPENLDAP_TRUE=
+  BUILD_PLUGIN_OPENLDAP_FALSE='#'
+else
+  BUILD_PLUGIN_OPENLDAP_TRUE='#'
+  BUILD_PLUGIN_OPENLDAP_FALSE=
+fi
+
+    enable_openldap="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-openvpn was given.
+if test "${enable_openvpn+set}" = set; then :
+  enableval=$enable_openvpn;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_OPENVPN 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_OPENVPN_TRUE=
+  BUILD_PLUGIN_OPENVPN_FALSE='#'
+else
+  BUILD_PLUGIN_OPENVPN_TRUE='#'
+  BUILD_PLUGIN_OPENVPN_FALSE=
+fi
+
+    enable_openvpn="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-oracle was given.
+if test "${enable_oracle+set}" = set; then :
+  enableval=$enable_oracle;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_oracle" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_oracle" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ORACLE 1" >>confdefs.h
+
+                   if test "x$with_oracle" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ORACLE_TRUE=
+  BUILD_PLUGIN_ORACLE_FALSE='#'
+else
+  BUILD_PLUGIN_ORACLE_TRUE='#'
+  BUILD_PLUGIN_ORACLE_FALSE=
+fi
+
+    enable_oracle="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-perl was given.
+if test "${enable_perl+set}" = set; then :
+  enableval=$enable_perl;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_perl" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_perl" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_PERL 1" >>confdefs.h
+
+                   if test "x$plugin_perl" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_PERL_TRUE=
+  BUILD_PLUGIN_PERL_FALSE='#'
+else
+  BUILD_PLUGIN_PERL_TRUE='#'
+  BUILD_PLUGIN_PERL_FALSE=
+fi
+
+    enable_perl="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-pf was given.
+if test "${enable_pf+set}" = set; then :
+  enableval=$enable_pf;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$have_net_pfvar_h" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$have_net_pfvar_h" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_PF 1" >>confdefs.h
+
+                   if test "x$have_net_pfvar_h" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_PF_TRUE=
+  BUILD_PLUGIN_PF_FALSE='#'
+else
+  BUILD_PLUGIN_PF_TRUE='#'
+  BUILD_PLUGIN_PF_FALSE=
+fi
+
+    enable_pf="$enable_plugin"
+
+
+# FIXME: Check for libevent, too.
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-pinba was given.
+if test "${enable_pinba+set}" = set; then :
+  enableval=$enable_pinba;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$have_protoc_c" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$have_protoc_c" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_PINBA 1" >>confdefs.h
+
+                   if test "x$have_protoc_c" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_PINBA_TRUE=
+  BUILD_PLUGIN_PINBA_FALSE='#'
+else
+  BUILD_PLUGIN_PINBA_TRUE='#'
+  BUILD_PLUGIN_PINBA_FALSE=
+fi
+
+    enable_pinba="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ping was given.
+if test "${enable_ping+set}" = set; then :
+  enableval=$enable_ping;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_liboping" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_liboping" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_PING 1" >>confdefs.h
+
+                   if test "x$with_liboping" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_PING_TRUE=
+  BUILD_PLUGIN_PING_FALSE='#'
+else
+  BUILD_PLUGIN_PING_TRUE='#'
+  BUILD_PLUGIN_PING_FALSE=
+fi
+
+    enable_ping="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-postgresql was given.
+if test "${enable_postgresql+set}" = set; then :
+  enableval=$enable_postgresql;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libpq" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libpq" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_POSTGRESQL 1" >>confdefs.h
+
+                   if test "x$with_libpq" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_POSTGRESQL_TRUE=
+  BUILD_PLUGIN_POSTGRESQL_FALSE='#'
+else
+  BUILD_PLUGIN_POSTGRESQL_TRUE='#'
+  BUILD_PLUGIN_POSTGRESQL_FALSE=
+fi
+
+    enable_postgresql="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-powerdns was given.
+if test "${enable_powerdns+set}" = set; then :
+  enableval=$enable_powerdns;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_POWERDNS 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_POWERDNS_TRUE=
+  BUILD_PLUGIN_POWERDNS_FALSE='#'
+else
+  BUILD_PLUGIN_POWERDNS_TRUE='#'
+  BUILD_PLUGIN_POWERDNS_FALSE=
+fi
+
+    enable_powerdns="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-processes was given.
+if test "${enable_processes+set}" = set; then :
+  enableval=$enable_processes;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_processes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_processes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_PROCESSES 1" >>confdefs.h
+
+                   if test "x$plugin_processes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_PROCESSES_TRUE=
+  BUILD_PLUGIN_PROCESSES_FALSE='#'
+else
+  BUILD_PLUGIN_PROCESSES_TRUE='#'
+  BUILD_PLUGIN_PROCESSES_FALSE=
+fi
+
+    enable_processes="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-protocols was given.
+if test "${enable_protocols+set}" = set; then :
+  enableval=$enable_protocols;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_protocols" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_protocols" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_PROTOCOLS 1" >>confdefs.h
+
+                   if test "x$plugin_protocols" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_PROTOCOLS_TRUE=
+  BUILD_PLUGIN_PROTOCOLS_FALSE='#'
+else
+  BUILD_PLUGIN_PROTOCOLS_TRUE='#'
+  BUILD_PLUGIN_PROTOCOLS_FALSE=
+fi
+
+    enable_protocols="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-python was given.
+if test "${enable_python+set}" = set; then :
+  enableval=$enable_python;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_python" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_python" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_PYTHON 1" >>confdefs.h
+
+                   if test "x$with_python" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_PYTHON_TRUE=
+  BUILD_PLUGIN_PYTHON_FALSE='#'
+else
+  BUILD_PLUGIN_PYTHON_TRUE='#'
+  BUILD_PLUGIN_PYTHON_FALSE=
+fi
+
+    enable_python="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-redis was given.
+if test "${enable_redis+set}" = set; then :
+  enableval=$enable_redis;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libhiredis" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libhiredis" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_REDIS 1" >>confdefs.h
+
+                   if test "x$with_libhiredis" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_REDIS_TRUE=
+  BUILD_PLUGIN_REDIS_FALSE='#'
+else
+  BUILD_PLUGIN_REDIS_TRUE='#'
+  BUILD_PLUGIN_REDIS_FALSE=
+fi
+
+    enable_redis="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-routeros was given.
+if test "${enable_routeros+set}" = set; then :
+  enableval=$enable_routeros;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_librouteros" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_librouteros" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ROUTEROS 1" >>confdefs.h
+
+                   if test "x$with_librouteros" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ROUTEROS_TRUE=
+  BUILD_PLUGIN_ROUTEROS_FALSE='#'
+else
+  BUILD_PLUGIN_ROUTEROS_TRUE='#'
+  BUILD_PLUGIN_ROUTEROS_FALSE=
+fi
+
+    enable_routeros="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-rrdcached was given.
+if test "${enable_rrdcached+set}" = set; then :
+  enableval=$enable_rrdcached;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$librrd_rrdc_update" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$librrd_rrdc_update" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_RRDCACHED 1" >>confdefs.h
+
+                   if test "x$librrd_rrdc_update" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_RRDCACHED_TRUE=
+  BUILD_PLUGIN_RRDCACHED_FALSE='#'
+else
+  BUILD_PLUGIN_RRDCACHED_TRUE='#'
+  BUILD_PLUGIN_RRDCACHED_FALSE=
+fi
+
+    enable_rrdcached="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-rrdtool was given.
+if test "${enable_rrdtool+set}" = set; then :
+  enableval=$enable_rrdtool;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_librrd" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_librrd" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_RRDTOOL 1" >>confdefs.h
+
+                   if test "x$with_librrd" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_RRDTOOL_TRUE=
+  BUILD_PLUGIN_RRDTOOL_FALSE='#'
+else
+  BUILD_PLUGIN_RRDTOOL_TRUE='#'
+  BUILD_PLUGIN_RRDTOOL_FALSE=
+fi
+
+    enable_rrdtool="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-sensors was given.
+if test "${enable_sensors+set}" = set; then :
+  enableval=$enable_sensors;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libsensors" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libsensors" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_SENSORS 1" >>confdefs.h
+
+                   if test "x$with_libsensors" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_SENSORS_TRUE=
+  BUILD_PLUGIN_SENSORS_FALSE='#'
+else
+  BUILD_PLUGIN_SENSORS_TRUE='#'
+  BUILD_PLUGIN_SENSORS_FALSE=
+fi
+
+    enable_sensors="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-serial was given.
+if test "${enable_serial+set}" = set; then :
+  enableval=$enable_serial;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_serial" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_serial" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_SERIAL 1" >>confdefs.h
+
+                   if test "x$plugin_serial" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_SERIAL_TRUE=
+  BUILD_PLUGIN_SERIAL_FALSE='#'
+else
+  BUILD_PLUGIN_SERIAL_TRUE='#'
+  BUILD_PLUGIN_SERIAL_FALSE=
+fi
+
+    enable_serial="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-sigrok was given.
+if test "${enable_sigrok+set}" = set; then :
+  enableval=$enable_sigrok;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libsigrok" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libsigrok" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_SIGROK 1" >>confdefs.h
+
+                   if test "x$with_libsigrok" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_SIGROK_TRUE=
+  BUILD_PLUGIN_SIGROK_FALSE='#'
+else
+  BUILD_PLUGIN_SIGROK_TRUE='#'
+  BUILD_PLUGIN_SIGROK_FALSE=
+fi
+
+    enable_sigrok="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-smart was given.
+if test "${enable_smart+set}" = set; then :
+  enableval=$enable_smart;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libatasmart" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libatasmart" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_SMART 1" >>confdefs.h
+
+                   if test "x$with_libatasmart" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_SMART_TRUE=
+  BUILD_PLUGIN_SMART_FALSE='#'
+else
+  BUILD_PLUGIN_SMART_TRUE='#'
+  BUILD_PLUGIN_SMART_FALSE=
+fi
+
+    enable_smart="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-snmp was given.
+if test "${enable_snmp+set}" = set; then :
+  enableval=$enable_snmp;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libnetsnmp" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libnetsnmp" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_SNMP 1" >>confdefs.h
+
+                   if test "x$with_libnetsnmp" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_SNMP_TRUE=
+  BUILD_PLUGIN_SNMP_FALSE='#'
+else
+  BUILD_PLUGIN_SNMP_TRUE='#'
+  BUILD_PLUGIN_SNMP_FALSE=
+fi
+
+    enable_snmp="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-statsd was given.
+if test "${enable_statsd+set}" = set; then :
+  enableval=$enable_statsd;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_STATSD 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_STATSD_TRUE=
+  BUILD_PLUGIN_STATSD_FALSE='#'
+else
+  BUILD_PLUGIN_STATSD_TRUE='#'
+  BUILD_PLUGIN_STATSD_FALSE=
+fi
+
+    enable_statsd="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-swap was given.
+if test "${enable_swap+set}" = set; then :
+  enableval=$enable_swap;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_swap" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_swap" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_SWAP 1" >>confdefs.h
+
+                   if test "x$plugin_swap" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_SWAP_TRUE=
+  BUILD_PLUGIN_SWAP_FALSE='#'
+else
+  BUILD_PLUGIN_SWAP_TRUE='#'
+  BUILD_PLUGIN_SWAP_FALSE=
+fi
+
+    enable_swap="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-syslog was given.
+if test "${enable_syslog+set}" = set; then :
+  enableval=$enable_syslog;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$have_syslog" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$have_syslog" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_SYSLOG 1" >>confdefs.h
+
+                   if test "x$have_syslog" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_SYSLOG_TRUE=
+  BUILD_PLUGIN_SYSLOG_FALSE='#'
+else
+  BUILD_PLUGIN_SYSLOG_TRUE='#'
+  BUILD_PLUGIN_SYSLOG_FALSE=
+fi
+
+    enable_syslog="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-table was given.
+if test "${enable_table+set}" = set; then :
+  enableval=$enable_table;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TABLE 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TABLE_TRUE=
+  BUILD_PLUGIN_TABLE_FALSE='#'
+else
+  BUILD_PLUGIN_TABLE_TRUE='#'
+  BUILD_PLUGIN_TABLE_FALSE=
+fi
+
+    enable_table="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-tail was given.
+if test "${enable_tail+set}" = set; then :
+  enableval=$enable_tail;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TAIL 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TAIL_TRUE=
+  BUILD_PLUGIN_TAIL_FALSE='#'
+else
+  BUILD_PLUGIN_TAIL_TRUE='#'
+  BUILD_PLUGIN_TAIL_FALSE=
+fi
+
+    enable_tail="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-tail_csv was given.
+if test "${enable_tail_csv+set}" = set; then :
+  enableval=$enable_tail_csv;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TAIL_CSV 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TAIL_CSV_TRUE=
+  BUILD_PLUGIN_TAIL_CSV_FALSE='#'
+else
+  BUILD_PLUGIN_TAIL_CSV_TRUE='#'
+  BUILD_PLUGIN_TAIL_CSV_FALSE=
+fi
+
+    enable_tail_csv="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-tape was given.
+if test "${enable_tape+set}" = set; then :
+  enableval=$enable_tape;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_tape" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_tape" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TAPE 1" >>confdefs.h
+
+                   if test "x$plugin_tape" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TAPE_TRUE=
+  BUILD_PLUGIN_TAPE_FALSE='#'
+else
+  BUILD_PLUGIN_TAPE_TRUE='#'
+  BUILD_PLUGIN_TAPE_FALSE=
+fi
+
+    enable_tape="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-target_notification was given.
+if test "${enable_target_notification+set}" = set; then :
+  enableval=$enable_target_notification;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TARGET_NOTIFICATION 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE=
+  BUILD_PLUGIN_TARGET_NOTIFICATION_FALSE='#'
+else
+  BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE='#'
+  BUILD_PLUGIN_TARGET_NOTIFICATION_FALSE=
+fi
+
+    enable_target_notification="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-target_replace was given.
+if test "${enable_target_replace+set}" = set; then :
+  enableval=$enable_target_replace;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TARGET_REPLACE 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TARGET_REPLACE_TRUE=
+  BUILD_PLUGIN_TARGET_REPLACE_FALSE='#'
+else
+  BUILD_PLUGIN_TARGET_REPLACE_TRUE='#'
+  BUILD_PLUGIN_TARGET_REPLACE_FALSE=
+fi
+
+    enable_target_replace="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-target_scale was given.
+if test "${enable_target_scale+set}" = set; then :
+  enableval=$enable_target_scale;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TARGET_SCALE 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TARGET_SCALE_TRUE=
+  BUILD_PLUGIN_TARGET_SCALE_FALSE='#'
+else
+  BUILD_PLUGIN_TARGET_SCALE_TRUE='#'
+  BUILD_PLUGIN_TARGET_SCALE_FALSE=
+fi
+
+    enable_target_scale="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-target_set was given.
+if test "${enable_target_set+set}" = set; then :
+  enableval=$enable_target_set;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TARGET_SET 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TARGET_SET_TRUE=
+  BUILD_PLUGIN_TARGET_SET_FALSE='#'
+else
+  BUILD_PLUGIN_TARGET_SET_TRUE='#'
+  BUILD_PLUGIN_TARGET_SET_FALSE=
+fi
+
+    enable_target_set="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-target_v5upgrade was given.
+if test "${enable_target_v5upgrade+set}" = set; then :
+  enableval=$enable_target_v5upgrade;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TARGET_V5UPGRADE 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE=
+  BUILD_PLUGIN_TARGET_V5UPGRADE_FALSE='#'
+else
+  BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE='#'
+  BUILD_PLUGIN_TARGET_V5UPGRADE_FALSE=
+fi
+
+    enable_target_v5upgrade="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-tcpconns was given.
+if test "${enable_tcpconns+set}" = set; then :
+  enableval=$enable_tcpconns;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_tcpconns" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_tcpconns" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TCPCONNS 1" >>confdefs.h
+
+                   if test "x$plugin_tcpconns" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TCPCONNS_TRUE=
+  BUILD_PLUGIN_TCPCONNS_FALSE='#'
+else
+  BUILD_PLUGIN_TCPCONNS_TRUE='#'
+  BUILD_PLUGIN_TCPCONNS_FALSE=
+fi
+
+    enable_tcpconns="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-teamspeak2 was given.
+if test "${enable_teamspeak2+set}" = set; then :
+  enableval=$enable_teamspeak2;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TEAMSPEAK2 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TEAMSPEAK2_TRUE=
+  BUILD_PLUGIN_TEAMSPEAK2_FALSE='#'
+else
+  BUILD_PLUGIN_TEAMSPEAK2_TRUE='#'
+  BUILD_PLUGIN_TEAMSPEAK2_FALSE=
+fi
+
+    enable_teamspeak2="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-ted was given.
+if test "${enable_ted+set}" = set; then :
+  enableval=$enable_ted;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_ted" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_ted" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TED 1" >>confdefs.h
+
+                   if test "x$plugin_ted" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TED_TRUE=
+  BUILD_PLUGIN_TED_FALSE='#'
+else
+  BUILD_PLUGIN_TED_TRUE='#'
+  BUILD_PLUGIN_TED_FALSE=
+fi
+
+    enable_ted="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-thermal was given.
+if test "${enable_thermal+set}" = set; then :
+  enableval=$enable_thermal;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_thermal" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_thermal" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_THERMAL 1" >>confdefs.h
+
+                   if test "x$plugin_thermal" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_THERMAL_TRUE=
+  BUILD_PLUGIN_THERMAL_FALSE='#'
+else
+  BUILD_PLUGIN_THERMAL_TRUE='#'
+  BUILD_PLUGIN_THERMAL_FALSE=
+fi
+
+    enable_thermal="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-threshold was given.
+if test "${enable_threshold+set}" = set; then :
+  enableval=$enable_threshold;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_THRESHOLD 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_THRESHOLD_TRUE=
+  BUILD_PLUGIN_THRESHOLD_FALSE='#'
+else
+  BUILD_PLUGIN_THRESHOLD_TRUE='#'
+  BUILD_PLUGIN_THRESHOLD_FALSE=
+fi
+
+    enable_threshold="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-tokyotyrant was given.
+if test "${enable_tokyotyrant+set}" = set; then :
+  enableval=$enable_tokyotyrant;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libtokyotyrant" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libtokyotyrant" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TOKYOTYRANT 1" >>confdefs.h
+
+                   if test "x$with_libtokyotyrant" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TOKYOTYRANT_TRUE=
+  BUILD_PLUGIN_TOKYOTYRANT_FALSE='#'
+else
+  BUILD_PLUGIN_TOKYOTYRANT_TRUE='#'
+  BUILD_PLUGIN_TOKYOTYRANT_FALSE=
+fi
+
+    enable_tokyotyrant="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-turbostat was given.
+if test "${enable_turbostat+set}" = set; then :
+  enableval=$enable_turbostat;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_turbostat" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_turbostat" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_TURBOSTAT 1" >>confdefs.h
+
+                   if test "x$plugin_turbostat" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_TURBOSTAT_TRUE=
+  BUILD_PLUGIN_TURBOSTAT_FALSE='#'
+else
+  BUILD_PLUGIN_TURBOSTAT_TRUE='#'
+  BUILD_PLUGIN_TURBOSTAT_FALSE=
+fi
+
+    enable_turbostat="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-unixsock was given.
+if test "${enable_unixsock+set}" = set; then :
+  enableval=$enable_unixsock;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_UNIXSOCK 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_UNIXSOCK_TRUE=
+  BUILD_PLUGIN_UNIXSOCK_FALSE='#'
+else
+  BUILD_PLUGIN_UNIXSOCK_TRUE='#'
+  BUILD_PLUGIN_UNIXSOCK_FALSE=
+fi
+
+    enable_unixsock="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-uptime was given.
+if test "${enable_uptime+set}" = set; then :
+  enableval=$enable_uptime;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_uptime" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_uptime" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_UPTIME 1" >>confdefs.h
+
+                   if test "x$plugin_uptime" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_UPTIME_TRUE=
+  BUILD_PLUGIN_UPTIME_FALSE='#'
+else
+  BUILD_PLUGIN_UPTIME_TRUE='#'
+  BUILD_PLUGIN_UPTIME_FALSE=
+fi
+
+    enable_uptime="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-users was given.
+if test "${enable_users+set}" = set; then :
+  enableval=$enable_users;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_users" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_users" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_USERS 1" >>confdefs.h
+
+                   if test "x$plugin_users" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_USERS_TRUE=
+  BUILD_PLUGIN_USERS_FALSE='#'
+else
+  BUILD_PLUGIN_USERS_TRUE='#'
+  BUILD_PLUGIN_USERS_FALSE=
+fi
+
+    enable_users="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-uuid was given.
+if test "${enable_uuid+set}" = set; then :
+  enableval=$enable_uuid;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_UUID 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_UUID_TRUE=
+  BUILD_PLUGIN_UUID_FALSE='#'
+else
+  BUILD_PLUGIN_UUID_TRUE='#'
+  BUILD_PLUGIN_UUID_FALSE=
+fi
+
+    enable_uuid="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-varnish was given.
+if test "${enable_varnish+set}" = set; then :
+  enableval=$enable_varnish;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libvarnish" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libvarnish" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_VARNISH 1" >>confdefs.h
+
+                   if test "x$with_libvarnish" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_VARNISH_TRUE=
+  BUILD_PLUGIN_VARNISH_FALSE='#'
+else
+  BUILD_PLUGIN_VARNISH_TRUE='#'
+  BUILD_PLUGIN_VARNISH_FALSE=
+fi
+
+    enable_varnish="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-virt was given.
+if test "${enable_virt+set}" = set; then :
+  enableval=$enable_virt;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_virt" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_virt" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_VIRT 1" >>confdefs.h
+
+                   if test "x$plugin_virt" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_VIRT_TRUE=
+  BUILD_PLUGIN_VIRT_FALSE='#'
+else
+  BUILD_PLUGIN_VIRT_TRUE='#'
+  BUILD_PLUGIN_VIRT_FALSE=
+fi
+
+    enable_virt="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-vmem was given.
+if test "${enable_vmem+set}" = set; then :
+  enableval=$enable_vmem;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_vmem" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_vmem" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_VMEM 1" >>confdefs.h
+
+                   if test "x$plugin_vmem" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_VMEM_TRUE=
+  BUILD_PLUGIN_VMEM_FALSE='#'
+else
+  BUILD_PLUGIN_VMEM_TRUE='#'
+  BUILD_PLUGIN_VMEM_FALSE=
+fi
+
+    enable_vmem="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-vserver was given.
+if test "${enable_vserver+set}" = set; then :
+  enableval=$enable_vserver;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_vserver" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_vserver" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_VSERVER 1" >>confdefs.h
+
+                   if test "x$plugin_vserver" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_VSERVER_TRUE=
+  BUILD_PLUGIN_VSERVER_FALSE='#'
+else
+  BUILD_PLUGIN_VSERVER_TRUE='#'
+  BUILD_PLUGIN_VSERVER_FALSE=
+fi
+
+    enable_vserver="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-wireless was given.
+if test "${enable_wireless+set}" = set; then :
+  enableval=$enable_wireless;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_wireless" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_wireless" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WIRELESS 1" >>confdefs.h
+
+                   if test "x$plugin_wireless" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WIRELESS_TRUE=
+  BUILD_PLUGIN_WIRELESS_FALSE='#'
+else
+  BUILD_PLUGIN_WIRELESS_TRUE='#'
+  BUILD_PLUGIN_WIRELESS_FALSE=
+fi
+
+    enable_wireless="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_graphite was given.
+if test "${enable_write_graphite+set}" = set; then :
+  enableval=$enable_write_graphite;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_GRAPHITE 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_GRAPHITE_TRUE=
+  BUILD_PLUGIN_WRITE_GRAPHITE_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_GRAPHITE_TRUE='#'
+  BUILD_PLUGIN_WRITE_GRAPHITE_FALSE=
+fi
+
+    enable_write_graphite="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_http was given.
+if test "${enable_write_http+set}" = set; then :
+  enableval=$enable_write_http;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libcurl" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libcurl" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_HTTP 1" >>confdefs.h
+
+                   if test "x$with_libcurl" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_HTTP_TRUE=
+  BUILD_PLUGIN_WRITE_HTTP_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_HTTP_TRUE='#'
+  BUILD_PLUGIN_WRITE_HTTP_FALSE=
+fi
+
+    enable_write_http="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_kafka was given.
+if test "${enable_write_kafka+set}" = set; then :
+  enableval=$enable_write_kafka;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_librdkafka" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_librdkafka" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_KAFKA 1" >>confdefs.h
+
+                   if test "x$with_librdkafka" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_KAFKA_TRUE=
+  BUILD_PLUGIN_WRITE_KAFKA_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_KAFKA_TRUE='#'
+  BUILD_PLUGIN_WRITE_KAFKA_FALSE=
+fi
+
+    enable_write_kafka="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_log was given.
+if test "${enable_write_log+set}" = set; then :
+  enableval=$enable_write_log;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_LOG 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_LOG_TRUE=
+  BUILD_PLUGIN_WRITE_LOG_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_LOG_TRUE='#'
+  BUILD_PLUGIN_WRITE_LOG_FALSE=
+fi
+
+    enable_write_log="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_mongodb was given.
+if test "${enable_write_mongodb+set}" = set; then :
+  enableval=$enable_write_mongodb;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libmongoc" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libmongoc" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_MONGODB 1" >>confdefs.h
+
+                   if test "x$with_libmongoc" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_MONGODB_TRUE=
+  BUILD_PLUGIN_WRITE_MONGODB_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_MONGODB_TRUE='#'
+  BUILD_PLUGIN_WRITE_MONGODB_FALSE=
+fi
+
+    enable_write_mongodb="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_redis was given.
+if test "${enable_write_redis+set}" = set; then :
+  enableval=$enable_write_redis;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libhiredis" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libhiredis" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_REDIS 1" >>confdefs.h
+
+                   if test "x$with_libhiredis" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_REDIS_TRUE=
+  BUILD_PLUGIN_WRITE_REDIS_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_REDIS_TRUE='#'
+  BUILD_PLUGIN_WRITE_REDIS_FALSE=
+fi
+
+    enable_write_redis="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_riemann was given.
+if test "${enable_write_riemann+set}" = set; then :
+  enableval=$enable_write_riemann;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$have_protoc_c" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$have_protoc_c" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_RIEMANN 1" >>confdefs.h
+
+                   if test "x$have_protoc_c" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_RIEMANN_TRUE=
+  BUILD_PLUGIN_WRITE_RIEMANN_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_RIEMANN_TRUE='#'
+  BUILD_PLUGIN_WRITE_RIEMANN_FALSE=
+fi
+
+    enable_write_riemann="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_sensu was given.
+if test "${enable_write_sensu+set}" = set; then :
+  enableval=$enable_write_sensu;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_SENSU 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_SENSU_TRUE=
+  BUILD_PLUGIN_WRITE_SENSU_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_SENSU_TRUE='#'
+  BUILD_PLUGIN_WRITE_SENSU_FALSE=
+fi
+
+    enable_write_sensu="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-write_tsdb was given.
+if test "${enable_write_tsdb+set}" = set; then :
+  enableval=$enable_write_tsdb;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_WRITE_TSDB 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_WRITE_TSDB_TRUE=
+  BUILD_PLUGIN_WRITE_TSDB_FALSE='#'
+else
+  BUILD_PLUGIN_WRITE_TSDB_TRUE='#'
+  BUILD_PLUGIN_WRITE_TSDB_FALSE=
+fi
+
+    enable_write_tsdb="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-xmms was given.
+if test "${enable_xmms+set}" = set; then :
+  enableval=$enable_xmms;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$with_libxmms" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$with_libxmms" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_XMMS 1" >>confdefs.h
+
+                   if test "x$with_libxmms" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_XMMS_TRUE=
+  BUILD_PLUGIN_XMMS_FALSE='#'
+else
+  BUILD_PLUGIN_XMMS_TRUE='#'
+  BUILD_PLUGIN_XMMS_FALSE=
+fi
+
+    enable_xmms="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-zfs_arc was given.
+if test "${enable_zfs_arc+set}" = set; then :
+  enableval=$enable_zfs_arc;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$plugin_zfs_arc" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$plugin_zfs_arc" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ZFS_ARC 1" >>confdefs.h
+
+                   if test "x$plugin_zfs_arc" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ZFS_ARC_TRUE=
+  BUILD_PLUGIN_ZFS_ARC_FALSE='#'
+else
+  BUILD_PLUGIN_ZFS_ARC_TRUE='#'
+  BUILD_PLUGIN_ZFS_ARC_FALSE=
+fi
+
+    enable_zfs_arc="$enable_plugin"
+
+
+
+    enable_plugin="no"
+    force="no"
+    # Check whether --enable-zookeeper was given.
+if test "${enable_zookeeper+set}" = set; then :
+  enableval=$enable_zookeeper;
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+
+else
+
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "xyes" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+
+fi
+
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "xyes" = "xyes" || test "x$force" = "xyes"
+           then
+
+$as_echo "#define HAVE_PLUGIN_ZOOKEEPER 1" >>confdefs.h
+
+                   if test "xyes" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+     if test "x$enable_plugin" = "xyes"; then
+  BUILD_PLUGIN_ZOOKEEPER_TRUE=
+  BUILD_PLUGIN_ZOOKEEPER_FALSE='#'
+else
+  BUILD_PLUGIN_ZOOKEEPER_TRUE='#'
+  BUILD_PLUGIN_ZOOKEEPER_FALSE=
+fi
+
+    enable_zookeeper="$enable_plugin"
+
+
+
+# Load either syslog or logfile
+LOAD_PLUGIN_SYSLOG=""
+LOAD_PLUGIN_LOGFILE=""
+LOAD_PLUGIN_LOG_LOGSTASH=""
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which default log plugin to load" >&5
+$as_echo_n "checking which default log plugin to load... " >&6; }
+default_log_plugin="none"
+if test "x$enable_syslog" = "xyes"
+then
+       default_log_plugin="syslog"
+else
+       LOAD_PLUGIN_SYSLOG="##"
+fi
+
+if test "x$enable_logfile" = "xyes"
+then
+       if test "x$default_log_plugin" = "xnone"
+       then
+               default_log_plugin="logfile"
+       else
+               LOAD_PLUGIN_LOGFILE="#"
+       fi
+else
+       LOAD_PLUGIN_LOGFILE="##"
+fi
+
+if test "x$enable_log_logstash" = "xyes"
+then
+  LOAD_PLUGIN_LOG_LOGSTASH="#"
+else
+  LOAD_PLUGIN_LOG_LOGSTASH="##"
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $default_log_plugin" >&5
+$as_echo "$default_log_plugin" >&6; }
+
+
+
+
+
+DEFAULT_LOG_LEVEL="info"
+if test "x$enable_debug" = "xyes"
+then
+       DEFAULT_LOG_LEVEL="debug"
+fi
+
+
+# Load only one of rrdtool, network, csv in the default config.
+LOAD_PLUGIN_RRDTOOL=""
+LOAD_PLUGIN_NETWORK=""
+LOAD_PLUGIN_CSV=""
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which default write plugin to load" >&5
+$as_echo_n "checking which default write plugin to load... " >&6; }
+default_write_plugin="none"
+if test "x$enable_rrdtool" = "xyes"
+then
+       default_write_plugin="rrdtool"
+else
+       LOAD_PLUGIN_RRDTOOL="##"
+fi
+
+if test "x$enable_network" = "xyes"
+then
+       if test "x$default_write_plugin" = "xnone"
+       then
+               default_write_plugin="network"
+       else
+               LOAD_PLUGIN_NETWORK="#"
+       fi
+else
+       LOAD_PLUGIN_NETWORK="##"
+fi
+
+if test "x$enable_csv" = "xyes"
+then
+       if test "x$default_write_plugin" = "xnone"
+       then
+               default_write_plugin="csv"
+       else
+               LOAD_PLUGIN_CSV="#"
+       fi
+else
+       LOAD_PLUGIN_CSV="##"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $default_write_plugin" >&5
+$as_echo "$default_write_plugin" >&6; }
+
+
+
+
+
+if test "x$ac_system" = "xLinux" \
+       && test "x$have_linux_ip_vs_h$have_net_ip_vs_h$have_ip_vs_h" = "xnonono"
+then
+       enable_ipvs="$enable_ipvs (ip_vs.h not found)"
+fi
+
+if test "x$ip_vs_h_needs_kernel_cflags" = "xyes"
+then
+       enable_ipvs="$enable_ipvs (needs $KERNEL_CFLAGS)"
+fi
+
+PERL_BINDINGS_OPTIONS="PREFIX=${prefix}"
+
+# Check whether --with-perl-bindings was given.
+if test "${with_perl_bindings+set}" = set; then :
+  withval=$with_perl_bindings;
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               PERL_BINDINGS_OPTIONS="$withval"
+               with_perl_bindings="yes"
+       else
+               with_perl_bindings="$withval"
+       fi
+
+else
+
+       if test -n "$perl_interpreter"
+       then
+               with_perl_bindings="yes"
+       else
+               with_perl_bindings="no (no perl interpreter found)"
+       fi
+
+fi
+
+if test "x$with_perl_bindings" = "xyes"
+then
+       PERL_BINDINGS="perl"
+else
+       PERL_BINDINGS=""
+fi
+
+
+
+LCC_VERSION_MAJOR=`echo $PACKAGE_VERSION | cut -d'.' -f1`
+LCC_VERSION_MINOR=`echo $PACKAGE_VERSION | cut -d'.' -f2`
+LCC_VERSION_PATCH=`echo $PACKAGE_VERSION | cut -d'.' -f3`
+
+LCC_VERSION_EXTRA=`echo $PACKAGE_VERSION | cut -d'.' -f4-`
+
+LCC_VERSION_STRING="$LCC_VERSION_MAJOR.$LCC_VERSION_MINOR.$LCC_VERSION_PATCH"
+
+
+
+
+
+
+
+ac_config_files="$ac_config_files src/libcollectdclient/collectd/lcc_features.h"
+
+
+ac_config_files="$ac_config_files Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+       cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+         mv -f confcache "$cache_file"$$ &&
+         mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+         mv -f confcache "$cache_file" ;;
+       esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then
+  as_fn_error $? "conditional \"INSTALL_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then
+  as_fn_error $? "conditional \"CONVENIENCE_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+LT_CONFIG_H=src/config.h
+
+    _ltdl_libobjs=
+    _ltdl_ltlibobjs=
+    if test -n "$_LT_LIBOBJS"; then
+      # Remove the extension.
+      _lt_sed_drop_objext='s/\.o$//;s/\.obj$//'
+      for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | sed "$_lt_sed_drop_objext" | sort -u`; do
+        _ltdl_libobjs="$_ltdl_libobjs $lt_libobj_prefix$i.$ac_objext"
+        _ltdl_ltlibobjs="$_ltdl_ltlibobjs $lt_libobj_prefix$i.lo"
+      done
+    fi
+    ltdl_LIBOBJS=$_ltdl_libobjs
+
+    ltdl_LTLIBOBJS=$_ltdl_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${COMPILER_IS_GCC_TRUE}" && test -z "${COMPILER_IS_GCC_FALSE}"; then
+  as_fn_error $? "conditional \"COMPILER_IS_GCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_PROTOC_C_TRUE}" && test -z "${HAVE_PROTOC_C_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_PROTOC_C\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_LINUX_TRUE}" && test -z "${BUILD_LINUX_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_LINUX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_SOLARIS_TRUE}" && test -z "${BUILD_SOLARIS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_SOLARIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_DARWIN_TRUE}" && test -z "${BUILD_DARWIN_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_DARWIN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_OPENBSD_TRUE}" && test -z "${BUILD_OPENBSD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_OPENBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_AIX_TRUE}" && test -z "${BUILD_AIX_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_AIX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_FREEBSD_TRUE}" && test -z "${BUILD_FREEBSD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_FREEBSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_FEATURE_STANDARDS_TRUE}" && test -z "${BUILD_FEATURE_STANDARDS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_FEATURE_STANDARDS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${IP_VS_H_NEEDS_KERNEL_CFLAGS_TRUE}" && test -z "${IP_VS_H_NEEDS_KERNEL_CFLAGS_FALSE}"; then
+  as_fn_error $? "conditional \"IP_VS_H_NEEDS_KERNEL_CFLAGS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBSOCKET_TRUE}" && test -z "${BUILD_WITH_LIBSOCKET_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBSOCKET\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBRT_TRUE}" && test -z "${BUILD_WITH_LIBRT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBRT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBPOSIX4_TRUE}" && test -z "${BUILD_WITH_LIBPOSIX4_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBPOSIX4\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBRESOLV_TRUE}" && test -z "${BUILD_WITH_LIBRESOLV_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBRESOLV\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_PERFSTAT_TRUE}" && test -z "${BUILD_WITH_PERFSTAT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_PERFSTAT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBKSTAT_TRUE}" && test -z "${BUILD_WITH_LIBKSTAT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBKSTAT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBDEVINFO_TRUE}" && test -z "${BUILD_WITH_LIBDEVINFO_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBDEVINFO\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBIOKIT_TRUE}" && test -z "${BUILD_WITH_LIBIOKIT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBIOKIT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBKVM_GETPROCS_TRUE}" && test -z "${BUILD_WITH_LIBKVM_GETPROCS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBKVM_GETPROCS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBKVM_GETSWAPINFO_TRUE}" && test -z "${BUILD_WITH_LIBKVM_GETSWAPINFO_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBKVM_GETSWAPINFO\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBKVM_NLIST_TRUE}" && test -z "${BUILD_WITH_LIBKVM_NLIST_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBKVM_NLIST\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBKVM_OPENFILES_TRUE}" && test -z "${BUILD_WITH_LIBKVM_OPENFILES_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBKVM_OPENFILES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBAQUAERO5_TRUE}" && test -z "${BUILD_WITH_LIBAQUAERO5_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBAQUAERO5\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBHIREDIS_TRUE}" && test -z "${BUILD_WITH_LIBHIREDIS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBHIREDIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBCURL_TRUE}" && test -z "${BUILD_WITH_LIBCURL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBCURL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBDBI_TRUE}" && test -z "${BUILD_WITH_LIBDBI_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBDBI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBESMTP_TRUE}" && test -z "${BUILD_WITH_LIBESMTP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBESMTP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBGANGLIA_TRUE}" && test -z "${BUILD_WITH_LIBGANGLIA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBGANGLIA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBGCRYPT_TRUE}" && test -z "${BUILD_WITH_LIBGCRYPT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBGCRYPT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBIPTC_TRUE}" && test -z "${BUILD_WITH_LIBIPTC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBIPTC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_JAVA_TRUE}" && test -z "${BUILD_WITH_JAVA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_JAVA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBLDAP_TRUE}" && test -z "${BUILD_WITH_LIBLDAP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBLDAP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBLVM2APP_TRUE}" && test -z "${BUILD_WITH_LIBLVM2APP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBLVM2APP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBMEMCACHED_TRUE}" && test -z "${BUILD_WITH_LIBMEMCACHED_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBMEMCACHED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBMONGOC_TRUE}" && test -z "${BUILD_WITH_LIBMONGOC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBMONGOC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBMYSQL_TRUE}" && test -z "${BUILD_WITH_LIBMYSQL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBMYSQL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBMNL_TRUE}" && test -z "${BUILD_WITH_LIBMNL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBMNL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBNETAPP_TRUE}" && test -z "${BUILD_WITH_LIBNETAPP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBNETAPP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBNETSNMP_TRUE}" && test -z "${BUILD_WITH_LIBNETSNMP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBNETSNMP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_OWN_LIBOCONFIG_TRUE}" && test -z "${BUILD_WITH_OWN_LIBOCONFIG_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_OWN_LIBOCONFIG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBOPING_TRUE}" && test -z "${BUILD_WITH_LIBOPING_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBOPING\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBPCAP_TRUE}" && test -z "${BUILD_WITH_LIBPCAP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBPCAP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBPERL_TRUE}" && test -z "${BUILD_WITH_LIBPERL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBPERL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_BROKEN_PERL_LOAD_MODULE_TRUE}" && test -z "${HAVE_BROKEN_PERL_LOAD_MODULE_FALSE}"; then
+  as_fn_error $? "conditional \"HAVE_BROKEN_PERL_LOAD_MODULE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBPQ_TRUE}" && test -z "${BUILD_WITH_LIBPQ_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBPQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBPTHREAD_TRUE}" && test -z "${BUILD_WITH_LIBPTHREAD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBPTHREAD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBRABBITMQ_TRUE}" && test -z "${BUILD_WITH_LIBRABBITMQ_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBRABBITMQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBRDKAFKA_TRUE}" && test -z "${BUILD_WITH_LIBRDKAFKA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBRDKAFKA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBROUTEROS_TRUE}" && test -z "${BUILD_WITH_LIBROUTEROS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBROUTEROS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LM_SENSORS_TRUE}" && test -z "${BUILD_WITH_LM_SENSORS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LM_SENSORS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBSIGROK_TRUE}" && test -z "${BUILD_WITH_LIBSIGROK_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBSIGROK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBSTATGRAB_TRUE}" && test -z "${BUILD_WITH_LIBSTATGRAB_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBSTATGRAB\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBTOKYOTYRANT_TRUE}" && test -z "${BUILD_WITH_LIBTOKYOTYRANT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBTOKYOTYRANT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBUDEV_TRUE}" && test -z "${BUILD_WITH_LIBUDEV_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBUDEV\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBXMMS_TRUE}" && test -z "${BUILD_WITH_LIBXMMS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBXMMS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBYAJL_TRUE}" && test -z "${BUILD_WITH_LIBYAJL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBYAJL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_WITH_LIBATASMART_TRUE}" && test -z "${BUILD_WITH_LIBATASMART_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_WITH_LIBATASMART\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_FEATURE_DEBUG_TRUE}" && test -z "${BUILD_FEATURE_DEBUG_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_FEATURE_DEBUG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_FEATURE_DAEMON_TRUE}" && test -z "${BUILD_FEATURE_DAEMON_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_FEATURE_DAEMON\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_FEATURE_GETIFADDRS_TRUE}" && test -z "${BUILD_FEATURE_GETIFADDRS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_FEATURE_GETIFADDRS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_AGGREGATION_TRUE}" && test -z "${BUILD_PLUGIN_AGGREGATION_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_AGGREGATION\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_AMQP_TRUE}" && test -z "${BUILD_PLUGIN_AMQP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_AMQP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_APACHE_TRUE}" && test -z "${BUILD_PLUGIN_APACHE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_APACHE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_APCUPS_TRUE}" && test -z "${BUILD_PLUGIN_APCUPS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_APCUPS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_APPLE_SENSORS_TRUE}" && test -z "${BUILD_PLUGIN_APPLE_SENSORS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_APPLE_SENSORS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_AQUAERO_TRUE}" && test -z "${BUILD_PLUGIN_AQUAERO_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_AQUAERO\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ASCENT_TRUE}" && test -z "${BUILD_PLUGIN_ASCENT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ASCENT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_BAROMETER_TRUE}" && test -z "${BUILD_PLUGIN_BAROMETER_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_BAROMETER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_BATTERY_TRUE}" && test -z "${BUILD_PLUGIN_BATTERY_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_BATTERY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_BIND_TRUE}" && test -z "${BUILD_PLUGIN_BIND_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_BIND\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CEPH_TRUE}" && test -z "${BUILD_PLUGIN_CEPH_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CEPH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CONNTRACK_TRUE}" && test -z "${BUILD_PLUGIN_CONNTRACK_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CONNTRACK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CONTEXTSWITCH_TRUE}" && test -z "${BUILD_PLUGIN_CONTEXTSWITCH_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CONTEXTSWITCH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CPUFREQ_TRUE}" && test -z "${BUILD_PLUGIN_CPUFREQ_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CPUFREQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CPU_TRUE}" && test -z "${BUILD_PLUGIN_CPU_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CPU\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CSV_TRUE}" && test -z "${BUILD_PLUGIN_CSV_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CSV\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CURL_TRUE}" && test -z "${BUILD_PLUGIN_CURL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CURL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CURL_JSON_TRUE}" && test -z "${BUILD_PLUGIN_CURL_JSON_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CURL_JSON\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CURL_XML_TRUE}" && test -z "${BUILD_PLUGIN_CURL_XML_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CURL_XML\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_CGROUPS_TRUE}" && test -z "${BUILD_PLUGIN_CGROUPS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_CGROUPS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_DBI_TRUE}" && test -z "${BUILD_PLUGIN_DBI_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_DBI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_DF_TRUE}" && test -z "${BUILD_PLUGIN_DF_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_DF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_DISK_TRUE}" && test -z "${BUILD_PLUGIN_DISK_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_DISK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_DRBD_TRUE}" && test -z "${BUILD_PLUGIN_DRBD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_DRBD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_DNS_TRUE}" && test -z "${BUILD_PLUGIN_DNS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_DNS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_EMAIL_TRUE}" && test -z "${BUILD_PLUGIN_EMAIL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_EMAIL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ENTROPY_TRUE}" && test -z "${BUILD_PLUGIN_ENTROPY_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ENTROPY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ETHSTAT_TRUE}" && test -z "${BUILD_PLUGIN_ETHSTAT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ETHSTAT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_EXEC_TRUE}" && test -z "${BUILD_PLUGIN_EXEC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_EXEC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_FHCOUNT_TRUE}" && test -z "${BUILD_PLUGIN_FHCOUNT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_FHCOUNT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_FILECOUNT_TRUE}" && test -z "${BUILD_PLUGIN_FILECOUNT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_FILECOUNT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_FSCACHE_TRUE}" && test -z "${BUILD_PLUGIN_FSCACHE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_FSCACHE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_GMOND_TRUE}" && test -z "${BUILD_PLUGIN_GMOND_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_GMOND\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_HDDTEMP_TRUE}" && test -z "${BUILD_PLUGIN_HDDTEMP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_HDDTEMP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_INTERFACE_TRUE}" && test -z "${BUILD_PLUGIN_INTERFACE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_INTERFACE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_IPC_TRUE}" && test -z "${BUILD_PLUGIN_IPC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_IPC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_IPMI_TRUE}" && test -z "${BUILD_PLUGIN_IPMI_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_IPMI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_IPTABLES_TRUE}" && test -z "${BUILD_PLUGIN_IPTABLES_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_IPTABLES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_IPVS_TRUE}" && test -z "${BUILD_PLUGIN_IPVS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_IPVS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_IRQ_TRUE}" && test -z "${BUILD_PLUGIN_IRQ_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_IRQ\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_JAVA_TRUE}" && test -z "${BUILD_PLUGIN_JAVA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_JAVA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_LOAD_TRUE}" && test -z "${BUILD_PLUGIN_LOAD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_LOAD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_LOGFILE_TRUE}" && test -z "${BUILD_PLUGIN_LOGFILE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_LOGFILE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_LOG_LOGSTASH_TRUE}" && test -z "${BUILD_PLUGIN_LOG_LOGSTASH_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_LOG_LOGSTASH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_LPAR_TRUE}" && test -z "${BUILD_PLUGIN_LPAR_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_LPAR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_LVM_TRUE}" && test -z "${BUILD_PLUGIN_LVM_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_LVM\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MADWIFI_TRUE}" && test -z "${BUILD_PLUGIN_MADWIFI_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MADWIFI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE}" && test -z "${BUILD_PLUGIN_MATCH_EMPTY_COUNTER_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MATCH_EMPTY_COUNTER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MATCH_HASHED_TRUE}" && test -z "${BUILD_PLUGIN_MATCH_HASHED_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MATCH_HASHED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MATCH_REGEX_TRUE}" && test -z "${BUILD_PLUGIN_MATCH_REGEX_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MATCH_REGEX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE}" && test -z "${BUILD_PLUGIN_MATCH_TIMEDIFF_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MATCH_TIMEDIFF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MATCH_VALUE_TRUE}" && test -z "${BUILD_PLUGIN_MATCH_VALUE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MATCH_VALUE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MBMON_TRUE}" && test -z "${BUILD_PLUGIN_MBMON_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MBMON\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MD_TRUE}" && test -z "${BUILD_PLUGIN_MD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MEMCACHEC_TRUE}" && test -z "${BUILD_PLUGIN_MEMCACHEC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MEMCACHEC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MEMCACHED_TRUE}" && test -z "${BUILD_PLUGIN_MEMCACHED_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MEMCACHED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MEMORY_TRUE}" && test -z "${BUILD_PLUGIN_MEMORY_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MEMORY\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MIC_TRUE}" && test -z "${BUILD_PLUGIN_MIC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MODBUS_TRUE}" && test -z "${BUILD_PLUGIN_MODBUS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MODBUS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MULTIMETER_TRUE}" && test -z "${BUILD_PLUGIN_MULTIMETER_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MULTIMETER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_MYSQL_TRUE}" && test -z "${BUILD_PLUGIN_MYSQL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_MYSQL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NETAPP_TRUE}" && test -z "${BUILD_PLUGIN_NETAPP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NETAPP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NETLINK_TRUE}" && test -z "${BUILD_PLUGIN_NETLINK_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NETLINK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NETWORK_TRUE}" && test -z "${BUILD_PLUGIN_NETWORK_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NETWORK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NFS_TRUE}" && test -z "${BUILD_PLUGIN_NFS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NFS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NGINX_TRUE}" && test -z "${BUILD_PLUGIN_NGINX_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NGINX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE}" && test -z "${BUILD_PLUGIN_NOTIFY_DESKTOP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NOTIFY_DESKTOP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NOTIFY_EMAIL_TRUE}" && test -z "${BUILD_PLUGIN_NOTIFY_EMAIL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NOTIFY_EMAIL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NTPD_TRUE}" && test -z "${BUILD_PLUGIN_NTPD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NTPD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NUMA_TRUE}" && test -z "${BUILD_PLUGIN_NUMA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NUMA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_NUT_TRUE}" && test -z "${BUILD_PLUGIN_NUT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_NUT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_OLSRD_TRUE}" && test -z "${BUILD_PLUGIN_OLSRD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_OLSRD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ONEWIRE_TRUE}" && test -z "${BUILD_PLUGIN_ONEWIRE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ONEWIRE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_OPENLDAP_TRUE}" && test -z "${BUILD_PLUGIN_OPENLDAP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_OPENLDAP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_OPENVPN_TRUE}" && test -z "${BUILD_PLUGIN_OPENVPN_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_OPENVPN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ORACLE_TRUE}" && test -z "${BUILD_PLUGIN_ORACLE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ORACLE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_PERL_TRUE}" && test -z "${BUILD_PLUGIN_PERL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_PERL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_PF_TRUE}" && test -z "${BUILD_PLUGIN_PF_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_PF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_PINBA_TRUE}" && test -z "${BUILD_PLUGIN_PINBA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_PINBA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_PING_TRUE}" && test -z "${BUILD_PLUGIN_PING_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_PING\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_POSTGRESQL_TRUE}" && test -z "${BUILD_PLUGIN_POSTGRESQL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_POSTGRESQL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_POWERDNS_TRUE}" && test -z "${BUILD_PLUGIN_POWERDNS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_POWERDNS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_PROCESSES_TRUE}" && test -z "${BUILD_PLUGIN_PROCESSES_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_PROCESSES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_PROTOCOLS_TRUE}" && test -z "${BUILD_PLUGIN_PROTOCOLS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_PROTOCOLS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_PYTHON_TRUE}" && test -z "${BUILD_PLUGIN_PYTHON_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_PYTHON\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_REDIS_TRUE}" && test -z "${BUILD_PLUGIN_REDIS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_REDIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ROUTEROS_TRUE}" && test -z "${BUILD_PLUGIN_ROUTEROS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ROUTEROS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_RRDCACHED_TRUE}" && test -z "${BUILD_PLUGIN_RRDCACHED_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_RRDCACHED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_RRDTOOL_TRUE}" && test -z "${BUILD_PLUGIN_RRDTOOL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_RRDTOOL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_SENSORS_TRUE}" && test -z "${BUILD_PLUGIN_SENSORS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_SENSORS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_SERIAL_TRUE}" && test -z "${BUILD_PLUGIN_SERIAL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_SERIAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_SIGROK_TRUE}" && test -z "${BUILD_PLUGIN_SIGROK_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_SIGROK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_SMART_TRUE}" && test -z "${BUILD_PLUGIN_SMART_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_SMART\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_SNMP_TRUE}" && test -z "${BUILD_PLUGIN_SNMP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_SNMP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_STATSD_TRUE}" && test -z "${BUILD_PLUGIN_STATSD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_STATSD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_SWAP_TRUE}" && test -z "${BUILD_PLUGIN_SWAP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_SWAP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_SYSLOG_TRUE}" && test -z "${BUILD_PLUGIN_SYSLOG_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_SYSLOG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TABLE_TRUE}" && test -z "${BUILD_PLUGIN_TABLE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TABLE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TAIL_TRUE}" && test -z "${BUILD_PLUGIN_TAIL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TAIL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TAIL_CSV_TRUE}" && test -z "${BUILD_PLUGIN_TAIL_CSV_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TAIL_CSV\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TAPE_TRUE}" && test -z "${BUILD_PLUGIN_TAPE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TAPE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE}" && test -z "${BUILD_PLUGIN_TARGET_NOTIFICATION_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TARGET_NOTIFICATION\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TARGET_REPLACE_TRUE}" && test -z "${BUILD_PLUGIN_TARGET_REPLACE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TARGET_REPLACE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TARGET_SCALE_TRUE}" && test -z "${BUILD_PLUGIN_TARGET_SCALE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TARGET_SCALE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TARGET_SET_TRUE}" && test -z "${BUILD_PLUGIN_TARGET_SET_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TARGET_SET\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE}" && test -z "${BUILD_PLUGIN_TARGET_V5UPGRADE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TARGET_V5UPGRADE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TCPCONNS_TRUE}" && test -z "${BUILD_PLUGIN_TCPCONNS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TCPCONNS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TEAMSPEAK2_TRUE}" && test -z "${BUILD_PLUGIN_TEAMSPEAK2_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TEAMSPEAK2\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TED_TRUE}" && test -z "${BUILD_PLUGIN_TED_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TED\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_THERMAL_TRUE}" && test -z "${BUILD_PLUGIN_THERMAL_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_THERMAL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_THRESHOLD_TRUE}" && test -z "${BUILD_PLUGIN_THRESHOLD_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_THRESHOLD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TOKYOTYRANT_TRUE}" && test -z "${BUILD_PLUGIN_TOKYOTYRANT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TOKYOTYRANT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_TURBOSTAT_TRUE}" && test -z "${BUILD_PLUGIN_TURBOSTAT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_TURBOSTAT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_UNIXSOCK_TRUE}" && test -z "${BUILD_PLUGIN_UNIXSOCK_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_UNIXSOCK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_UPTIME_TRUE}" && test -z "${BUILD_PLUGIN_UPTIME_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_UPTIME\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_USERS_TRUE}" && test -z "${BUILD_PLUGIN_USERS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_USERS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_UUID_TRUE}" && test -z "${BUILD_PLUGIN_UUID_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_UUID\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_VARNISH_TRUE}" && test -z "${BUILD_PLUGIN_VARNISH_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_VARNISH\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_VIRT_TRUE}" && test -z "${BUILD_PLUGIN_VIRT_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_VIRT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_VMEM_TRUE}" && test -z "${BUILD_PLUGIN_VMEM_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_VMEM\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_VSERVER_TRUE}" && test -z "${BUILD_PLUGIN_VSERVER_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_VSERVER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WIRELESS_TRUE}" && test -z "${BUILD_PLUGIN_WIRELESS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WIRELESS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_GRAPHITE_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_GRAPHITE_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_GRAPHITE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_HTTP_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_HTTP_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_HTTP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_KAFKA_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_KAFKA_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_KAFKA\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_LOG_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_LOG_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_LOG\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_MONGODB_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_MONGODB_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_MONGODB\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_REDIS_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_REDIS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_REDIS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_RIEMANN_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_RIEMANN_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_RIEMANN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_SENSU_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_SENSU_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_SENSU\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_WRITE_TSDB_TRUE}" && test -z "${BUILD_PLUGIN_WRITE_TSDB_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_WRITE_TSDB\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_XMMS_TRUE}" && test -z "${BUILD_PLUGIN_XMMS_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_XMMS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ZFS_ARC_TRUE}" && test -z "${BUILD_PLUGIN_ZFS_ARC_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ZFS_ARC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${BUILD_PLUGIN_ZOOKEEPER_TRUE}" && test -z "${BUILD_PLUGIN_ZOOKEEPER_FALSE}"; then
+  as_fn_error $? "conditional \"BUILD_PLUGIN_ZOOKEEPER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by collectd $as_me 5.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+collectd config.status 5.5.0
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+OBJDUMP \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+DLLTOOL \
+sharedlib_from_linklib_cmd \
+AR \
+AR_FLAGS \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+nm_file_list_spec \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "src/libcollectdclient/collectd/lcc_features.h") CONFIG_FILES="$CONFIG_FILES src/libcollectdclient/collectd/lcc_features.h" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+    "src/daemon/Makefile") CONFIG_FILES="$CONFIG_FILES src/daemon/Makefile" ;;
+    "src/collectd.conf") CONFIG_FILES="$CONFIG_FILES src/collectd.conf" ;;
+    "src/libcollectdclient/Makefile") CONFIG_FILES="$CONFIG_FILES src/libcollectdclient/Makefile" ;;
+    "src/libcollectdclient/libcollectdclient.pc") CONFIG_FILES="$CONFIG_FILES src/libcollectdclient/libcollectdclient.pc" ;;
+    "src/liboconfig/Makefile") CONFIG_FILES="$CONFIG_FILES src/liboconfig/Makefile" ;;
+    "bindings/Makefile") CONFIG_FILES="$CONFIG_FILES bindings/Makefile" ;;
+    "bindings/java/Makefile") CONFIG_FILES="$CONFIG_FILES bindings/java/Makefile" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = "\a"
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=[    ]*/{
+h
+s///
+s/^/:/
+s/[     ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[  ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[    ]*#[    ]*define[       ][      ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+         $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+       `' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$_am_arg" : 'X\(//\)[^/]' \| \
+        X"$_am_arg" : 'X\(//\)$' \| \
+        X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# An object symbol dumper.
+OBJDUMP=$lt_OBJDUMP
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive.
+AR_FLAGS=$lt_AR_FLAGS
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and in which our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+  if test x"$xsi_shell" = xyes; then
+  sed -e '/^func_dirname ()$/,/^} # func_dirname /c\
+func_dirname ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_basename ()$/,/^} # func_basename /c\
+func_basename ()\
+{\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\
+func_dirname_and_basename ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_stripname ()$/,/^} # func_stripname /c\
+func_stripname ()\
+{\
+\    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\
+\    # positional parameters, so assign one to ordinary parameter first.\
+\    func_stripname_result=${3}\
+\    func_stripname_result=${func_stripname_result#"${1}"}\
+\    func_stripname_result=${func_stripname_result%"${2}"}\
+} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\
+func_split_long_opt ()\
+{\
+\    func_split_long_opt_name=${1%%=*}\
+\    func_split_long_opt_arg=${1#*=}\
+} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\
+func_split_short_opt ()\
+{\
+\    func_split_short_opt_arg=${1#??}\
+\    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\
+} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\
+func_lo2o ()\
+{\
+\    case ${1} in\
+\      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\
+\      *)    func_lo2o_result=${1} ;;\
+\    esac\
+} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_xform ()$/,/^} # func_xform /c\
+func_xform ()\
+{\
+    func_xform_result=${1%.*}.lo\
+} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_arith ()$/,/^} # func_arith /c\
+func_arith ()\
+{\
+    func_arith_result=$(( $* ))\
+} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_len ()$/,/^} # func_len /c\
+func_len ()\
+{\
+    func_len_result=${#1}\
+} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+fi
+
+if test x"$lt_shell_append" = xyes; then
+  sed -e '/^func_append ()$/,/^} # func_append /c\
+func_append ()\
+{\
+    eval "${1}+=\\${2}"\
+} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\
+func_append_quoted ()\
+{\
+\    func_quote_for_eval "${2}"\
+\    eval "${1}+=\\\\ \\$func_quote_for_eval_result"\
+} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5
+$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;}
+fi
+
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$mf" : 'X\(//\)[^/]' \| \
+        X"$mf" : 'X\(//\)$' \| \
+        X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$file" : 'X\(//\)[^/]' \| \
+        X"$file" : 'X\(//\)$' \| \
+        X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+  # Remove --cache-file, --srcdir, and --disable-option-checking arguments
+  # so they do not pile up.
+  ac_sub_configure_args=
+  ac_prev=
+  eval "set x $ac_configure_args"
+  shift
+  for ac_arg
+  do
+    if test -n "$ac_prev"; then
+      ac_prev=
+      continue
+    fi
+    case $ac_arg in
+    -cache-file | --cache-file | --cache-fil | --cache-fi \
+    | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+      ac_prev=cache_file ;;
+    -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+    | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+    | --c=*)
+      ;;
+    --config-cache | -C)
+      ;;
+    -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+      ac_prev=srcdir ;;
+    -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+      ;;
+    -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+      ac_prev=prefix ;;
+    -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+      ;;
+    --disable-option-checking)
+      ;;
+    *)
+      case $ac_arg in
+      *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+      esac
+      as_fn_append ac_sub_configure_args " '$ac_arg'" ;;
+    esac
+  done
+
+  # Always prepend --prefix to ensure using the same prefix
+  # in subdir configurations.
+  ac_arg="--prefix=$prefix"
+  case $ac_arg in
+  *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+  esac
+  ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args"
+
+  # Pass --silent
+  if test "$silent" = yes; then
+    ac_sub_configure_args="--silent $ac_sub_configure_args"
+  fi
+
+  # Always prepend --disable-option-checking to silence warnings, since
+  # different subdirs can have different --enable and --with options.
+  ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args"
+
+  ac_popdir=`pwd`
+  for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+    # Do not complain, so a configure script can configure whichever
+    # parts of a large source tree are present.
+    test -d "$srcdir/$ac_dir" || continue
+
+    ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)"
+    $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5
+    $as_echo "$ac_msg" >&6
+    as_dir="$ac_dir"; as_fn_mkdir_p
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+    cd "$ac_dir"
+
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      ac_sub_configure=$ac_srcdir/configure.gnu
+    elif test -f "$ac_srcdir/configure"; then
+      ac_sub_configure=$ac_srcdir/configure
+    elif test -f "$ac_srcdir/configure.in"; then
+      # This should be Cygnus configure.
+      ac_sub_configure=$ac_aux_dir/configure
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5
+$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+      ac_sub_configure=
+    fi
+
+    # The recursion is here.
+    if test -n "$ac_sub_configure"; then
+      # Make the cache file name correct relative to the subdirectory.
+      case $cache_file in
+      [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+      *) # Relative name.
+       ac_sub_cache_file=$ac_top_build_prefix$cache_file ;;
+      esac
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+      # The eval makes quoting arguments work.
+      eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \
+          --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" ||
+       as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5
+    fi
+
+    cd "$ac_popdir"
+  done
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+if test "x$with_librrd" = "xyes" \
+       && test "x$librrd_threadsafe" != "xyes"
+then
+       with_librrd="yes (warning: librrd is not thread-safe)"
+fi
+
+if test "x$with_libperl" = "xyes"
+then
+       with_libperl="yes (version `$perl_interpreter -MConfig -e 'print $Config{version};'`)"
+else
+       enable_perl="no (needs libperl)"
+fi
+
+if test "x$enable_perl" = "xno" && test "x$c_cv_have_perl_ithreads" = "xno"
+then
+       enable_perl="no (libperl doesn't support ithreads)"
+fi
+
+if test "x$with_perl_bindings" = "xyes" \
+       && test "x$PERL_BINDINGS_OPTIONS" != "x"
+then
+       with_perl_bindings="yes ($PERL_BINDINGS_OPTIONS)"
+fi
+
+cat <<EOF;
+
+Configuration:
+  Libraries:
+    intel mic . . . . . . $with_mic
+    libaquaero5 . . . . . $with_libaquaero5
+    libatasmart . . . . . $with_libatasmart
+    libcurl . . . . . . . $with_libcurl
+    libdbi  . . . . . . . $with_libdbi
+    libesmtp  . . . . . . $with_libesmtp
+    libganglia  . . . . . $with_libganglia
+    libgcrypt . . . . . . $with_libgcrypt
+    libhal  . . . . . . . $with_libhal
+    libhiredis  . . . . . $with_libhiredis
+    libi2c-dev  . . . . . $with_libi2c
+    libiokit  . . . . . . $with_libiokit
+    libiptc . . . . . . . $with_libiptc
+    libjvm  . . . . . . . $with_java
+    libkstat  . . . . . . $with_kstat
+    libkvm  . . . . . . . $with_libkvm
+    libldap . . . . . . . $with_libldap
+    liblvm2app  . . . . . $with_liblvm2app
+    libmemcached  . . . . $with_libmemcached
+    libmnl  . . . . . . . $with_libmnl
+    libmodbus . . . . . . $with_libmodbus
+    libmongoc . . . . . . $with_libmongoc
+    libmysql  . . . . . . $with_libmysql
+    libnetapp . . . . . . $with_libnetapp
+    libnetsnmp  . . . . . $with_libnetsnmp
+    libnotify . . . . . . $with_libnotify
+    liboconfig  . . . . . $with_liboconfig
+    libopenipmi . . . . . $with_libopenipmipthread
+    liboping  . . . . . . $with_liboping
+    libowcapi . . . . . . $with_libowcapi
+    libpcap . . . . . . . $with_libpcap
+    libperfstat . . . . . $with_perfstat
+    libperl . . . . . . . $with_libperl
+    libpq . . . . . . . . $with_libpq
+    libpthread  . . . . . $with_libpthread
+    librabbitmq . . . . . $with_librabbitmq
+    librdkafka  . . . . . $with_librdkafka
+    librouteros . . . . . $with_librouteros
+    librrd  . . . . . . . $with_librrd
+    libsensors  . . . . . $with_libsensors
+    libsigrok   . . . . . $with_libsigrok
+    libstatgrab . . . . . $with_libstatgrab
+    libtokyotyrant  . . . $with_libtokyotyrant
+    libudev . . . . . . . $with_libudev
+    libupsclient  . . . . $with_libupsclient
+    libvarnish  . . . . . $with_libvarnish
+    libvirt . . . . . . . $with_libvirt
+    libxml2 . . . . . . . $with_libxml2
+    libxmms . . . . . . . $with_libxmms
+    libyajl . . . . . . . $with_libyajl
+    oracle  . . . . . . . $with_oracle
+    protobuf-c  . . . . . $have_protoc_c
+    python  . . . . . . . $with_python
+
+  Features:
+    daemon mode . . . . . $enable_daemon
+    debug . . . . . . . . $enable_debug
+
+  Bindings:
+    perl  . . . . . . . . $with_perl_bindings
+
+  Modules:
+    aggregation . . . . . $enable_aggregation
+    amqp    . . . . . . . $enable_amqp
+    apache  . . . . . . . $enable_apache
+    apcups  . . . . . . . $enable_apcups
+    apple_sensors . . . . $enable_apple_sensors
+    aquaero . . . . . . . $enable_aquaero
+    ascent  . . . . . . . $enable_ascent
+    barometer . . . . . . $enable_barometer
+    battery . . . . . . . $enable_battery
+    bind  . . . . . . . . $enable_bind
+    ceph  . . . . . . . . $enable_ceph
+    cgroups . . . . . . . $enable_cgroups
+    conntrack . . . . . . $enable_conntrack
+    contextswitch . . . . $enable_contextswitch
+    cpu . . . . . . . . . $enable_cpu
+    cpufreq . . . . . . . $enable_cpufreq
+    csv . . . . . . . . . $enable_csv
+    curl  . . . . . . . . $enable_curl
+    curl_json . . . . . . $enable_curl_json
+    curl_xml  . . . . . . $enable_curl_xml
+    dbi . . . . . . . . . $enable_dbi
+    df  . . . . . . . . . $enable_df
+    disk  . . . . . . . . $enable_disk
+    dns . . . . . . . . . $enable_dns
+    drbd  . . . . . . . . $enable_drbd
+    email . . . . . . . . $enable_email
+    entropy . . . . . . . $enable_entropy
+    ethstat . . . . . . . $enable_ethstat
+    exec  . . . . . . . . $enable_exec
+    fhcount . . . . . . . $enable_fhcount
+    filecount . . . . . . $enable_filecount
+    fscache . . . . . . . $enable_fscache
+    gmond . . . . . . . . $enable_gmond
+    hddtemp . . . . . . . $enable_hddtemp
+    interface . . . . . . $enable_interface
+    ipc . . . . . . . . . $enable_ipc
+    ipmi  . . . . . . . . $enable_ipmi
+    iptables  . . . . . . $enable_iptables
+    ipvs  . . . . . . . . $enable_ipvs
+    irq . . . . . . . . . $enable_irq
+    java  . . . . . . . . $enable_java
+    load  . . . . . . . . $enable_load
+    logfile . . . . . . . $enable_logfile
+    log_logstash  . . . . $enable_log_logstash
+    lpar  . . . . . . . . $enable_lpar
+    lvm . . . . . . . . . $enable_lvm
+    madwifi . . . . . . . $enable_madwifi
+    match_empty_counter . $enable_match_empty_counter
+    match_hashed  . . . . $enable_match_hashed
+    match_regex . . . . . $enable_match_regex
+    match_timediff  . . . $enable_match_timediff
+    match_value . . . . . $enable_match_value
+    mbmon . . . . . . . . $enable_mbmon
+    md  . . . . . . . . . $enable_md
+    memcachec . . . . . . $enable_memcachec
+    memcached . . . . . . $enable_memcached
+    memory  . . . . . . . $enable_memory
+    mic . . . . . . . . . $enable_mic
+    modbus  . . . . . . . $enable_modbus
+    multimeter  . . . . . $enable_multimeter
+    mysql . . . . . . . . $enable_mysql
+    netapp  . . . . . . . $enable_netapp
+    netlink . . . . . . . $enable_netlink
+    network . . . . . . . $enable_network
+    nfs . . . . . . . . . $enable_nfs
+    nginx . . . . . . . . $enable_nginx
+    notify_desktop  . . . $enable_notify_desktop
+    notify_email  . . . . $enable_notify_email
+    ntpd  . . . . . . . . $enable_ntpd
+    numa  . . . . . . . . $enable_numa
+    nut . . . . . . . . . $enable_nut
+    olsrd . . . . . . . . $enable_olsrd
+    onewire . . . . . . . $enable_onewire
+    openldap  . . . . . . $enable_openldap
+    openvpn . . . . . . . $enable_openvpn
+    oracle  . . . . . . . $enable_oracle
+    perl  . . . . . . . . $enable_perl
+    pf  . . . . . . . . . $enable_pf
+    pinba . . . . . . . . $enable_pinba
+    ping  . . . . . . . . $enable_ping
+    postgresql  . . . . . $enable_postgresql
+    powerdns  . . . . . . $enable_powerdns
+    processes . . . . . . $enable_processes
+    protocols . . . . . . $enable_protocols
+    python  . . . . . . . $enable_python
+    redis . . . . . . . . $enable_redis
+    routeros  . . . . . . $enable_routeros
+    rrdcached . . . . . . $enable_rrdcached
+    rrdtool . . . . . . . $enable_rrdtool
+    sensors . . . . . . . $enable_sensors
+    serial  . . . . . . . $enable_serial
+    sigrok  . . . . . . . $enable_sigrok
+    smart . . . . . . . . $enable_smart
+    snmp  . . . . . . . . $enable_snmp
+    statsd  . . . . . . . $enable_statsd
+    swap  . . . . . . . . $enable_swap
+    syslog  . . . . . . . $enable_syslog
+    table . . . . . . . . $enable_table
+    tail_csv  . . . . . . $enable_tail_csv
+    tail  . . . . . . . . $enable_tail
+    tape  . . . . . . . . $enable_tape
+    target_notification . $enable_target_notification
+    target_replace  . . . $enable_target_replace
+    target_scale  . . . . $enable_target_scale
+    target_set  . . . . . $enable_target_set
+    target_v5upgrade  . . $enable_target_v5upgrade
+    tcpconns  . . . . . . $enable_tcpconns
+    teamspeak2  . . . . . $enable_teamspeak2
+    ted . . . . . . . . . $enable_ted
+    thermal . . . . . . . $enable_thermal
+    threshold . . . . . . $enable_threshold
+    tokyotyrant . . . . . $enable_tokyotyrant
+    turbostat . . . . . . $enable_turbostat
+    unixsock  . . . . . . $enable_unixsock
+    uptime  . . . . . . . $enable_uptime
+    users . . . . . . . . $enable_users
+    uuid  . . . . . . . . $enable_uuid
+    varnish . . . . . . . $enable_varnish
+    virt  . . . . . . . . $enable_virt
+    vmem  . . . . . . . . $enable_vmem
+    vserver . . . . . . . $enable_vserver
+    wireless  . . . . . . $enable_wireless
+    write_graphite  . . . $enable_write_graphite
+    write_http  . . . . . $enable_write_http
+    write_kafka . . . . . $enable_write_kafka
+    write_log . . . . . . $enable_write_log
+    write_mongodb . . . . $enable_write_mongodb
+    write_redis . . . . . $enable_write_redis
+    write_riemann . . . . $enable_write_riemann
+    write_sensu . . . . . $enable_write_sensu
+    write_tsdb  . . . . . $enable_write_tsdb
+    xmms  . . . . . . . . $enable_xmms
+    zfs_arc . . . . . . . $enable_zfs_arc
+    zookeeper . . . . . . $enable_zookeeper
+
+EOF
+
+if test "x$dependency_error" = "xyes"; then
+       as_fn_error $? "\"Some plugins are missing dependencies - see the summary above for details\"" "$LINENO" 5
+fi
+
+if test "x$dependency_warning" = "xyes"; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \"Some plugins seem to have missing dependencies but have been enabled forcibly - see the summary above for details\"" >&5
+$as_echo "$as_me: WARNING: \"Some plugins seem to have missing dependencies but have been enabled forcibly - see the summary above for details\"" >&2;}
+fi
+
+# vim: set fdm=marker :
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..87d1502
--- /dev/null
@@ -0,0 +1,6048 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT([collectd],[m4_esyscmd(./version-gen.sh)])
+AC_CONFIG_SRCDIR(src/)
+AC_CONFIG_HEADERS(src/config.h)
+AC_CONFIG_AUX_DIR([libltdl/config])
+
+m4_ifdef([LT_PACKAGE_VERSION],
+       # libtool >= 2.2
+       [
+        LT_CONFIG_LTDL_DIR([libltdl])
+        LT_INIT([dlopen])
+        LTDL_INIT([convenience])
+        AC_DEFINE(LIBTOOL_VERSION, 2, [Define to used libtool version.])
+       ]
+,
+       # libtool <= 1.5
+       [
+        AC_LIBLTDL_CONVENIENCE
+        AC_SUBST(LTDLINCL)
+        AC_SUBST(LIBLTDL)
+        AC_LIBTOOL_DLOPEN
+        AC_CONFIG_SUBDIRS(libltdl)
+        AC_DEFINE(LIBTOOL_VERSION, 1, [Define to used libtool version.])
+       ]
+)
+
+AM_INIT_AUTOMAKE([tar-pax dist-bzip2 foreign])
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+AC_LANG(C)
+
+AC_PREFIX_DEFAULT("/opt/collectd")
+
+AC_SYS_LARGEFILE
+
+#
+# Checks for programs.
+#
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AM_PROG_CC_C_O
+AM_CONDITIONAL(COMPILER_IS_GCC, test "x$GCC" = "xyes")
+
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_PROG_LEX
+AC_PROG_YACC
+PKG_PROG_PKG_CONFIG
+
+AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no])
+AC_CHECK_HEADERS([google/protobuf-c/protobuf-c.h],
+                 [have_protobuf_c_h="yes"],
+                 [have_protobuf_c_h="no"])
+if test "x$have_protoc_c" = "xyes" && test "x$have_protobuf_c_h" != "xyes"
+then
+       have_protoc_c="no (unable to find <google/protobuf-c/protobuf-c.h>)"
+fi
+AM_CONDITIONAL(HAVE_PROTOC_C, test "x$have_protoc_c" = "xyes")
+
+AC_MSG_CHECKING([for kernel type ($host_os)])
+case $host_os in
+       *linux*)
+       AC_DEFINE([KERNEL_LINUX], 1, [True if program is to be compiled for a Linux kernel])
+       ac_system="Linux"
+       ;;
+       *solaris*)
+       AC_DEFINE([KERNEL_SOLARIS], 1, [True if program is to be compiled for a Solaris kernel])
+       ac_system="Solaris"
+       ;;
+       *darwin*)
+       AC_DEFINE([KERNEL_DARWIN], 1, [True if program is to be compiled for a Darwin kernel])
+       ac_system="Darwin"
+       ;;
+       *openbsd*)
+       AC_DEFINE([KERNEL_OPENBSD], 1, [True if program is to be compiled for an OpenBSD kernel])
+       ac_system="OpenBSD"
+       ;;
+       *aix*)
+       AC_DEFINE([KERNEL_AIX], 1, [True if program is to be compiled for a AIX kernel])
+       ac_system="AIX"
+       ;;
+       *freebsd*)
+       AC_DEFINE([KERNEL_FREEBSD], 1, [True if program is to be compiled for a FreeBSD kernel])
+       ac_system="FreeBSD"
+       ;;
+       *)
+       ac_system="unknown"
+esac
+AC_MSG_RESULT([$ac_system])
+
+AM_CONDITIONAL([BUILD_LINUX],[test "x$x$ac_system" = "xLinux"])
+AM_CONDITIONAL([BUILD_SOLARIS],[test "x$x$ac_system" = "xSolaris"])
+AM_CONDITIONAL([BUILD_DARWIN],[test "x$x$ac_system" = "xDarwin"])
+AM_CONDITIONAL([BUILD_OPENBSD],[test "x$x$ac_system" = "xOpenBSD"])
+AM_CONDITIONAL([BUILD_AIX],[test "x$x$ac_system" = "xAIX"])
+AM_CONDITIONAL([BUILD_FREEBSD],[test "x$x$ac_system" = "xFreeBSD"])
+
+if test "x$ac_system" = "xLinux"
+then
+       AC_ARG_VAR([KERNEL_DIR], [path to Linux kernel sources])
+       if test -z "$KERNEL_DIR"
+       then
+               KERNEL_DIR="/lib/modules/`uname -r`/source"
+       fi
+
+       KERNEL_CFLAGS="-I$KERNEL_DIR/include"
+       AC_SUBST(KERNEL_CFLAGS)
+fi
+
+if test "x$ac_system" = "xSolaris"
+then
+       AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Define to enforce POSIX thread semantics under Solaris.])
+       AC_DEFINE(_REENTRANT,               1, [Define to enable reentrancy interfaces.])
+fi
+if test "x$ac_system" = "xAIX"
+then
+       AC_DEFINE(_THREAD_SAFE_ERRNO, 1, [Define to use the thread-safe version of errno under AIX.])
+fi
+
+# Where to install .pc files.
+pkgconfigdir="${libdir}/pkgconfig"
+AC_SUBST(pkgconfigdir)
+
+# Check for standards compliance mode
+AC_ARG_ENABLE(standards,
+             AS_HELP_STRING([--enable-standards], [Enable standards compliance mode]),
+             [enable_standards="$enableval"],
+             [enable_standards="no"])
+if test "x$enable_standards" = "xyes"
+then
+       AC_DEFINE(_ISOC99_SOURCE,        1, [Define to enforce ISO C99 compliance.])
+       AC_DEFINE(_POSIX_C_SOURCE, 200809L, [Define to enforce POSIX.1-2008 compliance.])
+       AC_DEFINE(_XOPEN_SOURCE,       700, [Define to enforce X/Open 7 (XSI) compliance.])
+       AC_DEFINE(_REENTRANT,            1, [Define to enable reentrancy interfaces.])
+       if test "x$GCC" = "xyes"
+       then
+               CFLAGS="$CFLAGS -std=c99"
+       fi
+fi
+AM_CONDITIONAL(BUILD_FEATURE_STANDARDS, test "x$enable_standards" = "xyes")
+
+#
+# Checks for header files.
+#
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_HEADER_DIRENT
+AC_HEADER_STDBOOL
+
+AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h fnmatch.h libgen.h)
+
+# For ping library
+AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/in.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/ip.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/ip_icmp.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/ip_var.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/ip6.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/icmp6.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP6_H
+# include <netinet/ip6.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/tcp.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/udp.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+])
+
+# For cpu modules
+AC_CHECK_HEADERS(sys/dkstat.h)
+if test "x$ac_system" = "xDarwin"
+then
+       AC_CHECK_HEADERS(mach/mach_init.h mach/host_priv.h mach/mach_error.h mach/mach_host.h mach/mach_port.h mach/mach_types.h mach/message.h mach/processor_set.h mach/processor.h mach/processor_info.h mach/task.h mach/thread_act.h mach/vm_region.h mach/vm_map.h mach/vm_prot.h mach/vm_statistics.h mach/kern_return.h)
+       AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h IOKit/IOKitLib.h IOKit/IOTypes.h IOKit/ps/IOPSKeys.h IOKit/IOBSD.h IOKit/storage/IOBlockStorageDriver.h)
+       # For the battery plugin
+       AC_CHECK_HEADERS(IOKit/ps/IOPowerSources.h, [], [],
+[
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+])
+
+fi
+
+AC_CHECK_HEADERS(sys/sysctl.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
+AC_MSG_CHECKING([for sysctl kern.cp_times])
+if test -x /sbin/sysctl
+then
+       /sbin/sysctl kern.cp_times 2>/dev/null
+       if test $? -eq 0
+       then
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_SYSCTL_KERN_CP_TIMES, 1,
+               [Define if sysctl supports kern.cp_times])
+       else
+               AC_MSG_RESULT([no])
+       fi
+else
+       AC_MSG_RESULT([no])
+fi
+
+# For hddtemp module
+AC_CHECK_HEADERS(linux/major.h)
+
+# For md module (Linux only)
+if test "x$ac_system" = "xLinux"
+then
+       AC_CHECK_HEADERS(linux/raid/md_u.h,
+                        [have_linux_raid_md_u_h="yes"],
+                        [have_linux_raid_md_u_h="no"],
+[
+#include <sys/ioctl.h>
+#include <linux/major.h>
+#include <linux/types.h>
+])
+else
+       have_linux_raid_md_u_h="no"
+fi
+
+# For the swap module
+have_linux_wireless_h="no"
+if test "x$ac_system" = "xLinux"
+then
+  AC_CHECK_HEADERS(linux/wireless.h,
+                  [have_linux_wireless_h="yes"],
+                  [have_linux_wireless_h="no"],
+[
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+])
+fi
+
+# For the swap module
+have_sys_swap_h="yes"
+AC_CHECK_HEADERS(sys/swap.h vm/anon.h, [], [have_sys_swap_h="no"],
+[
+#undef _FILE_OFFSET_BITS
+#undef _LARGEFILE64_SOURCE
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
+if test "x$have_sys_swap_h$ac_system" = "xnoSolaris"
+then
+       hint_64=""
+       if test "x$GCC" = "xyes"
+       then
+               hint_64="CFLAGS='-m64'"
+       else
+               hint_64="CFLAGS='-xarch=v9'"
+       fi
+       AC_MSG_NOTICE([Solaris detected and sys/swap.h not usable. Try building a 64-bit binary ($hint_64 ./configure).])
+fi
+
+# For load module
+# For the processes plugin
+# For users module
+AC_CHECK_HEADERS(sys/loadavg.h linux/config.h utmp.h utmpx.h)
+
+# For interface plugin
+AC_CHECK_HEADERS(ifaddrs.h)
+AC_CHECK_HEADERS(net/if.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+])
+AC_CHECK_HEADERS(linux/if.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+])
+AC_CHECK_HEADERS(linux/inet_diag.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#if HAVE_LINUX_INET_DIAG_H
+# include <linux/inet_diag.h>
+#endif
+])
+AC_CHECK_HEADERS(linux/netdevice.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#if HAVE_LINUX_IF_H
+# include <linux/if.h>
+#endif
+])
+
+# For ethstat module
+AC_CHECK_HEADERS(linux/sockios.h,
+    [have_linux_sockios_h="yes"],
+    [have_linux_sockios_h="no"],
+    [
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+    ])
+AC_CHECK_HEADERS(linux/ethtool.h,
+    [have_linux_ethtool_h="yes"],
+    [have_linux_ethtool_h="no"],
+    [
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_LINUX_SOCKIOS_H
+# include <linux/sockios.h>
+#endif
+    ])
+
+# For ipvs module
+have_linux_ip_vs_h="no"
+have_net_ip_vs_h="no"
+have_ip_vs_h="no"
+ip_vs_h_needs_kernel_cflags="no"
+if test "x$ac_system" = "xLinux"
+then
+       AC_CHECK_HEADERS(linux/ip_vs.h, [have_linux_ip_vs_h="yes"])
+       AC_CHECK_HEADERS(net/ip_vs.h, [have_net_ip_vs_h="yes"])
+       AC_CHECK_HEADERS(ip_vs.h, [have_ip_vs_h="yes"])
+
+       if test "x$have_linux_ip_vs_h$have_net_ip_vs_h$have_ip_vs_h" = "xnonono" && test -d "$KERNEL_DIR"
+       then
+               SAVE_CFLAGS="$CFLAGS"
+               CFLAGS="$CFLAGS $KERNEL_CFLAGS"
+
+               AC_MSG_NOTICE([Did not find ip_vs.h. Trying again using headers from $KERNEL_DIR.])
+
+               AC_CHECK_HEADERS(linux/ip_vs.h, [have_linux_ip_vs_h="yes"])
+               AC_CHECK_HEADERS(net/ip_vs.h, [have_net_ip_vs_h="yes"])
+               AC_CHECK_HEADERS(ip_vs.h, [have_ip_vs_h="yes"])
+
+               if test "x$have_linux_ip_vs_h" = "xyes" || test "x$have_net_ip_vs_h" = "xyes" || test "x$have_ip_vs_h" = "xyes"
+               then
+                       ip_vs_h_needs_kernel_cflags="yes"
+               fi
+
+               CFLAGS="$SAVE_CFLAGS"
+       fi
+fi
+AM_CONDITIONAL(IP_VS_H_NEEDS_KERNEL_CFLAGS, test "x$ip_vs_h_needs_kernel_cflags" = "xyes")
+
+# For quota module
+AC_CHECK_HEADERS(sys/ucred.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
+# For mount interface
+AC_CHECK_HEADERS(sys/mount.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
+# For the email plugin
+AC_CHECK_HEADERS(linux/un.h, [], [],
+[
+#if HAVE_SYS_SOCKET_H
+#      include <sys/socket.h>
+#endif
+])
+
+AC_CHECK_HEADERS(pwd.h grp.h sys/un.h ctype.h limits.h xfs/xqm.h fs_info.h fshelp.h paths.h mntent.h mnttab.h sys/fstyp.h sys/fs_types.h sys/mntent.h sys/mnttab.h sys/statfs.h sys/statvfs.h sys/vfs.h sys/vfstab.h sys/vmmeter.h kvm.h wordexp.h locale.h)
+
+# 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
+# include <sys/socket.h>
+#endif
+])
+AC_CHECK_HEADERS(net/ppp_defs.h)
+AC_CHECK_HEADERS(net/if_ppp.h, [], [],
+[#if HAVE_NET_PPP_DEFS_H
+# include <net/ppp_defs.h>
+#endif
+])
+AC_CHECK_HEADERS(netinet/if_ether.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+])
+
+AC_CHECK_HEADERS(netinet/ip_compat.h)
+
+have_net_pfvar_h="no"
+AC_CHECK_HEADERS(net/pfvar.h,
+               [have_net_pfvar_h="yes"],
+               [have_net_pfvar_h="no"],
+[
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+])
+
+# For the multimeter plugin
+have_termios_h="no"
+AC_CHECK_HEADERS(termios.h, [have_termios_h="yes"])
+
+# For the turbostat plugin
+have_asm_msrindex_h="no"
+AC_CHECK_HEADERS(asm/msr-index.h, [have_asm_msrindex_h="yes"])
+
+if test "x$have_asm_msrindex_h" = "xyes"
+then
+  AC_CACHE_CHECK([whether asm/msr-index.h has MSR_CORE_C3_RESIDENCY],
+                 [c_cv_have_usable_asm_msrindex_h],
+                 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include<asm/msr-index.h>
+]]],
+[[[
+int y = MSR_CORE_C3_RESIDENCY;
+return(y);
+]]]
+  )],
+                 [c_cv_have_usable_asm_msrindex_h="yes"],
+                 [c_cv_have_usable_asm_msrindex_h="no"],
+                                  )
+                 )
+fi
+
+have_cpuid_h="no"
+AC_CHECK_HEADERS(cpuid.h, [have_cpuid_h="yes"])
+
+AC_CHECK_HEADERS(sys/capability.h)
+#
+# Checks for typedefs, structures, and compiler characteristics.
+#
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UID_T
+AC_TYPE_UINT32_T
+AC_HEADER_TIME
+
+#
+# Checks for library functions.
+#
+AC_PROG_GCC_TRADITIONAL
+AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale)
+
+AC_FUNC_STRERROR_R
+
+SAVE_CFLAGS="$CFLAGS"
+# Emulate behavior of src/Makefile.am
+if test "x$GCC" = "xyes"
+then
+       CFLAGS="$CFLAGS -Wall -Werror"
+fi
+
+AC_CACHE_CHECK([for strtok_r],
+  [c_cv_have_strtok_r_default],
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+]]],
+[[[
+      char buffer[] = "foo,bar,baz";
+      char *token;
+      char *dummy;
+      char *saveptr;
+
+      dummy = buffer;
+      saveptr = NULL;
+      while ((token = strtok_r (dummy, ",", &saveptr)) != NULL)
+      {
+        dummy = NULL;
+        printf ("token = %s;\n", token);
+      }
+]]]
+    )],
+    [c_cv_have_strtok_r_default="yes"],
+    [c_cv_have_strtok_r_default="no"]
+  )
+)
+
+if test "x$c_cv_have_strtok_r_default" = "xno"
+then
+  CFLAGS="$CFLAGS -D_REENTRANT=1"
+
+  AC_CACHE_CHECK([if strtok_r needs _REENTRANT],
+    [c_cv_have_strtok_r_reentrant],
+    AC_LINK_IFELSE(
+      [AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+]]],
+[[[
+        char buffer[] = "foo,bar,baz";
+        char *token;
+        char *dummy;
+        char *saveptr;
+
+        dummy = buffer;
+        saveptr = NULL;
+        while ((token = strtok_r (dummy, ",", &saveptr)) != NULL)
+        {
+          dummy = NULL;
+          printf ("token = %s;\n", token);
+        }
+]]]
+      )],
+      [c_cv_have_strtok_r_reentrant="yes"],
+      [AC_MSG_FAILURE([strtok_r isn't available. Please file a bugreport!])]
+    )
+  )
+fi
+
+CFLAGS="$SAVE_CFLAGS"
+if test "x$c_cv_have_strtok_r_reentrant" = "xyes"
+then
+       CFLAGS="$CFLAGS -D_REENTRANT=1"
+fi
+
+AC_CHECK_FUNCS(getpwnam_r getgrnam_r setgroups regcomp regerror regexec regfree)
+
+socket_needs_socket="no"
+AC_CHECK_FUNCS(socket, [], AC_CHECK_LIB(socket, socket, [socket_needs_socket="yes"], AC_MSG_ERROR(cannot find socket)))
+AM_CONDITIONAL(BUILD_WITH_LIBSOCKET, test "x$socket_needs_socket" = "xyes")
+
+clock_gettime_needs_rt="no"
+clock_gettime_needs_posix4="no"
+have_clock_gettime="no"
+AC_CHECK_FUNCS(clock_gettime, [have_clock_gettime="yes"])
+if test "x$have_clock_gettime" = "xno"
+then
+       AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_needs_rt="yes"
+                                        have_clock_gettime="yes"])
+fi
+if test "x$have_clock_gettime" = "xno"
+then
+       AC_CHECK_LIB(posix4, clock_gettime, [clock_gettime_needs_posix4="yes"
+                                            have_clock_gettime="yes"])
+fi
+if test "x$have_clock_gettime" = "xyes"
+then
+       AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if the clock_gettime(2) function is available.])
+else
+       AC_MSG_WARN(cannot find clock_gettime)
+fi
+
+nanosleep_needs_rt="no"
+nanosleep_needs_posix4="no"
+AC_CHECK_FUNCS(nanosleep,
+    [],
+    AC_CHECK_LIB(rt, nanosleep,
+        [nanosleep_needs_rt="yes"],
+        AC_CHECK_LIB(posix4, nanosleep,
+            [nanosleep_needs_posix4="yes"],
+            AC_MSG_ERROR(cannot find nanosleep))))
+
+AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$clock_gettime_needs_rt" = "xyes" || test "x$nanosleep_needs_rt" = "xyes")
+AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$clock_gettime_needs_posix4" = "xyes" || test "x$nanosleep_needs_posix4" = "xyes")
+
+AC_CHECK_FUNCS(sysctl, [have_sysctl="yes"], [have_sysctl="no"])
+AC_CHECK_FUNCS(sysctlbyname, [have_sysctlbyname="yes"], [have_sysctlbyname="no"])
+AC_CHECK_FUNCS(host_statistics, [have_host_statistics="yes"], [have_host_statistics="no"])
+AC_CHECK_FUNCS(processor_info, [have_processor_info="yes"], [have_processor_info="no"])
+AC_CHECK_FUNCS(thread_info, [have_thread_info="yes"], [have_thread_info="no"])
+AC_CHECK_FUNCS(statfs, [have_statfs="yes"], [have_statfs="no"])
+AC_CHECK_FUNCS(statvfs, [have_statvfs="yes"], [have_statvfs="no"])
+AC_CHECK_FUNCS(getifaddrs, [have_getifaddrs="yes"], [have_getifaddrs="no"])
+AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"])
+AC_CHECK_FUNCS(syslog, [have_syslog="yes"], [have_syslog="no"])
+AC_CHECK_FUNCS(getutent, [have_getutent="yes"], [have_getutent="no"])
+AC_CHECK_FUNCS(getutxent, [have_getutxent="yes"], [have_getutxent="no"])
+
+# Check for strptime {{{
+if test "x$GCC" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS -Wall -Wextra -Werror"
+fi
+
+AC_CHECK_FUNCS(strptime, [have_strptime="yes"], [have_strptime="no"])
+if test "x$have_strptime" = "xyes"
+then
+       AC_CACHE_CHECK([whether strptime is exported by default],
+                      [c_cv_have_strptime_default],
+                      AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <time.h>
+]]],
+[[[
+ struct tm stm;
+ (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm);
+]]]
+                      )],
+                      [c_cv_have_strptime_default="yes"],
+                      [c_cv_have_strptime_default="no"]))
+fi
+if test "x$have_strptime" = "xyes" && test "x$c_cv_have_strptime_default" = "xno"
+then
+       AC_CACHE_CHECK([whether strptime needs standards mode],
+                      [c_cv_have_strptime_standards],
+                      AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[[
+#ifndef _ISOC99_SOURCE
+# define _ISOC99_SOURCE 1
+#endif
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200112L
+#endif
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 500
+#endif
+#include <time.h>
+]]],
+[[[
+ struct tm stm;
+ (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm);
+]]]
+                      )],
+                      [c_cv_have_strptime_standards="yes"],
+                      [c_cv_have_strptime_standards="no"]))
+
+       if test "x$c_cv_have_strptime_standards" = "xyes"
+       then
+               AC_DEFINE([STRPTIME_NEEDS_STANDARDS], 1, [Set to true if strptime is only exported in X/Open mode (GNU libc).])
+       else
+               have_strptime="no"
+       fi
+fi
+
+if test "x$GCC" = "xyes"
+then
+       CFLAGS="$SAVE_CFLAGS"
+fi
+# }}} Check for strptime
+
+AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"])
+if test "x$have_swapctl" = "xyes"; then
+        AC_CACHE_CHECK([whether swapctl takes two arguments],
+                [c_cv_have_swapctl_two_args],
+                AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[[
+#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  undef _FILE_OFFSET_BITS
+#  undef _LARGEFILE64_SOURCE
+#endif
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/swap.h>
+#include <unistd.h>
+]]],
+[[[
+int num = swapctl(0, NULL);
+]]]
+                        )],
+                        [c_cv_have_swapctl_two_args="yes"],
+                        [c_cv_have_swapctl_two_args="no"]
+                )
+        )
+        AC_CACHE_CHECK([whether swapctl takes three arguments],
+                [c_cv_have_swapctl_three_args],
+                AC_COMPILE_IFELSE(
+                        [AC_LANG_PROGRAM(
+[[[
+#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  undef _FILE_OFFSET_BITS
+#  undef _LARGEFILE64_SOURCE
+#endif
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/swap.h>
+#include <unistd.h>
+]]],
+[[[
+int num = swapctl(0, NULL, 0);
+]]]
+                        )],
+                        [c_cv_have_swapctl_three_args="yes"],
+                        [c_cv_have_swapctl_three_args="no"]
+                )
+        )
+fi
+# Check for different versions of `swapctl' here..
+if test "x$have_swapctl" = "xyes"; then
+        if test "x$c_cv_have_swapctl_two_args" = "xyes"; then
+                AC_DEFINE(HAVE_SWAPCTL_TWO_ARGS, 1,
+                          [Define if the function swapctl exists and takes two arguments.])
+        fi
+        if test "x$c_cv_have_swapctl_three_args" = "xyes"; then
+                AC_DEFINE(HAVE_SWAPCTL_THREE_ARGS, 1,
+                          [Define if the function swapctl exists and takes three arguments.])
+        fi
+fi
+
+# Check for NAN
+AC_ARG_WITH(nan-emulation, [AS_HELP_STRING([--with-nan-emulation], [use emulated NAN. For crosscompiling only.])],
+[
+ if test "x$withval" = "xno"; then
+        nan_type="none"
+ else if test "x$withval" = "xyes"; then
+        nan_type="zero"
+ else
+        nan_type="$withval"
+ fi; fi
+],
+[nan_type="none"])
+if test "x$nan_type" = "xnone"; then
+  AC_CACHE_CHECK([whether NAN is defined by default],
+    [c_cv_have_nan_default],
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#include <math.h>
+static double foo = NAN;
+]]],
+[[[
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+]]]
+      )],
+      [c_cv_have_nan_default="yes"],
+      [c_cv_have_nan_default="no"]
+    )
+  )
+  if test "x$c_cv_have_nan_default" = "xyes"
+  then
+    nan_type="default"
+  fi
+fi
+if test "x$nan_type" = "xnone"; then
+  AC_CACHE_CHECK([whether NAN is defined by __USE_ISOC99],
+    [c_cv_have_nan_isoc],
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#define __USE_ISOC99 1
+#include <math.h>
+static double foo = NAN;
+]]],
+[[[
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+]]]
+      )],
+      [c_cv_have_nan_isoc="yes"],
+      [c_cv_have_nan_isoc="no"]
+    )
+  )
+  if test "x$c_cv_have_nan_isoc" = "xyes"
+  then
+    nan_type="isoc99"
+  fi
+fi
+if test "x$nan_type" = "xnone"; then
+  SAVE_LDFLAGS=$LDFLAGS
+  LDFLAGS="$LDFLAGS -lm"
+  AC_CACHE_CHECK([whether NAN can be defined by 0/0],
+    [c_cv_have_nan_zero],
+    AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#include <math.h>
+#ifdef NAN
+# undef NAN
+#endif
+#define NAN (0.0 / 0.0)
+#ifndef isnan
+# define isnan(f) ((f) != (f))
+#endif
+static double foo = NAN;
+]]],
+[[[
+       if (isnan (foo))
+        return 0;
+       else
+       return 1;
+]]]
+      )],
+      [c_cv_have_nan_zero="yes"],
+      [c_cv_have_nan_zero="no"]
+    )
+  )
+  LDFLAGS=$SAVE_LDFLAGS
+  if test "x$c_cv_have_nan_zero" = "xyes"
+  then
+    nan_type="zero"
+  fi
+fi
+
+if test "x$nan_type" = "xdefault"; then
+  AC_DEFINE(NAN_STATIC_DEFAULT, 1,
+    [Define if NAN is defined by default and can initialize static variables.])
+else if test "x$nan_type" = "xisoc99"; then
+  AC_DEFINE(NAN_STATIC_ISOC, 1,
+    [Define if NAN is defined by __USE_ISOC99 and can initialize static variables.])
+else if test "x$nan_type" = "xzero"; then
+  AC_DEFINE(NAN_ZERO_ZERO, 1,
+    [Define if NAN can be defined as (0.0 / 0.0)])
+else
+  AC_MSG_ERROR([Didn't find out how to statically initialize variables to NAN. Sorry.])
+fi; fi; fi
+
+AC_ARG_WITH(fp-layout, [AS_HELP_STRING([--with-fp-layout], [set the memory layout of doubles. For crosscompiling only.])],
+[
+ if test "x$withval" = "xnothing"; then
+       fp_layout_type="nothing"
+ else if test "x$withval" = "xendianflip"; then
+       fp_layout_type="endianflip"
+ else if test "x$withval" = "xintswap"; then
+       fp_layout_type="intswap"
+ else
+       AC_MSG_ERROR([Invalid argument for --with-fp-layout. Valid arguments are: nothing, endianflip, intswap]);
+fi; fi; fi
+],
+[fp_layout_type="unknown"])
+
+if test "x$fp_layout_type" = "xunknown"; then
+  AC_CACHE_CHECK([if doubles are stored in x86 representation],
+    [c_cv_fp_layout_need_nothing],
+    AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+]]],
+[[[
+       uint64_t i0;
+       uint64_t i1;
+       uint8_t c[8];
+       double d;
+
+       d = 8.642135e130;
+       memcpy ((void *) &i0, (void *) &d, 8);
+
+       i1 = i0;
+       memcpy ((void *) c, (void *) &i1, 8);
+
+       if ((c[0] == 0x2f) && (c[1] == 0x25)
+                       && (c[2] == 0xc0) && (c[3] == 0xc7)
+                       && (c[4] == 0x43) && (c[5] == 0x2b)
+                       && (c[6] == 0x1f) && (c[7] == 0x5b))
+               return (0);
+       else
+               return (1);
+]]]
+      )],
+      [c_cv_fp_layout_need_nothing="yes"],
+      [c_cv_fp_layout_need_nothing="no"]
+    )
+  )
+  if test "x$c_cv_fp_layout_need_nothing" = "xyes"; then
+    fp_layout_type="nothing"
+  fi
+fi
+if test "x$fp_layout_type" = "xunknown"; then
+  AC_CACHE_CHECK([if endianflip converts to x86 representation],
+    [c_cv_fp_layout_need_endianflip],
+    AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+#define endianflip(A) ((((uint64_t)(A) & 0xff00000000000000LL) >> 56) | \
+                       (((uint64_t)(A) & 0x00ff000000000000LL) >> 40) | \
+                       (((uint64_t)(A) & 0x0000ff0000000000LL) >> 24) | \
+                       (((uint64_t)(A) & 0x000000ff00000000LL) >> 8)  | \
+                       (((uint64_t)(A) & 0x00000000ff000000LL) << 8)  | \
+                       (((uint64_t)(A) & 0x0000000000ff0000LL) << 24) | \
+                       (((uint64_t)(A) & 0x000000000000ff00LL) << 40) | \
+                       (((uint64_t)(A) & 0x00000000000000ffLL) << 56))
+]]],
+[[[
+       uint64_t i0;
+       uint64_t i1;
+       uint8_t c[8];
+       double d;
+
+       d = 8.642135e130;
+       memcpy ((void *) &i0, (void *) &d, 8);
+
+       i1 = endianflip (i0);
+       memcpy ((void *) c, (void *) &i1, 8);
+
+       if ((c[0] == 0x2f) && (c[1] == 0x25)
+                       && (c[2] == 0xc0) && (c[3] == 0xc7)
+                       && (c[4] == 0x43) && (c[5] == 0x2b)
+                       && (c[6] == 0x1f) && (c[7] == 0x5b))
+               return (0);
+       else
+               return (1);
+]]]
+      )],
+      [c_cv_fp_layout_need_endianflip="yes"],
+      [c_cv_fp_layout_need_endianflip="no"]
+    )
+  )
+  if test "x$c_cv_fp_layout_need_endianflip" = "xyes"; then
+    fp_layout_type="endianflip"
+  fi
+fi
+if test "x$fp_layout_type" = "xunknown"; then
+  AC_CACHE_CHECK([if intswap converts to x86 representation],
+    [c_cv_fp_layout_need_intswap],
+    AC_RUN_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+#define intswap(A)    ((((uint64_t)(A) & 0xffffffff00000000LL) >> 32) | \
+                       (((uint64_t)(A) & 0x00000000ffffffffLL) << 32))
+]]],
+[[[
+       uint64_t i0;
+       uint64_t i1;
+       uint8_t c[8];
+       double d;
+
+       d = 8.642135e130;
+       memcpy ((void *) &i0, (void *) &d, 8);
+
+       i1 = intswap (i0);
+       memcpy ((void *) c, (void *) &i1, 8);
+
+       if ((c[0] == 0x2f) && (c[1] == 0x25)
+                       && (c[2] == 0xc0) && (c[3] == 0xc7)
+                       && (c[4] == 0x43) && (c[5] == 0x2b)
+                       && (c[6] == 0x1f) && (c[7] == 0x5b))
+               return (0);
+       else
+               return (1);
+]]]
+      )],
+      [c_cv_fp_layout_need_intswap="yes"],
+      [c_cv_fp_layout_need_intswap="no"]
+    )
+  )
+  if test "x$c_cv_fp_layout_need_intswap" = "xyes"; then
+    fp_layout_type="intswap"
+  fi
+fi
+
+if test "x$fp_layout_type" = "xnothing"; then
+  AC_DEFINE(FP_LAYOUT_NEED_NOTHING, 1,
+  [Define if doubles are stored in x86 representation.])
+else if test "x$fp_layout_type" = "xendianflip"; then
+  AC_DEFINE(FP_LAYOUT_NEED_ENDIANFLIP, 1,
+  [Define if endianflip is needed to convert to x86 representation.])
+else if test "x$fp_layout_type" = "xintswap"; then
+  AC_DEFINE(FP_LAYOUT_NEED_INTSWAP, 1,
+  [Define if intswap is needed to convert to x86 representation.])
+else
+  AC_MSG_ERROR([Didn't find out how doubles are stored in memory. Sorry.])
+fi; fi; fi
+
+# --with-useragent {{{
+AC_ARG_WITH(useragent, [AS_HELP_STRING([--with-useragent@<:@=AGENT@:>@], [User agent to use on http requests])],
+[
+    if test "x$withval" != "xno" && test "x$withval" != "xyes"
+    then
+        AC_DEFINE_UNQUOTED(COLLECTD_USERAGENT, ["$withval"], [User agent for http requests])
+    fi
+])
+
+# }}}
+
+have_getfsstat="no"
+AC_CHECK_FUNCS(getfsstat, [have_getfsstat="yes"])
+have_getvfsstat="no"
+AC_CHECK_FUNCS(getvfsstat, [have_getvfsstat="yes"])
+have_listmntent="no"
+AC_CHECK_FUNCS(listmntent, [have_listmntent="yes"])
+
+have_getmntent="no"
+AC_CHECK_FUNCS(getmntent, [have_getmntent="c"])
+if test "x$have_getmntent" = "xno"; then
+       AC_CHECK_LIB(sun, getmntent, [have_getmntent="sun"])
+fi
+if test "x$have_getmntent" = "xno"; then
+       AC_CHECK_LIB(seq, getmntent, [have_getmntent="seq"])
+fi
+if test "x$have_getmntent" = "xno"; then
+       AC_CHECK_LIB(gen, getmntent, [have_getmntent="gen"])
+fi
+
+if test "x$have_getmntent" = "xc"; then
+       AC_CACHE_CHECK([whether getmntent takes one argument],
+               [c_cv_have_one_getmntent],
+               AC_COMPILE_IFELSE(
+                       [AC_LANG_PROGRAM(
+[[[
+#include "$srcdir/src/utils_mount.h"
+]]],
+[[[
+FILE *fh;
+struct mntent *me;
+fh = setmntent ("/etc/mtab", "r");
+me = getmntent (fh);
+return(me->mnt_passno);
+]]]
+                       )],
+                       [c_cv_have_one_getmntent="yes"],
+                       [c_cv_have_one_getmntent="no"]
+               )
+       )
+       AC_CACHE_CHECK([whether getmntent takes two arguments],
+               [c_cv_have_two_getmntent],
+               AC_COMPILE_IFELSE(
+                       [AC_LANG_PROGRAM(
+[[[
+#include "$srcdir/src/utils_mount.h"
+]]],
+[[[
+                                FILE *fh;
+                                struct mnttab mt;
+                                int status;
+                                fh = fopen ("/etc/mnttab", "r");
+                                status = getmntent (fh, &mt);
+                                return(status);
+]]]
+                       )],
+                       [c_cv_have_two_getmntent="yes"],
+                       [c_cv_have_two_getmntent="no"]
+               )
+       )
+fi
+
+# Check for different versions of `getmntent' here..
+
+if test "x$have_getmntent" = "xc"; then
+       if test "x$c_cv_have_one_getmntent" = "xyes"; then
+               AC_DEFINE(HAVE_ONE_GETMNTENT, 1,
+                         [Define if the function getmntent exists and takes one argument.])
+       fi
+       if test "x$c_cv_have_two_getmntent" = "xyes"; then
+               AC_DEFINE(HAVE_TWO_GETMNTENT, 1,
+                         [Define if the function getmntent exists and takes two arguments.])
+       fi
+fi
+if test "x$have_getmntent" = "xsun"; then
+       AC_DEFINE(HAVE_SUN_GETMNTENT, 1,
+                 [Define if the function getmntent exists. It's the version from libsun.])
+fi
+if test "x$have_getmntent" = "xseq"; then
+       AC_DEFINE(HAVE_SEQ_GETMNTENT, 1,
+                 [Define if the function getmntent exists. It's the version from libseq.])
+fi
+if test "x$have_getmntent" = "xgen"; then
+       AC_DEFINE(HAVE_GEN_GETMNTENT, 1,
+                 [Define if the function getmntent exists. It's the version from libgen.])
+fi
+
+# Check for htonll
+AC_CACHE_CHECK([if have htonll defined],
+                  [c_cv_have_htonll],
+                  AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <sys/types.h>
+#include <netinet/in.h>
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+]]],
+[[[
+          return htonll(0);
+]]]
+    )],
+    [c_cv_have_htonll="yes"],
+    [c_cv_have_htonll="no"]
+  )
+)
+if test "x$c_cv_have_htonll" = "xyes"
+then
+    AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.])
+fi
+
+# Check for structures
+AC_CHECK_MEMBERS([struct if_data.ifi_ibytes, struct if_data.ifi_opackets, struct if_data.ifi_ierrors],
+       [AC_DEFINE(HAVE_STRUCT_IF_DATA, 1, [Define if struct if_data exists and is usable.])],
+       [],
+       [
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <net/if.h>
+       ])
+AC_CHECK_MEMBERS([struct net_device_stats.rx_bytes, struct net_device_stats.tx_packets, struct net_device_stats.rx_errors],
+       [AC_DEFINE(HAVE_STRUCT_NET_DEVICE_STATS, 1, [Define if struct net_device_stats exists and is usable.])],
+       [],
+       [
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <linux/if.h>
+       #include <linux/netdevice.h>
+       ])
+AC_CHECK_MEMBERS([struct inet_diag_req.id, struct inet_diag_req.idiag_states],
+       [AC_DEFINE(HAVE_STRUCT_LINUX_INET_DIAG_REQ, 1, [Define if struct inet_diag_req exists and is usable.])],
+       [],
+       [
+       #include <linux/inet_diag.h>
+       ])
+
+
+AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [],
+       [],
+       [
+       #include <netinet/in.h>
+       #include <net/if.h>
+       ])
+
+AC_CHECK_MEMBERS([struct kinfo_proc.ki_pid, struct kinfo_proc.ki_rssize, struct kinfo_proc.ki_rusage],
+       [
+               AC_DEFINE(HAVE_STRUCT_KINFO_PROC_FREEBSD, 1,
+                       [Define if struct kinfo_proc exists in the FreeBSD variant.])
+               have_struct_kinfo_proc_freebsd="yes"
+       ],
+       [
+               have_struct_kinfo_proc_freebsd="no"
+       ],
+       [
+#include <kvm.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+       ])
+
+AC_CHECK_MEMBERS([struct kinfo_proc.p_pid, struct kinfo_proc.p_vm_rssize],
+       [
+               AC_DEFINE(HAVE_STRUCT_KINFO_PROC_OPENBSD, 1,
+                       [Define if struct kinfo_proc exists in the OpenBSD variant.])
+               have_struct_kinfo_proc_openbsd="yes"
+       ],
+       [
+               have_struct_kinfo_proc_openbsd="no"
+       ],
+       [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <kvm.h>
+       ])
+
+AC_CHECK_MEMBERS([struct udphdr.uh_dport, struct udphdr.uh_sport], [], [],
+[#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+#if HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+])
+AC_CHECK_MEMBERS([struct udphdr.dest, struct udphdr.source], [], [],
+[#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+#if HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+])
+
+AC_CHECK_MEMBERS([kstat_io_t.nwritten, kstat_io_t.writes, kstat_io_t.nwrites, kstat_io_t.wtime],
+       [],
+       [],
+       [
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+       ])
+
+#
+# Checks for libraries begin here
+#
+
+with_libresolv="yes"
+AC_CHECK_LIB(resolv, res_search,
+[
+       AC_DEFINE(HAVE_LIBRESOLV, 1, [Define to 1 if you have the 'resolv' library (-lresolv).])
+],
+[with_libresolv="no"])
+AM_CONDITIONAL(BUILD_WITH_LIBRESOLV, test "x$with_libresolv" = "xyes")
+
+dnl Check for HAL (hardware abstraction library)
+with_libhal="yes"
+AC_CHECK_LIB(hal,libhal_device_property_exists,
+            [AC_DEFINE(HAVE_LIBHAL, 1, [Define to 1 if you have 'hal' library])],
+            [with_libhal="no"])
+if test "x$with_libhal" = "xyes"; then
+       if test "x$PKG_CONFIG" != "x"; then
+               BUILD_WITH_LIBHAL_CFLAGS="`$PKG_CONFIG --cflags hal`"
+               BUILD_WITH_LIBHAL_LIBS="`$PKG_CONFIG --libs hal`"
+               AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS)
+               AC_SUBST(BUILD_WITH_LIBHAL_LIBS)
+       fi
+fi
+
+m4_divert_once([HELP_WITH], [
+collectd additional packages:])
+
+if test "x$ac_system" = "xAIX"
+then
+       with_perfstat="yes"
+       with_procinfo="yes"
+else
+       with_perfstat="no (AIX only)"
+       with_procinfo="no (AIX only)"
+fi
+
+if test "x$with_perfstat" = "xyes"
+then
+       AC_CHECK_LIB(perfstat, perfstat_reset, [with_perfstat="yes"], [with_perfstat="no (perfstat not found)"], [])
+#      AC_CHECK_HEADERS(sys/protosw.h libperfstat.h,, [with_perfstat="no (perfstat not found)"])
+fi
+if test "x$with_perfstat" = "xyes"
+then
+        AC_DEFINE(HAVE_PERFSTAT, 1, [Define to 1 if you have the 'perfstat' library (-lperfstat)])
+        # struct members pertaining to donation have been added to libperfstat somewhere between AIX5.3ML5 and AIX5.3ML9
+        AC_CHECK_MEMBER([perfstat_partition_type_t.b.donate_enabled], [], [], [[#include <libperfstat.h]])
+        if test "x$av_cv_member_perfstat_partition_type_t_b_donate_enabled" = "xyes"
+        then
+               AC_DEFINE(PERFSTAT_SUPPORTS_DONATION, 1, [Define to 1 if your version of the 'perfstat' library supports donation])
+        fi
+fi
+AM_CONDITIONAL(BUILD_WITH_PERFSTAT, test "x$with_perfstat" = "xyes")
+
+# Processes plugin under AIX.
+if test "x$with_procinfo" = "xyes"
+then
+       AC_CHECK_HEADERS(procinfo.h,, [with_procinfo="no (procinfo.h not found)"])
+fi
+if test "x$with_procinfo" = "xyes"
+then
+        AC_DEFINE(HAVE_PROCINFO_H, 1, [Define to 1 if you have the procinfo.h])
+fi
+
+if test "x$ac_system" = "xSolaris"
+then
+       with_kstat="yes"
+       with_devinfo="yes"
+else
+       with_kstat="no (Solaris only)"
+       with_devinfo="no (Solaris only)"
+fi
+
+if test "x$with_kstat" = "xyes"
+then
+       AC_CHECK_LIB(kstat, kstat_open, [with_kstat="yes"], [with_kstat="no (libkstat not found)"], [])
+fi
+if test "x$with_kstat" = "xyes"
+then
+       AC_CHECK_LIB(devinfo, di_init, [with_devinfo="yes"], [with_devinfo="no (not found)"], [])
+       AC_CHECK_HEADERS(kstat.h,, [with_kstat="no (kstat.h not found)"])
+fi
+if test "x$with_kstat" = "xyes"
+then
+       AC_DEFINE(HAVE_LIBKSTAT, 1,
+                 [Define to 1 if you have the 'kstat' library (-lkstat)])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKSTAT, test "x$with_kstat" = "xyes")
+AM_CONDITIONAL(BUILD_WITH_LIBDEVINFO, test "x$with_devinfo" = "xyes")
+
+with_libiokit="no"
+if test "x$ac_system" = "xDarwin"
+then
+       with_libiokit="yes"
+else
+       with_libiokit="no"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes")
+
+with_libkvm="no"
+AC_CHECK_LIB(kvm, kvm_getprocs, [with_kvm_getprocs="yes"], [with_kvm_getprocs="no"])
+if test "x$with_kvm_getprocs" = "xyes"
+then
+       AC_DEFINE(HAVE_LIBKVM_GETPROCS, 1,
+                 [Define to 1 if you have the 'kvm' library with the 'kvm_getprocs' symbol (-lkvm)])
+       with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETPROCS, test "x$with_kvm_getprocs" = "xyes")
+
+AC_CHECK_LIB(kvm, kvm_getswapinfo, [with_kvm_getswapinfo="yes"], [with_kvm_getswapinfo="no"])
+if test "x$with_kvm_getswapinfo" = "xyes"
+then
+       AC_DEFINE(HAVE_LIBKVM_GETSWAPINFO, 1,
+                 [Define to 1 if you have the 'kvm' library with the 'kvm_getswapinfo' symbol (-lkvm)])
+       with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_GETSWAPINFO, test "x$with_kvm_getswapinfo" = "xyes")
+
+AC_CHECK_LIB(kvm, kvm_nlist, [with_kvm_nlist="yes"], [with_kvm_nlist="no"])
+if test "x$with_kvm_nlist" = "xyes"
+then
+       AC_CHECK_HEADERS(bsd/nlist.h nlist.h)
+       AC_DEFINE(HAVE_LIBKVM_NLIST, 1,
+                 [Define to 1 if you have the 'kvm' library with the 'kvm_nlist' symbol (-lkvm)])
+       with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_NLIST, test "x$with_kvm_nlist" = "xyes")
+
+AC_CHECK_LIB(kvm, kvm_openfiles, [with_kvm_openfiles="yes"], [with_kvm_openfiles="no"])
+if test "x$with_kvm_openfiles" = "xyes"
+then
+       AC_DEFINE(HAVE_LIBKVM_NLIST, 1,
+                 [Define to 1 if you have the 'kvm' library with the 'kvm_openfiles' symbol (-lkvm)])
+       with_libkvm="yes"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBKVM_OPENFILES, test "x$with_kvm_openfiles" = "xyes")
+
+# --with-libaquaero5 {{{
+AC_ARG_WITH(libaquaero5, [AS_HELP_STRING([--with-libaquaero5@<:@=PREFIX@:>@], [Path to aquatools-ng source code.])],
+[
+ if test "x$withval" = "xyes"
+ then
+        with_libaquaero5="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libaquaero5="no"
+ else
+        with_libaquaero5="yes"
+        LIBAQUAERO5_CFLAGS="$LIBAQUAERO5_CFLAGS -I$withval/src"
+        LIBAQUAERO5_LDFLAGS="$LIBAQUAERO5_LDFLAGS -L$withval/obj"
+ fi; fi
+],
+[with_libaquaero5="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBAQUAERO5_CFLAGS"
+LDFLAGS="$LDFLAGS $LIBAQUAERO5_LDFLAGS"
+
+if test "x$with_libaquaero5" = "xyes"
+then
+       if test "x$LIBAQUAERO5_CFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libaquaero5 CPPFLAGS: $LIBAQUAERO5_CFLAGS])
+       fi
+       AC_CHECK_HEADERS(libaquaero5.h,
+       [with_libaquaero5="yes"],
+       [with_libaquaero5="no (libaquaero5.h not found)"])
+fi
+if test "x$with_libaquaero5" = "xyes"
+then
+       if test "x$LIBAQUAERO5_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libaquaero5 LDFLAGS: $LIBAQUAERO5_LDFLAGS])
+       fi
+       AC_CHECK_LIB(aquaero5, libaquaero5_poll,
+       [with_libaquaero5="yes"],
+       [with_libaquaero5="no (symbol 'libaquaero5_poll' not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libaquaero5" = "xyes"
+then
+       BUILD_WITH_LIBAQUAERO5_CFLAGS="$LIBAQUAERO5_CFLAGS"
+       BUILD_WITH_LIBAQUAERO5_LDFLAGS="$LIBAQUAERO5_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBAQUAERO5_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBAQUAERO5_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBAQUAERO5, test "x$with_libaquaero5" = "xyes")
+# }}}
+
+# --with-libhiredis {{{
+AC_ARG_WITH(libhiredis, [AS_HELP_STRING([--with-libhiredis@<:@=PREFIX@:>@],
+      [Path to libhiredis.])],
+[
+ if test "x$withval" = "xyes"
+ then
+        with_libhiredis="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libhiredis="no"
+ else
+        with_libhiredis="yes"
+        LIBHIREDIS_CPPFLAGS="$LIBHIREDIS_CPPFLAGS -I$withval/include"
+        LIBHIREDIS_LDFLAGS="$LIBHIREDIS_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_libhiredis="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBHIREDIS_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBHIREDIS_LDFLAGS"
+
+if test "x$with_libhiredis" = "xyes"
+then
+       if test "x$LIBHIREDIS_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libhiredis CPPFLAGS: $LIBHIREDIS_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(hiredis/hiredis.h,
+       [with_libhiredis="yes"],
+       [with_libhiredis="no (hiredis.h not found)"])
+fi
+if test "x$with_libhiredis" = "xyes"
+then
+       if test "x$LIBHIREDIS_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libhiredis LDFLAGS: $LIBHIREDIS_LDFLAGS])
+       fi
+       AC_CHECK_LIB(hiredis, redisCommand,
+       [with_libhiredis="yes"],
+       [with_libhiredis="no (symbol 'redisCommand' not found)"])
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libhiredis" = "xyes"
+then
+       BUILD_WITH_LIBHIREDIS_CPPFLAGS="$LIBHIREDIS_CPPFLAGS"
+       BUILD_WITH_LIBHIREDIS_LDFLAGS="$LIBHIREDIS_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBHIREDIS_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBHIREDIS, test "x$with_libhiredis" = "xyes")
+# }}}
+
+# --with-libcurl {{{
+with_curl_config="curl-config"
+with_curl_cflags=""
+with_curl_libs=""
+AC_ARG_WITH(libcurl, [AS_HELP_STRING([--with-libcurl@<:@=PREFIX@:>@], [Path to libcurl.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libcurl="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libcurl="yes"
+       else
+               if test -f "$withval" && test -x "$withval"
+               then
+                       with_curl_config="$withval"
+                       with_libcurl="yes"
+               else if test -x "$withval/bin/curl-config"
+               then
+                       with_curl_config="$withval/bin/curl-config"
+                       with_libcurl="yes"
+               fi; fi
+               with_libcurl="yes"
+       fi; fi
+],
+[
+       with_libcurl="yes"
+])
+if test "x$with_libcurl" = "xyes"
+then
+       with_curl_cflags=`$with_curl_config --cflags 2>/dev/null`
+       curl_config_status=$?
+
+       if test $curl_config_status -ne 0
+       then
+               with_libcurl="no ($with_curl_config failed)"
+       else
+               SAVE_CPPFLAGS="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $with_curl_cflags"
+
+               AC_CHECK_HEADERS(curl/curl.h, [], [with_libcurl="no (curl/curl.h not found)"], [])
+
+               CPPFLAGS="$SAVE_CPPFLAGS"
+       fi
+fi
+if test "x$with_libcurl" = "xyes"
+then
+       with_curl_libs=`$with_curl_config --libs 2>/dev/null`
+       curl_config_status=$?
+
+       if test $curl_config_status -ne 0
+       then
+               with_libcurl="no ($with_curl_config failed)"
+       else
+               AC_CHECK_LIB(curl, curl_easy_init,
+                [with_libcurl="yes"],
+                [with_libcurl="no (symbol 'curl_easy_init' not found)"],
+                [$with_curl_libs])
+               AC_CHECK_DECL(CURLOPT_USERNAME,
+                [have_curlopt_username="yes"],
+                [have_curlopt_username="no"],
+                [[#include <curl/curl.h>]])
+               AC_CHECK_DECL(CURLOPT_TIMEOUT_MS,
+                [have_curlopt_timeout="yes"],
+                [have_curlopt_timeout="no"],
+                [[#include <curl/curl.h>]])
+       fi
+fi
+if test "x$with_libcurl" = "xyes"
+then
+       BUILD_WITH_LIBCURL_CFLAGS="$with_curl_cflags"
+       BUILD_WITH_LIBCURL_LIBS="$with_curl_libs"
+       AC_SUBST(BUILD_WITH_LIBCURL_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBCURL_LIBS)
+
+       if test "x$have_curlopt_username" = "xyes"
+       then
+               AC_DEFINE(HAVE_CURLOPT_USERNAME, 1, [Define if libcurl supports CURLOPT_USERNAME option.])
+       fi
+
+       if test "x$have_curlopt_timeout" = "xyes"
+       then
+               AC_DEFINE(HAVE_CURLOPT_TIMEOUT_MS, 1, [Define if libcurl supports CURLOPT_TIMEOUT_MS option.])
+       fi
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
+# }}}
+
+# --with-libdbi {{{
+with_libdbi_cppflags=""
+with_libdbi_ldflags=""
+AC_ARG_WITH(libdbi, [AS_HELP_STRING([--with-libdbi@<:@=PREFIX@:>@], [Path to libdbi.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libdbi_cppflags="-I$withval/include"
+               with_libdbi_ldflags="-L$withval/lib"
+               with_libdbi="yes"
+       else
+               with_libdbi="$withval"
+       fi
+],
+[
+       with_libdbi="yes"
+])
+if test "x$with_libdbi" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags"
+
+       AC_CHECK_HEADERS(dbi/dbi.h, [with_libdbi="yes"], [with_libdbi="no (dbi/dbi.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libdbi" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libdbi_cppflags"
+       LDFLAGS="$LDFLAGS $with_libdbi_ldflags"
+
+       AC_CHECK_LIB(dbi, dbi_initialize, [with_libdbi="yes"], [with_libdbi="no (Symbol 'dbi_initialize' not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libdbi" = "xyes"
+then
+       BUILD_WITH_LIBDBI_CPPFLAGS="$with_libdbi_cppflags"
+       BUILD_WITH_LIBDBI_LDFLAGS="$with_libdbi_ldflags"
+       BUILD_WITH_LIBDBI_LIBS="-ldbi"
+       AC_SUBST(BUILD_WITH_LIBDBI_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBDBI_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBDBI_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBDBI, test "x$with_libdbi" = "xyes")
+# }}}
+
+# --with-libesmtp {{{
+AC_ARG_WITH(libesmtp, [AS_HELP_STRING([--with-libesmtp@<:@=PREFIX@:>@], [Path to libesmtp.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include -D_THREAD_SAFE"
+               with_libesmtp="yes"
+       else
+               with_libesmtp="$withval"
+       fi
+],
+[
+       with_libesmtp="yes"
+])
+if test "x$with_libesmtp" = "xyes"
+then
+       AC_CHECK_LIB(esmtp, smtp_create_session,
+       [
+               AC_DEFINE(HAVE_LIBESMTP, 1, [Define to 1 if you have the esmtp library (-lesmtp).])
+       ], [with_libesmtp="no (libesmtp not found)"])
+fi
+if test "x$with_libesmtp" = "xyes"
+then
+       AC_CHECK_HEADERS(libesmtp.h,
+       [
+               AC_DEFINE(HAVE_LIBESMTP_H, 1, [Define to 1 if you have the <libesmtp.h> header file.])
+       ], [with_libesmtp="no (libesmtp.h not found)"])
+fi
+if test "x$with_libesmtp" = "xyes"
+then
+       collect_libesmtp=1
+else
+       collect_libesmtp=0
+fi
+AC_DEFINE_UNQUOTED(COLLECT_LIBESMTP, [$collect_libesmtp],
+       [Wether or not to use the esmtp library])
+AM_CONDITIONAL(BUILD_WITH_LIBESMTP, test "x$with_libesmtp" = "xyes")
+# }}}
+
+# --with-libganglia {{{
+AC_ARG_WITH(libganglia, [AS_HELP_STRING([--with-libganglia@<:@=PREFIX@:>@], [Path to libganglia.])],
+[
+ if test -f "$withval" && test -x "$withval"
+ then
+        with_libganglia_config="$withval"
+        with_libganglia="yes"
+ else if test -f "$withval/bin/ganglia-config" && test -x "$withval/bin/ganglia-config"
+ then
+        with_libganglia_config="$withval/bin/ganglia-config"
+        with_libganglia="yes"
+ else if test -d "$withval"
+ then
+        GANGLIA_CPPFLAGS="-I$withval/include"
+        GANGLIA_LDFLAGS="-L$withval/lib"
+        with_libganglia="yes"
+ else
+        with_libganglia_config="ganglia-config"
+        with_libganglia="$withval"
+ fi; fi; fi
+],
+[
+ with_libganglia_config="ganglia-config"
+ with_libganglia="yes"
+])
+
+if test "x$with_libganglia" = "xyes" && test "x$with_libganglia_config" != "x"
+then
+       if test "x$GANGLIA_CPPFLAGS" = "x"
+       then
+               GANGLIA_CPPFLAGS=`"$with_libganglia_config" --cflags 2>/dev/null`
+       fi
+
+       if test "x$GANGLIA_LDFLAGS" = "x"
+       then
+               GANGLIA_LDFLAGS=`"$with_libganglia_config" --ldflags 2>/dev/null`
+       fi
+
+       if test "x$GANGLIA_LIBS" = "x"
+       then
+               GANGLIA_LIBS=`"$with_libganglia_config" --libs 2>/dev/null`
+       fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $GANGLIA_CPPFLAGS"
+LDFLAGS="$LDFLAGS $GANGLIA_LDFLAGS"
+
+if test "x$with_libganglia" = "xyes"
+then
+       AC_CHECK_HEADERS(gm_protocol.h,
+       [
+               AC_DEFINE(HAVE_GM_PROTOCOL_H, 1,
+                         [Define to 1 if you have the <gm_protocol.h> header file.])
+       ], [with_libganglia="no (gm_protocol.h not found)"])
+fi
+
+if test "x$with_libganglia" = "xyes"
+then
+       AC_CHECK_LIB(ganglia, xdr_Ganglia_value_msg,
+       [
+               AC_DEFINE(HAVE_LIBGANGLIA, 1,
+                         [Define to 1 if you have the ganglia library (-lganglia).])
+       ], [with_libganglia="no (symbol xdr_Ganglia_value_msg not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+AC_SUBST(GANGLIA_CPPFLAGS)
+AC_SUBST(GANGLIA_LDFLAGS)
+AC_SUBST(GANGLIA_LIBS)
+AM_CONDITIONAL(BUILD_WITH_LIBGANGLIA, test "x$with_libganglia" = "xyes")
+# }}}
+
+# --with-libgcrypt {{{
+GCRYPT_CPPFLAGS="$GCRYPT_CPPFLAGS"
+GCRYPT_LDFLAGS="$GCRYPT_LDFLAGS"
+GCRYPT_LIBS="$GCRYPT_LIBS"
+AC_ARG_WITH(libgcrypt, [AS_HELP_STRING([--with-libgcrypt@<:@=PREFIX@:>@], [Path to libgcrypt.])],
+[
+ if test -f "$withval" && test -x "$withval"
+ then
+        with_libgcrypt_config="$withval"
+        with_libgcrypt="yes"
+ else if test -f "$withval/bin/gcrypt-config" && test -x "$withval/bin/gcrypt-config"
+ then
+        with_libgcrypt_config="$withval/bin/gcrypt-config"
+        with_libgcrypt="yes"
+ else if test -d "$withval"
+ then
+        GCRYPT_CPPFLAGS="$GCRYPT_CPPFLAGS -I$withval/include"
+        GCRYPT_LDFLAGS="$GCRYPT_LDFLAGS -L$withval/lib"
+        with_libgcrypt="yes"
+ else
+        with_libgcrypt_config="gcrypt-config"
+        with_libgcrypt="$withval"
+ fi; fi; fi
+],
+[
+ with_libgcrypt_config="libgcrypt-config"
+ with_libgcrypt="yes"
+])
+
+if test "x$with_libgcrypt" = "xyes" && test "x$with_libgcrypt_config" != "x"
+then
+       if test "x$GCRYPT_CPPFLAGS" = "x"
+       then
+               GCRYPT_CPPFLAGS=`"$with_libgcrypt_config" --cflags 2>/dev/null`
+       fi
+
+       if test "x$GCRYPT_LDFLAGS" = "x"
+       then
+               gcrypt_exec_prefix=`"$with_libgcrypt_config" --exec-prefix 2>/dev/null`
+               GCRYPT_LDFLAGS="-L$gcrypt_exec_prefix/lib"
+       fi
+
+       if test "x$GCRYPT_LIBS" = "x"
+       then
+               GCRYPT_LIBS=`"$with_libgcrypt_config" --libs 2>/dev/null`
+       fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $GCRYPT_CPPFLAGS"
+LDFLAGS="$LDFLAGS $GCRYPT_LDFLAGS"
+
+if test "x$with_libgcrypt" = "xyes"
+then
+       if test "x$GCRYPT_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([gcrypt CPPFLAGS: $GCRYPT_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(gcrypt.h,
+               [with_libgcrypt="yes"],
+               [with_libgcrypt="no (gcrypt.h not found)"])
+fi
+
+if test "x$with_libgcrypt" = "xyes"
+then
+       if test "x$GCRYPT_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([gcrypt LDFLAGS: $GCRYPT_LDFLAGS])
+       fi
+       AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer,
+               [with_libgcrypt="yes"],
+               [with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"])
+
+       if test "$with_libgcrypt" != "no"; then
+               m4_ifdef([AM_PATH_LIBGCRYPT],[AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")])
+               GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
+               GCRYPT_LIBS="$LIBGCRYPT_LIBS"
+       fi
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libgcrypt" = "xyes"
+then
+       AC_DEFINE(HAVE_LIBGCRYPT, 1, [Define to 1 if you have the gcrypt library (-lgcrypt).])
+fi
+
+AC_SUBST(GCRYPT_CPPFLAGS)
+AC_SUBST(GCRYPT_LDFLAGS)
+AC_SUBST(GCRYPT_LIBS)
+AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, test "x$with_libgcrypt" = "xyes")
+# }}}
+
+# --with-libiptc {{{
+AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
+[
+       if test "x$withval" = "xyes"
+       then
+               with_libiptc="pkgconfig"
+       else if test "x$withval" = "xno"
+       then
+               with_libiptc="no"
+       else
+               with_libiptc="yes"
+               with_libiptc_cflags="-I$withval/include"
+               with_libiptc_libs="-L$withval/lib"
+       fi; fi
+],
+[
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libiptc="pkgconfig"
+       else
+               with_libiptc="no (Linux only)"
+       fi
+])
+
+if test "x$with_libiptc" = "xpkgconfig" && test "x$PKG_CONFIG" = "x"
+then
+       with_libiptc="no (Don't have pkg-config)"
+fi
+
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       $PKG_CONFIG --exists 'libiptc' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libiptc="no (pkg-config doesn't know libiptc)"
+       fi
+fi
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       with_libiptc_cflags="`$PKG_CONFIG --cflags 'libiptc'`"
+       if test $? -ne 0
+       then
+               with_libiptc="no ($PKG_CONFIG failed)"
+       fi
+       with_libiptc_libs="`$PKG_CONFIG --libs 'libiptc'`"
+       if test $? -ne 0
+       then
+               with_libiptc="no ($PKG_CONFIG failed)"
+       fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $with_libiptc_cflags"
+
+# check whether the header file for libiptc is available.
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       AC_CHECK_HEADERS(libiptc/libiptc.h libiptc/libip6tc.h, ,
+                       [with_libiptc="no (header file missing)"])
+fi
+# If the header file is available, check for the required type declaractions.
+# They may be missing in old versions of libiptc. In that case, they will be
+# declared in the iptables plugin.
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       AC_CHECK_TYPES([iptc_handle_t, ip6tc_handle_t], [], [])
+fi
+# Check for the iptc_init symbol in the library.
+# This could be in iptc or ip4tc
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       SAVE_LIBS="$LIBS"
+       AC_SEARCH_LIBS(iptc_init, [iptc ip4tc],
+                       [with_libiptc="pkgconfig"],
+                       [with_libiptc="no"],
+                       [$with_libiptc_libs])
+       LIBS="$SAVE_LIBS"
+fi
+if test "x$with_libiptc" = "xpkgconfig"
+then
+       with_libiptc="yes"
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+
+AM_CONDITIONAL(BUILD_WITH_LIBIPTC, test "x$with_libiptc" = "xyes")
+if test "x$with_libiptc" = "xyes"
+then
+       BUILD_WITH_LIBIPTC_CPPFLAGS="$with_libiptc_cflags"
+       BUILD_WITH_LIBIPTC_LDFLAGS="$with_libiptc_libs"
+       AC_SUBST(BUILD_WITH_LIBIPTC_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBIPTC_LDFLAGS)
+fi
+# }}}
+
+# --with-java {{{
+with_java_home="$JAVA_HOME"
+if test "x$with_java_home" = "x"
+then
+       with_java_home="/usr/lib/jvm"
+fi
+with_java_vmtype="client"
+with_java_cflags=""
+with_java_libs=""
+JAVAC="$JAVAC"
+JAR="$JAR"
+AC_ARG_WITH(java, [AS_HELP_STRING([--with-java@<:@=PREFIX@:>@], [Path to Java home.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_java="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_java="yes"
+       else
+               with_java_home="$withval"
+               with_java="yes"
+       fi; fi
+],
+[with_java="yes"])
+if test "x$with_java" = "xyes"
+then
+       if test -d "$with_java_home"
+       then
+               AC_MSG_CHECKING([for jni.h])
+               TMPVAR=`find -L "$with_java_home" -name jni.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
+               if test "x$TMPVAR" != "x"
+               then
+                       AC_MSG_RESULT([found in $TMPVAR])
+                       JAVA_CPPFLAGS="$JAVA_CPPFLAGS -I$TMPVAR"
+               else
+                       AC_MSG_RESULT([not found])
+               fi
+
+               AC_MSG_CHECKING([for jni_md.h])
+               TMPVAR=`find -L "$with_java_home" -name jni_md.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
+               if test "x$TMPVAR" != "x"
+               then
+                       AC_MSG_RESULT([found in $TMPVAR])
+                       JAVA_CPPFLAGS="$JAVA_CPPFLAGS -I$TMPVAR"
+               else
+                       AC_MSG_RESULT([not found])
+               fi
+
+               AC_MSG_CHECKING([for libjvm.so])
+               TMPVAR=`find -L "$with_java_home" -name libjvm.so -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1`
+               if test "x$TMPVAR" != "x"
+               then
+                       AC_MSG_RESULT([found in $TMPVAR])
+                       JAVA_LDFLAGS="$JAVA_LDFLAGS -L$TMPVAR -Wl,-rpath -Wl,$TMPVAR"
+               else
+                       AC_MSG_RESULT([not found])
+               fi
+
+               if test "x$JAVAC" = "x"
+               then
+                       AC_MSG_CHECKING([for javac])
+                       TMPVAR=`find -L "$with_java_home" -name javac -type f 2>/dev/null | head -n 1`
+                       if test "x$TMPVAR" != "x"
+                       then
+                               JAVAC="$TMPVAR"
+                               AC_MSG_RESULT([$JAVAC])
+                       else
+                               AC_MSG_RESULT([not found])
+                       fi
+               fi
+               if test "x$JAR" = "x"
+               then
+                       AC_MSG_CHECKING([for jar])
+                       TMPVAR=`find -L "$with_java_home" -name jar -type f 2>/dev/null | head -n 1`
+                       if test "x$TMPVAR" != "x"
+                       then
+                               JAR="$TMPVAR"
+                               AC_MSG_RESULT([$JAR])
+                       else
+                               AC_MSG_RESULT([not found])
+                       fi
+               fi
+       else if test "x$with_java_home" != "x"
+       then
+               AC_MSG_WARN([JAVA_HOME: No such directory: $with_java_home])
+       fi; fi
+fi
+
+if test "x$JAVA_CPPFLAGS" != "x"
+then
+       AC_MSG_NOTICE([Building with JAVA_CPPFLAGS set to: $JAVA_CPPFLAGS])
+fi
+if test "x$JAVA_CFLAGS" != "x"
+then
+       AC_MSG_NOTICE([Building with JAVA_CFLAGS set to: $JAVA_CFLAGS])
+fi
+if test "x$JAVA_LDFLAGS" != "x"
+then
+       AC_MSG_NOTICE([Building with JAVA_LDFLAGS set to: $JAVA_LDFLAGS])
+fi
+if test "x$JAVAC" = "x"
+then
+       with_javac_path="$PATH"
+       if test "x$with_java_home" != "x"
+       then
+               with_javac_path="$with_java_home:with_javac_path"
+               if test -d "$with_java_home/bin"
+               then
+                       with_javac_path="$with_java_home/bin:with_javac_path"
+               fi
+       fi
+
+       AC_PATH_PROG(JAVAC, javac, [], "$with_javac_path")
+fi
+if test "x$JAVAC" = "x"
+then
+       with_java="no (javac not found)"
+fi
+if test "x$JAR" = "x"
+then
+       with_jar_path="$PATH"
+       if test "x$with_java_home" != "x"
+       then
+               with_jar_path="$with_java_home:$with_jar_path"
+               if test -d "$with_java_home/bin"
+               then
+                       with_jar_path="$with_java_home/bin:$with_jar_path"
+               fi
+       fi
+
+       AC_PATH_PROG(JAR, jar, [], "$with_jar_path")
+fi
+if test "x$JAR" = "x"
+then
+       with_java="no (jar not found)"
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_CFLAGS="$CFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $JAVA_CPPFLAGS"
+CFLAGS="$CFLAGS $JAVA_CFLAGS"
+LDFLAGS="$LDFLAGS $JAVA_LDFLAGS"
+
+if test "x$with_java" = "xyes"
+then
+       AC_CHECK_HEADERS(jni.h, [], [with_java="no (jni.h not found)"])
+fi
+if test "x$with_java" = "xyes"
+then
+       AC_CHECK_LIB(jvm, JNI_CreateJavaVM,
+       [with_java="yes"],
+       [with_java="no (libjvm not found)"],
+       [$JAVA_LIBS])
+fi
+if test "x$with_java" = "xyes"
+then
+       JAVA_LIBS="$JAVA_LIBS -ljvm"
+       AC_MSG_NOTICE([Building with JAVA_LIBS set to: $JAVA_LIBS])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+CFLAGS="$SAVE_CFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+AC_SUBST(JAVA_CPPFLAGS)
+AC_SUBST(JAVA_CFLAGS)
+AC_SUBST(JAVA_LDFLAGS)
+AC_SUBST(JAVA_LIBS)
+AM_CONDITIONAL(BUILD_WITH_JAVA, test "x$with_java" = "xyes")
+# }}}
+
+# --with-libldap {{{
+AC_ARG_WITH(libldap, [AS_HELP_STRING([--with-libldap@<:@=PREFIX@:>@], [Path to libldap.])],
+[
+ if test "x$withval" = "xyes"
+ then
+        with_libldap="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libldap="no"
+ else
+        with_libldap="yes"
+        LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS -I$withval/include"
+        LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_libldap="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBLDAP_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBLDAP_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+       if test "x$LIBLDAP_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libldap CPPFLAGS: $LIBLDAP_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(ldap.h,
+       [with_libldap="yes"],
+       [with_libldap="no ('ldap.h' not found)"])
+fi
+if test "x$with_libldap" = "xyes"
+then
+       if test "x$LIBLDAP_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libldap LDFLAGS: $LIBLDAP_LDFLAGS])
+       fi
+       AC_CHECK_LIB(ldap, ldap_initialize,
+       [with_libldap="yes"],
+       [with_libldap="no (symbol 'ldap_initialize' not found)"])
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+       BUILD_WITH_LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS"
+       BUILD_WITH_LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBLDAP_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBLDAP_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBLDAP, test "x$with_libldap" = "xyes")
+# }}}
+
+# --with-liblvm2app {{{
+with_liblvm2app_cppflags=""
+with_liblvm2app_ldflags=""
+AC_ARG_WITH(liblvm2app, [AS_HELP_STRING([--with-liblvm2app@<:@=PREFIX@:>@], [Path to liblvm2app.])],
+[
+        if test "x$withval" != "xno" && test "x$withval" != "xyes"
+        then
+                with_liblvm2app_cppflags="-I$withval/include"
+                with_liblvm2app_ldflags="-L$withval/lib"
+                with_liblvm2app="yes"
+        else
+                with_liblvm2app="$withval"
+        fi
+],
+[
+        with_liblvm2app="yes"
+])
+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"
+        AC_SUBST(BUILD_WITH_LIBLVM2APP_CPPFLAGS)
+        AC_SUBST(BUILD_WITH_LIBLVM2APP_LDFLAGS)
+        AC_SUBST(BUILD_WITH_LIBLVM2APP_LIBS)
+        AC_DEFINE(HAVE_LIBLVM2APP, 1, [Define if liblvm2app is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBLVM2APP, test "x$with_liblvm2app" = "xyes")
+# }}}
+
+# --with-libmemcached {{{
+with_libmemcached_cppflags=""
+with_libmemcached_ldflags=""
+AC_ARG_WITH(libmemcached, [AS_HELP_STRING([--with-libmemcached@<:@=PREFIX@:>@], [Path to libmemcached.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libmemcached_cppflags="-I$withval/include"
+               with_libmemcached_ldflags="-L$withval/lib"
+               with_libmemcached="yes"
+       else
+               with_libmemcached="$withval"
+       fi
+],
+[
+       with_libmemcached="yes"
+])
+if test "x$with_libmemcached" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libmemcached_cppflags"
+
+       AC_CHECK_HEADERS(libmemcached/memcached.h, [with_libmemcached="yes"], [with_libmemcached="no (libmemcached/memcached.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmemcached" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libmemcached_cppflags"
+       LDFLAGS="$LDFLAGS $with_libmemcached_ldflags"
+
+       AC_CHECK_LIB(memcached, memcached_create, [with_libmemcached="yes"], [with_libmemcached="no (Symbol 'memcached_create' not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libmemcached" = "xyes"
+then
+       BUILD_WITH_LIBMEMCACHED_CPPFLAGS="$with_libmemcached_cppflags"
+       BUILD_WITH_LIBMEMCACHED_LDFLAGS="$with_libmemcached_ldflags"
+       BUILD_WITH_LIBMEMCACHED_LIBS="-lmemcached"
+       AC_SUBST(BUILD_WITH_LIBMEMCACHED_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMEMCACHED_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMEMCACHED_LIBS)
+       AC_DEFINE(HAVE_LIBMEMCACHED, 1, [Define if libmemcached is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBMEMCACHED, test "x$with_libmemcached" = "xyes")
+# }}}
+
+# --with-libmodbus {{{
+with_libmodbus_config=""
+with_libmodbus_cflags=""
+with_libmodbus_libs=""
+AC_ARG_WITH(libmodbus, [AS_HELP_STRING([--with-libmodbus@<:@=PREFIX@:>@], [Path to the modbus library.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libmodbus="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libmodbus="use_pkgconfig"
+       else if test -d "$with_libmodbus/lib"
+       then
+               AC_MSG_NOTICE([Not checking for libmodbus: Manually configured])
+               with_libmodbus_cflags="-I$withval/include"
+               with_libmodbus_libs="-L$withval/lib -lmodbus"
+               with_libmodbus="yes"
+       fi; fi; fi
+],
+[with_libmodbus="use_pkgconfig"])
+
+# configure using pkg-config
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       if test "x$PKG_CONFIG" = "x"
+       then
+               with_libmodbus="no (Don't have pkg-config)"
+       fi
+fi
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       AC_MSG_NOTICE([Checking for libmodbus using $PKG_CONFIG])
+       $PKG_CONFIG --exists 'libmodbus' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libmodbus="no (pkg-config doesn't know libmodbus)"
+       fi
+fi
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       with_libmodbus_cflags="`$PKG_CONFIG --cflags 'libmodbus'`"
+       if test $? -ne 0
+       then
+               with_libmodbus="no ($PKG_CONFIG failed)"
+       fi
+       with_libmodbus_libs="`$PKG_CONFIG --libs 'libmodbus'`"
+       if test $? -ne 0
+       then
+               with_libmodbus="no ($PKG_CONFIG failed)"
+       fi
+fi
+if test "x$with_libmodbus" = "xuse_pkgconfig"
+then
+       with_libmodbus="yes"
+fi
+
+# with_libmodbus_cflags and with_libmodbus_libs are set up now, let's do
+# the actual checks.
+if test "x$with_libmodbus" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags"
+
+       AC_CHECK_HEADERS(modbus/modbus.h, [], [with_libmodbus="no (modbus/modbus.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libmodbus" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags"
+       LDFLAGS="$LDFLAGS $with_libmodbus_libs"
+
+       AC_CHECK_LIB(modbus, modbus_connect,
+                    [with_libmodbus="yes"],
+                    [with_libmodbus="no (symbol modbus_connect not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libmodbus" = "xyes"
+then
+       BUILD_WITH_LIBMODBUS_CFLAGS="$with_libmodbus_cflags"
+       BUILD_WITH_LIBMODBUS_LIBS="$with_libmodbus_libs"
+       AC_SUBST(BUILD_WITH_LIBMODBUS_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMODBUS_LIBS)
+fi
+# }}}
+
+# --with-libmongoc {{{
+AC_ARG_WITH(libmongoc, [AS_HELP_STRING([--with-libmongoc@<:@=PREFIX@:>@], [Path to libmongoc.])],
+[
+ if test "x$withval" = "xyes"
+ then
+        with_libmongoc="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libmongoc="no"
+ else
+        with_libmongoc="yes"
+        LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS -I$withval/include"
+        LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_libmongoc="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBMONGOC_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS"
+
+if test "x$with_libmongoc" = "xyes"
+then
+       if test "x$LIBMONGOC_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libmongoc CPPFLAGS: $LIBMONGOC_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(mongo.h,
+       [with_libmongoc="yes"],
+       [with_libmongoc="no ('mongo.h' not found)"],
+[#if HAVE_STDINT_H
+# define MONGO_HAVE_STDINT 1
+#else
+# define MONGO_USE_LONG_LONG_INT 1
+#endif
+])
+fi
+if test "x$with_libmongoc" = "xyes"
+then
+       if test "x$LIBMONGOC_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS])
+       fi
+       AC_CHECK_LIB(mongoc, mongo_run_command,
+       [with_libmongoc="yes"],
+       [with_libmongoc="no (symbol 'mongo_run_command' not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libmongoc" = "xyes"
+then
+       BUILD_WITH_LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS"
+       BUILD_WITH_LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBMONGOC_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMONGOC_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
+# }}}
+
+# --with-libmysql {{{
+with_mysql_config="mysql_config"
+with_mysql_cflags=""
+with_mysql_libs=""
+AC_ARG_WITH(libmysql, [AS_HELP_STRING([--with-libmysql@<:@=PREFIX@:>@], [Path to libmysql.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libmysql="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libmysql="yes"
+       else
+               if test -f "$withval" && test -x "$withval";
+               then
+                       with_mysql_config="$withval"
+               else if test -x "$withval/bin/mysql_config"
+               then
+                       with_mysql_config="$withval/bin/mysql_config"
+               fi; fi
+               with_libmysql="yes"
+       fi; fi
+],
+[
+       with_libmysql="yes"
+])
+if test "x$with_libmysql" = "xyes"
+then
+       with_mysql_cflags=`$with_mysql_config --cflags 2>/dev/null`
+       mysql_config_status=$?
+
+       if test $mysql_config_status -ne 0
+       then
+               with_libmysql="no ($with_mysql_config failed)"
+       else
+               SAVE_CPPFLAGS="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $with_mysql_cflags"
+
+               have_mysql_h="no"
+               have_mysql_mysql_h="no"
+               AC_CHECK_HEADERS(mysql.h, [have_mysql_h="yes"])
+
+               if test "x$have_mysql_h" = "xno"
+               then
+                       AC_CHECK_HEADERS(mysql/mysql.h, [have_mysql_mysql_h="yes"])
+               fi
+
+               if test "x$have_mysql_h$have_mysql_mysql_h" = "xnono"
+               then
+                       with_libmysql="no (mysql.h not found)"
+               fi
+
+               CPPFLAGS="$SAVE_CPPFLAGS"
+       fi
+fi
+if test "x$with_libmysql" = "xyes"
+then
+       with_mysql_libs=`$with_mysql_config --libs_r 2>/dev/null`
+       mysql_config_status=$?
+
+       if test $mysql_config_status -ne 0
+       then
+               with_libmysql="no ($with_mysql_config failed)"
+       else
+               AC_CHECK_LIB(mysqlclient, mysql_init,
+                [with_libmysql="yes"],
+                [with_libmysql="no (symbol 'mysql_init' not found)"],
+                [$with_mysql_libs])
+
+               AC_CHECK_LIB(mysqlclient, mysql_get_server_version,
+                [with_libmysql="yes"],
+                [with_libmysql="no (symbol 'mysql_get_server_version' not found)"],
+                [$with_mysql_libs])
+       fi
+fi
+if test "x$with_libmysql" = "xyes"
+then
+       BUILD_WITH_LIBMYSQL_CFLAGS="$with_mysql_cflags"
+       BUILD_WITH_LIBMYSQL_LIBS="$with_mysql_libs"
+       AC_SUBST(BUILD_WITH_LIBMYSQL_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMYSQL_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBMYSQL, test "x$with_libmysql" = "xyes")
+# }}}
+
+# --with-libmnl {{{
+with_libmnl_cflags=""
+with_libmnl_libs=""
+AC_ARG_WITH(libmnl, [AS_HELP_STRING([--with-libmnl@<:@=PREFIX@:>@], [Path to libmnl.])],
+[
+ echo "libmnl: withval = $withval"
+ if test "x$withval" = "xyes"
+ then
+        with_libmnl="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libmnl="no"
+ else
+        if test -d "$withval/include"
+        then
+                with_libmnl_cflags="-I$withval/include"
+                with_libmnl_libs="-L$withval/lib -lmnl"
+                with_libmnl="yes"
+        else
+                AC_MSG_ERROR("no such directory: $withval/include")
+        fi
+ fi; fi
+],
+[
+ if test "x$ac_system" = "xLinux"
+ then
+        with_libmnl="yes"
+ else
+        with_libmnl="no (Linux only library)"
+ fi
+])
+if test "x$PKG_CONFIG" = "x"
+then
+       with_libmnl="no (Don't have pkg-config)"
+fi
+if test "x$with_libmnl" = "xyes"
+then
+       if $PKG_CONFIG --exists libmnl 2>/dev/null; then
+         with_libmnl_cflags="$with_libmnl_ldflags `$PKG_CONFIG --cflags libmnl`"
+         with_libmnl_libs="$with_libmnl_libs `$PKG_CONFIG --libs libmnl`"
+       fi
+
+       AC_CHECK_HEADERS(libmnl.h libmnl/libmnl.h,
+       [
+        with_libmnl="yes"
+        break
+       ], [],
+[#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>])
+       AC_CHECK_HEADERS(linux/gen_stats.h linux/pkt_sched.h, [], [],
+[#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>])
+
+        AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+]],
+[[
+int retval = TCA_STATS2;
+return (retval);
+]]
+       )],
+       [AC_DEFINE([HAVE_TCA_STATS2], [1], [True if the enum-member TCA_STATS2 exists])])
+
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <stdio.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+]],
+[[
+int retval = TCA_STATS;
+return (retval);
+]]
+       )],
+       [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])])
+fi
+if test "x$with_libmnl" = "xyes"
+then
+       AC_CHECK_MEMBERS([struct rtnl_link_stats64.tx_window_errors],
+       [AC_DEFINE(HAVE_RTNL_LINK_STATS64, 1, [Define if struct rtnl_link_stats64 exists and is usable.])],
+       [],
+       [
+       #include <linux/if_link.h>
+       ])
+fi
+if test "x$with_libmnl" = "xyes"
+then
+       AC_CHECK_LIB(mnl, mnl_nlmsg_get_payload,
+                    [with_libmnl="yes"],
+                    [with_libmnl="no (symbol 'mnl_nlmsg_get_payload' not found)"],
+                    [$with_libmnl_libs])
+fi
+if test "x$with_libmnl" = "xyes"
+then
+       AC_DEFINE(HAVE_LIBMNL, 1, [Define if libmnl is present and usable.])
+       BUILD_WITH_LIBMNL_CFLAGS="$with_libmnl_cflags"
+       BUILD_WITH_LIBMNL_LIBS="$with_libmnl_libs"
+       AC_SUBST(BUILD_WITH_LIBMNL_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBMNL_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBMNL, test "x$with_libmnl" = "xyes")
+# }}}
+
+# --with-libnetapp {{{
+AC_ARG_VAR([LIBNETAPP_CPPFLAGS], [C preprocessor flags required to build with libnetapp])
+AC_ARG_VAR([LIBNETAPP_LDFLAGS],  [Linker flags required to build with libnetapp])
+AC_ARG_VAR([LIBNETAPP_LIBS],     [Other libraries required to link against libnetapp])
+LIBNETAPP_CPPFLAGS="$LIBNETAPP_CPPFLAGS"
+LIBNETAPP_LDFLAGS="$LIBNETAPP_LDFLAGS"
+LIBNETAPP_LIBS="$LIBNETAPP_LIBS"
+AC_ARG_WITH(libnetapp, [AS_HELP_STRING([--with-libnetapp@<:@=PREFIX@:>@], [Path to libnetapp.])],
+[
+ if test -d "$withval"
+ then
+        LIBNETAPP_CPPFLAGS="$LIBNETAPP_CPPFLAGS -I$withval/include"
+        LIBNETAPP_LDFLAGS="$LIBNETAPP_LDFLAGS -L$withval/lib"
+        with_libnetapp="yes"
+ else
+        with_libnetapp="$withval"
+ fi
+],
+[
+ with_libnetapp="yes"
+])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $LIBNETAPP_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBNETAPP_LDFLAGS"
+
+if test "x$with_libnetapp" = "xyes"
+then
+       if test "x$LIBNETAPP_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([netapp CPPFLAGS: $LIBNETAPP_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(netapp_api.h,
+               [with_libnetapp="yes"],
+               [with_libnetapp="no (netapp_api.h not found)"])
+fi
+
+if test "x$with_libnetapp" = "xyes"
+then
+       if test "x$LIBNETAPP_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([netapp LDFLAGS: $LIBNETAPP_LDFLAGS])
+       fi
+
+       if test "x$LIBNETAPP_LIBS" = "x"
+       then
+               LIBNETAPP_LIBS="-lpthread -lxml -ladt -lssl -lm -lcrypto -lz"
+       fi
+       AC_MSG_NOTICE([netapp LIBS: $LIBNETAPP_LIBS])
+
+       AC_CHECK_LIB(netapp, na_server_invoke_elem,
+               [with_libnetapp="yes"],
+               [with_libnetapp="no (symbol na_server_invoke_elem not found)"],
+               [$LIBNETAPP_LIBS])
+       LIBNETAPP_LIBS="-lnetapp $LIBNETAPP_LIBS"
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libnetapp" = "xyes"
+then
+       AC_DEFINE(HAVE_LIBNETAPP, 1, [Define to 1 if you have the netapp library (-lnetapp).])
+fi
+
+AC_SUBST(LIBNETAPP_CPPFLAGS)
+AC_SUBST(LIBNETAPP_LDFLAGS)
+AC_SUBST(LIBNETAPP_LIBS)
+AM_CONDITIONAL(BUILD_WITH_LIBNETAPP, test "x$with_libnetapp" = "xyes")
+# }}}
+
+# --with-libnetsnmp {{{
+with_snmp_config="net-snmp-config"
+with_snmp_cflags=""
+with_snmp_libs=""
+AC_ARG_WITH(libnetsnmp, [AS_HELP_STRING([--with-libnetsnmp@<:@=PREFIX@:>@], [Path to the Net-SNMPD library.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libnetsnmp="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libnetsnmp="yes"
+       else
+               if test -x "$withval"
+               then
+                       with_snmp_config="$withval"
+                       with_libnetsnmp="yes"
+               else
+                       with_snmp_config="$withval/bin/net-snmp-config"
+                       with_libnetsnmp="yes"
+               fi
+       fi; fi
+],
+[with_libnetsnmp="yes"])
+if test "x$with_libnetsnmp" = "xyes"
+then
+       with_snmp_cflags=`$with_snmp_config --cflags 2>/dev/null`
+       snmp_config_status=$?
+
+       if test $snmp_config_status -ne 0
+       then
+               with_libnetsnmp="no ($with_snmp_config failed)"
+       else
+               SAVE_CPPFLAGS="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $with_snmp_cflags"
+
+               AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"])
+
+               CPPFLAGS="$SAVE_CPPFLAGS"
+       fi
+fi
+if test "x$with_libnetsnmp" = "xyes"
+then
+       with_snmp_libs=`$with_snmp_config --libs 2>/dev/null`
+       snmp_config_status=$?
+
+       if test $snmp_config_status -ne 0
+       then
+               with_libnetsnmp="no ($with_snmp_config failed)"
+       else
+               AC_CHECK_LIB(netsnmp, init_snmp,
+               [with_libnetsnmp="yes"],
+               [with_libnetsnmp="no (libnetsnmp not found)"],
+               [$with_snmp_libs])
+       fi
+fi
+if test "x$with_libnetsnmp" = "xyes"
+then
+       BUILD_WITH_LIBSNMP_CFLAGS="$with_snmp_cflags"
+       BUILD_WITH_LIBSNMP_LIBS="$with_snmp_libs"
+       AC_SUBST(BUILD_WITH_LIBSNMP_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBSNMP_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBNETSNMP, test "x$with_libnetsnmp" = "xyes")
+# }}}
+
+# --with-liboconfig {{{
+with_own_liboconfig="no"
+liboconfig_LDFLAGS="$LDFLAGS"
+liboconfig_CPPFLAGS="$CPPFLAGS"
+AC_ARG_WITH(liboconfig, [AS_HELP_STRING([--with-liboconfig@<:@=PREFIX@:>@], [Path to liboconfig.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               if test -d "$withval/lib"
+               then
+                       liboconfig_LDFLAGS="$LDFLAGS -L$withval/lib"
+               fi
+               if test -d "$withval/include"
+               then
+                       liboconfig_CPPFLAGS="$CPPFLAGS -I$withval/include"
+               fi
+       fi
+       if test "x$withval" = "xno"
+       then
+               AC_MSG_ERROR("liboconfig is required")
+       fi
+],
+[
+       with_liboconfig="yes"
+])
+
+save_LDFLAGS="$LDFLAGS"
+save_CPPFLAGS="$CPPFLAGS"
+LDFLAGS="$liboconfig_LDFLAGS"
+CPPFLAGS="$liboconfig_CPPFLAGS"
+AC_CHECK_LIB(oconfig, oconfig_parse_fh,
+[
+       with_liboconfig="yes"
+       with_own_liboconfig="no"
+],
+[
+       with_liboconfig="yes"
+       with_own_liboconfig="yes"
+       LDFLAGS="$save_LDFLAGS"
+       CPPFLAGS="$save_CPPFLAGS"
+])
+
+AM_CONDITIONAL(BUILD_WITH_OWN_LIBOCONFIG, test "x$with_own_liboconfig" = "xyes")
+if test "x$with_own_liboconfig" = "xyes"
+then
+       with_liboconfig="yes (shipped version)"
+fi
+# }}}
+
+# --with-liboping {{{
+AC_ARG_WITH(liboping, [AS_HELP_STRING([--with-liboping@<:@=PREFIX@:>@], [Path to liboping.])],
+[
+ if test "x$withval" = "xyes"
+ then
+        with_liboping="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_liboping="no"
+ else
+        with_liboping="yes"
+        LIBOPING_CPPFLAGS="$LIBOPING_CPPFLAGS -I$withval/include"
+        LIBOPING_LDFLAGS="$LIBOPING_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_liboping="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBOPING_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBOPING_LDFLAGS"
+
+if test "x$with_liboping" = "xyes"
+then
+       if test "x$LIBOPING_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([liboping CPPFLAGS: $LIBOPING_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(oping.h,
+       [with_liboping="yes"],
+       [with_liboping="no (oping.h not found)"])
+fi
+if test "x$with_liboping" = "xyes"
+then
+       if test "x$LIBOPING_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([liboping LDFLAGS: $LIBOPING_LDFLAGS])
+       fi
+       AC_CHECK_LIB(oping, ping_construct,
+       [with_liboping="yes"],
+       [with_liboping="no (symbol 'ping_construct' not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_liboping" = "xyes"
+then
+       BUILD_WITH_LIBOPING_CPPFLAGS="$LIBOPING_CPPFLAGS"
+       BUILD_WITH_LIBOPING_LDFLAGS="$LIBOPING_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBOPING_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBOPING_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBOPING, test "x$with_liboping" = "xyes")
+# }}}
+
+# --with-oracle {{{
+with_oracle_cppflags=""
+with_oracle_libs=""
+AC_ARG_WITH(oracle, [AS_HELP_STRING([--with-oracle@<:@=ORACLE_HOME@:>@], [Path to Oracle.])],
+[
+       if test "x$withval" = "xyes"
+       then
+               if test "x$ORACLE_HOME" = "x"
+               then
+                       AC_MSG_WARN([Use of the Oracle library has been forced, but the environment variable ORACLE_HOME is not set.])
+               fi
+               with_oracle="yes"
+       else if test "x$withval" = "xno"
+       then
+               with_oracle="no"
+       else
+               with_oracle="yes"
+               ORACLE_HOME="$withval"
+       fi; fi
+],
+[
+       if test "x$ORACLE_HOME" = "x"
+       then
+               with_oracle="no (ORACLE_HOME is not set)"
+       else
+               with_oracle="yes"
+       fi
+])
+if test "x$ORACLE_HOME" != "x"
+then
+       with_oracle_cppflags="-I$ORACLE_HOME/rdbms/public"
+
+       if test -e "$ORACLE_HOME/lib/ldflags"
+       then
+               with_oracle_libs=`cat "$ORACLE_HOME/lib/ldflags"`
+       fi
+       #with_oracle_libs="-L$ORACLE_HOME/lib $with_oracle_libs -lclntsh"
+       with_oracle_libs="-L$ORACLE_HOME/lib -lclntsh"
+fi
+if test "x$with_oracle" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_oracle_cppflags"
+
+       AC_CHECK_HEADERS(oci.h, [with_oracle="yes"], [with_oracle="no (oci.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_oracle" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LIBS="$LIBS"
+       CPPFLAGS="$CPPFLAGS $with_oracle_cppflags"
+       LIBS="$LIBS $with_oracle_libs"
+
+       AC_CHECK_FUNC(OCIEnvCreate, [with_oracle="yes"], [with_oracle="no (Symbol 'OCIEnvCreate' not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+if test "x$with_oracle" = "xyes"
+then
+       BUILD_WITH_ORACLE_CFLAGS="$with_oracle_cppflags"
+       BUILD_WITH_ORACLE_LIBS="$with_oracle_libs"
+       AC_SUBST(BUILD_WITH_ORACLE_CFLAGS)
+       AC_SUBST(BUILD_WITH_ORACLE_LIBS)
+fi
+# }}}
+
+# --with-libowcapi {{{
+with_libowcapi_cppflags=""
+with_libowcapi_libs="-lowcapi"
+AC_ARG_WITH(libowcapi, [AS_HELP_STRING([--with-libowcapi@<:@=PREFIX@:>@], [Path to libowcapi.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libowcapi_cppflags="-I$withval/include"
+               with_libowcapi_libs="-L$withval/lib -lowcapi"
+               with_libowcapi="yes"
+       else
+               with_libowcapi="$withval"
+       fi
+],
+[
+       with_libowcapi="yes"
+])
+if test "x$with_libowcapi" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$with_libowcapi_cppflags"
+
+       AC_CHECK_HEADERS(owcapi.h, [with_libowcapi="yes"], [with_libowcapi="no (owcapi.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libowcapi" = "xyes"
+then
+       SAVE_LDFLAGS="$LDFLAGS"
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       LDFLAGS="$with_libowcapi_libs"
+       CPPFLAGS="$with_libowcapi_cppflags"
+
+       AC_CHECK_LIB(owcapi, OW_get, [with_libowcapi="yes"], [with_libowcapi="no (libowcapi not found)"])
+
+       LDFLAGS="$SAVE_LDFLAGS"
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libowcapi" = "xyes"
+then
+       BUILD_WITH_LIBOWCAPI_CPPFLAGS="$with_libowcapi_cppflags"
+       BUILD_WITH_LIBOWCAPI_LIBS="$with_libowcapi_libs"
+       AC_SUBST(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBOWCAPI_LIBS)
+fi
+# }}}
+
+# --with-libpcap {{{
+AC_ARG_WITH(libpcap, [AS_HELP_STRING([--with-libpcap@<:@=PREFIX@:>@], [Path to libpcap.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               with_libpcap="yes"
+       else
+               with_libpcap="$withval"
+       fi
+],
+[
+       with_libpcap="yes"
+])
+if test "x$with_libpcap" = "xyes"
+then
+       AC_CHECK_LIB(pcap, pcap_open_live,
+       [
+               AC_DEFINE(HAVE_LIBPCAP, 1, [Define to 1 if you have the pcap library (-lpcap).])
+       ], [with_libpcap="no (libpcap not found)"])
+fi
+if test "x$with_libpcap" = "xyes"
+then
+       AC_CHECK_HEADERS(pcap.h,,
+                        [with_libpcap="no (pcap.h not found)"])
+fi
+if test "x$with_libpcap" = "xyes"
+then
+       AC_CHECK_HEADERS(pcap-bpf.h,,
+                        [with_libpcap="no (pcap-bpf.h not found)"])
+fi
+if test "x$with_libpcap" = "xyes"
+then
+       AC_CACHE_CHECK([whether libpcap has PCAP_ERROR_IFACE_NOT_UP],
+                      [c_cv_libpcap_have_pcap_error_iface_not_up],
+                      AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <pcap.h>
+]]],
+[[[
+  int val = PCAP_ERROR_IFACE_NOT_UP;
+  return(val);
+]]]
+                      )],
+                      [c_cv_libpcap_have_pcap_error_iface_not_up="yes"],
+                      [c_cv_libpcap_have_pcap_error_iface_not_up="no"]))
+fi
+if test "x$c_cv_libpcap_have_pcap_error_iface_not_up" != "xyes"
+then
+               with_libpcap="no (pcap.h misses PCAP_ERROR_IFACE_NOT_UP)"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes")
+# }}}
+
+# --with-libperl {{{
+perl_interpreter="perl"
+AC_ARG_WITH(libperl, [AS_HELP_STRING([--with-libperl@<:@=PREFIX@:>@], [Path to libperl.])],
+[
+       if test -f "$withval" && test -x "$withval"
+       then
+               perl_interpreter="$withval"
+               with_libperl="yes"
+       else if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               perl_interpreter="$withval/bin/perl"
+               with_libperl="yes"
+       else
+               with_libperl="$withval"
+       fi; fi
+],
+[
+       with_libperl="yes"
+])
+
+AC_MSG_CHECKING([for perl])
+perl_interpreter=`which "$perl_interpreter" 2> /dev/null`
+if test -x "$perl_interpreter"
+then
+       AC_MSG_RESULT([yes ($perl_interpreter)])
+else
+       perl_interpreter=""
+       AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(PERL, "$perl_interpreter")
+
+if test "x$with_libperl" = "xyes" \
+       && test -n "$perl_interpreter"
+then
+  SAVE_CFLAGS="$CFLAGS"
+  SAVE_LIBS="$LIBS"
+dnl ARCHFLAGS="" -> disable multi -arch on OSX (see Config_heavy.pl:fetch_string)
+  PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ccopts`
+  PERL_LIBS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts`
+  CFLAGS="$CFLAGS $PERL_CFLAGS"
+  LIBS="$LIBS $PERL_LIBS"
+
+  AC_CACHE_CHECK([for libperl],
+    [c_cv_have_libperl],
+    AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[[
+#define PERL_NO_GET_CONTEXT
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+]]],
+[[[
+       dTHX;
+       load_module (PERL_LOADMOD_NOIMPORT,
+                        newSVpv ("Collectd::Plugin::FooBar", 24),
+                        Nullsv);
+]]]
+      )],
+      [c_cv_have_libperl="yes"],
+      [c_cv_have_libperl="no"]
+    )
+  )
+
+  if test "x$c_cv_have_libperl" = "xyes"
+  then
+         AC_DEFINE(HAVE_LIBPERL, 1, [Define if libperl is present and usable.])
+         AC_SUBST(PERL_CFLAGS)
+         AC_SUBST(PERL_LIBS)
+  else
+         with_libperl="no"
+  fi
+
+  CFLAGS="$SAVE_CFLAGS"
+  LIBS="$SAVE_LIBS"
+else if test -z "$perl_interpreter"; then
+  with_libperl="no (no perl interpreter found)"
+  c_cv_have_libperl="no"
+fi; fi
+AM_CONDITIONAL(BUILD_WITH_LIBPERL, test "x$with_libperl" = "xyes")
+
+if test "x$with_libperl" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LIBS="$LIBS"
+       CFLAGS="$CFLAGS $PERL_CFLAGS"
+       LIBS="$LIBS $PERL_LIBS"
+
+       AC_CACHE_CHECK([if perl supports ithreads],
+               [c_cv_have_perl_ithreads],
+               AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+#if !defined(USE_ITHREADS)
+# error "Perl does not support ithreads!"
+#endif /* !defined(USE_ITHREADS) */
+]]],
+[[[ ]]]
+                       )],
+                       [c_cv_have_perl_ithreads="yes"],
+                       [c_cv_have_perl_ithreads="no"]
+               )
+       )
+
+       if test "x$c_cv_have_perl_ithreads" = "xyes"
+       then
+               AC_DEFINE(HAVE_PERL_ITHREADS, 1, [Define if Perl supports ithreads.])
+       fi
+
+       CFLAGS="$SAVE_CFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+
+if test "x$with_libperl" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LIBS="$LIBS"
+       # trigger an error if Perl_load_module*() uses __attribute__nonnull__(3)
+       # (see issues #41 and #42)
+       CFLAGS="$CFLAGS $PERL_CFLAGS -Wall -Werror"
+       LIBS="$LIBS $PERL_LIBS"
+
+       AC_CACHE_CHECK([for broken Perl_load_module()],
+               [c_cv_have_broken_perl_load_module],
+               AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[[
+#define PERL_NO_GET_CONTEXT
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+]]],
+[[[
+                        dTHX;
+                        load_module (PERL_LOADMOD_NOIMPORT,
+                            newSVpv ("Collectd::Plugin::FooBar", 24),
+                            Nullsv);
+]]]
+                       )],
+                       [c_cv_have_broken_perl_load_module="no"],
+                       [c_cv_have_broken_perl_load_module="yes"]
+               )
+       )
+
+       CFLAGS="$SAVE_CFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+AM_CONDITIONAL(HAVE_BROKEN_PERL_LOAD_MODULE,
+               test "x$c_cv_have_broken_perl_load_module" = "xyes")
+
+if test "x$with_libperl" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LIBS="$LIBS"
+       CFLAGS="$CFLAGS $PERL_CFLAGS"
+       LIBS="$LIBS $PERL_LIBS"
+
+       AC_CHECK_MEMBER(
+               [struct mgvtbl.svt_local],
+               [have_struct_mgvtbl_svt_local="yes"],
+               [have_struct_mgvtbl_svt_local="no"],
+               [
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+               ])
+
+       if test "x$have_struct_mgvtbl_svt_local" = "xyes"
+       then
+               AC_DEFINE(HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL, 1,
+                                 [Define if Perl's struct mgvtbl has member svt_local.])
+       fi
+
+       CFLAGS="$SAVE_CFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+# }}}
+
+# --with-libpq {{{
+with_pg_config="pg_config"
+with_libpq_includedir=""
+with_libpq_libdir=""
+with_libpq_cppflags=""
+with_libpq_ldflags=""
+AC_ARG_WITH(libpq, [AS_HELP_STRING([--with-libpq@<:@=PREFIX@:>@],
+       [Path to libpq.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libpq="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libpq="yes"
+       else
+               if test -f "$withval" && test -x "$withval";
+               then
+                       with_pg_config="$withval"
+               else if test -x "$withval/bin/pg_config"
+               then
+                       with_pg_config="$withval/bin/pg_config"
+               fi; fi
+               with_libpq="yes"
+       fi; fi
+],
+[
+       with_libpq="yes"
+])
+if test "x$with_libpq" = "xyes"
+then
+       with_libpq_includedir=`$with_pg_config --includedir 2> /dev/null`
+       pg_config_status=$?
+
+       if test $pg_config_status -eq 0
+       then
+               if test -n "$with_libpq_includedir"; then
+                       for dir in $with_libpq_includedir; do
+                               with_libpq_cppflags="$with_libpq_cppflags -I$dir"
+                       done
+               fi
+       else
+               AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
+       fi
+
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libpq_cppflags"
+
+       AC_CHECK_HEADERS(libpq-fe.h, [],
+               [with_libpq="no (libpq-fe.h not found)"], [])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libpq" = "xyes"
+then
+       with_libpq_libdir=`$with_pg_config --libdir 2> /dev/null`
+       pg_config_status=$?
+
+       if test $pg_config_status -eq 0
+       then
+               if test -n "$with_libpq_libdir"; then
+                       for dir in $with_libpq_libdir; do
+                               with_libpq_ldflags="$with_libpq_ldflags -L$dir"
+                       done
+               fi
+       else
+               AC_MSG_WARN([$with_pg_config returned with status $pg_config_status])
+       fi
+
+       SAVE_LDFLAGS="$LDFLAGS"
+       LDFLAGS="$LDFLAGS $with_libpq_ldflags"
+
+       AC_CHECK_LIB(pq, PQconnectdb,
+               [with_libpq="yes"],
+               [with_libpq="no (symbol 'PQconnectdb' not found)"])
+
+       AC_CHECK_LIB(pq, PQserverVersion,
+               [with_libpq="yes"],
+               [with_libpq="no (symbol 'PQserverVersion' not found)"])
+
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libpq" = "xyes"
+then
+       BUILD_WITH_LIBPQ_CPPFLAGS="$with_libpq_cppflags"
+       BUILD_WITH_LIBPQ_LDFLAGS="$with_libpq_ldflags"
+       AC_SUBST(BUILD_WITH_LIBPQ_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBPQ_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBPQ, test "x$with_libpq" = "xyes")
+# }}}
+
+# --with-libpthread {{{
+AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
+[      if test "x$withval" != "xno" \
+               && test "x$withval" != "xyes"
+       then
+               LDFLAGS="$LDFLAGS -L$withval/lib"
+               CPPFLAGS="$CPPFLAGS -I$withval/include"
+               with_libpthread="yes"
+       else
+               if test "x$withval" = "xno"
+               then
+                       with_libpthread="no (disabled)"
+               fi
+       fi
+], [with_libpthread="yes"])
+if test "x$with_libpthread" = "xyes"
+then
+       AC_CHECK_LIB(pthread, pthread_create, [with_libpthread="yes"], [with_libpthread="no (libpthread not found)"], [])
+fi
+
+if test "x$with_libpthread" = "xyes"
+then
+       AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
+fi
+if test "x$with_libpthread" = "xyes"
+then
+       collect_pthread=1
+else
+       collect_pthread=0
+fi
+AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
+       [Wether or not to use pthread (POSIX threads) library])
+AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
+# }}}
+
+# --with-python {{{
+with_python_prog=""
+with_python_path="$PATH"
+AC_ARG_WITH(python, [AS_HELP_STRING([--with-python@<:@=PREFIX@:>@], [Path to the python interpreter.])],
+[
+ if test "x$withval" = "xyes" || test "x$withval" = "xno"
+ then
+        with_python="$withval"
+ else if test -x "$withval"
+ then
+        with_python_prog="$withval"
+        with_python_path="`dirname \"$withval\"`$PATH_SEPARATOR$with_python_path"
+        with_python="yes"
+ else if test -d "$withval"
+ then
+        with_python_path="$withval$PATH_SEPARATOR$with_python_path"
+        with_python="yes"
+ else
+        AC_MSG_WARN([Argument not recognized: $withval])
+ fi; fi; fi
+], [with_python="yes"])
+
+SAVE_PATH="$PATH"
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
+
+PATH="$with_python_path"
+
+if test "x$with_python" = "xyes" && test "x$with_python_prog" = "x"
+then
+       AC_MSG_CHECKING([for python])
+       with_python_prog="`which python 2>/dev/null`"
+       if test "x$with_python_prog" = "x"
+       then
+               AC_MSG_RESULT([not found])
+               with_python="no (interpreter not found)"
+       else
+               AC_MSG_RESULT([$with_python_prog])
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       AC_MSG_CHECKING([for Python CPPFLAGS])
+       python_include_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_python_inc())" | "$with_python_prog" 2>&1`
+       python_config_status=$?
+
+       if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x"
+       then
+               AC_MSG_RESULT([failed with status $python_config_status (output: $python_include_path)])
+               with_python="no"
+       else
+               AC_MSG_RESULT([$python_include_path])
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       CPPFLAGS="-I$python_include_path $CPPFLAGS"
+       AC_CHECK_HEADERS(Python.h,
+                        [with_python="yes"],
+                        [with_python="no ('Python.h' not found)"])
+fi
+
+if test "x$with_python" = "xyes"
+then
+       AC_MSG_CHECKING([for Python LDFLAGS])
+       python_library_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0))" | "$with_python_prog" 2>&1`
+       python_config_status=$?
+
+       if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x"
+       then
+               AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_path)])
+               with_python="no"
+       else
+               AC_MSG_RESULT([$python_library_path])
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       AC_MSG_CHECKING([for Python LIBS])
+       python_library_flags=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0))" | "$with_python_prog" 2>&1`
+       python_config_status=$?
+
+       if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x"
+       then
+               AC_MSG_RESULT([failed with status $python_config_status (output: $python_library_flags)])
+               with_python="no"
+       else
+               AC_MSG_RESULT([$python_library_flags])
+       fi
+fi
+
+if test "x$with_python" = "xyes"
+then
+       LDFLAGS="-L$python_library_path $LDFLAGS"
+       LIBS="$python_library_flags $LIBS"
+
+       AC_CHECK_FUNC(PyObject_CallFunction,
+                     [with_python="yes"],
+                     [with_python="no (Symbol 'PyObject_CallFunction' not found)"])
+fi
+
+PATH="$SAVE_PATH"
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
+
+if test "x$with_python" = "xyes"
+then
+       BUILD_WITH_PYTHON_CPPFLAGS="-I$python_include_path"
+       BUILD_WITH_PYTHON_LDFLAGS="-L$python_library_path"
+       BUILD_WITH_PYTHON_LIBS="$python_library_flags"
+       AC_SUBST(BUILD_WITH_PYTHON_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_PYTHON_LDFLAGS)
+       AC_SUBST(BUILD_WITH_PYTHON_LIBS)
+fi
+# }}} --with-python
+
+# --with-librabbitmq {{{
+with_librabbitmq_cppflags=""
+with_librabbitmq_ldflags=""
+AC_ARG_WITH(librabbitmq, [AS_HELP_STRING([--with-librabbitmq@<:@=PREFIX@:>@], [Path to librabbitmq.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_librabbitmq_cppflags="-I$withval/include"
+               with_librabbitmq_ldflags="-L$withval/lib"
+               with_librabbitmq="yes"
+       else
+               with_librabbitmq="$withval"
+       fi
+],
+[
+       with_librabbitmq="yes"
+])
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags"
+LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags"
+if test "x$with_librabbitmq" = "xyes"
+then
+       AC_CHECK_HEADERS(amqp.h, [with_librabbitmq="yes"], [with_librabbitmq="no (amqp.h not found)"])
+fi
+if test "x$with_librabbitmq" = "xyes"
+then
+       # librabbitmq up to version 0.9.1 provides "library_errno", later
+       # versions use "library_error". The library does not provide a version
+       # macro :( Use "AC_CHECK_MEMBERS" (plural) for automatic defines.
+       AC_CHECK_MEMBERS([amqp_rpc_reply_t.library_errno],,,
+                        [
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#if HAVE_STDIO_H
+# include <stdio.h>
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#include <amqp.h>
+                         ])
+fi
+if test "x$with_librabbitmq" = "xyes"
+then
+       AC_CHECK_LIB(rabbitmq, amqp_basic_publish, [with_librabbitmq="yes"], [with_librabbitmq="no (Symbol 'amqp_basic_publish' not found)"])
+fi
+if test "x$with_librabbitmq" = "xyes"
+then
+       BUILD_WITH_LIBRABBITMQ_CPPFLAGS="$with_librabbitmq_cppflags"
+       BUILD_WITH_LIBRABBITMQ_LDFLAGS="$with_librabbitmq_ldflags"
+       BUILD_WITH_LIBRABBITMQ_LIBS="-lrabbitmq"
+       AC_SUBST(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBRABBITMQ_LIBS)
+       AC_DEFINE(HAVE_LIBRABBITMQ, 1, [Define if librabbitmq is present and usable.])
+fi
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+AM_CONDITIONAL(BUILD_WITH_LIBRABBITMQ, test "x$with_librabbitmq" = "xyes")
+
+with_amqp_tcp_socket="no"
+if test "x$with_librabbitmq" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       SAVE_LIBS="$LIBS"
+       CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags"
+       LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags"
+       LIBS="-lrabbitmq"
+
+       AC_CHECK_HEADERS(amqp_tcp_socket.h amqp_socket.h)
+       AC_CHECK_FUNC(amqp_tcp_socket_new, [with_amqp_tcp_socket="yes"], [with_amqp_tcp_socket="no"])
+       if test "x$with_amqp_tcp_socket" = "xyes"
+       then
+               AC_DEFINE(HAVE_AMQP_TCP_SOCKET, 1,
+                               [Define if librabbitmq provides the new TCP socket interface.])
+       fi
+
+       AC_CHECK_DECLS(amqp_socket_close,
+                               [amqp_socket_close_decl="yes"], [amqp_socket_close_decl="no"],
+                               [[
+#include <amqp.h>
+#ifdef HAVE_AMQP_TCP_SOCKET_H
+# include <amqp_tcp_socket.h>
+#endif
+#ifdef HAVE_AMQP_SOCKET_H
+# include <amqp_socket.h>
+#endif
+                               ]])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+       LIBS="$SAVE_LIBS"
+fi
+# }}}
+
+# --with-librdkafka {{{
+AC_ARG_WITH(librdkafka, [AS_HELP_STRING([--with-librdkafka@<:@=PREFIX@:>@], [Path to librdkafka.])],
+[
+  if test "x$withval" != "xno" && test "x$withval" != "xyes"
+  then
+    with_librdkafka_cppflags="-I$withval/include"
+    with_librdkafka_ldflags="-L$withval/lib"
+    with_librdkafka_rpath="$withval/lib"
+    with_librdkafka="yes"
+  else
+    with_librdkafka="$withval"
+  fi
+],
+[
+  with_librdkafka="yes"
+])
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $with_librdkafka_cppflags"
+LDFLAGS="$LDFLAGS $with_librdkafka_ldflags"
+
+if test "x$with_librdkafka" = "xyes"
+then
+       AC_CHECK_HEADERS(librdkafka/rdkafka.h, [with_librdkafka="yes"], [with_librdkafka="no (librdkafka/rdkafka.h not found)"])
+fi
+
+if test "x$with_librdkafka" = "xyes"
+then
+       AC_CHECK_LIB(rdkafka, rd_kafka_new, [with_librdkafka="yes"], [with_librdkafka="no (Symbol 'rd_kafka_new' not found)"])
+  AC_CHECK_LIB(rdkafka, rd_kafka_conf_set_log_cb, [with_librdkafka_log_cb="yes"], [with_librdkafka_log_cb="no"])
+  AC_CHECK_LIB(rdkafka, rd_kafka_set_logger, [with_librdkafka_logger="yes"], [with_librdkafka_logger="no"])
+fi
+if test "x$with_librdkafka" = "xyes"
+then
+       BUILD_WITH_LIBRDKAFKA_CPPFLAGS="$with_librdkafka_cppflags"
+       BUILD_WITH_LIBRDKAFKA_LDFLAGS="$with_librdkafka_ldflags"
+       if test "x$with_librdkafka_rpath" != "x"
+       then
+               BUILD_WITH_LIBRDKAFKA_LIBS="-Wl,-rpath,$with_librdkafka_rpath -lrdkafka"
+       else
+               BUILD_WITH_LIBRDKAFKA_LIBS="-lrdkafka"
+       fi
+       AC_SUBST(BUILD_WITH_LIBRDKAFKA_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBRDKAFKA_LIBS)
+       AC_DEFINE(HAVE_LIBRDKAFKA, 1, [Define if librdkafka is present and usable.])
+  if test "x$with_librdkafka_log_cb" = "xyes"
+  then
+        AC_DEFINE(HAVE_LIBRDKAFKA_LOG_CB, 1, [Define if librdkafka log facility is present and usable.])
+  fi
+  if test "x$with_librdkafka_logger" = "xyes"
+  then
+        AC_DEFINE(HAVE_LIBRDKAFKA_LOGGER, 1, [Define if librdkafka log facility is present and usable.])
+  fi
+fi
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+AM_CONDITIONAL(BUILD_WITH_LIBRDKAFKA, test "x$with_librdkafka" = "xyes")
+
+# }}}
+
+# --with-librouteros {{{
+AC_ARG_WITH(librouteros, [AS_HELP_STRING([--with-librouteros@<:@=PREFIX@:>@], [Path to librouteros.])],
+[
+ if test "x$withval" = "xyes"
+ then
+        with_librouteros="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_librouteros="no"
+ else
+        with_librouteros="yes"
+        LIBROUTEROS_CPPFLAGS="$LIBROUTEROS_CPPFLAGS -I$withval/include"
+        LIBROUTEROS_LDFLAGS="$LIBROUTEROS_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_librouteros="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBROUTEROS_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBROUTEROS_LDFLAGS"
+
+if test "x$with_librouteros" = "xyes"
+then
+       if test "x$LIBROUTEROS_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([librouteros CPPFLAGS: $LIBROUTEROS_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(routeros_api.h,
+       [with_librouteros="yes"],
+       [with_librouteros="no (routeros_api.h not found)"])
+fi
+if test "x$with_librouteros" = "xyes"
+then
+       if test "x$LIBROUTEROS_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([librouteros LDFLAGS: $LIBROUTEROS_LDFLAGS])
+       fi
+       AC_CHECK_LIB(routeros, ros_interface,
+       [with_librouteros="yes"],
+       [with_librouteros="no (symbol 'ros_interface' not found)"])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_librouteros" = "xyes"
+then
+       BUILD_WITH_LIBROUTEROS_CPPFLAGS="$LIBROUTEROS_CPPFLAGS"
+       BUILD_WITH_LIBROUTEROS_LDFLAGS="$LIBROUTEROS_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBROUTEROS_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBROUTEROS_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBROUTEROS, test "x$with_librouteros" = "xyes")
+# }}}
+
+# --with-librrd {{{
+# AC_ARG_WITH (package, help-string, [action-if-given], [action-if-not-given])
+librrd_cflags=""
+librrd_ldflags=""
+librrd_threadsafe="yes"
+librrd_rrdc_update="no"
+AC_ARG_WITH(librrd, [AS_HELP_STRING([--with-librrd@<:@=PREFIX@:>@], [Path to rrdtool.])],
+[      if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               librrd_cflags="-I$withval/include"
+               librrd_ldflags="-L$withval/lib"
+               with_librrd="yes"
+       else
+               with_librrd="$withval"
+       fi
+], [with_librrd="yes"])
+if test "x$with_librrd" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $librrd_cflags"
+       LDFLAGS="$LDFLAGS $librrd_ldflags"
+
+       AC_CHECK_HEADERS(rrd.h,, [with_librrd="no (rrd.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_librrd" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $librrd_cflags"
+       LDFLAGS="$LDFLAGS $librrd_ldflags"
+
+       AC_CHECK_LIB(rrd_th, rrd_update_r,
+       [with_librrd="yes"
+        librrd_ldflags="$librrd_ldflags -lrrd_th -lm"
+       ],
+       [librrd_threadsafe="no"
+        AC_CHECK_LIB(rrd, rrd_update,
+        [with_librrd="yes"
+         librrd_ldflags="$librrd_ldflags -lrrd -lm"
+        ],
+        [with_librrd="no (symbol 'rrd_update' not found)"],
+        [-lm])
+       ],
+       [-lm])
+
+       if test "x$librrd_threadsafe" = "xyes"
+       then
+               AC_CHECK_LIB(rrd_th, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"])
+       else
+               AC_CHECK_LIB(rrd, rrdc_update, [librrd_rrdc_update="yes"], [librrd_rrdc_update="no"])
+       fi
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_librrd" = "xyes"
+then
+       BUILD_WITH_LIBRRD_CFLAGS="$librrd_cflags"
+       BUILD_WITH_LIBRRD_LDFLAGS="$librrd_ldflags"
+       AC_SUBST(BUILD_WITH_LIBRRD_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBRRD_LDFLAGS)
+fi
+if test "x$librrd_threadsafe" = "xyes"
+then
+       AC_DEFINE(HAVE_THREADSAFE_LIBRRD, 1, [Define to 1 if you have the threadsafe rrd library (-lrrd_th).])
+fi
+# }}}
+
+# --with-libsensors {{{
+with_sensors_cflags=""
+with_sensors_ldflags=""
+AC_ARG_WITH(libsensors, [AS_HELP_STRING([--with-libsensors@<:@=PREFIX@:>@], [Path to lm_sensors.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libsensors="no"
+       else
+               with_libsensors="yes"
+               if test "x$withval" != "xyes"
+               then
+                       with_sensors_cflags="-I$withval/include"
+                       with_sensors_ldflags="-L$withval/lib"
+                       with_libsensors="yes"
+               fi
+       fi
+],
+[
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libsensors="yes"
+       else
+               with_libsensors="no (Linux only library)"
+       fi
+])
+if test "x$with_libsensors" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
+
+#      AC_CHECK_HEADERS(sensors/sensors.h,
+#      [
+#              AC_DEFINE(HAVE_SENSORS_SENSORS_H, 1, [Define to 1 if you have the <sensors/sensors.h> header file.])
+#      ],
+#      [with_libsensors="no (sensors/sensors.h not found)"])
+       AC_CHECK_HEADERS(sensors/sensors.h, [], [with_libsensors="no (sensors/sensors.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libsensors" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_sensors_cflags"
+       LDFLAGS="$LDFLAGS $with_sensors_ldflags"
+
+       AC_CHECK_LIB(sensors, sensors_init,
+       [
+               AC_DEFINE(HAVE_LIBSENSORS, 1, [Define to 1 if you have the sensors library (-lsensors).])
+       ],
+       [with_libsensors="no (libsensors not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libsensors" = "xyes"
+then
+       BUILD_WITH_LIBSENSORS_CFLAGS="$with_sensors_cflags"
+       BUILD_WITH_LIBSENSORS_LDFLAGS="$with_sensors_ldflags"
+       AC_SUBST(BUILD_WITH_LIBSENSORS_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBSENSORS_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LM_SENSORS, test "x$with_libsensors" = "xyes")
+# }}}
+
+# --with-libsigrok {{{
+with_libsigrok_cflags=""
+with_libsigrok_ldflags=""
+AC_ARG_WITH(libsigrok, [AS_HELP_STRING([--with-libsigrok@<:@=PREFIX@:>@], [Path to libsigrok.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libsigrok="no"
+       else
+               with_libsigrok="yes"
+               if test "x$withval" != "xyes"
+               then
+                       with_libsigrok_cflags="-I$withval/include"
+                       with_libsigrok_ldflags="-L$withval/lib"
+               fi
+       fi
+],[with_libsigrok="yes"])
+
+# libsigrok has a glib dependency
+if test "x$with_libsigrok" = "xyes"
+then
+m4_ifdef([AM_PATH_GLIB_2_0],
+       [
+        AM_PATH_GLIB_2_0([2.28.0],
+               [with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"])
+       ],
+       [
+        with_libsigrok="no (glib not available)"
+       ]
+)
+fi
+
+# libsigrok headers
+if test "x$with_libsigrok" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
+
+       AC_CHECK_HEADERS(libsigrok/libsigrok.h, [], [with_libsigrok="no (libsigrok/libsigrok.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+# libsigrok library
+if test "x$with_libsigrok" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libsigrok_cflags"
+       LDFLAGS="$LDFLAGS $with_libsigrok_ldflags"
+
+       AC_CHECK_LIB(sigrok, sr_init,
+       [
+               AC_DEFINE(HAVE_LIBSIGROK, 1, [Define to 1 if you have the sigrok library (-lsigrok).])
+       ],
+       [with_libsigrok="no (libsigrok not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libsigrok" = "xyes"
+then
+       BUILD_WITH_LIBSIGROK_CFLAGS="$with_libsigrok_cflags"
+       BUILD_WITH_LIBSIGROK_LDFLAGS="$with_libsigrok_ldflags"
+       AC_SUBST(BUILD_WITH_LIBSIGROK_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBSIGROK_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBSIGROK, test "x$with_libsigrok" = "xyes")
+# }}}
+
+# --with-libstatgrab {{{
+with_libstatgrab_cflags=""
+with_libstatgrab_ldflags=""
+AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])],
+[
+ if test "x$withval" != "xno" \
+   && test "x$withval" != "xyes"
+ then
+   with_libstatgrab_cflags="-I$withval/include"
+   with_libstatgrab_ldflags="-L$withval/lib -lstatgrab"
+   with_libstatgrab="yes"
+   with_libstatgrab_pkg_config="no"
+ else
+   with_libstatgrab="$withval"
+   with_libstatgrab_pkg_config="yes"
+ fi
+ ],
+[
+ with_libstatgrab="yes"
+ with_libstatgrab_pkg_config="yes"
+])
+
+if test "x$with_libstatgrab" = "xyes" \
+  && test "x$with_libstatgrab_pkg_config" = "xyes"
+then
+  if test "x$PKG_CONFIG" != "x"
+  then
+    AC_MSG_CHECKING([pkg-config for libstatgrab])
+    temp_result="found"
+    $PKG_CONFIG --exists libstatgrab 2>/dev/null
+    if test "$?" != "0"
+    then
+      with_libstatgrab_pkg_config="no"
+      with_libstatgrab="no (pkg-config doesn't know libstatgrab)"
+      temp_result="not found"
+    fi
+    AC_MSG_RESULT([$temp_result])
+  else
+    AC_MSG_NOTICE([pkg-config not available, trying to guess flags for the statgrab library.])
+    with_libstatgrab_pkg_config="no"
+    with_libstatgrab_ldflags="$with_libstatgrab_ldflags -lstatgrab"
+  fi
+fi
+
+if test "x$with_libstatgrab" = "xyes" \
+  && test "x$with_libstatgrab_pkg_config" = "xyes" \
+  && test "x$with_libstatgrab_cflags" = "x"
+then
+  AC_MSG_CHECKING([for libstatgrab CFLAGS])
+  temp_result="`$PKG_CONFIG --cflags libstatgrab`"
+  if test "$?" = "0"
+  then
+    with_libstatgrab_cflags="$temp_result"
+  else
+    with_libstatgrab="no ($PKG_CONFIG --cflags libstatgrab failed)"
+    temp_result="$PKG_CONFIG --cflags libstatgrab failed"
+  fi
+  AC_MSG_RESULT([$temp_result])
+fi
+
+if test "x$with_libstatgrab" = "xyes" \
+  && test "x$with_libstatgrab_pkg_config" = "xyes" \
+  && test "x$with_libstatgrab_ldflags" = "x"
+then
+  AC_MSG_CHECKING([for libstatgrab LDFLAGS])
+  temp_result="`$PKG_CONFIG --libs libstatgrab`"
+  if test "$?" = "0"
+  then
+    with_libstatgrab_ldflags="$temp_result"
+  else
+    with_libstatgrab="no ($PKG_CONFIG --libs libstatgrab failed)"
+    temp_result="$PKG_CONFIG --libs libstatgrab failed"
+  fi
+  AC_MSG_RESULT([$temp_result])
+fi
+
+if test "x$with_libstatgrab" = "xyes"
+then
+  SAVE_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $with_libstatgrab_cflags"
+
+  AC_CHECK_HEADERS(statgrab.h,
+                  [with_libstatgrab="yes"],
+                  [with_libstatgrab="no (statgrab.h not found)"])
+
+  CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+if test "x$with_libstatgrab" = "xyes"
+then
+  SAVE_CFLAGS="$CFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
+
+  CFLAGS="$CFLAGS $with_libstatgrab_cflags"
+  LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
+
+  AC_CHECK_LIB(statgrab, sg_init,
+              [with_libstatgrab="yes"],
+              [with_libstatgrab="no (symbol sg_init not found)"])
+
+  CFLAGS="$SAVE_CFLAGS"
+  LDFLAGS="$SAVE_LDFLAGS"
+fi
+
+if test "x$with_libstatgrab" = "xyes"
+then
+  SAVE_CFLAGS="$CFLAGS"
+  SAVE_LIBS="$LIBS"
+
+  CFLAGS="$CFLAGS $with_libstatgrab_cflags"
+  LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
+  LIBS="-lstatgrab $LIBS"
+
+  AC_CACHE_CHECK([if libstatgrab >= 0.90],
+          [c_cv_have_libstatgrab_0_90],
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdio.h>
+#include <statgrab.h>
+]]],
+[[[
+      if (sg_init()) return 0;
+]]]
+    )],
+    [c_cv_have_libstatgrab_0_90="no"],
+    [c_cv_have_libstatgrab_0_90="yes"]
+          )
+  )
+
+  CFLAGS="$SAVE_CFLAGS"
+  LDFLAGS="$SAVE_LDFLAGS"
+  LIBS="$SAVE_LIBS"
+fi
+
+AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes")
+if test "x$with_libstatgrab" = "xyes"
+then
+  AC_DEFINE(HAVE_LIBSTATGRAB, 1, [Define to 1 if you have the 'statgrab' library (-lstatgrab)])
+  BUILD_WITH_LIBSTATGRAB_CFLAGS="$with_libstatgrab_cflags"
+  BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags"
+  AC_SUBST(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+  AC_SUBST(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+  if test "x$c_cv_have_libstatgrab_0_90" = "xyes"
+  then
+        AC_DEFINE(HAVE_LIBSTATGRAB_0_90, 1, [Define to 1 if libstatgrab version >= 0.90])
+  fi
+fi
+# }}}
+
+# --with-libtokyotyrant {{{
+with_libtokyotyrant_cppflags=""
+with_libtokyotyrant_ldflags=""
+with_libtokyotyrant_libs=""
+AC_ARG_WITH(libtokyotyrant, [AS_HELP_STRING([--with-libtokyotyrant@<:@=PREFIX@:>@], [Path to libtokyotyrant.])],
+[
+  if test "x$withval" = "xno"
+  then
+    with_libtokyotyrant="no"
+  else if test "x$withval" = "xyes"
+  then
+    with_libtokyotyrant="yes"
+  else
+    with_libtokyotyrant_cppflags="-I$withval/include"
+    with_libtokyotyrant_ldflags="-L$withval/include"
+    with_libtokyotyrant_libs="-ltokyotyrant"
+    with_libtokyotyrant="yes"
+  fi; fi
+],
+[
+  with_libtokyotyrant="yes"
+])
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  if $PKG_CONFIG --exists tokyotyrant
+  then
+    with_libtokyotyrant_cppflags="$with_libtokyotyrant_cppflags `$PKG_CONFIG --cflags tokyotyrant`"
+    with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `$PKG_CONFIG --libs-only-L tokyotyrant`"
+    with_libtokyotyrant_libs="$with_libtokyotyrant_libs `$PKG_CONFIG --libs-only-l tokyotyrant`"
+  fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $with_libtokyotyrant_cppflags"
+LDFLAGS="$LDFLAGS $with_libtokyotyrant_ldflags"
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  AC_CHECK_HEADERS(tcrdb.h,
+  [
+          AC_DEFINE(HAVE_TCRDB_H, 1,
+                    [Define to 1 if you have the <tcrdb.h> header file.])
+  ], [with_libtokyotyrant="no (tcrdb.h not found)"])
+fi
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  AC_CHECK_LIB(tokyotyrant, tcrdbrnum,
+  [
+          AC_DEFINE(HAVE_LIBTOKYOTYRANT, 1,
+                    [Define to 1 if you have the tokyotyrant library (-ltokyotyrant).])
+  ],
+  [with_libtokyotyrant="no (symbol tcrdbrnum not found)"],
+  [$with_libtokyotyrant_libs])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+  BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS="$with_libtokyotyrant_cppflags"
+  BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS="$with_libtokyotyrant_ldflags"
+  BUILD_WITH_LIBTOKYOTYRANT_LIBS="$with_libtokyotyrant_libs"
+  AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
+  AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
+  AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBTOKYOTYRANT, test "x$with_libtokyotyrant" = "xyes")
+# }}}
+
+# --with-libudev {{{
+with_libudev_cflags=""
+with_libudev_ldflags=""
+AC_ARG_WITH(libudev, [AS_HELP_STRING([--with-libudev@<:@=PREFIX@:>@], [Path to libudev.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libudev="no"
+       else
+               with_libudev="yes"
+               if test "x$withval" != "xyes"
+               then
+                       with_libudev_cflags="-I$withval/include"
+                       with_libudev_ldflags="-L$withval/lib"
+                       with_libudev="yes"
+               fi
+       fi
+],
+[
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libudev="yes"
+       else
+               with_libudev="no (Linux only library)"
+       fi
+])
+if test "x$with_libudev" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libudev_cflags"
+
+       AC_CHECK_HEADERS(libudev.h, [], [with_libudev="no (libudev.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libudev" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libudev_cflags"
+       LDFLAGS="$LDFLAGS $with_libudev_ldflags"
+
+       AC_CHECK_LIB(udev, udev_new,
+       [
+               AC_DEFINE(HAVE_LIBUDEV, 1, [Define to 1 if you have the udev library (-ludev).])
+       ],
+       [with_libudev="no (libudev not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libudev" = "xyes"
+then
+       BUILD_WITH_LIBUDEV_CFLAGS="$with_libudev_cflags"
+       BUILD_WITH_LIBUDEV_LDFLAGS="$with_libudev_ldflags"
+       AC_SUBST(BUILD_WITH_LIBUDEV_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBUDEV_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBUDEV, test "x$with_libudev" = "xyes")
+# }}}
+
+# --with-libupsclient {{{
+with_libupsclient_config=""
+with_libupsclient_cflags=""
+with_libupsclient_libs=""
+AC_ARG_WITH(libupsclient, [AS_HELP_STRING([--with-libupsclient@<:@=PREFIX@:>@], [Path to the upsclient library.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libupsclient="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libupsclient="use_pkgconfig"
+       else
+               if test -x "$withval"
+               then
+                       with_libupsclient_config="$withval"
+                       with_libupsclient="use_libupsclient_config"
+               else if test -x "$withval/bin/libupsclient-config"
+               then
+                       with_libupsclient_config="$withval/bin/libupsclient-config"
+                       with_libupsclient="use_libupsclient_config"
+               else
+                       AC_MSG_NOTICE([Not checking for libupsclient: Manually configured])
+                       with_libupsclient_cflags="-I$withval/include"
+                       with_libupsclient_libs="-L$withval/lib -lupsclient"
+                       with_libupsclient="yes"
+               fi; fi
+       fi; fi
+],
+[with_libupsclient="use_pkgconfig"])
+
+# configure using libupsclient-config
+if test "x$with_libupsclient" = "xuse_libupsclient_config"
+then
+       AC_MSG_NOTICE([Checking for libupsclient using $with_libupsclient_config])
+       with_libupsclient_cflags="`$with_libupsclient_config --cflags`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($with_libupsclient_config failed)"
+       fi
+       with_libupsclient_libs="`$with_libupsclient_config --libs`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($with_libupsclient_config failed)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_libupsclient_config"
+then
+       with_libupsclient="yes"
+fi
+
+# configure using pkg-config
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       if test "x$PKG_CONFIG" = "x"
+       then
+               with_libupsclient="no (Don't have pkg-config)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       AC_MSG_NOTICE([Checking for libupsclient using $PKG_CONFIG])
+       $PKG_CONFIG --exists 'libupsclient' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libupsclient="no (pkg-config doesn't know libupsclient)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       with_libupsclient_cflags="`$PKG_CONFIG --cflags 'libupsclient'`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($PKG_CONFIG failed)"
+       fi
+       with_libupsclient_libs="`$PKG_CONFIG --libs 'libupsclient'`"
+       if test $? -ne 0
+       then
+               with_libupsclient="no ($PKG_CONFIG failed)"
+       fi
+fi
+if test "x$with_libupsclient" = "xuse_pkgconfig"
+then
+       with_libupsclient="yes"
+fi
+
+# with_libupsclient_cflags and with_libupsclient_libs are set up now, let's do
+# the actual checks.
+if test "x$with_libupsclient" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+
+       AC_CHECK_HEADERS(upsclient.h, [], [with_libupsclient="no (upsclient.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+       LDFLAGS="$LDFLAGS $with_libupsclient_libs"
+
+       AC_CHECK_LIB(upsclient, upscli_connect,
+                    [with_libupsclient="yes"],
+                    [with_libupsclient="no (symbol upscli_connect not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libupsclient_cflags"
+
+       AC_CHECK_TYPES([UPSCONN_t, UPSCONN], [], [],
+[#include <stdlib.h>
+#include <stdio.h>
+#include <upsclient.h>])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libupsclient" = "xyes"
+then
+       BUILD_WITH_LIBUPSCLIENT_CFLAGS="$with_libupsclient_cflags"
+       BUILD_WITH_LIBUPSCLIENT_LIBS="$with_libupsclient_libs"
+       AC_SUBST(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBUPSCLIENT_LIBS)
+fi
+# }}}
+
+# --with-libxmms {{{
+with_xmms_config="xmms-config"
+with_xmms_cflags=""
+with_xmms_libs=""
+AC_ARG_WITH(libxmms, [AS_HELP_STRING([--with-libxmms@<:@=PREFIX@:>@], [Path to libxmms.])],
+[
+       if test "x$withval" != "xno" \
+               && test "x$withval" != "xyes"
+       then
+               if test -f "$withval" && test -x "$withval";
+               then
+                       with_xmms_config="$withval"
+               else if test -x "$withval/bin/xmms-config"
+               then
+                       with_xmms_config="$withval/bin/xmms-config"
+               fi; fi
+               with_libxmms="yes"
+       else if test "x$withval" = "xno"
+       then
+               with_libxmms="no"
+       else
+               with_libxmms="yes"
+       fi; fi
+],
+[
+       with_libxmms="yes"
+])
+if test "x$with_libxmms" = "xyes"
+then
+       with_xmms_cflags=`$with_xmms_config --cflags 2>/dev/null`
+       xmms_config_status=$?
+
+       if test $xmms_config_status -ne 0
+       then
+               with_libxmms="no"
+       fi
+fi
+if test "x$with_libxmms" = "xyes"
+then
+       with_xmms_libs=`$with_xmms_config --libs 2>/dev/null`
+       xmms_config_status=$?
+
+       if test $xmms_config_status -ne 0
+       then
+               with_libxmms="no"
+       fi
+fi
+if test "x$with_libxmms" = "xyes"
+then
+       AC_CHECK_LIB(xmms, xmms_remote_get_info,
+       [
+               BUILD_WITH_LIBXMMS_CFLAGS="$with_xmms_cflags"
+               BUILD_WITH_LIBXMMS_LIBS="$with_xmms_libs"
+               AC_SUBST(BUILD_WITH_LIBXMMS_CFLAGS)
+               AC_SUBST(BUILD_WITH_LIBXMMS_LIBS)
+       ],
+       [
+               with_libxmms="no"
+       ],
+       [$with_xmms_libs])
+fi
+with_libxmms_numeric=0
+if test "x$with_libxmms" = "xyes"
+then
+       with_libxmms_numeric=1
+fi
+AC_DEFINE_UNQUOTED(HAVE_LIBXMMS, [$with_libxmms_numeric], [Define to 1 if you have the 'xmms' library (-lxmms).])
+AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes")
+# }}}
+
+# --with-libyajl {{{
+with_libyajl_cppflags=""
+with_libyajl_ldflags=""
+AC_ARG_WITH(libyajl, [AS_HELP_STRING([--with-libyajl@<:@=PREFIX@:>@], [Path to libyajl.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libyajl_cppflags="-I$withval/include"
+               with_libyajl_ldflags="-L$withval/lib"
+               with_libyajl="yes"
+       else
+               with_libyajl="$withval"
+       fi
+],
+[
+       with_libyajl="yes"
+])
+if test "x$with_libyajl" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+
+       AC_CHECK_HEADERS(yajl/yajl_parse.h, [with_libyajl="yes"], [with_libyajl="no (yajl/yajl_parse.h not found)"])
+       AC_CHECK_HEADERS(yajl/yajl_version.h)
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+       LDFLAGS="$LDFLAGS $with_libyajl_ldflags"
+
+       AC_CHECK_LIB(yajl, yajl_alloc, [with_libyajl="yes"], [with_libyajl="no (Symbol 'yajl_alloc' not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+       BUILD_WITH_LIBYAJL_CPPFLAGS="$with_libyajl_cppflags"
+       BUILD_WITH_LIBYAJL_LDFLAGS="$with_libyajl_ldflags"
+       BUILD_WITH_LIBYAJL_LIBS="-lyajl"
+       AC_SUBST(BUILD_WITH_LIBYAJL_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBYAJL_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBYAJL_LIBS)
+       AC_DEFINE(HAVE_LIBYAJL, 1, [Define if libyajl is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes")
+# }}}
+
+# --with-mic {{{
+with_mic_cflags="-I/opt/intel/mic/sysmgmt/sdk/include"
+with_mic_ldpath="-L/opt/intel/mic/sysmgmt/sdk/lib/Linux"
+with_mic_libs=""
+AC_ARG_WITH(mic,[AS_HELP_STRING([--with-mic@<:@=PREFIX@:>@], [Path to Intel MIC Access API.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_mic="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_mic="yes"
+       else if test -d "$with_mic/lib"
+       then
+               AC_MSG_NOTICE([Not checking for Intel Mic: Manually configured])
+               with_mic_cflags="-I$withval/include"
+               with_mic_ldpath="-L$withval/lib/Linux"
+               with_mic_libs="-lMicAccessSDK -lscif -lpthread"
+               with_mic="yes"
+       fi; fi; fi
+],
+[with_mic="yes"])
+if test "x$with_mic" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_mic_cflags"
+       AC_CHECK_HEADERS(MicAccessApi.h,[],[with_mic="no (MicAccessApi not found)"])
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_mic" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_mic_cflags"
+       LDFLAGS="$LDFLAGS $with_mic_ldpath"
+
+       AC_CHECK_LIB(MicAccessSDK, MicInitAPI,
+                       [with_mic_ldpath="$with_mic_ldpath"
+                       with_mic_libs="-lMicAccessSDK -lscif -lpthread"],
+                       [with_mic="no (symbol MicInitAPI not found)"],[-lscif -lpthread])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+
+if test "x$with_mic" = "xyes"
+then
+       BUILD_WITH_MIC_CPPFLAGS="$with_mic_cflags"
+       BUILD_WITH_MIC_LIBPATH="$with_mic_ldpath"
+       BUILD_WITH_MIC_LDADD="$with_mic_libs"
+       AC_SUBST(BUILD_WITH_MIC_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_MIC_LIBPATH)
+       AC_SUBST(BUILD_WITH_MIC_LDADD)
+fi
+#}}}
+
+# --with-libvarnish {{{
+with_libvarnish_cppflags=""
+with_libvarnish_cflags=""
+with_libvarnish_libs=""
+AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Path to libvarnish.])],
+[
+       if test "x$withval" = "xno"
+       then
+               with_libvarnish="no"
+       else if test "x$withval" = "xyes"
+       then
+               with_libvarnish="use_pkgconfig"
+       else if test -d "$with_libvarnish/lib"
+       then
+               AC_MSG_NOTICE([Not checking for libvarnish: Manually configured])
+               with_libvarnish_cflags="-I$withval/include"
+               with_libvarnish_libs="-L$withval/lib -lvarnishapi"
+               with_libvarnish="yes"
+       fi; fi; fi
+],
+[with_libvarnish="use_pkgconfig"])
+
+# configure using pkg-config
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       if test "x$PKG_CONFIG" = "x"
+       then
+               with_libvarnish="no (Don't have pkg-config)"
+       fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       AC_MSG_NOTICE([Checking for varnishapi using $PKG_CONFIG])
+       $PKG_CONFIG --exists 'varnishapi' 2>/dev/null
+       if test $? -ne 0
+       then
+               with_libvarnish="no (pkg-config doesn't know varnishapi)"
+       fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       with_libvarnish_cflags="`$PKG_CONFIG --cflags 'varnishapi'`"
+       if test $? -ne 0
+       then
+               with_libvarnish="no ($PKG_CONFIG failed)"
+       fi
+       with_libvarnish_libs="`$PKG_CONFIG --libs 'varnishapi'`"
+       if test $? -ne 0
+       then
+               with_libvarnish="no ($PKG_CONFIG failed)"
+       fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+       with_libvarnish="yes"
+fi
+
+# with_libvarnish_cflags and with_libvarnish_libs are set up now, let's do
+# the actual checks.
+if test "x$with_libvarnish" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+
+       CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
+
+       AC_CHECK_HEADERS(varnish/vapi/vsc.h,
+               [AC_DEFINE([HAVE_VARNISH_V4], [1], [Varnish 4 API support])],
+               [AC_CHECK_HEADERS(varnish/vsc.h,
+                       [AC_DEFINE([HAVE_VARNISH_V3], [1], [Varnish 3 API support])],
+                       [AC_CHECK_HEADERS(varnish/varnishapi.h,
+                               [AC_DEFINE([HAVE_VARNISH_V2], [1], [Varnish 2 API support])],
+                               [with_libvarnish="no (found none of the varnish header files)"])])])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libvarnish" = "xyes"
+then
+       BUILD_WITH_LIBVARNISH_CFLAGS="$with_libvarnish_cflags"
+       BUILD_WITH_LIBVARNISH_LIBS="$with_libvarnish_libs"
+       AC_SUBST(BUILD_WITH_LIBVARNISH_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBVARNISH_LIBS)
+fi
+# }}}
+
+# pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
+with_libxml2="no (pkg-config isn't available)"
+with_libxml2_cflags=""
+with_libxml2_ldflags=""
+with_libvirt="no (pkg-config isn't available)"
+with_libvirt_cflags=""
+with_libvirt_ldflags=""
+if test "x$PKG_CONFIG" != "x"
+then
+       $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
+       if test "$?" = "0"
+       then
+               with_libxml2="yes"
+       else
+               with_libxml2="no (pkg-config doesn't know libxml-2.0)"
+       fi
+
+       $PKG_CONFIG --exists libvirt 2>/dev/null
+       if test "$?" = "0"
+       then
+               with_libvirt="yes"
+       else
+               with_libvirt="no (pkg-config doesn't know libvirt)"
+       fi
+fi
+if test "x$with_libxml2" = "xyes"
+then
+       with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`"
+       if test $? -ne 0
+       then
+               with_libxml2="no"
+       fi
+       with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`"
+       if test $? -ne 0
+       then
+               with_libxml2="no"
+       fi
+fi
+if test "x$with_libxml2" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libxml2_cflags"
+
+       AC_CHECK_HEADERS(libxml/parser.h, [],
+                     [with_libxml2="no (libxml/parser.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libxml2" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CFLAGS="$CFLAGS $with_libxml2_cflags"
+       LDFLAGS="$LDFLAGS $with_libxml2_ldflags"
+
+       AC_CHECK_LIB(xml2, xmlXPathEval,
+                    [with_libxml2="yes"],
+                    [with_libxml2="no (symbol xmlXPathEval not found)"])
+
+       CFLAGS="$SAVE_CFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+dnl Add the right compiler flags and libraries.
+if test "x$with_libxml2" = "xyes"; then
+       BUILD_WITH_LIBXML2_CFLAGS="$with_libxml2_cflags"
+       BUILD_WITH_LIBXML2_LIBS="$with_libxml2_ldflags"
+       AC_SUBST(BUILD_WITH_LIBXML2_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBXML2_LIBS)
+fi
+if test "x$with_libvirt" = "xyes"
+then
+       with_libvirt_cflags="`$PKG_CONFIG --cflags libvirt`"
+       if test $? -ne 0
+       then
+               with_libvirt="no"
+       fi
+       with_libvirt_ldflags="`$PKG_CONFIG --libs libvirt`"
+       if test $? -ne 0
+       then
+               with_libvirt="no"
+       fi
+fi
+if test "x$with_libvirt" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libvirt_cflags"
+
+       AC_CHECK_HEADERS(libvirt/libvirt.h, [],
+                     [with_libvirt="no (libvirt/libvirt.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libvirt" = "xyes"
+then
+       SAVE_CFLAGS="$CFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+
+       CFLAGS="$CFLAGS $with_libvirt_cflags"
+       LDFLAGS="$LDFLAGS $with_libvirt_ldflags"
+
+       AC_CHECK_LIB(virt, virDomainBlockStats,
+                    [with_libvirt="yes"],
+                    [with_libvirt="no (symbol virDomainBlockStats not found)"])
+
+       CFLAGS="$SAVE_CFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+dnl Add the right compiler flags and libraries.
+if test "x$with_libvirt" = "xyes"; then
+       BUILD_WITH_LIBVIRT_CFLAGS="$with_libvirt_cflags"
+       BUILD_WITH_LIBVIRT_LIBS="$with_libvirt_ldflags"
+       AC_SUBST(BUILD_WITH_LIBVIRT_CFLAGS)
+       AC_SUBST(BUILD_WITH_LIBVIRT_LIBS)
+fi
+# }}}
+
+# $PKG_CONFIG --exists OpenIPMIpthread {{{
+with_libopenipmipthread="yes"
+with_libopenipmipthread_cflags=""
+with_libopenipmipthread_libs=""
+
+AC_MSG_CHECKING([for pkg-config])
+temp_result="no"
+if test "x$PKG_CONFIG" = "x"
+then
+       with_libopenipmipthread="no"
+       temp_result="no"
+else
+       temp_result="$PKG_CONFIG"
+fi
+AC_MSG_RESULT([$temp_result])
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       AC_MSG_CHECKING([for libOpenIPMIpthread])
+       $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null
+       if test "$?" != "0"
+       then
+               with_libopenipmipthread="no (pkg-config doesn't know OpenIPMIpthread)"
+       fi
+       AC_MSG_RESULT([$with_libopenipmipthread])
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       AC_MSG_CHECKING([for libOpenIPMIpthread CFLAGS])
+       temp_result="`$PKG_CONFIG --cflags OpenIPMIpthread`"
+       if test "$?" = "0"
+       then
+               with_libopenipmipthread_cflags="$temp_result"
+       else
+               with_libopenipmipthread="no ($PKG_CONFIG --cflags OpenIPMIpthread failed)"
+               temp_result="$PKG_CONFIG --cflags OpenIPMIpthread failed"
+       fi
+       AC_MSG_RESULT([$temp_result])
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       AC_MSG_CHECKING([for libOpenIPMIpthread LDFLAGS])
+       temp_result="`$PKG_CONFIG --libs OpenIPMIpthread`"
+       if test "$?" = "0"
+       then
+               with_libopenipmipthread_ldflags="$temp_result"
+       else
+               with_libopenipmipthread="no ($PKG_CONFIG --libs OpenIPMIpthread failed)"
+               temp_result="$PKG_CONFIG --libs OpenIPMIpthread failed"
+       fi
+       AC_MSG_RESULT([$temp_result])
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libopenipmipthread_cflags"
+
+       AC_CHECK_HEADERS(OpenIPMI/ipmi_smi.h,
+                        [with_libopenipmipthread="yes"],
+                        [with_libopenipmipthread="no (OpenIPMI/ipmi_smi.h not found)"],
+[#include <OpenIPMI/ipmiif.h>
+#include <OpenIPMI/ipmi_err.h>
+#include <OpenIPMI/ipmi_posix.h>
+#include <OpenIPMI/ipmi_conn.h>
+])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       BUILD_WITH_OPENIPMI_CFLAGS="$with_libopenipmipthread_cflags"
+       BUILD_WITH_OPENIPMI_LIBS="$with_libopenipmipthread_ldflags"
+       AC_SUBST(BUILD_WITH_OPENIPMI_CFLAGS)
+       AC_SUBST(BUILD_WITH_OPENIPMI_LIBS)
+fi
+# }}}
+
+# --with-libatasmart {{{
+with_libatasmart_cppflags=""
+with_libatasmart_ldflags=""
+AC_ARG_WITH(libatasmart, [AS_HELP_STRING([--with-libatasmart@<:@=PREFIX@:>@], [Path to libatasmart.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libatasmart_cppflags="-I$withval/include"
+               with_libatasmart_ldflags="-L$withval/lib"
+               with_libatasmart="yes"
+       else
+               with_libatasmart="$withval"
+       fi
+],
+[
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libatasmart="yes"
+       else
+               with_libatasmart="no (Linux only library)"
+       fi
+])
+if test "x$with_libatasmart" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+
+       AC_CHECK_HEADERS(atasmart.h, [with_libatasmart="yes"], [with_libatasmart="no (atasmart.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+       LDFLAGS="$LDFLAGS $with_libatasmart_ldflags"
+
+       AC_CHECK_LIB(atasmart, sk_disk_open, [with_libatasmart="yes"], [with_libatasmart="no (Symbol 'sk_disk_open' not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+       BUILD_WITH_LIBATASMART_CPPFLAGS="$with_libatasmart_cppflags"
+       BUILD_WITH_LIBATASMART_LDFLAGS="$with_libatasmart_ldflags"
+       BUILD_WITH_LIBATASMART_LIBS="-latasmart"
+       AC_SUBST(BUILD_WITH_LIBATASMART_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBATASMART_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBATASMART_LIBS)
+       AC_DEFINE(HAVE_LIBATASMART, 1, [Define if libatasmart is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBATASMART, test "x$with_libatasmart" = "xyes")
+# }}}
+
+PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
+               [with_libnotify="yes"],
+               [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
+                        with_libnotify="no"
+                else
+                        with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"
+                fi])
+
+# Check for enabled/disabled features
+#
+
+# AC_COLLECTD(name, enable/disable, info-text, feature/module)
+# ------------------------------------------------------------
+dnl
+m4_define([my_toupper], [m4_translit([$1], m4_defn([m4_cr_letters]), m4_defn([m4_cr_LETTERS]))])
+dnl
+AC_DEFUN(
+       [AC_COLLECTD],
+       [
+       m4_if([$1], [], [AC_FATAL([AC_COLLECTD([$1], [$2], [$3], [$4]): 1st argument must not be empty])])dnl
+       m4_if(
+               [$2],
+               [enable],
+               [dnl
+               m4_define([EnDis],[disabled])dnl
+               m4_define([YesNo],[no])dnl
+               ],dnl
+               [m4_if(
+                       [$2],
+                       [disable],
+                       [dnl
+                       m4_define([EnDis],[enabled])dnl
+                       m4_define([YesNo],[yes])dnl
+                       ],
+                       [dnl
+                       AC_FATAL([AC_COLLECTD([$1], [$2], [$3], [$4]): 2nd argument must be either enable or disable])dnl
+                       ]dnl
+               )]dnl
+       )dnl
+       m4_if([$3], [feature], [],
+               [m4_if(
+                       [$3], [module], [],
+                       [dnl
+                       AC_FATAL([AC_COLLECTD([$1], [$2], [$3], [$4]): 3rd argument must be either feature or disable])dnl
+                       ]dnl
+               )]dnl
+       )dnl
+       AC_ARG_ENABLE(
+               [$1],
+               AS_HELP_STRING([--$2-$1], [$2 $4 (EnDis by def)]),
+               [],
+               enable_$1='[YesNo]'dnl
+       )# AC_ARG_ENABLE
+if test "x$enable_$1" = "xno"
+then
+       collectd_$1=0
+else
+       if test "x$enable_$1" = "xyes"
+       then
+               collectd_$1=1
+       else
+               AC_MSG_NOTICE([please specify either --enable-$1 or --disable-$1; enabling $1.])
+               collectd_$1=1
+               enable_$1='yes'
+       fi
+fi
+       AC_DEFINE_UNQUOTED([COLLECT_]my_toupper([$1]), [$collectd_$1], [wether or not to enable $3 $4])
+       AM_CONDITIONAL([BUILD_]my_toupper([$3])[_]my_toupper([$1]), [test "x$enable_$1" = "xyes"])dnl
+       ]dnl
+)# AC_COLLECTD(name, enable/disable, info-text, feature/module)
+
+# AC_PLUGIN(name, default, info)
+# ------------------------------------------------------------
+dnl
+AC_DEFUN(
+  [AC_PLUGIN],
+  [
+    enable_plugin="no"
+    force="no"
+    AC_ARG_ENABLE([$1], AS_HELP_STRING([--enable-$1],[$3]),
+    [
+     if test "x$enableval" = "xyes"
+     then
+            enable_plugin="yes"
+     else if test "x$enableval" = "xforce"
+     then
+            enable_plugin="yes"
+            force="yes"
+     else
+            enable_plugin="no (disabled on command line)"
+     fi; fi
+    ],
+    [
+        if test "x$enable_all_plugins" = "xauto"
+        then
+            if test "x$2" = "xyes"
+            then
+                    enable_plugin="yes"
+            else
+                    enable_plugin="no"
+            fi
+        else
+            enable_plugin="$enable_all_plugins"
+        fi
+    ])
+    if test "x$enable_plugin" = "xyes"
+    then
+           if test "x$2" = "xyes" || test "x$force" = "xyes"
+           then
+                   AC_DEFINE([HAVE_PLUGIN_]my_toupper([$1]), 1, [Define to 1 if the $1 plugin is enabled.])
+                   if test "x$2" != "xyes"
+                   then
+                           dependency_warning="yes"
+                   fi
+           else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
+                   dependency_error="yes"
+                   enable_plugin="no (dependency error)"
+           fi
+    fi
+    AM_CONDITIONAL([BUILD_PLUGIN_]my_toupper([$1]), test "x$enable_plugin" = "xyes")
+    enable_$1="$enable_plugin"
+  ]
+)# AC_PLUGIN(name, default, info)
+
+m4_divert_once([HELP_ENABLE], [
+collectd features:])
+# FIXME: Remove these calls to `AC_COLLECTD' and then remove that macro.
+AC_COLLECTD([debug],     [enable],  [feature], [debugging])
+AC_COLLECTD([daemon],    [disable], [feature], [daemon mode])
+AC_COLLECTD([getifaddrs],[enable],  [feature], [getifaddrs under Linux])
+
+dependency_warning="no"
+dependency_error="no"
+
+plugin_ascent="no"
+plugin_barometer="no"
+plugin_battery="no"
+plugin_bind="no"
+plugin_ceph="no"
+plugin_cgroups="no"
+plugin_conntrack="no"
+plugin_contextswitch="no"
+plugin_cpu="no"
+plugin_cpufreq="no"
+plugin_curl_json="no"
+plugin_curl_xml="no"
+plugin_df="no"
+plugin_disk="no"
+plugin_drbd="no"
+plugin_entropy="no"
+plugin_ethstat="no"
+plugin_fscache="no"
+plugin_interface="no"
+plugin_ipmi="no"
+plugin_ipvs="no"
+plugin_irq="no"
+plugin_load="no"
+plugin_log_logstash="no"
+plugin_memory="no"
+plugin_multimeter="no"
+plugin_nfs="no"
+plugin_numa="no"
+plugin_perl="no"
+plugin_processes="no"
+plugin_protocols="no"
+plugin_serial="no"
+plugin_swap="no"
+plugin_tape="no"
+plugin_tcpconns="no"
+plugin_ted="no"
+plugin_thermal="no"
+plugin_turbostat="no"
+plugin_uptime="no"
+plugin_users="no"
+plugin_virt="no"
+plugin_vmem="no"
+plugin_vserver="no"
+plugin_wireless="no"
+plugin_zfs_arc="no"
+plugin_zookeeper="no"
+
+# Linux
+if test "x$ac_system" = "xLinux"
+then
+       plugin_battery="yes"
+       plugin_conntrack="yes"
+       plugin_contextswitch="yes"
+       plugin_cgroups="yes"
+       plugin_cpu="yes"
+       plugin_cpufreq="yes"
+       plugin_disk="yes"
+       plugin_drbd="yes"
+       plugin_entropy="yes"
+       plugin_fscache="yes"
+       plugin_interface="yes"
+       plugin_ipc="yes"
+       plugin_irq="yes"
+       plugin_load="yes"
+       plugin_lvm="yes"
+       plugin_memory="yes"
+       plugin_nfs="yes"
+       plugin_numa="yes"
+       plugin_processes="yes"
+       plugin_protocols="yes"
+       plugin_serial="yes"
+       plugin_swap="yes"
+       plugin_tcpconns="yes"
+       plugin_thermal="yes"
+       plugin_uptime="yes"
+       plugin_vmem="yes"
+       plugin_vserver="yes"
+       plugin_wireless="yes"
+       plugin_zfs_arc="yes"
+
+       if test "x$have_linux_ip_vs_h" = "xyes" || test "x$have_net_ip_vs_h" = "xyes" || test "x$have_ip_vs_h" = "xyes"
+       then
+               plugin_ipvs="yes"
+       fi
+       if test "x$c_cv_have_usable_asm_msrindex_h" = "xyes" && test "x$have_cpuid_h" = "xyes"
+       then
+               plugin_turbostat="yes"
+       fi
+fi
+
+if test "x$ac_system" = "xOpenBSD"
+then
+       plugin_tcpconns="yes"
+fi
+
+# Mac OS X devices
+if test "x$with_libiokit" = "xyes"
+then
+       plugin_battery="yes"
+       plugin_disk="yes"
+fi
+
+# AIX
+
+if test "x$ac_system" = "xAIX"
+then
+        plugin_tcpconns="yes"
+        plugin_ipc="yes"
+fi
+
+# FreeBSD
+
+if test "x$ac_system" = "xFreeBSD"
+then
+        plugin_zfs_arc="yes"
+fi
+
+
+if test "x$with_perfstat" = "xyes"
+then
+       plugin_cpu="yes"
+       plugin_contextswitch="yes"
+       plugin_disk="yes"
+       plugin_memory="yes"
+       plugin_swap="yes"
+       plugin_interface="yes"
+       plugin_load="yes"
+       plugin_uptime="yes"
+fi
+
+if test "x$with_procinfo" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+# Solaris
+if test "x$with_kstat" = "xyes"
+then
+       plugin_nfs="yes"
+       plugin_processes="yes"
+       plugin_uptime="yes"
+       plugin_zfs_arc="yes"
+fi
+
+if test "x$with_devinfo$with_kstat" = "xyesyes"
+then
+       plugin_cpu="yes"
+       plugin_disk="yes"
+       plugin_interface="yes"
+       plugin_memory="yes"
+       plugin_tape="yes"
+fi
+
+# libi2c-dev
+with_libi2c="no"
+if test "x$ac_system" = "xLinux"
+then
+AC_CHECK_DECL(i2c_smbus_read_i2c_block_data,
+       [with_libi2c="yes"],
+       [with_libi2c="no (symbol i2c_smbus_read_i2c_block_data not found - have you installed libi2c-dev ?)"],
+       [[#include <stdlib.h>
+       #include <linux/i2c-dev.h>]])
+fi
+
+if test "x$with_libi2c" = "xyes"
+then
+       plugin_barometer="yes"
+fi
+
+
+# libstatgrab
+if test "x$with_libstatgrab" = "xyes"
+then
+       plugin_cpu="yes"
+       plugin_disk="yes"
+       plugin_interface="yes"
+       plugin_load="yes"
+       plugin_memory="yes"
+       plugin_swap="yes"
+       plugin_users="yes"
+fi
+
+if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes"
+then
+       plugin_ascent="yes"
+       if test "x$have_strptime" = "xyes"
+       then
+               plugin_bind="yes"
+       fi
+fi
+
+if test "x$with_libopenipmipthread" = "xyes"
+then
+       plugin_ipmi="yes"
+fi
+
+if test "x$with_libcurl" = "xyes" && test "x$with_libyajl" = "xyes"
+then
+       plugin_curl_json="yes"
+fi
+
+if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes"
+then
+       plugin_curl_xml="yes"
+fi
+
+if test "x$with_libyajl" = "xyes"
+then
+       plugin_ceph="yes"
+fi
+
+if test "x$have_processor_info" = "xyes"
+then
+       plugin_cpu="yes"
+fi
+if test "x$have_sysctl" = "xyes"
+then
+       plugin_cpu="yes"
+       plugin_memory="yes"
+       plugin_uptime="yes"
+       if test "x$ac_system" = "xDarwin"
+       then
+               plugin_swap="yes"
+       fi
+fi
+if test "x$have_sysctlbyname" = "xyes"
+then
+       plugin_contextswitch="yes"
+       plugin_cpu="yes"
+       plugin_memory="yes"
+       plugin_tcpconns="yes"
+fi
+
+# Df plugin: Check if we know how to determine mount points first.
+#if test "x$have_listmntent" = "xyes"; then
+#      plugin_df="yes"
+#fi
+if test "x$have_getvfsstat" = "xyes" || test "x$have_getfsstat" = "xyes"
+then
+       plugin_df="yes"
+fi
+if test "x$c_cv_have_two_getmntent" = "xyes" || test "x$have_getmntent" = "xgen" || test "x$have_getmntent" = "xsun"
+then
+       plugin_df="yes"
+fi
+#if test "x$have_getmntent" = "xseq"
+#then
+#      plugin_df="yes"
+#fi
+if test "x$c_cv_have_one_getmntent" = "xyes"
+then
+       plugin_df="yes"
+fi
+
+# Df plugin: Check if we have either `statfs' or `statvfs' second.
+if test "x$plugin_df" = "xyes"
+then
+       plugin_df="no"
+       if test "x$have_statfs" = "xyes"
+       then
+               plugin_df="yes"
+       fi
+       if test "x$have_statvfs" = "xyes"
+       then
+               plugin_df="yes"
+       fi
+fi
+
+if test "x$have_linux_sockios_h$have_linux_ethtool_h" = "xyesyes"
+then
+       plugin_ethstat="yes"
+fi
+
+if test "x$have_getifaddrs" = "xyes"
+then
+       plugin_interface="yes"
+fi
+
+if test "x$have_getloadavg" = "xyes"
+then
+       plugin_load="yes"
+fi
+
+if test "x$with_libyajl" = "xyes"
+then
+       plugin_log_logstash="yes"
+fi
+
+if test "x$c_cv_have_libperl$c_cv_have_perl_ithreads" = "xyesyes"
+then
+       plugin_perl="yes"
+fi
+
+# Mac OS X memory interface
+if test "x$have_host_statistics" = "xyes"
+then
+       plugin_memory="yes"
+fi
+
+if test "x$have_termios_h" = "xyes"
+then
+       if test "x$ac_system" != "xAIX"
+       then
+               plugin_multimeter="yes"
+       fi
+       plugin_ted="yes"
+fi
+
+if test "x$have_thread_info" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+if test "x$with_kvm_getprocs" = "xyes" && test "x$have_struct_kinfo_proc_freebsd" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+if test "x$with_kvm_getprocs" = "xyes" && test "x$have_struct_kinfo_proc_openbsd" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
+if test "x$with_kvm_getswapinfo" = "xyes"
+then
+       plugin_swap="yes"
+fi
+
+if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_two_args" = "xyes"
+then
+       plugin_swap="yes"
+fi
+
+if test "x$with_kvm_openfiles$with_kvm_nlist" = "xyesyes"
+then
+       plugin_tcpconns="yes"
+fi
+
+if test "x$have_getutent" = "xyes"
+then
+       plugin_users="yes"
+fi
+if test "x$have_getutxent" = "xyes"
+then
+       plugin_users="yes"
+fi
+
+if test "x$with_libxml2" = "xyes" && test "x$with_libvirt" = "xyes"
+then
+       plugin_virt="yes"
+fi
+
+
+m4_divert_once([HELP_ENABLE], [
+collectd plugins:])
+
+AC_ARG_ENABLE([all-plugins],
+               AS_HELP_STRING([--enable-all-plugins],[enable all plugins (auto by def)]),
+               [
+                if test "x$enableval" = "xyes"
+                then
+                        enable_all_plugins="yes"
+                else if test "x$enableval" = "xauto"
+                then
+                        enable_all_plugins="auto"
+                else
+                        enable_all_plugins="no"
+                fi; fi
+               ],
+               [enable_all_plugins="auto"])
+
+m4_divert_once([HELP_ENABLE], [])
+
+AC_PLUGIN([aggregation], [yes],                [Aggregation plugin])
+AC_PLUGIN([amqp],        [$with_librabbitmq],  [AMQP output plugin])
+AC_PLUGIN([apache],      [$with_libcurl],      [Apache httpd statistics])
+AC_PLUGIN([apcups],      [yes],                [Statistics of UPSes by APC])
+AC_PLUGIN([apple_sensors], [$with_libiokit],   [Apple's hardware sensors])
+AC_PLUGIN([aquaero],     [$with_libaquaero5],  [Aquaero's hardware sensors])
+AC_PLUGIN([ascent],      [$plugin_ascent],     [AscentEmu player statistics])
+AC_PLUGIN([barometer],   [$plugin_barometer],  [Barometer sensor on I2C])
+AC_PLUGIN([battery],     [$plugin_battery],    [Battery statistics])
+AC_PLUGIN([bind],        [$plugin_bind],       [ISC Bind nameserver statistics])
+AC_PLUGIN([ceph],        [$plugin_ceph],       [Ceph daemon statistics])
+AC_PLUGIN([conntrack],   [$plugin_conntrack],  [nf_conntrack statistics])
+AC_PLUGIN([contextswitch], [$plugin_contextswitch], [context switch statistics])
+AC_PLUGIN([cpufreq],     [$plugin_cpufreq],    [CPU frequency statistics])
+AC_PLUGIN([cpu],         [$plugin_cpu],        [CPU usage statistics])
+AC_PLUGIN([csv],         [yes],                [CSV output plugin])
+AC_PLUGIN([curl],        [$with_libcurl],      [CURL generic web statistics])
+AC_PLUGIN([curl_json],   [$plugin_curl_json],    [CouchDB statistics])
+AC_PLUGIN([curl_xml],   [$plugin_curl_xml],    [CURL generic xml statistics])
+AC_PLUGIN([cgroups],     [$plugin_cgroups],    [CGroups CPU usage accounting])
+AC_PLUGIN([dbi],         [$with_libdbi],       [General database statistics])
+AC_PLUGIN([df],          [$plugin_df],         [Filesystem usage statistics])
+AC_PLUGIN([disk],        [$plugin_disk],       [Disk usage statistics])
+AC_PLUGIN([drbd],        [$plugin_drbd],       [DRBD statistics])
+AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
+AC_PLUGIN([email],       [yes],                [EMail statistics])
+AC_PLUGIN([entropy],     [$plugin_entropy],    [Entropy statistics])
+AC_PLUGIN([ethstat],     [$plugin_ethstat],    [Stats from NIC driver])
+AC_PLUGIN([exec],        [yes],                [Execution of external programs])
+AC_PLUGIN([fhcount],     [yes],                [File handles statistics])
+AC_PLUGIN([filecount],   [yes],                [Count files in directories])
+AC_PLUGIN([fscache],     [$plugin_fscache],    [fscache statistics])
+AC_PLUGIN([gmond],       [$with_libganglia],   [Ganglia plugin])
+AC_PLUGIN([hddtemp],     [yes],                [Query hddtempd])
+AC_PLUGIN([interface],   [$plugin_interface],  [Interface traffic statistics])
+AC_PLUGIN([ipc],         [$plugin_ipc],        [IPC statistics])
+AC_PLUGIN([ipmi],        [$plugin_ipmi],       [IPMI sensor statistics])
+AC_PLUGIN([iptables],    [$with_libiptc],      [IPTables rule counters])
+AC_PLUGIN([ipvs],        [$plugin_ipvs],       [IPVS connection statistics])
+AC_PLUGIN([irq],         [$plugin_irq],        [IRQ statistics])
+AC_PLUGIN([java],        [$with_java],         [Embed the Java Virtual Machine])
+AC_PLUGIN([load],        [$plugin_load],       [System load])
+AC_PLUGIN([logfile],     [yes],                [File logging plugin])
+AC_PLUGIN([log_logstash], [$plugin_log_logstash], [Logstash json_event compatible logging])
+AC_PLUGIN([lpar],        [$with_perfstat],     [AIX logical partitions statistics])
+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])
+AC_PLUGIN([match_regex], [yes],                [The regex match])
+AC_PLUGIN([match_timediff], [yes],             [The timediff match])
+AC_PLUGIN([match_value], [yes],                [The value match])
+AC_PLUGIN([mbmon],       [yes],                [Query mbmond])
+AC_PLUGIN([md],          [$have_linux_raid_md_u_h], [md (Linux software RAID) devices])
+AC_PLUGIN([memcachec],   [$with_libmemcached], [memcachec statistics])
+AC_PLUGIN([memcached],   [yes],                [memcached statistics])
+AC_PLUGIN([memory],      [$plugin_memory],     [Memory usage])
+AC_PLUGIN([mic],         [$with_mic],          [Intel Many Integrated Core stats])
+AC_PLUGIN([modbus],      [$with_libmodbus],    [Modbus plugin])
+AC_PLUGIN([multimeter],  [$plugin_multimeter], [Read multimeter values])
+AC_PLUGIN([mysql],       [$with_libmysql],     [MySQL statistics])
+AC_PLUGIN([netapp],      [$with_libnetapp],    [NetApp plugin])
+AC_PLUGIN([netlink],     [$with_libmnl],       [Enhanced Linux network statistics])
+AC_PLUGIN([network],     [yes],                [Network communication plugin])
+AC_PLUGIN([nfs],         [$plugin_nfs],        [NFS statistics])
+AC_PLUGIN([nginx],       [$with_libcurl],      [nginx statistics])
+AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
+AC_PLUGIN([notify_email], [$with_libesmtp],    [Email notifier])
+AC_PLUGIN([ntpd],        [yes],                [NTPd statistics])
+AC_PLUGIN([numa],        [$plugin_numa],       [NUMA virtual memory statistics])
+AC_PLUGIN([nut],         [$with_libupsclient], [Network UPS tools statistics])
+AC_PLUGIN([olsrd],       [yes],                [olsrd statistics])
+AC_PLUGIN([onewire],     [$with_libowcapi],    [OneWire sensor statistics])
+AC_PLUGIN([openldap],    [$with_libldap],      [OpenLDAP statistics])
+AC_PLUGIN([openvpn],     [yes],                [OpenVPN client statistics])
+AC_PLUGIN([oracle],      [$with_oracle],       [Oracle plugin])
+AC_PLUGIN([perl],        [$plugin_perl],       [Embed a Perl interpreter])
+AC_PLUGIN([pf],          [$have_net_pfvar_h],  [BSD packet filter (PF) statistics])
+# FIXME: Check for libevent, too.
+AC_PLUGIN([pinba],       [$have_protoc_c],     [Pinba statistics])
+AC_PLUGIN([ping],        [$with_liboping],     [Network latency statistics])
+AC_PLUGIN([postgresql],  [$with_libpq],        [PostgreSQL database statistics])
+AC_PLUGIN([powerdns],    [yes],                [PowerDNS statistics])
+AC_PLUGIN([processes],   [$plugin_processes],  [Process statistics])
+AC_PLUGIN([protocols],   [$plugin_protocols],  [Protocol (IP, TCP, ...) statistics])
+AC_PLUGIN([python],      [$with_python],       [Embed a Python interpreter])
+AC_PLUGIN([redis],       [$with_libhiredis],    [Redis plugin])
+AC_PLUGIN([routeros],    [$with_librouteros],  [RouterOS plugin])
+AC_PLUGIN([rrdcached],   [$librrd_rrdc_update], [RRDTool output plugin])
+AC_PLUGIN([rrdtool],     [$with_librrd],       [RRDTool output plugin])
+AC_PLUGIN([sensors],     [$with_libsensors],   [lm_sensors statistics])
+AC_PLUGIN([serial],      [$plugin_serial],     [serial port traffic])
+AC_PLUGIN([sigrok],      [$with_libsigrok],    [sigrok acquisition sources])
+AC_PLUGIN([smart],       [$with_libatasmart],  [SMART statistics])
+AC_PLUGIN([snmp],        [$with_libnetsnmp],   [SNMP querying plugin])
+AC_PLUGIN([statsd],      [yes],                [StatsD plugin])
+AC_PLUGIN([swap],        [$plugin_swap],       [Swap usage statistics])
+AC_PLUGIN([syslog],      [$have_syslog],       [Syslog logging plugin])
+AC_PLUGIN([table],       [yes],                [Parsing of tabular data])
+AC_PLUGIN([tail],        [yes],                [Parsing of logfiles])
+AC_PLUGIN([tail_csv],    [yes],                [Parsing of CSV files])
+AC_PLUGIN([tape],        [$plugin_tape],       [Tape drive statistics])
+AC_PLUGIN([target_notification], [yes],        [The notification target])
+AC_PLUGIN([target_replace], [yes],             [The replace target])
+AC_PLUGIN([target_scale],[yes],                [The scale target])
+AC_PLUGIN([target_set],  [yes],                [The set target])
+AC_PLUGIN([target_v5upgrade], [yes],           [The v5upgrade target])
+AC_PLUGIN([tcpconns],    [$plugin_tcpconns],   [TCP connection statistics])
+AC_PLUGIN([teamspeak2],  [yes],                [TeamSpeak2 server statistics])
+AC_PLUGIN([ted],         [$plugin_ted],        [Read The Energy Detective values])
+AC_PLUGIN([thermal],     [$plugin_thermal],    [Linux ACPI thermal zone statistics])
+AC_PLUGIN([threshold],   [yes],                [Threshold checking plugin])
+AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant],  [TokyoTyrant database statistics])
+AC_PLUGIN([turbostat],   [$plugin_turbostat],  [Advanced statistic on Intel cpu states])
+AC_PLUGIN([unixsock],    [yes],                [Unixsock communication plugin])
+AC_PLUGIN([uptime],      [$plugin_uptime],     [Uptime statistics])
+AC_PLUGIN([users],       [$plugin_users],      [User statistics])
+AC_PLUGIN([uuid],        [yes],                [UUID as hostname plugin])
+AC_PLUGIN([varnish],     [$with_libvarnish],   [Varnish cache statistics])
+AC_PLUGIN([virt],        [$plugin_virt],       [Virtual machine statistics])
+AC_PLUGIN([vmem],        [$plugin_vmem],       [Virtual memory statistics])
+AC_PLUGIN([vserver],     [$plugin_vserver],    [Linux VServer statistics])
+AC_PLUGIN([wireless],    [$plugin_wireless],   [Wireless statistics])
+AC_PLUGIN([write_graphite], [yes],             [Graphite / Carbon output plugin])
+AC_PLUGIN([write_http],  [$with_libcurl],      [HTTP output plugin])
+AC_PLUGIN([write_kafka],  [$with_librdkafka],  [Kafka output plugin])
+AC_PLUGIN([write_log], [yes],                  [Log output plugin])
+AC_PLUGIN([write_mongodb], [$with_libmongoc],  [MongoDB output plugin])
+AC_PLUGIN([write_redis], [$with_libhiredis],    [Redis output plugin])
+AC_PLUGIN([write_riemann], [$have_protoc_c],   [Riemann output plugin])
+AC_PLUGIN([write_sensu], [yes],                [Sensu output plugin])
+AC_PLUGIN([write_tsdb],  [yes],                [TSDB output plugin])
+AC_PLUGIN([xmms],        [$with_libxmms],      [XMMS statistics])
+AC_PLUGIN([zfs_arc],     [$plugin_zfs_arc],    [ZFS ARC statistics])
+AC_PLUGIN([zookeeper],   [yes],               [Zookeeper statistics])
+
+dnl Default configuration file
+# Load either syslog or logfile
+LOAD_PLUGIN_SYSLOG=""
+LOAD_PLUGIN_LOGFILE=""
+LOAD_PLUGIN_LOG_LOGSTASH=""
+
+AC_MSG_CHECKING([which default log plugin to load])
+default_log_plugin="none"
+if test "x$enable_syslog" = "xyes"
+then
+       default_log_plugin="syslog"
+else
+       LOAD_PLUGIN_SYSLOG="##"
+fi
+
+if test "x$enable_logfile" = "xyes"
+then
+       if test "x$default_log_plugin" = "xnone"
+       then
+               default_log_plugin="logfile"
+       else
+               LOAD_PLUGIN_LOGFILE="#"
+       fi
+else
+       LOAD_PLUGIN_LOGFILE="##"
+fi
+
+if test "x$enable_log_logstash" = "xyes"
+then
+  LOAD_PLUGIN_LOG_LOGSTASH="#"
+else
+  LOAD_PLUGIN_LOG_LOGSTASH="##"
+fi
+
+
+AC_MSG_RESULT([$default_log_plugin])
+
+AC_SUBST(LOAD_PLUGIN_SYSLOG)
+AC_SUBST(LOAD_PLUGIN_LOGFILE)
+AC_SUBST(LOAD_PLUGIN_LOG_LOGSTASH)
+
+DEFAULT_LOG_LEVEL="info"
+if test "x$enable_debug" = "xyes"
+then
+       DEFAULT_LOG_LEVEL="debug"
+fi
+AC_SUBST(DEFAULT_LOG_LEVEL)
+
+# Load only one of rrdtool, network, csv in the default config.
+LOAD_PLUGIN_RRDTOOL=""
+LOAD_PLUGIN_NETWORK=""
+LOAD_PLUGIN_CSV=""
+
+AC_MSG_CHECKING([which default write plugin to load])
+default_write_plugin="none"
+if test "x$enable_rrdtool" = "xyes"
+then
+       default_write_plugin="rrdtool"
+else
+       LOAD_PLUGIN_RRDTOOL="##"
+fi
+
+if test "x$enable_network" = "xyes"
+then
+       if test "x$default_write_plugin" = "xnone"
+       then
+               default_write_plugin="network"
+       else
+               LOAD_PLUGIN_NETWORK="#"
+       fi
+else
+       LOAD_PLUGIN_NETWORK="##"
+fi
+
+if test "x$enable_csv" = "xyes"
+then
+       if test "x$default_write_plugin" = "xnone"
+       then
+               default_write_plugin="csv"
+       else
+               LOAD_PLUGIN_CSV="#"
+       fi
+else
+       LOAD_PLUGIN_CSV="##"
+fi
+AC_MSG_RESULT([$default_write_plugin])
+
+AC_SUBST(LOAD_PLUGIN_RRDTOOL)
+AC_SUBST(LOAD_PLUGIN_NETWORK)
+AC_SUBST(LOAD_PLUGIN_CSV)
+
+dnl ip_vs.h
+if test "x$ac_system" = "xLinux" \
+       && test "x$have_linux_ip_vs_h$have_net_ip_vs_h$have_ip_vs_h" = "xnonono"
+then
+       enable_ipvs="$enable_ipvs (ip_vs.h not found)"
+fi
+
+if test "x$ip_vs_h_needs_kernel_cflags" = "xyes"
+then
+       enable_ipvs="$enable_ipvs (needs $KERNEL_CFLAGS)"
+fi
+
+dnl Perl bindings
+PERL_BINDINGS_OPTIONS="PREFIX=${prefix}"
+AC_ARG_WITH(perl-bindings, [AS_HELP_STRING([--with-perl-bindings@<:@=OPTIONS@:>@], [Options passed to "perl Makefile.PL".])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               PERL_BINDINGS_OPTIONS="$withval"
+               with_perl_bindings="yes"
+       else
+               with_perl_bindings="$withval"
+       fi
+],
+[
+       if test -n "$perl_interpreter"
+       then
+               with_perl_bindings="yes"
+       else
+               with_perl_bindings="no (no perl interpreter found)"
+       fi
+])
+if test "x$with_perl_bindings" = "xyes"
+then
+       PERL_BINDINGS="perl"
+else
+       PERL_BINDINGS=""
+fi
+AC_SUBST(PERL_BINDINGS)
+AC_SUBST(PERL_BINDINGS_OPTIONS)
+
+dnl libcollectdclient
+LCC_VERSION_MAJOR=`echo $PACKAGE_VERSION | cut -d'.' -f1`
+LCC_VERSION_MINOR=`echo $PACKAGE_VERSION | cut -d'.' -f2`
+LCC_VERSION_PATCH=`echo $PACKAGE_VERSION | cut -d'.' -f3`
+
+LCC_VERSION_EXTRA=`echo $PACKAGE_VERSION | cut -d'.' -f4-`
+
+LCC_VERSION_STRING="$LCC_VERSION_MAJOR.$LCC_VERSION_MINOR.$LCC_VERSION_PATCH"
+
+AC_SUBST(LCC_VERSION_MAJOR)
+AC_SUBST(LCC_VERSION_MINOR)
+AC_SUBST(LCC_VERSION_PATCH)
+AC_SUBST(LCC_VERSION_EXTRA)
+AC_SUBST(LCC_VERSION_STRING)
+
+AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
+
+AC_CONFIG_FILES([Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
+AC_OUTPUT
+
+if test "x$with_librrd" = "xyes" \
+       && test "x$librrd_threadsafe" != "xyes"
+then
+       with_librrd="yes (warning: librrd is not thread-safe)"
+fi
+
+if test "x$with_libperl" = "xyes"
+then
+       with_libperl="yes (version `$perl_interpreter -MConfig -e 'print $Config{version};'`)"
+else
+       enable_perl="no (needs libperl)"
+fi
+
+if test "x$enable_perl" = "xno" && test "x$c_cv_have_perl_ithreads" = "xno"
+then
+       enable_perl="no (libperl doesn't support ithreads)"
+fi
+
+if test "x$with_perl_bindings" = "xyes" \
+       && test "x$PERL_BINDINGS_OPTIONS" != "x"
+then
+       with_perl_bindings="yes ($PERL_BINDINGS_OPTIONS)"
+fi
+
+cat <<EOF;
+
+Configuration:
+  Libraries:
+    intel mic . . . . . . $with_mic
+    libaquaero5 . . . . . $with_libaquaero5
+    libatasmart . . . . . $with_libatasmart
+    libcurl . . . . . . . $with_libcurl
+    libdbi  . . . . . . . $with_libdbi
+    libesmtp  . . . . . . $with_libesmtp
+    libganglia  . . . . . $with_libganglia
+    libgcrypt . . . . . . $with_libgcrypt
+    libhal  . . . . . . . $with_libhal
+    libhiredis  . . . . . $with_libhiredis
+    libi2c-dev  . . . . . $with_libi2c
+    libiokit  . . . . . . $with_libiokit
+    libiptc . . . . . . . $with_libiptc
+    libjvm  . . . . . . . $with_java
+    libkstat  . . . . . . $with_kstat
+    libkvm  . . . . . . . $with_libkvm
+    libldap . . . . . . . $with_libldap
+    liblvm2app  . . . . . $with_liblvm2app
+    libmemcached  . . . . $with_libmemcached
+    libmnl  . . . . . . . $with_libmnl
+    libmodbus . . . . . . $with_libmodbus
+    libmongoc . . . . . . $with_libmongoc
+    libmysql  . . . . . . $with_libmysql
+    libnetapp . . . . . . $with_libnetapp
+    libnetsnmp  . . . . . $with_libnetsnmp
+    libnotify . . . . . . $with_libnotify
+    liboconfig  . . . . . $with_liboconfig
+    libopenipmi . . . . . $with_libopenipmipthread
+    liboping  . . . . . . $with_liboping
+    libowcapi . . . . . . $with_libowcapi
+    libpcap . . . . . . . $with_libpcap
+    libperfstat . . . . . $with_perfstat
+    libperl . . . . . . . $with_libperl
+    libpq . . . . . . . . $with_libpq
+    libpthread  . . . . . $with_libpthread
+    librabbitmq . . . . . $with_librabbitmq
+    librdkafka  . . . . . $with_librdkafka
+    librouteros . . . . . $with_librouteros
+    librrd  . . . . . . . $with_librrd
+    libsensors  . . . . . $with_libsensors
+    libsigrok   . . . . . $with_libsigrok
+    libstatgrab . . . . . $with_libstatgrab
+    libtokyotyrant  . . . $with_libtokyotyrant
+    libudev . . . . . . . $with_libudev
+    libupsclient  . . . . $with_libupsclient
+    libvarnish  . . . . . $with_libvarnish
+    libvirt . . . . . . . $with_libvirt
+    libxml2 . . . . . . . $with_libxml2
+    libxmms . . . . . . . $with_libxmms
+    libyajl . . . . . . . $with_libyajl
+    oracle  . . . . . . . $with_oracle
+    protobuf-c  . . . . . $have_protoc_c
+    python  . . . . . . . $with_python
+
+  Features:
+    daemon mode . . . . . $enable_daemon
+    debug . . . . . . . . $enable_debug
+
+  Bindings:
+    perl  . . . . . . . . $with_perl_bindings
+
+  Modules:
+    aggregation . . . . . $enable_aggregation
+    amqp    . . . . . . . $enable_amqp
+    apache  . . . . . . . $enable_apache
+    apcups  . . . . . . . $enable_apcups
+    apple_sensors . . . . $enable_apple_sensors
+    aquaero . . . . . . . $enable_aquaero
+    ascent  . . . . . . . $enable_ascent
+    barometer . . . . . . $enable_barometer
+    battery . . . . . . . $enable_battery
+    bind  . . . . . . . . $enable_bind
+    ceph  . . . . . . . . $enable_ceph
+    cgroups . . . . . . . $enable_cgroups
+    conntrack . . . . . . $enable_conntrack
+    contextswitch . . . . $enable_contextswitch
+    cpu . . . . . . . . . $enable_cpu
+    cpufreq . . . . . . . $enable_cpufreq
+    csv . . . . . . . . . $enable_csv
+    curl  . . . . . . . . $enable_curl
+    curl_json . . . . . . $enable_curl_json
+    curl_xml  . . . . . . $enable_curl_xml
+    dbi . . . . . . . . . $enable_dbi
+    df  . . . . . . . . . $enable_df
+    disk  . . . . . . . . $enable_disk
+    dns . . . . . . . . . $enable_dns
+    drbd  . . . . . . . . $enable_drbd
+    email . . . . . . . . $enable_email
+    entropy . . . . . . . $enable_entropy
+    ethstat . . . . . . . $enable_ethstat
+    exec  . . . . . . . . $enable_exec
+    fhcount . . . . . . . $enable_fhcount
+    filecount . . . . . . $enable_filecount
+    fscache . . . . . . . $enable_fscache
+    gmond . . . . . . . . $enable_gmond
+    hddtemp . . . . . . . $enable_hddtemp
+    interface . . . . . . $enable_interface
+    ipc . . . . . . . . . $enable_ipc
+    ipmi  . . . . . . . . $enable_ipmi
+    iptables  . . . . . . $enable_iptables
+    ipvs  . . . . . . . . $enable_ipvs
+    irq . . . . . . . . . $enable_irq
+    java  . . . . . . . . $enable_java
+    load  . . . . . . . . $enable_load
+    logfile . . . . . . . $enable_logfile
+    log_logstash  . . . . $enable_log_logstash
+    lpar  . . . . . . . . $enable_lpar
+    lvm . . . . . . . . . $enable_lvm
+    madwifi . . . . . . . $enable_madwifi
+    match_empty_counter . $enable_match_empty_counter
+    match_hashed  . . . . $enable_match_hashed
+    match_regex . . . . . $enable_match_regex
+    match_timediff  . . . $enable_match_timediff
+    match_value . . . . . $enable_match_value
+    mbmon . . . . . . . . $enable_mbmon
+    md  . . . . . . . . . $enable_md
+    memcachec . . . . . . $enable_memcachec
+    memcached . . . . . . $enable_memcached
+    memory  . . . . . . . $enable_memory
+    mic . . . . . . . . . $enable_mic
+    modbus  . . . . . . . $enable_modbus
+    multimeter  . . . . . $enable_multimeter
+    mysql . . . . . . . . $enable_mysql
+    netapp  . . . . . . . $enable_netapp
+    netlink . . . . . . . $enable_netlink
+    network . . . . . . . $enable_network
+    nfs . . . . . . . . . $enable_nfs
+    nginx . . . . . . . . $enable_nginx
+    notify_desktop  . . . $enable_notify_desktop
+    notify_email  . . . . $enable_notify_email
+    ntpd  . . . . . . . . $enable_ntpd
+    numa  . . . . . . . . $enable_numa
+    nut . . . . . . . . . $enable_nut
+    olsrd . . . . . . . . $enable_olsrd
+    onewire . . . . . . . $enable_onewire
+    openldap  . . . . . . $enable_openldap
+    openvpn . . . . . . . $enable_openvpn
+    oracle  . . . . . . . $enable_oracle
+    perl  . . . . . . . . $enable_perl
+    pf  . . . . . . . . . $enable_pf
+    pinba . . . . . . . . $enable_pinba
+    ping  . . . . . . . . $enable_ping
+    postgresql  . . . . . $enable_postgresql
+    powerdns  . . . . . . $enable_powerdns
+    processes . . . . . . $enable_processes
+    protocols . . . . . . $enable_protocols
+    python  . . . . . . . $enable_python
+    redis . . . . . . . . $enable_redis
+    routeros  . . . . . . $enable_routeros
+    rrdcached . . . . . . $enable_rrdcached
+    rrdtool . . . . . . . $enable_rrdtool
+    sensors . . . . . . . $enable_sensors
+    serial  . . . . . . . $enable_serial
+    sigrok  . . . . . . . $enable_sigrok
+    smart . . . . . . . . $enable_smart
+    snmp  . . . . . . . . $enable_snmp
+    statsd  . . . . . . . $enable_statsd
+    swap  . . . . . . . . $enable_swap
+    syslog  . . . . . . . $enable_syslog
+    table . . . . . . . . $enable_table
+    tail_csv  . . . . . . $enable_tail_csv
+    tail  . . . . . . . . $enable_tail
+    tape  . . . . . . . . $enable_tape
+    target_notification . $enable_target_notification
+    target_replace  . . . $enable_target_replace
+    target_scale  . . . . $enable_target_scale
+    target_set  . . . . . $enable_target_set
+    target_v5upgrade  . . $enable_target_v5upgrade
+    tcpconns  . . . . . . $enable_tcpconns
+    teamspeak2  . . . . . $enable_teamspeak2
+    ted . . . . . . . . . $enable_ted
+    thermal . . . . . . . $enable_thermal
+    threshold . . . . . . $enable_threshold
+    tokyotyrant . . . . . $enable_tokyotyrant
+    turbostat . . . . . . $enable_turbostat
+    unixsock  . . . . . . $enable_unixsock
+    uptime  . . . . . . . $enable_uptime
+    users . . . . . . . . $enable_users
+    uuid  . . . . . . . . $enable_uuid
+    varnish . . . . . . . $enable_varnish
+    virt  . . . . . . . . $enable_virt
+    vmem  . . . . . . . . $enable_vmem
+    vserver . . . . . . . $enable_vserver
+    wireless  . . . . . . $enable_wireless
+    write_graphite  . . . $enable_write_graphite
+    write_http  . . . . . $enable_write_http
+    write_kafka . . . . . $enable_write_kafka
+    write_log . . . . . . $enable_write_log
+    write_mongodb . . . . $enable_write_mongodb
+    write_redis . . . . . $enable_write_redis
+    write_riemann . . . . $enable_write_riemann
+    write_sensu . . . . . $enable_write_sensu
+    write_tsdb  . . . . . $enable_write_tsdb
+    xmms  . . . . . . . . $enable_xmms
+    zfs_arc . . . . . . . $enable_zfs_arc
+    zookeeper . . . . . . $enable_zookeeper
+
+EOF
+
+if test "x$dependency_error" = "xyes"; then
+       AC_MSG_ERROR("Some plugins are missing dependencies - see the summary above for details")
+fi
+
+if test "x$dependency_warning" = "xyes"; then
+       AC_MSG_WARN("Some plugins seem to have missing dependencies but have been enabled forcibly - see the summary above for details")
+fi
+
+# vim: set fdm=marker :
diff --git a/contrib/GenericJMX.conf b/contrib/GenericJMX.conf
new file mode 100644 (file)
index 0000000..1d3fe56
--- /dev/null
@@ -0,0 +1,245 @@
+# contrib/GenericJMX.conf
+# -----------------------
+#
+# This is an example config file for the ‘GenericJMX’ plugin, a plugin written
+# in Java to receive values via the “Java Management Extensions” (JMX). The
+# plugin can be found in the
+#   bindings/java/org/collectd/java/
+# directory of the source distribution.
+#
+# This sample config defines a couple of <MBean /> blocks which query MBeans
+# provided by the JVM itself, i. e. which should be available for all Java
+# processes. The following MBean blocks are defined:
+#
+#   +-------------------+------------------------------------------------+
+#   ! Name              ! Description                                    !
+#   +-------------------+------------------------------------------------+
+#   ! classes           ! Number of classes being loaded.                !
+#   ! compilation       ! Time spent by the JVM compiling or optimizing. !
+#   ! garbage_collector ! Number of garbage collections and time spent.  !
+#   ! memory            ! Generic heap/nonheap memory usage.             !
+#   ! memory_pool       ! Memory usage by memory pool.                   !
+#   +-------------------+------------------------------------------------+
+#
+<Plugin "java">
+  LoadPlugin "org.collectd.java.GenericJMX"
+
+  <Plugin "GenericJMX">
+    ################
+    # MBean blocks #
+    ################
+    # Number of classes being loaded.
+    <MBean "classes">
+      ObjectName "java.lang:type=ClassLoading"
+      #InstancePrefix ""
+      #InstanceFrom ""
+
+      <Value>
+        Type "gauge"
+        InstancePrefix "loaded_classes"
+        #InstanceFrom ""
+        Table false
+        Attribute "LoadedClassCount"
+      </Value>
+    </MBean>
+
+    # Time spent by the JVM compiling or optimizing.
+    <MBean "compilation">
+      ObjectName "java.lang:type=Compilation"
+      #InstancePrefix ""
+      #InstanceFrom ""
+
+      <Value>
+        Type "total_time_in_ms"
+        InstancePrefix "compilation_time"
+        #InstanceFrom ""
+        Table false
+        Attribute "TotalCompilationTime"
+      </Value>
+    </MBean>
+
+    # Garbage collector information
+    <MBean "garbage_collector">
+      ObjectName "java.lang:type=GarbageCollector,*"
+      InstancePrefix "gc-"
+      InstanceFrom "name"
+
+      <Value>
+        Type "invocations"
+        #InstancePrefix ""
+        #InstanceFrom ""
+        Table false
+        Attribute "CollectionCount"
+      </Value>
+
+      <Value>
+        Type "total_time_in_ms"
+        InstancePrefix "collection_time"
+        #InstanceFrom ""
+        Table false
+        Attribute "CollectionTime"
+      </Value>
+
+#      # Not that useful, therefore commented out.
+#      <Value>
+#        Type "threads"
+#        #InstancePrefix ""
+#        #InstanceFrom ""
+#        Table false
+#        # Demonstration how to access composite types
+#        Attribute "LastGcInfo.GcThreadCount"
+#      </Value>
+    </MBean>
+
+    ######################################
+    # Define the "jmx_memory" type as:   #
+    #   jmx_memory  value:GAUGE:0:U      #
+    # See types.db(5) for details.       #
+    ######################################
+
+    # Generic heap/nonheap memory usage.
+    <MBean "memory">
+      ObjectName "java.lang:type=Memory"
+      #InstanceFrom ""
+      InstancePrefix "memory"
+
+      # Creates four values: committed, init, max, used
+      <Value>
+        Type "jmx_memory"
+        #InstancePrefix ""
+        #InstanceFrom ""
+        Table true
+        Attribute "HeapMemoryUsage"
+        InstancePrefix "heap-"
+      </Value>
+
+      # Creates four values: committed, init, max, used
+      <Value>
+        Type "jmx_memory"
+        #InstancePrefix ""
+        #InstanceFrom ""
+        Table true
+        Attribute "NonHeapMemoryUsage"
+        InstancePrefix "nonheap-"
+      </Value>
+    </MBean>
+
+    # Memory usage by memory pool.
+    <MBean "memory_pool">
+      ObjectName "java.lang:type=MemoryPool,*"
+      InstancePrefix "memory_pool-"
+      InstanceFrom "name"
+
+      <Value>
+        Type "jmx_memory"
+        #InstancePrefix ""
+        #InstanceFrom ""
+        Table true
+        Attribute "Usage"
+      </Value>
+    </MBean>
+
+    ### MBeans by Catalina / Tomcat ###
+    # The global request processor (summary for each request processor)
+    <MBean "catalina/global_request_processor">
+      ObjectName "Catalina:type=GlobalRequestProcessor,*"
+      InstancePrefix "request_processor-"
+      InstanceFrom "name"
+
+      <Value>
+        Type "io_octets"
+        InstancePrefix "global"
+        #InstanceFrom ""
+        Table false
+        Attribute "bytesReceived"
+        Attribute "bytesSent"
+      </Value>
+
+      <Value>
+        Type "total_requests"
+        InstancePrefix "global"
+        #InstanceFrom ""
+        Table false
+        Attribute "requestCount"
+      </Value>
+
+      <Value>
+        Type "total_time_in_ms"
+        InstancePrefix "global-processing"
+        #InstanceFrom ""
+        Table false
+        Attribute "processingTime"
+      </Value>
+    </MBean>
+
+    # Details for each  request processor
+    <MBean "catalina/detailed_request_processor">
+      ObjectName "Catalina:type=RequestProcessor,*"
+      InstancePrefix "request_processor-"
+      InstanceFrom "worker"
+
+      <Value>
+        Type "io_octets"
+        #InstancePrefix ""
+        InstanceFrom "name"
+        Table false
+        Attribute "bytesReceived"
+        Attribute "bytesSent"
+      </Value>
+
+      <Value>
+        Type "total_requests"
+        #InstancePrefix ""
+        InstanceFrom "name"
+        Table false
+        Attribute "requestCount"
+      </Value>
+
+      <Value>
+        Type "total_time_in_ms"
+        InstancePrefix "processing-"
+        InstanceFrom "name"
+        Table false
+        Attribute "processingTime"
+      </Value>
+    </MBean>
+
+    # Thread pool
+    <MBean "catalina/thread_pool">
+      ObjectName "Catalina:type=ThreadPool,*"
+      InstancePrefix "request_processor-"
+      InstanceFrom "name"
+
+      <Value>
+        Type "threads"
+        InstancePrefix "total"
+        #InstanceFrom ""
+        Table false
+        Attribute "currentThreadCount"
+      </Value>
+
+      <Value>
+        Type "threads"
+        InstancePrefix "running"
+        #InstanceFrom ""
+        Table false
+        Attribute "currentThreadsBusy"
+      </Value>
+    </MBean>
+
+    #####################
+    # Connection blocks #
+    #####################
+    <Connection>
+      ServiceURL "service:jmx:rmi:///jndi/rmi://localhost:17264/jmxrmi"
+      User "monitorRole"
+      Password "queeZie1"
+      Host "localhost"
+      Collect "classes"
+      Collect "compilation"
+      Collect "garbage_collector"
+      Collect "memory"
+      Collect "memory_pool"
+    </Connection>
+  </Plugin>
+</Plugin>
diff --git a/contrib/README b/contrib/README
new file mode 100644 (file)
index 0000000..1ebf1f1
--- /dev/null
@@ -0,0 +1,108 @@
+The files in this directory may be used to perform common tasks that aren't
+exactly `collectd's job. They may or may not require in-depth knowledge of RRD
+files and/or `collectd's inner workings. Use at your own risk.
+
+add_rra.sh
+----------
+  Before version 3.9.0 collectd used to create a different set of RRAs. The
+most detailed of these old RRAs had a one minute resolution. This script can
+be used to add three more RRAs: minimum, maximum and average with a ten second
+resolution and 2200 rows (~6 hours). This will make hourly statistics much more
+interesting. Please note that no sanity- checking whatsoever is performed. You
+can seriously fuck up your RRD files if you don't know what you're doing.
+
+collectd-network.py
+-------------------
+  This Python module by Adrian Perez implements the collectd network protocol
+in pure Python. It currently supports to receive data and notifications from
+collectd.
+
+collectd-unixsock.py
+--------------------
+  This Python module by Clay Loveless provides an interface to collect's
+unixsock plugin.
+
+collectd2html.pl
+----------------
+  This script by Vincent Stehlé will search for RRD files in
+`/var/lib/collectd/' and generate an HTML file and a directory containing
+several PNG files which are graphs of the RRD files found.
+
+collection.cgi
+--------------
+  Sample CGI script that creates graphs on the fly. The Perl modules `RRDs'
+(Debian package `librrds-perl'), `URI:Escape' (package liburi-perl),
+`HTML::Entities' (package libhtml-parser-perl) and a CGI capable web server
+(e.g. apache2 or boa) are needed. Simply install the script to a place where
+the webserver will treat it as a CGI script (/usr/lib/cgi-bin/ by default) and
+visit that page in a browser (http://localhost/cgi-bin/collection.cgi by
+default). Please refer to your webserver's documentation for more details.
+
+  Starting with version 4, collection.cgi requires a small config file, which
+should look something like this:
+
+  datadir: "/var/lib/collectd/rrd/"
+  libdir: "/usr/lib/collectd/"
+
+exec-munin.px
+-------------
+  Script to be used with the exec-plugin (see collectd-exec(5) for details)
+which executes munin plugins, parses the output and translates it to a format
+the exec-plugin understands. The features are limited - changing the munin
+plugins to use the output format understood by the exec-plugin is recommended.
+See the embedded POD documentation for more details:
+ $ perldoc contrib/exec-munin.px
+
+exec-smartctl
+-------------
+  Sample script for the exec plugin. Please refer to the documentation in the
+file - you will have to adapt it to your needs anyway.
+
+extractDS.px
+------------
+  Creates a new RRD-file with only one data-source (DS) of the source-RRD-
+file. That is very handy when you realise that you have bundled up DSes in one
+RRD-file that should have been in multiple RRD-files instead. Is is used by
+`migrate-3-4.px' to split up the cpu-, nfs-, swap-files and possibly others.
+
+fedora/
+-------
+  Init-script and Spec-file that can be used when creating RPM-packages for
+Fedora.
+
+GenericJMX.conf
+---------------
+  Example configuration file for the ‘GenericJMX’ Java plugin. Please read the
+documentation at the beginning of the file for more details.
+
+migrate-3-4.px
+--------------
+  Migration-script to ease the switch from version 3 to version 4. Many
+RRD-files are expected in a different place, some have been changed (DSes have
+been renamed) and others have bee split up into multiple files. This script
+prints a bash-script to STDOUT which should do most of the work for you. You
+may still need to do some things by hand, read `README.migration' for more
+details.
+
+redhat/
+-------
+  Spec-file and affiliated files to build an RedHat RPM package of collectd.
+
+snmp-data.conf
+--------------
+  Sample configuration for the SNMP plugin. This config includes a few standard
+<Data ..> definitions that you can include in your own config using the
+`Include' statement (available since version 4.2.0). The config includes some
+data that is defined in the IF-MIB, e. g. octet or packet counters, UPS-MIB and
+whatever people have send in. If you have some more definitions please send
+them in, so others can profit from it.
+
+solaris-smf
+-----------
+  Manifest file for the Solaris SMF system and detailed information on how to
+register collectd as a service with this system.
+
+collectd.service
+----------------
+  Service file for systemd. Please ship this file as
+  /lib/systemd/system/collectd.service in any linux package of collectd.
diff --git a/contrib/SpamAssassin/Collectd.pm b/contrib/SpamAssassin/Collectd.pm
new file mode 100644 (file)
index 0000000..1edcfc6
--- /dev/null
@@ -0,0 +1,218 @@
+#!/usr/bin/perl
+
+=head1 NAME
+
+Collectd - plugin for filling collectd with stats 
+
+=head1 INSTALLATION
+
+Just copy Collectd.pm into your SpamAssassin Plugin path 
+(e.g /usr/share/perl5/Mail/SpamAssassin/Plugin/) and
+add a loadplugin call into your init.pre file. 
+
+=head1 SYNOPSIS
+
+  loadplugin    Mail::SpamAssassin::Plugin::Collectd
+
+=head1 USER SETTINGS
+
+=over 4
+
+=item collectd_socket [ socket path ]      (default: /var/run/collectd-email)
+
+Where the collectd socket is
+
+=cut 
+
+=item collectd_buffersize [ size ] (default: 256) 
+
+the email plugin uses a fixed buffer, if a line exceeds this size
+it has to be continued in another line. (This is of course handled internally)
+If you have changed this setting please get it in sync with the SA Plugin
+config. 
+
+=cut 
+
+=item collectd_timeout [ sec ] (default: 2) 
+
+if sending data to to collectd takes too long the connection will be aborted. 
+
+=cut
+
+=item collectd_retries [ tries ] (default: 3)
+
+the collectd plugin uses a tread pool, if this is empty the connection fails,
+the SA Plugin then tries to reconnect. With this variable you can indicate how
+often it should try. 
+
+=cut
+
+=head1 DESCRIPTION
+
+This modules uses the email plugin of collectd from Sebastian Harl to
+collect statistical informations in rrd files to create some nice looking
+graphs with rrdtool. They communicate over a unix socket that the collectd
+plugin creates. The generated graphs will be placed in /var/lib/collectd/email
+
+=head1 AUTHOR
+
+Alexander Wirt <formorer@formorer.de>
+
+=head1 COPYRIGHT
+
+ Copyright 2006 Alexander Wirt <formorer@formorer.de> 
+ This program is free software; you can redistribute it and/or modify 
+ it under the the terms of either: 
+
+ a) the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+
+ or
+
+ b) the GPL (http://www.gnu.org/copyleft/gpl.html)  
+
+ use whatever you like more. 
+
+=cut
+
+package Mail::SpamAssassin::Plugin::Collectd;
+
+use Mail::SpamAssassin::Plugin;
+use Mail::SpamAssassin::Logger;
+use strict;
+use bytes; 
+use warnings;
+use Time::HiRes qw(usleep);
+use IO::Socket;
+
+use vars qw(@ISA);
+@ISA = qw(Mail::SpamAssassin::Plugin);
+
+sub new {
+    my ($class, $mailsa) = @_;
+
+    # the usual perlobj boilerplate to create a subclass object
+    $class = ref($class) || $class;
+    my $self = $class->SUPER::new($mailsa);
+    bless ($self, $class);
+
+    # register our config options
+    $self->set_config($mailsa->{conf});
+
+    # and return the new plugin object
+    return $self;
+}
+
+sub set_config {
+    my ($self, $conf) = @_;
+    my @cmds = ();
+
+    push (@cmds, {
+           setting => 'collectd_buffersize',
+           default => 256,
+           type =>
+           $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
+       });
+
+    push (@cmds, {
+           setting => 'collectd_socket', 
+           default => '/var/run/collectd-email',
+           type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
+    });
+
+       push (@cmds, {
+                       setting => 'collectd_timeout',
+                       default => 2,
+                       type =>
+                       $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
+       });
+
+       push (@cmds, {
+                       setting => 'collectd_retries',
+                       default => 3,
+                       type =>
+                       $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
+       });
+
+
+    $conf->{parser}->register_commands(\@cmds);
+}
+
+sub check_end {
+    my ($self, $params) = @_;
+    my $message_status = $params->{permsgstatus};
+       #create  new connection to our socket
+       eval {
+               local $SIG{ALRM} = sub { die "Sending to collectd timed out.\n" }; # NB: \n required
+
+               #generate a timeout
+               alarm $self->{main}->{conf}->{collectd_timeout};
+
+               my $sock;
+               #try at least $self->{main}->{conf}->{collectd_retries} to get a
+               #connection
+               for (my $i = 0; $i < $self->{main}->{conf}->{collectd_retries} ; ++$i) {
+                       last if $sock = new IO::Socket::UNIX
+                               ($self->{main}->{conf}->{collectd_socket});
+                       #sleep a random value between 0 and 50 microsecs to try for a new
+                       #thread
+                       usleep(int(rand(50))); 
+               }
+
+               die("could not connect to " .
+                               $self->{main}->{conf}->{collectd_socket} . ": $! - collectd plugin disabled") unless $sock; 
+
+               $sock->autoflush(1);
+
+               my $score = $message_status->{score};
+               #get the size of the message 
+               my $body = $message_status->{msg}->{pristine_body};
+
+               my $len = length($body);
+
+               if ($message_status->{score} >= $self->{main}->{conf}->{required_score} ) {
+                       #hey we have spam
+                       print $sock "e:spam:$len\n";
+               } else {
+                       print $sock "e:ham:$len\n";
+               }
+               print $sock "s:$score\n";
+               my @tmp_array; 
+               my @tests = @{$message_status->{test_names_hit}};
+
+               my $buffersize = $self->{main}->{conf}->{collectd_buffersize}; 
+               dbg("collectd: buffersize: $buffersize"); 
+
+               while  (scalar(@tests) > 0) {
+               push (@tmp_array, pop(@tests)); 
+                       if (length(join(',', @tmp_array) . '\n') > $buffersize) {
+                               push (@tests, pop(@tmp_array)); 
+                                       if (length(join(',', @tmp_array) . '\n') > $buffersize or scalar(@tmp_array) == 0) {
+                                               dbg("collectd: this shouldn't happen. Do you have tests"
+                                                       ." with names that have more than ~ $buffersize Bytes?");
+                                               return 1; 
+                                       } else {
+                                               dbg ( "collectd: c:" . join(',', @tmp_array) . "\n" ); 
+                                               print $sock "c:" . join(',', @tmp_array) . "\n"; 
+                                               #clean the array
+                                               @tmp_array = ();
+                                       } 
+                       } elsif ( scalar(@tests) == 0 ) {
+                               dbg ( "collectd: c:" . join(',', @tmp_array) . '\n' );
+                               print $sock "c:" . join(',', @tmp_array) . "\n";
+                       }
+               }
+               close($sock); 
+               alarm 0; 
+       };
+       if ($@) {
+               my $message = $@; 
+               chomp($message); 
+               info("collectd: $message");
+               return -1; 
+       }
+}
+
+1;
+
+# vim: syntax=perl sw=4 ts=4 noet shiftround
diff --git a/contrib/SpamAssassin/example.cf b/contrib/SpamAssassin/example.cf
new file mode 100644 (file)
index 0000000..7ffd708
--- /dev/null
@@ -0,0 +1,5 @@
+collectd_buffersize 256
+collectd_socket /var/run/collectd-email
+collectd_timeout 2
+collectd_retries 3 
+
diff --git a/contrib/add_rra.sh b/contrib/add_rra.sh
new file mode 100755 (executable)
index 0000000..c9306b0
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+INPUT=$1
+OUTPUT=$2
+
+if [ -z "$INPUT" -o -z "$OUTPUT" ]
+then
+       cat <<USAGE
+Usage: $0 <input> <output>
+USAGE
+       exit 1
+fi
+
+if [ ! -e "$INPUT" ]
+then
+       echo "No such file: $INPUT"
+       exit 1
+fi
+
+if [ -e "$OUTPUT" ]
+then
+       echo "File exists: $OUTPUT"
+       exit 1
+fi
+
+NUM_DS=0
+rrdtool dump "$INPUT" | while read LINE
+do
+       echo "$LINE"
+
+       if [ "$LINE" = "<ds>" ]
+       then
+               NUM_DS=$(($NUM_DS + 1))
+       fi
+       
+       if [ "$LINE" = "<!-- Round Robin Archives -->" ]
+       then
+               for CF in MIN MAX AVERAGE
+               do
+                       cat <<RRA
+       <rra>
+               <cf> $CF </cf>
+               <pdp_per_row> 1 </pdp_per_row>
+               <xff> 0.0000000000e+00 </xff>
+
+               <cdp_prep>
+RRA
+                       for ((i=0; i < $NUM_DS; i++))
+                       do
+                               echo "                  <ds><value> NaN </value>  <unknown_datapoints> 1 </unknown_datapoints></ds>"
+                       done
+                       echo "          </cdp_prep>"
+                       echo "          <database>"
+
+                       DS_VALUES=`for ((i=0; i < $NUM_DS; i++)); do echo -n "<v> NaN </v>"; done`
+                       for ((i=0; i < 2200; i++))
+                       do
+                               echo "                  <!-- $i --> <row>$DS_VALUES</row>"
+                       done
+                       echo "          </database>"
+                       echo "  </rra>"
+               done
+       fi
+done >"$OUTPUT.xml"
+
+rrdtool restore "$OUTPUT.xml" "$OUTPUT" -r >/dev/null
+rm -f "$OUTPUT.xml"
diff --git a/contrib/aix/collectd.spec b/contrib/aix/collectd.spec
new file mode 100644 (file)
index 0000000..c148d79
--- /dev/null
@@ -0,0 +1,75 @@
+
+%define name    collectd
+%define version 4.10.1
+%define release 1
+
+Name:           %{name}
+Summary:        Statistics collection daemon for filling RRD files.
+Version:        %{version}
+Release:        %{release}
+#Source:         http://collectd.org/files/%{name}-%{version}.tar.gz
+Source0:        %{name}-%{version}.tar.gz
+Group:          System Environment/Daemons
+BuildRoot:      %{_tmppath}/%{name}-%{version}-buildroot
+License:        GPL
+BuildPrereq:    rrdtool-devel,net-snmp-devel
+Requires:       rrdtool,net-snmp
+Packager:       Aurelien Reynaud <collectd@wattapower.net>
+Vendor:         collectd development team <collectd@verplant.org>
+
+%description
+collectd is a small daemon which collects system information periodically and
+provides mechanisms to monitor and store the values in a variety of ways. It
+is written in C for performance. Since the daemon doesn't need to startup
+every time it wants to update the values it's very fast and easy on the
+system. Also, the statistics are very fine grained since the files are updated
+every 10 seconds.
+
+%prep
+%setup
+
+%build
+# The RM variable in the RPM environment conflicts with that of the build environment,
+# at least when building on AIX 6.1. This is definitely a bug in one of the tools but
+# for now we work around it by unsetting the variable below.
+[ -n "$RM" ] && unset RM
+./configure LDFLAGS="-Wl,-brtl" --prefix=/opt/freeware --mandir=/opt/freeware/man --disable-dns --with-libnetsnmp=/opt/freeware/bin/net-snmp-config
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/%{name}
+mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+cp contrib/aix/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
+
+%clean
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
+
+%files
+%defattr(-,root,system)
+%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
+%config(noreplace) %attr(0644,root,system) %{_sysconfdir}/collectd.conf
+%attr(0755,root,system) /etc/rc.d/init.d/collectd
+%attr(0755,root,system) %{_sbindir}/collectd
+%attr(0755,root,system) %{_bindir}/collectd-nagios
+%attr(0755,root,system) %{_sbindir}/collectdmon
+%attr(0644,root,system) %{_mandir}/man1/*
+%attr(0644,root,system) %{_mandir}/man5/*
+
+# client
+%attr(0644,root,system) %{_includedir}/%{name}/client.h
+%attr(0644,root,system) %{_includedir}/%{name}/lcc_features.h
+
+%attr(0644,root,system) %{_libdir}/libcollectdclient.*
+%attr(0644,root,system) %{_libdir}/pkgconfig/libcollectdclient.pc
+
+%attr(0444,root,system) %{_libdir}/%{name}/*.so
+%attr(0444,root,system) %{_libdir}/%{name}/*.a
+%attr(0444,root,system) %{_libdir}/%{name}/*.la
+
+%attr(0644,root,system) %{_datadir}/%{name}/types.db
+
+%dir %{_localstatedir}/lib/%{name}
+%dir %{_localstatedir}/run
+
diff --git a/contrib/aix/init.d-collectd b/contrib/aix/init.d-collectd
new file mode 100755 (executable)
index 0000000..d893153
--- /dev/null
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# description: collectd startup script
+#
+# March 2010, Aurelien Reynaud <collectd@wattapower.net>
+#
+
+# Some plugins need libs in non-standard paths
+case `uname` in
+       SunOS)
+               LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/ssl/lib"
+               export LD_LIBRARY_PATH
+               ;;
+       *)
+               ;;
+esac
+
+# Set umask
+umask 022
+
+COLLECTD_BIN=/opt/freeware/sbin/collectd
+PIDFILE=/opt/freeware/var/run/collectd.pid
+
+# Check for missing binaries (stale symlinks should not happen)
+if [ ! -x $COLLECTD_BIN ]; then
+       echo "$COLLECTD_BIN not installed"
+       [ "$1" = "stop" ] && exit 0
+       exit 5
+fi
+
+# Check for existence of needed config file and read it
+COLLECTD_CONFIG=/opt/freeware/etc/collectd.conf
+if [ ! -r $COLLECTD_CONFIG ]; then
+       echo "$COLLECTD_CONFIG not existing"
+       [ "$1" = "stop" ] && exit 0
+       exit 6
+fi
+
+case "$1" in
+    start)
+       if [ -r $PIDFILE ]; then
+           echo "collectd daemon is already running with PID `cat $PIDFILE`."
+           exit 1
+       fi
+       echo "Starting collectd..."
+
+       ## Start daemon
+       $COLLECTD_BIN
+       ;;
+    stop)
+       echo "Shutting down collectd daemon... "
+       ## Stop daemon.
+       if [ -r $PIDFILE ]; then
+           pid=`cat $PIDFILE`
+           kill -15 $pid
+           while ps -p $pid >/dev/null; do
+               sleep 1
+           done
+           rm -f $PIDFILE
+       fi
+       ;;
+    status)
+       if [ -r $PIDFILE ]; then
+           echo "collectd daemon is running with PID `cat $PIDFILE`."
+       else
+           echo "collectd daemon is not running."
+       fi
+       ;;
+    restart)
+       ## Stop the service and regardless of whether it was
+       ## running or not, start it again.
+       $0 stop
+       $0 start
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|status|restart}"
+       exit 1
+       ;;
+esac
diff --git a/contrib/collectd.service b/contrib/collectd.service
new file mode 100644 (file)
index 0000000..ee4d596
--- /dev/null
@@ -0,0 +1,15 @@
+[Unit]
+Description=statistics collection daemon
+Documentation=man:collectd(1)
+After=local-fs.target network.target
+Requires=local-fs.target network.target
+
+[Service]
+ExecStart=/usr/sbin/collectd -C /etc/collectd/collectd.conf -f
+Restart=always
+RestartSec=10
+StandardOutput=syslog
+StandardError=syslog
+
+[Install]
+WantedBy=multi-user.target
diff --git a/contrib/collectd2html.pl b/contrib/collectd2html.pl
new file mode 100644 (file)
index 0000000..fe4e2bd
--- /dev/null
@@ -0,0 +1,258 @@
+#!/usr/bin/perl
+
+################################################################################
+#
+# collectd2html.pl
+#
+# Description:
+#   Generate an html page with all rrd data gathered by collectd.
+#
+# Usage:
+#   collectd2html.pl
+#
+#   When run on <host>, it generated <host>.html and <host>.dir, the latter
+#   containing all necessary images.
+#
+#
+# Copyright 2006 Vincent Stehlé <vincent.stehle@free.fr>
+#
+# Patch to configure the data directory and hostname by Eddy Petrisor
+# <eddy.petrisor@gmail.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+################################################################################
+
+use warnings;
+use strict;
+use Fatal qw(open close);
+use File::Basename;
+use Getopt::Long qw(:config no_ignore_case bundling pass_through);
+
+my $DIR       = "/var/lib/collectd";
+my $HOST      = undef;
+my $IMG_FMT   = "PNG";
+my $RECURSIVE = 1;
+
+GetOptions (
+    "host=s"         => \$HOST,
+    "data-dir=s"     => \$DIR,
+    "image-format=s" => \$IMG_FMT,
+    "recursive"      => \$RECURSIVE
+);
+
+if (($DIR !~ m/\/rrd\/?$/) && (-d "$DIR/rrd")) {
+       $DIR .= "/rrd";
+}
+
+if (defined($HOST) && ($DIR !~ m/\/$HOST\/?$/) && (-d "$DIR/$HOST")) {
+       $DIR .= "/$HOST";
+}
+
+my @COLORS = (0xff7777, 0x7777ff, 0x55ff55, 0xffcc77, 0xff77ff, 0x77ffff,
+       0xffff77, 0x55aaff);
+my @tmp = `/bin/hostname -f`; chomp(@tmp);
+$HOST = $tmp[0] if (! defined $HOST);
+my $svg_p = ($IMG_FMT eq "SVG");
+my $IMG_SFX = $svg_p ? ".svg" : ".png";
+my $IMG_DIR = "${HOST}.dir";
+my $HTML = "${HOST}.xhtml";
+
+################################################################################
+#
+# fade_component
+#
+# Description:
+#   Fade a color's component to the white.
+#
+################################################################################
+sub fade_component($)
+{
+       my($component) = @_;
+       return (($component + 255 * 5) / 6);
+}
+
+################################################################################
+#
+# fade_color
+#
+# Description:
+#   Fade a color to the white.
+#
+################################################################################
+sub fade_color($)
+{
+       my($color) = @_;
+       my $r = 0;
+
+       for my $i (0 .. 2){
+               my $shft = ($i * 8);
+               my $component = (($color >> $shft) & 255);
+               $r |= (fade_component($component) << $shft);
+       }
+
+       return $r;
+}
+
+################################################################################
+#
+# main
+#
+################################################################################
+system("rm -fR $IMG_DIR");
+system("mkdir -p $IMG_DIR");
+local *OUT;
+open(OUT, ">$HTML");
+my $title="Rrd plot for $HOST";
+
+print OUT <<END;
+<!DOCTYPE html PUBLIC
+  "-//W3C//DTD XHTML 1.1//EN"
+  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<style type="text/css" media="screen">
+.graph { text-align: center; }
+object.graph { width: 670; height: 179; }
+</style>
+<title>$title</title>
+<meta http-equiv="Content-Type"
+      content="application/xhtml+xml; charset=us-ascii" />
+</head>
+<body>
+END
+
+# list interesting rrd
+my @rrds;
+my @list;
+
+if ($RECURSIVE) {
+       @list = `find $DIR -type f -name '*.rrd'`;
+}
+else {
+       @list = `ls $DIR/*.rrd`;
+}
+chomp(@list);
+
+@list = sort @list;
+foreach my $rrd (@list){
+       $rrd =~ m/^$DIR\/(.*)\.rrd$/;
+       push(@rrds, $1);
+}
+
+# table of contents
+print OUT <<END;
+<h1><a id="top">$title</a></h1>
+<p>
+END
+
+foreach my $bn (@rrds){
+       my $cleaned_bn = $bn;
+       $cleaned_bn =~ tr/%\//__/;
+       print OUT <<END;
+<a href="#$cleaned_bn">$bn</a>
+END
+}
+
+print OUT <<END;
+</p>
+END
+
+# graph interesting rrd
+for (my $i = 0; $i < scalar(@rrds); ++$i) {
+       my $bn = $rrds[$i];
+       print "$bn\n";
+
+       my $rrd = $list[$i];
+       my $cmd = "rrdtool info $rrd |grep 'ds\\[' |sed 's/^ds\\[//'" 
+               ." |sed 's/\\].*//' |sort |uniq";
+       my @dss = `$cmd`; chomp(@dss);
+
+       # all DEF
+       my $j = 0;
+       my $defs = "";
+
+       foreach my $ds (@dss){
+               $defs .= " DEF:${ds}_avg=$rrd:$ds:AVERAGE"
+                       ." DEF:${ds}_max=$rrd:$ds:MAX ";
+       }
+
+       # all AREA
+       $j = 0;
+
+       foreach my $ds (@dss){
+               my $color = $COLORS[$j % scalar(@COLORS)]; $j++;
+               my $faded_color = fade_color($color);
+               $defs .= sprintf(" AREA:${ds}_max#%06x ", $faded_color);
+       }
+
+       # all LINE      
+       $j = 0;
+
+       foreach my $ds (@dss){
+               my $color = $COLORS[$j % scalar(@COLORS)]; $j++;
+               $defs .= sprintf(" LINE2:${ds}_avg#%06x:$ds"
+                       ." GPRINT:${ds}_avg:AVERAGE:%%5.1lf%%sAvg"
+                       ." GPRINT:${ds}_max:MAX:%%5.1lf%%sMax"
+                       , $color);
+       }
+
+       my $cleaned_bn = $bn;
+       $cleaned_bn =~ tr/%\//__/;
+       print OUT <<END;
+<h2><a id="$cleaned_bn">$bn</a></h2>
+END
+
+       # graph various ranges
+       foreach my $span qw(1hour 1day 1week 1month){
+               system("mkdir -p $IMG_DIR/" . dirname($bn));
+               my $img = "$IMG_DIR/${bn}-$span$IMG_SFX";
+
+               my $cmd = "rrdtool graph $img"
+                       ." -t \"$bn $span\" --imgformat $IMG_FMT --width 600 --height 100"
+                       ." --start now-$span --end now --interlaced"
+                       ." $defs >/dev/null 2>&1";
+               system($cmd);
+
+               my $cleaned_img = $img; $cleaned_img =~ s/%/%25/g;
+               if (! $svg_p) {
+                       print OUT <<END;
+<p class="graph"><img src="$cleaned_img" alt="${bn} $span" /></p>
+END
+               } else {
+                       print OUT <<END;
+<p class="graph"><object data="$cleaned_img" type="image/svg+xml">
+  ${bn} $span</object></p>
+END
+               }
+       }
+
+       print OUT <<END;
+<p><a href="#top">[top]</a></p>
+END
+}
+
+print OUT <<END;
+<hr />
+<p>
+  <a href="http://validator.w3.org/check?uri=referer"><img
+     src="http://www.w3.org/Icons/valid-xhtml10"
+     alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
+</p>
+</body>
+</html>
+END
+
+close(OUT);
diff --git a/contrib/collectd_network.py b/contrib/collectd_network.py
new file mode 100644 (file)
index 0000000..809f19d
--- /dev/null
@@ -0,0 +1,337 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim: fileencoding=utf-8
+#
+# Copyright © 2009 Adrian Perez <aperez@igalia.com>
+#
+# Distributed under terms of the GPLv2 license or newer.
+# 
+# Frank Marien (frank@apsu.be) 6 Sep 2012
+# - quick fixes for 5.1 binary protocol
+# - updated to python 3
+# - fixed for larger packet sizes (possible on lo interface)
+# - fixed comment typo (decode_network_string decodes a string)
+
+"""
+Collectd network protocol implementation.
+"""
+
+import socket,struct,sys
+import platform
+if platform.python_version() < '2.8.0':
+    # Python 2.7 and below io.StringIO does not like unicode
+    from StringIO import StringIO
+else:
+    try:
+      from io import StringIO
+    except ImportError:
+      from cStringIO import StringIO
+
+from datetime import datetime
+from copy import deepcopy
+
+
+DEFAULT_PORT = 25826
+"""Default port"""
+
+DEFAULT_IPv4_GROUP = "239.192.74.66"
+"""Default IPv4 multicast group"""
+
+DEFAULT_IPv6_GROUP = "ff18::efc0:4a42"
+"""Default IPv6 multicast group"""
+
+HR_TIME_DIV = (2.0**30)
+
+# Message kinds
+TYPE_HOST            = 0x0000
+TYPE_TIME            = 0x0001
+TYPE_TIME_HR         = 0x0008
+TYPE_PLUGIN          = 0x0002
+TYPE_PLUGIN_INSTANCE = 0x0003
+TYPE_TYPE            = 0x0004
+TYPE_TYPE_INSTANCE   = 0x0005
+TYPE_VALUES          = 0x0006
+TYPE_INTERVAL        = 0x0007
+TYPE_INTERVAL_HR     = 0x0009
+
+# For notifications
+TYPE_MESSAGE         = 0x0100
+TYPE_SEVERITY        = 0x0101
+
+# DS kinds
+DS_TYPE_COUNTER      = 0
+DS_TYPE_GAUGE        = 1
+DS_TYPE_DERIVE       = 2
+DS_TYPE_ABSOLUTE     = 3
+
+header = struct.Struct("!2H")
+number = struct.Struct("!Q")
+short  = struct.Struct("!H")
+double = struct.Struct("<d")
+
+def decode_network_values(ptype, plen, buf):
+    """Decodes a list of DS values in collectd network format
+    """
+    nvalues = short.unpack_from(buf, header.size)[0]
+    off = header.size + short.size + nvalues
+    valskip = double.size
+
+    # Check whether our expected packet size is the reported one
+    assert ((valskip + 1) * nvalues + short.size + header.size) == plen
+    assert double.size == number.size
+
+    result = []
+    for dstype in [ord(x) for x in buf[header.size+short.size:off]]:
+        if dstype == DS_TYPE_COUNTER:
+            result.append((dstype, number.unpack_from(buf, off)[0]))
+            off += valskip
+        elif dstype == DS_TYPE_GAUGE:
+            result.append((dstype, double.unpack_from(buf, off)[0]))
+            off += valskip
+        elif dstype == DS_TYPE_DERIVE:
+            result.append((dstype, number.unpack_from(buf, off)[0]))
+            off += valskip
+        elif dstype == DS_TYPE_ABSOLUTE:
+            result.append((dstype, number.unpack_from(buf, off)[0]))
+            off += valskip
+        else:
+            raise ValueError("DS type %i unsupported" % dstype)
+
+    return result
+
+
+def decode_network_number(ptype, plen, buf):
+    """Decodes a number (64-bit unsigned) from collectd network format.
+    """
+    return number.unpack_from(buf, header.size)[0]
+
+
+def decode_network_string(msgtype, plen, buf):
+    """Decodes a string from collectd network format.
+    """
+    return buf[header.size:plen-1]
+
+
+# Mapping of message types to decoding functions.
+_decoders = {
+    TYPE_VALUES         : decode_network_values,
+    TYPE_TIME           : decode_network_number,
+    TYPE_TIME_HR        : decode_network_number,
+    TYPE_INTERVAL       : decode_network_number,
+    TYPE_INTERVAL_HR    : decode_network_number,
+    TYPE_HOST           : decode_network_string,
+    TYPE_PLUGIN         : decode_network_string,
+    TYPE_PLUGIN_INSTANCE: decode_network_string,
+    TYPE_TYPE           : decode_network_string,
+    TYPE_TYPE_INSTANCE  : decode_network_string,
+    TYPE_MESSAGE        : decode_network_string,
+    TYPE_SEVERITY       : decode_network_number,
+}
+
+
+def decode_network_packet(buf):
+    """Decodes a network packet in collectd format.
+    """
+    off = 0
+    blen = len(buf)
+
+    while off < blen:
+        ptype, plen = header.unpack_from(buf, off)
+
+        if plen > blen - off:
+            raise ValueError("Packet longer than amount of data in buffer")
+
+        if ptype not in _decoders:
+            raise ValueError("Message type %i not recognized" % ptype)
+
+        yield ptype, _decoders[ptype](ptype, plen, buf[off:])
+        off += plen
+
+
+class Data(object):
+    time = 0
+    host = None
+    plugin = None
+    plugininstance = None
+    type = None
+    typeinstance = None
+
+    def __init__(self, **kw):
+        [setattr(self, k, v) for k, v in kw.items()]
+
+    @property
+    def datetime(self):
+        return datetime.fromtimestamp(self.time)
+
+    @property
+    def source(self):
+        buf = StringIO()
+        if self.host:
+            buf.write(str(self.host))
+        if self.plugin:
+            buf.write("/")
+            buf.write(str(self.plugin))
+        if self.plugininstance:
+            buf.write("/")
+            buf.write(str(self.plugininstance))
+        if self.type:
+            buf.write("/")
+            buf.write(str(self.type))
+        if self.typeinstance:
+            buf.write("/")
+            buf.write(str(self.typeinstance))
+        return buf.getvalue()
+
+    def __str__(self):
+        return "[%i] %s" % (self.time, self.source)
+
+
+
+class Notification(Data):
+    FAILURE  = 1
+    WARNING  = 2
+    OKAY     = 4
+
+    SEVERITY = {
+        FAILURE: "FAILURE",
+        WARNING: "WARNING",
+        OKAY   : "OKAY",
+    }
+
+    __severity = 0
+    message  = ""
+
+    def __set_severity(self, value):
+        if value in (self.FAILURE, self.WARNING, self.OKAY):
+            self.__severity = value
+
+    severity = property(lambda self: self.__severity, __set_severity)
+
+    @property
+    def severitystring(self):
+        return self.SEVERITY.get(self.severity, "UNKNOWN")
+
+    def __str__(self):
+        return "%s [%s] %s" % (
+                super(Notification, self).__str__(),
+                self.severitystring,
+                self.message)
+
+
+
+class Values(Data, list):
+    def __str__(self):
+        return "%s %s" % (Data.__str__(self), list.__str__(self))
+
+
+
+def interpret_opcodes(iterable):
+    vl = Values()
+    nt = Notification()
+
+    for kind, data in iterable:
+        if kind == TYPE_TIME:
+            vl.time = nt.time = data
+        elif kind == TYPE_TIME_HR:
+            vl.time = nt.time = data / HR_TIME_DIV
+        elif kind == TYPE_INTERVAL:
+            vl.interval = data
+        elif kind == TYPE_INTERVAL_HR:
+            vl.interval = data / HR_TIME_DIV
+        elif kind == TYPE_HOST:
+            vl.host = nt.host = data
+        elif kind == TYPE_PLUGIN:
+            vl.plugin = nt.plugin = data
+        elif kind == TYPE_PLUGIN_INSTANCE:
+            vl.plugininstance = nt.plugininstance = data
+        elif kind == TYPE_TYPE:
+            vl.type = nt.type = data
+        elif kind == TYPE_TYPE_INSTANCE:
+            vl.typeinstance = nt.typeinstance = data
+        elif kind == TYPE_SEVERITY:
+            nt.severity = data
+        elif kind == TYPE_MESSAGE:
+            nt.message = data
+            yield deepcopy(nt)
+        elif kind == TYPE_VALUES:
+            vl[:] = data
+            yield deepcopy(vl)
+
+
+
+class Reader(object):
+    """Network reader for collectd data.
+
+    Listens on the network in a given address, which can be a multicast
+    group address, and handles reading data when it arrives.
+    """
+    addr = None
+    host = None
+    port = DEFAULT_PORT
+
+    BUFFER_SIZE = 16384
+
+
+    def __init__(self, host=None, port=DEFAULT_PORT, multicast=False):
+        if host is None:
+            multicast = True
+            host = DEFAULT_IPv4_GROUP
+
+        self.host, self.port = host, port
+        self.ipv6 = ":" in self.host
+
+        family, socktype, proto, canonname, sockaddr = socket.getaddrinfo(
+                None if multicast else self.host, self.port,
+                socket.AF_INET6 if self.ipv6 else socket.AF_UNSPEC,
+                socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)[0]
+
+        self._sock = socket.socket(family, socktype, proto)
+        self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        self._sock.bind(sockaddr)
+
+        if multicast:
+            if hasattr(socket, "SO_REUSEPORT"):
+                self._sock.setsockopt(
+                        socket.SOL_SOCKET,
+                        socket.SO_REUSEPORT, 1)
+
+            val = None
+            if family == socket.AF_INET:
+                assert "." in self.host
+                val = struct.pack("4sl",
+                        socket.inet_aton(self.host), socket.INADDR_ANY)
+            elif family == socket.AF_INET6:
+                raise NotImplementedError("IPv6 support not ready yet")
+            else:
+                raise ValueError("Unsupported network address family")
+
+            self._sock.setsockopt(
+                    socket.IPPROTO_IPV6 if self.ipv6 else socket.IPPROTO_IP,
+                    socket.IP_ADD_MEMBERSHIP, val)
+            self._sock.setsockopt(
+                    socket.IPPROTO_IPV6 if self.ipv6 else socket.IPPROTO_IP,
+                    socket.IP_MULTICAST_LOOP, 0)
+
+
+    def receive(self):
+        """Receives a single raw collect network packet.
+        """
+        return self._sock.recv(self.BUFFER_SIZE)
+
+
+    def decode(self, buf=None):
+        """Decodes a given buffer or the next received packet.
+        """
+        if buf is None:
+            buf = self.receive()
+        return decode_network_packet(buf)
+
+
+    def interpret(self, iterable=None):
+        """Interprets a sequence
+        """
+        if iterable is None:
+            iterable = self.decode()
+        if isinstance(iterable, str):
+            iterable = self.decode(iterable)
+        return interpret_opcodes(iterable)
diff --git a/contrib/collectd_unix_sock.rb b/contrib/collectd_unix_sock.rb
new file mode 100644 (file)
index 0000000..f473361
--- /dev/null
@@ -0,0 +1,135 @@
+# Ruby class to access collectd daemon through the UNIX socket
+# plugin.
+#
+# Requires collectd to be configured with the unixsock plugin, like so:
+#
+# LoadPlugin unixsock
+# <Plugin unixsock>
+#   SocketFile "/var/run/collectd-unixsock"
+#   SocketPerms "0775"
+# </Plugin>
+#
+# Copyright (C) 2009 Novell Inc.
+# Author: Duncan Mac-Vicar P. <dmacvicar@suse.de>
+#
+# Inspired in python version:
+# Copyright (C) 2008 Clay Loveless <clay@killersoft.com>
+#
+# This software is provided 'as-is', without any express or implied
+# warranty.  In no event will the author be held liable for any damages
+# arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not
+#    claim that you wrote the original software. If you use this software
+#    in a product, an acknowledgment in the product documentation would be
+#    appreciated but is not required.
+# 2. Altered source versions must be plainly marked as such, and must not be
+#    misrepresented as being the original software.
+# 3. This notice may not be removed or altered from any source distribution.
+#
+require 'socket'
+
+# Access to collectd data using the unix socket
+# interface
+#
+# see http://collectd.org/wiki/index.php/Plugin:UnixSock
+#
+class CollectdUnixSock
+  include Socket::Constants
+
+  # initializes the collectd interface
+  # path is the location of the collectd
+  # unix socket
+  #
+  # collectd = CollectdUnixSock.new
+  #
+  def initialize(path='/var/run/collectd-unixsock')
+    @socket = UNIXSocket.open(path)
+    # @socket = Socket.new(AF_UNIX, SOCK_STREAM, 0)
+    # @socket.connect(path)
+    @path = path
+  end
+
+  # iterates over available values, passing the
+  # identifier to the block and the time
+  # the data for this identifier was last
+  # updated
+  #
+  # collectd.each_value do |time, identifier|
+  #   ...
+  # end
+  def each_value
+    n_lines = cmd("LISTVAL")
+    n_lines.times do
+      line = @socket.readline
+      time_s, identifier = line.split(' ', 2)
+      time = Time.at(time_s.to_i)
+      yield time, identifier
+    end
+  end
+
+  # iterates over each value current data
+  #
+  # collectd.each_value_data('myhost/swap/swap-free') { |col, val| }
+  #
+  # each iteration gives the column name and the value for it.
+  #
+  # You can also disable flushing by specifying it as an option:
+  #
+  # client.each_value_data('tarro/swap/swap-free',
+  #                   :flush => false ) do |col, val|
+  #    # .. do something with col and val
+  # end
+  #
+  # :flush option is by default true
+  #
+  def each_value_data(identifier, opts={})
+    n_lines = cmd("GETVAL \"#{identifier}\"")
+    n_lines.times do
+      line = @socket.readline
+      col, val = line.split('=', 2)
+      yield col, val
+    end
+
+    # unless the user explicitly disabled
+    # flush...
+    unless opts[:flush] == false
+      cmd("FLUSH identifier=\"#{identifier}\"")
+    end
+    
+  end
+  
+  private
+  
+  # internal command execution
+  def cmd(c)
+    @socket.write("#{c}\n")
+    line = @socket.readline
+    status_string, message = line.split(' ', 2)
+    status = status_string.to_i
+    raise message if status < 0
+    status  
+  end
+  
+end
+
+if __FILE__ == $0
+
+  client = CollectdUnixSock.new
+  client.each_value do |time, id|
+    puts "#{time.to_i} - #{id}"
+  end
+
+  client.each_value_data("tarro/cpu-0/cpu-user") do |col, val|
+    puts "#{col} -> #{val}"
+  end
+  
+  client.each_value_data("tarro/interface/if_packets-eth0") do |col, val|
+    puts "#{col} -> #{val}"
+  end
+  
+end
diff --git a/contrib/collectd_unixsock.py b/contrib/collectd_unixsock.py
new file mode 100644 (file)
index 0000000..5cd4ab8
--- /dev/null
@@ -0,0 +1,243 @@
+#-*- coding: ISO-8859-1 -*-
+# collect.py: the python collectd-unixsock module.
+#
+# Requires collectd to be configured with the unixsock plugin, like so:
+#
+# LoadPlugin unixsock
+# <Plugin unixsock>
+#   SocketFile "/var/run/collectd-unixsock"
+#   SocketPerms "0775"
+# </Plugin>
+#
+# Copyright (C) 2008 Clay Loveless <clay@killersoft.com>
+#
+# This software is provided 'as-is', without any express or implied
+# warranty.  In no event will the author be held liable for any damages
+# arising from the use of this software.
+#
+# Permission is granted to anyone to use this software for any purpose,
+# including commercial applications, and to alter it and redistribute it
+# freely, subject to the following restrictions:
+#
+# 1. The origin of this software must not be misrepresented; you must not
+#    claim that you wrote the original software. If you use this software
+#    in a product, an acknowledgment in the product documentation would be
+#    appreciated but is not required.
+# 2. Altered source versions must be plainly marked as such, and must not be
+#    misrepresented as being the original software.
+# 3. This notice may not be removed or altered from any source distribution.
+
+import socket
+import sys
+
+
+class Collectd():
+
+    def __init__(self, path='/var/run/collectd-unixsock', noisy=False):
+        self.noisy = noisy
+        self.path = path
+        self._sock = self._connect()
+
+    def flush(self, timeout=None, plugins=[], identifiers=[]):
+        """Send a FLUSH command.
+
+        Full documentation:
+            http://collectd.org/wiki/index.php/Plain_text_protocol#FLUSH
+
+        """
+        # have to pass at least one plugin or identifier
+        if not plugins and not identifiers:
+            return None
+        args = []
+        if timeout:
+            args.append("timeout=%s" % timeout)
+        if plugins:
+            plugin_args = map(lambda x: "plugin=%s" % x, plugins)
+            args.extend(plugin_args)
+        if identifiers:
+            identifier_args = map(lambda x: "identifier=%s" % x, identifiers)
+            args.extend(identifier_args)
+        return self._cmd('FLUSH %s' % ' '.join(args))
+
+    def getthreshold(self, identifier):
+        """Send a GETTHRESHOLD command.
+
+        Full documentation:
+            http://collectd.org/wiki/index.php/Plain_text_protocol#GETTHRESHOLD
+
+        """
+        numvalues = self._cmd('GETTHRESHOLD "%s"' % identifier)
+        lines = []
+        if not numvalues or numvalues < 0:
+            raise KeyError("Identifier '%s' not found" % identifier)
+        lines = self._readlines(numvalues)
+        return lines
+
+    def getval(self, identifier, flush_after=True):
+        """Send a GETVAL command.
+
+        Also flushes the identifier if flush_after is True.
+
+        Full documentation:
+            http://collectd.org/wiki/index.php/Plain_text_protocol#GETVAL
+
+        """
+        numvalues = self._cmd('GETVAL "%s"' % identifier)
+        lines = []
+        if not numvalues or numvalues < 0:
+            raise KeyError("Identifier '%s' not found" % identifier)
+        lines = self._readlines(numvalues)
+        if flush_after:
+            self.flush(identifiers=[identifier])
+        return lines
+
+    def listval(self):
+        """Send a LISTVAL command.
+
+        Full documentation:
+            http://collectd.org/wiki/index.php/Plain_text_protocol#LISTVAL
+
+        """
+        numvalues = self._cmd('LISTVAL')
+        lines = []
+        if numvalues:
+            lines = self._readlines(numvalues)
+        return lines
+
+    def putnotif(self, message, options={}):
+        """Send a PUTNOTIF command.
+
+        Options must be passed as a Python dictionary. Example:
+          options={'severity': 'failure', 'host': 'example.com'}
+
+        Full documentation:
+            http://collectd.org/wiki/index.php/Plain_text_protocol#PUTNOTIF
+
+        """
+        args = []
+        if options:
+            options_args = map(lambda x: "%s=%s" % (x, options[x]), options)
+            args.extend(options_args)
+        args.append('message="%s"' % message)
+        return self._cmd('PUTNOTIF %s' % ' '.join(args))
+
+    def putval(self, identifier, values, options={}):
+        """Send a PUTVAL command.
+
+        Options must be passed as a Python dictionary. Example:
+          options={'interval': 10}
+
+        Full documentation:
+            http://collectd.org/wiki/index.php/Plain_text_protocol#PUTVAL
+
+        """
+        args = []
+        args.append('"%s"' % identifier)
+        if options:
+            options_args = map(lambda x: "%s=%s" % (x, options[x]), options)
+            args.extend(options_args)
+        values = map(str, values)
+        args.append(':'.join(values))
+        return self._cmd('PUTVAL %s' % ' '.join(args))
+
+    def _cmd(self, c):
+        try:
+            return self._cmdattempt(c)
+        except socket.error, (errno, errstr):
+            sys.stderr.write("[error] Sending to socket failed: [%d] %s\n"
+                             % (errno, errstr))
+            self._sock = self._connect()
+            return self._cmdattempt(c)
+
+    def _cmdattempt(self, c):
+        if self.noisy:
+            print "[send] %s" % c
+        if not self._sock:
+            sys.stderr.write("[error] Socket unavailable. Can not send.")
+            return False
+        self._sock.send(c + "\n")
+        status_message = self._readline()
+        if self.noisy:
+            print "[receive] %s" % status_message
+        if not status_message:
+            return None
+        code, message = status_message.split(' ', 1)
+        if int(code):
+            return int(code)
+        return False
+
+    def _connect(self):
+        try:
+            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            sock.connect(self.path)
+            if self.noisy:
+                print "[socket] connected to %s" % self.path
+            return sock
+        except socket.error, (errno, errstr):
+            sys.stderr.write("[error] Connecting to socket failed: [%d] %s"
+                             % (errno, errstr))
+            return None
+
+    def _readline(self):
+        """Read single line from socket"""
+        if not self._sock:
+            sys.stderr.write("[error] Socket unavailable. Can not read.")
+            return None
+        try:
+            data = ''
+            buf = []
+            recv = self._sock.recv
+            while data != "\n":
+                data = recv(1)
+                if not data:
+                    break
+                if data != "\n":
+                    buf.append(data)
+            return ''.join(buf)
+        except socket.error, (errno, errstr):
+            sys.stderr.write("[error] Reading from socket failed: [%d] %s"
+                             % (errno, errstr))
+            self._sock = self._connect()
+            return None
+
+    def _readlines(self, sizehint=0):
+        """Read multiple lines from socket"""
+        total = 0
+        list = []
+        while True:
+            line = self._readline()
+            if not line:
+                break
+            list.append(line)
+            total = len(list)
+            if sizehint and total >= sizehint:
+                break
+        return list
+
+    def __del__(self):
+        if not self._sock:
+            return
+        try:
+            self._sock.close()
+        except socket.error, (errno, errstr):
+            sys.stderr.write("[error] Closing socket failed: [%d] %s"
+                             % (errno, errstr))
+
+
+if __name__ == '__main__':
+    """Collect values from socket and dump to STDOUT"""
+
+    c = Collectd('/var/run/collectd-unixsock', noisy=True)
+    list = c.listval()
+    for val in list:
+        stamp, identifier = val.split()
+        print "\n%s" % identifier
+        print "\tUpdate time: %s" % stamp
+
+        values = c.getval(identifier)
+        print "\tValue list: %s" % ', '.join(values)
+
+        # don't fetch thresholds by default because collectd will crash
+        # if there is no treshold for the given identifier
+        #thresholds = c.getthreshold(identifier)
+        #print "\tThresholds: %s" % ', '.join(thresholds)
diff --git a/contrib/collection.cgi b/contrib/collection.cgi
new file mode 100755 (executable)
index 0000000..5ff259f
--- /dev/null
@@ -0,0 +1,3515 @@
+#!/usr/bin/perl
+# Copyright (c) 2006-2010 Florian Forster <octo at collectd.org>
+# Copyright (c) 2006-2008 Sebastian Harl <sh at tokkee.org>
+# Copyright (c) 2008      Mirko Buffoni <briareos at eswat.org>
+#
+# 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.
+
+use strict;
+use warnings;
+
+use Carp (qw(cluck confess));
+use CGI (':cgi');
+use CGI::Carp ('fatalsToBrowser');
+use HTML::Entities ('encode_entities');
+use URI::Escape ('uri_escape');
+use RRDs ();
+use Data::Dumper ();
+
+our $Config = "/etc/collection.conf";
+our @DataDirs = ();
+our @DontShowTypes = ();
+our $LibDir;
+
+our $ValidTimespan =
+{
+  hour => 3600,
+  day => 86400,
+  week => 7 * 86400,
+  month => 31 * 86400,
+  year => 366 * 86400
+};
+
+our @RRDDefaultArgs = ('-w', '400');
+
+our $Args = {};
+
+our $GraphDefs;
+our $MetaGraphDefs = {};
+load_graph_definitions ();
+
+for (qw(action host plugin plugin_instance type type_instance timespan))
+{
+       $Args->{$_} = param ($_);
+}
+
+exit (main ());
+
+sub read_config
+{
+       my $fh;
+       open ($fh, "< $Config") or confess ("open ($Config): $!");
+       while (my $line = <$fh>)
+       {
+               chomp ($line);
+               next if (!$line);
+               next if ($line =~ m/^\s*#/);
+               next if ($line =~ m/^\s*$/);
+
+               my $key;
+               my $value;
+
+               if ($line =~ m/^([A-Za-z]+):\s*"((?:[^"\\]+|\\.)*)"$/)
+               {
+                       $key = lc ($1); $value = $2;
+                       $value =~ s/\\(.)/$1/g;
+               }
+               elsif ($line =~ m/([A-Za-z]+):\s*([0-9]+)$/)
+               {
+                       $key = lc ($1); $value = 0 + $2;
+               }
+               else
+               {
+                       print STDERR "Cannot parse line: $line\n";
+                       next;
+               }
+
+               if ($key eq 'datadir')
+               {
+                       $value =~ s#/*$##;
+                       push (@DataDirs, $value);
+               }
+               elsif ($key eq 'libdir')
+               {
+                       $value =~ s#/*$##;
+                       $LibDir = $value;
+               }
+               elsif ($key eq 'dontshowtype')
+               {
+                 push (@DontShowTypes, $value);
+               }
+               else
+               {
+                       print STDERR "Unknown key: $key\n";
+               }
+       }
+       close ($fh);
+} # read_config
+
+sub validate_args
+{
+       if ($Args->{'action'} && ($Args->{'action'} =~ m/^(overview|show_host|show_plugin|show_type|show_graph)$/))
+       {
+               $Args->{'action'} = $1;
+       }
+       else
+       {
+               $Args->{'action'} = 'overview';
+       }
+
+       if ($Args->{'host'} && ($Args->{'host'} =~ m#/#))
+       {
+               delete ($Args->{'host'});
+       }
+
+       if ($Args->{'plugin'} && ($Args->{'plugin'} =~ m#/#))
+       {
+               delete ($Args->{'plugin'});
+       }
+
+       if ($Args->{'type'} && ($Args->{'type'} =~ m#/#))
+       {
+               delete ($Args->{'type'});
+       }
+
+       if (!$Args->{'plugin'} || ($Args->{'plugin_instance'}
+               && ($Args->{'plugin_instance'} =~ m#/#)))
+       {
+               delete ($Args->{'plugin_instance'});
+       }
+
+       if (!$Args->{'type'} || ($Args->{'type_instance'}
+               && ($Args->{'type_instance'} =~ m#/#)))
+       {
+               delete ($Args->{'type_instance'});
+       }
+
+       if (defined ($Args->{'timespan'})
+         && ($Args->{'timespan'} =~ m/^(hour|day|week|month|year)$/))
+       {
+         $Args->{'timespan'} = $1;
+       }
+       else
+       {
+         $Args->{'timespan'} = 'day';
+       }
+} # validate_args
+
+{
+  my $hosts;
+  sub _find_hosts
+  {
+    if (defined ($hosts))
+    {
+      return (keys %$hosts);
+    }
+
+    $hosts = {};
+
+    for (my $i = 0; $i < @DataDirs; $i++)
+    {
+      my @tmp;
+      my $dh;
+
+      opendir ($dh, $DataDirs[$i]) or next;
+      @tmp = grep { ($_ !~ m/^\./) && (-d $DataDirs[$i] . '/' . $_) } (readdir ($dh));
+      closedir ($dh);
+
+      $hosts->{$_} = 1 for (@tmp);
+    } # for (@DataDirs)
+
+    return (keys %$hosts);
+  } # _find_hosts
+}
+
+sub _get_param_host
+{
+  my %all_hosts = map { $_ => 1 } (_find_hosts ());
+  my @selected_hosts = ();
+  for (param ('host'))
+  {
+    if (defined ($all_hosts{$_}))
+    {
+      push (@selected_hosts, "$_");
+    }
+  }
+  return (@selected_hosts);
+} # _get_param_host
+
+sub _get_param_timespan
+{
+  my $timespan = param ('timespan');
+
+  $timespan ||= 'day';
+  $timespan = lc ($timespan);
+
+  if (!defined ($ValidTimespan->{$timespan}))
+  {
+    $timespan = 'day';
+  }
+
+  return ($timespan);
+} # _get_param_timespan
+
+sub _find_plugins
+{
+  my $host = shift;
+  my %plugins = ();
+
+  for (my $i = 0; $i < @DataDirs; $i++)
+  {
+    my $dir = $DataDirs[$i] . "/$host";
+    my @tmp;
+    my $dh;
+
+    opendir ($dh, $dir) or next;
+    @tmp = grep { ($_ !~ m/^\./) && (-d "$dir/$_") } (readdir ($dh));
+    closedir ($dh);
+
+    for (@tmp)
+    {
+      my ($plugin, $instance) = split (m/-/, $_, 2);
+      $plugins{$plugin} = [] if (!exists $plugins{$plugin});
+      push (@{$plugins{$plugin}}, $instance);
+    }
+  } # for (@DataDirs)
+
+  return (%plugins);
+} # _find_plugins
+
+sub _find_types
+{
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my %types = ();
+
+  for (my $i = 0; $i < @DataDirs; $i++)
+  {
+    my $dir = $DataDirs[$i] . "/$host/$plugin" . (defined ($plugin_instance) ? "-$plugin_instance" : '');
+    my @tmp;
+    my $dh;
+
+    opendir ($dh, $dir) or next;
+    @tmp = grep { ($_ !~ m/^\./) && ($_ =~ m/\.rrd$/i) && (-f "$dir/$_") } (readdir ($dh));
+    closedir ($dh);
+
+    for (@tmp)
+    {
+      my $name = "$_";
+      $name =~ s/\.rrd$//i;
+      my ($type, $instance) = split (m/-/, $name, 2);
+      if (grep { $_ eq $type } @DontShowTypes) { next; }
+      $types{$type} = [] if (!$types{$type});
+      push (@{$types{$type}}, $instance) if (defined ($instance));
+    }
+  } # for (@DataDirs)
+
+  return (%types);
+} # _find_types
+
+sub _find_files_for_host
+{
+  my $host = shift;
+  my $ret = {};
+
+  my %plugins = _find_plugins ($host);
+  for (keys %plugins)
+  {
+    my $plugin = $_;
+    my $plugin_instances = $plugins{$plugin};
+
+    if (!$plugin_instances || !@$plugin_instances)
+    {
+      $plugin_instances = ['-'];
+    }
+
+    $ret->{$plugin} = {};
+
+    for (@$plugin_instances)
+    {
+      my $plugin_instance = defined ($_) ? $_ : '-';
+      my %types = _find_types ($host, $plugin,
+       ($plugin_instance ne '-')
+       ? $plugin_instance
+       : undef);
+
+      $ret->{$plugin}{$plugin_instance} = {};
+
+      for (keys %types)
+      {
+       my $type = $_;
+       my $type_instances = $types{$type};
+
+       $ret->{$plugin}{$plugin_instance}{$type} = {};
+
+       for (@$type_instances)
+       {
+         $ret->{$plugin}{$plugin_instance}{$type}{$_} = 1;
+       }
+
+       if (!@$type_instances)
+       {
+         $ret->{$plugin}{$plugin_instance}{$type}{'-'} = 1;
+       }
+      } # for (keys %types)
+    } # for (@$plugin_instances)
+  } # for (keys %plugins)
+
+  return ($ret);
+} # _find_files_for_host
+
+sub _find_files_for_hosts
+{
+  my @hosts = @_;
+  my $all_plugins = {};
+
+  for (my $i = 0; $i < @hosts; $i++)
+  {
+    my $tmp = _find_files_for_host ($hosts[$i]);
+    _files_union ($all_plugins, $tmp);
+  }
+
+  return ($all_plugins);
+} # _find_files_for_hosts
+
+sub _files_union
+{
+  my $dest = shift;
+  my $src = shift;
+
+  for (keys %$src)
+  {
+    my $plugin = $_;
+    $dest->{$plugin} ||= {};
+
+    for (keys %{$src->{$plugin}})
+    {
+      my $pinst = $_;
+      $dest->{$plugin}{$pinst} ||= {};
+
+      for (keys %{$src->{$plugin}{$pinst}})
+      {
+       my $type = $_;
+       $dest->{$plugin}{$pinst}{$type} ||= {};
+
+       for (keys %{$src->{$plugin}{$pinst}{$type}})
+       {
+         my $tinst = $_;
+         $dest->{$plugin}{$pinst}{$type}{$tinst} = 1;
+       }
+      }
+    }
+  }
+} # _files_union
+
+sub _files_plugin_inst_count
+{
+  my $src = shift;
+  my $i = 0;
+
+  for (keys %$src)
+  {
+    if (exists ($MetaGraphDefs->{$_}))
+    {
+      $i++;
+    }
+    else
+    {
+      $i = $i + keys %{$src->{$_}};
+    }
+  }
+  return ($i);
+} # _files_plugin_count
+
+sub list_hosts
+{
+  my @hosts = _find_hosts ();
+  @hosts = sort (@hosts);
+
+  print "<ul>\n";
+  for (my $i = 0; $i < @hosts; $i++)
+  {
+    my $host_html = encode_entities ($hosts[$i]);
+    my $host_url = uri_escape ($hosts[$i]);
+
+    print qq(  <li><a href="${\script_name ()}?action=show_host;host=$host_url">$host_html</a></li>\n);
+  }
+  print "</ul>\n";
+} # list_hosts
+
+sub _string_to_color
+{
+  my $color = shift;
+  if ($color =~ m/([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])/)
+  {
+    return ([hex ($1) / 255.0, hex ($2) / 255.0, hex ($3) / 255.0]);
+  }
+  return;
+} # _string_to_color
+
+sub _color_to_string
+{
+  confess ("Wrong number of arguments") if (@_ != 1);
+  return (sprintf ('%02hx%02hx%02hx', map { int (255.0 * $_) } @{$_[0]}));
+} # _color_to_string
+
+sub _get_random_color
+{
+  my ($r, $g, $b) = (rand (), rand ());
+  my $min = 0.0;
+  my $max = 1.0;
+
+  if (($r + $g) < 1.0)
+  {
+    $min = 1.0 - ($r + $g);
+  }
+  else
+  {
+    $max = 2.0 - ($r + $g);
+  }
+
+  $b = $min + (rand () * ($max - $min));
+
+  return ([$r, $g, $b]);
+} # _get_random_color
+
+sub _get_n_colors
+{
+       my $instances = shift;
+       my $num = scalar @$instances;
+       my $ret = {};
+
+       for (my $i = 0; $i < $num; $i++)
+       {
+               my $pos = 6 * $i / $num;
+               my $n = int ($pos);
+               my $p = $pos - $n;
+               my $q = 1 - $p;
+
+               my $red   = 0;
+               my $green = 0;
+               my $blue  = 0;
+
+               my $color;
+
+               if ($n == 0)
+               {
+                       $red  = 255;
+                       $blue = 255 * $p;
+               }
+               elsif ($n == 1)
+               {
+                       $red  = 255 * $q;
+                       $blue = 255;
+               }
+               elsif ($n == 2)
+               {
+                       $green = 255 * $p;
+                       $blue  = 255;
+               }
+               elsif ($n == 3)
+               {
+                       $green = 255;
+                       $blue  = 255 * $q;
+               }
+               elsif ($n == 4)
+               {
+                       $red   = 255 * $p;
+                       $green = 255;
+               }
+               elsif ($n == 5)
+               {
+                       $red   = 255;
+                       $green = 255 * $q;
+               }
+               else { die; }
+
+               $color = sprintf ("%02x%02x%02x", $red, $green, $blue);
+               $ret->{$instances->[$i]} = $color;
+       }
+
+       return ($ret);
+} # _get_n_colors
+
+sub _get_faded_color
+{
+  my $fg = shift;
+  my $bg;
+  my %opts = @_;
+  my $ret = [undef, undef, undef];
+
+  $opts{'background'} ||= [1.0, 1.0, 1.0];
+  $opts{'alpha'} ||= 0.25;
+
+  if (!ref ($opts{'background'}))
+  {
+    $opts{'background'} = _string_to_color ($opts{'background'})
+      or confess ("Cannot parse background color " . $opts{'background'});
+  }
+  $bg = $opts{'background'};
+
+  for (my $i = 0; $i < 3; $i++)
+  {
+    $ret->[$i] = ($opts{'alpha'} * $fg->[$i])
+       + ((1.0 - $opts{'alpha'}) * $bg->[$i]);
+  }
+
+  return ($ret);
+} # _get_faded_color
+
+sub _custom_sort_arrayref
+{
+  my $array_ref = shift;
+  my $array_sort = shift;
+  my $unknown_first = shift || 0;
+
+  my %elements = map { $_ => 1 } (@$array_ref);
+  splice (@$array_ref, 0);
+
+  for (@$array_sort)
+  {
+    next if (!exists ($elements{$_}));
+    push (@$array_ref, $_);
+    delete ($elements{$_});
+  }
+  if ($unknown_first) {
+    unshift (@$array_ref, sort (keys %elements));
+  }
+  else {
+    push (@$array_ref, sort (keys %elements));
+  }
+} # _custom_sort_arrayref
+
+sub action_show_host
+{
+  my @hosts = _get_param_host ();
+  @hosts = sort (@hosts);
+
+  my $timespan = _get_param_timespan ();
+  my $all_plugins = _find_files_for_hosts (@hosts);
+
+  my $url_prefix = script_name () . '?action=show_plugin'
+  . join ('', map { ';host=' . uri_escape ($_) } (@hosts))
+  . ';timespan=' . uri_escape ($timespan);
+
+  print qq(    <div><a href="${\script_name ()}?action=overview">Back to list of hosts</a></div>\n);
+
+  print "    <p>Available plugins:</p>\n"
+  . "    <ul>\n";
+  for (sort (keys %$all_plugins))
+  {
+    my $plugin = $_;
+    my $plugin_html = encode_entities ($plugin);
+    my $url_plugin = $url_prefix . ';plugin=' . uri_escape ($plugin);
+    print qq(      <li><a href="$url_plugin">$plugin_html</a></li>\n);
+  }
+  print "   </ul>\n";
+} # action_show_host
+
+sub action_show_plugin
+{
+  my @hosts = _get_param_host ();
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $timespan = _get_param_timespan ();
+
+  my $hosts_url = join (';', map { 'host=' . uri_escape ($_) } (@hosts));
+  my $url_prefix = script_name () . "?$hosts_url";
+
+  my $all_plugins = {};
+  my $plugins_per_host = {};
+  my $selected_plugins = {};
+
+  for (my $i = 0; $i < @hosts; $i++)
+  {
+    $plugins_per_host->{$hosts[$i]} = _find_files_for_host ($hosts[$i]);
+    _files_union ($all_plugins, $plugins_per_host->{$hosts[$i]});
+  }
+
+  for (param ('plugin'))
+  {
+    if (defined ($all_plugins->{$_}))
+    {
+      $selected_plugins->{$_} = 1;
+    }
+  }
+
+  print qq(    <div><a href="${\script_name ()}?action=show_host;$hosts_url">Back to list of plugins</a></div>\n);
+
+  # Print table header
+  print <<HTML;
+    <table class="graphs">
+      <tr>
+        <th>Plugins</th>
+HTML
+  for (@hosts)
+  {
+    print "\t<th>", encode_entities ($_), "</th>\n";
+  }
+  print "      </tr>\n";
+
+  for (sort (keys %$selected_plugins))
+  {
+    my $plugin = $_;
+    my $plugin_html = encode_entities ($plugin);
+    my $plugin_url = "$url_prefix;plugin=" . uri_escape ($plugin);
+    my $all_pinst = $all_plugins->{$plugin};
+
+    for (sort (keys %$all_pinst))
+    {
+      my $pinst = $_;
+      my $pinst_html = '';
+      my $pinst_url = $plugin_url;
+
+      if ($pinst ne '-')
+      {
+       $pinst_html = encode_entities ($pinst);
+       $pinst_url .= ';plugin_instance=' . uri_escape ($pinst);
+      }
+
+      my $files_printed = 0;
+      my $files_num = _files_plugin_inst_count ($all_pinst->{$pinst});
+      if ($files_num < 1)
+      {
+       next;
+      }
+      my $rowspan = ($files_num == 1) ? '' : qq( rowspan="$files_num");
+
+      for (sort (keys %{$all_plugins->{$plugin}{$pinst}}))
+      {
+       my $type = $_;
+       my $type_html = encode_entities ($type);
+       my $type_url = "$pinst_url;type=" . uri_escape ($type);
+
+       if ($files_printed == 0)
+       {
+         my $title = $plugin_html;
+         if ($pinst ne '-')
+         {
+           $title .= " ($pinst_html)";
+         }
+         print "      <tr>\n";
+         print "\t<td$rowspan>$title</td>\n";
+       }
+
+       if (exists ($MetaGraphDefs->{$type}))
+       {
+         my $graph_url = script_name () . '?action=show_graph'
+         . ';plugin=' . uri_escape ($plugin)
+         . ';type=' . uri_escape ($type)
+         . ';timespan=' . uri_escape ($timespan);
+         if ($pinst ne '-')
+         {
+           $graph_url .= ';plugin_instance=' . uri_escape ($pinst);
+         }
+
+         if ($files_printed != 0)
+         {
+           print "      <tr>\n";
+         }
+
+         for (@hosts)
+         {
+           my $host = $_;
+           my $host_graph_url = $graph_url . ';host=' . uri_escape ($host);
+
+           print "\t<td>";
+           if (exists $plugins_per_host->{$host}{$plugin}{$pinst}{$type})
+           {
+             print qq(<img src="$host_graph_url" />);
+             #print encode_entities (qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />));
+           }
+           print "</td>\n";
+         } # for (my $k = 0; $k < @hosts; $k++)
+
+         print "      </tr>\n";
+
+         $files_printed++;
+         next; # pinst
+       } # if (exists ($MetaGraphDefs->{$type}))
+
+       for (sort (keys %{$all_plugins->{$plugin}{$pinst}{$type}}))
+       {
+         my $tinst = $_;
+         my $tinst_esc = encode_entities ($tinst);
+         my $graph_url = script_name () . '?action=show_graph'
+         . ';plugin=' . uri_escape ($plugin)
+         . ';type=' . uri_escape ($type)
+         . ';timespan=' . uri_escape ($timespan);
+         if ($pinst ne '-')
+         {
+           $graph_url .= ';plugin_instance=' . uri_escape ($pinst);
+         }
+         if ($tinst ne '-')
+         {
+           $graph_url .= ';type_instance=' . uri_escape ($tinst);
+         }
+
+         if ($files_printed != 0)
+         {
+           print "      <tr>\n";
+         }
+
+         for (my $k = 0; $k < @hosts; $k++)
+         {
+           my $host = $hosts[$k];
+           my $host_graph_url = $graph_url . ';host=' . uri_escape ($host);
+
+           print "\t<td>";
+           if ($plugins_per_host->{$host}{$plugin}{$pinst}{$type}{$tinst})
+           {
+             print qq(<img src="$host_graph_url" />);
+             #print encode_entities (qq(<img src="${\script_name ()}?action=show_graph;host=$host_esc;$param_plugin;$param_type;timespan=$timespan" />));
+           }
+           print "</td>\n";
+         } # for (my $k = 0; $k < @hosts; $k++)
+
+         print "      </tr>\n";
+
+         $files_printed++;
+       } # for ($tinst)
+      } # for ($type)
+    } # for ($pinst)
+  } # for ($plugin)
+  print "   </table>\n";
+} # action_show_plugin
+
+sub action_show_type
+{
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instance = shift;
+
+  my $host_url = uri_escape ($host);
+  my $plugin_url = uri_escape ($plugin);
+  my $plugin_html = encode_entities ($plugin);
+  my $plugin_instance_url = defined ($plugin_instance) ? uri_escape ($plugin_instance) : undef;
+  my $type_url = uri_escape ($type);
+  my $type_instance_url = defined ($type_instance) ? uri_escape ($type_instance) : undef;
+
+  my $url_prefix = script_name () . "?action=show_plugin;host=$host_url;plugin=$plugin_url";
+  $url_prefix .= ";plugin_instance=$plugin_instance_url" if (defined ($plugin_instance));
+
+  print qq(    <div><a href="$url_prefix">Back to plugin &quot;$plugin_html&quot;</a></div>\n);
+
+  $url_prefix = script_name () . "?action=show_graph;host=$host_url;plugin=$plugin_url";
+  $url_prefix .= ";plugin_instance=$plugin_instance_url" if (defined ($plugin_instance));
+  $url_prefix .= ";type=$type_url";
+  $url_prefix .= ";type_instance=$type_instance_url" if (defined ($type_instance));
+
+  for (qw(hour day week month year))
+  {
+    my $timespan = $_;
+
+    print qq#  <div><img src="$url_prefix;timespan=$timespan" /></div>\n#;
+  }
+} # action_show_type
+
+sub action_show_graph
+{
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instance = shift;
+  my @rrd_args;
+  my $title;
+  
+  my %times = (hour => -3600, day => -86400, week => 7 * -86400, month => 31 * -86400, year => 366 * -86400);
+  my $start_time = $times{$Args->{'timespan'}} || -86400;
+
+  #print STDERR Data::Dumper->Dump ([$Args], ['Args']);
+
+  # FIXME
+  if (exists ($MetaGraphDefs->{$type}))
+  {
+    my %types = _find_types ($host, $plugin, $plugin_instance);
+    return $MetaGraphDefs->{$type}->($host, $plugin, $plugin_instance, $type, $types{$type});
+  }
+
+  return if (!defined ($GraphDefs->{$type}));
+  @rrd_args = @{$GraphDefs->{$type}};
+
+  $title = "$host/$plugin" . (defined ($plugin_instance) ? "-$plugin_instance" : '')
+  . "/$type" . (defined ($type_instance) ? "-$type_instance" : '');
+
+  for (my $i = 0; $i < @DataDirs; $i++)
+  {
+    my $file = $DataDirs[$i] . "/$title.rrd";
+    next if (!-f $file);
+
+    $file =~ s/:/\\:/g;
+    s/{file}/$file/ for (@rrd_args);
+
+    RRDs::graph ('-', '-a', 'PNG', '-s', $start_time, '-t', $title, @RRDDefaultArgs, @rrd_args);
+    if (my $err = RRDs::error ())
+    {
+      die ("RRDs::graph: $err");
+    }
+  }
+} # action_show_graph
+
+sub print_selector
+{
+  my @hosts = _find_hosts ();
+  @hosts = sort (@hosts);
+
+  my %selected_hosts = map { $_ => 1 } (_get_param_host ());
+  my $timespan_selected = _get_param_timespan ();
+
+  print <<HTML;
+    <form action="${\script_name ()}" method="get">
+      <fieldset>
+       <legend>Selector</legend>
+       <select name="host" multiple="multiple" size="10">
+HTML
+  for (my $i = 0; $i < @hosts; $i++)
+  {
+    my $host = encode_entities ($hosts[$i]);
+    my $selected = defined ($selected_hosts{$hosts[$i]}) ? ' selected="selected"' : '';
+    print qq(\t  <option value="$host"$selected>$host</option>\n);
+  }
+  print "\t</select>\n";
+
+  if (keys %selected_hosts)
+  {
+    my $all_plugins = _find_files_for_hosts (keys %selected_hosts);
+    my %selected_plugins = map { $_ => 1 } (param ('plugin'));
+
+    print qq(\t<select name="plugin" multiple="multiple" size="10">\n);
+    for (sort (keys %$all_plugins))
+    {
+      my $plugin = $_;
+      my $plugin_html = encode_entities ($plugin);
+      my $selected = (defined ($selected_plugins{$plugin})
+       ? ' selected="selected"' : '');
+      print qq(\t  <option value="$plugin_html"$selected>$plugin</option>\n);
+    }
+    print "</select>\n";
+  } # if (keys %selected_hosts)
+
+  print qq(\t<select name="timespan">\n);
+  for (qw(Hour Day Week Month Year))
+  {
+    my $timespan_uc = $_;
+    my $timespan_lc = lc ($_);
+    my $selected = ($timespan_selected eq $timespan_lc)
+      ? ' selected="selected"' : '';
+    print qq(\t  <option value="$timespan_lc"$selected>$timespan_uc</option>\n);
+  }
+  print <<HTML;
+       </select>
+       <input type="submit" name="button" value="Ok" />
+      </fieldset>
+    </form>
+HTML
+}
+
+sub print_header
+{
+  print <<HEAD;
+Content-Type: application/xhtml+xml; charset=utf-8
+Cache-Control: no-cache
+
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+  <head>
+    <title>collection.cgi, Version 2</title>
+    <style type="text/css">
+      img
+      {
+       border: none;
+      }
+      table.graphs
+      {
+       border-collapse: collapse;
+      }
+      table.graphs td,
+      table.graphs th
+      {
+       border: 1px solid black;
+       empty-cells: hide;
+      }
+    </style>
+  </head>
+
+  <body>
+HEAD
+  print_selector ();
+} # print_header
+
+sub print_footer
+{
+  print <<FOOT;
+  </body>
+</html>
+FOOT
+} # print_footer
+
+sub main
+{
+       read_config ();
+       validate_args ();
+
+       if (defined ($Args->{'host'})
+         && defined ($Args->{'plugin'})
+         && defined ($Args->{'type'})
+         && ($Args->{'action'} eq 'show_graph'))
+       {
+         $| = 1;
+         print STDOUT header (-Content_Type => 'image/png');
+         action_show_graph ($Args->{'host'},
+           $Args->{'plugin'}, $Args->{'plugin_instance'},
+           $Args->{'type'}, $Args->{'type_instance'});
+         return (0);
+       }
+
+       print_header ();
+
+       if (!$Args->{'host'})
+       {
+         list_hosts ();
+       }
+       elsif (!$Args->{'plugin'})
+       {
+         action_show_host ($Args->{'host'});
+       }
+       elsif (!$Args->{'type'})
+       {
+         action_show_plugin ($Args->{'plugin'}, $Args->{'plugin_instance'});
+       }
+       else
+       {
+         action_show_type ($Args->{'host'},
+           $Args->{'plugin'}, $Args->{'plugin_instance'},
+           $Args->{'type'}, $Args->{'type_instance'});
+       }
+
+       print_footer ();
+
+       return (0);
+}
+
+sub load_graph_definitions
+{
+  my $Canvas = 'FFFFFF';
+
+  my $FullRed    = 'FF0000';
+  my $FullGreen  = '00E000';
+  my $FullBlue   = '0000FF';
+  my $FullYellow = 'F0A000';
+  my $FullCyan   = '00A0FF';
+  my $FullMagenta= 'A000FF';
+
+  my $HalfRed    = 'F7B7B7';
+  my $HalfGreen  = 'B7EFB7';
+  my $HalfBlue   = 'B7B7F7';
+  my $HalfYellow = 'F3DFB7';
+  my $HalfCyan   = 'B7DFF7';
+  my $HalfMagenta= 'DFB7F7';
+
+  my $HalfBlueGreen = '89B3C9';
+
+  $GraphDefs =
+  {
+    apache_bytes => ['DEF:min_raw={file}:value:MIN',
+    'DEF:avg_raw={file}:value:AVERAGE',
+    'DEF:max_raw={file}:value:MAX',
+    'CDEF:min=min_raw,8,*',
+    'CDEF:avg=avg_raw,8,*',
+    'CDEF:max=max_raw,8,*',
+    'CDEF:mytime=avg_raw,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*',
+    'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
+    "AREA:avg#$HalfBlue",
+    "LINE1:avg#$FullBlue:Bit/s",
+    'GPRINT:min:MIN:%5.1lf%s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last',
+    'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+    ],
+   apache_connections => ['DEF:min={file}:value:MIN',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Connections",
+    'GPRINT:min:MIN:%6.2lf Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:max:MAX:%6.2lf Max,',
+    'GPRINT:avg:LAST:%6.2lf Last'
+    ],
+    apache_idle_workers => ['DEF:min={file}:value:MIN',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Idle Workers",
+    'GPRINT:min:MIN:%6.2lf Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:max:MAX:%6.2lf Max,',
+    'GPRINT:avg:LAST:%6.2lf Last'
+    ],
+    apache_requests => ['DEF:min={file}:value:MIN',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Requests/s",
+    'GPRINT:min:MIN:%6.2lf Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:max:MAX:%6.2lf Max,',
+    'GPRINT:avg:LAST:%6.2lf Last'
+    ],
+    apache_scoreboard => ['DEF:min={file}:value:MIN',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Processes",
+    'GPRINT:min:MIN:%6.2lf Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:max:MAX:%6.2lf Max,',
+    'GPRINT:avg:LAST:%6.2lf Last'
+    ],
+    bitrate => ['-v', 'Bits/s',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Bits/s",
+    'GPRINT:min:MIN:%5.1lf%s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Average,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last\l'
+    ],
+    charge => ['-v', 'Ah',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Charge",
+    'GPRINT:min:MIN:%5.1lf%sAh Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sAh Avg,',
+    'GPRINT:max:MAX:%5.1lf%sAh Max,',
+    'GPRINT:avg:LAST:%5.1lf%sAh Last\l'
+    ],
+    connections => ['-v', 'Connections',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Connections",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    cpu => ['-v', 'CPU load',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Percent",
+    'GPRINT:min:MIN:%6.2lf%% Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf%% Avg,',
+    'GPRINT:max:MAX:%6.2lf%% Max,',
+    'GPRINT:avg:LAST:%6.2lf%% Last\l'
+    ],
+    current => ['-v', 'Ampere',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Current",
+    'GPRINT:min:MIN:%5.1lf%sA Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sA Avg,',
+    'GPRINT:max:MAX:%5.1lf%sA Max,',
+    'GPRINT:avg:LAST:%5.1lf%sA Last\l'
+    ],
+    df => ['-v', 'Percent', '-l', '0',
+    'DEF:free_avg={file}:free:AVERAGE',
+    'DEF:free_min={file}:free:MIN',
+    'DEF:free_max={file}:free:MAX',
+    'DEF:used_avg={file}:used:AVERAGE',
+    'DEF:used_min={file}:used:MIN',
+    'DEF:used_max={file}:used:MAX',
+    'CDEF:total=free_avg,used_avg,+',
+    'CDEF:free_pct=100,free_avg,*,total,/',
+    'CDEF:used_pct=100,used_avg,*,total,/',
+    'CDEF:free_acc=free_pct,used_pct,+',
+    'CDEF:used_acc=used_pct',
+    "AREA:free_acc#$HalfGreen",
+    "AREA:used_acc#$HalfRed",
+    "LINE1:free_acc#$FullGreen:Free",
+    'GPRINT:free_min:MIN:%5.1lf%sB Min,',
+    'GPRINT:free_avg:AVERAGE:%5.1lf%sB Avg,',
+    'GPRINT:free_max:MAX:%5.1lf%sB Max,',
+    'GPRINT:free_avg:LAST:%5.1lf%sB Last\l',
+    "LINE1:used_acc#$FullRed:Used",
+    'GPRINT:used_min:MIN:%5.1lf%sB Min,',
+    'GPRINT:used_avg:AVERAGE:%5.1lf%sB Avg,',
+    'GPRINT:used_max:MAX:%5.1lf%sB Max,',
+    'GPRINT:used_avg:LAST:%5.1lf%sB Last\l'
+    ],
+    disk => [
+    'DEF:rtime_avg={file}:rtime:AVERAGE',
+    'DEF:rtime_min={file}:rtime:MIN',
+    'DEF:rtime_max={file}:rtime:MAX',
+    'DEF:wtime_avg={file}:wtime:AVERAGE',
+    'DEF:wtime_min={file}:wtime:MIN',
+    'DEF:wtime_max={file}:wtime:MAX',
+    'CDEF:rtime_avg_ms=rtime_avg,1000,/',
+    'CDEF:rtime_min_ms=rtime_min,1000,/',
+    'CDEF:rtime_max_ms=rtime_max,1000,/',
+    'CDEF:wtime_avg_ms=wtime_avg,1000,/',
+    'CDEF:wtime_min_ms=wtime_min,1000,/',
+    'CDEF:wtime_max_ms=wtime_max,1000,/',
+    'CDEF:total_avg_ms=rtime_avg_ms,wtime_avg_ms,+',
+    'CDEF:total_min_ms=rtime_min_ms,wtime_min_ms,+',
+    'CDEF:total_max_ms=rtime_max_ms,wtime_max_ms,+',
+    "AREA:total_max_ms#$HalfRed",
+    "AREA:total_min_ms#$Canvas",
+    "LINE1:wtime_avg_ms#$FullGreen:Write",
+    'GPRINT:wtime_min_ms:MIN:%5.1lf%s Min,',
+    'GPRINT:wtime_avg_ms:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:wtime_max_ms:MAX:%5.1lf%s Max,',
+    'GPRINT:wtime_avg_ms:LAST:%5.1lf%s Last\n',
+    "LINE1:rtime_avg_ms#$FullBlue:Read ",
+    'GPRINT:rtime_min_ms:MIN:%5.1lf%s Min,',
+    'GPRINT:rtime_avg_ms:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:rtime_max_ms:MAX:%5.1lf%s Max,',
+    'GPRINT:rtime_avg_ms:LAST:%5.1lf%s Last\n',
+    "LINE1:total_avg_ms#$FullRed:Total",
+    'GPRINT:total_min_ms:MIN:%5.1lf%s Min,',
+    'GPRINT:total_avg_ms:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:total_max_ms:MAX:%5.1lf%s Max,',
+    'GPRINT:total_avg_ms:LAST:%5.1lf%s Last'
+    ],
+    disk_octets => ['-v', 'Bytes/s',
+    'DEF:out_min={file}:write:MIN',
+    'DEF:out_avg={file}:write:AVERAGE',
+    'DEF:out_max={file}:write:MAX',
+    'DEF:inc_min={file}:read:MIN',
+    'DEF:inc_avg={file}:read:AVERAGE',
+    'DEF:inc_max={file}:read:MAX',
+    'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+    'CDEF:mytime=out_avg,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
+    'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+    'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
+    'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+    "AREA:out_avg#$HalfGreen",
+    "AREA:inc_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:out_avg#$FullGreen:Written",
+    'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:out_max:MAX:%5.1lf%s Max,',
+    'GPRINT:out_avg:LAST:%5.1lf%s Last',
+    'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+    "LINE1:inc_avg#$FullBlue:Read   ",
+    'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:inc_max:MAX:%5.1lf%s Max,',
+    'GPRINT:inc_avg:LAST:%5.1lf%s Last',
+    'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+    ],
+    disk_merged => ['-v', 'Merged Ops/s',
+    'DEF:out_min={file}:write:MIN',
+    'DEF:out_avg={file}:write:AVERAGE',
+    'DEF:out_max={file}:write:MAX',
+    'DEF:inc_min={file}:read:MIN',
+    'DEF:inc_avg={file}:read:AVERAGE',
+    'DEF:inc_max={file}:read:MAX',
+    'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+    "AREA:out_avg#$HalfGreen",
+    "AREA:inc_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:out_avg#$FullGreen:Written",
+    'GPRINT:out_avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:out_max:MAX:%6.2lf Max,',
+    'GPRINT:out_avg:LAST:%6.2lf Last\l',
+    "LINE1:inc_avg#$FullBlue:Read   ",
+    'GPRINT:inc_avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:inc_max:MAX:%6.2lf Max,',
+    'GPRINT:inc_avg:LAST:%6.2lf Last\l'
+    ],
+    disk_ops => ['-v', 'Ops/s',
+    'DEF:out_min={file}:write:MIN',
+    'DEF:out_avg={file}:write:AVERAGE',
+    'DEF:out_max={file}:write:MAX',
+    'DEF:inc_min={file}:read:MIN',
+    'DEF:inc_avg={file}:read:AVERAGE',
+    'DEF:inc_max={file}:read:MAX',
+    'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+    "AREA:out_avg#$HalfGreen",
+    "AREA:inc_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:out_avg#$FullGreen:Written",
+    'GPRINT:out_avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:out_max:MAX:%6.2lf Max,',
+    'GPRINT:out_avg:LAST:%6.2lf Last\l',
+    "LINE1:inc_avg#$FullBlue:Read   ",
+    'GPRINT:inc_avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:inc_max:MAX:%6.2lf Max,',
+    'GPRINT:inc_avg:LAST:%6.2lf Last\l'
+    ],
+    disk_time => ['-v', 'Seconds/s',
+    'DEF:out_min_raw={file}:write:MIN',
+    'DEF:out_avg_raw={file}:write:AVERAGE',
+    'DEF:out_max_raw={file}:write:MAX',
+    'DEF:inc_min_raw={file}:read:MIN',
+    'DEF:inc_avg_raw={file}:read:AVERAGE',
+    'DEF:inc_max_raw={file}:read:MAX',
+    'CDEF:out_min=out_min_raw,1000,/',
+    'CDEF:out_avg=out_avg_raw,1000,/',
+    'CDEF:out_max=out_max_raw,1000,/',
+    'CDEF:inc_min=inc_min_raw,1000,/',
+    'CDEF:inc_avg=inc_avg_raw,1000,/',
+    'CDEF:inc_max=inc_max_raw,1000,/',
+    'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+    "AREA:out_avg#$HalfGreen",
+    "AREA:inc_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:out_avg#$FullGreen:Written",
+    'GPRINT:out_avg:AVERAGE:%5.1lf%ss Avg,',
+    'GPRINT:out_max:MAX:%5.1lf%ss Max,',
+    'GPRINT:out_avg:LAST:%5.1lf%ss Last\l',
+    "LINE1:inc_avg#$FullBlue:Read   ",
+    'GPRINT:inc_avg:AVERAGE:%5.1lf%ss Avg,',
+    'GPRINT:inc_max:MAX:%5.1lf%ss Max,',
+    'GPRINT:inc_avg:LAST:%5.1lf%ss Last\l'
+    ],
+    dns_octets => ['DEF:rsp_min_raw={file}:responses:MIN',
+    'DEF:rsp_avg_raw={file}:responses:AVERAGE',
+    'DEF:rsp_max_raw={file}:responses:MAX',
+    'DEF:qry_min_raw={file}:queries:MIN',
+    'DEF:qry_avg_raw={file}:queries:AVERAGE',
+    'DEF:qry_max_raw={file}:queries:MAX',
+    'CDEF:rsp_min=rsp_min_raw,8,*',
+    'CDEF:rsp_avg=rsp_avg_raw,8,*',
+    'CDEF:rsp_max=rsp_max_raw,8,*',
+    'CDEF:qry_min=qry_min_raw,8,*',
+    'CDEF:qry_avg=qry_avg_raw,8,*',
+    'CDEF:qry_max=qry_max_raw,8,*',
+    'CDEF:overlap=rsp_avg,qry_avg,GT,qry_avg,rsp_avg,IF',
+    'CDEF:mytime=rsp_avg_raw,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:rsp_avg_sample=rsp_avg_raw,UN,0,rsp_avg_raw,IF,sample_len,*',
+    'CDEF:rsp_avg_sum=PREV,UN,0,PREV,IF,rsp_avg_sample,+',
+    'CDEF:qry_avg_sample=qry_avg_raw,UN,0,qry_avg_raw,IF,sample_len,*',
+    'CDEF:qry_avg_sum=PREV,UN,0,PREV,IF,qry_avg_sample,+',
+    "AREA:rsp_avg#$HalfGreen",
+    "AREA:qry_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:rsp_avg#$FullGreen:Responses",
+    'GPRINT:rsp_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:rsp_max:MAX:%5.1lf%s Max,',
+    'GPRINT:rsp_avg:LAST:%5.1lf%s Last',
+    'GPRINT:rsp_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+    "LINE1:qry_avg#$FullBlue:Queries  ",
+    #'GPRINT:qry_min:MIN:%5.1lf %s Min,',
+    'GPRINT:qry_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:qry_max:MAX:%5.1lf%s Max,',
+    'GPRINT:qry_avg:LAST:%5.1lf%s Last',
+    'GPRINT:qry_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+    ],
+    dns_opcode => [
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Queries/s",
+    'GPRINT:min:MIN:%9.3lf Min,',
+    'GPRINT:avg:AVERAGE:%9.3lf Average,',
+    'GPRINT:max:MAX:%9.3lf Max,',
+    'GPRINT:avg:LAST:%9.3lf Last\l'
+    ],
+    email_count => ['-v', 'Mails',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfMagenta",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullMagenta:Count ",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    email_size => ['-v', 'Bytes',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfMagenta",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullMagenta:Count ",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    spam_score => ['-v', 'Score',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Score ",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    spam_check => [
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfMagenta",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullMagenta:Count ",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    conntrack => ['-v', 'Entries',
+    'DEF:avg={file}:entropy:AVERAGE',
+    'DEF:min={file}:entropy:MIN',
+    'DEF:max={file}:entropy:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Count",
+    'GPRINT:min:MIN:%4.0lf Min,',
+    'GPRINT:avg:AVERAGE:%4.0lf Avg,',
+    'GPRINT:max:MAX:%4.0lf Max,',
+    'GPRINT:avg:LAST:%4.0lf Last\l'
+    ],
+    entropy => ['-v', 'Bits',
+    'DEF:avg={file}:entropy:AVERAGE',
+    'DEF:min={file}:entropy:MIN',
+    'DEF:max={file}:entropy:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Bits",
+    'GPRINT:min:MIN:%4.0lfbit Min,',
+    'GPRINT:avg:AVERAGE:%4.0lfbit Avg,',
+    'GPRINT:max:MAX:%4.0lfbit Max,',
+    'GPRINT:avg:LAST:%4.0lfbit Last\l'
+    ],
+    fanspeed => ['-v', 'RPM',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfMagenta",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullMagenta:RPM",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    frequency => ['-v', 'Hertz',
+    'DEF:avg={file}:frequency:AVERAGE',
+    'DEF:min={file}:frequency:MIN',
+    'DEF:max={file}:frequency:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Frequency [Hz]",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    frequency_offset => [ # NTPd
+    'DEF:ppm_avg={file}:ppm:AVERAGE',
+    'DEF:ppm_min={file}:ppm:MIN',
+    'DEF:ppm_max={file}:ppm:MAX',
+    "AREA:ppm_max#$HalfBlue",
+    "AREA:ppm_min#$Canvas",
+    "LINE1:ppm_avg#$FullBlue:{inst}",
+    'GPRINT:ppm_min:MIN:%5.2lf Min,',
+    'GPRINT:ppm_avg:AVERAGE:%5.2lf Avg,',
+    'GPRINT:ppm_max:MAX:%5.2lf Max,',
+    'GPRINT:ppm_avg:LAST:%5.2lf Last'
+    ],
+    gauge => ['-v', 'Exec value',
+    'DEF:temp_avg={file}:value:AVERAGE',
+    'DEF:temp_min={file}:value:MIN',
+    'DEF:temp_max={file}:value:MAX',
+    "AREA:temp_max#$HalfBlue",
+    "AREA:temp_min#$Canvas",
+    "LINE1:temp_avg#$FullBlue:Exec value",
+    'GPRINT:temp_min:MIN:%6.2lf Min,',
+    'GPRINT:temp_avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:temp_max:MAX:%6.2lf Max,',
+    'GPRINT:temp_avg:LAST:%6.2lf Last\l'
+    ],
+    hddtemp => [
+    'DEF:temp_avg={file}:value:AVERAGE',
+    'DEF:temp_min={file}:value:MIN',
+    'DEF:temp_max={file}:value:MAX',
+    "AREA:temp_max#$HalfRed",
+    "AREA:temp_min#$Canvas",
+    "LINE1:temp_avg#$FullRed:Temperature",
+    'GPRINT:temp_min:MIN:%4.1lf Min,',
+    'GPRINT:temp_avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:temp_max:MAX:%4.1lf Max,',
+    'GPRINT:temp_avg:LAST:%4.1lf Last\l'
+    ],
+    humidity => ['-v', 'Percent',
+    'DEF:temp_avg={file}:value:AVERAGE',
+    'DEF:temp_min={file}:value:MIN',
+    'DEF:temp_max={file}:value:MAX',
+    "AREA:temp_max#$HalfGreen",
+    "AREA:temp_min#$Canvas",
+    "LINE1:temp_avg#$FullGreen:Temperature",
+    'GPRINT:temp_min:MIN:%4.1lf%% Min,',
+    'GPRINT:temp_avg:AVERAGE:%4.1lf%% Avg,',
+    'GPRINT:temp_max:MAX:%4.1lf%% Max,',
+    'GPRINT:temp_avg:LAST:%4.1lf%% Last\l'
+    ],
+    if_errors => ['-v', 'Errors/s',
+    'DEF:tx_min={file}:tx:MIN',
+    'DEF:tx_avg={file}:tx:AVERAGE',
+    'DEF:tx_max={file}:tx:MAX',
+    'DEF:rx_min={file}:rx:MIN',
+    'DEF:rx_avg={file}:rx:AVERAGE',
+    'DEF:rx_max={file}:rx:MAX',
+    'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
+    'CDEF:mytime=tx_avg,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
+    'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
+    'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
+    'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
+    "AREA:tx_avg#$HalfGreen",
+    "AREA:rx_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:tx_avg#$FullGreen:TX",
+    'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:tx_max:MAX:%5.1lf%s Max,',
+    'GPRINT:tx_avg:LAST:%5.1lf%s Last',
+    'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
+    "LINE1:rx_avg#$FullBlue:RX",
+    #'GPRINT:rx_min:MIN:%5.1lf %s Min,',
+    'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:rx_max:MAX:%5.1lf%s Max,',
+    'GPRINT:rx_avg:LAST:%5.1lf%s Last',
+    'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l'
+    ],
+    if_collisions => ['-v', 'Collisions/s',
+    'DEF:min_raw={file}:value:MIN',
+    'DEF:avg_raw={file}:value:AVERAGE',
+    'DEF:max_raw={file}:value:MAX',
+    'CDEF:min=min_raw,8,*',
+    'CDEF:avg=avg_raw,8,*',
+    'CDEF:max=max_raw,8,*',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Collisions/s",
+    'GPRINT:min:MIN:%5.1lf %s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last\l'
+    ],
+    if_dropped => ['-v', 'Packets/s',
+    'DEF:tx_min={file}:tx:MIN',
+    'DEF:tx_avg={file}:tx:AVERAGE',
+    'DEF:tx_max={file}:tx:MAX',
+    'DEF:rx_min={file}:rx:MIN',
+    'DEF:rx_avg={file}:rx:AVERAGE',
+    'DEF:rx_max={file}:rx:MAX',
+    'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
+    'CDEF:mytime=tx_avg,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
+    'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
+    'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
+    'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
+    "AREA:tx_avg#$HalfGreen",
+    "AREA:rx_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:tx_avg#$FullGreen:TX",
+    'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:tx_max:MAX:%5.1lf%s Max,',
+    'GPRINT:tx_avg:LAST:%5.1lf%s Last',
+    'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
+    "LINE1:rx_avg#$FullBlue:RX",
+    #'GPRINT:rx_min:MIN:%5.1lf %s Min,',
+    'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:rx_max:MAX:%5.1lf%s Max,',
+    'GPRINT:rx_avg:LAST:%5.1lf%s Last',
+    'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l'
+    ],
+    if_packets => ['-v', 'Packets/s',
+    'DEF:tx_min={file}:tx:MIN',
+    'DEF:tx_avg={file}:tx:AVERAGE',
+    'DEF:tx_max={file}:tx:MAX',
+    'DEF:rx_min={file}:rx:MIN',
+    'DEF:rx_avg={file}:rx:AVERAGE',
+    'DEF:rx_max={file}:rx:MAX',
+    'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
+    'CDEF:mytime=tx_avg,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
+    'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
+    'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
+    'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
+    "AREA:tx_avg#$HalfGreen",
+    "AREA:rx_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:tx_avg#$FullGreen:TX",
+    'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:tx_max:MAX:%5.1lf%s Max,',
+    'GPRINT:tx_avg:LAST:%5.1lf%s Last',
+    'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
+    "LINE1:rx_avg#$FullBlue:RX",
+    #'GPRINT:rx_min:MIN:%5.1lf %s Min,',
+    'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:rx_max:MAX:%5.1lf%s Max,',
+    'GPRINT:rx_avg:LAST:%5.1lf%s Last',
+    'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l'
+    ],
+    if_rx_errors => ['-v', 'Errors/s',
+    'DEF:min={file}:value:MIN',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:max={file}:value:MAX',
+    'CDEF:mytime=avg,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:avg_sample=avg,UN,0,avg,IF,sample_len,*',
+    'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
+    "AREA:avg#$HalfBlue",
+    "LINE1:avg#$FullBlue:Errors/s",
+    'GPRINT:avg:AVERAGE:%3.1lf%s Avg,',
+    'GPRINT:max:MAX:%3.1lf%s Max,',
+    'GPRINT:avg:LAST:%3.1lf%s Last',
+    'GPRINT:avg_sum:LAST:(ca. %2.0lf%s Total)\l'
+    ],
+    ipt_bytes => ['-v', 'Bits/s',
+    'DEF:min_raw={file}:value:MIN',
+    'DEF:avg_raw={file}:value:AVERAGE',
+    'DEF:max_raw={file}:value:MAX',
+    'CDEF:min=min_raw,8,*',
+    'CDEF:avg=avg_raw,8,*',
+    'CDEF:max=max_raw,8,*',
+    'CDEF:mytime=avg_raw,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*',
+    'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Bits/s",
+    #'GPRINT:min:MIN:%5.1lf %s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last',
+    'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+    ],
+    ipt_packets => ['-v', 'Packets/s',
+    'DEF:min_raw={file}:value:MIN',
+    'DEF:avg_raw={file}:value:AVERAGE',
+    'DEF:max_raw={file}:value:MAX',
+    'CDEF:min=min_raw,8,*',
+    'CDEF:avg=avg_raw,8,*',
+    'CDEF:max=max_raw,8,*',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Packets/s",
+    'GPRINT:min:MIN:%5.1lf %s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last\l'
+    ],
+    irq => ['-v', 'Issues/s',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Issues/s",
+    'GPRINT:min:MIN:%6.2lf Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:max:MAX:%6.2lf Max,',
+    'GPRINT:avg:LAST:%6.2lf Last\l'
+    ],
+    load => ['-v', 'System load',
+    'DEF:s_avg={file}:shortterm:AVERAGE',
+    'DEF:s_min={file}:shortterm:MIN',
+    'DEF:s_max={file}:shortterm:MAX',
+    'DEF:m_avg={file}:midterm:AVERAGE',
+    'DEF:m_min={file}:midterm:MIN',
+    'DEF:m_max={file}:midterm:MAX',
+    'DEF:l_avg={file}:longterm:AVERAGE',
+    'DEF:l_min={file}:longterm:MIN',
+    'DEF:l_max={file}:longterm:MAX',
+    "AREA:s_max#$HalfGreen",
+    "AREA:s_min#$Canvas",
+    "LINE1:s_avg#$FullGreen: 1m average",
+    'GPRINT:s_min:MIN:%4.2lf Min,',
+    'GPRINT:s_avg:AVERAGE:%4.2lf Avg,',
+    'GPRINT:s_max:MAX:%4.2lf Max,',
+    'GPRINT:s_avg:LAST:%4.2lf Last\n',
+    "LINE1:m_avg#$FullBlue: 5m average",
+    'GPRINT:m_min:MIN:%4.2lf Min,',
+    'GPRINT:m_avg:AVERAGE:%4.2lf Avg,',
+    'GPRINT:m_max:MAX:%4.2lf Max,',
+    'GPRINT:m_avg:LAST:%4.2lf Last\n',
+    "LINE1:l_avg#$FullRed:15m average",
+    'GPRINT:l_min:MIN:%4.2lf Min,',
+    'GPRINT:l_avg:AVERAGE:%4.2lf Avg,',
+    'GPRINT:l_max:MAX:%4.2lf Max,',
+    'GPRINT:l_avg:LAST:%4.2lf Last'
+    ],
+    load_percent => [
+    'DEF:avg={file}:percent:AVERAGE',
+    'DEF:min={file}:percent:MIN',
+    'DEF:max={file}:percent:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Load",
+    'GPRINT:min:MIN:%5.1lf%s%% Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,',
+    'GPRINT:max:MAX:%5.1lf%s%% Max,',
+    'GPRINT:avg:LAST:%5.1lf%s%% Last\l'
+    ],
+    mails => ['DEF:rawgood={file}:good:AVERAGE',
+    'DEF:rawspam={file}:spam:AVERAGE',
+    'CDEF:good=rawgood,UN,0,rawgood,IF',
+    'CDEF:spam=rawspam,UN,0,rawspam,IF',
+    'CDEF:negspam=spam,-1,*',
+    "AREA:good#$HalfGreen",
+    "LINE1:good#$FullGreen:Good mails",
+    'GPRINT:good:AVERAGE:%4.1lf Avg,',
+    'GPRINT:good:MAX:%4.1lf Max,',
+    'GPRINT:good:LAST:%4.1lf Last\n',
+    "AREA:negspam#$HalfRed",
+    "LINE1:negspam#$FullRed:Spam mails",
+    'GPRINT:spam:AVERAGE:%4.1lf Avg,',
+    'GPRINT:spam:MAX:%4.1lf Max,',
+    'GPRINT:spam:LAST:%4.1lf Last',
+    'HRULE:0#000000'
+    ],
+    memcached_command => ['-v', 'Commands',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Commands",
+    'GPRINT:min:MIN:%5.1lf%s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:max:MAX:%5.1lf Max,',
+    'GPRINT:avg:LAST:%5.1lf Last\l'
+    ],
+    memcached_connections => ['-v', 'Connections',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Connections",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    memcached_items => ['-v', 'Items',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Items",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    memcached_octets => ['-v', 'Bits/s',
+    'DEF:out_min={file}:tx:MIN',
+    'DEF:out_avg={file}:tx:AVERAGE',
+    'DEF:out_max={file}:tx:MAX',
+    'DEF:inc_min={file}:rx:MIN',
+    'DEF:inc_avg={file}:rx:AVERAGE',
+    'DEF:inc_max={file}:rx:MAX',
+    'CDEF:mytime=out_avg,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
+    'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+    'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
+    'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+    'CDEF:out_bit_min=out_min,8,*',
+    'CDEF:out_bit_avg=out_avg,8,*',
+    'CDEF:out_bit_max=out_max,8,*',
+    'CDEF:inc_bit_min=inc_min,8,*',
+    'CDEF:inc_bit_avg=inc_avg,8,*',
+    'CDEF:inc_bit_max=inc_max,8,*',
+    'CDEF:overlap=out_bit_avg,inc_bit_avg,GT,inc_bit_avg,out_bit_avg,IF',
+    "AREA:out_bit_avg#$HalfGreen",
+    "AREA:inc_bit_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:out_bit_avg#$FullGreen:Written",
+    'GPRINT:out_bit_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:out_bit_max:MAX:%5.1lf%s Max,',
+    'GPRINT:out_bit_avg:LAST:%5.1lf%s Last',
+    'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+    "LINE1:inc_bit_avg#$FullBlue:Read   ",
+    'GPRINT:inc_bit_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:inc_bit_max:MAX:%5.1lf%s Max,',
+    'GPRINT:inc_bit_avg:LAST:%5.1lf%s Last',
+    'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+    ],
+    memcached_ops => ['-v', 'Ops',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Ops",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    memory => ['-b', '1024', '-v', 'Bytes',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Memory",
+    'GPRINT:min:MIN:%5.1lf%sbyte Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sbyte Avg,',
+    'GPRINT:max:MAX:%5.1lf%sbyte Max,',
+    'GPRINT:avg:LAST:%5.1lf%sbyte Last\l'
+    ],
+    old_memory => [
+    'DEF:used_avg={file}:used:AVERAGE',
+    'DEF:free_avg={file}:free:AVERAGE',
+    'DEF:buffers_avg={file}:buffers:AVERAGE',
+    'DEF:cached_avg={file}:cached:AVERAGE',
+    'DEF:used_min={file}:used:MIN',
+    'DEF:free_min={file}:free:MIN',
+    'DEF:buffers_min={file}:buffers:MIN',
+    'DEF:cached_min={file}:cached:MIN',
+    'DEF:used_max={file}:used:MAX',
+    'DEF:free_max={file}:free:MAX',
+    'DEF:buffers_max={file}:buffers:MAX',
+    'DEF:cached_max={file}:cached:MAX',
+    'CDEF:cached_avg_nn=cached_avg,UN,0,cached_avg,IF',
+    'CDEF:buffers_avg_nn=buffers_avg,UN,0,buffers_avg,IF',
+    'CDEF:free_cached_buffers_used=free_avg,cached_avg_nn,+,buffers_avg_nn,+,used_avg,+',
+    'CDEF:cached_buffers_used=cached_avg,buffers_avg_nn,+,used_avg,+',
+    'CDEF:buffers_used=buffers_avg,used_avg,+',
+    "AREA:free_cached_buffers_used#$HalfGreen",
+    "AREA:cached_buffers_used#$HalfBlue",
+    "AREA:buffers_used#$HalfYellow",
+    "AREA:used_avg#$HalfRed",
+    "LINE1:free_cached_buffers_used#$FullGreen:Free        ",
+    'GPRINT:free_min:MIN:%5.1lf%s Min,',
+    'GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:free_max:MAX:%5.1lf%s Max,',
+    'GPRINT:free_avg:LAST:%5.1lf%s Last\n',
+    "LINE1:cached_buffers_used#$FullBlue:Page cache  ",
+    'GPRINT:cached_min:MIN:%5.1lf%s Min,',
+    'GPRINT:cached_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:cached_max:MAX:%5.1lf%s Max,',
+    'GPRINT:cached_avg:LAST:%5.1lf%s Last\n',
+    "LINE1:buffers_used#$FullYellow:Buffer cache",
+    'GPRINT:buffers_min:MIN:%5.1lf%s Min,',
+    'GPRINT:buffers_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:buffers_max:MAX:%5.1lf%s Max,',
+    'GPRINT:buffers_avg:LAST:%5.1lf%s Last\n',
+    "LINE1:used_avg#$FullRed:Used        ",
+    'GPRINT:used_min:MIN:%5.1lf%s Min,',
+    'GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:used_max:MAX:%5.1lf%s Max,',
+    'GPRINT:used_avg:LAST:%5.1lf%s Last'
+    ],
+    mysql_commands => ['-v', 'Issues/s',
+    "DEF:val_avg={file}:value:AVERAGE",
+    "DEF:val_min={file}:value:MIN",
+    "DEF:val_max={file}:value:MAX",
+    "AREA:val_max#$HalfBlue",
+    "AREA:val_min#$Canvas",
+    "LINE1:val_avg#$FullBlue:Issues/s",
+    'GPRINT:val_min:MIN:%5.2lf Min,',
+    'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
+    'GPRINT:val_max:MAX:%5.2lf Max,',
+    'GPRINT:val_avg:LAST:%5.2lf Last'
+    ],
+    mysql_handler => ['-v', 'Issues/s',
+    "DEF:val_avg={file}:value:AVERAGE",
+    "DEF:val_min={file}:value:MIN",
+    "DEF:val_max={file}:value:MAX",
+    "AREA:val_max#$HalfBlue",
+    "AREA:val_min#$Canvas",
+    "LINE1:val_avg#$FullBlue:Issues/s",
+    'GPRINT:val_min:MIN:%5.2lf Min,',
+    'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
+    'GPRINT:val_max:MAX:%5.2lf Max,',
+    'GPRINT:val_avg:LAST:%5.2lf Last'
+    ],
+    mysql_octets => ['-v', 'Bits/s',
+    'DEF:out_min={file}:tx:MIN',
+    'DEF:out_avg={file}:tx:AVERAGE',
+    'DEF:out_max={file}:tx:MAX',
+    'DEF:inc_min={file}:rx:MIN',
+    'DEF:inc_avg={file}:rx:AVERAGE',
+    'DEF:inc_max={file}:rx:MAX',
+    'CDEF:mytime=out_avg,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
+    'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+    'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
+    'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+    'CDEF:out_bit_min=out_min,8,*',
+    'CDEF:out_bit_avg=out_avg,8,*',
+    'CDEF:out_bit_max=out_max,8,*',
+    'CDEF:inc_bit_min=inc_min,8,*',
+    'CDEF:inc_bit_avg=inc_avg,8,*',
+    'CDEF:inc_bit_max=inc_max,8,*',
+    'CDEF:overlap=out_bit_avg,inc_bit_avg,GT,inc_bit_avg,out_bit_avg,IF',
+    "AREA:out_bit_avg#$HalfGreen",
+    "AREA:inc_bit_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:out_bit_avg#$FullGreen:Written",
+    'GPRINT:out_bit_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:out_bit_max:MAX:%5.1lf%s Max,',
+    'GPRINT:out_bit_avg:LAST:%5.1lf%s Last',
+    'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+    "LINE1:inc_bit_avg#$FullBlue:Read   ",
+    'GPRINT:inc_bit_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:inc_bit_max:MAX:%5.1lf%s Max,',
+    'GPRINT:inc_bit_avg:LAST:%5.1lf%s Last',
+    'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+    ],
+    mysql_qcache => ['-v', 'Queries/s',
+    "DEF:hits_min={file}:hits:MIN",
+    "DEF:hits_avg={file}:hits:AVERAGE",
+    "DEF:hits_max={file}:hits:MAX",
+    "DEF:inserts_min={file}:inserts:MIN",
+    "DEF:inserts_avg={file}:inserts:AVERAGE",
+    "DEF:inserts_max={file}:inserts:MAX",
+    "DEF:not_cached_min={file}:not_cached:MIN",
+    "DEF:not_cached_avg={file}:not_cached:AVERAGE",
+    "DEF:not_cached_max={file}:not_cached:MAX",
+    "DEF:lowmem_prunes_min={file}:lowmem_prunes:MIN",
+    "DEF:lowmem_prunes_avg={file}:lowmem_prunes:AVERAGE",
+    "DEF:lowmem_prunes_max={file}:lowmem_prunes:MAX",
+    "DEF:queries_min={file}:queries_in_cache:MIN",
+    "DEF:queries_avg={file}:queries_in_cache:AVERAGE",
+    "DEF:queries_max={file}:queries_in_cache:MAX",
+    "CDEF:unknown=queries_avg,UNKN,+",
+    "CDEF:not_cached_agg=hits_avg,inserts_avg,+,not_cached_avg,+",
+    "CDEF:inserts_agg=hits_avg,inserts_avg,+",
+    "CDEF:hits_agg=hits_avg",
+    "AREA:not_cached_agg#$HalfYellow",
+    "AREA:inserts_agg#$HalfBlue",
+    "AREA:hits_agg#$HalfGreen",
+    "LINE1:not_cached_agg#$FullYellow:Not Cached      ",
+    'GPRINT:not_cached_min:MIN:%5.2lf Min,',
+    'GPRINT:not_cached_avg:AVERAGE:%5.2lf Avg,',
+    'GPRINT:not_cached_max:MAX:%5.2lf Max,',
+    'GPRINT:not_cached_avg:LAST:%5.2lf Last\l',
+    "LINE1:inserts_agg#$FullBlue:Inserts         ",
+    'GPRINT:inserts_min:MIN:%5.2lf Min,',
+    'GPRINT:inserts_avg:AVERAGE:%5.2lf Avg,',
+    'GPRINT:inserts_max:MAX:%5.2lf Max,',
+    'GPRINT:inserts_avg:LAST:%5.2lf Last\l',
+    "LINE1:hits_agg#$FullGreen:Hits            ",
+    'GPRINT:hits_min:MIN:%5.2lf Min,',
+    'GPRINT:hits_avg:AVERAGE:%5.2lf Avg,',
+    'GPRINT:hits_max:MAX:%5.2lf Max,',
+    'GPRINT:hits_avg:LAST:%5.2lf Last\l',
+    "LINE1:lowmem_prunes_avg#$FullRed:Lowmem Prunes   ",
+    'GPRINT:lowmem_prunes_min:MIN:%5.2lf Min,',
+    'GPRINT:lowmem_prunes_avg:AVERAGE:%5.2lf Avg,',
+    'GPRINT:lowmem_prunes_max:MAX:%5.2lf Max,',
+    'GPRINT:lowmem_prunes_avg:LAST:%5.2lf Last\l',
+    "LINE1:unknown#$Canvas:Queries in cache",
+    'GPRINT:queries_min:MIN:%5.0lf Min,',
+    'GPRINT:queries_avg:AVERAGE:%5.0lf Avg,',
+    'GPRINT:queries_max:MAX:%5.0lf Max,',
+    'GPRINT:queries_avg:LAST:%5.0lf Last\l'
+    ],
+    mysql_threads => ['-v', 'Threads',
+    "DEF:running_min={file}:running:MIN",
+    "DEF:running_avg={file}:running:AVERAGE",
+    "DEF:running_max={file}:running:MAX",
+    "DEF:connected_min={file}:connected:MIN",
+    "DEF:connected_avg={file}:connected:AVERAGE",
+    "DEF:connected_max={file}:connected:MAX",
+    "DEF:cached_min={file}:cached:MIN",
+    "DEF:cached_avg={file}:cached:AVERAGE",
+    "DEF:cached_max={file}:cached:MAX",
+    "DEF:created_min={file}:created:MIN",
+    "DEF:created_avg={file}:created:AVERAGE",
+    "DEF:created_max={file}:created:MAX",
+    "CDEF:unknown=created_avg,UNKN,+",
+    "CDEF:cached_agg=connected_avg,cached_avg,+",
+    "AREA:cached_agg#$HalfGreen",
+    "AREA:connected_avg#$HalfBlue",
+    "AREA:running_avg#$HalfRed",
+    "LINE1:cached_agg#$FullGreen:Cached   ",
+    'GPRINT:cached_min:MIN:%5.1lf Min,',
+    'GPRINT:cached_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:cached_max:MAX:%5.1lf Max,',
+    'GPRINT:cached_avg:LAST:%5.1lf Last\l',
+    "LINE1:connected_avg#$FullBlue:Connected",
+    'GPRINT:connected_min:MIN:%5.1lf Min,',
+    'GPRINT:connected_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:connected_max:MAX:%5.1lf Max,',
+    'GPRINT:connected_avg:LAST:%5.1lf Last\l',
+    "LINE1:running_avg#$FullRed:Running  ",
+    'GPRINT:running_min:MIN:%5.1lf Min,',
+    'GPRINT:running_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:running_max:MAX:%5.1lf Max,',
+    'GPRINT:running_avg:LAST:%5.1lf Last\l',
+    "LINE1:unknown#$Canvas:Created  ",
+    'GPRINT:created_min:MIN:%5.0lf Min,',
+    'GPRINT:created_avg:AVERAGE:%5.0lf Avg,',
+    'GPRINT:created_max:MAX:%5.0lf Max,',
+    'GPRINT:created_avg:LAST:%5.0lf Last\l'
+    ],
+    nfs_procedure => ['-v', 'Issues/s',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Issues/s",
+    'GPRINT:min:MIN:%6.2lf Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:max:MAX:%6.2lf Max,',
+    'GPRINT:avg:LAST:%6.2lf Last\l'
+    ],
+    nfs3_procedures => [
+    "DEF:null_avg={file}:null:AVERAGE",
+    "DEF:getattr_avg={file}:getattr:AVERAGE",
+    "DEF:setattr_avg={file}:setattr:AVERAGE",
+    "DEF:lookup_avg={file}:lookup:AVERAGE",
+    "DEF:access_avg={file}:access:AVERAGE",
+    "DEF:readlink_avg={file}:readlink:AVERAGE",
+    "DEF:read_avg={file}:read:AVERAGE",
+    "DEF:write_avg={file}:write:AVERAGE",
+    "DEF:create_avg={file}:create:AVERAGE",
+    "DEF:mkdir_avg={file}:mkdir:AVERAGE",
+    "DEF:symlink_avg={file}:symlink:AVERAGE",
+    "DEF:mknod_avg={file}:mknod:AVERAGE",
+    "DEF:remove_avg={file}:remove:AVERAGE",
+    "DEF:rmdir_avg={file}:rmdir:AVERAGE",
+    "DEF:rename_avg={file}:rename:AVERAGE",
+    "DEF:link_avg={file}:link:AVERAGE",
+    "DEF:readdir_avg={file}:readdir:AVERAGE",
+    "DEF:readdirplus_avg={file}:readdirplus:AVERAGE",
+    "DEF:fsstat_avg={file}:fsstat:AVERAGE",
+    "DEF:fsinfo_avg={file}:fsinfo:AVERAGE",
+    "DEF:pathconf_avg={file}:pathconf:AVERAGE",
+    "DEF:commit_avg={file}:commit:AVERAGE",
+    "DEF:null_max={file}:null:MAX",
+    "DEF:getattr_max={file}:getattr:MAX",
+    "DEF:setattr_max={file}:setattr:MAX",
+    "DEF:lookup_max={file}:lookup:MAX",
+    "DEF:access_max={file}:access:MAX",
+    "DEF:readlink_max={file}:readlink:MAX",
+    "DEF:read_max={file}:read:MAX",
+    "DEF:write_max={file}:write:MAX",
+    "DEF:create_max={file}:create:MAX",
+    "DEF:mkdir_max={file}:mkdir:MAX",
+    "DEF:symlink_max={file}:symlink:MAX",
+    "DEF:mknod_max={file}:mknod:MAX",
+    "DEF:remove_max={file}:remove:MAX",
+    "DEF:rmdir_max={file}:rmdir:MAX",
+    "DEF:rename_max={file}:rename:MAX",
+    "DEF:link_max={file}:link:MAX",
+    "DEF:readdir_max={file}:readdir:MAX",
+    "DEF:readdirplus_max={file}:readdirplus:MAX",
+    "DEF:fsstat_max={file}:fsstat:MAX",
+    "DEF:fsinfo_max={file}:fsinfo:MAX",
+    "DEF:pathconf_max={file}:pathconf:MAX",
+    "DEF:commit_max={file}:commit:MAX",
+    "CDEF:other_avg=null_avg,readlink_avg,create_avg,mkdir_avg,symlink_avg,mknod_avg,remove_avg,rmdir_avg,rename_avg,link_avg,readdir_avg,readdirplus_avg,fsstat_avg,fsinfo_avg,pathconf_avg,+,+,+,+,+,+,+,+,+,+,+,+,+,+",
+    "CDEF:other_max=null_max,readlink_max,create_max,mkdir_max,symlink_max,mknod_max,remove_max,rmdir_max,rename_max,link_max,readdir_max,readdirplus_max,fsstat_max,fsinfo_max,pathconf_max,+,+,+,+,+,+,+,+,+,+,+,+,+,+",
+    "CDEF:stack_read=read_avg",
+    "CDEF:stack_getattr=stack_read,getattr_avg,+",
+    "CDEF:stack_access=stack_getattr,access_avg,+",
+    "CDEF:stack_lookup=stack_access,lookup_avg,+",
+    "CDEF:stack_write=stack_lookup,write_avg,+",
+    "CDEF:stack_commit=stack_write,commit_avg,+",
+    "CDEF:stack_setattr=stack_commit,setattr_avg,+",
+    "CDEF:stack_other=stack_setattr,other_avg,+",
+    "AREA:stack_other#$HalfRed",
+    "AREA:stack_setattr#$HalfGreen",
+    "AREA:stack_commit#$HalfYellow",
+    "AREA:stack_write#$HalfGreen",
+    "AREA:stack_lookup#$HalfBlue",
+    "AREA:stack_access#$HalfMagenta",
+    "AREA:stack_getattr#$HalfCyan",
+    "AREA:stack_read#$HalfBlue",
+    "LINE1:stack_other#$FullRed:Other  ",
+    'GPRINT:other_max:MAX:%5.1lf Max,',
+    'GPRINT:other_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:other_avg:LAST:%5.1lf Last\l',
+    "LINE1:stack_setattr#$FullGreen:setattr",
+    'GPRINT:setattr_max:MAX:%5.1lf Max,',
+    'GPRINT:setattr_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:setattr_avg:LAST:%5.1lf Last\l',
+    "LINE1:stack_commit#$FullYellow:commit ",
+    'GPRINT:commit_max:MAX:%5.1lf Max,',
+    'GPRINT:commit_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:commit_avg:LAST:%5.1lf Last\l',
+    "LINE1:stack_write#$FullGreen:write  ",
+    'GPRINT:write_max:MAX:%5.1lf Max,',
+    'GPRINT:write_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:write_avg:LAST:%5.1lf Last\l',
+    "LINE1:stack_lookup#$FullBlue:lookup ",
+    'GPRINT:lookup_max:MAX:%5.1lf Max,',
+    'GPRINT:lookup_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:lookup_avg:LAST:%5.1lf Last\l',
+    "LINE1:stack_access#$FullMagenta:access ",
+    'GPRINT:access_max:MAX:%5.1lf Max,',
+    'GPRINT:access_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:access_avg:LAST:%5.1lf Last\l',
+    "LINE1:stack_getattr#$FullCyan:getattr",
+    'GPRINT:getattr_max:MAX:%5.1lf Max,',
+    'GPRINT:getattr_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:getattr_avg:LAST:%5.1lf Last\l',
+    "LINE1:stack_read#$FullBlue:read   ",
+    'GPRINT:read_max:MAX:%5.1lf Max,',
+    'GPRINT:read_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:read_avg:LAST:%5.1lf Last\l'
+    ],
+    partition => [
+    "DEF:rbyte_avg={file}:rbytes:AVERAGE",
+    "DEF:rbyte_min={file}:rbytes:MIN",
+    "DEF:rbyte_max={file}:rbytes:MAX",
+    "DEF:wbyte_avg={file}:wbytes:AVERAGE",
+    "DEF:wbyte_min={file}:wbytes:MIN",
+    "DEF:wbyte_max={file}:wbytes:MAX",
+    'CDEF:overlap=wbyte_avg,rbyte_avg,GT,rbyte_avg,wbyte_avg,IF',
+    "AREA:wbyte_avg#$HalfGreen",
+    "AREA:rbyte_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:wbyte_avg#$FullGreen:Write",
+    'GPRINT:wbyte_min:MIN:%5.1lf%s Min,',
+    'GPRINT:wbyte_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:wbyte_max:MAX:%5.1lf%s Max,',
+    'GPRINT:wbyte_avg:LAST:%5.1lf%s Last\l',
+    "LINE1:rbyte_avg#$FullBlue:Read ",
+    'GPRINT:rbyte_min:MIN:%5.1lf%s Min,',
+    'GPRINT:rbyte_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:rbyte_max:MAX:%5.1lf%s Max,',
+    'GPRINT:rbyte_avg:LAST:%5.1lf%s Last\l'
+    ],
+    percent => ['-v', 'Percent',
+    'DEF:avg={file}:percent:AVERAGE',
+    'DEF:min={file}:percent:MIN',
+    'DEF:max={file}:percent:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Percent",
+    'GPRINT:min:MIN:%5.1lf%% Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%% Avg,',
+    'GPRINT:max:MAX:%5.1lf%% Max,',
+    'GPRINT:avg:LAST:%5.1lf%% Last\l'
+    ],
+    ping => ['DEF:ping_avg={file}:ping:AVERAGE',
+    'DEF:ping_min={file}:ping:MIN',
+    'DEF:ping_max={file}:ping:MAX',
+    "AREA:ping_max#$HalfBlue",
+    "AREA:ping_min#$Canvas",
+    "LINE1:ping_avg#$FullBlue:Ping",
+    'GPRINT:ping_min:MIN:%4.1lf ms Min,',
+    'GPRINT:ping_avg:AVERAGE:%4.1lf ms Avg,',
+    'GPRINT:ping_max:MAX:%4.1lf ms Max,',
+    'GPRINT:ping_avg:LAST:%4.1lf ms Last'],
+    pg_blks => ['DEF:pg_blks_avg={file}:value:AVERAGE',
+    'DEF:pg_blks_min={file}:value:MIN',
+    'DEF:pg_blks_max={file}:value:MAX',
+    "AREA:pg_blks_max#$HalfBlue",
+    "AREA:pg_blks_min#$Canvas",
+    "LINE1:pg_blks_avg#$FullBlue:Blocks",
+    'GPRINT:pg_blks_min:MIN:%4.1lf%s Min,',
+    'GPRINT:pg_blks_avg:AVERAGE:%4.1lf%s Avg,',
+    'GPRINT:pg_blks_max:MAX:%4.1lf%s Max,',
+    'GPRINT:pg_blks_avg:LAST:%4.1lf%s Last'],
+    pg_db_size => ['DEF:pg_db_size_avg={file}:value:AVERAGE',
+    'DEF:pg_db_size_min={file}:value:MIN',
+    'DEF:pg_db_size_max={file}:value:MAX',
+    "AREA:pg_db_size_max#$HalfBlue",
+    "AREA:pg_db_size_min#$Canvas",
+    "LINE1:pg_db_size_avg#$FullBlue:Bytes",
+    'GPRINT:pg_db_size_min:MIN:%4.1lf%s Min,',
+    'GPRINT:pg_db_size_avg:AVERAGE:%4.1lf%s Avg,',
+    'GPRINT:pg_db_size_max:MAX:%4.1lf%s Max,',
+    'GPRINT:pg_db_size_avg:LAST:%4.1lf%s Last'],
+    pg_n_tup_c => ['DEF:pg_n_tup_avg={file}:value:AVERAGE',
+    'DEF:pg_n_tup_min={file}:value:MIN',
+    'DEF:pg_n_tup_max={file}:value:MAX',
+    "AREA:pg_n_tup_max#$HalfBlue",
+    "AREA:pg_n_tup_min#$Canvas",
+    "LINE1:pg_n_tup_avg#$FullBlue:Tuples",
+    'GPRINT:pg_n_tup_min:MIN:%4.1lf%s Min,',
+    'GPRINT:pg_n_tup_avg:AVERAGE:%4.1lf%s Avg,',
+    'GPRINT:pg_n_tup_max:MAX:%4.1lf%s Max,',
+    'GPRINT:pg_n_tup_avg:LAST:%4.1lf%s Last'],
+    pg_n_tup_g => ['DEF:pg_n_tup_avg={file}:value:AVERAGE',
+    'DEF:pg_n_tup_min={file}:value:MIN',
+    'DEF:pg_n_tup_max={file}:value:MAX',
+    "AREA:pg_n_tup_max#$HalfBlue",
+    "AREA:pg_n_tup_min#$Canvas",
+    "LINE1:pg_n_tup_avg#$FullBlue:Tuples",
+    'GPRINT:pg_n_tup_min:MIN:%4.1lf%s Min,',
+    'GPRINT:pg_n_tup_avg:AVERAGE:%4.1lf%s Avg,',
+    'GPRINT:pg_n_tup_max:MAX:%4.1lf%s Max,',
+    'GPRINT:pg_n_tup_avg:LAST:%4.1lf%s Last'],
+    pg_numbackends => ['DEF:pg_numbackends_avg={file}:value:AVERAGE',
+    'DEF:pg_numbackends_min={file}:value:MIN',
+    'DEF:pg_numbackends_max={file}:value:MAX',
+    "AREA:pg_numbackends_max#$HalfBlue",
+    "AREA:pg_numbackends_min#$Canvas",
+    "LINE1:pg_numbackends_avg#$FullBlue:Backends",
+    'GPRINT:pg_numbackends_min:MIN:%4.1lf%s Min,',
+    'GPRINT:pg_numbackends_avg:AVERAGE:%4.1lf%s Avg,',
+    'GPRINT:pg_numbackends_max:MAX:%4.1lf%s Max,',
+    'GPRINT:pg_numbackends_avg:LAST:%4.1lf%s Last'],
+    pg_scan => ['DEF:pg_scan_avg={file}:value:AVERAGE',
+    'DEF:pg_scan_min={file}:value:MIN',
+    'DEF:pg_scan_max={file}:value:MAX',
+    "AREA:pg_scan_max#$HalfBlue",
+    "AREA:pg_scan_min#$Canvas",
+    "LINE1:pg_scan_avg#$FullBlue:Scans",
+    'GPRINT:pg_scan_min:MIN:%4.1lf%s Min,',
+    'GPRINT:pg_scan_avg:AVERAGE:%4.1lf%s Avg,',
+    'GPRINT:pg_scan_max:MAX:%4.1lf%s Max,',
+    'GPRINT:pg_scan_avg:LAST:%4.1lf%s Last'],
+    pg_xact => ['DEF:pg_xact_avg={file}:value:AVERAGE',
+    'DEF:pg_xact_min={file}:value:MIN',
+    'DEF:pg_xact_max={file}:value:MAX',
+    "AREA:pg_xact_max#$HalfBlue",
+    "AREA:pg_xact_min#$Canvas",
+    "LINE1:pg_xact_avg#$FullBlue:Transactions",
+    'GPRINT:pg_xact_min:MIN:%4.1lf%s Min,',
+    'GPRINT:pg_xact_avg:AVERAGE:%4.1lf%s Avg,',
+    'GPRINT:pg_xact_max:MAX:%4.1lf%s Max,',
+    'GPRINT:pg_xact_avg:LAST:%4.1lf%s Last'],
+    power => ['-v', 'Watt',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Watt",
+    'GPRINT:min:MIN:%5.1lf%sW Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sW Avg,',
+    'GPRINT:max:MAX:%5.1lf%sW Max,',
+    'GPRINT:avg:LAST:%5.1lf%sW Last\l'
+    ],
+    processes => [
+    "DEF:running_avg={file}:running:AVERAGE",
+    "DEF:running_min={file}:running:MIN",
+    "DEF:running_max={file}:running:MAX",
+    "DEF:sleeping_avg={file}:sleeping:AVERAGE",
+    "DEF:sleeping_min={file}:sleeping:MIN",
+    "DEF:sleeping_max={file}:sleeping:MAX",
+    "DEF:zombies_avg={file}:zombies:AVERAGE",
+    "DEF:zombies_min={file}:zombies:MIN",
+    "DEF:zombies_max={file}:zombies:MAX",
+    "DEF:stopped_avg={file}:stopped:AVERAGE",
+    "DEF:stopped_min={file}:stopped:MIN",
+    "DEF:stopped_max={file}:stopped:MAX",
+    "DEF:paging_avg={file}:paging:AVERAGE",
+    "DEF:paging_min={file}:paging:MIN",
+    "DEF:paging_max={file}:paging:MAX",
+    "DEF:blocked_avg={file}:blocked:AVERAGE",
+    "DEF:blocked_min={file}:blocked:MIN",
+    "DEF:blocked_max={file}:blocked:MAX",
+    'CDEF:paging_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,blocked_avg,paging_avg,+,+,+,+,+',
+    'CDEF:blocked_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,blocked_avg,+,+,+,+',
+    'CDEF:zombies_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,+,+,+',
+    'CDEF:stopped_acc=sleeping_avg,running_avg,stopped_avg,+,+',
+    'CDEF:running_acc=sleeping_avg,running_avg,+',
+    'CDEF:sleeping_acc=sleeping_avg',
+    "AREA:paging_acc#$HalfYellow",
+    "AREA:blocked_acc#$HalfCyan",
+    "AREA:zombies_acc#$HalfRed",
+    "AREA:stopped_acc#$HalfMagenta",
+    "AREA:running_acc#$HalfGreen",
+    "AREA:sleeping_acc#$HalfBlue",
+    "LINE1:paging_acc#$FullYellow:Paging  ",
+    'GPRINT:paging_min:MIN:%5.1lf Min,',
+    'GPRINT:paging_avg:AVERAGE:%5.1lf Average,',
+    'GPRINT:paging_max:MAX:%5.1lf Max,',
+    'GPRINT:paging_avg:LAST:%5.1lf Last\l',
+    "LINE1:blocked_acc#$FullCyan:Blocked ",
+    'GPRINT:blocked_min:MIN:%5.1lf Min,',
+    'GPRINT:blocked_avg:AVERAGE:%5.1lf Average,',
+    'GPRINT:blocked_max:MAX:%5.1lf Max,',
+    'GPRINT:blocked_avg:LAST:%5.1lf Last\l',
+    "LINE1:zombies_acc#$FullRed:Zombies ",
+    'GPRINT:zombies_min:MIN:%5.1lf Min,',
+    'GPRINT:zombies_avg:AVERAGE:%5.1lf Average,',
+    'GPRINT:zombies_max:MAX:%5.1lf Max,',
+    'GPRINT:zombies_avg:LAST:%5.1lf Last\l',
+    "LINE1:stopped_acc#$FullMagenta:Stopped ",
+    'GPRINT:stopped_min:MIN:%5.1lf Min,',
+    'GPRINT:stopped_avg:AVERAGE:%5.1lf Average,',
+    'GPRINT:stopped_max:MAX:%5.1lf Max,',
+    'GPRINT:stopped_avg:LAST:%5.1lf Last\l',
+    "LINE1:running_acc#$FullGreen:Running ",
+    'GPRINT:running_min:MIN:%5.1lf Min,',
+    'GPRINT:running_avg:AVERAGE:%5.1lf Average,',
+    'GPRINT:running_max:MAX:%5.1lf Max,',
+    'GPRINT:running_avg:LAST:%5.1lf Last\l',
+    "LINE1:sleeping_acc#$FullBlue:Sleeping",
+    'GPRINT:sleeping_min:MIN:%5.1lf Min,',
+    'GPRINT:sleeping_avg:AVERAGE:%5.1lf Average,',
+    'GPRINT:sleeping_max:MAX:%5.1lf Max,',
+    'GPRINT:sleeping_avg:LAST:%5.1lf Last\l'
+    ],
+    ps_count => ['-v', 'Processes',
+    'DEF:procs_avg={file}:processes:AVERAGE',
+    'DEF:procs_min={file}:processes:MIN',
+    'DEF:procs_max={file}:processes:MAX',
+    'DEF:thrds_avg={file}:threads:AVERAGE',
+    'DEF:thrds_min={file}:threads:MIN',
+    'DEF:thrds_max={file}:threads:MAX',
+    "AREA:thrds_avg#$HalfBlue",
+    "AREA:procs_avg#$HalfRed",
+    "LINE1:thrds_avg#$FullBlue:Threads  ",
+    'GPRINT:thrds_min:MIN:%5.1lf Min,',
+    'GPRINT:thrds_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:thrds_max:MAX:%5.1lf Max,',
+    'GPRINT:thrds_avg:LAST:%5.1lf Last\l',
+    "LINE1:procs_avg#$FullRed:Processes",
+    'GPRINT:procs_min:MIN:%5.1lf Min,',
+    'GPRINT:procs_avg:AVERAGE:%5.1lf Avg,',
+    'GPRINT:procs_max:MAX:%5.1lf Max,',
+    'GPRINT:procs_avg:LAST:%5.1lf Last\l'
+    ],
+    ps_cputime => ['-v', 'Jiffies',
+    'DEF:user_avg_raw={file}:user:AVERAGE',
+    'DEF:user_min_raw={file}:user:MIN',
+    'DEF:user_max_raw={file}:user:MAX',
+    'DEF:syst_avg_raw={file}:syst:AVERAGE',
+    'DEF:syst_min_raw={file}:syst:MIN',
+    'DEF:syst_max_raw={file}:syst:MAX',
+    'CDEF:user_avg=user_avg_raw,1000000,/',
+    'CDEF:user_min=user_min_raw,1000000,/',
+    'CDEF:user_max=user_max_raw,1000000,/',
+    'CDEF:syst_avg=syst_avg_raw,1000000,/',
+    'CDEF:syst_min=syst_min_raw,1000000,/',
+    'CDEF:syst_max=syst_max_raw,1000000,/',
+    'CDEF:user_syst=syst_avg,UN,0,syst_avg,IF,user_avg,+',
+    "AREA:user_syst#$HalfBlue",
+    "AREA:syst_avg#$HalfRed",
+    "LINE1:user_syst#$FullBlue:User  ",
+    'GPRINT:user_min:MIN:%5.1lf%s Min,',
+    'GPRINT:user_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:user_max:MAX:%5.1lf%s Max,',
+    'GPRINT:user_avg:LAST:%5.1lf%s Last\l',
+    "LINE1:syst_avg#$FullRed:System",
+    'GPRINT:syst_min:MIN:%5.1lf%s Min,',
+    'GPRINT:syst_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:syst_max:MAX:%5.1lf%s Max,',
+    'GPRINT:syst_avg:LAST:%5.1lf%s Last\l'
+    ],
+    ps_pagefaults => ['-v', 'Pagefaults/s',
+    'DEF:minor_avg={file}:minflt:AVERAGE',
+    'DEF:minor_min={file}:minflt:MIN',
+    'DEF:minor_max={file}:minflt:MAX',
+    'DEF:major_avg={file}:majflt:AVERAGE',
+    'DEF:major_min={file}:majflt:MIN',
+    'DEF:major_max={file}:majflt:MAX',
+    'CDEF:minor_major=major_avg,UN,0,major_avg,IF,minor_avg,+',
+    "AREA:minor_major#$HalfBlue",
+    "AREA:major_avg#$HalfRed",
+    "LINE1:minor_major#$FullBlue:Minor",
+    'GPRINT:minor_min:MIN:%5.1lf%s Min,',
+    'GPRINT:minor_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:minor_max:MAX:%5.1lf%s Max,',
+    'GPRINT:minor_avg:LAST:%5.1lf%s Last\l',
+    "LINE1:major_avg#$FullRed:Major",
+    'GPRINT:major_min:MIN:%5.1lf%s Min,',
+    'GPRINT:major_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:major_max:MAX:%5.1lf%s Max,',
+    'GPRINT:major_avg:LAST:%5.1lf%s Last\l'
+    ],
+    ps_rss => ['-v', 'Bytes',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:avg#$HalfBlue",
+    "LINE1:avg#$FullBlue:RSS",
+    'GPRINT:min:MIN:%5.1lf%s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last\l'
+    ],
+    ps_state => ['-v', 'Processes',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Processes",
+    'GPRINT:min:MIN:%6.2lf Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+    'GPRINT:max:MAX:%6.2lf Max,',
+    'GPRINT:avg:LAST:%6.2lf Last\l'
+    ],
+    signal_noise => ['-v', 'dBm',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Noise",
+    'GPRINT:min:MIN:%5.1lf%sdBm Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sdBm Avg,',
+    'GPRINT:max:MAX:%5.1lf%sdBm Max,',
+    'GPRINT:avg:LAST:%5.1lf%sdBm Last\l'
+    ],
+    signal_power => ['-v', 'dBm',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Power",
+    'GPRINT:min:MIN:%5.1lf%sdBm Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sdBm Avg,',
+    'GPRINT:max:MAX:%5.1lf%sdBm Max,',
+    'GPRINT:avg:LAST:%5.1lf%sdBm Last\l'
+    ],
+    signal_quality => ['-v', '%',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Quality",
+    'GPRINT:min:MIN:%5.1lf%s%% Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,',
+    'GPRINT:max:MAX:%5.1lf%s%% Max,',
+    'GPRINT:avg:LAST:%5.1lf%s%% Last\l'
+    ],
+    swap => ['-v', 'Bytes', '-b', '1024',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Bytes",
+    'GPRINT:min:MIN:%6.2lf%sByte Min,',
+    'GPRINT:avg:AVERAGE:%6.2lf%sByte Avg,',
+    'GPRINT:max:MAX:%6.2lf%sByte Max,',
+    'GPRINT:avg:LAST:%6.2lf%sByte Last\l'
+    ],
+    old_swap => [
+    'DEF:used_avg={file}:used:AVERAGE',
+    'DEF:used_min={file}:used:MIN',
+    'DEF:used_max={file}:used:MAX',
+    'DEF:free_avg={file}:free:AVERAGE',
+    'DEF:free_min={file}:free:MIN',
+    'DEF:free_max={file}:free:MAX',
+    'DEF:cach_avg={file}:cached:AVERAGE',
+    'DEF:cach_min={file}:cached:MIN',
+    'DEF:cach_max={file}:cached:MAX',
+    'DEF:resv_avg={file}:resv:AVERAGE',
+    'DEF:resv_min={file}:resv:MIN',
+    'DEF:resv_max={file}:resv:MAX',
+    'CDEF:cach_avg_notnull=cach_avg,UN,0,cach_avg,IF',
+    'CDEF:resv_avg_notnull=resv_avg,UN,0,resv_avg,IF',
+    'CDEF:used_acc=used_avg',
+    'CDEF:resv_acc=used_acc,resv_avg_notnull,+',
+    'CDEF:cach_acc=resv_acc,cach_avg_notnull,+',
+    'CDEF:free_acc=cach_acc,free_avg,+',
+    "AREA:free_acc#$HalfGreen",
+    "AREA:cach_acc#$HalfBlue",
+    "AREA:resv_acc#$HalfYellow",
+    "AREA:used_acc#$HalfRed",
+    "LINE1:free_acc#$FullGreen:Free    ",
+    'GPRINT:free_min:MIN:%5.1lf%s Min,',
+    'GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:free_max:MAX:%5.1lf%s Max,',
+    'GPRINT:free_avg:LAST:%5.1lf%s Last\n',
+    "LINE1:cach_acc#$FullBlue:Cached  ",
+    'GPRINT:cach_min:MIN:%5.1lf%s Min,',
+    'GPRINT:cach_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:cach_max:MAX:%5.1lf%s Max,',
+    'GPRINT:cach_avg:LAST:%5.1lf%s Last\l',
+    "LINE1:resv_acc#$FullYellow:Reserved",
+    'GPRINT:resv_min:MIN:%5.1lf%s Min,',
+    'GPRINT:resv_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:resv_max:MAX:%5.1lf%s Max,',
+    'GPRINT:resv_avg:LAST:%5.1lf%s Last\n',
+    "LINE1:used_acc#$FullRed:Used    ",
+    'GPRINT:used_min:MIN:%5.1lf%s Min,',
+    'GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:used_max:MAX:%5.1lf%s Max,',
+    'GPRINT:used_avg:LAST:%5.1lf%s Last\l'
+    ],
+    tcp_connections => ['-v', 'Connections',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Connections",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    temperature => ['-v', 'Celsius',
+    'DEF:temp_avg={file}:value:AVERAGE',
+    'DEF:temp_min={file}:value:MIN',
+    'DEF:temp_max={file}:value:MAX',
+    'CDEF:average=temp_avg,0.2,*,PREV,UN,temp_avg,PREV,IF,0.8,*,+',
+    "AREA:temp_max#$HalfRed",
+    "AREA:temp_min#$Canvas",
+    "LINE1:temp_avg#$FullRed:Temperature",
+    'GPRINT:temp_min:MIN:%4.1lf Min,',
+    'GPRINT:temp_avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:temp_max:MAX:%4.1lf Max,',
+    'GPRINT:temp_avg:LAST:%4.1lf Last\l'
+    ],
+    timeleft => ['-v', 'Minutes',
+    'DEF:avg={file}:timeleft:AVERAGE',
+    'DEF:min={file}:timeleft:MIN',
+    'DEF:max={file}:timeleft:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Time left [min]",
+    'GPRINT:min:MIN:%5.1lf%s Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:max:MAX:%5.1lf%s Max,',
+    'GPRINT:avg:LAST:%5.1lf%s Last\l'
+    ],
+    time_offset => [ # NTPd
+    'DEF:s_avg={file}:seconds:AVERAGE',
+    'DEF:s_min={file}:seconds:MIN',
+    'DEF:s_max={file}:seconds:MAX',
+    "AREA:s_max#$HalfBlue",
+    "AREA:s_min#$Canvas",
+    "LINE1:s_avg#$FullBlue:{inst}",
+    'GPRINT:s_min:MIN:%7.3lf%s Min,',
+    'GPRINT:s_avg:AVERAGE:%7.3lf%s Avg,',
+    'GPRINT:s_max:MAX:%7.3lf%s Max,',
+    'GPRINT:s_avg:LAST:%7.3lf%s Last'
+    ],
+    if_octets => ['-v', 'Bits/s', '-l', '0',
+    'DEF:out_min_raw={file}:tx:MIN',
+    'DEF:out_avg_raw={file}:tx:AVERAGE',
+    'DEF:out_max_raw={file}:tx:MAX',
+    'DEF:inc_min_raw={file}:rx:MIN',
+    'DEF:inc_avg_raw={file}:rx:AVERAGE',
+    'DEF:inc_max_raw={file}:rx:MAX',
+    'CDEF:out_min=out_min_raw,8,*',
+    'CDEF:out_avg=out_avg_raw,8,*',
+    'CDEF:out_max=out_max_raw,8,*',
+    'CDEF:inc_min=inc_min_raw,8,*',
+    'CDEF:inc_avg=inc_avg_raw,8,*',
+    'CDEF:inc_max=inc_max_raw,8,*',
+    'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+    'CDEF:mytime=out_avg_raw,TIME,TIME,IF',
+    'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+    'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+    'CDEF:out_avg_sample=out_avg_raw,UN,0,out_avg_raw,IF,sample_len,*',
+    'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+    'CDEF:inc_avg_sample=inc_avg_raw,UN,0,inc_avg_raw,IF,sample_len,*',
+    'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+    "AREA:out_avg#$HalfGreen",
+    "AREA:inc_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:out_avg#$FullGreen:Outgoing",
+    'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:out_max:MAX:%5.1lf%s Max,',
+    'GPRINT:out_avg:LAST:%5.1lf%s Last',
+    'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+    "LINE1:inc_avg#$FullBlue:Incoming",
+    #'GPRINT:inc_min:MIN:%5.1lf %s Min,',
+    'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:inc_max:MAX:%5.1lf%s Max,',
+    'GPRINT:inc_avg:LAST:%5.1lf%s Last',
+    'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+    ],
+    cpufreq => [
+    'DEF:cpufreq_avg={file}:value:AVERAGE',
+    'DEF:cpufreq_min={file}:value:MIN',
+    'DEF:cpufreq_max={file}:value:MAX',
+    "AREA:cpufreq_max#$HalfBlue",
+    "AREA:cpufreq_min#$Canvas",
+    "LINE1:cpufreq_avg#$FullBlue:Frequency",
+    'GPRINT:cpufreq_min:MIN:%5.1lf%s Min,',
+    'GPRINT:cpufreq_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:cpufreq_max:MAX:%5.1lf%s Max,',
+    'GPRINT:cpufreq_avg:LAST:%5.1lf%s Last\l'
+    ],
+    multimeter => [
+    'DEF:multimeter_avg={file}:value:AVERAGE',
+    'DEF:multimeter_min={file}:value:MIN',
+    'DEF:multimeter_max={file}:value:MAX',
+    "AREA:multimeter_max#$HalfBlue",
+    "AREA:multimeter_min#$Canvas",
+    "LINE1:multimeter_avg#$FullBlue:Multimeter",
+    'GPRINT:multimeter_min:MIN:%4.1lf Min,',
+    'GPRINT:multimeter_avg:AVERAGE:%4.1lf Average,',
+    'GPRINT:multimeter_max:MAX:%4.1lf Max,',
+    'GPRINT:multimeter_avg:LAST:%4.1lf Last\l'
+    ],
+    users => ['-v', 'Users',
+    'DEF:users_avg={file}:users:AVERAGE',
+    'DEF:users_min={file}:users:MIN',
+    'DEF:users_max={file}:users:MAX',
+    "AREA:users_max#$HalfBlue",
+    "AREA:users_min#$Canvas",
+    "LINE1:users_avg#$FullBlue:Users",
+    'GPRINT:users_min:MIN:%4.1lf Min,',
+    'GPRINT:users_avg:AVERAGE:%4.1lf Average,',
+    'GPRINT:users_max:MAX:%4.1lf Max,',
+    'GPRINT:users_avg:LAST:%4.1lf Last\l'
+    ],
+    voltage => ['-v', 'Voltage',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Voltage",
+    'GPRINT:min:MIN:%5.1lf%sV Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sV Avg,',
+    'GPRINT:max:MAX:%5.1lf%sV Max,',
+    'GPRINT:avg:LAST:%5.1lf%sV Last\l'
+    ],
+    vs_threads => [
+    "DEF:avg={file}:value:AVERAGE",
+    "DEF:min={file}:value:MIN",
+    "DEF:max={file}:value:MAX",
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Threads",
+    'GPRINT:min:MIN:%5.1lf Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf Avg.,',
+    'GPRINT:max:MAX:%5.1lf Max,',
+    'GPRINT:avg:LAST:%5.1lf Last\l',
+    ],
+    vs_memory => ['-b', '1024', '-v', 'Bytes',
+    "DEF:avg={file}:value:AVERAGE",
+    "DEF:min={file}:value:MIN",
+    "DEF:max={file}:value:MAX",
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:",
+    'GPRINT:min:MIN:%5.1lf%sbytes Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf%sbytes Avg.,',
+    'GPRINT:max:MAX:%5.1lf%sbytes Max,',
+    'GPRINT:avg:LAST:%5.1lf%sbytes Last\l',
+    ],
+    vs_processes => [
+    "DEF:avg={file}:value:AVERAGE",
+    "DEF:min={file}:value:MIN",
+    "DEF:max={file}:value:MAX",
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Processes",
+    'GPRINT:min:MIN:%5.1lf Min,',
+    'GPRINT:avg:AVERAGE:%5.1lf Avg.,',
+    'GPRINT:max:MAX:%5.1lf Max,',
+    'GPRINT:avg:LAST:%5.1lf Last\l',
+    ],
+    vmpage_number => ['-v', 'Pages',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Number",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    vmpage_faults => [
+    "DEF:minf_avg={file}:minflt:AVERAGE",
+    "DEF:minf_min={file}:minflt:MIN",
+    "DEF:minf_max={file}:minflt:MAX",
+    "DEF:majf_avg={file}:majflt:AVERAGE",
+    "DEF:majf_min={file}:majflt:MIN",
+    "DEF:majf_max={file}:majflt:MAX",
+    'CDEF:overlap=majf_avg,minf_avg,GT,minf_avg,majf_avg,IF',
+    "AREA:majf_avg#$HalfGreen",
+    "AREA:minf_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:majf_avg#$FullGreen:Major",
+    'GPRINT:majf_min:MIN:%5.1lf%s Min,',
+    'GPRINT:majf_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:majf_max:MAX:%5.1lf%s Max,',
+    'GPRINT:majf_avg:LAST:%5.1lf%s Last\l',
+    "LINE1:minf_avg#$FullBlue:Minor",
+    'GPRINT:minf_min:MIN:%5.1lf%s Min,',
+    'GPRINT:minf_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:minf_max:MAX:%5.1lf%s Max,',
+    'GPRINT:minf_avg:LAST:%5.1lf%s Last\l'
+    ],
+    vmpage_io => [
+    "DEF:rpag_avg={file}:in:AVERAGE",
+    "DEF:rpag_min={file}:in:MIN",
+    "DEF:rpag_max={file}:in:MAX",
+    "DEF:wpag_avg={file}:out:AVERAGE",
+    "DEF:wpag_min={file}:out:MIN",
+    "DEF:wpag_max={file}:out:MAX",
+    'CDEF:overlap=wpag_avg,rpag_avg,GT,rpag_avg,wpag_avg,IF',
+    "AREA:wpag_avg#$HalfGreen",
+    "AREA:rpag_avg#$HalfBlue",
+    "AREA:overlap#$HalfBlueGreen",
+    "LINE1:wpag_avg#$FullGreen:OUT",
+    'GPRINT:wpag_min:MIN:%5.1lf%s Min,',
+    'GPRINT:wpag_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:wpag_max:MAX:%5.1lf%s Max,',
+    'GPRINT:wpag_avg:LAST:%5.1lf%s Last\l',
+    "LINE1:rpag_avg#$FullBlue:IN ",
+    'GPRINT:rpag_min:MIN:%5.1lf%s Min,',
+    'GPRINT:rpag_avg:AVERAGE:%5.1lf%s Avg,',
+    'GPRINT:rpag_max:MAX:%5.1lf%s Max,',
+    'GPRINT:rpag_avg:LAST:%5.1lf%s Last\l'
+    ],
+    vmpage_action => ['-v', 'Pages',
+    'DEF:avg={file}:value:AVERAGE',
+    'DEF:min={file}:value:MIN',
+    'DEF:max={file}:value:MAX',
+    "AREA:max#$HalfBlue",
+    "AREA:min#$Canvas",
+    "LINE1:avg#$FullBlue:Number",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+    virt_cpu_total => ['-v', 'Milliseconds',
+    'DEF:avg_raw={file}:ns:AVERAGE',
+    'DEF:min_raw={file}:ns:MIN',
+    'DEF:max_raw={file}:ns:MAX',
+    'CDEF:avg=avg_raw,1000000,/',
+    'CDEF:min=min_raw,1000000,/',
+    'CDEF:max=max_raw,1000000,/',
+    "AREA:avg#$HalfBlue",
+    "LINE1:avg#$FullBlue:CPU time",
+    'GPRINT:min:MIN:%4.1lf Min,',
+    'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+    'GPRINT:max:MAX:%4.1lf Max,',
+    'GPRINT:avg:LAST:%4.1lf Last\l'
+    ],
+  };
+  $GraphDefs->{'if_multicast'} = $GraphDefs->{'ipt_packets'};
+  $GraphDefs->{'if_tx_errors'} = $GraphDefs->{'if_rx_errors'};
+  $GraphDefs->{'dns_qtype'} = $GraphDefs->{'dns_opcode'};
+  $GraphDefs->{'dns_rcode'} = $GraphDefs->{'dns_opcode'};
+  $GraphDefs->{'vmpage_io-memory'} = $GraphDefs->{'vmpage_io'};
+  $GraphDefs->{'vmpage_io-swap'} = $GraphDefs->{'vmpage_io'};
+  $GraphDefs->{'virt_cpu_total'} = $GraphDefs->{'virt_cpu_total'};
+
+  $MetaGraphDefs->{'cpu'} = \&meta_graph_cpu;
+  $MetaGraphDefs->{'df_complex'} = \&meta_graph_df;
+  $MetaGraphDefs->{'dns_qtype'} = \&meta_graph_dns;
+  $MetaGraphDefs->{'dns_rcode'} = \&meta_graph_dns;
+  $MetaGraphDefs->{'if_rx_errors'} = \&meta_graph_if_rx_errors;
+  $MetaGraphDefs->{'if_tx_errors'} = \&meta_graph_if_rx_errors;
+  $MetaGraphDefs->{'memory'} = \&meta_graph_memory;
+  $MetaGraphDefs->{'nfs_procedure'} = \&meta_graph_nfs_procedure;
+  $MetaGraphDefs->{'ps_state'} = \&meta_graph_ps_state;
+  $MetaGraphDefs->{'swap'} = \&meta_graph_swap;
+  $MetaGraphDefs->{'mysql_commands'} = \&meta_graph_mysql_commands;
+  $MetaGraphDefs->{'mysql_handler'} = \&meta_graph_mysql_commands;
+  $MetaGraphDefs->{'tcp_connections'} = \&meta_graph_tcp_connections;
+  $MetaGraphDefs->{'vmpage_number'} = \&meta_graph_vmpage_number;
+  $MetaGraphDefs->{'vmpage_action'} = \&meta_graph_vmpage_action;
+} # load_graph_definitions
+
+sub meta_graph_generic_stack
+{
+  confess ("Wrong number of arguments") if (@_ != 2);
+
+  my $opts = shift;
+  my $sources = shift;
+  my $i;
+
+  my $timespan_str = _get_param_timespan ();
+  my $timespan_int = (-1) * $ValidTimespan->{$timespan_str};
+
+  $opts->{'title'} ||= 'Unknown title';
+  $opts->{'rrd_opts'} ||= [];
+  $opts->{'colors'} ||= {};
+
+  my @cmd = ('-', '-a', 'PNG', '-s', $timespan_int,
+    '-t', $opts->{'title'} || 'Unknown title',
+    @RRDDefaultArgs, @{$opts->{'rrd_opts'}});
+
+  my $max_inst_name = 0;
+  my @vnames = ();
+
+  for ($i = 0; $i < @$sources; $i++)
+  {
+    my $tmp = $sources->[$i]->{'name'};
+    $tmp =~ tr/A-Za-z0-9\-_/_/c;
+    $vnames[$i] = $i . $tmp;
+  }
+
+  for ($i = 0; $i < @$sources; $i++)
+  {
+    my $inst_data = $sources->[$i];
+    my $inst_name = $inst_data->{'name'} || confess;
+    my $file = $inst_data->{'file'} || confess;
+    my $vname = $vnames[$i];
+
+    if (length ($inst_name) > $max_inst_name)
+    {
+      $max_inst_name = length ($inst_name);
+    }
+
+    confess ("No such file: $file") if (!-e $file);
+
+    push (@cmd,
+      qq#DEF:${vname}_min=$file:value:MIN#,
+      qq#DEF:${vname}_avg=$file:value:AVERAGE#,
+      qq#DEF:${vname}_max=$file:value:MAX#,
+      qq#CDEF:${vname}_nnl=${vname}_avg,UN,0,${vname}_avg,IF#);
+  }
+
+  {
+    my $vname = $vnames[@vnames - 1];
+
+    push (@cmd, qq#CDEF:${vname}_stk=${vname}_nnl#);
+  }
+  for (my $i = 1; $i < @$sources; $i++)
+  {
+    my $vname0 = $vnames[@vnames - ($i + 1)];
+    my $vname1 = $vnames[@vnames - $i];
+
+    push (@cmd, qq#CDEF:${vname0}_stk=${vname0}_nnl,${vname1}_stk,+#);
+  }
+
+  for (my $i = 0; $i < @$sources; $i++)
+  {
+    my $inst_data = $sources->[$i];
+    my $inst_name = $inst_data->{'name'};
+
+    my $vname = $vnames[$i];
+
+    my $legend = sprintf ('%-*s', $max_inst_name, $inst_name);
+
+    my $line_color;
+    my $area_color;
+
+    my $number_format = $opts->{'number_format'} || '%6.1lf';
+
+    if (exists ($opts->{'colors'}{$inst_name}))
+    {
+      $line_color = $opts->{'colors'}{$inst_name};
+      $area_color = _string_to_color ($line_color);
+    }
+    else
+    {
+      $area_color = _get_random_color ();
+      $line_color = _color_to_string ($area_color);
+    }
+    $area_color = _color_to_string (_get_faded_color ($area_color));
+
+    push (@cmd, qq(AREA:${vname}_stk#$area_color),
+      qq(LINE1:${vname}_stk#$line_color:$legend),
+      qq(GPRINT:${vname}_min:MIN:$number_format Min,),
+      qq(GPRINT:${vname}_avg:AVERAGE:$number_format Avg,),
+      qq(GPRINT:${vname}_max:MAX:$number_format Max,),
+      qq(GPRINT:${vname}_avg:LAST:$number_format Last\\l),
+    );
+  }
+
+  RRDs::graph (@cmd);
+  if (my $errmsg = RRDs::error ())
+  {
+    confess ("RRDs::graph: $errmsg");
+  }
+} # meta_graph_generic_stack
+
+sub meta_graph_cpu
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+
+  $opts->{'rrd_opts'} = ['-v', 'Percent'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    'idle'      => 'ffffff',
+    'nice'      => '00e000',
+    'user'      => '0000ff',
+    'wait'      => 'ffb000',
+    'system'    => 'ff0000',
+    'softirq'   => 'ff00ff',
+    'interrupt' => 'a000a0',
+    'steal'     => '000000'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [qw(idle nice user wait system softirq interrupt steal)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_cpu
+
+sub meta_graph_df
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  my $prefix = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+
+  $opts->{'title'} = "Disk usage $prefix";
+
+  $opts->{'number_format'} = '%5.1lf%s';
+  $opts->{'rrd_opts'} = ['-l', 0, '-b', '1024', '-v', 'Bytes'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    'used'              => 'ff0000',
+    'snap_normal_used'  => 'c10640',
+    'snap_reserve_used' => '820c81',
+    'snap_reserved'     => 'f15aef',
+    'reserved'          => 'ffb000',
+    'free'              => '00ff00',
+    'sis_saved'         => '00e0e0',
+    'dedup_saved'       => '00c1c1',
+    'compression_saved' => '00a2a2'
+  };
+
+  # LVM uses LV names as type-instance; they should sort first
+  _custom_sort_arrayref ($type_instances,
+    [qw(compression_saved dedup_saved sis_saved free reserved snap_reserved
+      snap_reserve_used snap_normal_used used)], 1);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$prefix-$inst.rrd")
+      {
+       $file = "$_/$prefix-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $prefix") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_df
+
+sub meta_graph_dns
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+
+  $opts->{'rrd_opts'} = ['-v', 'Queries/s'];
+
+  my @files = ();
+
+  @$type_instances = sort @$type_instances;
+
+  $opts->{'colors'} = _get_n_colors ($type_instances);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_dns
+
+sub meta_graph_memory
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.1lf%s';
+
+  $opts->{'rrd_opts'} = ['-b', '1024', '-v', 'Bytes'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    'free'     => '00e000',
+    'cached'   => '0000ff',
+    'buffered' => 'ffb000',
+    'used'     => 'ff0000'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [qw(free cached buffered used)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_memory
+
+sub meta_graph_if_rx_errors
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.2lf';
+  $opts->{'rrd_opts'} = ['-v', 'Errors/s'];
+
+  my @files = ();
+
+  for (sort @$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_if_rx_errors
+
+sub meta_graph_mysql_commands
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.2lf';
+
+  my @files = ();
+
+  for (sort @$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_mysql_commands
+
+sub meta_graph_nfs_procedure
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.1lf%s';
+
+  my @files = ();
+
+  for (sort @$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_nfs_procedure
+
+sub meta_graph_ps_state
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'rrd_opts'} = ['-v', 'Processes'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    'Running'      => '00e000',
+    'Sleeping'  => '0000ff',
+    'Paging'      => 'ffb000',
+    'Zombies'   => 'ff0000',
+    'Blocked'   => 'ff00ff',
+    'Stopped' => 'a000a0'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [qw(paging blocked zombies stopped running sleeping)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => ucfirst ($inst),
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_ps_state
+
+sub meta_graph_swap
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%5.1lf%s';
+  $opts->{'rrd_opts'} = ['-v', 'Bytes'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    'Free'     => '00e000',
+    'Cached'   => '0000ff',
+    'Reserved' => 'ffb000',
+    'Used'     => 'ff0000'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [qw(free cached reserved used)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => ucfirst ($inst),
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_swap
+
+sub meta_graph_tcp_connections
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%6.2lf';
+
+  $opts->{'rrd_opts'} = ['-v', 'Connections'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    ESTABLISHED          => '00e000',
+    SYN_SENT     => '00e0ff',
+    SYN_RECV     => '00e0a0',
+    FIN_WAIT1    => 'f000f0',
+    FIN_WAIT2    => 'f000a0',
+    TIME_WAIT    => 'ffb000',
+    CLOSE        => '0000f0',
+    CLOSE_WAIT   => '0000a0',
+    LAST_ACK     => '000080',
+    LISTEN       => 'ff0000',
+    CLOSING      => '000000'
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [reverse qw(ESTABLISHED SYN_SENT SYN_RECV FIN_WAIT1 FIN_WAIT2 TIME_WAIT CLOSE
+    CLOSE_WAIT LAST_ACK CLOSING LISTEN)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_tcp_connections
+
+sub meta_graph_vmpage_number
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%6.2lf';
+
+  $opts->{'rrd_opts'} = ['-v', 'Pages'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    anon_pages   => '00e000',
+    bounce       => '00e0ff',
+    dirty        => '00e0a0',
+    file_pages   => 'f000f0',
+    mapped       => 'f000a0',
+    page_table_pages     => 'ffb000',
+    slab         => '0000f0',
+    unstable     => '0000a0',
+    writeback    => 'ff0000',
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [reverse qw(anon_pages bounce dirty file_pages mapped page_table_pages slab unstable writeback)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_vmpage_number
+
+sub meta_graph_vmpage_action
+{
+  confess ("Wrong number of arguments") if (@_ != 5);
+
+  my $host = shift;
+  my $plugin = shift;
+  my $plugin_instance = shift;
+  my $type = shift;
+  my $type_instances = shift;
+
+  my $opts = {};
+  my $sources = [];
+
+  $opts->{'title'} = "$host/$plugin"
+  . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+  $opts->{'number_format'} = '%6.2lf';
+
+  $opts->{'rrd_opts'} = ['-v', 'Pages'];
+
+  my @files = ();
+
+  $opts->{'colors'} =
+  {
+    activate     => '00e000',
+    deactivate   => '00e0ff',
+    free         => '00e0a0',
+    alloc        => 'f000f0',
+    refill       => 'f000a0',
+    scan_direct          => 'ffb000',
+    scan_kswapd          => '0000f0',
+    steal        => '0000a0',
+  };
+
+  _custom_sort_arrayref ($type_instances,
+    [reverse qw(activate deactivate alloc free refill scan_direct scan_kswapd steal)]);
+
+  for (@$type_instances)
+  {
+    my $inst = $_;
+    my $file = '';
+    my $title = $opts->{'title'};
+
+    for (@DataDirs)
+    {
+      if (-e "$_/$title-$inst.rrd")
+      {
+       $file = "$_/$title-$inst.rrd";
+       last;
+      }
+    }
+    confess ("No file found for $title") if ($file eq '');
+
+    push (@$sources,
+      {
+       name => $inst,
+       file => $file
+      }
+    );
+  } # for (@$type_instances)
+
+  return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_vmpage_action
+# vim: shiftwidth=2:softtabstop=2:tabstop=8
diff --git a/contrib/collection.conf b/contrib/collection.conf
new file mode 100644 (file)
index 0000000..e8444f5
--- /dev/null
@@ -0,0 +1,3 @@
+datadir: "/opt/collectd/var/lib/collectd/rrd/"
+libdir: "/opt/collectd/lib/collectd/"
+
diff --git a/contrib/collection3/README b/contrib/collection3/README
new file mode 100644 (file)
index 0000000..c890042
--- /dev/null
@@ -0,0 +1,43 @@
+ collection3 - Web frontend for collectd
+=========================================
+http://collectd.org/
+
+About
+-----
+
+  collection3 is a graphing front-end for the RRD files created by and filled
+  with collectd. It is written in Perl and should be run as an CGI-script.
+  Graphs are generated on-the-fly, so no cron job or similar is necessary.
+
+Layout
+------
+
+  The files used by collection3 are organized in a typical UNIX fashion: The
+  configuration resides in etc/, executable scripts are in bin/, supplementary
+  Perl modules are in lib/ and static data for displaying the web page are in
+  share/.
+
+  All files in all subdirectories except bin/ should NOT be executable.
+  Ideally, the webserver should not serve them either. Consider using
+  `.htaccess' files or other means to configure the web server to deny access
+  to these directories.
+
+Dependencies
+------------
+
+  collection3 depends on the following Perl modules not included in the Perl
+  distribution itself:
+
+  * Config::General
+  * Regexp::Common
+  * HTML::Entities
+  * RRDs
+
+Copyright and License
+---------------------
+
+  Copyright (C) 2008  Florian octo Forster <octo at verplant.org>
+
+  collection3 is provided under the terms of the GNU General Public License,
+  version 2 (GPLv2).
+
diff --git a/contrib/collection3/bin/.htaccess b/contrib/collection3/bin/.htaccess
new file mode 100644 (file)
index 0000000..1695f50
--- /dev/null
@@ -0,0 +1,2 @@
+Options +ExecCGI
+AddHandler cgi-script .cgi
diff --git a/contrib/collection3/bin/graph.cgi b/contrib/collection3/bin/graph.cgi
new file mode 100755 (executable)
index 0000000..2b3f2fe
--- /dev/null
@@ -0,0 +1,334 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2008-2011  Florian Forster
+# Copyright (C) 2011       noris network AG
+#
+# 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+# Authors:
+#   Florian "octo" Forster <octo at collectd.org>
+
+use strict;
+use warnings;
+use utf8;
+use vars (qw($BASE_DIR));
+
+BEGIN
+{
+  if (defined $ENV{'SCRIPT_FILENAME'})
+  {
+    if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$})
+    {
+      $::BASE_DIR = $1;
+      unshift (@::INC, "$::BASE_DIR/lib");
+    }
+  }
+}
+
+use Carp (qw(confess cluck));
+use CGI (':cgi');
+use RRDs ();
+use File::Temp (':POSIX');
+
+use Collectd::Graph::Config (qw(gc_read_config gc_get_scalar));
+use Collectd::Graph::TypeLoader (qw(tl_load_type));
+
+use Collectd::Graph::Common (qw(sanitize_type get_selected_files
+      epoch_to_rfc1123 flush_files));
+use Collectd::Graph::Type ();
+
+sub base_dir
+{
+  if (defined $::BASE_DIR)
+  {
+    return ($::BASE_DIR);
+  }
+
+  if (!defined ($ENV{'SCRIPT_FILENAME'}))
+  {
+    return;
+  }
+
+  if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$})
+  {
+    $::BASE_DIR = $1;
+    return ($::BASE_DIR);
+  }
+
+  return;
+}
+
+sub lib_dir
+{
+  my $base = base_dir ();
+
+  if ($base)
+  {
+    return "$base/lib";
+  }
+  else
+  {
+    return "../lib";
+  }
+}
+
+sub sysconf_dir
+{
+  my $base = base_dir ();
+
+  if ($base)
+  {
+    return "$base/etc";
+  }
+  else
+  {
+    return "../etc";
+  }
+}
+
+sub init
+{
+  my $lib_dir = lib_dir ();
+  my $sysconf_dir = sysconf_dir ();
+
+  if (!grep { $lib_dir eq $_ } (@::INC))
+  {
+    unshift (@::INC, $lib_dir);
+  }
+
+  gc_read_config ("$sysconf_dir/collection.conf");
+}
+
+sub main
+{
+  my $Begin = param ('begin');
+  my $End = param ('end');
+  my $GraphWidth = param ('width');
+  my $GraphHeight = param ('height');
+  my $Index = param ('index') || 0;
+  my $OutputFormat = 'PNG';
+  my $ContentType = 'image/png';
+
+  init ();
+
+  if (param ('format'))
+  {
+    my $temp = param ('format') || '';
+    $temp = uc ($temp);
+
+    if ($temp =~ m/^(PNG|SVG|EPS|PDF)$/)
+    {
+      $OutputFormat = $temp;
+
+      if ($OutputFormat eq 'SVG') { $ContentType = 'image/svg+xml'; }
+      elsif ($OutputFormat eq 'EPS') { $ContentType = 'image/eps'; }
+      elsif ($OutputFormat eq 'PDF') { $ContentType = 'application/pdf'; }
+    }
+  }
+
+  if (param ('debug'))
+  {
+    print <<HTTP;
+Content-Type: text/plain
+
+HTTP
+    $ContentType = 'text/plain';
+  }
+
+  if ($GraphWidth)
+  {
+    $GraphWidth =~ s/\D//g;
+  }
+
+  if (!$GraphWidth)
+  {
+    $GraphWidth = gc_get_scalar ('GraphWidth', 400);
+  }
+
+  if ($GraphHeight)
+  {
+    $GraphHeight =~ s/\D//g;
+  }
+
+  if (!$GraphHeight)
+  {
+    $GraphHeight = gc_get_scalar ('GraphHeight', 100);
+  }
+
+  { # Sanitize begin and end times
+    $End ||= 0;
+    $Begin ||= 0;
+
+    if ($End =~ m/\D/)
+    {
+      $End = 0;
+    }
+
+    if (!$Begin || !($Begin =~ m/^-?([1-9][0-9]*)$/))
+    {
+      $Begin = -86400;
+    }
+
+    if ($Begin < 0)
+    {
+      if ($End)
+      {
+        $Begin = $End + $Begin;
+      }
+      else
+      {
+        $Begin = time () + $Begin;
+      }
+    }
+
+    if ($Begin < 0)
+    {
+      $Begin = time () - 86400;
+    }
+
+    if (($End > 0) && ($Begin > $End))
+    {
+      my $temp = $End;
+      $End = $Begin;
+      $Begin = $temp;
+    }
+  }
+
+  my $type = param ('type') or die;
+  my $obj;
+
+  $obj = tl_load_type ($type);
+  if (!$obj)
+  {
+    confess ("tl_load_type ($type) failed");
+  }
+
+  $type = ucfirst (lc ($type));
+  $type =~ s/_([A-Za-z])/\U$1\E/g;
+  $type = sanitize_type ($type);
+
+  my $files = get_selected_files ();
+  if (param ('debug'))
+  {
+    require Data::Dumper;
+    print Data::Dumper->Dump ([$files], ['files']);
+  }
+  for (@$files)
+  {
+    $obj->addFiles ($_);
+  }
+
+  my $expires = time ();
+# IF (End is `now')
+#    OR (Begin is before `now' AND End is after `now')
+  if (($End == 0) || (($Begin <= $expires) && ($End >= $expires)))
+  {
+    # 400 == width in pixels
+    my $timespan;
+
+    if ($End == 0)
+    {
+      $timespan = $expires - $Begin;
+    }
+    else
+    {
+      $timespan = $End - $Begin;
+    }
+    $expires += int ($timespan / 400.0);
+  }
+# IF (End is not `now')
+#    AND (End is before `now')
+# ==> Graph will never change again!
+  elsif (($End > 0) && ($End < $expires))
+  {
+    $expires += (366 * 86400);
+  }
+  elsif ($Begin > $expires)
+  {
+    $expires = $Begin;
+  }
+
+# Send FLUSH command to the daemon if necessary and possible.
+  flush_files ($files,
+    begin => $Begin,
+    end => $End,
+    addr => gc_get_scalar ('UnixSockAddr', undef),
+    interval => gc_get_scalar ('Interval', 10));
+
+  print header (-Content_type => $ContentType,
+    -Last_Modified => epoch_to_rfc1123 ($obj->getLastModified ()),
+    -Expires => epoch_to_rfc1123 ($expires));
+
+  if (param ('debug'))
+  {
+    print "\$expires = $expires;\n";
+  }
+
+  my $args = $obj->getRRDArgs (0 + $Index);
+  if (param ('debug'))
+  {
+    require Data::Dumper;
+    print Data::Dumper->Dump ([$obj], ['obj']);
+    print join (",\n", @$args) . "\n";
+    print "Last-Modified: " . epoch_to_rfc1123 ($obj->getLastModified ()) . "\n";
+  }
+  else
+  {
+    my @timesel = ();
+    my $tmpfile = tmpnam ();
+    my $status;
+
+    if ($End) # $Begin is always true
+    {
+      @timesel = ('-s', $Begin, '-e', $End);
+    }
+    else
+    {
+      @timesel = ('-s', $Begin); # End is implicitely `now'.
+    }
+
+    if (-S "/var/run/rrdcached.sock" && -w "/var/run/rrdcached.sock")
+    {
+      $ENV{"RRDCACHED_ADDRESS"} = "/var/run/rrdcached.sock";
+    }
+    unlink ($tmpfile);
+    RRDs::graph ($tmpfile, '-a', $OutputFormat, '--width', $GraphWidth, '--height', $GraphHeight, @timesel, @$args);
+    if (my $err = RRDs::error ())
+    {
+      print STDERR "RRDs::graph failed: $err\n";
+      exit (1);
+    }
+
+    $status = open (IMG, '<', $tmpfile) or die ("open ($tmpfile): $!");
+    if (!$status)
+    {
+      print STDERR "graph.cgi: Unable to open temporary file \"$tmpfile\" for reading: $!\n";
+    }
+    else
+    {
+      local $/ = undef;
+      while (my $data = <IMG>)
+      {
+        print STDOUT $data;
+      }
+
+      close (IMG);
+      unlink ($tmpfile);
+    }
+  }
+} # sub main
+
+main ();
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/bin/index.cgi b/contrib/collection3/bin/index.cgi
new file mode 100755 (executable)
index 0000000..4723af9
--- /dev/null
@@ -0,0 +1,502 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2008-2011  Florian Forster
+# Copyright (C) 2011       noris network AG
+#
+# 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+# Authors:
+#   Florian "octo" Forster <octo at collectd.org>
+
+use strict;
+use warnings;
+use utf8;
+use vars (qw($BASE_DIR));
+
+BEGIN
+{
+  if (defined $ENV{'SCRIPT_FILENAME'})
+  {
+    if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$})
+    {
+      $::BASE_DIR = $1;
+      unshift (@::INC, "$::BASE_DIR/lib");
+    }
+  }
+}
+
+use Carp (qw(cluck confess));
+use CGI (':cgi');
+use CGI::Carp ('fatalsToBrowser');
+use HTML::Entities ('encode_entities');
+
+use Data::Dumper;
+
+use Collectd::Graph::Config (qw(gc_read_config gc_get_scalar));
+use Collectd::Graph::TypeLoader (qw(tl_load_type));
+use Collectd::Graph::Common (qw(get_files_from_directory get_all_hosts
+      get_timespan_selection get_selected_files get_host_selection
+      get_plugin_selection flush_files));
+use Collectd::Graph::Type ();
+
+our $TimeSpans =
+{
+  Hour  =>        3600,
+  Day   =>       86400,
+  Week  =>   7 * 86400,
+  Month =>  31 * 86400,
+  Year  => 366 * 86400
+};
+
+my %Actions =
+(
+  list_hosts => \&action_list_hosts,
+  show_selection => \&action_show_selection
+);
+
+sub base_dir
+{
+  if (defined $::BASE_DIR)
+  {
+    return ($::BASE_DIR);
+  }
+
+  if (!defined ($ENV{'SCRIPT_FILENAME'}))
+  {
+    return;
+  }
+
+  if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$})
+  {
+    $::BASE_DIR = $1;
+    return ($::BASE_DIR);
+  }
+
+  return;
+}
+
+sub lib_dir
+{
+  my $base = base_dir ();
+
+  if ($base)
+  {
+    return "$base/lib";
+  }
+  else
+  {
+    return "../lib";
+  }
+}
+
+sub sysconf_dir
+{
+  my $base = base_dir ();
+
+  if ($base)
+  {
+    return "$base/etc";
+  }
+  else
+  {
+    return "../etc";
+  }
+}
+
+sub init
+{
+  my $lib_dir = lib_dir ();
+  my $sysconf_dir = sysconf_dir ();
+
+  if (!grep { $lib_dir eq $_ } (@::INC))
+  {
+    unshift (@::INC, $lib_dir);
+  }
+
+  gc_read_config ("$sysconf_dir/collection.conf");
+}
+
+sub main
+{
+  my $Debug = param ('debug') ? 1 : 0;
+  my $action = param ('action') || 'list_hosts';
+
+  if (!exists ($Actions{$action}))
+  {
+    print STDERR "No such action: $action\n";
+    return (1);
+  }
+
+  init ();
+
+  $Actions{$action}->();
+  return (1);
+} # sub main
+
+sub can_handle_xhtml
+{
+  my %types = ();
+
+  if (!defined $ENV{'HTTP_ACCEPT'})
+  {
+    return;
+  }
+
+  for (split (',', $ENV{'HTTP_ACCEPT'}))
+  {
+    my $type = lc ($_);
+    my $q = 1.0;
+
+    if ($type =~ m#^([^;]+);q=([0-9\.]+)$#)
+    {
+      $type = $1;
+      $q = 0.0 + $2;
+    }
+    $types{$type} = $q;
+  }
+
+  if (!defined ($types{'application/xhtml+xml'}))
+  {
+    return;
+  }
+  elsif (!defined ($types{'text/html'}))
+  {
+    return (1);
+  }
+  elsif ($types{'application/xhtml+xml'} < $types{'text/html'})
+  {
+    return;
+  }
+  else
+  {
+    return (1);
+  }
+} # can_handle_xhtml
+
+my $html_started;
+sub start_html
+{
+  return if ($html_started);
+
+  my $end;
+  my $begin;
+  my $timespan;
+
+  $end = time ();
+  $timespan = get_timespan_selection ();
+  $begin = $end - $timespan;
+
+  if (can_handle_xhtml ())
+  {
+    print header (-Content_Type => 'application/xhtml+xml; charset=UTF-8');
+    print <<HTML;
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.w3.org/MarkUp/SCHEMA/xhtml11.xsd"
+    xml:lang="en">
+HTML
+  }
+  else
+  {
+    print header (-Content_Type => 'text/html; charset=UTF-8');
+    print <<HTML;
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+    "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+HTML
+  }
+  print <<HTML;
+  <head>
+    <title>collection.cgi, Version 3</title>
+    <link rel="icon" href="../share/shortcut-icon.png" type="image/png" />
+    <link rel="stylesheet" href="../share/style.css" type="text/css" />
+    <script type="text/javascript" src="../share/navigate.js"></script>
+  </head>
+  <body onload="nav_init ($begin, $end);">
+HTML
+  $html_started = 1;
+}
+
+sub end_html
+{
+  print <<HTML;
+  </body>
+</html>
+HTML
+  $html_started = 0;
+}
+
+sub contains_invalid_chars
+{
+  my $str = shift;
+
+  for (split (m//, $str))
+  {
+    my $n = ord ($_);
+
+    # Whitespace is allowed.
+    if (($n >= 9) && ($n <= 13))
+    {
+      next;
+    }
+    elsif ($n < 32)
+    {
+      return (1);
+    }
+  }
+
+  return;
+}
+
+sub show_selector
+{
+  my $timespan_selection = get_timespan_selection ();
+  my $host_selection = get_host_selection ();
+  my $plugin_selection = get_plugin_selection ();
+
+  print <<HTML;
+    <form action="${\script_name ()}" method="get">
+      <fieldset>
+        <legend>Data selection</legend>
+        <select name="hostname" multiple="multiple" size="15">
+HTML
+  for (sort (keys %$host_selection))
+  {
+    next if contains_invalid_chars ($_);
+    my $host = encode_entities ($_);
+    my $selected = $host_selection->{$_}
+    ? ' selected="selected"'
+    : '';
+    print qq#          <option value="$host"$selected>$host</option>\n#;
+  }
+  print <<HTML;
+        </select>
+       <select name="plugin" multiple="multiple" size="15">
+HTML
+  for (sort (keys %$plugin_selection))
+  {
+    next if contains_invalid_chars ($_);
+    my $plugin = encode_entities ($_);
+    my $selected = $plugin_selection->{$_}
+    ? ' selected="selected"'
+    : '';
+    print qq#          <option value="$plugin"$selected>$plugin</option>\n#;
+  }
+  print <<HTML;
+       </select>
+       <select name="timespan">
+HTML
+  for (sort { $TimeSpans->{$a} <=> $TimeSpans->{$b} } (keys (%$TimeSpans)))
+  {
+    next if contains_invalid_chars ($_);
+    my $name = encode_entities ($_);
+    my $value = $TimeSpans->{$_};
+    my $selected = ($value == $timespan_selection)
+    ? ' selected="selected"'
+    : '';
+    print qq#          <option value="$value"$selected>$name</option>\n#;
+  }
+  print <<HTML;
+        </select>
+       <input type="hidden" name="action" value="show_selection" />
+       <input type="submit" name="ok_button" value="OK" />
+      </fieldset>
+    </form>
+HTML
+} # show_selector
+
+sub action_list_hosts
+{
+  start_html ();
+  show_selector ();
+
+  my @hosts = get_all_hosts ();
+  print "    <ul>\n";
+  for (sort @hosts)
+  {
+    my $url = encode_entities (script_name () . "?action=show_selection;hostname=$_");
+    next if contains_invalid_chars ($_);
+    my $name = encode_entities ($_);
+    print qq#      <li><a href="$url">$name</a></li>\n#;
+  }
+  print "    </ul>\n";
+
+  end_html ();
+} # action_list_hosts
+
+=head1 MODULE LOADING
+
+This script makes use of the various B<Collectd::Graph::Type::*> modules. If a
+file like C<foo.rrd> is encountered it tries to load the
+B<Collectd::Graph::Type::Foo> module and, if that fails, falls back to the
+B<Collectd::Graph::Type> base class.
+
+If you want to create a specialized graph for a certain type, you have to
+create a new module which inherits from the B<Collectd::Graph::Type> base
+class. A description of provided (and used) methods can be found in the inline
+documentation of the B<Collectd::Graph::Type> module.
+
+There are other, more specialized, "abstract" classes that possibly better fit
+your need. Unfortunately they are not yet documented.
+
+=over 4
+
+=item B<Collectd::Graph::Type::GenericStacked>
+
+Specialized class that groups files by their plugin instance and stacks them on
+top of each other. Example types that inherit from this class are
+B<Collectd::Graph::Type::Cpu> and B<Collectd::Graph::Type::Memory>.
+
+=item B<Collectd::Graph::Type::GenericIO>
+
+Specialized class for input/output graphs. This class can only handle files
+with exactly two data sources, input and output. Example types that inherit
+from this class are B<Collectd::Graph::Type::DiskOctets> and
+B<Collectd::Graph::Type::IfOctets>.
+
+=back
+
+=cut
+
+sub action_show_selection
+{
+  start_html ();
+  show_selector ();
+
+  my $all_files;
+  my $timespan;
+
+  my $types = {};
+
+  my $id_counter = 0;
+
+  $all_files = get_selected_files ();
+  $timespan = get_timespan_selection ();
+
+  if (param ('debug'))
+  {
+    print "<pre>", Data::Dumper->Dump ([$all_files], ['all_files']), "</pre>\n";
+  }
+
+  # Send FLUSH command to the daemon if necessary and possible.
+  flush_files ($all_files,
+      begin => time () - $timespan,
+      end => time (),
+      addr => gc_get_scalar ('UnixSockAddr', undef),
+      interval => gc_get_scalar ('Interval', 10));
+
+  for (@$all_files)
+  {
+    my $file = $_;
+    my $type = ucfirst (lc ($file->{'type'}));
+
+    $type =~ s/[^A-Za-z0-9_]//g;
+    $type =~ s/_([A-Za-z0-9])/\U$1\E/g;
+
+    if (!defined ($types->{$type}))
+    {
+      $types->{$type} = tl_load_type ($file->{'type'});
+      if (!$types->{$type})
+      {
+        warn ("tl_load_type (" . $file->{'type'} . ") failed");
+        next;
+      }
+    }
+
+    $types->{$type}->addFiles ($file);
+  }
+#print STDOUT Data::Dumper->Dump ([$types], ['types']);
+
+  print qq#    <table>\n#;
+  for (sort (keys %$types))
+  {
+    my $type = $_;
+
+    if (!defined ($types->{$type}))
+    {
+      next;
+    }
+
+    my $graphs_num = $types->{$type}->getGraphsNum ();
+
+    for (my $i = 0; $i < $graphs_num; $i++)
+    {
+      my $args = $types->{$type}->getGraphArgs ($i);
+      my $url = encode_entities ("graph.cgi?$args;begin=-$timespan");
+      my $id = sprintf ("graph%04i", $id_counter++);
+
+      print "      <tr>\n";
+      print "        <td rowspan=\"$graphs_num\">$type</td>\n" if ($i == 0);
+      print <<EOF;
+        <td>
+          <div class="graph_canvas">
+            <div class="graph_float">
+              <img id="${id}" class="graph_image"
+                alt="A graph"
+                src="$url" />
+              <div class="controls zoom">
+                <div title="Earlier"
+                  onclick="nav_move_earlier ('${id}');">&#x2190;</div>
+                <div title="Zoom out"
+                  onclick="nav_zoom_out ('${id}');">-</div>
+                <div title="Zoom in"
+                  onclick="nav_zoom_in ('${id}');">+</div>
+                <div title="Later"
+                  onclick="nav_move_later ('${id}');">&#x2192;</div>
+              </div>
+              <div class="controls preset">
+                <div title="Show current hour"
+                  onclick="nav_time_reset ('${id}', 3600);">H</div>
+                <div title="Show current day"
+                  onclick="nav_time_reset ('${id}', 86400);">D</div>
+                <div title="Show current week"
+                  onclick="nav_time_reset ('${id}', 7 * 86400);">W</div>
+                <div title="Show current month"
+                  onclick="nav_time_reset ('${id}', 31 * 86400);">M</div>
+                <div title="Show current year"
+                  onclick="nav_time_reset ('${id}', 366 * 86400);">Y</div>
+                <div title="Set all images to this timespan"
+                  onclick="nav_set_reference ('${id}');">!</div>
+              </div>
+            </div>
+          </div>
+       </td>
+EOF
+      # print qq#        <td><img src="$url" /></td>\n#;
+      print "      </tr>\n";
+    }
+  }
+
+  print "    </table>\n";
+  end_html ();
+}
+
+main ();
+
+=head1 SEE ALSO
+
+L<Collectd::Graph::Type>
+
+=head1 AUTHOR AND LICENSE
+
+Copyright (c) 2008 by Florian Forster
+E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
+General Public License, VersionE<nbsp>2 (GPLv2).
+
+=cut
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/bin/json.cgi b/contrib/collection3/bin/json.cgi
new file mode 100755 (executable)
index 0000000..99e2703
--- /dev/null
@@ -0,0 +1,108 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2008  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use lib ('../lib');
+use utf8;
+
+use FindBin ('$RealBin');
+use CGI (':cgi');
+use CGI::Carp ('fatalsToBrowser');
+use URI::Escape ('uri_escape');
+use JSON ('objToJson');
+
+use Data::Dumper;
+
+use Collectd::Graph::Config (qw(gc_read_config));
+use Collectd::Graph::TypeLoader (qw(tl_load_type));
+use Collectd::Graph::Common (qw(get_all_hosts get_files_for_host type_to_module_name));
+use Collectd::Graph::Type ();
+
+our $Debug = param ('debug') ? 1 : 0;
+our $ServerName = 'collect.noris.net';
+
+gc_read_config ("$RealBin/../etc/collection.conf");
+
+if ($Debug)
+{
+  print "Content-Type: text/plain; charset=utf-8\n\n";
+}
+else
+{
+  print "Content-Type: application/json; charset=utf-8\n\n";
+}
+
+my $obj = {};
+my @hosts = get_all_hosts ();
+for (my $i = 0; $i < @hosts; $i++)
+{
+  my $host_obj = {};
+  my $host = $hosts[$i];
+  my $files = get_files_for_host ($host);
+  my %graphs = ();
+  my @graphs = ();
+
+  # Group files by graphs
+  for (@$files)
+  {
+    my $file = $_;
+    my $type = $file->{'type'};
+
+    # Create a new graph object if this is the first of this type.
+    if (!defined ($graphs{$type}))
+    {
+      $graphs{$type} = tl_load_type ($file->{'type'});
+      if (!$graphs{$type})
+      {
+        cluck ("tl_load_type (" . $file->{'type'} . ") failed");
+        next;
+      }
+    }
+
+    $graphs{$type}->addFiles ($file);
+  } # for (@$files)
+
+  #print qq(  ") . objToJson ({ foo => 123 }) . qq(":\n  {\n);
+
+  @graphs = keys %graphs;
+  for (my $j = 0; $j < @graphs; $j++)
+  {
+    my $type = $graphs[$j];
+    my $graphs_num = $graphs{$type}->getGraphsNum ();
+
+    if (!defined ($host_obj->{$type}))
+    {
+      $host_obj->{$type} = [];
+    }
+
+    for (my $k = 0; $k < $graphs_num; $k++)
+    {
+      my $args = $graphs{$type}->getGraphArgs ($k);
+      my $url = "http://$ServerName/cgi-bin/collection3/bin/graph.cgi?" . $args;
+      push (@{$host_obj->{$type}}, $url);
+    }
+  } # for (keys %graphs)
+
+  $obj->{$host} = $host_obj;
+} # for (my $i = 0; $i < @hosts; $i++)
+
+print STDOUT objToJson ($obj, { pretty => 1, indent => 2 });
+
+exit (0);
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/etc/.htaccess b/contrib/collection3/etc/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/contrib/collection3/etc/collection.conf b/contrib/collection3/etc/collection.conf
new file mode 100644 (file)
index 0000000..3e19bfc
--- /dev/null
@@ -0,0 +1,726 @@
+#DataDir "/var/lib/collectd/rrd"
+GraphWidth 400
+#UnixSockAddr "/var/run/collectd-unixsock"
+<Type apache_bytes>
+  DataSources value
+  DSName "value Bytes/s"
+  RRDTitle "Apache Traffic"
+  RRDVerticalLabel "Bytes/s"
+  RRDFormat "%5.1lf%s"
+  Color value 0000ff
+</Type>
+<Type apache_requests>
+  DataSources value
+  DSName "value Requests/s"
+  RRDTitle "Apache Traffic"
+  RRDVerticalLabel "Requests/s"
+  RRDFormat "%5.2lf"
+  Color value 00d000
+</Type>
+<Type apache_scoreboard>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Apache scoreboard on {hostname}"
+  RRDVerticalLabel "Slots"
+  RRDFormat "%6.2lf"
+  DSName closing Closing
+  DSName dnslookup DNS lookup
+  DSName finishing Finishing
+  DSName idle_cleanup Idle cleanup
+  DSName keepalive Keep alive
+  DSName logging Logging
+  DSName open Open (empty)
+  DSName reading Reading
+  DSName sending Sending
+  DSName starting Starting
+  DSName waiting Waiting
+  Order open closing dnslookup finishing idle_cleanup keepalive logging open reading sending starting waiting
+  Color closing      000080
+  Color dnslookup    ff0000
+  Color finishing    008080
+  Color idle_cleanup ffff00
+  Color keepalive    0080ff
+  Color logging      a000a0
+  Color open         e0e0e0
+  Color reading      0000ff
+  Color sending      00e000
+  Color starting     ff00ff
+  Color waiting      ffb000
+</Type>
+<Type arc_counts>
+  Module ArcCounts
+  RRDTitle "ARC {type_instance} on {hostname}"
+# RRDOptions ...
+</Type>
+<Type arc_l2_bytes>
+  Module GenericIO
+  DataSources read write
+  DSName  "read Read   "
+  DSName "write Written"
+  RRDTitle "L2ARC traffic"
+  RRDVerticalLabel "Bytes per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+</Type>
+<Type arc_l2_size>
+  RRDTitle "L2ARC size on {hostname}"
+  RRDVerticalLabel "Size"
+  RRDFormat "%4.0lf%s"
+  RRDOptions -b 1024
+  DSName "value Current size"
+  Color value  00e000
+</Type>
+<Type arc_size>
+  DataSources "current target minlimit maxlimit"
+  RRDTitle "ARC size on {hostname}"
+  RRDVerticalLabel "Size"
+  RRDFormat "%4.0lf%s"
+  RRDOptions -b 1024
+  DSName  "current Current size"
+  DSName   "target Target size "
+  DSName "maxlimit Max size    "
+  DSName "minlimit Min size    "
+  Color current  00e000
+  Color target   0000ff
+  Color minlimit ff0000
+  Color maxlimit ff00ff
+</Type>
+<Type arc_ratio>
+  DataSources value
+  RRDTitle "{type_instance}ARC ratio on {hostname}"
+  RRDVerticalLabel "Ratio"
+  RRDFormat "%4.1lf"
+  RRDOptions -l 0
+  DSName "value Hit ratio"
+</Type>
+<Type bitrate>
+  DataSources value
+  RRDTitle "Bitrate ({instance})"
+  RRDVerticalLabel "Bit/s"
+  RRDFormat "%5.1lf%s"
+  DSName "value Bitrate"
+</Type>
+<Type cache_ratio>
+  DataSources value
+  DSName value Percent
+  RRDTitle "Cache hit ratio for {plugin_instance} {type_instance}"
+  RRDVerticalLabel "Percent"
+  RRDFormat "%5.1lf %%"
+</Type>
+<Type cpu>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "CPU {plugin_instance} usage"
+  RRDVerticalLabel "Jiffies"
+  RRDFormat "%5.2lf"
+  DSName idle Idle
+  DSName nice Nice
+  DSName user User
+  DSName wait Wait-IO
+  DSName system System
+  DSName softirq SoftIRQ
+  DSName interrupt IRQ
+  DSName steal Steal
+  Order idle nice user wait system softirq interrupt steal
+  Color idle      e8e8e8
+  Color nice      00e000
+  Color user      0000ff
+  Color wait      ffb000
+  Color system    ff0000
+  Color softirq   ff00ff
+  Color interrupt a000a0
+  Color steal     000000
+</Type>
+<Type current>
+  DataSources value
+  DSName value Current
+  RRDTitle "Current ({type_instance})"
+  RRDVerticalLabel "Ampere"
+  RRDFormat "%4.1lfA"
+  Color value ffb000
+</Type>
+<Type df>
+  Module Df
+  DataSources free used
+</Type>
+<Type df_complex>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Disk/Volume usage on {plugin_instance}"
+  RRDVerticalLabel "Byte"
+  RRDFormat "%5.1lf%s"
+  DSName "sis_saved         SIS saved         "
+  DSName "reserved          Reserved          "
+  DSName "free              Free              "
+  DSName "used              Used              "
+  DSName "snap_normal_used  Snap used (normal)"
+  DSName "snap_reserved     Snap reserved     "
+  DSName "snap_reserve_used Snap used (resv)  "
+  Order sis_saved reserved free used snap_normal_used snap_reserved snap_reserve_used
+  Color sis_saved 00e0e0
+  Color reserved ffb000
+  Color free  00ff00
+  Color snap_reverse   ff8000
+  Color used  ff0000
+  Color snap_normal_used  c10640
+  Color snap_reserved     f15aef
+  Color snap_reserve_used 820c81
+</Type>
+<Type disk_latency>
+  Module GenericIO
+  DataSources read write
+  DSName "read Read "
+  DSName write Write
+  RRDTitle "Disk Latency for {plugin_instance}"
+  RRDVerticalLabel "seconds"
+  Scale 0.000001
+  RRDFormat "%5.1lf %ss"
+</Type>
+<Type disk_octets>
+  Module GenericIO
+  DataSources read write
+  DSName "read Read   "
+  DSName write Written
+  RRDTitle "Disk Traffic ({instance})"
+  RRDVerticalLabel "Bytes per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+</Type>
+<Type disk_ops>
+  Module GenericIO
+  DataSources read write
+  DSName "read Read   "
+  DSName write Written
+  RRDTitle "Disk Operations ({instance})"
+  RRDVerticalLabel "Operations per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf"
+</Type>
+<Type disk_ops_complex>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Netapp disc ops on {plugin_instance}"
+  RRDVerticalLabel "Ops"
+  RRDFormat "%6.2lf"
+  DSName fcp_ops   FCP-Ops
+  DSName nfs_ops   NFS-Ops
+  DSName http_ops  HTTP-Ops
+  DSName cifs_ops  CIFS-Ops
+  DSName dafs_ops  DAFS-Ops
+  DSName iscsi_ops iSCSI-Ops
+  Order fcp_ops nfs_ops http_ops cifs_ops dafs_ops iscsi_ops
+  Color fcp_ops    000080
+  Color nfs_ops    ff0000
+  Color http_ops   ffb000
+  Color cifs_ops   00e0a0
+  Color dafs_ops   00e000
+  Color iscsi_ops  00e0ff
+</Type>
+<Type disk_merged>
+  Module GenericIO
+  DataSources read write
+  DSName "read Read   "
+  DSName write Written
+  RRDTitle "Disk Merged Operations ({instance})"
+  RRDVerticalLabel "Merged operations/s"
+# RRDOptions ...
+  RRDFormat "%5.1lf"
+</Type>
+<Type disk_time>
+  Module GenericIO
+  DataSources read write
+  DSName "read Read   "
+  DSName write Written
+  RRDTitle "Disk time per operation ({instance})"
+  RRDVerticalLabel "Avg. Time/Op"
+# RRDOptions ...
+  RRDFormat "%5.1lf%ss"
+  Scale 0.001
+</Type>
+<Type dns_opcode>
+  DataSources value
+  DSName "value Queries/s"
+  RRDTitle "DNS Opcode {type_instance}"
+  RRDVerticalLabel "Queries/s"
+  RRDFormat "%6.1lf"
+</Type>
+<Type conntrack>
+  DataSources value
+  DSName value Conntrack count
+  RRDTitle "nf_conntrack connections on {hostname}"
+  RRDVerticalLabel "Count"
+  RRDFormat "%4.0lf"
+</Type>
+<Type entropy>
+  DataSources value
+  DSName value Entropy bits
+  RRDTitle "Available entropy on {hostname}"
+  RRDVerticalLabel "Bits"
+  RRDFormat "%4.0lf"
+</Type>
+<Type fanspeed>
+  DataSources value
+  DSName value RPM
+  RRDTitle "Fanspeed ({instance})"
+  RRDVerticalLabel "RPM"
+  RRDFormat "%6.1lf"
+  Color value 00b000
+</Type>
+<Type frequency>
+  DataSources value
+  DSName value Frequency
+  RRDTitle "Frequency ({type_instance})"
+  RRDVerticalLabel "Hertz"
+  RRDFormat "%4.1lfHz"
+  Color value a000a0
+</Type>
+<Type humidity>
+  DataSources value
+  DSName value Humitidy
+  RRDTitle "Humitidy ({instance})"
+  RRDVerticalLabel "Percent"
+  RRDFormat "%4.1lf%%"
+  Color value 00e000
+</Type>
+<Type if_errors>
+  Module GenericIO
+  DataSources rx tx
+  DSName rx RX
+  DSName tx TX
+  RRDTitle "Interface Errors ({type_instance})"
+  RRDVerticalLabel "Errors per second"
+# RRDOptions ...
+  RRDFormat "%.3lf"
+</Type>
+<Type if_rx_errors>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Interface receive errors ({plugin_instance})"
+  RRDVerticalLabel "Erorrs/s"
+  RRDFormat "%.1lf"
+  Color length  f00000
+  Color over    00e0ff
+  Color crc     00e000
+  Color frame   ffb000
+  Color fifo    f000c0
+  Color missed  0000f0
+</Type>
+<Type if_tx_errors>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Interface transmit errors ({plugin_instance})"
+  RRDVerticalLabel "Erorrs/s"
+  RRDFormat "%.1lf"
+  Color aborted   f00000
+  Color carrier   00e0ff
+  Color fifo      00e000
+  Color heartbeat ffb000
+  Color window    f000c0
+</Type>
+<Type if_octets>
+  Module GenericIO
+  DataSources rx tx
+  DSName rx RX
+  DSName tx TX
+  RRDTitle "Interface Traffic ({instance})"
+  RRDVerticalLabel "Bits per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+  Scale 8
+</Type>
+<Type if_packets>
+  Module GenericIO
+  DataSources rx tx
+  DSName rx RX
+  DSName tx TX
+  RRDTitle "Interface Packets ({type_instance})"
+  RRDVerticalLabel "Packets per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+</Type>
+<Type invocations>
+  DataSources value
+  DSName "value Invocations/s"
+  RRDTitle "Invocations ({instance})"
+  RRDVerticalLabel "Invocations/s"
+  RRDFormat "%5.1lf"
+</Type>
+<Type io_octets>
+  Module GenericIO
+  DataSources rx tx
+  DSName "rx Read   "
+  DSName "tx Written"
+  RRDTitle "IO Traffic ({instance})"
+  RRDVerticalLabel "Bytes per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+</Type>
+<Type ipt_bytes>
+  DataSources value
+  DSName value Bytes/s
+  RRDTitle "Traffic ({type_instance})"
+  RRDVerticalLabel "Bytes per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+</Type>
+<Type ipt_packets>
+  DataSources value
+  DSName value Packets/s
+  RRDTitle "Packets ({type_instance})"
+  RRDVerticalLabel "Packets per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf"
+</Type>
+<Type irq>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Interrupts on {hostname}"
+  RRDVerticalLabel "IRQs/s"
+  RRDFormat "%5.1lf"
+</Type>
+<Type load>
+  Module Load
+</Type>
+<Type java_memory>
+  Module JavaMemory
+  DataSources value
+</Type>
+<Type memory>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Physical memory utilization on {hostname}"
+  RRDVerticalLabel "Bytes"
+  RRDFormat "%5.1lf%s"
+  RRDOptions -b 1024 -l 0
+  DSName     "free Free    "
+  DSName   "cached Cached  "
+  DSName "buffered Buffered"
+  DSName   "locked Locked  "
+  DSName     "used Used    "
+  DSName     "available Available    "
+  DSName  "system_cache System Cache "
+  DSName    "pool_paged Paged Pool   "
+  DSName "pool_nonpaged Nonpaged Pool"
+  DSName   "working_set Working Set  "
+  DSName   "system_code System Code  "
+  DSName "system_driver System Driver"
+  #Order used buffered cached free
+  Order free cached buffered used available system_cache system_driver system_code pool_paged pool_nonpaged working_set
+  Color free      00e000
+  Color cached    0000ff
+  Color buffered  ffb000
+  Color locked    ff00ff
+  Color used      ff0000
+  Color available      00e000
+  Color system_cache   0000ff
+  Color system_driver  ff00ff
+  Color system_code    a000a0
+  Color pool_paged     ffb000
+  Color pool_nonpaged  ff8000
+  Color working_set    ff0000
+</Type>
+<Type mysql_commands>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "MySQL commands ({plugin_instance})"
+  RRDVerticalLabel "Invocations"
+  RRDFormat "%6.2lf"
+
+
+  DSName admin_commands admin_commands
+  DSName alter_table alter_table
+  DSName begin begin
+  DSName change_db change_db
+  DSName check check
+  DSName commit commit
+  DSName create_db create_db
+  DSName create_table create_table
+  DSName delete delete
+  DSName drop_db drop_db
+  DSName drop_table drop_table
+  DSName flush flush
+  DSName grant grant
+  DSName insert insert
+  DSName insert_select insert_select
+  DSName lock_tables lock_tables
+  DSName optimize optimize
+  DSName rename_table rename_table
+  DSName replace replace
+  DSName revoke revoke
+  DSName select select
+  DSName set_option set_option
+  DSName show_create_table show_create_table
+  DSName show_databases show_databases
+  DSName show_fields show_fields
+  DSName show_keys show_keys
+  DSName show_master_status show_master_status
+  DSName show_processlist show_processlist
+  DSName show_slave_hosts show_slave_hosts
+  DSName show_status show_status
+  DSName show_tables show_tables
+  DSName show_triggers show_triggers
+  DSName show_variables show_variables
+  DSName unlock_tables unlock_tables
+  DSName update update
+  DSName update_multi update_multi
+
+  Order admin_commands alter_table begin change_db check commit create_db create_table delete drop_db drop_table flush grant insert insert_select lock_tables optimize rename_table replace revoke select set_option show_create_table show_databases show_fields show_keys show_master_status show_processlist show_slave_hosts show_status show_tables show_triggers show_variables unlock_tables update update_multi
+
+  Color admin_commands ff0000
+  Color alter_table ff002a
+  Color begin ff0055
+  Color change_db ff007f
+  Color check ff00aa
+  Color commit ff00d4
+  Color create_db ff00ff
+  Color create_table d400ff
+  Color delete aa00ff
+  Color drop_db 7f00ff
+  Color drop_table 5400ff
+  Color flush 2a00ff
+  Color grant 0000ff
+  Color insert 002aff
+  Color insert_select 0055ff
+  Color lock_tables 007fff
+  Color optimize 00a9ff
+  Color rename_table 00d4ff
+  Color replace 00ffff
+  Color revoke 00ffd4
+  Color select 00ffa9
+  Color set_option 00ff7f
+  Color show_create_table 00ff55
+  Color show_databases 00ff2a
+  Color show_fields 00ff00
+  Color show_keys 2aff00
+  Color show_master_status 54ff00
+  Color show_processlist 7fff00
+  Color show_slave_hosts aaff00
+  Color show_status d4ff00
+  Color show_tables ffff00
+  Color show_triggers ffd400
+  Color show_variables ffaa00
+  Color unlock_tables ff7f00
+  Color update ff5400
+  Color update_multi ff2a00
+</Type>
+<Type mysql_handler>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "MySQL handler ({plugin_instance})"
+  RRDVerticalLabel "Invocations"
+  RRDFormat "%6.2lf"
+  DSName commit commit
+  DSName delete delete
+  DSName read_first read_first
+  DSName read_key read_key
+  DSName read_next read_next
+  DSName read_prev read_prev
+  DSName read_rnd read_rnd
+  DSName read_rnd_next read_rnd_next
+  DSName update update
+  DSName write write
+  Order commit delete read_first read_key read_next read_prev read_rnd read_rnd_next update write
+  Color commit ff0000
+  Color delete ff0099
+  Color read_first cc00ff
+  Color read_key 3200ff
+  Color read_next 0065ff
+  Color read_prev 00ffff
+  Color read_rnd 00ff65
+  Color read_rnd_next 33ff00
+  Color update cbff00
+  Color write ff9800
+</Type>
+<Type mysql_octets>
+  Module GenericIO
+  DataSources rx tx
+  DSName rx RX
+  DSName tx TX
+  RRDTitle "MySQL Traffic ({plugin_instance})"
+  RRDVerticalLabel "Bits per second"
+  RRDFormat "%5.1lf%s"
+  Scale 8
+</Type>
+<Type percent>
+  DataSources value
+  DSName value Percent
+  RRDTitle "Percent ({type_instance})"
+  RRDVerticalLabel "Percent"
+  RRDFormat "%4.1lf%%"
+  Color value 0000ff
+</Type>
+<Type ping>
+  DataSources value
+  DSName "value Latency"
+  RRDTitle "Network latency ({type_instance})"
+  RRDVerticalLabel "Milliseconds"
+  RRDFormat "%5.2lfms"
+</Type>
+<Type power>
+  DataSources value
+  DSName value Watts
+  RRDTitle "Power ({type_instance})"
+  RRDVerticalLabel "Watts"
+  RRDFormat "%6.2lf%sW"
+  Color value 008080
+</Type>
+<Type ps_cputime>
+  Module PsCputime
+</Type>
+<Type ps_disk_octets>
+  Module GenericIO
+  DataSources read write
+  DSName "read Read   "
+  DSName write Written
+  RRDTitle "Process disk traffic ({instance})"
+  RRDVerticalLabel "Bytes per second"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+</Type>
+<Type ps_rss>
+  DataSources value
+  DSName value RSS
+  RRDTitle "Resident Segment Size ({instance})"
+  RRDVerticalLabel "Bytes"
+  RRDFormat "%6.2lf%s"
+</Type>
+<Type ps_state>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Processes on {hostname}"
+  RRDVerticalLabel "Processes"
+  RRDFormat "%5.1lf"
+  DSName running  Running
+  DSName sleeping Sleeping
+  DSName paging   Paging
+  DSName zombies  Zombies
+  DSName blocked  Blocked
+  DSName stopped  Stopped
+  Order paging blocked zombies stopped running sleeping
+  Color running  00e000
+  Color sleeping 0000ff
+  Color paging   ffb000
+  Color zombies  ff0000
+  Color blocked  ff00ff
+  Color stopped  a000a0
+</Type>
+<Type signal_power>
+  DataSources value
+  RRDTitle "Signal power ({instance})"
+  RRDVerticalLabel "dB"
+  RRDFormat "%5.1lf"
+  DSName "value Signal power"
+</Type>
+<Type signal_quality>
+  DataSources value
+  RRDTitle "Signal quality ({instance})"
+  RRDVerticalLabel "Percent"
+  RRDFormat "%5.1lf%%"
+  DSName "value Signal quality"
+</Type>
+<Type snr>
+  DataSources value
+  RRDTitle "Signal / noise ratio ({instance})"
+  RRDVerticalLabel "dBm"
+  RRDFormat "%5.1lf"
+  DSName "value S/N"
+</Type>
+<Type swap>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "Swap utilization on {hostname}"
+  RRDVerticalLabel "Bytes"
+  RRDFormat "%5.1lf%s"
+  RRDOptions -b 1024 -l 0
+  DSName     "free Free    "
+  DSName   "cached Cached  "
+  DSName     "used Used    "
+  #Order used cached free
+  Order free cached used
+  Color free      00e000
+  Color cached    0000ff
+  Color used      ff0000
+</Type>
+<Type table_size>
+  Module TableSize
+  DataSources value
+  DSName value Bytes
+  RRDTitle "Table size ({instance})"
+  RRDVerticalLabel "Size [Bytes]"
+# RRDOptions ...
+  RRDFormat "%5.1lf%s"
+</Type>
+<Type tcp_connections>
+  Module GenericStacked
+  DataSources value
+  RRDTitle "TCP connections ({plugin_instance})"
+  RRDVerticalLabel "Connections"
+  RRDFormat "%5.1lf"
+  Order LISTEN CLOSING LAST_ACK CLOSE_WAIT CLOSE TIME_WAIT FIN_WAIT2 FIN_WAIT1 SYN_RECV SYN_SENT ESTABLISHED CLOSED
+  Color ESTABLISHED 00e000
+  Color SYN_SENT   00e0ff
+  Color SYN_RECV   00e0a0
+  Color FIN_WAIT1  f000f0
+  Color FIN_WAIT2  f000a0
+  Color TIME_WAIT  ffb000
+  Color CLOSE      0000f0
+  Color CLOSE_WAIT 0000a0
+  Color LAST_ACK   000080
+  Color LISTEN     ff0000
+  Color CLOSING    000000
+  Color CLOSED     0000f0
+</Type>
+<Type temperature>
+  DataSources value
+  DSName value Temp
+  RRDTitle "Temperature ({instance})"
+  RRDVerticalLabel "°Celsius"
+  RRDFormat "%4.1lf°C"
+</Type>
+<Type threads>
+  DataSources value
+  DSName "value Threads"
+  RRDTitle "Threads ({instance})"
+  RRDVerticalLabel "Threads"
+  RRDFormat "%5.2lf"
+</Type>
+<Type total_requests>
+  DataSources value
+  DSName "value Requests/s"
+  RRDTitle "Requests ({instance})"
+  RRDVerticalLabel "Requests/s"
+  RRDFormat "%6.2lf"
+</Type>
+<Type total_time_in_ms>
+  DataSources value
+  DSName "value Time"
+  RRDTitle "Time {instance}"
+  RRDVerticalLabel "Seconds"
+  RRDFormat "%6.2lf %ss"
+  Scale 0.001
+</Type>
+<Type users>
+  DataSources value
+  DSName value Users
+  RRDTitle "Users ({type_instance}) on {hostname}"
+  RRDVerticalLabel "Users"
+  RRDFormat "%.1lf"
+  Color value 0000f0
+</Type>
+<Type voltage>
+  DataSources value
+  DSName value Volts
+  RRDTitle "Voltage ({type_instance})"
+  RRDVerticalLabel "Volts"
+  RRDFormat "%4.1lfV"
+  Color value f00000
+</Type>
+<Type wirkleistung>
+  Module Wirkleistung
+  DataSources kWh
+  DSName value Wh
+  RRDTitle "Watt"
+  RRDVerticalLabel "W"
+  RRDFormat "%4.1lfW"
+</Type>
+# vim: set sw=2 sts=2 et syntax=apache fileencoding=utf-8 :
diff --git a/contrib/collection3/lib/.htaccess b/contrib/collection3/lib/.htaccess
new file mode 100644 (file)
index 0000000..3a42882
--- /dev/null
@@ -0,0 +1 @@
+Deny from all
diff --git a/contrib/collection3/lib/Collectd/Config.pm b/contrib/collection3/lib/Collectd/Config.pm
new file mode 100644 (file)
index 0000000..a376002
--- /dev/null
@@ -0,0 +1,144 @@
+package Collectd::Graph::Config;
+
+=head1 NAME
+
+Collectd::Graph::Config - Parse the collection3 config file.
+
+=cut
+
+# Copyright (C) 2008  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+
+use Carp (qw(cluck confess));
+use Exporter ();
+use Config::General ('ParseConfig');
+use Collectd::Graph::Type ();
+
+@Collectd::Graph::Config::ISA = ('Exporter');
+@Collectd::Graph::Config::EXPORT_OK = (qw(gc_read_config gc_get_config
+  gc_get_scalar));
+
+our $Configuration = undef;
+
+return (1);
+
+=head1 EXPORTED FUNCTIONS
+
+=over 4
+
+=item B<gc_read_config> (I<$file>)
+
+Reads the configuration from the file located at I<$file>. Returns B<true> when
+successful and B<false> otherwise.
+
+=cut
+
+sub gc_read_config
+{
+  my $file = shift;
+  my %conf;
+
+  if ($Configuration)
+  {
+    return (1);
+  }
+
+  $file ||= "etc/collection.conf";
+
+  %conf = ParseConfig (-ConfigFile => $file,
+    -LowerCaseNames => 1,
+    -UseApacheInclude => 1,
+    -IncludeDirectories => 1,
+    ($Config::General::VERSION >= 2.38) ? (-IncludeAgain => 0) : (),
+    -MergeDuplicateBlocks => 1,
+    -CComments => 0);
+  if (!%conf)
+  {
+    return;
+  }
+
+  $Configuration = \%conf;
+  return (1);
+} # gc_read_config
+
+=item B<gc_get_config> ()
+
+Returns the hash as provided by L<Config::General>. The hash is returned as a
+hash reference. Don't change it!
+
+=cut
+
+sub gc_get_config
+{
+  return ($Configuration);
+} # gc_get_config
+
+=item B<gc_get_config> (I<$key>, [I<$default>])
+
+Returns the scalar value I<$key> from the config file. If the key does not
+exist, I<$default> will be returned. If no default is given, B<undef> will be
+used in this case.
+
+=cut
+
+sub gc_get_scalar
+{
+  my $key = shift;
+  my $default = (@_ != 0) ? shift : undef;
+  my $value;
+
+  if (!$Configuration)
+  {
+    return ($default);
+  }
+
+  $value = $Configuration->{lc ($key)};
+  if (!defined ($value))
+  {
+    return ($default);
+  }
+
+  if (ref ($value) ne '')
+  {
+    cluck ("Value for `$key' should be scalar, but actually is "
+      . ref ($value));
+    return ($default);
+  }
+
+  return ($value);
+} # gc_get_config
+
+=back
+
+=head1 DEPENDS ON
+
+L<Config::General>
+
+=head1 SEE ALSO
+
+L<Collectd::Graph::Type>
+
+=head1 AUTHOR AND LICENSE
+
+Copyright (c) 2008 by Florian Forster
+E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
+General Public License, VersionE<nbsp>2 (GPLv2).
+
+=cut
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :
diff --git a/contrib/collection3/lib/Collectd/Graph/Common.pm b/contrib/collection3/lib/Collectd/Graph/Common.pm
new file mode 100644 (file)
index 0000000..cc7e141
--- /dev/null
@@ -0,0 +1,825 @@
+package Collectd::Graph::Common;
+
+# Copyright (C) 2008-2011  Florian Forster
+# Copyright (C) 2011       noris network AG
+#
+# 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+# Authors:
+#   Florian "octo" Forster <octo at collectd.org>
+
+use strict;
+use warnings;
+
+use vars (qw($ColorCanvas $ColorFullBlue $ColorHalfBlue));
+
+use Collectd::Unixsock ();
+use Carp (qw(confess cluck));
+use CGI (':cgi');
+use Exporter;
+use Collectd::Graph::Config (qw(gc_get_scalar));
+
+our $Cache = {};
+
+$ColorCanvas   = 'FFFFFF';
+$ColorFullBlue = '0000FF';
+$ColorHalfBlue = 'B7B7F7';
+
+@Collectd::Graph::Common::ISA = ('Exporter');
+@Collectd::Graph::Common::EXPORT_OK = (qw(
+  $ColorCanvas
+  $ColorFullBlue
+  $ColorHalfBlue
+
+  sanitize_hostname
+  sanitize_plugin sanitize_plugin_instance
+  sanitize_type sanitize_type_instance
+  group_files_by_plugin_instance
+  get_files_from_directory
+  filename_to_ident
+  ident_to_filename
+  ident_to_string
+  get_all_hosts
+  get_files_for_host
+  get_files_by_ident
+  get_selected_files
+  get_timespan_selection
+  get_host_selection
+  get_plugin_selection
+  get_random_color
+  get_faded_color
+  sort_idents_by_type_instance
+  type_to_module_name
+  epoch_to_rfc1123
+  flush_files
+));
+
+our $DefaultDataDir = '/var/lib/collectd/rrd';
+
+return (1);
+
+sub _sanitize_generic_allow_minus
+{
+  my $str = "" . shift;
+
+  # remove all slashes
+  $str =~ s#/##g;
+
+  # remove all dots and dashes at the beginning and at the end.
+  $str =~ s#^[\.-]+##;
+  $str =~ s#[\.-]+$##;
+
+  return ($str);
+}
+
+sub _sanitize_generic_no_minus
+{
+  # Do everything the allow-minus variant does..
+  my $str = _sanitize_generic_allow_minus (@_);
+
+  # .. and remove the dashes, too
+  $str =~ s#/##g;
+
+  return ($str);
+} # _sanitize_generic_no_minus
+
+sub sanitize_hostname
+{
+  return (_sanitize_generic_allow_minus (@_));
+}
+
+sub sanitize_plugin
+{
+  return (_sanitize_generic_no_minus (@_));
+}
+
+sub sanitize_plugin_instance
+{
+  return (_sanitize_generic_allow_minus (@_));
+}
+
+sub sanitize_type
+{
+  return (_sanitize_generic_no_minus (@_));
+}
+
+sub sanitize_type_instance
+{
+  return (_sanitize_generic_allow_minus (@_));
+}
+
+sub group_files_by_plugin_instance
+{
+  my @files = @_;
+  my $data = {};
+
+  for (my $i = 0; $i < @files; $i++)
+  {
+    my $file = $files[$i];
+    my $key1 = $file->{'hostname'} || '';
+    my $key2 = $file->{'plugin_instance'} || '';
+    my $key = "$key1-$key2";
+
+    $data->{$key} ||= [];
+    push (@{$data->{$key}}, $file);
+  }
+
+  return ($data);
+}
+
+sub filename_to_ident
+{
+  my $file = shift;
+  my $ret;
+
+  if ($file =~ m#([^/]+)/([^/\-]+)(?:-([^/]+))?/([^/\-]+)(?:-([^/]+))?\.rrd$#)
+  {
+    $ret = {hostname => $1, plugin => $2, type => $4};
+    if (defined ($3))
+    {
+      $ret->{'plugin_instance'} = $3;
+    }
+    if (defined ($5))
+    {
+      $ret->{'type_instance'} = $5;
+    }
+    if ($`)
+    {
+      $ret->{'_prefix'} = $`;
+    }
+  }
+  else
+  {
+    return;
+  }
+
+  return ($ret);
+} # filename_to_ident
+
+sub ident_to_filename
+{
+  my $ident = shift;
+  my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir);
+
+  my $ret = '';
+
+  if (defined ($ident->{'_prefix'}))
+  {
+    $ret .= $ident->{'_prefix'};
+  }
+  else
+  {
+    $ret .= "$data_dir/";
+  }
+
+  if (!$ident->{'hostname'})
+  {
+    cluck ("hostname is undefined")
+  }
+  if (!$ident->{'plugin'})
+  {
+    cluck ("plugin is undefined")
+  }
+  if (!$ident->{'type'})
+  {
+    cluck ("type is undefined")
+  }
+
+  $ret .= $ident->{'hostname'} . '/' . $ident->{'plugin'};
+  if (defined ($ident->{'plugin_instance'}))
+  {
+    $ret .= '-' . $ident->{'plugin_instance'};
+  }
+
+  $ret .= '/' . $ident->{'type'};
+  if (defined ($ident->{'type_instance'}))
+  {
+    $ret .= '-' . $ident->{'type_instance'};
+  }
+  $ret .= '.rrd';
+
+  return ($ret);
+} # ident_to_filename
+
+sub _part_to_string
+{
+  my $part = shift;
+
+  if (!defined ($part))
+  {
+    return ("(UNDEF)");
+  }
+  if (ref ($part) eq 'ARRAY')
+  {
+    if (1 == @$part)
+    {
+      return ($part->[0]);
+    }
+    else
+    {
+      return ('(' . join (',', @$part) . ')');
+    }
+  }
+  else
+  {
+    return ($part);
+  }
+} # _part_to_string
+
+sub ident_to_string
+{
+  my $ident = shift;
+
+  my $ret = '';
+
+  $ret .= _part_to_string ($ident->{'hostname'})
+  . '/' . _part_to_string ($ident->{'plugin'});
+  if (defined ($ident->{'plugin_instance'}))
+  {
+    $ret .= '-' . _part_to_string ($ident->{'plugin_instance'});
+  }
+
+  $ret .= '/' . _part_to_string ($ident->{'type'});
+  if (defined ($ident->{'type_instance'}))
+  {
+    $ret .= '-' . _part_to_string ($ident->{'type_instance'});
+  }
+
+  return ($ret);
+} # ident_to_string
+
+sub get_files_from_directory
+{
+  my $dir = shift;
+  my $recursive = @_ ? shift : 0;
+  my $dh;
+  my @directories = ();
+  my @files = ();
+  my $ret = [];
+
+  opendir ($dh, $dir) or die ("opendir ($dir): $!");
+  while (my $entry = readdir ($dh))
+  {
+    next if ($entry =~ m/^\./);
+
+    $entry = "$dir/$entry";
+
+    if (-d $entry)
+    {
+      push (@directories, $entry);
+    }
+    elsif (-f $entry)
+    {
+      push (@files, $entry);
+    }
+  }
+  closedir ($dh);
+
+  push (@$ret, map { filename_to_ident ($_) } sort (@files));
+
+  if ($recursive > 0)
+  {
+    for (@directories)
+    {
+      my $temp = get_files_from_directory ($_, $recursive - 1);
+      if ($temp && @$temp)
+      {
+        push (@$ret, @$temp);
+      }
+    }
+  }
+
+  return ($ret);
+} # get_files_from_directory
+
+sub get_all_hosts
+{
+  my $ret = [];
+
+  if (defined ($Cache->{'get_all_hosts'}))
+  {
+    $ret = $Cache->{'get_all_hosts'};
+  }
+  else
+  {
+    my $dh;
+    my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir);
+
+    opendir ($dh, "$data_dir") or confess ("opendir ($data_dir): $!");
+    while (my $entry = readdir ($dh))
+    {
+      next if ($entry =~ m/^\./);
+      next if (!-d "$data_dir/$entry");
+      push (@$ret, sanitize_hostname ($entry));
+    }
+    closedir ($dh);
+
+    $Cache->{'get_all_hosts'} = $ret;
+  }
+
+  if (wantarray ())
+  {
+    return (@$ret);
+  }
+  elsif (@$ret)
+  {
+    return ($ret);
+  }
+  else
+  {
+    return;
+  }
+} # get_all_hosts
+
+sub get_all_plugins
+{
+  my @hosts = @_;
+  my $ret = {};
+  my $dh;
+  my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir);
+  my $cache_key;
+
+  if (@hosts)
+  {
+    $cache_key = join (';', @hosts);
+  }
+  else
+  {
+    $cache_key = "/*/";
+    @hosts = get_all_hosts ();
+  }
+
+  if (defined ($Cache->{'get_all_plugins'}{$cache_key}))
+  {
+    $ret = $Cache->{'get_all_plugins'}{$cache_key};
+
+    if (wantarray ())
+    {
+      return (sort (keys %$ret));
+    }
+    else
+    {
+      return ($ret);
+    }
+  }
+
+  for (@hosts)
+  {
+    my $host = $_;
+    opendir ($dh, "$data_dir/$host") or next;
+    while (my $entry = readdir ($dh))
+    {
+      my $plugin;
+      my $plugin_instance = '';
+
+      next if ($entry =~ m/^\./);
+      next if (!-d "$data_dir/$host/$entry");
+
+      if ($entry =~ m#^([^-]+)-(.+)$#)
+      {
+       $plugin = $1;
+       $plugin_instance = $2;
+      }
+      elsif ($entry =~ m#^([^-]+)$#)
+      {
+       $plugin = $1;
+       $plugin_instance = '';
+      }
+      else
+      {
+       next;
+      }
+
+      $ret->{$plugin} ||= {};
+      $ret->{$plugin}{$plugin_instance} = 1;
+    } # while (readdir)
+    closedir ($dh);
+  } # for (@hosts)
+
+  $Cache->{'get_all_plugins'}{$cache_key} = $ret;
+  if (wantarray ())
+  {
+    return (sort (keys %$ret));
+  }
+  else
+  {
+    return ($ret);
+  }
+} # get_all_plugins
+
+sub get_files_for_host
+{
+  my $host = sanitize_hostname (shift);
+  my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir);
+  return (get_files_from_directory ("$data_dir/$host", 2));
+} # get_files_for_host
+
+sub _filter_ident
+{
+  my $filter = shift;
+  my $ident = shift;
+
+  for (qw(hostname plugin plugin_instance type type_instance))
+  {
+    my $part = $_;
+    my $tmp;
+
+    if (!defined ($filter->{$part}))
+    {
+      next;
+    }
+    if (!defined ($ident->{$part}))
+    {
+      return (1);
+    }
+
+    if (ref $filter->{$part})
+    {
+      if (!grep { $ident->{$part} eq $_ } (@{$filter->{$part}}))
+      {
+       return (1);
+      }
+    }
+    else
+    {
+      if ($ident->{$part} ne $filter->{$part})
+      {
+       return (1);
+      }
+    }
+  }
+
+  return (0);
+} # _filter_ident
+
+sub _get_all_files
+{
+  my $ret;
+
+  if (defined ($Cache->{'_get_all_files'}))
+  {
+    $ret = $Cache->{'_get_all_files'};
+  }
+  else
+  {
+    my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir);
+
+    $ret = get_files_from_directory ($data_dir, 3);
+    $Cache->{'_get_all_files'} = $ret;
+  }
+
+  return ($ret);
+} # _get_all_files
+
+sub get_files_by_ident
+{
+  my $ident = shift;
+  my $all_files;
+  my @ret = ();
+
+  my $cache_key = ident_to_string ($ident);
+  if (defined ($Cache->{'get_files_by_ident'}{$cache_key}))
+  {
+    my $ret = $Cache->{'get_files_by_ident'}{$cache_key};
+
+    return ($ret)
+  }
+
+  $all_files = _get_all_files ();
+
+  @ret = grep { _filter_ident ($ident, $_) == 0 } (@$all_files);
+
+  $Cache->{'get_files_by_ident'}{$cache_key} = \@ret;
+  return (\@ret);
+} # get_files_by_ident
+
+sub get_selected_files
+{
+  my $ident = {};
+  
+  for (qw(hostname plugin plugin_instance type type_instance))
+  {
+    my $part = $_;
+    my @temp = param ($part);
+    if (!@temp)
+    {
+      next;
+    }
+    elsif (($part eq 'plugin') || ($part eq 'type'))
+    {
+      $ident->{$part} = [map { _sanitize_generic_no_minus ($_) } (@temp)];
+    }
+    else
+    {
+      $ident->{$part} = [map { _sanitize_generic_allow_minus ($_) } (@temp)];
+    }
+  }
+
+  return (get_files_by_ident ($ident));
+} # get_selected_files
+
+sub get_timespan_selection
+{
+  my $ret = 86400;
+  if (param ('timespan'))
+  {
+    my $temp = int (param ('timespan'));
+    if ($temp && ($temp > 0))
+    {
+      $ret = $temp;
+    }
+  }
+
+  return ($ret);
+} # get_timespan_selection
+
+sub get_host_selection
+{
+  my %ret = ();
+
+  for (get_all_hosts ())
+  {
+    $ret{$_} = 0;
+  }
+
+  for (param ('hostname'))
+  {
+    my $host = _sanitize_generic_allow_minus ($_);
+    if (defined ($ret{$host}))
+    {
+      $ret{$host} = 1;
+    }
+  }
+
+  if (wantarray ())
+  {
+    return (grep { $ret{$_} > 0 } (sort (keys %ret)));
+  }
+  else
+  {
+    return (\%ret);
+  }
+} # get_host_selection
+
+sub get_plugin_selection
+{
+  my %ret = ();
+  my @hosts = get_host_selection ();
+
+  for (get_all_plugins (@hosts))
+  {
+    $ret{$_} = 0;
+  }
+
+  for (param ('plugin'))
+  {
+    if (defined ($ret{$_}))
+    {
+      $ret{$_} = 1;
+    }
+  }
+
+  if (wantarray ())
+  {
+    return (grep { $ret{$_} > 0 } (sort (keys %ret)));
+  }
+  else
+  {
+    return (\%ret);
+  }
+} # get_plugin_selection
+
+sub _string_to_color
+{
+  my $color = shift;
+  if ($color =~ m/([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])/)
+  {
+    return ([hex ($1) / 255.0, hex ($2) / 255.0, hex ($3) / 255.0]);
+  }
+  return;
+} # _string_to_color
+
+sub _color_to_string
+{
+  confess ("Wrong number of arguments") if (@_ != 1);
+  return (sprintf ('%02hx%02hx%02hx', map { int (255.0 * $_) } @{$_[0]}));
+} # _color_to_string
+
+sub get_random_color
+{
+  my ($r, $g, $b) = (rand (), rand ());
+  my $min = 0.0;
+  my $max = 1.0;
+
+  if (($r + $g) < 1.0)
+  {
+    $min = 1.0 - ($r + $g);
+  }
+  else
+  {
+    $max = 2.0 - ($r + $g);
+  }
+
+  $b = $min + (rand () * ($max - $min));
+
+  return (_color_to_string ([$r, $g, $b]));
+} # get_random_color
+
+sub get_faded_color
+{
+  my $fg = shift;
+  my $bg;
+  my %opts = @_;
+  my $ret = [undef, undef, undef];
+
+  $opts{'background'} ||= [1.0, 1.0, 1.0];
+  $opts{'alpha'} ||= 0.25;
+
+  if (!ref ($fg))
+  {
+    $fg = _string_to_color ($fg)
+      or confess ("Cannot parse foreground color $fg");
+  }
+
+  if (!ref ($opts{'background'}))
+  {
+    $opts{'background'} = _string_to_color ($opts{'background'})
+      or confess ("Cannot parse background color " . $opts{'background'});
+  }
+  $bg = $opts{'background'};
+
+  for (my $i = 0; $i < 3; $i++)
+  {
+    $ret->[$i] = ($opts{'alpha'} * $fg->[$i])
+       + ((1.0 - $opts{'alpha'}) * $bg->[$i]);
+  }
+
+  return (_color_to_string ($ret));
+} # get_faded_color
+
+sub sort_idents_by_type_instance
+{
+  my $idents = shift;
+  my $array_sort = shift;
+
+  my %elements = map { $_->{'type_instance'} => $_ } (@$idents);
+  splice (@$idents, 0);
+
+  for (@$array_sort)
+  {
+    next if (!exists ($elements{$_}));
+    push (@$idents, $elements{$_});
+    delete ($elements{$_});
+  }
+  push (@$idents, map { $elements{$_} } (sort (keys %elements)));
+} # sort_idents_by_type_instance
+
+sub type_to_module_name
+{
+  my $type = shift;
+  my $ret;
+  
+  $ret = ucfirst (lc ($type));
+
+  $ret =~ s/[^A-Za-z_]//g;
+  $ret =~ s/_([A-Za-z])/\U$1\E/g;
+
+  return ("Collectd::Graph::Type::$ret");
+} # type_to_module_name
+
+sub epoch_to_rfc1123
+{
+  my @days = (qw(Sun Mon Tue Wed Thu Fri Sat));
+  my @months = (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec));
+
+  my $epoch = @_ ? shift : time ();
+  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime($epoch);
+  my $string = sprintf ('%s, %02d %s %4d %02d:%02d:%02d GMT', $days[$wday], $mday,
+      $months[$mon], 1900 + $year, $hour ,$min, $sec);
+  return ($string);
+}
+
+sub flush_files
+{
+  my $all_files = shift;
+  my %opts = @_;
+
+  my $begin;
+  my $end;
+  my $addr;
+  my $interval;
+  my $sock;
+  my $now;
+  my $files_to_flush = [];
+  my $status;
+
+  if (!defined $opts{'begin'})
+  {
+    cluck ("begin is not defined");
+    return;
+  }
+  $begin = $opts{'begin'};
+
+  if (!defined $opts{'end'})
+  {
+    cluck ("end is not defined");
+    return;
+  }
+  $end = $opts{'end'};
+
+  if (!$opts{'addr'})
+  {
+    return (1);
+  }
+
+  $interval = $opts{'interval'} || 10;
+
+  if (ref ($all_files) eq 'HASH')
+  {
+    my @tmp = ($all_files);
+    $all_files = \@tmp;
+  }
+
+  $now = time ();
+  # Don't flush anything if the timespan is in the future.
+  if (($end > $now) && ($begin > $now))
+  {
+    return (1);
+  }
+
+  for (@$all_files)
+  {
+    my $file_orig = $_;
+    my $file_name = ident_to_filename ($file_orig);
+    my $file_copy = {};
+    my @statbuf;
+    my $mtime;
+
+    @statbuf = stat ($file_name);
+    if (!@statbuf)
+    {
+      next;
+    }
+    $mtime = $statbuf[9];
+
+    # Skip if file is fresh
+    if (($now - $mtime) <= $interval)
+    {
+      next;
+    }
+    # or $end is before $mtime
+    elsif (($end != 0) && (($end - $mtime) <= 0))
+    {
+      next;
+    }
+
+    $file_copy->{'host'} = $file_orig->{'hostname'};
+    $file_copy->{'plugin'} = $file_orig->{'plugin'};
+    if (exists $file_orig->{'plugin_instance'})
+    {
+      $file_copy->{'plugin_instance'} = $file_orig->{'plugin_instance'}
+    }
+    $file_copy->{'type'} = $file_orig->{'type'};
+    if (exists $file_orig->{'type_instance'})
+    {
+      $file_copy->{'type_instance'} = $file_orig->{'type_instance'}
+    }
+
+    push (@$files_to_flush, $file_copy);
+  } # for (@$all_files)
+
+  if (!@$files_to_flush)
+  {
+    return (1);
+  }
+
+  $sock = Collectd::Unixsock->new ($opts{'addr'});
+  if (!$sock)
+  {
+    return;
+  }
+
+  $status = $sock->flush (plugins => ['rrdtool'], identifier => $files_to_flush);
+  if (!$status)
+  {
+    cluck ("FLUSH failed: " . $sock->{'error'});
+    $sock->destroy ();
+    return;
+  }
+
+  $sock->destroy ();
+  return (1);
+} # flush_files
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Config.pm b/contrib/collection3/lib/Collectd/Graph/Config.pm
new file mode 100644 (file)
index 0000000..36f8706
--- /dev/null
@@ -0,0 +1,143 @@
+package Collectd::Graph::Config;
+
+=head1 NAME
+
+Collectd::Graph::Config - Parse the collection3 config file.
+
+=cut
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+
+use Carp (qw(cluck confess));
+use Exporter ();
+use Config::General ('ParseConfig');
+
+@Collectd::Graph::Config::ISA = ('Exporter');
+@Collectd::Graph::Config::EXPORT_OK = (qw(gc_read_config gc_get_config
+  gc_get_scalar));
+
+our $Configuration = undef;
+
+return (1);
+
+=head1 EXPORTED FUNCTIONS
+
+=over 4
+
+=item B<gc_read_config> (I<$file>)
+
+Reads the configuration from the file located at I<$file>. Returns B<true> when
+successful and B<false> otherwise.
+
+=cut
+
+sub gc_read_config
+{
+  my $file = shift;
+  my %conf;
+
+  if ($Configuration)
+  {
+    return (1);
+  }
+
+  $file ||= "etc/collection.conf";
+
+  %conf = ParseConfig (-ConfigFile => $file,
+    -LowerCaseNames => 1,
+    -UseApacheInclude => 1,
+    -IncludeDirectories => 1,
+    ($Config::General::VERSION >= 2.38) ? (-IncludeAgain => 0) : (),
+    -MergeDuplicateBlocks => 1,
+    -CComments => 0);
+  if (!%conf)
+  {
+    return;
+  }
+
+  $Configuration = \%conf;
+  return (1);
+} # gc_read_config
+
+=item B<gc_get_config> ()
+
+Returns the hash as provided by L<Config::General>. The hash is returned as a
+hash reference. Don't change it!
+
+=cut
+
+sub gc_get_config
+{
+  return ($Configuration);
+} # gc_get_config
+
+=item B<gc_get_config> (I<$key>, [I<$default>])
+
+Returns the scalar value I<$key> from the config file. If the key does not
+exist, I<$default> will be returned. If no default is given, B<undef> will be
+used in this case.
+
+=cut
+
+sub gc_get_scalar
+{
+  my $key = shift;
+  my $default = (@_ != 0) ? shift : undef;
+  my $value;
+
+  if (!$Configuration)
+  {
+    return ($default);
+  }
+
+  $value = $Configuration->{lc ($key)};
+  if (!defined ($value))
+  {
+    return ($default);
+  }
+
+  if (ref ($value) ne '')
+  {
+    cluck ("Value for `$key' should be scalar, but actually is "
+      . ref ($value));
+    return ($default);
+  }
+
+  return ($value);
+} # gc_get_config
+
+=back
+
+=head1 DEPENDS ON
+
+L<Config::General>
+
+=head1 SEE ALSO
+
+L<Collectd::Graph::Type>
+
+=head1 AUTHOR AND LICENSE
+
+Copyright (c) 2008 by Florian Forster
+E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
+General Public License, VersionE<nbsp>2 (GPLv2).
+
+=cut
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type.pm b/contrib/collection3/lib/Collectd/Graph/Type.pm
new file mode 100644 (file)
index 0000000..81add72
--- /dev/null
@@ -0,0 +1,513 @@
+package Collectd::Graph::Type;
+
+=head1 NAME
+
+Collectd::Graph::Type - Base class for the collectd graphing infrastructure
+
+=cut
+
+# Copyright (C) 2008  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+
+use Carp (qw(confess cluck));
+use RRDs ();
+use URI::Escape (qw(uri_escape));
+
+use Collectd::Graph::Common (qw($ColorCanvas $ColorFullBlue $ColorHalfBlue
+  ident_to_filename
+  ident_to_string
+  get_faded_color));
+
+return (1);
+
+=head1 DESCRIPTION
+
+This module serves as base class for more specialized classes realizing
+specific "types".
+
+=head1 MEMBER VARIABLES
+
+As typical in Perl, a Collectd::Graph::Type object is a blessed hash reference.
+Member variables are entries in that hash. Inheriting classes are free to add
+additional entries. To set the member variable B<foo> to B<42>, do:
+
+ $obj->{'foo'} = 42;
+
+The following members control the behavior of Collectd::Graph::Type.
+
+=over 4
+
+=item B<files> (array reference)
+
+List of RRD files. Each file is passed as "ident", i.E<nbsp>e. broken up into
+"hostname", "plugin", "type" and optionally "plugin_instance" and
+"type_instance". Use the B<addFiles> method rather than setting this directly.
+
+=item B<data_sources> (array reference)
+
+List of data sources in the RRD files. If this is not given, the default
+implementation of B<getDataSources> will use B<RRDs::info> to find out which
+data sources are contained in the files.
+
+=item B<ds_names> (array reference)
+
+Names of the data sources as printed in the graph. Should be in the same order
+as the data sources are returned by B<getDataSources>.
+
+=item B<rrd_title> (string)
+
+Title of the RRD graph. The title can contain "{hostname}", "{plugin}" and so
+on which are replaced with their actual value. See the B<getTitle> method
+below.
+
+=item B<rrd_opts> (array reference)
+
+List of options directly passed to B<RRDs::graph>.
+
+=item B<rrd_format> (string)
+
+Format to use with B<GPRINT>. Defaults to C<%5.1lf>.
+
+=item B<rrd_colors> (hash reference)
+
+Mapping of data source names to colors, used when graphing the different data
+sources.  Colors are given in the typical hexadecimal RGB form, but without
+leading "#", e.E<nbsp>g.:
+
+ $obj->{'rrd_colors'} = {foo => 'ff0000', bar => '00ff00'};
+
+=back
+
+=head1 METHODS
+
+The following methods are used by the graphing front end and may be overwritten
+to customize their behavior.
+
+=over 4
+
+=cut
+
+sub _get_ds_from_file
+{
+  my $file = shift;
+  my $info = RRDs::info ($file);
+  my %ds = ();
+  my @ds = ();
+
+  if (!$info || (ref ($info) ne 'HASH'))
+  {
+    return;
+  }
+
+  for (keys %$info)
+  {
+    if (m/^ds\[([^\]]+)\]/)
+    {
+      $ds{$1} = 1;
+    }
+  }
+
+  @ds = (keys %ds);
+  if (wantarray ())
+  {
+    return (@ds);
+  }
+  elsif (@ds)
+  {
+    return (\@ds);
+  }
+  else
+  {
+    return;
+  }
+} # _get_ds_from_file
+
+sub new
+{
+  my $pkg = shift;
+  my $obj = bless ({files => []}, $pkg);
+
+  if (@_)
+  {
+    $obj->addFiles (@_);
+  }
+
+  return ($obj);
+}
+
+=item B<addFiles> ({ I<ident> }, [...])
+
+Adds the given idents (which are hash references) to the B<files> member
+variable, see above.
+
+=cut
+
+sub addFiles
+{
+  my $obj = shift;
+  push (@{$obj->{'files'}}, @_);
+}
+
+=item B<getGraphsNum> ()
+
+Returns the number of graphs that can be generated from the added files. By
+default this number equals the number of files.
+
+=cut
+
+sub getGraphsNum
+{
+  my $obj = shift;
+  return (scalar @{$obj->{'files'}});
+}
+
+=item B<getDataSources> ()
+
+Returns the names of the data sources. If the B<data_sources> member variable
+is unset B<RRDs::info> is used to read that information from the first file.
+Set the B<data_sources> member variable instead of overloading this method!
+
+=cut
+
+sub getDataSources
+{
+  my $obj = shift;
+
+  if (!defined $obj->{'data_sources'})
+  {
+    my $ident;
+    my $filename;
+
+    if (!@{$obj->{'files'}})
+    {
+      return;
+    }
+
+    $ident = $obj->{'files'}[0];
+    $filename = ident_to_filename ($ident);
+
+    $obj->{'data_sources'} = _get_ds_from_file ($filename);
+    if (!$obj->{'data_sources'})
+    {
+      cluck ("_get_ds_from_file ($filename) failed.");
+    }
+  }
+
+  if (!defined $obj->{'data_sources'})
+  {
+    return;
+  }
+  elsif (wantarray ())
+  {
+    return (@{$obj->{'data_sources'}})
+  }
+  else
+  {
+    $obj->{'data_sources'};
+  }
+} # getDataSources
+
+
+=item B<getTitle> (I<$index>)
+
+Returns the title of the I<$index>th B<graph> (not necessarily file!). If the
+B<rrd_title> member variable is unset, a generic title is generated from the
+ident. Otherwise the substrings "{hostname}", "{plugin}", "{plugin_instance}",
+"{type}", and "{type_instance}" are replaced by their respective values.
+
+=cut
+
+sub getTitle
+{
+  my $obj = shift;
+  my $ident = shift;
+  my $title = $obj->{'rrd_title'};
+
+  if (!$title)
+  {
+    return (ident_to_string ($ident));
+  }
+
+  my $hostname = $ident->{'hostname'};
+  my $plugin = $ident->{'plugin'};
+  my $plugin_instance = $ident->{'plugin_instance'};
+  my $type = $ident->{'type'};
+  my $type_instance = $ident->{'type_instance'};
+  my $instance;
+
+  if ((defined $type_instance) && (defined $plugin_instance))
+  {
+    $instance = "$plugin_instance/$type_instance";
+  }
+  elsif (defined $type_instance)
+  {
+    $instance = $type_instance;
+  }
+  elsif (defined $plugin_instance)
+  {
+    $instance = $plugin_instance;
+  }
+  else
+  {
+    $instance = 'no instance';
+  }
+
+  if (!defined $plugin_instance)
+  {
+    $plugin_instance = 'no instance';
+  }
+
+  if (!defined $type_instance)
+  {
+    $type_instance = 'no instance';
+  }
+
+  $title =~ s#{hostname}#$hostname#g;
+  $title =~ s#{plugin}#$plugin#g;
+  $title =~ s#{plugin_instance}#$plugin_instance#g;
+  $title =~ s#{type}#$type#g;
+  $title =~ s#{type_instance}#$type_instance#g;
+  $title =~ s#{instance}#$instance#g;
+
+  return ($title);
+}
+
+=item B<getRRDArgs> (I<$index>)
+
+Return the arguments needed to generate the graph from the RRD file(s). If the
+file has only one data source, this default implementation will generate that
+typical min, average, max graph you probably know from temperatures and such.
+If the RRD files have multiple data sources, the average of each data source is
+printes as simple line.
+
+=cut
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $ident = $obj->{'files'}[$index];
+  if (!$ident)
+  {
+    cluck ("Invalid index: $index");
+    return;
+  }
+  my $filename = ident_to_filename ($ident);
+
+  my $rrd_opts = $obj->{'rrd_opts'} || [];
+  my $rrd_title = $obj->getTitle ($ident);
+  my $format = $obj->{'rrd_format'} || '%5.1lf';
+
+  my $rrd_colors = $obj->{'rrd_colors'};
+  my @ret = ('-t', $rrd_title, @$rrd_opts);
+
+  if (defined $obj->{'rrd_vertical'})
+  {
+    push (@ret, '-v', $obj->{'rrd_vertical'});
+  }
+
+  my $ds_names = $obj->{'ds_names'};
+  if (!$ds_names)
+  {
+    $ds_names = {};
+  }
+
+  my $ds = $obj->getDataSources ();
+  if (!$ds)
+  {
+    confess ("obj->getDataSources failed.");
+  }
+
+  if (!$rrd_colors)
+  {
+    my @tmp = ('0000ff', 'ff0000', '00ff00', 'ff00ff', '00ffff', 'ffff00');
+
+    for (my $i = 0; $i < @$ds; $i++)
+    {
+      $rrd_colors->{$ds->[$i]} = $tmp[$i % @tmp];
+    }
+  }
+
+  for (my $i = 0; $i < @$ds; $i++)
+  {
+    my $f = $filename;
+    my $ds_name = $ds->[$i];
+
+    # We need to escape colons for RRDTool..
+    $f =~ s#:#\\:#g;
+    $ds_name =~ s#:#\\:#g;
+
+    if (exists ($obj->{'scale'}))
+    {
+      my $scale = 0.0 + $obj->{'scale'};
+      push (@ret,
+       "DEF:min${i}_raw=${f}:${ds_name}:MIN",
+       "DEF:avg${i}_raw=${f}:${ds_name}:AVERAGE",
+       "DEF:max${i}_raw=${f}:${ds_name}:MAX",
+       "CDEF:max${i}=max${i}_raw,$scale,*",
+       "CDEF:avg${i}=avg${i}_raw,$scale,*",
+       "CDEF:min${i}=min${i}_raw,$scale,*");
+    }
+    else
+    {
+      push (@ret,
+       "DEF:min${i}=${f}:${ds_name}:MIN",
+       "DEF:avg${i}=${f}:${ds_name}:AVERAGE",
+       "DEF:max${i}=${f}:${ds_name}:MAX");
+    }
+  }
+
+  if (@$ds == 1)
+  {
+    my $ds_name = $ds->[0];
+    my $color_fg = $rrd_colors->{$ds_name} || '000000';
+    my $color_bg = get_faded_color ($color_fg);
+
+    if ($ds_names->{$ds_name})
+    {
+      $ds_name = $ds_names->{$ds_name};
+    }
+    $ds_name =~ s#:#\\:#g;
+
+    push (@ret, 
+      "AREA:max0#${color_bg}",
+      "AREA:min0#${ColorCanvas}",
+      "LINE1:avg0#${color_fg}:${ds_name}",
+      "GPRINT:min0:MIN:${format} Min,",
+      "GPRINT:avg0:AVERAGE:${format} Avg,",
+      "GPRINT:max0:MAX:${format} Max,",
+      "GPRINT:avg0:LAST:${format} Last\\l");
+  }
+  else
+  {
+    for (my $i = 0; $i < @$ds; $i++)
+    {
+      my $ds_name = $ds->[$i];
+      my $color = $rrd_colors->{$ds_name} || '000000';
+
+      if ($ds_names->{$ds_name})
+      {
+       $ds_name = $ds_names->{$ds_name};
+      }
+
+      push (@ret, 
+       "LINE1:avg${i}#${color}:${ds_name}",
+       "GPRINT:min${i}:MIN:${format} Min,",
+       "GPRINT:avg${i}:AVERAGE:${format} Avg,",
+       "GPRINT:max${i}:MAX:${format} Max,",
+       "GPRINT:avg${i}:LAST:${format} Last\\l");
+    }
+  }
+
+  return (\@ret);
+} # getRRDArgs
+
+=item B<getGraphArgs> (I<$index>)
+
+Returns the parameters that should be passed to the CGI script to generate the
+I<$index>th graph. The returned string is already URI-encoded and will possibly
+set the "hostname", "plugin", "plugin_instance", "type", and "type_instance"
+parameters.
+
+The default implementation simply uses the ident of the I<$index>th file to
+fill this.
+
+=cut
+
+sub getGraphArgs
+{
+  my $obj = shift;
+  my $index = shift;
+  my $ident = $obj->{'files'}[$index];
+
+  my @args = ();
+  for (qw(hostname plugin plugin_instance type type_instance))
+  {
+    if (defined ($ident->{$_}))
+    {
+      push (@args, uri_escape ($_) . '=' . uri_escape ($ident->{$_}));
+    }
+  }
+
+  return (join (';', @args));
+}
+
+=item B<getLastModified> ([I<$index>])
+
+If I<$index> is not given, the modification time of all files is scanned and the most recent modification is returned. If I<$index> is given, only the files belonging to the I<$index>th graph will be considered.
+
+=cut
+
+sub getLastModified
+{
+  my $obj = shift;
+  my $index = @_ ? shift : -1;
+
+  my $mtime = 0;
+
+  if ($index == -1)
+  {
+    for (@{$obj->{'files'}})
+    {
+      my $ident = $_;
+      my $filename = ident_to_filename ($ident);
+      my @statbuf = stat ($filename);
+
+      if (!@statbuf)
+      {
+       next;
+      }
+
+      if ($mtime < $statbuf[9])
+      {
+       $mtime = $statbuf[9];
+      }
+    }
+  }
+  else
+  {
+    my $ident = $obj->{'files'}[$index];
+    my $filename = ident_to_filename ($ident);
+    my @statbuf = stat ($filename);
+
+    $mtime = $statbuf[9];
+  }
+
+  if (!$mtime)
+  {
+    return;
+  }
+  return ($mtime);
+} # getLastModified
+
+=back
+
+=head1 SEE ALSO
+
+L<Collectd::Graph::Type::GenericStacked>
+
+=head1 AUTHOR AND LICENSE
+
+Copyright (c) 2008 by Florian Forster
+E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
+General Public License, VersionE<nbsp>2 (GPLv2).
+
+=cut
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/ArcCounts.pm b/contrib/collection3/lib/Collectd/Graph/Type/ArcCounts.pm
new file mode 100644 (file)
index 0000000..7a8946e
--- /dev/null
@@ -0,0 +1,110 @@
+package Collectd::Graph::Type::ArcCounts;
+
+# Copyright (C) 2009  Anthony Dewhurst <dewhurst at gmail>
+#
+# This program is available software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the available 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 available Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw(ident_to_filename get_faded_color));
+
+return (1);
+
+sub getDataSources
+{
+  return ([qw(available usedbydatasetbydataset usedbysnapshots usedbyrefres usedbychildren)]);
+} # getDataSources
+
+sub new
+{
+  my $pkg = shift;
+  my $obj = Collectd::Graph::Type->new (@_);
+  $obj->{'data_sources'} = [qw(demand_data demand_metadata prefetch_data prefetch_metadata)];
+  $obj->{'rrd_opts'} = [];
+  $obj->{'rrd_title'} = 'ARC {type_instance} on {hostname}';
+
+  return (bless ($obj, $pkg));
+} # new
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $ident = $obj->{'files'}[$index];
+  if (!$ident)
+  {
+    cluck ("Invalid index: $index");
+    return;
+  }
+  my $filename = ident_to_filename ($ident);
+  $filename =~ s#:#\\:#g;
+
+  my $legend = $ident->{'type_instance'};
+
+
+  my $faded_green = get_faded_color ('00ff00');
+  my $faded_blue = get_faded_color ('0000ff');
+  my $faded_red = get_faded_color ('ff0000');
+  my $faded_cyan = get_faded_color ('00ffff');
+
+  my @ret = @{$obj->{'rrd_opts'}};
+
+  push @ret, '-t', $obj->getTitle($ident);
+  push @ret, '-v', ucfirst($ident->{'type_instance'});
+
+  my $ds = {
+    demand_data       => { legend => "Demand data    ", color => "00ff00" },
+    demand_metadata   => { legend => "Demand metadata", color => "0000ff" },
+    prefetch_data     => { legend => "Prefetch data  ", color => "ff0000" },
+    prefetch_metadata => { legend => "Prefetch meta  ", color => "ff00ff" },
+  };
+
+  foreach (qw(demand_data demand_metadata prefetch_data prefetch_metadata))
+  {
+    push @ret,
+      "DEF:${_}_min=${filename}:${_}:MIN",
+      "DEF:${_}_avg=${filename}:${_}:AVERAGE",
+      "DEF:${_}_max=${filename}:${_}:MAX";
+  }
+
+  {
+    push @ret,
+      "CDEF:stack_prefetch_metadata=prefetch_metadata_avg",
+      "CDEF:stack_prefetch_data=prefetch_data_avg,stack_prefetch_metadata,+",
+      "CDEF:stack_demand_metadata=demand_metadata_avg,stack_prefetch_data,+",
+      "CDEF:stack_demand_data=demand_data_avg,stack_demand_metadata,+",
+      "AREA:stack_demand_data#${faded_green}",
+      "AREA:stack_demand_metadata#${faded_blue}",
+      "AREA:stack_prefetch_data#${faded_red}",
+      "AREA:stack_prefetch_metadata#${faded_cyan}",
+  }
+
+  foreach (qw(demand_data demand_metadata prefetch_data prefetch_metadata))
+  {
+    push @ret,
+      "LINE1:stack_${_}#" . $ds->{$_}->{color} . ":" . $ds->{$_}->{legend},
+      "GPRINT:${_}_min:MIN:%5.1lf Min,",
+      "GPRINT:${_}_avg:AVERAGE:%5.1lf Avg,",
+      "GPRINT:${_}_max:MAX:%5.1lf Max,",
+      "GPRINT:${_}_avg:LAST:%5.1lf Last\l";
+  }
+
+  return \@ret;
+
+} # getRRDArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/Df.pm b/contrib/collection3/lib/Collectd/Graph/Type/Df.pm
new file mode 100644 (file)
index 0000000..4a70c41
--- /dev/null
@@ -0,0 +1,83 @@
+package Collectd::Graph::Type::Df;
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw(ident_to_filename get_faded_color));
+
+return (1);
+
+sub getDataSources
+{
+  return ([qw(free used)]);
+} # getDataSources
+
+sub new
+{
+  my $pkg = shift;
+  my $obj = Collectd::Graph::Type->new (@_);
+  $obj->{'data_sources'} = [qw(free used)];
+  $obj->{'rrd_opts'} = ['-v', 'Bytes'];
+  $obj->{'rrd_title'} = 'Disk space ({instance})';
+  $obj->{'rrd_format'} = '%5.1lf%sB';
+  $obj->{'colors'} = [qw(00b000 ff0000)];
+
+  return (bless ($obj, $pkg));
+} # new
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $ident = $obj->{'files'}[$index];
+  if (!$ident)
+  {
+    cluck ("Invalid index: $index");
+    return;
+  }
+  my $filename = ident_to_filename ($ident);
+  $filename =~ s#:#\\:#g;
+
+  my $faded_green = get_faded_color ('00ff00');
+  my $faded_red = get_faded_color ('ff0000');
+
+  return (['-t', $obj->getTitle ($ident), '-v', 'Bytes', '-l', '0',
+    "DEF:free_min=${filename}:free:MIN",
+    "DEF:free_avg=${filename}:free:AVERAGE",
+    "DEF:free_max=${filename}:free:MAX",
+    "DEF:used_min=${filename}:used:MIN",
+    "DEF:used_avg=${filename}:used:AVERAGE",
+    "DEF:used_max=${filename}:used:MAX",
+    "CDEF:both_avg=free_avg,used_avg,+",
+    "AREA:both_avg#${faded_green}",
+    "AREA:used_avg#${faded_red}",
+    'LINE1:both_avg#00ff00:Free',
+    'GPRINT:free_min:MIN:%5.1lf%sB Min,',
+    'GPRINT:free_avg:AVERAGE:%5.1lf%sB Avg,',
+    'GPRINT:free_max:MAX:%5.1lf%sB Max,',
+    'GPRINT:free_avg:LAST:%5.1lf%sB Last\l',
+    'LINE1:used_avg#ff0000:Used',
+    'GPRINT:used_min:MIN:%5.1lf%sB Min,',
+    'GPRINT:used_avg:AVERAGE:%5.1lf%sB Avg,',
+    'GPRINT:used_max:MAX:%5.1lf%sB Max,',
+    'GPRINT:used_avg:LAST:%5.1lf%sB Last\l']);
+} # getRRDArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/GenericIO.pm b/contrib/collection3/lib/Collectd/Graph/Type/GenericIO.pm
new file mode 100644 (file)
index 0000000..7ed915b
--- /dev/null
@@ -0,0 +1,140 @@
+package Collectd::Graph::Type::GenericIO;
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Carp ('confess');
+
+use Collectd::Graph::Common (qw($ColorCanvas ident_to_filename get_faded_color));
+
+return (1);
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $ident = $obj->{'files'}[$index] || confess ("Unknown index $index");
+  my $filename = ident_to_filename ($ident);
+
+  my $rrd_opts = $obj->{'rrd_opts'} || [];
+  my $rrd_title = $obj->getTitle ($ident);
+  my $format = $obj->{'rrd_format'} || '%5.1lf%s';
+
+  my $ds_list = $obj->getDataSources ();
+  my $ds_names = $obj->{'ds_names'};
+  if (!$ds_names)
+  {
+    $ds_names = {};
+  }
+
+  my $colors = $obj->{'rrd_colors'} || {};
+  my @ret = ('-t', $rrd_title, @$rrd_opts);
+
+  if (defined $obj->{'rrd_vertical'})
+  {
+    push (@ret, '-v', $obj->{'rrd_vertical'});
+  }
+
+  if (@$ds_list != 2)
+  {
+    my $num = 0 + @$ds_list;
+    confess ("Expected two data sources, but there is/are $num");
+  }
+
+  my $rx_ds = $ds_list->[0];
+  my $tx_ds = $ds_list->[1];
+
+  my $rx_ds_name = $ds_names->{$rx_ds} || $rx_ds;
+  my $tx_ds_name = $ds_names->{$tx_ds} || $tx_ds;
+
+  my $rx_color_fg = $colors->{$rx_ds} || '0000ff';
+  my $tx_color_fg = $colors->{$tx_ds} || '00b000';
+
+  my $rx_color_bg = get_faded_color ($rx_color_fg);
+  my $tx_color_bg = get_faded_color ($tx_color_fg);
+  my $overlap_color = get_faded_color ($rx_color_bg, background => $tx_color_bg);
+
+  $filename =~ s#:#\\:#g;
+  $rx_ds =~ s#:#\\:#g;
+  $tx_ds =~ s#:#\\:#g;
+  $rx_ds_name =~ s#:#\\:#g;
+  $tx_ds_name =~ s#:#\\:#g;
+
+  if ($obj->{'scale'})
+  {
+    my $factor = $obj->{'scale'};
+
+    push (@ret,
+       "DEF:min_rx_raw=${filename}:${rx_ds}:MIN",
+       "DEF:avg_rx_raw=${filename}:${rx_ds}:AVERAGE",
+       "DEF:max_rx_raw=${filename}:${rx_ds}:MAX",
+       "DEF:min_tx_raw=${filename}:${tx_ds}:MIN",
+       "DEF:avg_tx_raw=${filename}:${tx_ds}:AVERAGE",
+       "DEF:max_tx_raw=${filename}:${tx_ds}:MAX",
+       "CDEF:min_rx=min_rx_raw,${factor},*",
+       "CDEF:avg_rx=avg_rx_raw,${factor},*",
+       "CDEF:max_rx=max_rx_raw,${factor},*",
+       "CDEF:min_tx=min_tx_raw,${factor},*",
+       "CDEF:avg_tx=avg_tx_raw,${factor},*",
+       "CDEF:max_tx=max_tx_raw,${factor},*");
+  }
+  else # (!$obj->{'scale'})
+  {
+    push (@ret,
+       "DEF:min_rx=${filename}:${rx_ds}:MIN",
+       "DEF:avg_rx=${filename}:${rx_ds}:AVERAGE",
+       "DEF:max_rx=${filename}:${rx_ds}:MAX",
+       "DEF:min_tx=${filename}:${tx_ds}:MIN",
+       "DEF:avg_tx=${filename}:${tx_ds}:AVERAGE",
+       "DEF:max_tx=${filename}:${tx_ds}:MAX");
+  }
+
+  push (@ret,
+    "CDEF:avg_rx_bytes=avg_rx,8,/",
+    "VDEF:global_min_rx=min_rx,MINIMUM",
+    "VDEF:global_avg_rx=avg_rx,AVERAGE",
+    "VDEF:global_max_rx=max_rx,MAXIMUM",
+    "VDEF:global_tot_rx=avg_rx_bytes,TOTAL",
+    "CDEF:avg_tx_bytes=avg_tx,8,/",
+    "VDEF:global_min_tx=min_tx,MINIMUM",
+    "VDEF:global_avg_tx=avg_tx,AVERAGE",
+    "VDEF:global_max_tx=max_tx,MAXIMUM",
+    "VDEF:global_tot_tx=avg_tx_bytes,TOTAL");
+
+  push (@ret,
+      "CDEF:overlap=avg_rx,avg_tx,LT,avg_rx,avg_tx,IF",
+      "AREA:avg_rx#${rx_color_bg}",
+      "AREA:avg_tx#${tx_color_bg}",
+      "AREA:overlap#${overlap_color}",
+      "LINE1:avg_rx#${rx_color_fg}:${rx_ds_name}",
+      "GPRINT:global_min_rx:${format} Min,",
+      "GPRINT:global_avg_rx:${format} Avg,",
+      "GPRINT:global_max_rx:${format} Max,",
+      "GPRINT:global_tot_rx:ca. ${format} Total\\l",
+      "LINE1:avg_tx#${tx_color_fg}:${tx_ds_name}",
+      "GPRINT:global_min_tx:${format} Min,",
+      "GPRINT:global_avg_tx:${format} Avg,",
+      "GPRINT:global_max_tx:${format} Max,",
+      "GPRINT:global_tot_tx:ca. ${format} Total\\l");
+
+  return (\@ret);
+} # getRRDArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/GenericStacked.pm b/contrib/collection3/lib/Collectd/Graph/Type/GenericStacked.pm
new file mode 100644 (file)
index 0000000..c5114a8
--- /dev/null
@@ -0,0 +1,230 @@
+package Collectd::Graph::Type::GenericStacked;
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw($ColorCanvas $ColorFullBlue $ColorHalfBlue
+  group_files_by_plugin_instance ident_to_filename sanitize_type_instance
+  get_faded_color sort_idents_by_type_instance));
+
+return (1);
+
+sub getGraphsNum
+{
+  my $obj = shift;
+  my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
+
+  return (scalar (keys %$group));
+}
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
+  my @group = sort (keys %$group);
+
+  my $rrd_opts = $obj->{'rrd_opts'} || [];
+  my $format = $obj->{'rrd_format'} || '%5.1lf';
+
+  my $idents = $group->{$group[$index]};
+  my $ds_name_len = 0;
+
+  my $ds = $obj->getDataSources ();
+  if (!$ds)
+  {
+    confess ("obj->getDataSources failed.");
+  }
+  if (@$ds != 1)
+  {
+    confess ("I can only work with RRD files that have "
+      . "exactly one data source!");
+  }
+  my $data_source = $ds->[0];
+
+  my $rrd_title = $obj->getTitle ($idents->[0]);
+
+  my $colors = $obj->{'rrd_colors'} || {};
+  my @ret = ('-t', $rrd_title, @$rrd_opts);
+
+  my $ignore_unknown = $obj->{'ignore_unknown'} || 0;
+  if ($ignore_unknown)
+  {
+    if ($ignore_unknown =~ m/^(yes|true|on)$/i)
+    {
+      $ignore_unknown = 1;
+    }
+    else
+    {
+      $ignore_unknown = 0;
+    }
+  }
+
+  my $stacking = $obj->{'stacking'};
+  if ($stacking)
+  {
+    if ($stacking =~ m/^(no|false|off|none)$/i)
+    {
+      $stacking = 0;
+    }
+    else
+    {
+      $stacking = 1;
+    }
+  }
+  else # if (!$stacking)
+  {
+    $stacking = 1;
+  }
+
+  if (defined $obj->{'rrd_vertical'})
+  {
+    push (@ret, '-v', $obj->{'rrd_vertical'});
+  }
+
+  if ($obj->{'custom_order'})
+  {
+    sort_idents_by_type_instance ($idents, $obj->{'custom_order'});
+  }
+
+  if ($ignore_unknown)
+  {
+    my $new_idents = [];
+    for (@$idents)
+    {
+      if (exists ($obj->{'ds_names'}{$_->{'type_instance'}}))
+      {
+       push (@$new_idents, $_);
+      }
+    }
+
+    if (@$new_idents)
+    {
+      $idents = $new_idents;
+    }
+  }
+
+  $obj->{'ds_names'} ||= {};
+  my @names = map { $obj->{'ds_names'}{$_->{'type_instance'}} || $_->{'type_instance'} } (@$idents);
+
+  for (my $i = 0; $i < @$idents; $i++)
+  {
+    my $ident = $idents->[$i];
+    my $filename = ident_to_filename ($ident);
+
+    if ($ds_name_len < length ($names[$i]))
+    {
+      $ds_name_len = length ($names[$i]);
+    }
+
+    # Escape colons _after_ the length has been checked.
+    $names[$i] =~ s/:/\\:/g;
+
+    push (@ret,
+      "DEF:min${i}=${filename}:${data_source}:MIN",
+      "DEF:avg${i}=${filename}:${data_source}:AVERAGE",
+      "DEF:max${i}=${filename}:${data_source}:MAX");
+  }
+
+  if ($stacking)
+  {
+    for (my $i = @$idents - 1; $i >= 0; $i--)
+    {
+      if ($i == (@$idents - 1))
+      {
+        push (@ret,
+         "CDEF:cdef${i}=avg${i},UN,0,avg${i},IF");
+      }
+      else
+      {
+        my $j = $i + 1;
+        push (@ret,
+          "CDEF:cdef${i}=avg${i},UN,0,avg${i},IF,cdef${j},+");
+      }
+    }
+
+    for (my $i = 0; $i < @$idents; $i++)
+    {
+      my $type_instance = $idents->[$i]{'type_instance'};
+      my $color = '000000';
+      if (exists $colors->{$type_instance})
+      {
+        $color = $colors->{$type_instance};
+      }
+
+      $color = get_faded_color ($color);
+
+      push (@ret,
+        "AREA:cdef${i}#${color}");
+    }
+  }
+  else # if (!$stacking)
+  {
+    for (my $i = @$idents - 1; $i >= 0; $i--)
+    {
+      push (@ret,
+        "CDEF:cdef${i}=avg${i}");
+    }
+  }
+
+  for (my $i = 0; $i < @$idents; $i++)
+  {
+    my $type_instance = $idents->[$i]{'type_instance'};
+    my $ds_name = sprintf ("%-*s", $ds_name_len, $names[$i]);
+    my $color = '000000';
+    if (exists $colors->{$type_instance})
+    {
+      $color = $colors->{$type_instance};
+    }
+    push (@ret,
+      "LINE1:cdef${i}#${color}:${ds_name}",
+      "GPRINT:min${i}:MIN:${format} Min,",
+      "GPRINT:avg${i}:AVERAGE:${format} Avg,",
+      "GPRINT:max${i}:MAX:${format} Max,",
+      "GPRINT:avg${i}:LAST:${format} Last\\l");
+  }
+
+  return (\@ret);
+}
+
+sub getGraphArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
+  my @group = sort (keys %$group);
+
+  my $idents = $group->{$group[$index]};
+
+  my @args = ();
+  for (qw(hostname plugin plugin_instance type))
+  {
+    if (defined ($idents->[0]{$_}))
+    {
+      push (@args, $_ . '=' . $idents->[0]{$_});
+    }
+  }
+
+  return (join (';', @args));
+} # getGraphArgs
+
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/JavaMemory.pm b/contrib/collection3/lib/Collectd/Graph/Type/JavaMemory.pm
new file mode 100644 (file)
index 0000000..0da2988
--- /dev/null
@@ -0,0 +1,162 @@
+package Collectd::Graph::Type::JavaMemory;
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw($ColorCanvas $ColorFullBlue $ColorHalfBlue
+  group_files_by_plugin_instance ident_to_filename sanitize_type_instance
+  get_faded_color sort_idents_by_type_instance));
+
+return (1);
+
+sub getGraphsNum
+{
+  my $obj = shift;
+  my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
+
+  return (scalar (keys %$group));
+}
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
+  my @group = sort (keys %$group);
+
+  my $rrd_opts = $obj->{'rrd_opts'} || [];
+  my $format = $obj->{'rrd_format'} || '%5.1lf';
+
+  my $idents = $group->{$group[$index]};
+  my %type_instance = ();
+
+  my $ds = $obj->getDataSources ();
+  if (!$ds)
+  {
+    confess ("obj->getDataSources failed.");
+  }
+  if (@$ds != 1)
+  {
+    confess ("I can only work with RRD files that have "
+      . "exactly one data source!");
+  }
+  my $data_source = $ds->[0];
+
+  my $rrd_title = $idents->[0]{'plugin_instance'};
+  $rrd_title =~ s/^memory_pool-//;
+  $rrd_title = "Memory pool \"$rrd_title\"";
+
+  my $ds_names =
+  {
+    max       => 'Max      ',
+    committed => 'Committed',
+    used      => 'Used     ',
+    init      => 'Init     '
+  };
+
+  my $colors =
+  {
+    max       => '00ff00',
+    committed => 'ff8000',
+    used      => 'ff0000',
+    init      => '0000f0',
+    'head-committed'    => '000000',
+    'head-init'         => '000000',
+    'head-max'          => '000000',
+    'head-used'         => '000000',
+    'nonhead-committed' => '000000',
+    'nonhead-init'      => '000000',
+    'nonhead-max'       => '000000',
+    'nonhead-used'      => '000000'
+  };
+  my @ret = ('-t', $rrd_title, @$rrd_opts);
+
+  if (defined $obj->{'rrd_vertical'})
+  {
+    push (@ret, '-v', $obj->{'rrd_vertical'});
+  }
+  else
+  {
+    push (@ret, '-v', "Bytes");
+  }
+
+  for (@$idents)
+  {
+    my $ident = $_;
+    if ($ident->{'type_instance'})
+    {
+      $type_instance{$ident->{'type_instance'}} = $ident;
+    }
+  }
+
+  if (exists ($type_instance{'committed'})
+    && exists ($type_instance{'init'})
+    && exists ($type_instance{'max'})
+    && exists ($type_instance{'used'}))
+  {
+    for (qw(max committed init used))
+    {
+      my $inst = $_;
+      my $file = ident_to_filename ($type_instance{$inst});
+      my $color = $colors->{$inst};
+      my $name = $ds_names->{$inst};
+      push (@ret,
+       "DEF:${inst}_min=${file}:value:MIN",
+       "DEF:${inst}_avg=${file}:value:AVERAGE",
+       "DEF:${inst}_max=${file}:value:MAX",
+       "AREA:${inst}_avg#${color}10",
+       "LINE1:${inst}_avg#${color}:${name}",
+       "GPRINT:${inst}_min:MIN:%5.1lf\%sB Min,",
+       "GPRINT:${inst}_avg:AVERAGE:%5.1lf\%sB Avg,",
+       "GPRINT:${inst}_max:MAX:%5.1lf\%sB Max,",
+       "GPRINT:${inst}_avg:LAST:%5.1lf\%sB Last\\l");
+    }
+    return (\@ret);
+  }
+  else
+  {
+    require Collectd::Graph::Type::GenericStacked;
+    return (Collectd::Graph::Type::GenericStacked::getRRDArgs ($obj, $index));
+  }
+} # getRRDArgs
+
+sub getGraphArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $group = group_files_by_plugin_instance (@{$obj->{'files'}});
+  my @group = sort (keys %$group);
+
+  my $idents = $group->{$group[$index]};
+
+  my @args = ();
+  for (qw(hostname plugin plugin_instance type))
+  {
+    if (defined ($idents->[0]{$_}))
+    {
+      push (@args, $_ . '=' . $idents->[0]{$_});
+    }
+  }
+
+  return (join (';', @args));
+} # getGraphArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/Load.pm b/contrib/collection3/lib/Collectd/Graph/Type/Load.pm
new file mode 100644 (file)
index 0000000..b6ca4a6
--- /dev/null
@@ -0,0 +1,69 @@
+package Collectd::Graph::Type::Load;
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw($ColorCanvas ident_to_filename get_faded_color));
+
+return (1);
+
+sub new
+{
+  my $pkg = shift;
+  my $obj = Collectd::Graph::Type->new (@_);
+  $obj->{'data_sources'} = [qw(shortterm midterm longterm)];
+  $obj->{'rrd_opts'} = ['-v', 'System load'];
+  $obj->{'rrd_title'} = 'System load';
+  $obj->{'rrd_format'} = '%.2lf';
+  $obj->{'colors'} = [qw(00ff00 0000ff ff0000)];
+
+  return (bless ($obj, $pkg));
+} # new
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $ident = $obj->{'files'}[$index];
+  if (!$ident)
+  {
+    cluck ("Invalid index: $index");
+    return;
+  }
+  my $filename = ident_to_filename ($ident);
+  $filename =~ s#:#\\:#g;
+
+  my $faded_green = get_faded_color ('00ff00');
+
+  return (['-t', 'System load', '-v', 'System load',
+    "DEF:s_min=${filename}:shortterm:MIN",
+    "DEF:s_avg=${filename}:shortterm:AVERAGE",
+    "DEF:s_max=${filename}:shortterm:MAX",
+    "DEF:m_min=${filename}:midterm:MIN",
+    "DEF:m_avg=${filename}:midterm:AVERAGE",
+    "DEF:m_max=${filename}:midterm:MAX",
+    "DEF:l_min=${filename}:longterm:MIN",
+    "DEF:l_avg=${filename}:longterm:AVERAGE",
+    "DEF:l_max=${filename}:longterm:MAX",
+    "AREA:s_max#${faded_green}",
+    "AREA:s_min#${ColorCanvas}",
+    "LINE1:s_avg#00ff00: 1 min",
+    "GPRINT:s_min:MIN:%.2lf Min,",
+    "GPRINT:s_avg:AVERAGE:%.2lf Avg,",
+    "GPRINT:s_max:MAX:%.2lf Max,",
+    "GPRINT:s_avg:LAST:%.2lf Last\\l",
+    "LINE1:m_avg#0000ff: 5 min",
+    "GPRINT:m_min:MIN:%.2lf Min,",
+    "GPRINT:m_avg:AVERAGE:%.2lf Avg,",
+    "GPRINT:m_max:MAX:%.2lf Max,",
+    "GPRINT:m_avg:LAST:%.2lf Last\\l",
+    "LINE1:l_avg#ff0000:15 min",
+    "GPRINT:l_min:MIN:%.2lf Min,",
+    "GPRINT:l_avg:AVERAGE:%.2lf Avg,",
+    "GPRINT:l_max:MAX:%.2lf Max,",
+    "GPRINT:l_avg:LAST:%.2lf Last\\l"]);
+} # sub getRRDArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/PsCputime.pm b/contrib/collection3/lib/Collectd/Graph/Type/PsCputime.pm
new file mode 100644 (file)
index 0000000..b0a8f9a
--- /dev/null
@@ -0,0 +1,97 @@
+package Collectd::Graph::Type::PsCputime;
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw(ident_to_filename get_faded_color));
+
+return (1);
+
+sub getDataSources
+{
+  return ([qw(syst user)]);
+} # getDataSources
+
+sub new
+{
+  my $pkg = shift;
+  my $obj = Collectd::Graph::Type->new (@_);
+  $obj->{'data_sources'} = [qw(syst user)];
+  $obj->{'rrd_opts'} = ['-v', 'CPU time [s]', '-l', '0'];
+  $obj->{'rrd_title'} = 'CPU time used by {plugin_instance}';
+  $obj->{'rrd_format'} = '%5.1lf';
+  $obj->{'colors'} = [qw(00b000 ff0000)];
+
+  return (bless ($obj, $pkg));
+} # new
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $ident = $obj->{'files'}[$index];
+  if (!$ident)
+  {
+    cluck ("Invalid index: $index");
+    return;
+  }
+  my $filename = ident_to_filename ($ident);
+  $filename =~ s#:#\\:#g;
+
+  my $faded_blue = get_faded_color ('0000ff');
+  my $faded_red = get_faded_color ('ff0000');
+
+  return (['-t', $obj->getTitle (), @{$obj->{'rrd_opts'}},
+    "DEF:user_min_raw=${filename}:user:MIN",
+    "DEF:user_avg_raw=${filename}:user:AVERAGE",
+    "DEF:user_max_raw=${filename}:user:MAX",
+    "DEF:syst_min_raw=${filename}:syst:MIN",
+    "DEF:syst_avg_raw=${filename}:syst:AVERAGE",
+    "DEF:syst_max_raw=${filename}:syst:MAX",
+    "CDEF:user_min=0.000001,user_min_raw,*",
+    "CDEF:user_avg=0.000001,user_avg_raw,*",
+    "CDEF:user_max=0.000001,user_max_raw,*",
+    "CDEF:syst_min=0.000001,syst_min_raw,*",
+    "CDEF:syst_avg=0.000001,syst_avg_raw,*",
+    "CDEF:syst_max=0.000001,syst_max_raw,*",
+    "VDEF:v_user_min=user_min,MINIMUM",
+    "VDEF:v_user_avg=user_avg,AVERAGE",
+    "VDEF:v_user_max=user_max,MAXIMUM",
+    "VDEF:v_user_lst=syst_avg,LAST",
+    "VDEF:v_syst_min=syst_min,MINIMUM",
+    "VDEF:v_syst_avg=syst_avg,AVERAGE",
+    "VDEF:v_syst_max=syst_max,MAXIMUM",
+    "VDEF:v_syst_lst=syst_avg,LAST",
+    "CDEF:user_stack=syst_avg,user_avg,+",
+    "AREA:user_stack#${faded_blue}",
+    'LINE1:user_stack#0000ff:User  ',
+    'GPRINT:v_user_min:%5.1lf%ss Min,',
+    'GPRINT:v_user_avg:%5.1lf%ss Avg,',
+    'GPRINT:v_user_max:%5.1lf%ss Max,',
+    'GPRINT:v_user_lst:%5.1lf%ss Last\l',
+    "AREA:syst_avg#${faded_red}",
+    'LINE1:syst_avg#ff0000:System',
+    'GPRINT:v_syst_min:%5.1lf%ss Min,',
+    'GPRINT:v_syst_avg:%5.1lf%ss Avg,',
+    'GPRINT:v_syst_max:%5.1lf%ss Max,',
+    'GPRINT:v_syst_lst:%5.1lf%ss Last\l']);
+} # getRRDArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/TableSize.pm b/contrib/collection3/lib/Collectd/Graph/Type/TableSize.pm
new file mode 100644 (file)
index 0000000..5ad8ae0
--- /dev/null
@@ -0,0 +1,236 @@
+package Collectd::Graph::Type::TableSize;
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw($ColorCanvas $ColorFullBlue $ColorHalfBlue
+  ident_to_filename sanitize_type_instance
+  get_random_color sort_idents_by_type_instance));
+
+use RRDs ();
+
+return (1);
+
+sub _get_last_value
+{
+  my $ident = shift;
+  my $value = undef;
+  my $filename = ident_to_filename ($ident);
+  my ($start ,$step ,$names ,$data) = RRDs::fetch ($filename, 'AVERAGE', '-s', '-3600');
+  if (my $errmsg = RRDs::error ())
+  {
+    print STDERR "RRDs::fetch ($filename) failed: $errmsg\n";
+    return;
+  }
+
+  for (@$data)
+  {
+    my $line = $_;
+
+    for (@$line)
+    {
+      my $ds = $_;
+
+      if (defined ($ds))
+      {
+       $value = $ds;
+      }
+    }
+  } # for (@$data)
+
+  return ($value);
+} # _get_last_value
+
+sub getLastValues
+{
+  my $obj = shift;
+  my $last_value = {};
+
+  if (exists ($obj->{'last_value'}))
+  {
+    return ($obj->{'last_value'});
+  }
+
+  for (@{$obj->{'files'}})
+  {
+    my $file = $_;
+
+    $last_value->{$file} = _get_last_value ($file);
+  }
+  $obj->{'last_value'} = $last_value;
+  return ($obj->{'last_value'});
+} # getLastValues
+
+sub _group_files
+{
+  my $obj = shift;
+  my $data = [];
+  my @files;
+  my $last_values;
+
+  $last_values = $obj->getLastValues ();
+
+  @files = sort
+  { 
+    if (!defined ($last_values->{$a}) && !defined ($last_values->{$b}))
+    {
+      return (0);
+    }
+    elsif (!defined ($last_values->{$a}))
+    {
+      return (1);
+    }
+    elsif (!defined ($last_values->{$b}))
+    {
+      return (-1);
+    }
+    else
+    {
+      return ($last_values->{$a} <=> $last_values->{$b});
+    }
+  } (@{$obj->{'files'}});
+
+  for (my $i = 0; $i < @files; $i++)
+  {
+    my $file = $files[$i];
+    my $j = int ($i / 10);
+
+    $data->[$j] ||= [];
+    push (@{$data->[$j]}, $file);
+  }
+
+  return ($data);
+} # _group_files
+
+sub getGraphsNum
+{
+  my $obj = shift;
+  my $group = _group_files ($obj);
+
+  return (0 + @$group);
+}
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $group = _group_files ($obj);
+
+  my $rrd_opts = $obj->{'rrd_opts'} || [];
+  my $format = $obj->{'rrd_format'} || '%5.1lf';
+
+  my $idents = $group->[$index];
+  my $ds_name_len = 0;
+
+  my $ds = $obj->getDataSources ();
+  if (!$ds)
+  {
+    confess ("obj->getDataSources failed.");
+  }
+  if (@$ds != 1)
+  {
+    confess ("I can only work with RRD files that have "
+      . "exactly one data source!");
+  }
+  my $data_source = $ds->[0];
+
+  my $rrd_title = $obj->getTitle ($idents->[0]);
+
+  my $colors = $obj->{'rrd_colors'} || {};
+  my @ret = ('-t', $rrd_title, @$rrd_opts);
+
+  if (defined $obj->{'rrd_vertical'})
+  {
+    push (@ret, '-v', $obj->{'rrd_vertical'});
+  }
+
+  if ($obj->{'custom_order'})
+  {
+    sort_idents_by_type_instance ($idents, $obj->{'custom_order'});
+  }
+
+  $obj->{'ds_names'} ||= {};
+  my @names = map { $obj->{'ds_names'}{$_->{'type_instance'}} || $_->{'type_instance'} } (@$idents);
+
+  for (my $i = 0; $i < @$idents; $i++)
+  {
+    my $ident = $idents->[$i];
+    my $filename = ident_to_filename ($ident);
+
+    if ($ds_name_len < length ($names[$i]))
+    {
+      $ds_name_len = length ($names[$i]);
+    }
+    
+    # Escape colons _after_ the length has been checked.
+    $names[$i] =~ s/:/\\:/g;
+
+    push (@ret,
+      "DEF:min${i}=${filename}:${data_source}:MIN",
+      "DEF:avg${i}=${filename}:${data_source}:AVERAGE",
+      "DEF:max${i}=${filename}:${data_source}:MAX");
+  }
+
+  for (my $i = 0; $i < @$idents; $i++)
+  {
+    my $type_instance = $idents->[$i]{'type_instance'};
+    my $ds_name = sprintf ("%-*s", $ds_name_len, $names[$i]);
+    my $color = '000000';
+    if (exists $colors->{$type_instance})
+    {
+      $color = $colors->{$type_instance};
+    }
+    else
+    {
+      $color = get_random_color ();
+    }
+    push (@ret,
+      "LINE1:avg${i}#${color}:${ds_name}",
+      "GPRINT:min${i}:MIN:${format} Min,",
+      "GPRINT:avg${i}:AVERAGE:${format} Avg,",
+      "GPRINT:max${i}:MAX:${format} Max,",
+      "GPRINT:avg${i}:LAST:${format} Last\\l");
+  }
+
+  return (\@ret);
+}
+
+sub getGraphArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $group = _group_files ($obj);
+  my $idents = $group->[$index];
+
+  my @args = ();
+  for (qw(hostname plugin plugin_instance type))
+  {
+    if (defined ($idents->[0]{$_}))
+    {
+      push (@args, $_ . '=' . $idents->[0]{$_});
+    }
+  }
+  push (@args, "index=$index");
+
+  return (join (';', @args));
+} # getGraphArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/Type/Wirkleistung.pm b/contrib/collection3/lib/Collectd/Graph/Type/Wirkleistung.pm
new file mode 100644 (file)
index 0000000..6d5234f
--- /dev/null
@@ -0,0 +1,90 @@
+package Collectd::Graph::Type::Wirkleistung;
+
+# Copyright (C) 2009  Stefan Pfab <spfab at noris.net>
+#
+# 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+use base ('Collectd::Graph::Type');
+
+use Collectd::Graph::Common (qw(ident_to_filename get_faded_color));
+
+return (1);
+
+sub getDataSources
+{
+  return ([qw(wirkleistung)]);
+} # getDataSources
+
+sub new
+{
+  my $pkg = shift;
+  my $obj = Collectd::Graph::Type->new (@_);
+  $obj->{'data_sources'} = [qw(wirkleistung)];
+  $obj->{'rrd_opts'} = ['-v', 'Watt'];
+  $obj->{'rrd_title'} = 'Wirkleistung ({type_instance})';
+  $obj->{'rrd_format'} = '%5.1lf%s W';
+  $obj->{'colors'} = [qw(000000 f00000)];
+
+  return (bless ($obj, $pkg));
+} # new
+
+sub getRRDArgs
+{
+  my $obj = shift;
+  my $index = shift;
+
+  my $ident = $obj->{'files'}[$index];
+  if (!$ident)
+  {
+    cluck ("Invalid index: $index");
+    return;
+  }
+  my $filename = ident_to_filename ($ident);
+  $filename =~ s#:#\\:#g;
+
+  my $faded_green = get_faded_color ('00ff00');
+  my $faded_red = get_faded_color ('ff0000');
+
+  return (['-t', 'Wirkleistung (' . $ident->{'type_instance'} . ')', '-v', 'Watt', '-l', '0',
+    "DEF:min0=${filename}:kWh:MIN",
+    "DEF:avg0=${filename}:kWh:AVERAGE",
+    "DEF:max0=${filename}:kWh:MAX",
+    'AREA:max0#bfbfbf',
+    'AREA:min0#FFFFFF',
+    'CDEF:watt_avg0=avg0,36000,*,',
+    'CDEF:watt_min0=min0,36000,*,',
+    'CDEF:watt_max0=max0,36000,*,',
+    'CDEF:watt_total=avg0,10,*,',
+    'VDEF:total=watt_total,TOTAL',
+    'VDEF:first=watt_total,FIRST',
+    'VDEF:last=watt_total,LAST',
+    #'CDEF:first_value=first,POP',
+    #'CDEF:first_time=first,POP',
+    'LINE1:watt_avg0#000000:W',
+    'HRULE:190#ff0000',
+    'GPRINT:watt_min0:MIN:%4.1lfW Min,',
+    'GPRINT:watt_avg0:AVERAGE:%4.1lfW Avg,',
+    'GPRINT:watt_max0:MAX:%4.1lfW Max,',
+    'GPRINT:watt_avg0:LAST:%4.1lfW Last\l',
+    'GPRINT:total:%4.1lf%sWh Gesamtverbrauch im angezeigten Zeitraum\l',
+    'GPRINT:first:erster Wert %c:strftime',
+    'GPRINT:last:letzter Wert %c:strftime']);
+
+    # HRULE:190\ ff0000    
+
+} # getRRDArgs
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
diff --git a/contrib/collection3/lib/Collectd/Graph/TypeLoader.pm b/contrib/collection3/lib/Collectd/Graph/TypeLoader.pm
new file mode 100644 (file)
index 0000000..3d6f61e
--- /dev/null
@@ -0,0 +1,270 @@
+package Collectd::Graph::TypeLoader;
+
+=head1 NAME
+
+Collectd::Graph::TypeLoader - Load a module according to the "type"
+
+=cut
+
+# Copyright (C) 2008,2009  Florian octo Forster <octo at verplant.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+use strict;
+use warnings;
+
+use Carp (qw(cluck confess));
+use Exporter ();
+use Config::General ('ParseConfig');
+use Collectd::Graph::Config ('gc_get_config');
+use Collectd::Graph::Type ();
+
+@Collectd::Graph::TypeLoader::ISA = ('Exporter');
+@Collectd::Graph::TypeLoader::EXPORT_OK = ('tl_load_type');
+
+our @ArrayMembers = (qw(data_sources rrd_opts custom_order));
+our @ScalarMembers = (qw(rrd_title rrd_format rrd_vertical scale ignore_unknown stacking));
+our @DSMappedMembers = (qw(ds_names rrd_colors));
+
+our %MemberToConfigMap =
+(
+  data_sources => 'datasources',
+  ds_names => 'dsname',
+  rrd_title => 'rrdtitle',
+  rrd_opts => 'rrdoptions',
+  rrd_format => 'rrdformat',
+  rrd_vertical => 'rrdverticallabel',
+  rrd_colors => 'color',
+  scale => 'scale', # GenericIO only
+  custom_order => 'order', # GenericStacked only
+  stacking => 'stacking', # GenericStacked only
+  ignore_unknown => 'ignoreunknown' # GenericStacked only
+);
+
+return (1);
+
+sub _create_object
+{
+  my $module = shift;
+  my $obj;
+
+  # Suppress warnings and error messages caused by the eval.
+  local $SIG{__WARN__} = sub { return (1); print STDERR "WARNING: " . join (', ', @_) . "\n"; };
+  local $SIG{__DIE__}  = sub { return (1); print STDERR "FATAL: "   . join (', ', @_) . "\n"; };
+
+  eval <<PERL;
+  require $module;
+  \$obj = ${module}->new ();
+PERL
+  if (!$obj)
+  {
+    return;
+  }
+
+  return ($obj);
+} # _create_object
+
+sub _load_module_from_config
+{
+  my $conf = shift;
+
+  my $module = $conf->{'module'};
+  my $obj;
+  
+  if ($module && !($module =~ m/::/))
+  {
+    $module = "Collectd::Graph::Type::$module";
+  }
+
+  if ($module)
+  {
+    $obj = _create_object ($module);
+    if (!$obj)
+    {
+      #cluck ("Creating an $module object failed");
+      warn ("Creating an $module object failed");
+      return;
+    }
+  }
+  else
+  {
+    $obj = Collectd::Graph::Type->new ();
+    if (!$obj)
+    {
+      cluck ("Creating an Collectd::Graph::Type object failed");
+      return;
+    }
+  }
+
+  for (@ScalarMembers) # {{{
+  {
+    my $member = $_;
+    my $key = $MemberToConfigMap{$member};
+    my $val;
+
+    if (!defined $conf->{$key})
+    {
+      next;
+    }
+    $val = $conf->{$key};
+    
+    if (ref ($val) ne '')
+    {
+      cluck ("Invalid value type for $key: " . ref ($val));
+      next;
+    }
+
+    $obj->{$member} = $val;
+  } # }}}
+
+  for (@ArrayMembers) # {{{
+  {
+    my $member = $_;
+    my $key = $MemberToConfigMap{$member};
+    my $val;
+
+    if (!defined $conf->{$key})
+    {
+      next;
+    }
+    $val = $conf->{$key};
+    
+    if (ref ($val) eq 'ARRAY')
+    {
+      $obj->{$member} = $val;
+    }
+    elsif (ref ($val) eq '')
+    {
+      $obj->{$member} = [split (' ', $val)];
+    }
+    else
+    {
+      cluck ("Invalid value type for $key: " . ref ($val));
+    }
+  } # }}}
+
+  for (@DSMappedMembers) # {{{
+  {
+    my $member = $_;
+    my $key = $MemberToConfigMap{$member};
+    my @val_list;
+
+    if (!defined $conf->{$key})
+    {
+      next;
+    }
+
+    if (ref ($conf->{$key}) eq 'ARRAY')
+    {
+      @val_list = @{$conf->{$key}};
+    }
+    elsif (ref ($conf->{$key}) eq '')
+    {
+      @val_list = ($conf->{$key});
+    }
+    else
+    {
+      cluck ("Invalid value type for $key: " . ref ($conf->{$key}));
+      next;
+    }
+
+    for (@val_list)
+    {
+      my $line = $_;
+      my $ds;
+      my $val;
+
+      if (!defined ($line) || (ref ($line) ne ''))
+      {
+        next;
+      }
+
+      ($ds, $val) = split (' ', $line, 2);
+      if (!$ds || !$val)
+      {
+        next;
+      }
+
+      $obj->{$member} ||= {};
+      $obj->{$member}{$ds} = $val;
+    } # for (@val_list)
+  } # }}} for (@DSMappedMembers)
+
+  return ($obj);
+} # _load_module_from_config
+
+sub _load_module_generic
+{
+  my $type = shift;
+  my $module = ucfirst (lc ($type));
+  my $obj;
+
+  $module =~ s/[^A-Za-z_]//g;
+  $module =~ s/_([A-Za-z])/\U$1\E/g;
+
+  $obj = _create_object ($module);
+  if (!$obj)
+  {
+    $obj = Collectd::Graph::Type->new ();
+    if (!$obj)
+    {
+      cluck ("Creating an Collectd::Graph::Type object failed");
+      return;
+    }
+  }
+
+  return ($obj);
+} # _load_module_generic
+
+=head1 EXPORTED FUNCTIONS
+
+=over 4
+
+=item B<tl_load_type> (I<$type>)
+
+Does whatever is necessary to get an object with which to graph RRD files of
+type I<$type>.
+
+=cut
+
+sub tl_load_type
+{
+  my $type = shift;
+  my $conf = gc_get_config ();
+
+  if (defined ($conf) && defined ($conf->{'type'}{$type}))
+  {
+    return (_load_module_from_config ($conf->{'type'}{$type}));
+  }
+  else
+  {
+    return (_load_module_generic ($type));
+  }
+} # tl_load_type
+
+=back
+
+=head1 SEE ALSO
+
+L<Collectd::Graph::Type::GenericStacked>
+
+=head1 AUTHOR AND LICENSE
+
+Copyright (c) 2008 by Florian Forster
+E<lt>octoE<nbsp>atE<nbsp>verplant.orgE<gt>. Licensed under the terms of the GNU
+General Public License, VersionE<nbsp>2 (GPLv2).
+
+=cut
+
+# vim: set shiftwidth=2 softtabstop=2 tabstop=8 et fdm=marker :
diff --git a/contrib/collection3/share/.htaccess b/contrib/collection3/share/.htaccess
new file mode 100644 (file)
index 0000000..e139ace
--- /dev/null
@@ -0,0 +1,2 @@
+Options -ExecCGI
+SetHandler none
diff --git a/contrib/collection3/share/navigate.js b/contrib/collection3/share/navigate.js
new file mode 100644 (file)
index 0000000..3bfe56e
--- /dev/null
@@ -0,0 +1,300 @@
+function nav_init (time_begin, time_end)
+{
+  var all_images;
+  var i;
+
+  all_images = document.getElementsByTagName ("img");
+  for (i = 0; i < all_images.length; i++)
+  {
+    if (all_images[i].className != "graph_image")
+      continue;
+
+    all_images[i].navTimeBegin = new Number (time_begin);
+    all_images[i].navTimeEnd   = new Number (time_end);
+
+    all_images[i].navBaseURL = all_images[i].src.replace (/;(begin|end)=[^;]*/g, '');
+
+    if (all_images[i].addEventListener) /* Mozilla */
+    {
+      all_images[i].addEventListener ('dblclick', nav_handle_dblclick,
+          false /* == bubbling */);
+      all_images[i].addEventListener ('DOMMouseScroll', nav_handle_wheel,
+          false /* == bubbling */);
+    }
+    else
+    {
+      all_images[i].ondblclick = nav_handle_dblclick;
+      all_images[i].onmousewheel = nav_handle_wheel;
+    }
+  }
+
+  return (true);
+} /* nav_init */
+
+function nav_image_repaint (img)
+{
+  if (!img || !img.navBaseURL
+      || !img.navTimeBegin || !img.navTimeEnd)
+    return;
+
+  img.src = img.navBaseURL + ";"
+    + "begin=" + img.navTimeBegin.toFixed (0) + ";"
+    + "end=" + img.navTimeEnd.toFixed (0);
+} /* nav_image_repaint */
+
+function nav_time_reset (img_id ,diff)
+{
+  var img;
+
+  img = document.getElementById (img_id);
+  if (!img)
+    return (false);
+
+  img.navTimeEnd = new Number ((new Date ()).getTime () / 1000);
+  img.navTimeBegin = new Number (img.navTimeEnd - diff);
+
+  nav_image_repaint (img);
+
+  return (true);
+}
+
+function nav_time_change_obj (img, factor_begin, factor_end)
+{
+  var diff;
+
+  if (!img || !img.navBaseURL
+      || !img.navTimeBegin || !img.navTimeEnd)
+    return (false);
+
+  diff = img.navTimeEnd - img.navTimeBegin;
+
+  /* Prevent zooming in if diff is less than five minutes */
+  if ((diff <= 300) && (factor_begin > 0.0) && (factor_end < 0.0))
+    return (true);
+
+  img.navTimeBegin += (diff * factor_begin);
+  img.navTimeEnd   += (diff * factor_end);
+
+  nav_image_repaint (img);
+
+  return (true);
+} /* nav_time_change */
+
+function nav_time_change (img_id, factor_begin, factor_end)
+{
+  var diff;
+
+  if (img_id == '*')
+  {
+    var all_images;
+    var i;
+
+    all_images = document.getElementsByTagName ("img");
+    for (i = 0; i < all_images.length; i++)
+    {
+      if (all_images[i].className != "graph_image")
+        continue;
+    
+      nav_time_change_obj (all_images[i], factor_begin, factor_end);
+    }
+  }
+  else
+  {
+    var img;
+
+    img = document.getElementById (img_id);
+    if (!img)
+      return (false);
+
+    nav_time_change_obj (img, factor_begin, factor_end);
+  }
+
+  return (true);
+} /* nav_time_change */
+
+function nav_move_earlier (img_id)
+{
+  return (nav_time_change (img_id, -0.2, -0.2));
+} /* nav_move_earlier */
+
+function nav_move_later (img_id)
+{
+  return (nav_time_change (img_id, +0.2, +0.2));
+} /* nav_move_later */
+
+function nav_zoom_in (img_id)
+{
+  return (nav_time_change (img_id, +0.2, -0.2));
+} /* nav_zoom_in */
+
+function nav_zoom_out (img_id)
+{
+  return (nav_time_change (img_id, (-1.0 / 3.0), (1.0 / 3.0)));
+} /* nav_zoom_in */
+
+function nav_set_reference (img_id)
+{
+  var img;
+  var all_images;
+  var tmp;
+  var i;
+
+  img = document.getElementById (img_id);
+  if (!img || (img.className != "graph_image")
+      || !img.navTimeBegin || !img.navTimeEnd)
+    return;
+
+  all_images = document.getElementsByTagName ("img");
+  for (i = 0; i < all_images.length; i++)
+  {
+    tmp = all_images[i];
+    if (!tmp || (tmp.className != "graph_image")
+        || !tmp.navTimeBegin || !tmp.navTimeEnd)
+      continue;
+
+    if (tmp.id == img_id)
+      continue;
+
+    tmp.navTimeBegin = img.navTimeBegin;
+    tmp.navTimeEnd = img.navTimeEnd;
+
+    nav_image_repaint (tmp);
+  }
+} /* nav_set_reference */
+
+/* 
+ * TODO: calculate the mouse position relative to the image in a cross-browser
+ * manner.
+ */
+function nav_calculate_offset_x (obj)
+{
+  var offset = 0;
+
+  if (!obj)
+    return (offset);
+
+  offset = obj.offsetLeft;
+  if (obj.offsetParent)
+    offset += nav_calculate_offset_x (obj.offsetParent);
+
+  return (offset);
+} /* nav_calculate_offset_x */
+
+function nav_calculate_event_x (e)
+{
+  var pos = 0;
+  var off = 0;
+
+  if (!e || !e.target)
+    return;
+  
+  off = nav_calculate_offset_x (e.target);
+
+  if (e.pageX || e.pageY)
+  {
+    pos = e.pageX;
+  }
+  else if (e.clientX || e.clientY)
+  {
+    pos = e.clientX + document.body.scrollLeft
+      + document.documentElement.scrollLeft;
+  }
+
+  return (pos);
+} /* nav_calculate_event_x */
+
+function nav_recenter (e)
+{
+  var x;
+  var y;
+  var img;
+  var diff;
+  var time_old_center;
+  var time_new_center;
+  var width;
+
+  img = e.target;
+  if (!img || (img.className != "graph_image")
+      || !img.navTimeBegin || !img.navTimeEnd)
+    return;
+
+  width = img.width - 97;
+
+  x = e.layerX - 70;
+  if (!x || (x < 0) || (x > width))
+    return;
+
+  y = e.layerY;
+  if (!y || (y < 35) || (y > 135))
+    return;
+
+  diff = img.navTimeEnd - img.navTimeBegin;
+
+  time_old_center = img.navTimeBegin + (diff / 2.0);
+  time_new_center = img.navTimeBegin + (x * diff / width);
+
+  img.navTimeBegin += (time_new_center - time_old_center);
+  img.navTimeEnd   += (time_new_center - time_old_center);
+} /* nav_recenter */
+
+function nav_handle_dblclick (e)
+{
+  var img;
+
+  /* M$IE */
+  if (!e)
+    e = window.event;
+
+  img = e.target;
+  if (!img || (img.className != "graph_image")
+      || !img.navTimeBegin || !img.navTimeEnd)
+    return;
+
+  nav_recenter (e);
+  nav_image_repaint (img);
+
+  // e.returnValue = false;
+} /* nav_handle_dblclick */
+
+/* Taken from <http://adomas.org/javascript-mouse-wheel/> */
+function nav_handle_wheel (e)
+{
+  var delta = 0;
+  var img;
+  
+  /* M$IE */
+  if (!e)
+    e = window.event;
+
+  img = e.target;
+  if (!img || (img.className != "graph_image")
+      || !img.navTimeBegin || !img.navTimeEnd)
+    return;
+
+  /* Opera and M$IE */
+  if (e.wheelDelta)
+  {
+    delta = e.wheelDelta; 
+    if (window.opera)
+      delta = delta * (-1);
+  }
+  else if (e.detail)
+  {
+    delta = e.detail * (-1);
+  }
+
+  if (!delta)
+    return;
+
+  nav_recenter (e);
+  if (delta > 0)
+    nav_zoom_in (img.id);
+  else
+    nav_zoom_out (img.id);
+
+  if (e.preventDefault)
+    e.preventDefault ();
+  e.returnValue = false;
+} /* function nav_handle_wheel */
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/contrib/collection3/share/shortcut-icon.png b/contrib/collection3/share/shortcut-icon.png
new file mode 100644 (file)
index 0000000..6af57e5
Binary files /dev/null and b/contrib/collection3/share/shortcut-icon.png differ
diff --git a/contrib/collection3/share/style.css b/contrib/collection3/share/style.css
new file mode 100644 (file)
index 0000000..8c12951
--- /dev/null
@@ -0,0 +1,79 @@
+div.graph
+{
+}
+
+div.graph_canvas div.graph_float
+{
+  float: left;
+  position: relative;
+}
+
+div.graph_float div.controls
+{
+  display: none;
+  position: absolute;
+}
+
+div.graph_float:hover div.controls
+{
+  display: block;
+}
+
+div.graph_float div.controls.zoom
+{
+  right: 5px;
+  bottom: 10px;
+}
+
+div.graph_float div.controls.preset
+{
+  right: 5px;
+  top: 5px;
+}
+
+div.graph_float div.controls div
+{
+  display: block;
+
+  color: gray;
+  background: white;
+
+  text-decoration: none;
+  text-align: center;
+  font-size: small;
+
+  cursor: pointer;
+
+  border: 1px solid gray;
+  width: 1em;
+  height: 1em;
+  padding: 1px;
+  margin: 0px;
+}
+
+div.graph_float div.controls div:hover
+{
+  color: black;
+  border-color: black;
+}
+
+div.graph_float div.controls.preset div
+{
+  margin: 1px 0px 1px 0px;
+}
+
+div.graph_float div.controls.zoom div
+{
+  float: left;
+  margin: 0px 1px 0px 1px;
+}
+
+table
+{
+  border-collapse: collapse;
+}
+td, th
+{
+  border: 1px solid gray;
+}
+/* vim: set sw=2 sts=2 et : */
diff --git a/contrib/collection3/test.px b/contrib/collection3/test.px
new file mode 100644 (file)
index 0000000..f855226
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use HTML::Entities;
+use Carp ('croak');
+
+my @bad_strings = ("foo\x0f<bar>\n", "foo\x00<bar>\n");
+my @good_strings = ("foo <bar>\n", "foo\t<bar>\n");
+
+sub contains_invalid_chars
+{
+  my $str = shift;
+
+  for (split (m//, $str))
+  {
+    my $n = ord ($_);
+
+    if (($n >= 9) && ($n <= 13))
+    {
+      next;
+    }
+    elsif ($n < 32)
+    {
+      return (1);
+    }
+  }
+
+  return;
+}
+
+sub assert
+{
+  if (!$_[0])
+  {
+    croak ("assertion failed");
+  }
+}
+
+for (@bad_strings)
+{
+  assert (contains_invalid_chars ($_));
+}
+
+for (@good_strings)
+{
+  assert (!contains_invalid_chars ($_));
+}
diff --git a/contrib/cussh.pl b/contrib/cussh.pl
new file mode 100755 (executable)
index 0000000..ae758d1
--- /dev/null
@@ -0,0 +1,512 @@
+#!/usr/bin/perl
+#
+# collectd - contrib/cussh.pl
+# Copyright (C) 2007-2009  Sebastian Harl
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# 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:
+#   Sebastian Harl <sh at tokkee.org>
+#
+
+=head1 NAME
+
+cussh - collectd UNIX socket shell
+
+=head1 SYNOPSIS
+
+B<cussh> [I<E<lt>pathE<gt>>]
+
+=head1 DESCRIPTION
+
+B<collectd>'s unixsock plugin allows external programs to access the values it
+has collected or received and to submit own values. This is a little
+interactive frontend for this plugin.
+
+=head1 OPTIONS
+
+=over 4
+
+=item I<E<lt>pathE<gt>>
+
+The path to the UNIX socket provided by collectd's unixsock plugin. (Default:
+F</var/run/collectd-unixsock>)
+
+=back
+
+=cut
+
+use strict;
+use warnings;
+
+use Collectd::Unixsock();
+
+{ # main
+       my $path = $ARGV[0] || "/var/run/collectd-unixsock";
+       my $sock = Collectd::Unixsock->new($path);
+
+       my $cmds = {
+               HELP    => \&cmd_help,
+               PUTVAL  => \&putval,
+               GETVAL  => \&getval,
+               GETTHRESHOLD  => \&getthreshold,
+               FLUSH   => \&flush,
+               LISTVAL => \&listval,
+               PUTNOTIF => \&putnotif,
+       };
+
+       if (! $sock) {
+               print STDERR "Unable to connect to $path!\n";
+               exit 1;
+       }
+
+       print "cussh version 0.2, Copyright (C) 2007-2008 Sebastian Harl\n"
+               . "cussh comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
+               . "and you are welcome to redistribute it under certain conditions.\n"
+               . "See the GNU General Public License 2 for more details.\n\n";
+
+       while (1) {
+               print "cussh> ";
+               my $line = <STDIN>;
+
+               last if (! $line);
+
+               chomp $line;
+
+               last if ($line =~ m/^quit$/i);
+
+               my ($cmd) = $line =~ m/^(\w+)\s*/;
+               $line = $';
+
+               next if (! $cmd);
+               $cmd = uc $cmd;
+
+               my $f = undef;
+               if (defined $cmds->{$cmd}) {
+                       $f = $cmds->{$cmd};
+               }
+               else {
+                       print STDERR "ERROR: Unknown command $cmd!\n";
+                       next;
+               }
+
+               if (! $f->($sock, $line)) {
+                       print STDERR "ERROR: Command failed!\n";
+                       next;
+               }
+       }
+
+       $sock->destroy();
+       exit 0;
+}
+
+sub tokenize {
+       my $line     = shift || return;
+       my $line_ptr = $line;
+       my @line     = ();
+
+       my $token_pattern = qr/[^"\s]+|"[^"]+"/;
+
+       while (my ($token) = $line_ptr =~ m/^($token_pattern)\s+/) {
+               $line_ptr = $';
+               push @line, $token;
+       }
+
+       if ($line_ptr =~ m/^$token_pattern$/) {
+               push @line, $line_ptr;
+       }
+       else {
+               my ($token) = split m/ /, $line_ptr, 1;
+               print STDERR "Failed to parse line: $line\n";
+               print STDERR "Parse error near token \"$token\".\n";
+               return;
+       }
+
+       foreach my $l (@line) {
+               if ($l =~ m/^"(.*)"$/) {
+                       $l = $1;
+               }
+       }
+       return @line;
+}
+
+sub getid {
+       my $string = shift || return;
+
+       my ($h, $p, $pi, $t, $ti) =
+               $string =~ m#^([^/]+)/([^/-]+)(?:-([^/]+))?/([^/-]+)(?:-([^/]+))?\s*#;
+       $string = $';
+
+       return if ((! $h) || (! $p) || (! $t));
+
+       my %id = ();
+
+       ($id{'host'}, $id{'plugin'}, $id{'type'}) = ($h, $p, $t);
+
+       $id{'plugin_instance'} = $pi if defined ($pi);
+       $id{'type_instance'} = $ti if defined ($ti);
+       return \%id;
+}
+
+sub putid {
+       my $ident = shift || return;
+
+       my $string;
+
+       $string = $ident->{'host'} . "/" . $ident->{'plugin'};
+
+       if (defined $ident->{'plugin_instance'}) {
+               $string .= "-" . $ident->{'plugin_instance'};
+       }
+
+       $string .= "/" . $ident->{'type'};
+
+       if (defined $ident->{'type_instance'}) {
+               $string .= "-" . $ident->{'type_instance'};
+       }
+       return $string;
+}
+
+=head1 COMMANDS
+
+=over 4
+
+=item B<HELP>
+
+=cut
+
+sub cmd_help {
+       my $sock = shift;
+       my $line = shift || '';
+
+       my @line = tokenize($line);
+       my $cmd = shift (@line);
+
+       my %text = (
+               help => <<HELP,
+Available commands:
+  HELP
+  PUTVAL
+  GETVAL
+  GETTHRESHOLD
+  FLUSH
+  LISTVAL
+  PUTNOTIF
+
+See the embedded Perldoc documentation for details. To do that, run:
+  perldoc $0
+HELP
+               putval => <<HELP,
+PUTVAL <id> <value0> [<value1> ...]
+
+Submits a value to the daemon.
+HELP
+               getval => <<HELP,
+GETVAL <id>
+
+Retrieves the current value or values from the daemon.
+HELP
+               flush => <<HELP,
+FLUSH [plugin=<plugin>] [timeout=<timeout>] [identifier=<id>] [...]
+
+Sends a FLUSH command to the daemon.
+HELP
+               listval => <<HELP,
+LISTVAL
+
+Prints a list of available values.
+HELP
+               putnotif => <<HELP
+PUTNOTIF severity=<severity> [...] message=<message>
+
+Sends a notifications message to the daemon.
+HELP
+       );
+
+       if (!$cmd)
+       {
+               $cmd = 'help';
+       }
+       if (!exists ($text{$cmd}))
+       {
+               print STDOUT "Unknown command: " . uc ($cmd) . "\n\n";
+               $cmd = 'help';
+       }
+
+       print STDOUT $text{$cmd};
+
+       return 1;
+} # cmd_help
+
+=item B<PUTVAL> I<Identifier> I<Valuelist>
+
+=cut
+
+sub putval {
+       my $sock = shift || return;
+       my $line = shift || return;
+
+       my @line = tokenize($line);
+
+       my $id;
+       my $ret;
+
+       if (! @line) {
+               return;
+       }
+
+       if (scalar(@line) < 2) {
+               print STDERR "Synopsis: PUTVAL <id> <value0> [<value1> ...]" . $/;
+               return;
+       }
+
+       $id = getid($line[0]);
+
+       if (! $id) {
+               print STDERR "Invalid id \"$line[0]\"." . $/;
+               return;
+       }
+
+       my ($time, @values) = split m/:/, $line;
+       $ret = $sock->putval(%$id, time => $time, values => \@values);
+
+       if (! $ret) {
+               print STDERR "socket error: " . $sock->{'error'} . $/;
+       }
+       return $ret;
+}
+
+=item B<GETVAL> I<Identifier>
+
+=cut
+
+sub getval {
+       my $sock = shift || return;
+       my $line = shift || return;
+
+       my @line = tokenize($line);
+
+       my $id;
+       my $vals;
+
+       if (! @line) {
+               return;
+       }
+
+       if (scalar(@line) < 1) {
+               print STDERR "Synopsis: GETVAL <id>" . $/;
+               return;
+       }
+
+       $id = getid($line[0]);
+
+       if (! $id) {
+               print STDERR "Invalid id \"$line[0]\"." . $/;
+               return;
+       }
+
+       $vals = $sock->getval(%$id);
+
+       if (! $vals) {
+               print STDERR "socket error: " . $sock->{'error'} . $/;
+               return;
+       }
+
+       foreach my $key (keys %$vals) {
+               print "\t$key: $vals->{$key}\n";
+       }
+       return 1;
+}
+
+=item B<GETTHRESHOLD> I<Identifier>
+
+=cut
+
+sub getthreshold {
+       my $sock = shift || return;
+       my $line = shift || return;
+
+       my @line = tokenize($line);
+
+       my $id;
+       my $vals;
+
+       if (! @line) {
+               return;
+       }
+
+       if (scalar(@line) < 1) {
+               print STDERR "Synopsis: GETTHRESHOLD <id>" . $/;
+               return;
+       }
+
+       $id = getid($line[0]);
+
+       if (! $id) {
+               print STDERR "Invalid id \"$line[0]\"." . $/;
+               return;
+       }
+
+       $vals = $sock->getthreshold(%$id);
+
+       if (! $vals) {
+               print STDERR "socket error: " . $sock->{'error'} . $/;
+               return;
+       }
+
+       foreach my $key (keys %$vals) {
+               print "\t$key: $vals->{$key}\n";
+       }
+       return 1;
+}
+
+=item B<FLUSH> [B<timeout>=I<$timeout>] [B<plugin>=I<$plugin>[ ...]]
+
+=cut
+
+sub flush {
+       my $sock = shift || return;
+       my $line = shift;
+
+       my @line = tokenize($line);
+
+       my $res;
+
+       if (! $line) {
+               $res = $sock->flush();
+       }
+       else {
+               my %args = ();
+
+               foreach my $i (@line) {
+                       my ($option, $value) = $i =~ m/^([^=]+)=(.+)$/;
+                       next if (! ($option && $value));
+
+                       if ($option eq "plugin") {
+                               push @{$args{"plugins"}}, $value;
+                       }
+                       elsif ($option eq "timeout") {
+                               $args{"timeout"} = $value;
+                       }
+                       elsif ($option eq "identifier") {
+                               my $id = getid ($value);
+                               if (!$id)
+                               {
+                                       print STDERR "Not a valid identifier: \"$value\"\n";
+                                       next;
+                               }
+                               push @{$args{"identifier"}}, $id;
+                       }
+                       else {
+                               print STDERR "Invalid option \"$option\".\n";
+                               return;
+                       }
+               }
+
+               $res = $sock->flush(%args);
+       }
+
+       if (! $res) {
+               print STDERR "socket error: " . $sock->{'error'} . $/;
+       }
+       return $res;
+}
+
+=item B<LISTVAL>
+
+=cut
+
+sub listval {
+       my $sock = shift || return;
+       my $line = shift;
+
+       my @res;
+
+       if ($line ne "") {
+               print STDERR "Synopsis: LISTVAL" . $/;
+               return;
+       }
+
+       @res = $sock->listval();
+
+       if (! @res) {
+               print STDERR "socket error: " . $sock->{'error'} . $/;
+               return;
+       }
+
+       foreach my $ident (@res) {
+               print $ident->{'time'} . " " . putid($ident) . $/;
+       }
+       return 1;
+}
+
+=item B<PUTNOTIF> [[B<severity>=I<$severity>] [B<message>=I<$message>] [ ...]]
+
+=cut
+
+sub putnotif {
+       my $sock = shift || return;
+       my $line = shift || return;
+
+       my @line = tokenize($line);
+
+       my $ret;
+
+       my (%values) = ();
+       foreach my $i (@line) {
+               my ($key, $val) = split m/=/, $i, 2;
+               if ($key && $val) {
+                       $values{$key} = $val;
+               }
+               else {
+                       $values{'message'} = defined($values{'message'})
+                               ? ($values{'message'} . ' ' . $key)
+                               : $key;
+               }
+       }
+       $values{'time'} ||= time();
+
+       $ret = $sock->putnotif(%values);
+       if (! $ret) {
+               print STDERR "socket error: " . $sock->{'error'} . $/;
+       }
+       return $ret;
+}
+
+=back
+
+These commands follow the exact same syntax as described in
+L<collectd-unixsock(5)>.
+
+=head1 SEE ALSO
+
+L<collectd(1)>, L<collectd-unisock(5)>
+
+=head1 AUTHOR
+
+Written by Sebastian Harl E<lt>sh@tokkee.orgE<gt>.
+
+B<collectd> has been written by Florian Forster and others.
+
+=head1 COPYRIGHT
+
+Copyright (C) 2007 Sebastian Harl.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; only version 2 of the License is applicable.
+
+=cut
+
+# vim: set sw=4 ts=4 tw=78 noexpandtab :
diff --git a/contrib/examples/MyPlugin.pm b/contrib/examples/MyPlugin.pm
new file mode 100644 (file)
index 0000000..b1a8a6d
--- /dev/null
@@ -0,0 +1,170 @@
+# /usr/share/doc/collectd/examples/MyPlugin.pm
+#
+# A Perl plugin template for collectd.
+#
+# Written by Sebastian Harl <sh@tokkee.org>
+#
+# This 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.
+
+# Notes:
+# - each of the functions below (and the corresponding plugin_register call)
+#   is optional
+
+package Collectd::Plugin::MyPlugin;
+
+use strict;
+use warnings;
+
+use Collectd qw( :all );
+
+# data set definition:
+# see section "DATA TYPES" in collectd-perl(5) for details
+#
+# NOTE: If you're defining a custom data-set, you have to make that known to
+# any servers as well. Else, the server is not able to store values using the
+# type defined by that data-set.
+# It is strongly recommended to use one of the types and data-sets pre-defined
+# in the types.db file.
+my $dataset =
+[
+       {
+               name => 'my_ds',
+               type => DS_TYPE_GAUGE,
+               min  => 0,
+               max  => 65535,
+       },
+];
+
+# This code is executed after loading the plugin to register it with collectd.
+plugin_register (TYPE_LOG, 'myplugin', 'my_log');
+plugin_register (TYPE_NOTIF, 'myplugin', 'my_notify');
+plugin_register (TYPE_DATASET, 'mytype', $dataset);
+plugin_register (TYPE_INIT, 'myplugin', 'my_init');
+plugin_register (TYPE_READ, 'myplugin', 'my_read');
+plugin_register (TYPE_WRITE, 'myplugin', 'my_write');
+plugin_register (TYPE_SHUTDOWN, 'myplugin', 'my_shutdown');
+
+# For each of the functions below see collectd-perl(5) for details about
+# arguments and the like.
+
+# This function is called once upon startup to initialize the plugin.
+sub my_init
+{
+       # open sockets, initialize data structures, ...
+
+       # A false return value indicates an error and causes the plugin to be
+       # disabled.
+       return 1;
+} # my_init ()
+
+# This function is called in regular intervals to collectd the data.
+sub my_read
+{
+       # value list to dispatch to collectd:
+       # see section "DATA TYPES" in collectd-perl(5) for details
+       my $vl = {};
+
+       # do the magic to read the data:
+       # the number of values has to match the number of data sources defined in
+       # the registered data set. The type used here (in this example:
+       # "mytype") must be defined in the types.db, see types.db(5) for
+       # details, or registered as "TYPE_DATASET".
+       $vl->{'values'} = [ rand(65535) ];
+       $vl->{'plugin'} = 'myplugin';
+       $vl->{'type'}   = 'mytype';
+       # any other elements are optional
+
+       # dispatch the values to collectd which passes them on to all registered
+       # write functions
+       plugin_dispatch_values ($vl);
+
+       # A false return value indicates an error and the plugin will be skipped
+       # for an increasing amount of time.
+       return 1;
+} # my_read ()
+
+# This function is called after values have been dispatched to collectd.
+sub my_write
+{
+       my $type = shift;
+       my $ds   = shift;
+       my $vl   = shift;
+
+       if (scalar (@$ds) != scalar (@{$vl->{'values'}})) {
+               plugin_log (LOG_WARNING, "DS number does not match values length");
+               return;
+       }
+
+       for (my $i = 0; $i < scalar (@$ds); ++$i) {
+               # do the magic to output the data
+               print "$vl->{'host'}: $vl->{'plugin'}: ";
+
+               if (defined $vl->{'plugin_instance'}) {
+                       print "$vl->{'plugin_instance'}: ";
+               }
+
+               print "$type: ";
+
+               if (defined $vl->{'type_instance'}) {
+                       print "$vl->{'type_instance'}: ";
+               }
+
+               print "$vl->{'values'}->[$i]\n";
+       }
+       return 1;
+} # my_write()
+
+# This function is called before shutting down collectd.
+sub my_shutdown
+{
+       # close sockets, ...
+       return 1;
+} # my_shutdown ()
+
+# This function is called when plugin_log () has been used.
+sub my_log
+{
+       my $level = shift;
+       my $msg   = shift;
+
+       print "LOG: $level - $msg\n";
+       return 1;
+} # my_log ()
+
+# This function is called when plugin_dispatch_notification () has been used
+sub my_notify
+{
+       my $notif = shift;
+
+       my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($notif->{'time'});
+
+       printf "NOTIF (%04d-%02d-%02d %02d:%02d:%02d): %d - ",
+                       $year + 1900, $mon + 1, $mday, $hour, $min, $sec,
+                       $notif->{'severity'};
+
+       if (defined $notif->{'host'}) {
+               print "$notif->{'host'}: ";
+       }
+
+       if (defined $notif->{'plugin'}) {
+               print "$notif->{'plugin'}: ";
+       }
+
+       if (defined $notif->{'plugin_instance'}) {
+               print "$notif->{'plugin_instance'}: ";
+       }
+
+       if (defined $notif->{'type'}) {
+               print "$notif->{'type'}: ";
+       }
+
+       if (defined $notif->{'type_instance'}) {
+               print "$notif->{'type_instance'}: ";
+       }
+
+       print "$notif->{'message'}\n";
+       return 1;
+} # my_notify ()
+
diff --git a/contrib/examples/myplugin.c b/contrib/examples/myplugin.c
new file mode 100644 (file)
index 0000000..9539062
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * /usr/share/doc/collectd/examples/myplugin.c
+ *
+ * A plugin template for collectd.
+ *
+ * Written by Sebastian Harl <sh@tokkee.org>
+ *
+ * This 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.
+ */
+
+/*
+ * Notes:
+ * - plugins are executed in parallel, thus, thread-safe
+ *   functions need to be used
+ * - each of the functions below (except module_register)
+ *   is optional
+ */
+
+#if ! HAVE_CONFIG_H
+
+#include <stdlib.h>
+
+#include <string.h>
+
+#ifndef __USE_ISOC99 /* required for NAN */
+# define DISABLE_ISOC99 1
+# define __USE_ISOC99 1
+#endif /* !defined(__USE_ISOC99) */
+#include <math.h>
+#if DISABLE_ISOC99
+# undef DISABLE_ISOC99
+# undef __USE_ISOC99
+#endif /* DISABLE_ISOC99 */
+
+#include <time.h>
+
+#endif /* ! HAVE_CONFIG */
+
+#include <collectd/collectd.h>
+#include <collectd/common.h>
+#include <collectd/plugin.h>
+
+/*
+ * data source definition:
+ * - name of the data source
+ * - type of the data source (DS_TYPE_GAUGE, DS_TYPE_COUNTER)
+ * - minimum allowed value
+ * - maximum allowed value
+ */
+static data_source_t dsrc[1] =
+{
+       { "my_ds", DS_TYPE_GAUGE, 0, NAN }
+};
+
+/*
+ * data set definition:
+ * - name of the data set
+ * - number of data sources
+ * - list of data sources
+ *
+ * NOTE: If you're defining a custom data-set, you have to make that known to
+ * any servers as well. Else, the server is not able to store values using the
+ * type defined by that data-set.
+ * It is strongly recommended to use one of the types and data-sets
+ * pre-defined in the types.db file.
+ */
+static data_set_t ds =
+{
+       "myplugin", STATIC_ARRAY_SIZE (dsrc), dsrc
+};
+
+/*
+ * This function is called once upon startup to initialize the plugin.
+ */
+static int my_init (void)
+{
+       /* open sockets, initialize data structures, ... */
+
+       /* A return value != 0 indicates an error and causes the plugin to be
+          disabled. */
+    return 0;
+} /* static int my_init (void) */
+
+/*
+ * This function is called in regular intervalls to collect the data.
+ */
+static int my_read (void)
+{
+       value_t values[1]; /* the size of this list should equal the number of
+                                                 data sources */
+       value_list_t vl = VALUE_LIST_INIT;
+
+       /* do the magic to read the data */
+       values[0].gauge = random ();
+
+       vl.values     = values;
+       vl.values_len = 1;
+       vl.time       = time (NULL);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "myplugin", sizeof (vl.plugin));
+
+       /* it is strongly recommended to use a type defined in the types.db file
+        * instead of a custom type */
+       sstrncpy (vl.type, "myplugin", sizeof (vl.plugin));
+       /* optionally set vl.plugin_instance and vl.type_instance to reasonable
+        * values (default: "") */
+
+       /* dispatch the values to collectd which passes them on to all registered
+        * write functions */
+       plugin_dispatch_values (&vl);
+
+       /* A return value != 0 indicates an error and the plugin will be skipped
+        * for an increasing amount of time. */
+    return 0;
+} /* static int my_read (void) */
+
+/*
+ * This function is called after values have been dispatched to collectd.
+ */
+static int my_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t *ud)
+{
+       char name[1024] = "";
+       int i = 0;
+
+       if (ds->ds_num != vl->values_len) {
+               plugin_log (LOG_WARNING, "DS number does not match values length");
+               return -1;
+       }
+
+       /* get the default base filename for the output file - depending on the
+        * provided values this will be something like
+        * <host>/<plugin>[-<plugin_type>]/<instance>[-<instance_type>] */
+       if (0 != format_name (name, 1024, vl->host, vl->plugin,
+                       vl->plugin_instance, ds->type, vl->type_instance))
+               return -1;
+
+       for (i = 0; i < ds->ds_num; ++i) {
+               /* do the magic to output the data */
+               printf ("%s (%s) at %i: ", name,
+                               (ds->ds->type == DS_TYPE_GAUGE) ? "GAUGE" : "COUNTER",
+                               (int)vl->time);
+
+               if (ds->ds->type == DS_TYPE_GAUGE)
+                       printf ("%f\n", vl->values[i].gauge);
+               else
+                       printf ("%lld\n", vl->values[i].counter);
+       }
+       return 0;
+} /* static int my_write (data_set_t *, value_list_t *) */
+
+/*
+ * This function is called when plugin_log () has been used.
+ */
+static void my_log (int severity, const char *msg, user_data_t *ud)
+{
+       printf ("LOG: %i - %s\n", severity, msg);
+       return;
+} /* static void my_log (int, const char *) */
+
+/*
+ * This function is called when plugin_dispatch_notification () has been used.
+ */
+static int my_notify (const notification_t *notif, user_data_t *ud)
+{
+       char time_str[32] = "";
+       struct tm *tm = NULL;
+
+       int n = 0;
+
+       if (NULL == (tm = localtime (&notif->time)))
+               time_str[0] = '\0';
+
+       n = strftime (time_str, 32, "%F %T", tm);
+       if (n >= 32) n = 31;
+       time_str[n] = '\0';
+
+       printf ("NOTIF (%s): %i - ", time_str, notif->severity);
+
+       if ('\0' != *notif->host)
+               printf ("%s: ", notif->host);
+
+       if ('\0' != *notif->plugin)
+               printf ("%s: ", notif->plugin);
+
+       if ('\0' != *notif->plugin_instance)
+               printf ("%s: ", notif->plugin_instance);
+
+       if ('\0' != *notif->type)
+               printf ("%s: ", notif->type);
+
+       if ('\0' != *notif->type_instance)
+               printf ("%s: ", notif->type_instance);
+
+       printf ("%s\n", notif->message);
+       return 0;
+} /* static int my_notify (notification_t *) */
+
+/*
+ * This function is called before shutting down collectd.
+ */
+static int my_shutdown (void)
+{
+       /* close sockets, free data structures, ... */
+       return 0;
+} /* static int my_shutdown (void) */
+
+/*
+ * This function is called after loading the plugin to register it with
+ * collectd.
+ */
+void module_register (void)
+{
+       plugin_register_log ("myplugin", my_log, /* user data */ NULL);
+       plugin_register_notification ("myplugin", my_notify,
+                       /* user data */ NULL);
+       plugin_register_data_set (&ds);
+       plugin_register_read ("myplugin", my_read);
+       plugin_register_init ("myplugin", my_init);
+       plugin_register_write ("myplugin", my_write, /* user data */ NULL);
+       plugin_register_shutdown ("myplugin", my_shutdown);
+    return;
+} /* void module_register (void) */
+
diff --git a/contrib/exec-ksm.sh b/contrib/exec-ksm.sh
new file mode 100755 (executable)
index 0000000..a21aa1d
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# collectd - contrib/exec-ksm.sh
+# Copyright (C) 2011  Florian Forster
+#
+# 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:
+#   Florian Forster <octo at collectd.org>
+
+HOSTNAME="${COLLECTD_HOSTNAME:-$(hostname -f)}"
+INTERVAL="${COLLECTD_INTERVAL:-60}"
+
+function read_file() {
+  local type="$1"
+  local type_instance="$2"
+  local file_name="/sys/kernel/mm/ksm/$3"
+  local ident="$HOSTNAME/exec-ksm/vmpage_number-${type_instance}"
+
+  echo "PUTVAL \"$ident\" interval=$INTERVAL N:$(< $file_name)"
+}
+
+if [[ 0 -eq $(< /sys/kernel/mm/ksm/run) ]]; then
+  echo "$0: KSM not active." >&2
+  exit 1
+fi
+
+while sleep "$INTERVAL"
+do
+  read_file vmpage_number    shared   pages_shared
+  read_file vmpage_number    saved    pages_sharing
+  read_file vmpage_number    unshared pages_unshared
+  read_file vmpage_number    volatile pages_volatile
+  read_file total_operations scan     full_scans
+done
+
+exit 0
diff --git a/contrib/exec-munin.conf b/contrib/exec-munin.conf
new file mode 100644 (file)
index 0000000..d7c31a4
--- /dev/null
@@ -0,0 +1,6 @@
+AddType temperature temperature
+
+Interval 300
+
+Script /tmp/ipmisens2
+Script /tmp/munin-sensors.pl
diff --git a/contrib/exec-munin.px b/contrib/exec-munin.px
new file mode 100755 (executable)
index 0000000..3e62ce0
--- /dev/null
@@ -0,0 +1,272 @@
+#!/usr/bin/perl
+
+#
+# collectd - contrib/exec-munin.px
+# Copyright (C) 2007,2008  Florian Forster
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#
+# Authors:
+#   Florian octo Forster <octo at verplant.org>
+#
+
+use strict;
+use warnings;
+
+=head1 NAME
+
+exec-munin.px
+
+=head1 DESCRIPTION
+
+This script allows you to use plugins that were written for Munin with
+collectd's C<exec-plugin>. Since the data models of Munin and collectd are
+quite different rewriting the plugins should be preferred over using this
+transition layer. Having more than one "data source" for one "data set" doesn't
+work with this script, for example.
+
+=cut
+
+use Sys::Hostname ('hostname');
+use File::Basename ('basename');
+use Config::General ('ParseConfig');
+use Regexp::Common ('number');
+
+our $ConfigFile = '/etc/exec-munin.conf';
+our $TypeMap = {};
+our $Scripts = [];
+our $Interval = defined ($ENV{'COLLECTD_INTERVAL'}) ? (0 + $ENV{'COLLECTD_INTERVAL'}) : 300;
+our $Hostname = defined ($ENV{'COLLECTD_HOSTNAME'}) ? $ENV{'COLLECTD_HOSTNAME'} : '';
+
+main ();
+exit (0);
+
+# Configuration {{{
+
+=head1 CONFIGURATION
+
+This script reads it's configuration from F</etc/exec-munin.conf>. The
+configuration is read using C<Config::General> which understands a Apache-like
+config syntax, so it's very similar to the F<collectd.conf> syntax, too.
+
+Here's a short sample config:
+
+  AddType voltage-in in
+  AddType voltage-out out
+  Interval 300
+  Script /usr/lib/munin/plugins/nut
+
+The options have the following semantic (i.E<nbsp>e. meaning):
+
+=over 4
+
+=item B<AddType> I<to> I<from> [I<from> ...]
+
+collectd uses B<types> to specify how data is structured. In Munin all data is
+structured the same way, so some way of telling collectd how to handle the data
+is needed. This option translates the so called "field names" of Munin to the
+"types" of collectd. If more than one field are of the same type, e.E<nbsp>g.
+the C<nut> plugin above provides C<in> and C<out> which are both voltages, you
+can use a hyphen to add a "type instance" to the type.
+
+For a list of already defined "types" look at the F<types.db> file in
+collectd's shared data directory, e.E<nbsp>g. F</usr/share/collectd/>.
+
+=item B<Interval> I<Seconds>
+
+Sets the interval in which the plugins are executed. This doesn't need to match
+the interval setting of the collectd daemon. Usually, you want to execute the
+Munin plugins much less often, e.E<nbsp>g. every 300 seconds versus every 10
+seconds.
+
+=item B<Script> I<File>
+
+Adds a script to the list of scripts to be executed once per I<Interval>
+seconds.
+
+=back
+
+=cut
+
+sub handle_config_addtype
+{
+  my $list = shift;
+
+  for (my $i = 0; $i < @$list; $i++)
+  {
+    my ($to, @from) = split (' ', $list->[$i]);
+    for (my $j = 0; $j < @from; $j++)
+    {
+      $TypeMap->{$from[$j]} = $to;
+    }
+  }
+} # handle_config_addtype
+
+sub handle_config_script
+{
+  my $scripts = shift;
+
+  for (my $i = 0; $i < @$scripts; $i++)
+  {
+    my $script = $scripts->[$i];
+    if (!-e $script)
+    {
+      print STDERR "Script `$script' doesn't exist.\n";
+    }
+    elsif (!-x $script)
+    {
+      print STDERR "Script `$script' exists but is not executable.\n";
+    }
+    else
+    {
+      push (@$Scripts, $script);
+    }
+  } # for $i
+} # handle_config_script
+
+sub handle_config
+{
+  my $config = shift;
+
+  if (defined ($config->{'addtype'}))
+  {
+    if (ref ($config->{'addtype'}) eq 'ARRAY')
+    {
+      handle_config_addtype ($config->{'addtype'});
+    }
+    elsif (ref ($config->{'addtype'}) eq '')
+    {
+      handle_config_addtype ([$config->{'addtype'}]);
+    }
+    else
+    {
+      print STDERR "Cannot handle ref type '"
+      . ref ($config->{'addtype'}) . "' for option 'AddType'.\n";
+    }
+  }
+
+  if (defined ($config->{'script'}))
+  {
+    if (ref ($config->{'script'}) eq 'ARRAY')
+    {
+      handle_config_script ($config->{'script'});
+    }
+    elsif (ref ($config->{'script'}) eq '')
+    {
+      handle_config_script ([$config->{'script'}]);
+    }
+    else
+    {
+      print STDERR "Cannot handle ref type '"
+      . ref ($config->{'script'}) . "' for option 'Script'.\n";
+    }
+  }
+
+  if (defined ($config->{'interval'})
+    && (ref ($config->{'interval'}) eq ''))
+  {
+    my $num = int ($config->{'interval'});
+    if ($num > 0)
+    {
+      $Interval = $num;
+    }
+  }
+} # handle_config }}}
+
+sub execute_script
+{
+  my $fh;
+  my $pinst;
+  my $time = time ();
+  my $script = shift;
+  my $host = $Hostname || hostname () || 'localhost';
+  if (!open ($fh, '-|', $script))
+  {
+    print STDERR "Cannot execute $script: $!";
+    return;
+  }
+
+  $pinst = basename ($script);
+
+  while (my $line = <$fh>)
+  {
+    chomp ($line);
+    if ($line =~ m#^([^\.\-/]+)\.value\s+($RE{num}{real})#)
+    {
+      my $field = $1;
+      my $value = $2;
+      my $type = (defined ($TypeMap->{$field})) ? $TypeMap->{$field} : $field;
+      my $ident = "$host/munin-$pinst/$type";
+
+      $ident =~ s/"/\\"/g;
+
+      print qq(PUTVAL "$ident" interval=$Interval $time:$value\n);
+    }
+  }
+
+  close ($fh);
+} # execute_script
+
+sub main
+{
+  my $last_run;
+  my $next_run;
+
+  my %config = ParseConfig (-ConfigFile => $ConfigFile,
+    -AutoTrue => 1,
+    -LowerCaseNames => 1);
+  handle_config (\%config);
+
+  while (42)
+  {
+    $last_run = time ();
+    $next_run = $last_run + $Interval;
+
+    for (@$Scripts)
+    {
+      execute_script ($_);
+    }
+
+    while ((my $timeleft = ($next_run - time ())) > 0)
+    {
+      sleep ($timeleft);
+    }
+  }
+} # main
+
+=head1 REQUIREMENTS
+
+This script requires the following Perl modules to be installed:
+
+=over 4
+
+=item C<Config::General>
+
+=item C<Regexp::Common>
+
+=back
+
+=head1 SEE ALSO
+
+L<http://munin.projects.linpro.no/>,
+L<http://collectd.org/>,
+L<collectd-exec(5)>
+
+=head1 AUTHOR
+
+Florian octo Forster E<lt>octo at verplant.orgE<gt>
+
+=cut
+
+# vim: set sw=2 sts=2 ts=8 fdm=marker :
diff --git a/contrib/exec-nagios.conf b/contrib/exec-nagios.conf
new file mode 100644 (file)
index 0000000..71644f7
--- /dev/null
@@ -0,0 +1,15 @@
+# Run `perldoc exec-nagios.px' for details on this config file.
+
+NRPEConfig /etc/nrpe.cfg
+
+Interval 300
+
+<Script /usr/lib/nagios/check_tcp>
+       Arguments -H alice -p 22
+       Type delay
+</Script>
+
+<Script /usr/lib/nagios/check_dns>
+       Arguments -H alice
+       Type delay
+</Script>
diff --git a/contrib/exec-nagios.px b/contrib/exec-nagios.px
new file mode 100755 (executable)
index 0000000..ec13b0a
--- /dev/null
@@ -0,0 +1,529 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+=head1 NAME
+
+exec-nagios.px
+
+=head1 DESCRIPTION
+
+This script allows you to use plugins that were written for Nagios with
+collectd's C<exec-plugin>. If the plugin checks some kind of threshold, please
+consider configuring the threshold using collectd's own facilities instead of
+using this transition layer.
+
+=cut
+
+use Sys::Hostname ('hostname');
+use File::Basename ('basename');
+use Config::General ('ParseConfig');
+use Regexp::Common ('number');
+
+our $ConfigFile = '/etc/exec-nagios.conf';
+our $TypeMap = {};
+our $NRPEMap = {};
+our $Scripts = [];
+our $Interval = defined ($ENV{'COLLECTD_INTERVAL'}) ? (0 + $ENV{'COLLECTD_INTERVAL'}) : 300;
+our $Hostname = defined ($ENV{'COLLECTD_HOSTNAME'}) ? $ENV{'COLLECTD_HOSTNAME'} : '';
+
+main ();
+exit (0);
+
+# Configuration
+# {{{
+
+=head1 CONFIGURATION
+
+This script reads it's configuration from F</etc/exec-nagios.conf>. The
+configuration is read using C<Config::General> which understands a Apache-like
+config syntax, so it's very similar to the F<collectd.conf> syntax, too.
+
+Here's a short sample config:
+
+  NRPEConfig "/etc/nrpe.cfg"
+  Interval 300
+  <Script /usr/lib/nagios/check_tcp>
+    Arguments -H alice -p 22
+    Type delay
+  </Script>
+  <Script /usr/lib/nagios/check_dns>
+    Arguments -H alice
+    Type delay
+  </Script>
+
+The options have the following semantic (i.E<nbsp>e. meaning):
+
+=over 4
+
+=item B<NRPEConfig> I<File>
+
+Read the NRPE config and add the command definitions to an alias table. After
+reading the file you can use the NRPE command name rather than the script's
+filename within B<Script> blocks (see below). If both, the NRPE config and the
+B<Script> block, define arguments they will be merged by concatenating the
+arguments together in the order "NRPE-args Script-args".
+
+Please note that this option is rather dumb. It does not support "command
+argument processing" (i.e. replacing C<$ARG1$> and friends), inclusion of other
+NRPE config files, include directories etc.
+
+=item B<Interval> I<Seconds>
+
+Sets the interval in which the plugins are executed. This doesn't need to match
+the interval setting of the collectd daemon. Usually, you want to execute the
+Nagios plugins much less often, e.E<nbsp>g. every 300 seconds versus every 10
+seconds.
+
+=item E<lt>B<Script> I<File>E<gt>
+
+Adds a script to the list of scripts to be executed once per I<Interval>
+seconds. If the B<NRPEConfig> is given above the B<Script> block, you may use
+the NRPE command name rather than the script's filename. You can use the
+following optional arguments to specify the operation further:
+
+=over 4
+
+=item B<Arguments> I<Arguments>
+
+Pass the arguments I<Arguments> to the script. This is often needed with Nagios
+plugins, because much of the logic is implemented in the plugins, not in the
+daemon. If you need to specify a warning and/or critical range here, please
+consider using collectd's own threshold mechanism, which is by far the more
+elegant solution than this transition layer.
+
+=item B<Type> I<Type>
+
+If the plugin provides "performance data" the performance data is dispatched to
+collectd with this type. If no type is configured the data is ignored. Please
+note that this is limited to types that take exactly one value, such as the
+type C<delay> in the example above. If you need more complex performance data,
+rewrite the plugin as a collectd plugin (or at least port it do run directly
+with the C<exec-plugin>).
+
+=back
+
+=back
+
+=cut
+
+sub parse_nrpe_conf
+{
+  my $file = shift;
+  my $fh;
+  my $status;
+
+  $status = open ($fh, '<', $file);
+  if (!$status)
+  {
+    print STDERR "Reading NRPE config from \"$file\" failed: $!\n";
+    return;
+  }
+
+  while (<$fh>)
+  {
+    my $line = $_;
+    chomp ($line);
+
+    if ($line =~ m/^\s*command\[([^\]]+)\]\s*=\s*(.+)$/)
+    {
+      my $alias = $1;
+      my $script;
+      my $arguments;
+
+      ($script, $arguments) = split (' ', $2, 2);
+
+      if ($NRPEMap->{$alias})
+      {
+        print STDERR "Warning: NRPE command \"$alias\" redefined.\n";
+      }
+
+      $NRPEMap->{$alias} = { script => $script };
+      if ($arguments)
+      {
+        $NRPEMap->{$alias}{'arguments'} = $arguments;
+      }
+    }
+  } # while (<$fh>)
+
+  close ($fh);
+} # parse_nrpe_conf
+
+sub handle_config_addtype
+{
+  my $list = shift;
+
+  for (my $i = 0; $i < @$list; $i++)
+  {
+    my ($to, @from) = split (' ', $list->[$i]);
+    for (my $j = 0; $j < @from; $j++)
+    {
+      $TypeMap->{$from[$j]} = $to;
+    }
+  }
+} # handle_config_addtype
+
+# Update the script record. This function adds the name of the script /
+# executable to the hash and merges the configured and NRPE arguments if
+# required.
+sub update_script_opts
+{
+  my $opts = shift;
+  my $script = shift;
+  my $nrpe_args = shift;
+
+  $opts->{'script'} = $script;
+
+  if ($nrpe_args)
+  {
+    if ($opts->{'arguments'})
+    {
+      $opts->{'arguments'} = $nrpe_args . ' ' . $opts->{'arguments'};
+    }
+    else
+    {
+      $opts->{'arguments'} = $nrpe_args;
+    }
+  }
+} # update_script_opts
+
+sub handle_config_script
+{
+  my $scripts = shift;
+
+  for (keys %$scripts)
+  {
+    my $script = $_;
+    my $opts = $scripts->{$script};
+
+    my $nrpe_args = '';
+
+    # Check if the script exists in the NRPE map. If so, replace the alias name
+    # with the actual script name.
+    if ($NRPEMap->{$script})
+    {
+      if ($NRPEMap->{$script}{'arguments'})
+      {
+        $nrpe_args = $NRPEMap->{$script}{'arguments'};
+      }
+      $script = $NRPEMap->{$script}{'script'};
+    }
+
+    # Check if the script exists and is executable.
+    if (!-e $script)
+    {
+      print STDERR "Script `$script' doesn't exist.\n";
+    }
+    elsif (!-x $script)
+    {
+      print STDERR "Script `$script' exists but is not executable.\n";
+    }
+    else
+    {
+      # Add the script to the global @$Script array.
+      if (ref ($opts) eq 'ARRAY')
+      {
+        for (@$opts)
+        {
+          my $opt = $_;
+          update_script_opts ($opt, $script, $nrpe_args);
+          push (@$Scripts, $opt);
+        }
+      }
+      else
+      {
+        update_script_opts ($opts, $script, $nrpe_args);
+        push (@$Scripts, $opts);
+      }
+    }
+  } # for (keys %$scripts)
+} # handle_config_script
+
+sub handle_config
+{
+  my $config = shift;
+
+  if (defined ($config->{'nrpeconfig'}))
+  {
+    if (ref ($config->{'nrpeconfig'}) eq 'ARRAY')
+    {
+      for (@{$config->{'nrpeconfig'}})
+      {
+        parse_nrpe_conf ($_);
+      }
+    }
+    elsif (ref ($config->{'nrpeconfig'}) eq '')
+    {
+      parse_nrpe_conf ($config->{'nrpeconfig'});
+    }
+    else
+    {
+      print STDERR "Cannot handle ref type '"
+      . ref ($config->{'nrpeconfig'}) . "' for option 'NRPEConfig'.\n";
+    }
+  }
+
+  if (defined ($config->{'addtype'}))
+  {
+    if (ref ($config->{'addtype'}) eq 'ARRAY')
+    {
+      handle_config_addtype ($config->{'addtype'});
+    }
+    elsif (ref ($config->{'addtype'}) eq '')
+    {
+      handle_config_addtype ([$config->{'addtype'}]);
+    }
+    else
+    {
+      print STDERR "Cannot handle ref type '"
+      . ref ($config->{'addtype'}) . "' for option 'AddType'.\n";
+    }
+  }
+
+  if (defined ($config->{'script'}))
+  {
+    if (ref ($config->{'script'}) eq 'HASH')
+    {
+      handle_config_script ($config->{'script'});
+    }
+    else
+    {
+      print STDERR "Cannot handle ref type '"
+      . ref ($config->{'script'}) . "' for option 'Script'.\n";
+    }
+  }
+
+  if (defined ($config->{'interval'})
+    && (ref ($config->{'interval'}) eq ''))
+  {
+    my $num = int ($config->{'interval'});
+    if ($num > 0)
+    {
+      $Interval = $num;
+    }
+  }
+} # handle_config }}}
+
+sub scale_value
+{
+  my $value = shift;
+  my $unit = shift;
+
+  if (!$unit)
+  {
+    return ($value);
+  }
+
+  if (($unit =~ m/^mb(yte)?$/i) || ($unit eq 'M'))
+  {
+    return ($value * 1000000);
+  }
+  elsif ($unit =~ m/^k(b(yte)?)?$/i)
+  {
+    return ($value * 1000);
+  }
+
+  return ($value);
+}
+
+sub sanitize_instance
+{
+  my $inst = shift;
+
+  if ($inst eq '/')
+  {
+    return ('root');
+  }
+
+  $inst =~ s/[^A-Za-z_-]/_/g;
+  $inst =~ s/__+/_/g;
+  $inst =~ s/^_//;
+  $inst =~ s/_$//;
+
+  return ($inst);
+}
+
+sub handle_performance_data
+{
+  my $host = shift;
+  my $plugin = shift;
+  my $pinst = shift;
+  my $type = shift;
+  my $time = shift;
+  my $line = shift;
+  my $ident = "$host/$plugin-$pinst/$type-$tinst";
+
+  my $tinst;
+  my $value;
+  my $unit;
+
+  if ($line =~ m/^([^=]+)=($RE{num}{real})([^;]*)/)
+  {
+    $tinst = sanitize_instance ($1);
+    $value = scale_value ($2, $3);
+  }
+  else
+  {
+    return;
+  }
+
+  $ident =~ s/"/\\"/g;
+
+  print qq(PUTVAL "$ident" interval=$Interval ${time}:$value\n);
+}
+
+sub execute_script
+{
+  my $fh;
+  my $pinst;
+  my $time = time ();
+  my $script = shift;
+  my @args = ();
+  my $host = $Hostname || hostname () || 'localhost';
+
+  my $state = 0;
+  my $serviceoutput;
+  my @serviceperfdata;
+  my @longserviceoutput;
+
+  my $script_name = $script->{'script'};
+  
+  if ($script->{'arguments'})
+  {
+    @args = split (' ', $script->{'arguments'});
+  }
+
+  if (!open ($fh, '-|', $script_name, @args))
+  {
+    print STDERR "Cannot execute $script_name: $!";
+    return;
+  }
+
+  $pinst = sanitize_instance (basename ($script_name));
+
+  # Parse the output of the plugin. The format is seriously fucked up, because
+  # it got extended way beyond what it could handle.
+  while (my $line = <$fh>)
+  {
+    chomp ($line);
+
+    if ($state == 0)
+    {
+      my $perfdata;
+      ($serviceoutput, $perfdata) = split (m/\s*\|\s*/, $line, 2);
+      
+      if ($perfdata)
+      {
+        push (@serviceperfdata, split (' ', $perfdata));
+      }
+
+      $state = 1;
+    }
+    elsif ($state == 1)
+    {
+      my $longoutput;
+      my $perfdata;
+      ($longoutput, $perfdata) = split (m/\s*\|\s*/, $line, 2);
+
+      push (@longserviceoutput, $longoutput);
+
+      if ($perfdata)
+      {
+        push (@serviceperfdata, split (' ', $perfdata));
+        $state = 2;
+      }
+    }
+    else # ($state == 2)
+    {
+      push (@serviceperfdata, split (' ', $line));
+    }
+  }
+
+  close ($fh);
+  # Save the exit status of the check in $state
+  $state = $? >> 8;
+
+  if ($state == 0)
+  {
+    $state = 'okay';
+  }
+  elsif ($state == 1)
+  {
+    $state = 'warning';
+  }
+  else
+  {
+    $state = 'failure';
+  }
+
+  {
+    my $type = $script->{'type'} || 'nagios_check';
+
+    print "PUTNOTIF time=$time severity=$state host=$host plugin=nagios "
+    . "plugin_instance=$pinst type=$type message=$serviceoutput\n";
+  }
+
+  if ($script->{'type'})
+  {
+    for (@serviceperfdata)
+    {
+      handle_performance_data ($host, 'nagios', $pinst, $script->{'type'},
+        $time, $_);
+    }
+  }
+} # execute_script
+
+sub main
+{
+  my $last_run;
+  my $next_run;
+
+  my %config = ParseConfig (-ConfigFile => $ConfigFile,
+    -AutoTrue => 1,
+    -LowerCaseNames => 1);
+  handle_config (\%config);
+
+  while (42)
+  {
+    $last_run = time ();
+    $next_run = $last_run + $Interval;
+
+    for (@$Scripts)
+    {
+      execute_script ($_);
+    }
+
+    while ((my $timeleft = ($next_run - time ())) > 0)
+    {
+      sleep ($timeleft);
+    }
+  }
+} # main
+
+=head1 REQUIREMENTS
+
+This script requires the following Perl modules to be installed:
+
+=over 4
+
+=item C<Config::General>
+
+=item C<Regexp::Common>
+
+=back
+
+=head1 SEE ALSO
+
+L<http://www.nagios.org/>,
+L<http://nagiosplugins.org/>,
+L<http://collectd.org/>,
+L<collectd-exec(5)>
+
+=head1 AUTHOR
+
+Florian octo Forster E<lt>octo at verplant.orgE<gt>
+
+=cut
+
+# vim: set sw=2 sts=2 ts=8 fdm=marker :
diff --git a/contrib/exec-smartctl b/contrib/exec-smartctl
new file mode 100755 (executable)
index 0000000..99b6986
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Sample script for the exec plugin (collectd-exec(5))
+#
+# This script uses smartctl(8) to read HDD temperatures. The drives are
+# attached to a 3ware RAID controller which hddtempd can't handle.
+# Unfortunately the smartmontools don't have a library so we can't write a
+# C-plugin, at least not easily.
+# Please note that only root can read the SMART attributes from harddrives,
+# because special ``capabilities'' are necessary. However, the exec plugin will
+# refuse to run scripts as root, which is why `sudo' is used here for
+# fine-grained root privileges for the user `smart'. This isn't as straigt
+# forward as one might hope, but we think that the gained security is worth it.
+
+# The sudo configuration looks something like this:
+# -- 8< --
+# Cmnd_Alias      SMARTCTL = /usr/sbin/smartctl -d 3ware\,0 -A /dev/twe0, /usr/sbin/smartctl -d 3ware\,1 -A /dev/twe0, /usr/sbin/smartctl -d ata -A /dev/sda
+# smart   ALL = (root) NOPASSWD: SMARTCTL
+# -- >8 --
+
+HOSTNAME="${COLLECTD_HOSTNAME:-`hostname -f`}"
+INTERVAL="${COLLECTD_INTERVAL:-60}"
+
+while sleep "$INTERVAL"
+do
+       TEMP=$((sudo smartctl -d 3ware,0 -A /dev/twe0 | grep Temperature_Celsius | awk '{ print $10; }') 2>/dev/null);
+       if [ $? -ne 0 ]
+       then
+               TEMP="U"
+       fi
+       echo "PUTVAL $HOSTNAME/exec-smart/temperature-3ware_0 interval=$INTERVAL N:$TEMP"
+
+       TEMP=$((sudo smartctl -d 3ware,1 -A /dev/twe0 | grep Temperature_Celsius | awk '{ print $10; }') 2>/dev/null);
+       if [ $? -ne 0 ]
+       then
+               TEMP="U"
+       fi
+       echo "PUTVAL $HOSTNAME/exec-smart/temperature-3ware_1 interval=$INTERVAL N:$TEMP"
+
+       TEMP=$((sudo smartctl -d ata -A /dev/sda | grep Temperature_Celsius | awk '{ print $10; }') 2>/dev/null);
+       if [ $? -ne 0 ]
+       then
+               TEMP="U"
+       fi
+       echo "PUTVAL $HOSTNAME/exec-smart/temperature-sata_0 interval=$INTERVAL N:$TEMP"
+done
diff --git a/contrib/fedora/collectd.spec b/contrib/fedora/collectd.spec
new file mode 100644 (file)
index 0000000..a35923c
--- /dev/null
@@ -0,0 +1,376 @@
+Summary:       Statistics collection daemon for filling RRD files.
+Name:           collectd
+Version:       4.2.0
+Release:       1.fc6
+Source:                http://collectd.org/files/%{name}-%{version}.tar.gz
+License:       GPL
+Group:         System Environment/Daemons
+BuildRoot:     %{_tmppath}/%{name}-%{version}-root
+BuildPrereq:   lm_sensors-devel
+BuildPrereq:   mysql-devel
+BuildPrereq:   rrdtool-devel
+BuildPrereq:   net-snmp-devel
+Requires:      rrdtool
+Requires:      perl-Regexp-Common
+Packager:      Florian octo Forster <octo@verplant.org>
+Vendor:                Florian octo Forster <octo@verplant.org>
+
+%description
+collectd is a small daemon written in C for performance.  It reads various
+system  statistics  and updates  RRD files,  creating  them if neccessary.
+Since the daemon doesn't need to startup every time it wants to update the
+files it's very fast and easy on the system. Also, the statistics are very
+fine grained since the files are updated every 10 seconds.
+
+%package apache
+Summary:       apache-plugin for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, curl
+%description apache
+This plugin collectd data provided by Apache's `mod_status'.
+
+%package email
+Summary:       email-plugin for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, spamassassin
+%description email
+This plugin collectd data provided by spamassassin.
+
+%package mysql
+Summary:       mysql-module for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, mysql
+%description mysql
+MySQL  querying  plugin.  This plugins  provides data of  issued commands,
+called handlers and database traffic.
+
+%package sensors
+Summary:       libsensors-module for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, lm_sensors
+%description sensors
+This  plugin  for  collectd  provides  querying  of sensors  supported  by
+lm_sensors.
+
+%prep
+rm -rf $RPM_BUILD_ROOT
+%setup
+
+%build
+./configure --prefix=%{_prefix} --sbindir=%{_sbindir} --mandir=%{_mandir} --libdir=%{_libdir} --sysconfdir=%{_sysconfdir}
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+mkdir -p $RPM_BUILD_ROOT/var/www/cgi-bin
+cp src/collectd.conf $RPM_BUILD_ROOT/etc/collectd.conf
+cp contrib/fedora/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
+cp contrib/collection.cgi $RPM_BUILD_ROOT/var/www/cgi-bin
+cp contrib/collection.conf $RPM_BUILD_ROOT/etc/collection.conf
+mkdir -p $RPM_BUILD_ROOT/var/lib/collectd
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+/sbin/chkconfig --add collectd
+/sbin/chkconfig collectd on
+
+%preun
+if [ "$1" = 0 ]; then
+   /sbin/chkconfig collectd off
+   /etc/init.d/collectd stop
+   /sbin/chkconfig --del collectd
+fi
+exit 0
+
+%postun
+if [ "$1" -ge 1 ]; then
+    /etc/init.d/collectd restart
+fi
+exit 0
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
+%attr(0644,root,root) %config(noreplace) /etc/collectd.conf
+%attr(0644,root,root) %config(noreplace) /etc/collection.conf
+%attr(0755,root,root) /etc/rc.d/init.d/collectd
+%attr(0755,root,root) /var/www/cgi-bin/collection.cgi
+%attr(0755,root,root) %{_sbindir}/collectd
+%attr(0755,root,root) %{_bindir}/collectd-nagios
+%attr(0644,root,root) %{_mandir}/man1/*
+%attr(0644,root,root) %{_mandir}/man5/*
+
+%attr(0644,root,root) /usr/lib/perl5/5.8.8/i386-linux-thread-multi/perllocal.pod
+%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd.pm
+%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd/Unixsock.pm
+%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi/auto/Collectd/.packlist
+%attr(0644,root,root) %{_mandir}/man3/Collectd::Unixsock.3pm.gz
+
+%attr(0644,root,root) %{_libdir}/%{name}/apcups.so*
+%attr(0644,root,root) %{_libdir}/%{name}/apcups.la
+
+# FIXME!!!
+#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.so*
+#%attr(0644,root,root) %{_libdir}/%{name}/apple_sensors.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/battery.so*
+%attr(0644,root,root) %{_libdir}/%{name}/battery.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/conntrack.so*
+%attr(0644,root,root) %{_libdir}/%{name}/conntrack.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.so*
+%attr(0644,root,root) %{_libdir}/%{name}/cpufreq.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/cpu.so*
+%attr(0644,root,root) %{_libdir}/%{name}/cpu.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/csv.so*
+%attr(0644,root,root) %{_libdir}/%{name}/csv.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/df.so*
+%attr(0644,root,root) %{_libdir}/%{name}/df.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/disk.so*
+%attr(0644,root,root) %{_libdir}/%{name}/disk.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/dns.so*
+%attr(0644,root,root) %{_libdir}/%{name}/dns.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/entropy.so*
+%attr(0644,root,root) %{_libdir}/%{name}/entropy.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/exec.so*
+%attr(0644,root,root) %{_libdir}/%{name}/exec.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.so*
+%attr(0644,root,root) %{_libdir}/%{name}/hddtemp.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/interface.so*
+%attr(0644,root,root) %{_libdir}/%{name}/interface.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/iptables.so*
+%attr(0644,root,root) %{_libdir}/%{name}/iptables.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/irq.so*
+%attr(0644,root,root) %{_libdir}/%{name}/irq.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/load.so*
+%attr(0644,root,root) %{_libdir}/%{name}/load.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/logfile.so*
+%attr(0644,root,root) %{_libdir}/%{name}/logfile.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/mbmon.so*
+%attr(0644,root,root) %{_libdir}/%{name}/mbmon.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/memcached.so*
+%attr(0644,root,root) %{_libdir}/%{name}/memcached.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/memory.so*
+%attr(0644,root,root) %{_libdir}/%{name}/memory.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/multimeter.so*
+%attr(0644,root,root) %{_libdir}/%{name}/multimeter.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/network.so*
+%attr(0644,root,root) %{_libdir}/%{name}/network.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/nfs.so*
+%attr(0644,root,root) %{_libdir}/%{name}/nfs.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/nginx.so*
+%attr(0644,root,root) %{_libdir}/%{name}/nginx.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/ntpd.so*
+%attr(0644,root,root) %{_libdir}/%{name}/ntpd.la
+
+# FIXME!!!
+#%attr(0644,root,root) %{_libdir}/%{name}/nut.so*
+#%attr(0644,root,root) %{_libdir}/%{name}/nut.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/perl.so*
+%attr(0644,root,root) %{_libdir}/%{name}/perl.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/ping.so*
+%attr(0644,root,root) %{_libdir}/%{name}/ping.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/processes.so*
+%attr(0644,root,root) %{_libdir}/%{name}/processes.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.so*
+%attr(0644,root,root) %{_libdir}/%{name}/rrdtool.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/serial.so*
+%attr(0644,root,root) %{_libdir}/%{name}/serial.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/swap.so*
+%attr(0644,root,root) %{_libdir}/%{name}/swap.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/snmp.so*
+%attr(0644,root,root) %{_libdir}/%{name}/snmp.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/syslog.so*
+%attr(0644,root,root) %{_libdir}/%{name}/syslog.la
+
+# FIXME!!!
+#%attr(0644,root,root) %{_libdir}/%{name}/tape.so*
+#%attr(0644,root,root) %{_libdir}/%{name}/tape.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.so*
+%attr(0644,root,root) %{_libdir}/%{name}/tcpconns.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/unixsock.so*
+%attr(0644,root,root) %{_libdir}/%{name}/unixsock.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/users.so*
+%attr(0644,root,root) %{_libdir}/%{name}/users.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/vserver.so*
+%attr(0644,root,root) %{_libdir}/%{name}/vserver.la
+
+%attr(0644,root,root) %{_libdir}/%{name}/wireless.so*
+%attr(0644,root,root) %{_libdir}/%{name}/wireless.la
+
+%attr(0644,root,root) %{_datadir}/%{name}/types.db
+
+%dir /var/lib/collectd
+
+%files apache
+%attr(0644,root,root) %{_libdir}/%{name}/apache.so*
+%attr(0644,root,root) %{_libdir}/%{name}/apache.la
+
+%files email
+%attr(0644,root,root) %{_libdir}/%{name}/email.so*
+%attr(0644,root,root) %{_libdir}/%{name}/email.la
+
+%files mysql
+%attr(0644,root,root) %{_libdir}/%{name}/mysql.so*
+%attr(0644,root,root) %{_libdir}/%{name}/mysql.la
+
+%files sensors
+%attr(0644,root,root) %{_libdir}/%{name}/sensors.so*
+%attr(0644,root,root) %{_libdir}/%{name}/sensors.la
+
+%changelog
+* Wed Oct 31 2007 Iain Lea <iain@bricbrac.de> 4.2.0
+- New major release
+- Changes to support 4.2.0 (ie. contrib/collection.conf)
+
+* Mon Aug 06 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.6
+- New upstream version
+
+* Wed Jul 25 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.5
+- New major release
+- Changes to support 4.0.5 
+
+* Wed Jan 11 2007 Iain Lea <iain@bricbrac.de> 3.11.0-0
+- fixed spec file to build correctly on fedora core
+- added improved init.d script to work with chkconfig
+- added %post and %postun to call chkconfig automatically
+
+* Sun Jul 09 2006 Florian octo Forster <octo@verplant.org> 3.10.0-1
+- New upstream version
+
+* Tue Jun 25 2006 Florian octo Forster <octo@verplant.org> 3.9.4-1
+- New upstream version
+
+* Tue Jun 01 2006 Florian octo Forster <octo@verplant.org> 3.9.3-1
+- New upstream version
+
+* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.9.2-1
+- New upstream version
+
+* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.8.5-1
+- New upstream version
+
+* Fri Apr 21 2006 Florian octo Forster <octo@verplant.org> 3.9.1-1
+- New upstream version
+
+* Fri Apr 14 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
+- New upstream version
+- Added the `apache' package.
+
+* Thu Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
+- New upstream version
+
+* Thu Mar 13 2006 Florian octo Forster <octo@verplant.org> 3.8.1-1
+- New upstream version
+
+* Thu Mar 09 2006 Florian octo Forster <octo@verplant.org> 3.8.0-1
+- New upstream version
+
+* Sat Feb 18 2006 Florian octo Forster <octo@verplant.org> 3.7.2-1
+- Include `tape.so' so the build doesn't terminate because of missing files..
+- New upstream version
+
+* Sat Feb 04 2006 Florian octo Forster <octo@verplant.org> 3.7.1-1
+- New upstream version
+
+* Mon Jan 30 2006 Florian octo Forster <octo@verplant.org> 3.7.0-1
+- New upstream version
+- Removed the extra `hddtemp' package
+
+* Tue Jan 24 2006 Florian octo Forster <octo@verplant.org> 3.6.2-1
+- New upstream version
+
+* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.1-1
+- New upstream version
+
+* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.0-1
+- New upstream version
+- Added config file, `collectd.conf(5)', `df.so'
+- Added package `collectd-mysql', dependency on `mysqlclient10 | mysql'
+
+* Wed Dec 07 2005 Florian octo Forster <octo@verplant.org> 3.5.0-1
+- New upstream version
+
+* Sat Nov 26 2005 Florian octo Forster <octo@verplant.org> 3.4.0-1
+- New upstream version
+
+* Sat Nov 05 2005 Florian octo Forster <octo@verplant.org> 3.3.0-1
+- New upstream version
+
+* Tue Oct 26 2005 Florian octo Forster <octo@verplant.org> 3.2.0-1
+- New upstream version
+- Added statement to remove the `*.la' files. This fixes a problem when
+  `Unpackaged files terminate build' is in effect.
+- Added `processes.so*' to the main package
+
+* Fri Oct 14 2005 Florian octo Forster <octo@verplant.org> 3.1.0-1
+- New upstream version
+- Added package `collectd-hddtemp'
+
+* Fri Sep 30 2005 Florian octo Forster <octo@verplant.org> 3.0.0-1
+- New upstream version
+- Split the package into `collectd' and `collectd-sensors'
+
+* Fri Sep 16 2005 Florian octo Forster <octo@verplant.org> 2.1.0-1
+- New upstream version
+
+* Mon Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
+- New upstream version
+
+* Mon Aug 29 2005 Florian octo Forster <octo@verplant.org> 1.8.0-1
+- New upstream version
+
+* Sun Aug 25 2005 Florian octo Forster <octo@verplant.org> 1.7.0-1
+- New upstream version
+
+* Sun Aug 21 2005 Florian octo Forster <octo@verplant.org> 1.6.0-1
+- New upstream version
+
+* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5.1-1
+- New upstream version
+
+* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5-1
+- New upstream version
+
+* Mon Jul 11 2005 Florian octo Forster <octo@verplant.org> 1.4.2-1
+- New upstream version
+
+* Sat Jul 09 2005 Florian octo Forster <octo@verplant.org> 1.4-1
+- Built on RedHat 7.3
diff --git a/contrib/fedora/init.d-collectd b/contrib/fedora/init.d-collectd
new file mode 100644 (file)
index 0000000..ea8662a
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/bash
+#
+# collectd    Startup script for the Collectd statistics gathering daemon
+# chkconfig: - 86 15
+# description: Collectd is a statistics gathering daemon used to collect \
+#   system information ie. cpu, memory, disk, network
+# processname: collectd
+# config: /etc/collectd.conf
+# config: /etc/sysconfig/collectd
+# pidfile: /var/run/collectd.pid
+
+# Source function library.
+. /etc/init.d/functions
+
+RETVAL=0
+ARGS=""
+prog="collectd"
+CONFIG=/etc/collectd.conf
+
+if [ -r /etc/default/$prog ]; then
+       . /etc/default/$prog
+fi
+
+start () {
+       echo -n $"Starting $prog: "
+       if [ -r "$CONFIG" ]
+       then
+               daemon /usr/sbin/collectd -C "$CONFIG"
+               RETVAL=$?
+               echo
+               [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
+       fi
+}
+stop () {
+       echo -n $"Stopping $prog: "
+       killproc $prog
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
+}
+# See how we were called.
+case "$1" in
+  start)
+       start
+       ;;
+  stop)
+       stop
+       ;;
+  status)
+       status $prog
+       ;;
+  restart|reload)
+       stop
+       start
+       ;;
+  condrestart)
+       [ -f /var/lock/subsys/$prog ] && stop && start || :
+       ;;
+  *)
+       echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
+       exit 1
+esac
+
+exit $?
+
+# vim:syntax=sh
diff --git a/contrib/iptables/accounting.sh b/contrib/iptables/accounting.sh
new file mode 100755 (executable)
index 0000000..a9a3be9
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/bash
+#Simple script that sets up some chains in mangle table to do global logging of all 
+#traffic going in and out of an interface
+#Could also use the regular input/output tree but this also catches the forwarded nat traffic
+
+IT="iptables -t mangle"
+
+#First clear the old stuff
+$IT -F incoming
+$IT -F outgoing
+$IT -N incoming
+$IT -N outgoing
+
+$IT -D PREROUTING -i eth0 -j incoming
+$IT -D POSTROUTING -o eth0 -j outgoing
+
+#should add some arg == stop exit here...
+
+$IT -A PREROUTING -i eth0 -j incoming
+$IT -A POSTROUTING -o eth0 -j outgoing
+
+$IT -A incoming -p tcp -m comment --comment "tcp"
+$IT -A incoming -p udp -m comment --comment "udp"
+$IT -A incoming -p icmp -m comment --comment "icmp"
+
+$IT -A outgoing -p tcp -m comment --comment "tcp"
+$IT -A outgoing -p udp -m comment --comment "udp"
+$IT -A outgoing -p icmp -m comment --comment "icmp"
+
diff --git a/contrib/migrate-3-4.px b/contrib/migrate-3-4.px
new file mode 100755 (executable)
index 0000000..ed19a7b
--- /dev/null
@@ -0,0 +1,387 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Getopt::Long ('GetOptions');
+use Data::Dumper ();
+use File::Basename ('dirname');
+
+our $InDir = '/var/lib/collectd';
+our $OutDir = '/tmp/collectd-4';
+our $Hostname = 'localhost';
+
+# Types:
+# +------------+----------------------+----+----+----+
+# ! Subdir     ! Type                 ! ti ! pi ! ex !
+# +------------+----------------------+----+----+----+
+# ! apache     ! apache_bytes         !    !    !    !
+# ! apache     ! apache_requests      !    !    !    !
+# ! apache     ! apache_scoreboard    ! x  !    !    !
+# ! battery    ! charge               !    ! x  !    !
+# ! apcups     ! charge_percent       !    !    !    !
+# !            ! cpu                  ! x  !    ! x  !
+# !            ! cpufreq              ! x  !    !    !
+# ! battery    ! current              !    ! x  !    !
+# ! ntpd       ! delay                ! x  !    !    !
+# !            ! df                   ! x  !    !    !
+# !            ! disk                 ! x  !    !    !
+# ! dns        ! dns_traffic          !    !    !    !
+# ! apple_se.. ! fanspeed             ! x  !    !    !
+# ! mbmon      ! fanspeed             ! x  !    !    !
+# ! apcups     ! frequency            ! x  !    !    !
+# ! ntpd       ! frequency_offset     ! x  !    !    !
+# !            ! hddtemp              ! x  !    !    !
+# ! interface  ! if_errors            !    ! x  !    !
+# ! interface  ! if_packets           !    ! x  !    !
+# !            ! lm_sensors           !    !    !    !
+# !            ! load                 !    !    !    !
+# ! apcups     ! load_percent         !    !    !    !
+# !            ! memory               !    !    !    !
+# !            ! multimeter           !    !    !    !
+# ! mysql      ! mysql_commands       ! x  !    !    !
+# ! mysql      ! mysql_handler        ! x  !    !    !
+# ! mysql      ! mysql_qcache         !    !    !    !
+# ! mysql      ! mysql_threads        !    !    !    !
+# !            ! nfs2_procedures      ! x  !    ! x  !
+# !            ! nfs3_procedures      ! x  !    ! x  !
+# ! dns        ! opcode               ! x  !    !    !
+# !            ! partition            ! x  !    !    !
+# !            ! ping                 ! x  !    !    !
+# !            ! processes            !    !    !    !
+# ! processes  ! ps_count             ! x  !    !    !
+# ! processes  ! ps_cputime           ! x  !    !    !
+# ! processes  ! ps_pagefaults        ! x  !    !    !
+# ! processes  ! ps_rss               ! x  !    !    !
+# ! dns        ! qtype                ! x  !    !    !
+# ! dns        ! rcode                ! x  !    !    !
+# ! (*)        ! sensors              ! x  !    !    !
+# !            ! serial               ! x  !    !    !
+# !            ! swap                 !    !    !    !
+# !            ! tape                 ! x  !    !    !
+# ! apple_se.. ! temperature          ! x  !    !    !
+# ! mbmon      ! temperature          ! x  !    !    !
+# ! ntpd       ! time_dispersion      ! x  !    !    !
+# ! ntpd       ! time_offset          ! x  !    !    !
+# ! apcups     ! timeleft             !    !    !    !
+# !            ! traffic              ! x  !    !    ! ->rx,tx
+# ! vserver    ! traffic              ! x  ! x  !    ! ->rx.tx
+# !            ! users                !    !    !    !
+# ! apucups    ! voltage              ! x  !    !    !
+# ! battery    ! voltage              !    ! x  !    !
+# ! mbmon      ! voltage              ! x  !    !    !
+# ! vserver    ! vs_memory            !    ! x  !    !
+# ! vserver    ! vs_processes         !    ! x  !    !
+# ! vserver    ! vs_threads           !    ! x  !    !
+# !            ! wireless             ! x  !    !    !
+# +------------+----------------------+----+----+----+
+
+our %Subdirs =
+(
+       apache => 0,
+       apcups => 0,
+       apple_sensors => 0,
+       battery => 1,
+       dns => 0,
+       interface => 1,
+       mbmon => 0,
+       mysql => 0,
+       ntpd => 0,
+       processes => 0,
+       sensors => 1,
+       vserver => 1
+);
+
+our %TypeTranslate =
+(
+       cpu => sub { $_ = shift; $_->{'plugin_instance'} = $_->{'type_instance'}; $_->{'type_instance'} = undef; $_; },
+       hddtemp => sub { $_ = shift; $_->{'plugin'} = 'hddtemp'; $_->{'type'} = 'temperature'; $_->{'type_instance'} = $_->{'type_instance'}; $_; },
+       if_errors => sub { $_ = shift; $_->{'type_instance'} = $_->{'plugin_instance'}; $_->{'plugin_instance'} = undef; $_; },
+       if_packets => sub { $_ = shift; $_->{'type_instance'} = $_->{'plugin_instance'}; $_->{'plugin_instance'} = undef; $_; },
+       nfs2_procedures => sub { $_ = shift; @$_{qw(plugin plugin_instance type type_instance)} = ('nfs', 'v2' . $_->{'type_instance'}, 'nfs_procedure', undef); $_; },
+       nfs3_procedures => sub { $_ = shift; @$_{qw(plugin plugin_instance type type_instance)} = ('nfs', 'v3' . $_->{'type_instance'}, 'nfs_procedure', undef); $_; },
+       partition => sub { $_ = shift; $_->{'plugin'} = 'disk'; $_; },
+       processes => sub { $_ = shift; $_->{'type'} = 'ps_state'; $_; },
+       traffic => sub { $_ = shift; $_->{'plugin'} =~ s/^traffic$/interface/; @$_{qw(plugin_instance type)} = (undef, 'if_octets'); $_; }
+);
+
+our %TypeSplit =
+(
+       cpu => { from => [qw(user nice syst idle wait)], to => 'value', type_instance => [qw(user nice system idle wait)] },
+       memory => { from => [qw(used free buffers cached)], to => 'value', type_instance => [qw(used free buffered cached)] },
+       nfs3_procedures => { from => [qw(null getattr lookup access readlink
+               read write create mkdir symlink mknod remove rmdir rename link
+               readdir readdirplus fsstat fsinfo pathconf commit)], to => 'value' },
+       nfs2_procedures => { from => [qw(create fsstat getattr link lookup
+               mkdir null read readdir readlink remove rename rmdir root
+               setattr symlink wrcache write)], to => 'value' },
+       processes => { from => [qw(running sleeping zombies stopped paging blocked)], to => 'value' },
+       swap => { from => [qw(cached free used resv)], to => 'value', type_instance => [qw(cached free used reserved)] }
+);
+
+our %TypeRename =
+(
+       traffic => { from => [qw(incoming outgoing)], to => [qw(rx tx)] },
+       vs_processes => { from => [qw(total)], to => [qw(value)] },
+);
+
+GetOptions ("indir|i=s" => \$InDir,
+       "outdir|o=s" => \$OutDir,
+       "hostname=s" => \$Hostname) or exit_usage ();
+
+die "No such directory: $InDir" if (!-d $InDir);
+
+our @Files = ();
+our %OutDirs = ();
+
+@Files = find_files ();
+
+for (@Files)
+{
+       my $orig_filename = $_;
+       my $orig = parse_file ($orig_filename);
+       my $dest = translate_file ($orig);
+       my $dest_filename = get_filename ($dest);
+
+       my $dest_directory = dirname ($dest_filename);
+       if (!exists ($OutDirs{$dest_directory}))
+       {
+               print "[ -d '$OutDir/$dest_directory' ] || mkdir -p '$OutDir/$dest_directory'\n";
+               $OutDirs{$dest_directory} = 1;
+       }
+
+       if (($orig->{'type'} eq 'disk') || ($orig->{'type'} eq 'partition'))
+       {
+               special_disk ($orig_filename, $orig, $dest_filename, $dest);
+       }
+       elsif (exists ($TypeSplit{$orig->{'type'}}))
+       {
+               my $src_dses = $TypeSplit{$orig->{'type'}}->{'from'};
+               my $dst_ds = $TypeSplit{$orig->{'type'}}->{'to'};
+               my $type_instances = exists ($TypeSplit{$orig->{'type'}}->{'type_instance'})
+                       ? $TypeSplit{$orig->{'type'}}->{'type_instance'}
+                       : $TypeSplit{$orig->{'type'}}->{'from'};
+
+               for (my $i = 0; $i < @$src_dses; $i++)
+               {
+                       my $src_ds = $src_dses->[$i];
+                       $dest->{'type_instance'} = $type_instances->[$i];
+                       $dest_filename = get_filename ($dest);
+                       print "./rrd_filter.px -i '$InDir/$orig_filename' -m '${src_ds}:${dst_ds}' -o '$OutDir/$dest_filename'\n";
+               }
+       }
+       else
+       {
+               print "cp '$InDir/$orig_filename' '$OutDir/$dest_filename'\n";
+       }
+
+       if (exists ($TypeRename{$orig->{'type'}}))
+       {
+               my $src_dses = $TypeRename{$orig->{'type'}}->{'from'};
+               my $dst_dses = $TypeRename{$orig->{'type'}}->{'to'};
+
+               print "rrdtool tune '$OutDir/$dest_filename'";
+               for (my $i = 0; $i < @$src_dses; $i++)
+               {
+                       print " --data-source-rename "
+                               . $src_dses->[$i] . ':' . $dst_dses->[$i];
+               }
+               print "\n";
+       }
+}
+
+exit (0);
+
+sub translate_file
+{
+       my $orig = shift;
+       my $dest = {};
+       %$dest = %$orig;
+
+       if (defined ($TypeTranslate{$orig->{'type'}}))
+       {
+               $TypeTranslate{$orig->{'type'}}->($dest);
+       }
+
+       return ($dest);
+} # translate_file
+
+sub get_filename
+{
+       my $args = shift;
+       my $filename = $args->{'host'}
+       . '/' . $args->{'plugin'} . (defined ($args->{'plugin_instance'}) ? '-'.$args->{'plugin_instance'} : '')
+       . '/' . $args->{'type'} . (defined ($args->{'type_instance'}) ? '-'.$args->{'type_instance'} : '') . '.rrd';
+
+       return ($filename);
+}
+
+sub parse_file
+{
+       my $fullname = shift;
+       my @parts = split ('/', $fullname);
+
+       my $filename;
+
+       my $host;
+       my $plugin;
+       my $plugin_instance;
+       my $type;
+       my $type_instance;
+
+       $filename = pop (@parts);
+
+       if ($filename =~ m/^([^-]+)(?:-(.*))?\.rrd$/)
+       {
+               $type = $1;
+               $type_instance = $2;
+       }
+       else
+       {
+               return;
+       }
+
+       if (@parts)
+       {
+               my $dirname = pop (@parts);
+               my $regex_str = join ('|', keys (%Subdirs));
+               if ($dirname =~ m/^($regex_str)(?:-(.*))?$/)
+               {
+                       $plugin = $1;
+                       $plugin_instance = $2;
+               }
+               else
+               {
+                       push (@parts, $dirname);
+               }
+       }
+       if (!$plugin)
+       {
+               $plugin = $type;
+       }
+
+       if (@parts)
+       {
+               $host = pop (@parts);
+       }
+       else
+       {
+               $host = $Hostname;
+       }
+
+       return
+       ({
+               host => $host,
+               plugin => $plugin,
+               plugin_instance => $plugin_instance,
+               type => $type,
+               type_instance => $type_instance
+       });
+} # parse_file
+
+sub find_files
+{
+       my $reldir = @_ ? shift : '';
+       my $absdir = $InDir . ($reldir ? "/$reldir" : '');
+
+       my $dh;
+
+       my @files = ();
+       my @dirs = ();
+
+       opendir ($dh, $absdir) or die ("opendir ($absdir): $!");
+       while (my $file = readdir ($dh))
+       {
+               next if ($file =~ m/^\./);
+               next if (-l "$absdir/$file");
+               if (-d "$absdir/$file")
+               {
+                       push (@dirs, ($reldir ? "$reldir/" : '') . $file);
+               }
+               elsif ($file =~ m/\.rrd$/)
+               {
+                       push (@files, ($reldir ? "$reldir/" : '') . $file);
+               }
+       }
+       closedir ($dh);
+
+       for (my $i = 0; $i < @dirs; $i++)
+       {
+               push (@files, find_files ($dirs[$i]));
+       }
+
+       return (@files);
+} # find_files
+
+{my $cache;
+sub _special_disk_instance
+{
+       my $orig_instance = shift;
+
+       if (!defined ($cache))
+       {
+               my $fh;
+               open ($fh, "< /proc/diskstats") or die ("open (/proc/diststats): $!");
+
+               $cache = {};
+               while (my $line = <$fh>)
+               {
+                       chomp ($line);
+                       my @fields = split (' ', $line);
+                       $cache->{$fields[0] . '-' . $fields[1]} = $fields[2];
+               }
+               close ($fh);
+       }
+
+       return (defined ($cache->{$orig_instance})
+               ? $cache->{$orig_instance}
+               : $orig_instance);
+}}
+
+sub special_disk
+{
+       my $orig_filename = shift;
+       my $orig = shift;
+       my $dest_filename = shift;
+       my $dest = shift;
+       my $dest_directory;
+
+       $dest->{'type_instance'} = undef;
+       $dest->{'plugin_instance'} = _special_disk_instance ($orig->{'type_instance'});
+       if ($dest->{'plugin_instance'} eq $orig->{'type_instance'})
+       {
+               print qq(echo "You may need to rename these files" >&2\n);
+       }
+
+       $dest->{'type'} = 'disk_merged';
+       $dest_filename = get_filename ($dest);
+
+       $dest_directory = dirname ($dest_filename);
+       if (!exists ($OutDirs{$dest_directory}))
+       {
+               print "[ -d '$OutDir/$dest_directory' ] || mkdir -p '$OutDir/$dest_directory'\n";
+               $OutDirs{$dest_directory} = 1;
+       }
+
+       print "./rrd_filter.px -i '$InDir/$orig_filename' -m 'rmerged:read' -m 'wmerged:write' -o '$OutDir/$dest_filename'\n";
+
+       $dest->{'type'} = 'disk_octets';
+       $dest_filename = get_filename ($dest);
+       print "./rrd_filter.px -i '$InDir/$orig_filename' -m 'rbytes:read' -m 'wbytes:write' -o '$OutDir/$dest_filename'\n";
+
+       $dest->{'type'} = 'disk_ops';
+       $dest_filename = get_filename ($dest);
+       print "./rrd_filter.px -i '$InDir/$orig_filename' -m 'rcount:read' -m 'wcount:write' -o '$OutDir/$dest_filename'\n";
+
+       $dest->{'type'} = 'disk_time';
+       $dest_filename = get_filename ($dest);
+       print "./rrd_filter.px -i '$InDir/$orig_filename' -m 'rtime:read' -m 'wtime:write' -o '$OutDir/$dest_filename'\n";
+}
+
+sub exit_usage
+{
+       print <<EOF;
+Usage: $0 [-i indir] [-o outdir] [--hostname myhostname]
+EOF
+       exit (1);
+}
diff --git a/contrib/migrate-4-5.px b/contrib/migrate-4-5.px
new file mode 100755 (executable)
index 0000000..c2a9555
--- /dev/null
@@ -0,0 +1,255 @@
+#!/usr/bin/perl
+
+# collectd - contrib/migrate-4-5.px
+# Copyright (C) 2010  Florian Forster
+#
+# 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:
+#   Florian Forster <octo at collectd.org>
+
+use strict;
+use warnings;
+
+use Getopt::Long ('GetOptions');
+use Data::Dumper ();
+use File::Basename ('dirname');
+
+our $InDir = '/var/lib/collectd';
+our $RRDtool = 'rrdtool';
+our $RRDFilter = 'rrd_filter.px';
+
+our %TypesCounterToDerive = # {{{
+(
+  apache_bytes => ["count"],
+  apache_requests => ["count"],
+  arc_counts => ["demand_data", "demand_metadata", "prefetch_data", "prefetch_metadata"],
+  arc_l2_bytes => ["read", "write"],
+  ath_stat => ["value"],
+  compression => ["uncompressed", "compressed"],
+  connections => ["value"],
+  cpu => ["value"],
+  current => ["value"],
+  disk_merged => ["read", "write"],
+  disk_octets => ["read", "write"],
+  disk_ops => ["read", "write"],
+  disk_ops_complex => ["value"],
+  disk_time => ["read", "write"],
+  dns_answer => ["value"],
+  dns_notify => ["value"],
+  dns_octets => ["queries", "responses"],
+  dns_opcode => ["value"],
+  dns_qtype => ["value"],
+  dns_query => ["value"],
+  dns_question => ["value"],
+  dns_rcode => ["value"],
+  dns_reject => ["value"],
+  dns_request => ["value"],
+  dns_resolver => ["value"],
+  dns_response => ["value"],
+  dns_transfer => ["value"],
+  dns_update => ["value"],
+  dns_zops => ["value"],
+  fscache_stat => ["value"],
+  fork_rate => ["value"],
+  http_request_methods => ["count"],
+  http_requests => ["count"],
+  http_response_codes => ["count"],
+  if_collisions => ["value"],
+  if_dropped => ["rx", "tx"],
+  if_errors => ["rx", "tx"],
+  if_multicast => ["value"],
+  if_octets => ["rx", "tx"],
+  if_packets => ["rx", "tx"],
+  if_rx_errors => ["value"],
+  if_tx_errors => ["value"],
+  io_octets => ["rx", "tx"],
+  io_packets => ["rx", "tx"],
+  ipt_bytes => ["value"],
+  ipt_packets => ["value"],
+  irq => ["value"],
+  memcached_command => ["value"],
+  memcached_octets => ["rx", "tx"],
+  memcached_ops => ["value"],
+  mysql_commands => ["value"],
+  mysql_handler => ["value"],
+  mysql_locks => ["value"],
+  mysql_log_position => ["value"],
+  mysql_octets => ["rx", "tx"],
+  nfs_procedure => ["value"],
+  nginx_requests => ["value"],
+  node_octets => ["rx", "tx"],
+  node_stat => ["value"],
+  operations => ["value"],
+  pg_blks => ["value"],
+  pg_n_tup_c => ["value"],
+  pg_scan => ["value"],
+  pg_xact => ["value"],
+  protocol_counter => ["value"],
+  ps_cputime => ["user", "syst"],
+  ps_pagefaults => ["minflt", "majflt"],
+  ps_code => ["value"],
+  ps_data => ["value"],
+  serial_octets => ["rx", "tx"],
+  swap_io => ["value"],
+  virt_cpu_total => ["ns"],
+  virt_vcpu => ["ns"],
+  vmpage_action => ["value"],
+  vmpage_faults => ["minflt", "majflt"],
+  vmpage_io => ["in", "out"],
+); # }}} %TypesCounterToDerive
+
+our %TypesRenameDataSource = # {{{
+(
+  absolute => "count",
+  apache_bytes => "count",
+  apache_connections => "count",
+  apache_idle_workers => "count",
+  apache_requests => "count",
+  apache_scoreboard => "count",
+  conntrack => "entropy",
+  contextswitch => "contextswitches",
+  delay => "seconds",
+  entropy => "entropy",
+  file_size => "bytes",
+  frequency => "frequency",
+  frequency_offset => "ppm",
+  http_request_methods => "count",
+  http_requests => "count",
+  http_response_codes => "count",
+  percent => "percent",
+  ping => "ping",
+  records => "count",
+  time_dispersion => "seconds",
+  timeleft => "timeleft",
+  time_offset => "seconds",
+  users => "users",
+  virt_cpu_total => "ns",
+  virt_vcpu => "ns",
+); # }}} %TypesRenameDataSource
+
+sub handle_file # {{{
+{
+  my @path = @_;
+  my $path = join ('/', @path);
+
+  if (!($path =~ m/\.rrd$/))
+  {
+    return;
+  }
+
+  my $tmp = pop (@path);
+  $tmp =~ s/\.rrd$//;
+  my ($type, $type_inst) = split (m/-/, $tmp, 2);
+  $type_inst ||= '';
+
+  $tmp = pop (@path);
+  my ($plugin, $plugin_inst) = split (m/-/, $tmp, 2);
+  $plugin_inst ||= '';
+
+  if ($TypesRenameDataSource{$type})
+  {
+    my $old_ds = $TypesRenameDataSource{$type};
+    print "$RRDtool tune \"$path\" --data-source-rename ${old_ds}:value\n";
+  }
+
+  if ($TypesCounterToDerive{$type})
+  {
+    my $ds_names = $TypesCounterToDerive{$type};
+    
+    for (@$ds_names)
+    {
+      my $name = $_;
+      print "$RRDtool tune \"$path\" --data-source-type ${name}:DERIVE --minimum ${name}:0 --maximum ${name}:U\n";
+    }
+  }
+
+  if ((($plugin eq 'df') || ($plugin eq 'interface'))
+    && (!$plugin_inst) && ($type_inst))
+  {
+    my $dir = join ('/', @path);
+    print "mkdir -p \"$dir/$plugin-$type_inst\"\n";
+    if (($plugin eq 'df') and ($type eq 'df'))
+    {
+      print "$RRDFilter --infile=\"$path\" --outfile=\"$dir/$plugin-$type_inst/df_complex-free.rrd\" --map free:value\n";
+      print "$RRDFilter --infile=\"$path\" --outfile=\"$dir/$plugin-$type_inst/df_complex-used.rrd\" --map used:value\n";
+    }
+    else
+    {
+      print "mv \"$path\" \"$dir/$plugin-$type_inst/$type.rrd\"\n";
+    }
+  }
+} # }}} sub handle_file
+
+sub scan_dir # {{{
+{
+  my @dir_parts = @_;
+  my $dir_str = join ('/', @dir_parts);
+  my $dh;
+
+  opendir ($dh, $dir_str) || die;
+  while (my $entry = readdir ($dh))
+  {
+    my $entry_path = "$dir_str/$entry";
+
+    if ($entry =~ m/^\./)
+    {
+      next;
+    }
+
+    if (-d $entry_path)
+    {
+      scan_dir (@dir_parts, $entry);
+    }
+    elsif (-f $entry_path)
+    {
+      handle_file (@dir_parts, $entry);
+    }
+  }
+  closedir ($dh);
+} # }}} sub scan_dir
+
+sub exit_usage # {{{
+{
+  print STDERR <<EOF;
+migrate-4-5.px [OPTIONS]
+
+Valid options are:
+
+  --indir <dir>         Source directory
+                        Default: $InDir
+  --rrdtool <path>      Path to the RRDtool binary
+                        Default: $RRDtool
+  --rrdfilter <path>    Path to the rrd_filter.px script
+                        Default: $RRDFilter
+
+EOF
+  exit (1);
+} # }}} sub exit_usage
+
+GetOptions ("indir|i=s" => \$InDir,
+        "rrdtool=s" => \$RRDtool,
+        "rrdfilter=s" => \$RRDFilter,
+        "help|h" => \&exit_usage) or exit_usage ();
+
+print "#!/bin/bash\n\n";
+
+scan_dir ($InDir);
+
+# vim: set sw=2 sts=2 et fdm=marker :
diff --git a/contrib/network-proxy.py b/contrib/network-proxy.py
new file mode 100644 (file)
index 0000000..98a4ad8
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+# vim: sts=4 sw=4 et
+
+# Simple unicast proxy to send collectd traffic to another host/port.
+# Copyright (C) 2007  Pavel Shramov <shramov at mexmat.net>
+#
+# 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., 59 Temple
+# Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""
+Simple unicast proxy for collectd (>= 4.0).
+Binds to 'local' address and forwards all traffic to 'remote'.
+"""
+
+import socket
+import struct
+
+""" Local multicast group/port"""
+local  = ("239.192.74.66", 25826)
+""" Address to send packets """
+remote = ("grid.pp.ru", 35826)
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+mreq = struct.pack("4sl", socket.inet_aton(local[0]), socket.INADDR_ANY)
+
+sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
+sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
+sock.bind(local)
+
+out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+
+if __name__ == "__main__":
+    while True:
+        (buf, addr) = sock.recvfrom(2048)
+        sock.sendto(buf, remote)
diff --git a/contrib/oracle/create_schema.ddl b/contrib/oracle/create_schema.ddl
new file mode 100644 (file)
index 0000000..86b1e83
--- /dev/null
@@ -0,0 +1,264 @@
+-- collectd - contrib/oracle/create_schema.ddl
+-- Copyright (C) 2008,2009  Roman Klesel
+--
+-- 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:
+--   Roman Klesel <roman.klesel at noris.de>
+
+-- Description
+--------------
+-- This will create a schema to provide collectd with the required permissions
+-- and space for statistic data.
+-- The idea is to store the output of some expensive queries in static tables
+-- and fill these tables with dbms_scheduler jobs as often as necessary.
+-- collectd will then just read from the static tables. This will reduces the
+-- chance that your system will be killed by excessive monitoring queries and
+-- gives the dba control on the interval the information provided to collectd
+-- will be refreshed. You have to create a dbms_scheduler job for each of the
+-- schemas you what to monitor for object-space-usage. See the example below.
+--
+-- Requirements
+---------------
+-- make sure you have: 
+--             write permission in $PWD
+--             you have GID of oracle software owner
+--             set $ORACLE_HOME 
+--             set $ORACLE_SID
+--             DB is up an running in RW mode
+-- execute like this:
+-- sqlplus /nolog @ create_collectd-schema.dll
+
+spool create_collectd-schema.log
+connect / as sysdba
+
+-- Create user, tablespace and permissions
+CREATE TABLESPACE "COLLECTD-TBS" 
+       DATAFILE SIZE 30M 
+       AUTOEXTEND ON 
+       NEXT 10M 
+       MAXSIZE 300M
+       LOGGING 
+       EXTENT MANAGEMENT LOCAL 
+       SEGMENT SPACE MANAGEMENT AUTO 
+       DEFAULT NOCOMPRESS;
+
+CREATE ROLE "CREATE_COLLECTD_SCHEMA" NOT IDENTIFIED;
+GRANT CREATE JOB TO "CREATE_COLLECTD_SCHEMA";
+GRANT CREATE SEQUENCE TO "CREATE_COLLECTD_SCHEMA";
+GRANT CREATE SYNONYM TO "CREATE_COLLECTD_SCHEMA";
+GRANT CREATE TABLE TO "CREATE_COLLECTD_SCHEMA";
+GRANT CREATE VIEW TO "CREATE_COLLECTD_SCHEMA";
+GRANT CREATE PROCEDURE TO "CREATE_COLLECTD_SCHEMA";
+
+CREATE USER "COLLECTDU" 
+       PROFILE "DEFAULT" 
+       IDENTIFIED BY "Change_me-1st" 
+       PASSWORD EXPIRE 
+       DEFAULT TABLESPACE "COLLECTD-TBS"
+       TEMPORARY TABLESPACE "TEMP"
+       QUOTA UNLIMITED ON "COLLECTD-TBS"
+       ACCOUNT UNLOCK;
+
+GRANT "CONNECT" TO "COLLECTDU";
+GRANT "SELECT_CATALOG_ROLE" TO "COLLECTDU";
+GRANT "CREATE_COLLECTD_SCHEMA" TO "COLLECTDU";
+GRANT analyze any TO "COLLECTDU";
+GRANT select on dba_tables TO "COLLECTDU";
+GRANT select on dba_lobs TO "COLLECTDU";
+GRANT select on dba_indexes TO "COLLECTDU";
+GRANT select on dba_segments TO "COLLECTDU";
+GRANT select on dba_tab_columns TO "COLLECTDU";
+GRANT select on dba_free_space TO "COLLECTDU";
+GRANT select on dba_data_files TO "COLLECTDU";
+-- Create tables and indexes
+
+alter session set current_schema=collectdu;
+
+create table c_tbs_usage (
+       tablespace_name varchar2(30),
+       bytes_free number,
+    bytes_used  number,
+        CONSTRAINT "C_TBS_USAGE_UK1" UNIQUE ("TABLESPACE_NAME") USING INDEX
+        TABLESPACE "COLLECTD-TBS"  ENABLE)
+        TABLESPACE "COLLECTD-TBS";
+
+CREATE TABLE "COLLECTDU"."C_TBL_SIZE" (
+    "OWNER" VARCHAR2(30 BYTE), 
+       "TABLE_NAME" VARCHAR2(30 BYTE), 
+       "BYTES" NUMBER, 
+        CONSTRAINT "C_TBL_SIZE_UK1" UNIQUE ("OWNER", "TABLE_NAME")
+         USING INDEX TABLESPACE "COLLECTD-TBS"  ENABLE)
+         TABLESPACE "COLLECTD-TBS" ;
+
+create or replace PROCEDURE get_object_size(owner IN VARCHAR2) AS
+
+v_owner VARCHAR2(30) := owner;
+
+l_free_blks NUMBER;
+l_total_blocks NUMBER;
+l_total_bytes NUMBER;
+l_unused_blocks NUMBER;
+l_unused_bytes NUMBER;
+l_lastusedextfileid NUMBER;
+l_lastusedextblockid NUMBER;
+l_last_used_block NUMBER;
+
+CURSOR cur_tbl IS
+SELECT owner,
+  TABLE_NAME
+FROM dba_tables
+WHERE owner = v_owner;
+
+CURSOR cur_idx IS
+SELECT owner,
+  index_name,
+  TABLE_NAME
+FROM dba_indexes
+WHERE owner = v_owner;
+
+CURSOR cur_lob IS
+SELECT owner,
+  segment_name,
+  TABLE_NAME
+FROM dba_lobs
+WHERE owner = v_owner;
+
+BEGIN
+
+  DELETE FROM c_tbl_size
+  WHERE owner = v_owner;
+  COMMIT;
+
+  FOR r_tbl IN cur_tbl
+  LOOP
+    BEGIN
+      dbms_space.unused_space(segment_owner => r_tbl.owner,   segment_name => r_tbl.TABLE_NAME,   segment_type => 'TABLE',   total_blocks => l_total_blocks,   total_bytes => l_total_bytes,   unused_blocks => l_unused_blocks,   unused_bytes => l_unused_bytes,   last_used_extent_file_id => l_lastusedextfileid,   last_used_extent_block_id => l_lastusedextblockid,   last_used_block => l_last_used_block);
+
+    EXCEPTION
+    WHEN others THEN
+      DBMS_OUTPUT.PUT_LINE('tbl_name: ' || r_tbl.TABLE_NAME);
+    END;
+    INSERT
+    INTO c_tbl_size
+    VALUES(r_tbl.owner,   r_tbl.TABLE_NAME,   l_total_bytes -l_unused_bytes);
+  END LOOP;
+
+  COMMIT;
+
+  FOR r_idx IN cur_idx
+  LOOP
+    BEGIN
+      dbms_space.unused_space(segment_owner => r_idx.owner,   segment_name => r_idx.index_name,   segment_type => 'INDEX',   total_blocks => l_total_blocks,   total_bytes => l_total_bytes,   unused_blocks => l_unused_blocks,   unused_bytes => l_unused_bytes,   last_used_extent_file_id => l_lastusedextfileid,   last_used_extent_block_id => l_lastusedextblockid,   last_used_block => l_last_used_block);
+
+    EXCEPTION
+    WHEN others THEN
+      DBMS_OUTPUT.PUT_LINE('idx_name: ' || r_idx.index_name);
+    END;
+
+    UPDATE c_tbl_size
+    SET bytes = bytes + l_total_bytes -l_unused_bytes
+    WHERE owner = r_idx.owner
+     AND TABLE_NAME = r_idx.TABLE_NAME;
+  END LOOP;
+
+  COMMIT;
+
+  FOR r_lob IN cur_lob
+  LOOP
+    BEGIN
+      dbms_space.unused_space(segment_owner => r_lob.owner,   segment_name => r_lob.segment_name,   segment_type => 'LOB',   total_blocks => l_total_blocks,   total_bytes => l_total_bytes,   unused_blocks => l_unused_blocks,   unused_bytes => l_unused_bytes,   last_used_extent_file_id => l_lastusedextfileid,   last_used_extent_block_id => l_lastusedextblockid,   last_used_block => l_last_used_block);
+
+    EXCEPTION
+    WHEN others THEN
+      DBMS_OUTPUT.PUT_LINE('lob_name: ' || r_lob.segment_name);
+    END;
+
+    UPDATE c_tbl_size
+    SET bytes = bytes + l_total_bytes -l_unused_bytes
+    WHERE owner = r_lob.owner
+     AND TABLE_NAME = r_lob.TABLE_NAME;
+  END LOOP;
+
+  COMMIT;
+
+END get_object_size;
+/
+
+create or replace PROCEDURE get_tbs_size AS
+BEGIN
+
+execute immediate 'truncate table c_tbs_usage';
+
+insert into c_tbs_usage (
+select df.tablespace_name as tablespace_name, 
+       decode(df.maxbytes,
+               0,
+               sum(fs.bytes),
+               (df.maxbytes-(df.bytes-sum(fs.bytes)))) as bytes_free,
+       decode(df.maxbytes,
+               0,
+               round((df.bytes-sum(fs.bytes))),
+               round(df.maxbytes-(df.maxbytes-(df.bytes-sum(fs.bytes))))) as bytes_used
+from dba_free_space fs inner join 
+       (select 
+               tablespace_name, 
+               sum(bytes) bytes, 
+               sum(decode(maxbytes,0,bytes,maxbytes))  maxbytes
+        from dba_data_files
+        group by tablespace_name ) df          
+on fs.tablespace_name = df.tablespace_name
+group by df.tablespace_name,df.maxbytes,df.bytes);
+
+COMMIT;
+
+END get_tbs_size;
+/
+
+BEGIN
+sys.dbms_scheduler.create_job(
+job_name => '"COLLECTDU"."C_TBSSIZE_JOB"',
+job_type => 'PLSQL_BLOCK',
+job_action => 'begin
+   get_tbs_size();
+end;',
+repeat_interval => 'FREQ=MINUTELY;INTERVAL=5',
+start_date => systimestamp at time zone 'Europe/Berlin',
+job_class => '"DEFAULT_JOB_CLASS"',
+auto_drop => FALSE,
+enabled => TRUE);
+END;
+/
+
+BEGIN
+sys.dbms_scheduler.create_job(
+job_name => '"COLLECTDU"."C_TBLSIZE_COLLECTDU_JOB"',
+job_type => 'PLSQL_BLOCK',
+job_action => 'begin
+   get_object_size( owner => ''COLLECTDU'' );
+end;',
+repeat_interval => 'FREQ=HOURLY;INTERVAL=12',
+start_date => systimestamp at time zone 'Europe/Berlin',
+job_class => '"DEFAULT_JOB_CLASS"',
+auto_drop => FALSE,
+enabled => TRUE);
+END;
+/
+
+spool off
+quit
+
+-- vim: set syntax=sql :
diff --git a/contrib/oracle/db_systat.sql b/contrib/oracle/db_systat.sql
new file mode 100644 (file)
index 0000000..cf2a3c4
--- /dev/null
@@ -0,0 +1,55 @@
+-- Table sizes
+SELECT owner,
+  TABLE_NAME,
+  bytes
+FROM collectdu.c_tbl_size;
+
+-- Tablespace sizes
+SELECT tablespace_name,
+  bytes_free,
+  bytes_used
+FROM collectdu.c_tbs_usage;
+
+-- IO per Tablespace
+SELECT SUM(vf.phyblkrd) *8192 AS
+phy_blk_r,
+  SUM(vf.phyblkwrt) *8192 AS
+phy_blk_w,
+  'tablespace' AS
+i_prefix,
+  dt.tablespace_name
+FROM((dba_data_files dd JOIN v$filestat vf ON dd.file_id = vf.file#) JOIN dba_tablespaces dt ON dd.tablespace_name = dt.tablespace_name)
+GROUP BY dt.tablespace_name;
+
+-- Buffer Pool Hit Ratio:
+SELECT DISTINCT 100 *ROUND(1 -((MAX(decode(name,   'physical reads cache',   VALUE))) /(MAX(decode(name,   'db block gets from cache',   VALUE)) + MAX(decode(name,   'consistent gets from cache',   VALUE)))),   4) AS
+VALUE,
+  'BUFFER_CACHE_HIT_RATIO' AS
+buffer_cache_hit_ratio
+FROM v$sysstat;
+
+-- Shared Pool Hit Ratio:
+SELECT 
+  100.0 * sum(PINHITS) / sum(pins) as VALUE,
+  'SHAREDPOOL_HIT_RATIO' AS SHAREDPOOL_HIT_RATIO
+FROM V$LIBRARYCACHE;
+
+-- PGA Hit Ratio:
+SELECT VALUE,
+  'PGA_HIT_RATIO' AS
+pga_hit_ratio
+FROM v$pgastat
+WHERE name = 'cache hit percentage';
+
+-- DB Efficiency
+SELECT ROUND(SUM(decode(metric_name,   'Database Wait Time Ratio',   VALUE)),   2) AS
+database_wait_time_ratio,
+  ROUND(SUM(decode(metric_name,   'Database CPU Time Ratio',   VALUE)),   2) AS
+database_cpu_time_ratio,
+  'DB_EFFICIENCY' AS
+db_efficiency
+FROM sys.v_$sysmetric
+WHERE metric_name IN('Database CPU Time Ratio',   'Database Wait Time Ratio')
+ AND intsize_csec =
+  (SELECT MAX(intsize_csec)
+   FROM sys.v_$sysmetric);
diff --git a/contrib/php-collection/browser.js b/contrib/php-collection/browser.js
new file mode 100644 (file)
index 0000000..4ddc424
--- /dev/null
@@ -0,0 +1,790 @@
+/*
+ * Copyright (C) 2009  Bruno Prémont <bonbons AT linux-vserver.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+// Toggle visibility of a div
+function toggleDiv(divID) {
+       var div   = document.getElementById(divID);
+       var label = document.getElementById(divID+'_sw');
+       var label_txt = null;
+       if (div) {
+               if (div.style.display == 'none') {
+                       div.style.display = 'block';
+                       label_txt = 'Hide';
+               } else {
+                       div.style.display = 'none';
+                       label_txt = 'Show';
+               }
+       }
+       if (label_txt && label) {
+               var childCnt = label.childNodes.length;
+               while (childCnt > 0)
+                       label.removeChild(label.childNodes[--childCnt]);
+               label.appendChild(document.createTextNode(label_txt));
+       }
+       GraphPositionToolbox(null);
+}
+
+var req = null;
+
+// DHTML helper code to asynchronous loading of content
+function loadXMLDoc(url, query) {
+       if (window.XMLHttpRequest) {
+               req = new XMLHttpRequest();
+               req.onreadystatechange = processReqChange;
+               req.open('POST', url, true);
+               req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 
+               req.send(query);
+       } else if (window.ActiveXObject) {
+               req = new ActiveXObject("Microsoft.XMLHTTP");
+               if (req) {
+                       req.onreadystatechange = processReqChange;
+                       req.open('POST', url, true);
+                       req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); 
+                       req.send(query);
+               }
+       }
+}
+
+// DHTML new-content dispatcher
+function processReqChange(evt) {
+       if (req.readyState == 4) {
+               if (req.status == 200) {
+                       var response = req.responseXML.documentElement;
+                       var method = response.getElementsByTagName('method')[0].firstChild.data;
+                       var result = response.getElementsByTagName('result')[0];
+                       req = null;
+                       eval(method + '(result)');
+               }
+       }
+}
+
+// Update contents of a <select> drop-down list
+function refillSelect(options, select) {
+       if (!select)
+               return -1;
+
+       var childCnt = select.childNodes.length;
+       var oldValue = select.selectedIndex > 0 ? select.options[select.selectedIndex].value : '/';
+       while (childCnt > 0)
+               select.removeChild(select.childNodes[--childCnt]);
+
+       var optCnt = options ? options.length : 0;
+       if (optCnt == 0) {
+               select.setAttribute('disabled', 'disabled');
+               return -1;
+       } else {
+               select.removeAttribute('disabled');
+               var keepSelection = false;
+               if (optCnt == 1) {
+                       keepSelection = true;
+                       oldValue = options[0].firstChild ? options[0].firstChild.data : '';
+               } else if (oldValue != '/') {
+                       for (i = 0; i < optCnt && !keepSelection; i++)
+                               if (oldValue == (options[i].firstChild ? options[i].firstChild.data : ''))
+                                       keepSelection = true;
+               }
+               newOption = document.createElement("option");
+               newOption.value = '/';
+               if (keepSelection)
+                       newOption.setAttribute('disabled', 'disabled');
+               else
+                       newOption.setAttribute('selected', 'selected');
+               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");
+                       newOption.value = options[i].firstChild ? options[i].firstChild.data : '';
+                       if (keepSelection && newOption.value == oldValue)
+                               newOption.setAttribute('selected', 'selected');
+                       if (newOption.value[0] == '@') {
+                               newOption.setAttribute('style', 'font-style: italic');
+                               if (newOption.value == '@' || newOption.value == '@merge')
+                                       newOption.appendChild(document.createTextNode('Meta graph'));
+                               else if (newOption.value == '@all')
+                                       newOption.appendChild(document.createTextNode('All entries'));
+                               else if (newOption.value == '@merge_sum')
+                                       newOption.appendChild(document.createTextNode('Meta summed graph'));
+                               else if (newOption.value == '@merge_avg')
+                                       newOption.appendChild(document.createTextNode('Meta averaged graph'));
+                               else if (newOption.value == '@merge_stack')
+                                       newOption.appendChild(document.createTextNode('Meta stacked graph'));
+                               else if (newOption.value == '@merge_line')
+                                       newOption.appendChild(document.createTextNode('Meta lines graph'));
+                               else
+                                       newOption.appendChild(document.createTextNode(newOption.value));
+                       } else
+                               newOption.appendChild(document.createTextNode(newOption.value));
+                       select.appendChild(newOption);
+               }
+               return keepSelection ? select.selectedIndex : -1;
+       }
+}
+
+// Request refresh of host list
+function ListRefreshHost() {
+       var query = 'action=list_hosts';
+       loadXMLDoc(dhtml_url, query);
+}
+
+// Handle update to host list
+function ListOfHost(response) {
+       var select = document.getElementById('host_list');
+       var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
+       if (idx > 0) {
+               ListRefreshPlugin();
+       } else
+               ListOfPlugin(null);
+}
+
+// Request refresh of plugin list
+function ListRefreshPlugin() {
+       var host_list = document.getElementById('host_list');
+       var host      = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
+       if (host != '/') {
+               var query = 'action=list_plugins&host='+encodeURIComponent(host);
+               loadXMLDoc(dhtml_url, query);
+       } else {
+               ListOfPlugin(null);
+       }
+}
+
+// Handle update to plugin list
+function ListOfPlugin(response) {
+       var select = document.getElementById('plugin_list');
+       var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
+       if (idx > 0) {
+               ListRefreshPluginInstance();
+       } else
+               ListOfPluginInstance(null);
+}
+
+// Request refresh of plugin instance list
+function ListRefreshPluginInstance() {
+       var host_list   = document.getElementById('host_list');
+       var host        = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
+       var plugin_list = document.getElementById('plugin_list');
+       var plugin      = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
+       if (host != '/' && plugin != '/') {
+               var query = 'action=list_pinsts&host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin);
+               loadXMLDoc(dhtml_url, query);
+       } else {
+               ListOfPluginInstance(null);
+       }
+}
+
+// Handle update of plugin instance list
+function ListOfPluginInstance(response) {
+       var select = document.getElementById('pinst_list');
+       var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
+       if (idx > 0) {
+               ListRefreshType();
+       } else
+               ListOfType(null);
+}
+
+// Request refresh of type list
+function ListRefreshType() {
+       var host_list   = document.getElementById('host_list');
+       var host        = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
+       var plugin_list = document.getElementById('plugin_list');
+       var plugin      = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
+       var pinst_list  = document.getElementById('pinst_list');
+       var pinst       = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
+       if (host != '/' && plugin != '/' && pinst != '/') {
+               var query = 'action=list_types&host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin)+'&plugin_instance='+encodeURIComponent(pinst);
+               loadXMLDoc(dhtml_url, query);
+       } else {
+               ListOfType(null);
+       }
+}
+
+// Handle update of type list
+function ListOfType(response) {
+       var select = document.getElementById('type_list');
+       var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
+       if (idx > 0) {
+               ListRefreshTypeInstance();
+       } else
+               ListOfTypeInstance(null);
+}
+
+// Request refresh of type instance list
+function ListRefreshTypeInstance() {
+       var host_list   = document.getElementById('host_list');
+       var host        = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
+       var plugin_list = document.getElementById('plugin_list');
+       var plugin      = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
+       var pinst_list  = document.getElementById('pinst_list');
+       var pinst       = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
+       var type_list   = document.getElementById('type_list');
+       var type        = type_list.selectedIndex >= 0 ? type_list.options[type_list.selectedIndex].value : '/';
+       if (host != '/' && plugin != '/' && pinst != '/' && type != '/') {
+               var query = 'action=list_tinsts&host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin)+'&plugin_instance='+encodeURIComponent(pinst)+'&type='+encodeURIComponent(type);
+               loadXMLDoc(dhtml_url, query);
+       } else {
+               ListOfTypeInstance(null);
+       }
+}
+
+// Handle update of type instance list
+function ListOfTypeInstance(response) {
+       var select = document.getElementById('tinst_list');
+       var idx = refillSelect(response ? response.getElementsByTagName('option') : null, select);
+       if (idx > 0) {
+               // Enable add button
+               RefreshButtons();
+       } else {
+               // Disable add button
+               RefreshButtons();
+       }
+}
+
+function RefreshButtons() {
+       var host_list   = document.getElementById('host_list');
+       var host        = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
+       var plugin_list = document.getElementById('plugin_list');
+       var plugin      = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
+       var pinst_list  = document.getElementById('pinst_list');
+       var pinst       = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
+       var type_list   = document.getElementById('type_list');
+       var type        = type_list.selectedIndex >= 0 ? type_list.options[type_list.selectedIndex].value : '/';
+       var tinst_list  = document.getElementById('tinst_list');
+       var tinst       = tinst_list.selectedIndex >= 0 ? tinst_list.options[tinst_list.selectedIndex].value : '/';
+       if (host != '/' && plugin != '/' && pinst != '/' && type != '/' && tinst != '/') {
+               document.getElementById('btnAdd').removeAttribute('disabled');
+       } else {
+               document.getElementById('btnAdd').setAttribute('disabled', 'disabled');
+       }
+
+       var graphs = document.getElementById('graphs');
+       if (graphs.getElementsByTagName('div').length > 1) {
+               document.getElementById('btnClear').removeAttribute('disabled');
+               document.getElementById('btnRefresh').removeAttribute('disabled');
+       } else {
+               document.getElementById('btnClear').setAttribute('disabled', 'disabled');
+               document.getElementById('btnRefresh').setAttribute('disabled', 'disabled');
+       }
+}
+
+var nextGraphId = 1;
+var graphList = new Array();
+
+function GraphAppend() {
+       var host_list   = document.getElementById('host_list');
+       var host        = host_list.selectedIndex >= 0 ? host_list.options[host_list.selectedIndex].value : '/';
+       var plugin_list = document.getElementById('plugin_list');
+       var plugin      = plugin_list.selectedIndex >= 0 ? plugin_list.options[plugin_list.selectedIndex].value : '/';
+       var pinst_list  = document.getElementById('pinst_list');
+       var pinst       = pinst_list.selectedIndex >= 0 ? pinst_list.options[pinst_list.selectedIndex].value : '/';
+       var type_list   = document.getElementById('type_list');
+       var type        = type_list.selectedIndex >= 0 ? type_list.options[type_list.selectedIndex].value : '/';
+       var tinst_list  = document.getElementById('tinst_list');
+       var tinst       = tinst_list.selectedIndex >= 0 ? tinst_list.options[tinst_list.selectedIndex].value : '/';
+       var time_list   = document.getElementById('timespan');
+       var timespan    = time_list.selectedIndex >= 0 ? time_list.options[time_list.selectedIndex].value : '';
+       var tinyLegend  = document.getElementById('tinylegend').checked;
+       var logarithmic = document.getElementById('logarithmic').checked;
+       if (host[0] == '@' || plugin[0] == '@' || pinst[0] == '@' || type[0] == '@' || (tinst[0] == '@' && tinst.substr(0, 5) != '@merge')) {
+               var query = 'action=list_graphs&host='+encodeURIComponent(host)+'&plugin='+encodeURIComponent(plugin)+'&plugin_instance='+encodeURIComponent(pinst);
+               query = query+'&type='+encodeURIComponent(type)+'&type_instance='+encodeURIComponent(tinst)+'&timespan='+encodeURIComponent(timespan);
+               query = query+(logarithmic ? '&logarithmic=1' : '')+(tinyLegend ? '&tinylegend=1' : '');
+               loadXMLDoc(dhtml_url, query);
+       } else
+               GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic);
+}
+
+function ListOfGraph(response) {
+       var graphs = response ? response.getElementsByTagName('graph') : null;
+       if (graphs && graphs.length > 0) {
+               for (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');
+       } else
+               alert('No graph found for adding');
+}
+
+function GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic) {
+       var graphs      = document.getElementById('graphs');
+
+       if (host != '/' && plugin != '/' && pinst != '/' && type != '/') {
+               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 = '';
+               if (tinst == '@') {
+                       graph_alt   = host+'/'+plugin+(pinst.length > 0 ? '-'+pinst : '')+'/'+type;
+                       graph_title = type+' of '+plugin+(pinst.length > 0 ? '-'+pinst : '')+' plugin for '+host;
+               } else {
+                       graph_alt   = host+'/'+plugin+(pinst.length > 0 ? '-'+pinst : '')+'/'+type+(tinst.length > 0 ? '-'+tinst : '');
+                       graph_title = type+(tinst.length > 0 ? '-'+tinst : '')+' of '+plugin+(pinst.length > 0 ? '-'+pinst : '')+' plugin for '+host;
+                       graph_src  += '&type_instance='+encodeURIComponent(tinst);
+               }
+               if (logarithmic)
+                       graph_src += '&logarithmic=1';
+               if (tinyLegend)
+                       graph_src += '&tinylegend=1';
+               if (timespan)
+                       graph_src += '&timespan='+encodeURIComponent(timespan);
+               var now    = new Date();
+               graph_src += '&ts='+now.getTime();
+               graphList.push(graph_id+' '+encodeURIComponent(graph_alt)+(logarithmic ? '&logarithmic=1' : '')+(tinyLegend ? '&tinylegend=1' : '')+'&timespan='+encodeURIComponent(timespan));
+
+               // Graph container
+               newGraph = document.createElement('div');
+               newGraph.setAttribute('class', 'graph');
+               newGraph.setAttribute('id', graph_id);
+               // Graph cell + graph
+               newImg = document.createElement('img');
+               newImg.setAttribute('src', graph_src);
+               newImg.setAttribute('alt', graph_alt);
+               newImg.setAttribute('title', graph_title);
+               newImg.setAttribute('onclick', 'GraphToggleTools("'+graph_id+'")');
+               newGraph.appendChild(newImg);
+               graphs.appendChild(newGraph);
+       }
+       document.getElementById('nograph').style.display = 'none';
+       RefreshButtons();
+}
+
+function GraphDropAll() {
+       var graphs = document.getElementById('graphs');
+       var childCnt = graphs.childNodes.length;
+       while (childCnt > 0)
+               if (graphs.childNodes[--childCnt].id != 'nograph' && (graphs.childNodes[childCnt].nodeName == 'div' || graphs.childNodes[childCnt].nodeName == 'DIV'))
+                       graphs.removeChild(graphs.childNodes[childCnt]);
+               else if (graphs.childNodes[childCnt].id == 'nograph')
+                       graphs.childNodes[childCnt].style.display = 'block';
+       graphList = new Array();
+       RefreshButtons();
+}
+
+function GraphToggleTools(graph) {
+       var graphId = document.getElementById('ge_graphid').value;
+       var ref_img = null;
+       if (graphId == graph || graph == '') {
+               ref_img = null;
+       } else {
+               var graphDiv = document.getElementById(graph);
+               var imgs     = graphDiv ? graphDiv.getElementsByTagName('img') : null;
+               var imgCnt   = imgs ? imgs.length : 0;
+               while (imgCnt > 0)
+                       if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph')
+                               ref_img = imgs[imgCnt];
+       }
+       if (ref_img) {
+               var ts_sel  =  document.getElementById('ge_timespan');
+               var src_url = ref_img.src;
+               var ge      = document.getElementById('ge');
+               // Fix field values
+               var ts = src_url.match(/&timespan=[^&]*/);
+               ts = ts ? ts[0].substr(10) : '';
+               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++)
+                       if (ts_sel.options[i].value == ts) {
+                               ts_sel.selectedIndex = i;
+                               break;
+                       }
+               // show tools box and position it properly
+               ge.style.display = 'table';
+               GraphPositionToolbox(ref_img);
+       } else {
+               // hide tools box
+               document.getElementById('ge').style.display = 'none';
+               document.getElementById('ge_graphid').value = '';
+       }
+}
+
+function GraphPositionToolbox(ref_img) {
+       var ge      = document.getElementById('ge');
+       if (ge.style.display != 'none') {
+               var wl = 0; var wt = 0;
+               var x = ref_img;
+               if (ref_img == null) {
+                       var graphDiv = document.getElementById(document.getElementById('ge_graphid').value);
+                       var imgs     = graphDiv ? graphDiv.getElementsByTagName('img') : null;
+                       var imgCnt   = imgs ? imgs.length : 0;
+                       while (imgCnt > 0)
+                               if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph')
+                                       ref_img = imgs[imgCnt];
+
+                       if (ref_img == null) {
+                               document.getElementById('ge_graphid').value = '';
+                               ge.style.display = 'none';
+                               return;
+                       } else
+                               x = ref_img;
+               }
+               while (x != null) {
+                       wl += x.offsetLeft;
+                       wt += x.offsetTop;
+                       x = x.offsetParent;
+               }
+               ge.style.left    = (wl + (ref_img.offsetWidth - ge.offsetWidth) / 2)+'px';
+               ge.style.top     = (wt + (ref_img.offsetHeight - ge.offsetHeight) / 2)+'px';
+       }
+}
+
+function GraphRefreshAll() {
+       var imgs   = document.getElementById('graphs').getElementsByTagName('img');
+       var imgCnt = imgs.length;
+       var now    = new Date();
+       var newTS  = '&ts='+now.getTime();
+       while (imgCnt > 0)
+               if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph') {
+                       var oldSrc = imgs[imgCnt].src;
+                       var newSrc = oldSrc.replace(/&ts=[0-9]+/, newTS);
+                       if (newSrc == oldSrc)
+                               newSrc = newSrc + newTS;
+                       imgs[imgCnt].setAttribute('src', newSrc);
+               }
+}
+
+function GraphRefresh(graph) {
+       var graphElement = null;
+       if (graph == null) {
+               var graphId = document.getElementById('ge_graphid').value;
+               if (graphId != '')
+                       graphElement = document.getElementById(graphId);
+       } else 
+               graphElement = document.getElementById(graph);
+       if (graphElement != null) {
+               var imgs = graphElement.getElementsByTagName('img');
+               var imgCnt = imgs.length;
+               while (imgCnt > 0)
+                       if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph') {
+                               var now    = new Date();
+                               var newTS  = '&ts='+now.getTime();
+                               var oldSrc = imgs[imgCnt].src;
+                               var newSrc = oldSrc.replace(/&ts=[0-9]+/, newTS);
+                               if (newSrc == oldSrc)
+                                       newSrc = newSrc+newTS;
+                               imgs[imgCnt].setAttribute('src', newSrc);
+                               break;
+                       }
+       }
+}
+
+function GraphAdjust(graph) {
+       var graphId = graph == null ? document.getElementById('ge_graphid').value : graph;
+       var graphElement = document.getElementById(graphId);
+       if (graphElement != null) {
+               var time_list   = document.getElementById('ge_timespan');
+               var timespan    = time_list.selectedIndex >= 0 ? time_list.options[time_list.selectedIndex].value : '';
+               var tinyLegend  = document.getElementById('ge_tinylegend').checked;
+               var logarithmic = document.getElementById('ge_logarithmic').checked
+               var imgs = graphElement.getElementsByTagName('img');
+               var imgCnt = imgs.length;
+               var ref_img     = null;
+               while (imgCnt > 0)
+                       if (imgs[--imgCnt].parentNode.getAttribute('class') == 'graph') {
+                               var now    = new Date();
+                               var newTS  = '&ts='+now.getTime();
+                               var oldSrc = imgs[imgCnt].src;
+                               var newSrc = oldSrc.replace(/&ts=[^&]*/, newTS);
+                               if (newSrc == oldSrc)
+                                       newSrc = newSrc+newTS;
+                               newSrc     = newSrc.replace(/&logarithmic=[^&]*/, '');
+                               if (logarithmic)
+                                       newSrc += '&logarithmic=1';
+                               newSrc     = newSrc.replace(/&tinylegend=[^&]*/, '');
+                               if (tinyLegend)
+                                       newSrc += '&tinylegend=1';
+                               newSrc     = newSrc.replace(/&timespan=[^&]*/, '');
+                               if (timespan)
+                                       newSrc += '&timespan='+encodeURIComponent(timespan);
+                               imgs[imgCnt].setAttribute('src', newSrc);
+
+                               var myList = Array();
+                               for (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=[^&]*/, '');
+                                               newSrc = newSrc.replace(/&tinylegend=[^&]*/, '');
+                                               newSrc = newSrc.replace(/&timespan=[^&]*/, '');
+                                               newSrc = newSrc+(logarithmic ? '&logarithmic=1' : '')+(tinyLegend ? '&tinylegend=1' : '')+'&timespan='+encodeURIComponent(timespan);
+                                               myList.push(newSrc);
+                                               continue;
+                                       } else
+                                               myList.push(graphList[i]);
+                               graphList = myList;
+                               window.setTimeout("GraphPositionToolbox(null)", 10);
+                               // GraphPositionToolbox(imgs[imgCnt]);
+                               break;
+                       }
+       }
+}
+
+function GraphRemove(graph) {
+       var graphs = document.getElementById('graphs');
+       var graphId = graph == null ? document.getElementById('ge_graphid').value : graph;
+       var graphElement = document.getElementById(graphId);
+       if (graphElement) {
+               GraphToggleTools('');
+               graphs.removeChild(graphElement);
+               RefreshButtons();
+               if (graphs.getElementsByTagName('div').length == 1)
+                       document.getElementById('nograph').style.display = 'block';
+
+               var myList = Array();
+               for (i = 0; i < graphList.length; i++)
+                       if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ')
+                               continue;
+                       else
+                               myList.push(graphList[i]);
+               graphList = myList;
+       }
+}
+
+function GraphMoveUp(graph) {
+       var graphs    = document.getElementById('graphs');
+       var graphId   = graph == null ? document.getElementById('ge_graphid').value : graph;
+       var childCnt  = graphs.childNodes.length;
+       var prevGraph = null;
+       for (i = 0; i < childCnt; i++)
+               if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
+                       if (graphs.childNodes[i].id == 'nograph') {
+                               // Skip
+                       } else if (graphs.childNodes[i].id == graphId) {
+                               var myGraph = graphs.childNodes[i];
+                               if (prevGraph) {
+                                       graphs.removeChild(myGraph);
+                                       graphs.insertBefore(myGraph, prevGraph);
+                               }
+                               break;
+                       } else
+                               prevGraph = graphs.childNodes[i];
+               }
+       for (i = 0; i < graphList.length; i++)
+               if (graphList[i].substring(0, graphId.length) == graphId && graphList[i].charAt(graphId.length) == ' ') {
+                       if (i > 0) {
+                               var tmp = graphList[i-1];
+                               graphList[i-1] = graphList[i];
+                               graphList[i]   = tmp;
+                       }
+                       break;
+               }
+       GraphPositionToolbox(null);
+}
+
+function GraphMoveDown(graph) {
+       var graphs    = document.getElementById('graphs');
+       var graphId   = graph == null ? document.getElementById('ge_graphid').value : graph;
+       var childCnt  = graphs.childNodes.length;
+       var nextGraph = null;
+       var myGraph   = null;
+       for (i = 0; i < childCnt; i++)
+               if (graphs.childNodes[i].nodeName == 'div' || graphs.childNodes[i].nodeName == 'DIV') {
+                       if (graphs.childNodes[i].id == 'nograph') {
+                               // Skip
+                       } else if (graphs.childNodes[i].id == graphId) {
+                               myGraph = graphs.childNodes[i];
+                       } else if (myGraph) {
+                               nextGraph = graphs.childNodes[i];
+                               graphs.removeChild(nextGraph);
+                               graphs.insertBefore(nextGraph, myGraph);
+                               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;
+                       }
+                       break;
+               }
+       GraphPositionToolbox(null);
+}
+
+function GraphListFromCookie(lname) {
+       if (document.cookie.length > 0) {
+               var cname= 'graphLst'+lname+'=';
+               var cookies = document.cookie.split('; ');
+               for (i = 0; i < cookies.length; i++)
+                       if (cookies[i].substring(0, cname.length) == cname)
+                               return cookies[i].substring(cname.length).split('/');
+       }
+       return new Array();
+}
+
+function GraphListNameSort(a, b) {
+       if (a[0] > b[0])
+               return 1
+       else if (a[0] < b[0])
+               return -1;
+       else
+               return 0;
+}
+
+function GraphListRefresh() {
+       var select   = document.getElementById('GraphList');
+       var childCnt = select.childNodes.length;
+       var oldValue = select.selectedIndex > 0 ? select.options[select.selectedIndex].value : '/';
+       while (childCnt > 0)
+               select.removeChild(select.childNodes[--childCnt]);
+
+       // Determine available names
+       var options = new Array();
+       if (document.cookie.length > 0) {
+               var cookies = document.cookie.split('; ');
+               for (i = 0; i < cookies.length; i++)
+                       if (cookies[i].substring(0, 8) == 'graphLst') {
+                               var p = cookies[i].indexOf('=');
+                               if (p < 0)
+                                       continue;
+                               options.push(new Array(cookies[i].substring(8, p), cookies[i].substring(p+1).split('/').length));
+                       }
+       }
+       options.sort(GraphListNameSort);
+
+       var optCnt  = options ? options.length : 0;
+       if (optCnt == 0) {
+               select.setAttribute('disabled', 'disabled');
+               return -1;
+       } else {
+               select.removeAttribute('disabled');
+               for (i = 0; i < optCnt; i++) {
+                       newOption = document.createElement("option");
+                       newOption.value = options[i][0];
+                       if (newOption.value == oldValue)
+                               newOption.setAttribute('selected', 'selected');
+                       if (options[i][1] == 1)
+                               newOption.appendChild(document.createTextNode(newOption.value+' (1 graph)'));
+                       else
+                               newOption.appendChild(document.createTextNode(newOption.value+' ('+options[i][1]+' graphs)'));
+                       select.appendChild(newOption);
+               }
+               return select.selectedIndex;
+       }
+}
+
+function GraphListCheckName(doalert) {
+       var lname = document.getElementById('GraphListName');
+       if (lname) {
+               if (lname.value.match(/^[a-zA-Z0-9_-]+$/)) {
+                       lname.style.backgroundColor = '';
+                       return lname.value;
+               } else {
+                       lname.style.backgroundColor = '#ffdddd';
+                       if (doalert && lname.value.length == 0)
+                               alert('Graph list name is empty.\n\n'+
+                                     'Please fill in a name and try again.');
+                       else if (doalert)
+                               alert('Graph list name contains non-permitted character.\n\n'+
+                                     'Only anlphanumerical characters (a-z, A-Z, 0-9), hyphen (-) and underscore (_) are permitted.\n'+
+                                     'Please correct and try again.');
+                       lname.focus();
+               }
+       }
+       return '';
+}
+
+function GraphSave() {
+       var lstName = GraphListCheckName(true);
+       if (lstName.length == 0)
+               return;
+       if (graphList.length > 0) {
+               // Save graph list to cookie
+               var str = '';
+               for (i = 0; i < graphList.length; i++) {
+                       var g = graphList[i].indexOf(' ');
+                       if (i > 0)
+                               str += '/';
+                       str += graphList[i].substring(g+1);
+               }
+
+               document.cookie = 'graphLst'+lstName+'='+str;
+               if (GraphListFromCookie(lstName).length == 0)
+                       alert("Failed to save graph list '"+lstName+"' to cookie.");
+               else
+                       alert("Successfully saved current graph list.");
+       } else {
+               document.cookie = 'graphLst'+lstName+'=; expires='+new Date().toGMTString();
+               alert("Cleared saved graph list.");
+       }
+       GraphListRefresh();
+}
+
+function GraphDrop() {
+       var cname = document.getElementById('GraphList');
+       if (cname && cname.selectedIndex >= 0) {
+               cname = cname.options[cname.selectedIndex].value;
+               document.cookie = 'graphLst'+cname+'=; expires='+new Date().toGMTString();
+               GraphListRefresh();
+       } else
+               return;
+}
+
+function GraphLoad() {
+       var cname = document.getElementById('GraphList');
+       if (cname && cname.selectedIndex >= 0)
+               cname = cname.options[cname.selectedIndex].value;
+       else
+               return;
+       // Load graph list from cookie
+       var grLst = GraphListFromCookie(cname);
+       var oldLength = graphList.length;
+       for (i = 0; i < grLst.length; i++) {
+               var host        = '';
+               var plugin      = '';
+               var pinst       = '';
+               var type        = '';
+               var tinst       = '';
+               var timespan    = '';
+               var logarithmic = false;
+               var tinyLegend  = false;
+               var graph = grLst[i].split('&');
+               for (j = 0; j < graph.length; j++)
+                       if (graph[j] == 'logarithmic=1')
+                               logarithmic = true;
+                       else if (graph[j] == 'tinylegend=1')
+                               tinyLegend = true;
+                       else if (graph[j].substring(0, 9) == 'timespan=')
+                               timespan = decodeURIComponent(graph[j].substring(9));
+               graph = decodeURIComponent(graph[0]).split('/');
+               host = graph[0];
+               if (graph.length > 1) {
+                       var g = graph[1].indexOf('-');
+                       if (g >= 0) {
+                               plugin = graph[1].substring(0, g);
+                               pinst  = graph[1].substring(g+1);
+                       } else
+                               plugin = graph[1];
+               }
+               if (graph.length > 2) {
+                       var g = graph[2].indexOf('-');
+                       if (g >= 0) {
+                               type  = graph[2].substring(0, g);
+                               tinst = graph[2].substring(g+1);
+                       } else
+                               type  = graph[2];
+               }
+
+               if (host && plugin && type)
+                       GraphDoAppend(host, plugin, pinst, type, tinst, timespan, tinyLegend, logarithmic);
+       }
+       if (grLst.length == 0)
+               alert("No list '"+cname+"' found for loading.");
+       else if (grLst.length + oldLength != graphList.length)
+               alert("Could not load all graphs, probably damaged cookie.");
+}
+
diff --git a/contrib/php-collection/config.php b/contrib/php-collection/config.php
new file mode 100644 (file)
index 0000000..dbd0aab
--- /dev/null
@@ -0,0 +1,58 @@
+<?php // vim:fenc=utf-8:filetype=php:ts=4
+/**
+ * Configuration file for Collectd graph browser
+ */
+
+// Array of paths when collectd's rrdtool plugin writes RRDs
+$config['datadirs']   = array('/var/lib/collectd/rrd/');
+// Width of graph to be generated by rrdgraph
+$config['rrd_width']  = 600;
+// Height of graph to be generated by rrdgraph
+$config['rrd_height'] = 120;
+// List of supported timespans (used for period drop-down list)
+$config['timespan']   = array(
+       array('name'=>'hour',  'label'=>'past hour',  'seconds'=>3600),
+       array('name'=>'day',   'label'=>'past day',   'seconds'=>86400),
+       array('name'=>'week',  'label'=>'past week',  'seconds'=>604800),
+       array('name'=>'month', 'label'=>'past month', 'seconds'=>2678400),
+       array('name'=>'year',  'label'=>'past year',  'seconds'=>31622400));
+// Interval at which values are collectd (currently ignored)
+$config['rrd_interval']  = 10;
+// Average rows/rra (currently ignored)
+$config['rrd_rows']      = 2400;
+// Additional options to pass to rrdgraph
+$config['rrd_opts']      = array();
+// Predefined set of colors for use by collectd_draw_rrd()
+$config['rrd_colors']    = array(
+                'h_1'=>'F7B7B7',  'f_1'=>'FF0000', // Red
+                'h_2'=>'B7EFB7',  'f_2'=>'00E000', // Green
+                'h_3'=>'B7B7F7',  'f_3'=>'0000FF', // Blue
+                'h_4'=>'F3DFB7',  'f_4'=>'F0A000', // Yellow
+                'h_5'=>'B7DFF7',  'f_5'=>'00A0FF', // Cyan
+                'h_6'=>'DFB7F7',  'f_6'=>'A000FF', // Magenta
+                'h_7'=>'FFC782',  'f_7'=>'FF8C00', // Orange
+                'h_8'=>'DCFF96',  'f_8'=>'AAFF00', // Lime
+                'h_9'=>'83FFCD',  'f_9'=>'00FF99',
+               'h_10'=>'81D9FF', 'f_10'=>'00B2FF',
+               'h_11'=>'FF89F5', 'f_11'=>'FF00EA',
+               'h_12'=>'FF89AE', 'f_12'=>'FF0051',
+               'h_13'=>'BBBBBB', 'f_13'=>'555555',
+       );
+/*
+ * URL to collectd's unix socket (unixsock plugin)
+ *  enabled:  'unix:///var/run/collectd/collectd-unixsock'
+ *  disabled: null
+ */
+$config['collectd_sock'] = null;
+/*
+ * Path to TTF font file to use in error images
+ * (fallback when file does not exist is GD fixed font)
+ */
+$config['error_font']    = '/usr/share/fonts/corefonts/arial.ttf';
+
+/*
+ * Constant defining full path to rrdtool
+ */
+define('RRDTOOL', '/usr/bin/rrdtool');
+
+?>
diff --git a/contrib/php-collection/definitions.local.php b/contrib/php-collection/definitions.local.php
new file mode 100644 (file)
index 0000000..4218ae4
--- /dev/null
@@ -0,0 +1,79 @@
+<?php // vim:fenc=utf-8:filetype=php:ts=4
+/*
+ * Copyright (C) 2009  Bruno Prémont <bonbons AT linux-vserver.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+function load_graph_definitions_local($logarithmic = false, $tinylegend = false) {
+       global $GraphDefs, $MetaGraphDefs;
+
+       // Define 1-rrd Graph definitions here
+       $GraphDefs['local_type'] = array(
+               '-v', 'Commits',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#B7B7F7",
+               "AREA:min#FFFFFF",
+               "LINE1:avg#0000FF:Commits",
+               'GPRINT:min:MIN:%6.1lf Min,',
+               'GPRINT:avg:AVERAGE:%6.1lf Avg,',
+               'GPRINT:max:MAX:%6.1lf Max,',
+               'GPRINT:avg:LAST:%6.1lf Last\l');
+
+       // Define MetaGraph definition type -> function mappings here
+       $MetaGraphDefs['local_meta'] = 'meta_graph_local';
+}
+
+function meta_graph_local($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['rrd_opts'] = array('-v', 'Events');
+
+       $files = array();
+/*     $opts['colors'] = array(
+               'ham'     => '00e000',
+               'spam'    => '0000ff',
+               'malware' => '990000',
+
+               'sent'     => '00e000',
+               'deferred' => 'a0e000',
+               'reject'   => 'ff0000',
+               'bounced'  => 'a00050'
+       );
+
+       $type_instances = array('ham', 'spam', 'malware',  'sent', 'deferred', 'reject', 'bounced'); */
+       foreach ($type_instances as $inst) {
+               $file  = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+//     return collectd_draw_meta_stack($opts, $sources);
+       return collectd_draw_meta_line($opts, $sources);
+}
+
+?>
diff --git a/contrib/php-collection/definitions.php b/contrib/php-collection/definitions.php
new file mode 100644 (file)
index 0000000..7297d85
--- /dev/null
@@ -0,0 +1,2105 @@
+<?php // vim:fenc=utf-8:filetype=php:ts=4
+/*
+ * Copyright (C) 2009  Bruno Prémont <bonbons AT linux-vserver.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *
+ * Most RRD Graph definitions copied from collection.cgi
+ */
+$GraphDefs     = array();
+$MetaGraphDefs = array();
+
+if (is_file('definitions.local.php'))
+       require_once('definitions.local.php');
+
+function load_graph_definitions($logarithmic = false, $tinylegend = false) {
+       global $GraphDefs, $MetaGraphDefs;
+
+       $Canvas   = 'FFFFFF';
+
+       $FullRed    = 'FF0000';
+       $FullGreen  = '00E000';
+       $FullBlue   = '0000FF';
+       $FullYellow = 'F0A000';
+       $FullCyan   = '00A0FF';
+       $FullMagenta= 'A000FF';
+
+       $HalfRed    = 'F7B7B7';
+       $HalfGreen  = 'B7EFB7';
+       $HalfBlue   = 'B7B7F7';
+       $HalfYellow = 'F3DFB7';
+       $HalfCyan   = 'B7DFF7';
+       $HalfMagenta= 'DFB7F7';
+
+       $HalfBlueGreen = '89B3C9';
+
+       $GraphDefs = array();
+       $GraphDefs['apache_bytes'] = array(
+               '-v', 'Bits/s',
+               'DEF:min_raw={file}:value:MIN',
+               'DEF:avg_raw={file}:value:AVERAGE',
+               'DEF:max_raw={file}:value:MAX',
+               'CDEF:min=min_raw,8,*',
+               'CDEF:avg=avg_raw,8,*',
+               'CDEF:max=max_raw,8,*',
+               'CDEF:mytime=avg_raw,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*',
+               'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
+               "AREA:avg#$HalfBlue",
+               "LINE1:avg#$FullBlue:Bit/s",
+               'GPRINT:min:MIN:%5.1lf%s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last',
+               'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l');
+       $GraphDefs['apache_requests'] = array(
+               '-v', 'Requests/s',
+               'DEF:min={file}:value:MIN',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Requests/s",
+               'GPRINT:min:MIN:%6.2lf Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:max:MAX:%6.2lf Max,',
+               'GPRINT:avg:LAST:%6.2lf Last');
+       $GraphDefs['apache_scoreboard'] = array(
+               'DEF:min={file}:value:MIN',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Processes",
+               'GPRINT:min:MIN:%6.2lf Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:max:MAX:%6.2lf Max,',
+               'GPRINT:avg:LAST:%6.2lf Last');
+       $GraphDefs['bitrate'] = array(
+               '-v', 'Bits/s',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Bits/s",
+               'GPRINT:min:MIN:%5.1lf%s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Average,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['charge'] = array(
+               '-v', 'Ah',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Charge",
+               'GPRINT:min:MIN:%5.1lf%sAh Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%sAh Avg,',
+               'GPRINT:max:MAX:%5.1lf%sAh Max,',
+               'GPRINT:avg:LAST:%5.1lf%sAh Last\l');
+       $GraphDefs['counter'] = array(
+               '-v', 'Events',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Percent",
+               'GPRINT:min:MIN:%6.2lf%% Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf%% Avg,',
+               'GPRINT:max:MAX:%6.2lf%% Max,',
+               'GPRINT:avg:LAST:%6.2lf%% Last\l');
+               $GraphDefs['cpu'] = array(
+               '-v', 'CPU load',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Percent",
+               'GPRINT:min:MIN:%6.2lf%% Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf%% Avg,',
+               'GPRINT:max:MAX:%6.2lf%% Max,',
+               'GPRINT:avg:LAST:%6.2lf%% Last\l');
+       $GraphDefs['current'] = array(
+               '-v', 'Ampere',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Current",
+               'GPRINT:min:MIN:%5.1lf%sA Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%sA Avg,',
+               'GPRINT:max:MAX:%5.1lf%sA Max,',
+               'GPRINT:avg:LAST:%5.1lf%sA Last\l');
+       $GraphDefs['df'] = array(
+               '-v', 'Percent', '-l', '0',
+               'DEF:free_avg={file}:free:AVERAGE',
+               'DEF:free_min={file}:free:MIN',
+               'DEF:free_max={file}:free:MAX',
+               'DEF:used_avg={file}:used:AVERAGE',
+               'DEF:used_min={file}:used:MIN',
+               'DEF:used_max={file}:used:MAX',
+               'CDEF:total=free_avg,used_avg,+',
+               'CDEF:free_pct=100,free_avg,*,total,/',
+               'CDEF:used_pct=100,used_avg,*,total,/',
+               'CDEF:free_acc=free_pct,used_pct,+',
+               'CDEF:used_acc=used_pct',
+               "AREA:free_acc#$HalfGreen",
+               "AREA:used_acc#$HalfRed",
+               "LINE1:free_acc#$FullGreen:Free",
+               'GPRINT:free_min:MIN:%5.1lf%sB Min,',
+               'GPRINT:free_avg:AVERAGE:%5.1lf%sB Avg,',
+               'GPRINT:free_max:MAX:%5.1lf%sB Max,',
+               'GPRINT:free_avg:LAST:%5.1lf%sB Last\l',
+               "LINE1:used_acc#$FullRed:Used",
+               'GPRINT:used_min:MIN:%5.1lf%sB Min,',
+               'GPRINT:used_avg:AVERAGE:%5.1lf%sB Avg,',
+               'GPRINT:used_max:MAX:%5.1lf%sB Max,',
+               'GPRINT:used_avg:LAST:%5.1lf%sB Last\l');
+       $GraphDefs['disk'] = array(
+               'DEF:rtime_avg={file}:rtime:AVERAGE',
+               'DEF:rtime_min={file}:rtime:MIN',
+               'DEF:rtime_max={file}:rtime:MAX',
+               'DEF:wtime_avg={file}:wtime:AVERAGE',
+               'DEF:wtime_min={file}:wtime:MIN',
+               'DEF:wtime_max={file}:wtime:MAX',
+               'CDEF:rtime_avg_ms=rtime_avg,1000,/',
+               'CDEF:rtime_min_ms=rtime_min,1000,/',
+               'CDEF:rtime_max_ms=rtime_max,1000,/',
+               'CDEF:wtime_avg_ms=wtime_avg,1000,/',
+               'CDEF:wtime_min_ms=wtime_min,1000,/',
+               'CDEF:wtime_max_ms=wtime_max,1000,/',
+               'CDEF:total_avg_ms=rtime_avg_ms,wtime_avg_ms,+',
+               'CDEF:total_min_ms=rtime_min_ms,wtime_min_ms,+',
+               'CDEF:total_max_ms=rtime_max_ms,wtime_max_ms,+',
+               "AREA:total_max_ms#$HalfRed",
+               "AREA:total_min_ms#$Canvas",
+               "LINE1:wtime_avg_ms#$FullGreen:Write",
+               'GPRINT:wtime_min_ms:MIN:%5.1lf%s Min,',
+               'GPRINT:wtime_avg_ms:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:wtime_max_ms:MAX:%5.1lf%s Max,',
+               'GPRINT:wtime_avg_ms:LAST:%5.1lf%s Last\n',
+               "LINE1:rtime_avg_ms#$FullBlue:Read ",
+               'GPRINT:rtime_min_ms:MIN:%5.1lf%s Min,',
+               'GPRINT:rtime_avg_ms:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:rtime_max_ms:MAX:%5.1lf%s Max,',
+               'GPRINT:rtime_avg_ms:LAST:%5.1lf%s Last\n',
+               "LINE1:total_avg_ms#$FullRed:Total",
+               'GPRINT:total_min_ms:MIN:%5.1lf%s Min,',
+               'GPRINT:total_avg_ms:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:total_max_ms:MAX:%5.1lf%s Max,',
+               'GPRINT:total_avg_ms:LAST:%5.1lf%s Last');
+       $GraphDefs['disk_octets'] = array(
+               '-v', 'Bytes/s', '--units=si',
+               'DEF:out_min={file}:write:MIN',
+               'DEF:out_avg={file}:write:AVERAGE',
+               'DEF:out_max={file}:write:MAX',
+               'DEF:inc_min={file}:read:MIN',
+               'DEF:inc_avg={file}:read:AVERAGE',
+               'DEF:inc_max={file}:read:MAX',
+               'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+               'CDEF:mytime=out_avg,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
+               'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+               'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
+               'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+               "AREA:out_avg#$HalfGreen",
+               "AREA:inc_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:out_avg#$FullGreen:Written",
+               'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:out_max:MAX:%5.1lf%s Max,',
+               'GPRINT:out_avg:LAST:%5.1lf%s Last',
+               'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+               "LINE1:inc_avg#$FullBlue:Read   ",
+               'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:inc_max:MAX:%5.1lf%s Max,',
+               'GPRINT:inc_avg:LAST:%5.1lf%s Last',
+               'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l');
+       $GraphDefs['disk_merged'] = array(
+               '-v', 'Merged Ops/s', '--units=si',
+               'DEF:out_min={file}:write:MIN',
+               'DEF:out_avg={file}:write:AVERAGE',
+               'DEF:out_max={file}:write:MAX',
+               'DEF:inc_min={file}:read:MIN',
+               'DEF:inc_avg={file}:read:AVERAGE',
+               'DEF:inc_max={file}:read:MAX',
+               'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+               "AREA:out_avg#$HalfGreen",
+               "AREA:inc_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:out_avg#$FullGreen:Written",
+               'GPRINT:out_avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:out_max:MAX:%6.2lf Max,',
+               'GPRINT:out_avg:LAST:%6.2lf Last\l',
+               "LINE1:inc_avg#$FullBlue:Read   ",
+               'GPRINT:inc_avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:inc_max:MAX:%6.2lf Max,',
+               'GPRINT:inc_avg:LAST:%6.2lf Last\l');
+               $GraphDefs['disk_ops'] = array(
+               '-v', 'Ops/s', '--units=si',
+               'DEF:out_min={file}:write:MIN',
+               'DEF:out_avg={file}:write:AVERAGE',
+               'DEF:out_max={file}:write:MAX',
+               'DEF:inc_min={file}:read:MIN',
+               'DEF:inc_avg={file}:read:AVERAGE',
+               'DEF:inc_max={file}:read:MAX',
+               'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+               "AREA:out_avg#$HalfGreen",
+               "AREA:inc_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:out_avg#$FullGreen:Written",
+               'GPRINT:out_avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:out_max:MAX:%6.2lf Max,',
+               'GPRINT:out_avg:LAST:%6.2lf Last\l',
+               "LINE1:inc_avg#$FullBlue:Read   ",
+               'GPRINT:inc_avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:inc_max:MAX:%6.2lf Max,',
+               'GPRINT:inc_avg:LAST:%6.2lf Last\l');
+       $GraphDefs['disk_time'] = array(
+               '-v', 'Seconds/s',
+               'DEF:out_min_raw={file}:write:MIN',
+               'DEF:out_avg_raw={file}:write:AVERAGE',
+               'DEF:out_max_raw={file}:write:MAX',
+               'DEF:inc_min_raw={file}:read:MIN',
+               'DEF:inc_avg_raw={file}:read:AVERAGE',
+               'DEF:inc_max_raw={file}:read:MAX',
+               'CDEF:out_min=out_min_raw,1000,/',
+               'CDEF:out_avg=out_avg_raw,1000,/',
+               'CDEF:out_max=out_max_raw,1000,/',
+               'CDEF:inc_min=inc_min_raw,1000,/',
+               'CDEF:inc_avg=inc_avg_raw,1000,/',
+               'CDEF:inc_max=inc_max_raw,1000,/',
+               'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+               "AREA:out_avg#$HalfGreen",
+               "AREA:inc_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:out_avg#$FullGreen:Written",
+               'GPRINT:out_avg:AVERAGE:%5.1lf%ss Avg,',
+               'GPRINT:out_max:MAX:%5.1lf%ss Max,',
+               'GPRINT:out_avg:LAST:%5.1lf%ss Last\l',
+               "LINE1:inc_avg#$FullBlue:Read   ",
+               'GPRINT:inc_avg:AVERAGE:%5.1lf%ss Avg,',
+               'GPRINT:inc_max:MAX:%5.1lf%ss Max,',
+               'GPRINT:inc_avg:LAST:%5.1lf%ss Last\l');
+       $GraphDefs['dns_traffic'] = array(
+               'DEF:rsp_min_raw={file}:responses:MIN',
+               'DEF:rsp_avg_raw={file}:responses:AVERAGE',
+               'DEF:rsp_max_raw={file}:responses:MAX',
+               'DEF:qry_min_raw={file}:queries:MIN',
+               'DEF:qry_avg_raw={file}:queries:AVERAGE',
+               'DEF:qry_max_raw={file}:queries:MAX',
+               'CDEF:rsp_min=rsp_min_raw,8,*',
+               'CDEF:rsp_avg=rsp_avg_raw,8,*',
+               'CDEF:rsp_max=rsp_max_raw,8,*',
+               'CDEF:qry_min=qry_min_raw,8,*',
+               'CDEF:qry_avg=qry_avg_raw,8,*',
+               'CDEF:qry_max=qry_max_raw,8,*',
+               'CDEF:overlap=rsp_avg,qry_avg,GT,qry_avg,rsp_avg,IF',
+               'CDEF:mytime=rsp_avg_raw,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:rsp_avg_sample=rsp_avg_raw,UN,0,rsp_avg_raw,IF,sample_len,*',
+               'CDEF:rsp_avg_sum=PREV,UN,0,PREV,IF,rsp_avg_sample,+',
+               'CDEF:qry_avg_sample=qry_avg_raw,UN,0,qry_avg_raw,IF,sample_len,*',
+               'CDEF:qry_avg_sum=PREV,UN,0,PREV,IF,qry_avg_sample,+',
+               "AREA:rsp_avg#$HalfGreen",
+               "AREA:qry_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:rsp_avg#$FullGreen:Responses",
+               'GPRINT:rsp_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:rsp_max:MAX:%5.1lf%s Max,',
+               'GPRINT:rsp_avg:LAST:%5.1lf%s Last',
+               'GPRINT:rsp_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+               "LINE1:qry_avg#$FullBlue:Queries  ",
+//                     'GPRINT:qry_min:MIN:%5.1lf %s Min,',
+               'GPRINT:qry_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:qry_max:MAX:%5.1lf%s Max,',
+               'GPRINT:qry_avg:LAST:%5.1lf%s Last',
+               'GPRINT:qry_avg_sum:LAST:(ca. %5.1lf%sB Total)\l');
+       $GraphDefs['email_count'] = array(
+               '-v', 'Mails',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfMagenta",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullMagenta:Count ",
+               'GPRINT:min:MIN:%4.1lf Min,',
+               'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:max:MAX:%4.1lf Max,',
+               'GPRINT:avg:LAST:%4.1lf Last\l');
+       $GraphDefs['files'] = $GraphDefs['email_count'];
+       $GraphDefs['email_size'] = array(
+               '-v', 'Bytes',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfMagenta",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullMagenta:Count ",
+               'GPRINT:min:MIN:%4.1lf Min,',
+               'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:max:MAX:%4.1lf Max,',
+               'GPRINT:avg:LAST:%4.1lf Last\l');
+       $GraphDefs['bytes'] = $GraphDefs['email_size'];
+       $GraphDefs['spam_score'] = array(
+               '-v', 'Score',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Score ",
+               'GPRINT:min:MIN:%4.1lf Min,',
+               'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:max:MAX:%4.1lf Max,',
+               'GPRINT:avg:LAST:%4.1lf Last\l');
+       $GraphDefs['spam_check'] = array(
+               'DEF:avg={file}:hits:AVERAGE',
+               'DEF:min={file}:hits:MIN',
+               'DEF:max={file}:hits:MAX',
+               "AREA:max#$HalfMagenta",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullMagenta:Count ",
+               'GPRINT:min:MIN:%4.1lf Min,',
+               'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:max:MAX:%4.1lf Max,',
+               'GPRINT:avg:LAST:%4.1lf Last\l');
+       $GraphDefs['conntrack'] = array(
+               '-v', 'Entries',
+               'DEF:avg={file}:entropy:AVERAGE',
+               'DEF:min={file}:entropy:MIN',
+               'DEF:max={file}:entropy:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Count",
+               'GPRINT:min:MIN:%4.0lf Min,',
+               'GPRINT:avg:AVERAGE:%4.0lf Avg,',
+               'GPRINT:max:MAX:%4.0lf Max,',
+               'GPRINT:avg:LAST:%4.0lf Last\l');
+       $GraphDefs['entropy'] = array(
+               '-v', 'Bits',
+               'DEF:avg={file}:entropy:AVERAGE',
+               'DEF:min={file}:entropy:MIN',
+               'DEF:max={file}:entropy:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Bits",
+               'GPRINT:min:MIN:%4.0lfbit Min,',
+               'GPRINT:avg:AVERAGE:%4.0lfbit Avg,',
+               'GPRINT:max:MAX:%4.0lfbit Max,',
+               'GPRINT:avg:LAST:%4.0lfbit Last\l');
+       $GraphDefs['fanspeed'] = array(
+               '-v', 'RPM',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfMagenta",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullMagenta:RPM",
+               'GPRINT:min:MIN:%4.1lf Min,',
+               'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:max:MAX:%4.1lf Max,',
+               'GPRINT:avg:LAST:%4.1lf Last\l');
+       $GraphDefs['frequency'] = array(
+               '-v', 'Hertz',
+               'DEF:avg={file}:frequency:AVERAGE',
+               'DEF:min={file}:frequency:MIN',
+               'DEF:max={file}:frequency:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Frequency [Hz]",
+               'GPRINT:min:MIN:%4.1lf Min,',
+               'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:max:MAX:%4.1lf Max,',
+               'GPRINT:avg:LAST:%4.1lf Last\l');
+       $GraphDefs['frequency_offset'] = array( // NTPd
+               'DEF:ppm_avg={file}:ppm:AVERAGE',
+               'DEF:ppm_min={file}:ppm:MIN',
+               'DEF:ppm_max={file}:ppm:MAX',
+               "AREA:ppm_max#$HalfBlue",
+               "AREA:ppm_min#$Canvas",
+               "LINE1:ppm_avg#$FullBlue:{inst}",
+               'GPRINT:ppm_min:MIN:%5.2lf Min,',
+               'GPRINT:ppm_avg:AVERAGE:%5.2lf Avg,',
+               'GPRINT:ppm_max:MAX:%5.2lf Max,',
+               'GPRINT:ppm_avg:LAST:%5.2lf Last');
+       $GraphDefs['gauge'] = array(
+               '-v', 'Exec value',
+               'DEF:temp_avg={file}:value:AVERAGE',
+               'DEF:temp_min={file}:value:MIN',
+               'DEF:temp_max={file}:value:MAX',
+               "AREA:temp_max#$HalfBlue",
+               "AREA:temp_min#$Canvas",
+               "LINE1:temp_avg#$FullBlue:Exec value",
+               'GPRINT:temp_min:MIN:%6.2lf Min,',
+               'GPRINT:temp_avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:temp_max:MAX:%6.2lf Max,',
+               'GPRINT:temp_avg:LAST:%6.2lf Last\l');
+       $GraphDefs['hddtemp'] = array(
+               '-v', '°C',
+               'DEF:temp_avg={file}:value:AVERAGE',
+               'DEF:temp_min={file}:value:MIN',
+               'DEF:temp_max={file}:value:MAX',
+               "AREA:temp_max#$HalfRed",
+               "AREA:temp_min#$Canvas",
+               "LINE1:temp_avg#$FullRed:Temperature",
+               'GPRINT:temp_min:MIN:%4.1lf Min,',
+               'GPRINT:temp_avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:temp_max:MAX:%4.1lf Max,',
+               'GPRINT:temp_avg:LAST:%4.1lf Last\l');
+       $GraphDefs['humidity'] = array(
+               '-v', 'Percent',
+               'DEF:temp_avg={file}:value:AVERAGE',
+               'DEF:temp_min={file}:value:MIN',
+               'DEF:temp_max={file}:value:MAX',
+               "AREA:temp_max#$HalfGreen",
+               "AREA:temp_min#$Canvas",
+               "LINE1:temp_avg#$FullGreen:Temperature",
+               'GPRINT:temp_min:MIN:%4.1lf%% Min,',
+               'GPRINT:temp_avg:AVERAGE:%4.1lf%% Avg,',
+               'GPRINT:temp_max:MAX:%4.1lf%% Max,',
+               'GPRINT:temp_avg:LAST:%4.1lf%% Last\l');
+       $GraphDefs['if_errors'] = array(
+               '-v', 'Errors/s', '--units=si',
+               'DEF:tx_min={file}:tx:MIN',
+               'DEF:tx_avg={file}:tx:AVERAGE',
+               'DEF:tx_max={file}:tx:MAX',
+               'DEF:rx_min={file}:rx:MIN',
+               'DEF:rx_avg={file}:rx:AVERAGE',
+               'DEF:rx_max={file}:rx:MAX',
+               'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
+               'CDEF:mytime=tx_avg,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
+               'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
+               'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
+               'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
+               "AREA:tx_avg#$HalfGreen",
+               "AREA:rx_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:tx_avg#$FullGreen:TX",
+               'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:tx_max:MAX:%5.1lf%s Max,',
+               'GPRINT:tx_avg:LAST:%5.1lf%s Last',
+               'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
+               "LINE1:rx_avg#$FullBlue:RX",
+//                     'GPRINT:rx_min:MIN:%5.1lf %s Min,',
+               'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:rx_max:MAX:%5.1lf%s Max,',
+               'GPRINT:rx_avg:LAST:%5.1lf%s Last',
+               'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l');
+       $GraphDefs['if_collisions'] = array(
+               '-v', 'Collisions/s', '--units=si',
+               'DEF:min_raw={file}:value:MIN',
+               'DEF:avg_raw={file}:value:AVERAGE',
+               'DEF:max_raw={file}:value:MAX',
+               'CDEF:min=min_raw,8,*',
+               'CDEF:avg=avg_raw,8,*',
+               'CDEF:max=max_raw,8,*',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Collisions/s",
+               'GPRINT:min:MIN:%5.1lf %s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['if_dropped'] = array(
+               '-v', 'Packets/s', '--units=si',
+               'DEF:tx_min={file}:tx:MIN',
+               'DEF:tx_avg={file}:tx:AVERAGE',
+               'DEF:tx_max={file}:tx:MAX',
+               'DEF:rx_min={file}:rx:MIN',
+               'DEF:rx_avg={file}:rx:AVERAGE',
+               'DEF:rx_max={file}:rx:MAX',
+               'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
+               'CDEF:mytime=tx_avg,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
+               'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
+               'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
+               'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
+               "AREA:tx_avg#$HalfGreen",
+               "AREA:rx_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:tx_avg#$FullGreen:TX",
+               'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:tx_max:MAX:%5.1lf%s Max,',
+               'GPRINT:tx_avg:LAST:%5.1lf%s Last',
+               'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
+               "LINE1:rx_avg#$FullBlue:RX",
+//                     'GPRINT:rx_min:MIN:%5.1lf %s Min,',
+               'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:rx_max:MAX:%5.1lf%s Max,',
+               'GPRINT:rx_avg:LAST:%5.1lf%s Last',
+               'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l');
+       $GraphDefs['if_packets'] = array(
+               '-v', 'Packets/s', '--units=si',
+               'DEF:tx_min={file}:tx:MIN',
+               'DEF:tx_avg={file}:tx:AVERAGE',
+               'DEF:tx_max={file}:tx:MAX',
+               'DEF:rx_min={file}:rx:MIN',
+               'DEF:rx_avg={file}:rx:AVERAGE',
+               'DEF:rx_max={file}:rx:MAX',
+               'CDEF:overlap=tx_avg,rx_avg,GT,rx_avg,tx_avg,IF',
+               'CDEF:mytime=tx_avg,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:tx_avg_sample=tx_avg,UN,0,tx_avg,IF,sample_len,*',
+               'CDEF:tx_avg_sum=PREV,UN,0,PREV,IF,tx_avg_sample,+',
+               'CDEF:rx_avg_sample=rx_avg,UN,0,rx_avg,IF,sample_len,*',
+               'CDEF:rx_avg_sum=PREV,UN,0,PREV,IF,rx_avg_sample,+',
+               "AREA:tx_avg#$HalfGreen",
+               "AREA:rx_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:tx_avg#$FullGreen:TX",
+               'GPRINT:tx_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:tx_max:MAX:%5.1lf%s Max,',
+               'GPRINT:tx_avg:LAST:%5.1lf%s Last',
+               'GPRINT:tx_avg_sum:LAST:(ca. %4.0lf%s Total)\l',
+               "LINE1:rx_avg#$FullBlue:RX",
+//                     'GPRINT:rx_min:MIN:%5.1lf %s Min,',
+               'GPRINT:rx_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:rx_max:MAX:%5.1lf%s Max,',
+               'GPRINT:rx_avg:LAST:%5.1lf%s Last',
+               'GPRINT:rx_avg_sum:LAST:(ca. %4.0lf%s Total)\l');
+       $GraphDefs['if_rx_errors'] = array(
+               '-v', 'Errors/s', '--units=si',
+               'DEF:min={file}:value:MIN',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:max={file}:value:MAX',
+               'CDEF:mytime=avg,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:avg_sample=avg,UN,0,avg,IF,sample_len,*',
+               'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
+               "AREA:avg#$HalfBlue",
+               "LINE1:avg#$FullBlue:Errors/s",
+               'GPRINT:avg:AVERAGE:%3.1lf%s Avg,',
+               'GPRINT:max:MAX:%3.1lf%s Max,',
+               'GPRINT:avg:LAST:%3.1lf%s Last',
+               'GPRINT:avg_sum:LAST:(ca. %2.0lf%s Total)\l');
+       $GraphDefs['ipt_bytes'] = array(
+               '-v', 'Bits/s',
+               'DEF:min_raw={file}:value:MIN',
+               'DEF:avg_raw={file}:value:AVERAGE',
+               'DEF:max_raw={file}:value:MAX',
+               'CDEF:min=min_raw,8,*',
+               'CDEF:avg=avg_raw,8,*',
+               'CDEF:max=max_raw,8,*',
+               'CDEF:mytime=avg_raw,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*',
+               'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Bits/s",
+//                     'GPRINT:min:MIN:%5.1lf %s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last',
+               'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l');
+       $GraphDefs['ipt_packets'] = array(
+               '-v', 'Packets/s',
+               'DEF:min_raw={file}:value:MIN',
+               'DEF:avg_raw={file}:value:AVERAGE',
+               'DEF:max_raw={file}:value:MAX',
+               'CDEF:min=min_raw,8,*',
+               'CDEF:avg=avg_raw,8,*',
+               'CDEF:max=max_raw,8,*',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Packets/s",
+               'GPRINT:min:MIN:%5.1lf %s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['irq'] = array(
+               '-v', 'Issues/s',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Issues/s",
+               'GPRINT:min:MIN:%6.2lf Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:max:MAX:%6.2lf Max,',
+               'GPRINT:avg:LAST:%6.2lf Last\l');
+       $GraphDefs['load'] = array(
+               '-v', 'System load',
+               'DEF:s_avg={file}:shortterm:AVERAGE',
+               'DEF:s_min={file}:shortterm:MIN',
+               'DEF:s_max={file}:shortterm:MAX',
+               'DEF:m_avg={file}:midterm:AVERAGE',
+               'DEF:m_min={file}:midterm:MIN',
+               'DEF:m_max={file}:midterm:MAX',
+               'DEF:l_avg={file}:longterm:AVERAGE',
+               'DEF:l_min={file}:longterm:MIN',
+               'DEF:l_max={file}:longterm:MAX',
+               "AREA:s_max#$HalfGreen",
+               "AREA:s_min#$Canvas",
+               "LINE1:s_avg#$FullGreen: 1m average",
+               'GPRINT:s_min:MIN:%4.2lf Min,',
+               'GPRINT:s_avg:AVERAGE:%4.2lf Avg,',
+               'GPRINT:s_max:MAX:%4.2lf Max,',
+               'GPRINT:s_avg:LAST:%4.2lf Last\n',
+               "LINE1:m_avg#$FullBlue: 5m average",
+               'GPRINT:m_min:MIN:%4.2lf Min,',
+               'GPRINT:m_avg:AVERAGE:%4.2lf Avg,',
+               'GPRINT:m_max:MAX:%4.2lf Max,',
+               'GPRINT:m_avg:LAST:%4.2lf Last\n',
+               "LINE1:l_avg#$FullRed:15m average",
+               'GPRINT:l_min:MIN:%4.2lf Min,',
+               'GPRINT:l_avg:AVERAGE:%4.2lf Avg,',
+               'GPRINT:l_max:MAX:%4.2lf Max,',
+               'GPRINT:l_avg:LAST:%4.2lf Last');
+       $GraphDefs['load_percent'] = array(
+               'DEF:avg={file}:percent:AVERAGE',
+               'DEF:min={file}:percent:MIN',
+               'DEF:max={file}:percent:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Load",
+               'GPRINT:min:MIN:%5.1lf%s%% Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s%% Avg,',
+               'GPRINT:max:MAX:%5.1lf%s%% Max,',
+               'GPRINT:avg:LAST:%5.1lf%s%% Last\l');
+       $GraphDefs['mails'] = array(
+               'DEF:rawgood={file}:good:AVERAGE',
+               'DEF:rawspam={file}:spam:AVERAGE',
+               'CDEF:good=rawgood,UN,0,rawgood,IF',
+               'CDEF:spam=rawspam,UN,0,rawspam,IF',
+               'CDEF:negspam=spam,-1,*',
+               "AREA:good#$HalfGreen",
+               "LINE1:good#$FullGreen:Good mails",
+               'GPRINT:good:AVERAGE:%4.1lf Avg,',
+               'GPRINT:good:MAX:%4.1lf Max,',
+               'GPRINT:good:LAST:%4.1lf Last\n',
+               "AREA:negspam#$HalfRed",
+               "LINE1:negspam#$FullRed:Spam mails",
+               'GPRINT:spam:AVERAGE:%4.1lf Avg,',
+               'GPRINT:spam:MAX:%4.1lf Max,',
+               'GPRINT:spam:LAST:%4.1lf Last',
+               'HRULE:0#000000');
+       $GraphDefs['memory'] = array(
+               '-b', '1024', '-v', 'Bytes',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Memory",
+               'GPRINT:min:MIN:%5.1lf%sbyte Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%sbyte Avg,',
+               'GPRINT:max:MAX:%5.1lf%sbyte Max,',
+               'GPRINT:avg:LAST:%5.1lf%sbyte Last\l');
+       $GraphDefs['old_memory'] = array(
+               'DEF:used_avg={file}:used:AVERAGE',
+               'DEF:free_avg={file}:free:AVERAGE',
+               'DEF:buffers_avg={file}:buffers:AVERAGE',
+               'DEF:cached_avg={file}:cached:AVERAGE',
+               'DEF:used_min={file}:used:MIN',
+               'DEF:free_min={file}:free:MIN',
+               'DEF:buffers_min={file}:buffers:MIN',
+               'DEF:cached_min={file}:cached:MIN',
+               'DEF:used_max={file}:used:MAX',
+               'DEF:free_max={file}:free:MAX',
+               'DEF:buffers_max={file}:buffers:MAX',
+               'DEF:cached_max={file}:cached:MAX',
+               'CDEF:cached_avg_nn=cached_avg,UN,0,cached_avg,IF',
+               'CDEF:buffers_avg_nn=buffers_avg,UN,0,buffers_avg,IF',
+               'CDEF:free_cached_buffers_used=free_avg,cached_avg_nn,+,buffers_avg_nn,+,used_avg,+',
+               'CDEF:cached_buffers_used=cached_avg,buffers_avg_nn,+,used_avg,+',
+               'CDEF:buffers_used=buffers_avg,used_avg,+',
+               "AREA:free_cached_buffers_used#$HalfGreen",
+               "AREA:cached_buffers_used#$HalfBlue",
+               "AREA:buffers_used#$HalfYellow",
+               "AREA:used_avg#$HalfRed",
+               "LINE1:free_cached_buffers_used#$FullGreen:Free        ",
+               'GPRINT:free_min:MIN:%5.1lf%s Min,',
+               'GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:free_max:MAX:%5.1lf%s Max,',
+               'GPRINT:free_avg:LAST:%5.1lf%s Last\n',
+               "LINE1:cached_buffers_used#$FullBlue:Page cache  ",
+               'GPRINT:cached_min:MIN:%5.1lf%s Min,',
+               'GPRINT:cached_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:cached_max:MAX:%5.1lf%s Max,',
+               'GPRINT:cached_avg:LAST:%5.1lf%s Last\n',
+               "LINE1:buffers_used#$FullYellow:Buffer cache",
+               'GPRINT:buffers_min:MIN:%5.1lf%s Min,',
+               'GPRINT:buffers_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:buffers_max:MAX:%5.1lf%s Max,',
+               'GPRINT:buffers_avg:LAST:%5.1lf%s Last\n',
+               "LINE1:used_avg#$FullRed:Used        ",
+               'GPRINT:used_min:MIN:%5.1lf%s Min,',
+               'GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:used_max:MAX:%5.1lf%s Max,',
+               'GPRINT:used_avg:LAST:%5.1lf%s Last');
+       $GraphDefs['mysql_commands'] = array(
+               '-v', 'Issues/s',
+               "DEF:val_avg={file}:value:AVERAGE",
+               "DEF:val_min={file}:value:MIN",
+               "DEF:val_max={file}:value:MAX",
+               "AREA:val_max#$HalfBlue",
+               "AREA:val_min#$Canvas",
+               "LINE1:val_avg#$FullBlue:Issues/s",
+               'GPRINT:val_min:MIN:%5.2lf Min,',
+               'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
+               'GPRINT:val_max:MAX:%5.2lf Max,',
+               'GPRINT:val_avg:LAST:%5.2lf Last');
+       $GraphDefs['mysql_handler'] = array(
+               '-v', 'Issues/s',
+               "DEF:val_avg={file}:value:AVERAGE",
+               "DEF:val_min={file}:value:MIN",
+               "DEF:val_max={file}:value:MAX",
+               "AREA:val_max#$HalfBlue",
+               "AREA:val_min#$Canvas",
+               "LINE1:val_avg#$FullBlue:Issues/s",
+               'GPRINT:val_min:MIN:%5.2lf Min,',
+               'GPRINT:val_avg:AVERAGE:%5.2lf Avg,',
+               'GPRINT:val_max:MAX:%5.2lf Max,',
+               'GPRINT:val_avg:LAST:%5.2lf Last');
+       $GraphDefs['mysql_octets'] = array(
+               '-v', 'Bits/s',
+               'DEF:out_min={file}:tx:MIN',
+               'DEF:out_avg={file}:tx:AVERAGE',
+               'DEF:out_max={file}:tx:MAX',
+               'DEF:inc_min={file}:rx:MIN',
+               'DEF:inc_avg={file}:rx:AVERAGE',
+               'DEF:inc_max={file}:rx:MAX',
+               'CDEF:mytime=out_avg,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
+               'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+               'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
+               'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+               'CDEF:out_bit_min=out_min,8,*',
+               'CDEF:out_bit_avg=out_avg,8,*',
+               'CDEF:out_bit_max=out_max,8,*',
+               'CDEF:inc_bit_min=inc_min,8,*',
+               'CDEF:inc_bit_avg=inc_avg,8,*',
+               'CDEF:inc_bit_max=inc_max,8,*',
+               'CDEF:overlap=out_bit_avg,inc_bit_avg,GT,inc_bit_avg,out_bit_avg,IF',
+               "AREA:out_bit_avg#$HalfGreen",
+               "AREA:inc_bit_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:out_bit_avg#$FullGreen:Written",
+               'GPRINT:out_bit_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:out_bit_max:MAX:%5.1lf%s Max,',
+               'GPRINT:out_bit_avg:LAST:%5.1lf%s Last',
+               'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+               "LINE1:inc_bit_avg#$FullBlue:Read   ",
+               'GPRINT:inc_bit_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:inc_bit_max:MAX:%5.1lf%s Max,',
+               'GPRINT:inc_bit_avg:LAST:%5.1lf%s Last',
+               'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l');
+       $GraphDefs['mysql_qcache'] = array(
+               '-v', 'Queries/s',
+               "DEF:hits_min={file}:hits:MIN",
+               "DEF:hits_avg={file}:hits:AVERAGE",
+               "DEF:hits_max={file}:hits:MAX",
+               "DEF:inserts_min={file}:inserts:MIN",
+               "DEF:inserts_avg={file}:inserts:AVERAGE",
+               "DEF:inserts_max={file}:inserts:MAX",
+               "DEF:not_cached_min={file}:not_cached:MIN",
+               "DEF:not_cached_avg={file}:not_cached:AVERAGE",
+               "DEF:not_cached_max={file}:not_cached:MAX",
+               "DEF:lowmem_prunes_min={file}:lowmem_prunes:MIN",
+               "DEF:lowmem_prunes_avg={file}:lowmem_prunes:AVERAGE",
+               "DEF:lowmem_prunes_max={file}:lowmem_prunes:MAX",
+               "DEF:queries_min={file}:queries_in_cache:MIN",
+               "DEF:queries_avg={file}:queries_in_cache:AVERAGE",
+               "DEF:queries_max={file}:queries_in_cache:MAX",
+               "CDEF:unknown=queries_avg,UNKN,+",
+               "CDEF:not_cached_agg=hits_avg,inserts_avg,+,not_cached_avg,+",
+               "CDEF:inserts_agg=hits_avg,inserts_avg,+",
+               "CDEF:hits_agg=hits_avg",
+               "AREA:not_cached_agg#$HalfYellow",
+               "AREA:inserts_agg#$HalfBlue",
+               "AREA:hits_agg#$HalfGreen",
+               "LINE1:not_cached_agg#$FullYellow:Not Cached      ",
+               'GPRINT:not_cached_min:MIN:%5.2lf Min,',
+               'GPRINT:not_cached_avg:AVERAGE:%5.2lf Avg,',
+               'GPRINT:not_cached_max:MAX:%5.2lf Max,',
+               'GPRINT:not_cached_avg:LAST:%5.2lf Last\l',
+               "LINE1:inserts_agg#$FullBlue:Inserts         ",
+               'GPRINT:inserts_min:MIN:%5.2lf Min,',
+               'GPRINT:inserts_avg:AVERAGE:%5.2lf Avg,',
+               'GPRINT:inserts_max:MAX:%5.2lf Max,',
+               'GPRINT:inserts_avg:LAST:%5.2lf Last\l',
+               "LINE1:hits_agg#$FullGreen:Hits            ",
+               'GPRINT:hits_min:MIN:%5.2lf Min,',
+               'GPRINT:hits_avg:AVERAGE:%5.2lf Avg,',
+               'GPRINT:hits_max:MAX:%5.2lf Max,',
+               'GPRINT:hits_avg:LAST:%5.2lf Last\l',
+               "LINE1:lowmem_prunes_avg#$FullRed:Lowmem Prunes   ",
+               'GPRINT:lowmem_prunes_min:MIN:%5.2lf Min,',
+               'GPRINT:lowmem_prunes_avg:AVERAGE:%5.2lf Avg,',
+               'GPRINT:lowmem_prunes_max:MAX:%5.2lf Max,',
+               'GPRINT:lowmem_prunes_avg:LAST:%5.2lf Last\l',
+               "LINE1:unknown#$Canvas:Queries in cache",
+               'GPRINT:queries_min:MIN:%5.0lf Min,',
+               'GPRINT:queries_avg:AVERAGE:%5.0lf Avg,',
+               'GPRINT:queries_max:MAX:%5.0lf Max,',
+               'GPRINT:queries_avg:LAST:%5.0lf Last\l');
+       $GraphDefs['mysql_threads'] = array(
+               '-v', 'Threads',
+               "DEF:running_min={file}:running:MIN",
+               "DEF:running_avg={file}:running:AVERAGE",
+               "DEF:running_max={file}:running:MAX",
+               "DEF:connected_min={file}:connected:MIN",
+               "DEF:connected_avg={file}:connected:AVERAGE",
+               "DEF:connected_max={file}:connected:MAX",
+               "DEF:cached_min={file}:cached:MIN",
+               "DEF:cached_avg={file}:cached:AVERAGE",
+               "DEF:cached_max={file}:cached:MAX",
+               "DEF:created_min={file}:created:MIN",
+               "DEF:created_avg={file}:created:AVERAGE",
+               "DEF:created_max={file}:created:MAX",
+               "CDEF:unknown=created_avg,UNKN,+",
+               "CDEF:cached_agg=connected_avg,cached_avg,+",
+               "AREA:cached_agg#$HalfGreen",
+               "AREA:connected_avg#$HalfBlue",
+               "AREA:running_avg#$HalfRed",
+               "LINE1:cached_agg#$FullGreen:Cached   ",
+               'GPRINT:cached_min:MIN:%5.1lf Min,',
+               'GPRINT:cached_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:cached_max:MAX:%5.1lf Max,',
+               'GPRINT:cached_avg:LAST:%5.1lf Last\l',
+               "LINE1:connected_avg#$FullBlue:Connected",
+               'GPRINT:connected_min:MIN:%5.1lf Min,',
+               'GPRINT:connected_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:connected_max:MAX:%5.1lf Max,',
+               'GPRINT:connected_avg:LAST:%5.1lf Last\l',
+               "LINE1:running_avg#$FullRed:Running  ",
+               'GPRINT:running_min:MIN:%5.1lf Min,',
+               'GPRINT:running_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:running_max:MAX:%5.1lf Max,',
+               'GPRINT:running_avg:LAST:%5.1lf Last\l',
+               "LINE1:unknown#$Canvas:Created  ",
+               'GPRINT:created_min:MIN:%5.0lf Min,',
+               'GPRINT:created_avg:AVERAGE:%5.0lf Avg,',
+               'GPRINT:created_max:MAX:%5.0lf Max,',
+               'GPRINT:created_avg:LAST:%5.0lf Last\l');
+       $GraphDefs['nfs_procedure'] = array(
+               '-v', 'Issues/s',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Issues/s",
+               'GPRINT:min:MIN:%6.2lf Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:max:MAX:%6.2lf Max,',
+               'GPRINT:avg:LAST:%6.2lf Last\l');
+       $GraphDefs['nfs3_procedures'] = array(
+               "DEF:null_avg={file}:null:AVERAGE",
+               "DEF:getattr_avg={file}:getattr:AVERAGE",
+               "DEF:setattr_avg={file}:setattr:AVERAGE",
+               "DEF:lookup_avg={file}:lookup:AVERAGE",
+               "DEF:access_avg={file}:access:AVERAGE",
+               "DEF:readlink_avg={file}:readlink:AVERAGE",
+               "DEF:read_avg={file}:read:AVERAGE",
+               "DEF:write_avg={file}:write:AVERAGE",
+               "DEF:create_avg={file}:create:AVERAGE",
+               "DEF:mkdir_avg={file}:mkdir:AVERAGE",
+               "DEF:symlink_avg={file}:symlink:AVERAGE",
+               "DEF:mknod_avg={file}:mknod:AVERAGE",
+               "DEF:remove_avg={file}:remove:AVERAGE",
+               "DEF:rmdir_avg={file}:rmdir:AVERAGE",
+               "DEF:rename_avg={file}:rename:AVERAGE",
+               "DEF:link_avg={file}:link:AVERAGE",
+               "DEF:readdir_avg={file}:readdir:AVERAGE",
+               "DEF:readdirplus_avg={file}:readdirplus:AVERAGE",
+               "DEF:fsstat_avg={file}:fsstat:AVERAGE",
+               "DEF:fsinfo_avg={file}:fsinfo:AVERAGE",
+               "DEF:pathconf_avg={file}:pathconf:AVERAGE",
+               "DEF:commit_avg={file}:commit:AVERAGE",
+               "DEF:null_max={file}:null:MAX",
+               "DEF:getattr_max={file}:getattr:MAX",
+               "DEF:setattr_max={file}:setattr:MAX",
+               "DEF:lookup_max={file}:lookup:MAX",
+               "DEF:access_max={file}:access:MAX",
+               "DEF:readlink_max={file}:readlink:MAX",
+               "DEF:read_max={file}:read:MAX",
+               "DEF:write_max={file}:write:MAX",
+               "DEF:create_max={file}:create:MAX",
+               "DEF:mkdir_max={file}:mkdir:MAX",
+               "DEF:symlink_max={file}:symlink:MAX",
+               "DEF:mknod_max={file}:mknod:MAX",
+               "DEF:remove_max={file}:remove:MAX",
+               "DEF:rmdir_max={file}:rmdir:MAX",
+               "DEF:rename_max={file}:rename:MAX",
+               "DEF:link_max={file}:link:MAX",
+               "DEF:readdir_max={file}:readdir:MAX",
+               "DEF:readdirplus_max={file}:readdirplus:MAX",
+               "DEF:fsstat_max={file}:fsstat:MAX",
+               "DEF:fsinfo_max={file}:fsinfo:MAX",
+               "DEF:pathconf_max={file}:pathconf:MAX",
+               "DEF:commit_max={file}:commit:MAX",
+               "CDEF:other_avg=null_avg,readlink_avg,create_avg,mkdir_avg,symlink_avg,mknod_avg,remove_avg,rmdir_avg,rename_avg,link_avg,readdir_avg,readdirplus_avg,fsstat_avg,fsinfo_avg,pathconf_avg,+,+,+,+,+,+,+,+,+,+,+,+,+,+",
+               "CDEF:other_max=null_max,readlink_max,create_max,mkdir_max,symlink_max,mknod_max,remove_max,rmdir_max,rename_max,link_max,readdir_max,readdirplus_max,fsstat_max,fsinfo_max,pathconf_max,+,+,+,+,+,+,+,+,+,+,+,+,+,+",
+               "CDEF:stack_read=read_avg",
+               "CDEF:stack_getattr=stack_read,getattr_avg,+",
+               "CDEF:stack_access=stack_getattr,access_avg,+",
+               "CDEF:stack_lookup=stack_access,lookup_avg,+",
+               "CDEF:stack_write=stack_lookup,write_avg,+",
+               "CDEF:stack_commit=stack_write,commit_avg,+",
+               "CDEF:stack_setattr=stack_commit,setattr_avg,+",
+               "CDEF:stack_other=stack_setattr,other_avg,+",
+               "AREA:stack_other#$HalfRed",
+               "AREA:stack_setattr#$HalfGreen",
+               "AREA:stack_commit#$HalfYellow",
+               "AREA:stack_write#$HalfGreen",
+               "AREA:stack_lookup#$HalfBlue",
+               "AREA:stack_access#$HalfMagenta",
+               "AREA:stack_getattr#$HalfCyan",
+               "AREA:stack_read#$HalfBlue",
+               "LINE1:stack_other#$FullRed:Other  ",
+               'GPRINT:other_max:MAX:%5.1lf Max,',
+               'GPRINT:other_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:other_avg:LAST:%5.1lf Last\l',
+               "LINE1:stack_setattr#$FullGreen:setattr",
+               'GPRINT:setattr_max:MAX:%5.1lf Max,',
+               'GPRINT:setattr_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:setattr_avg:LAST:%5.1lf Last\l',
+               "LINE1:stack_commit#$FullYellow:commit ",
+               'GPRINT:commit_max:MAX:%5.1lf Max,',
+               'GPRINT:commit_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:commit_avg:LAST:%5.1lf Last\l',
+               "LINE1:stack_write#$FullGreen:write  ",
+               'GPRINT:write_max:MAX:%5.1lf Max,',
+               'GPRINT:write_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:write_avg:LAST:%5.1lf Last\l',
+               "LINE1:stack_lookup#$FullBlue:lookup ",
+               'GPRINT:lookup_max:MAX:%5.1lf Max,',
+               'GPRINT:lookup_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:lookup_avg:LAST:%5.1lf Last\l',
+               "LINE1:stack_access#$FullMagenta:access ",
+               'GPRINT:access_max:MAX:%5.1lf Max,',
+               'GPRINT:access_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:access_avg:LAST:%5.1lf Last\l',
+               "LINE1:stack_getattr#$FullCyan:getattr",
+               'GPRINT:getattr_max:MAX:%5.1lf Max,',
+               'GPRINT:getattr_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:getattr_avg:LAST:%5.1lf Last\l',
+               "LINE1:stack_read#$FullBlue:read   ",
+               'GPRINT:read_max:MAX:%5.1lf Max,',
+               'GPRINT:read_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:read_avg:LAST:%5.1lf Last\l');
+       $GraphDefs['opcode'] = array(
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Queries/s",
+               'GPRINT:min:MIN:%9.3lf Min,',
+               'GPRINT:avg:AVERAGE:%9.3lf Average,',
+               'GPRINT:max:MAX:%9.3lf Max,',
+               'GPRINT:avg:LAST:%9.3lf Last\l');
+       $GraphDefs['partition'] = array(
+               "DEF:rbyte_avg={file}:rbytes:AVERAGE",
+               "DEF:rbyte_min={file}:rbytes:MIN",
+               "DEF:rbyte_max={file}:rbytes:MAX",
+               "DEF:wbyte_avg={file}:wbytes:AVERAGE",
+               "DEF:wbyte_min={file}:wbytes:MIN",
+               "DEF:wbyte_max={file}:wbytes:MAX",
+               'CDEF:overlap=wbyte_avg,rbyte_avg,GT,rbyte_avg,wbyte_avg,IF',
+               "AREA:wbyte_avg#$HalfGreen",
+               "AREA:rbyte_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",    "LINE1:wbyte_avg#$FullGreen:Write",
+               'GPRINT:wbyte_min:MIN:%5.1lf%s Min,',
+               'GPRINT:wbyte_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:wbyte_max:MAX:%5.1lf%s Max,',
+               'GPRINT:wbyte_avg:LAST:%5.1lf%s Last\l',
+               "LINE1:rbyte_avg#$FullBlue:Read ",
+               'GPRINT:rbyte_min:MIN:%5.1lf%s Min,',
+               'GPRINT:rbyte_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:rbyte_max:MAX:%5.1lf%s Max,',
+               'GPRINT:rbyte_avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['percent'] = array(
+               '-v', 'Percent',
+               'DEF:avg={file}:percent:AVERAGE',
+               'DEF:min={file}:percent:MIN',
+               'DEF:max={file}:percent:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Percent",
+               'GPRINT:min:MIN:%5.1lf%% Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%% Avg,',
+               'GPRINT:max:MAX:%5.1lf%% Max,',
+               'GPRINT:avg:LAST:%5.1lf%% Last\l');
+       $GraphDefs['ping'] = array(
+               'DEF:ping_avg={file}:ping:AVERAGE',
+               'DEF:ping_min={file}:ping:MIN',
+               'DEF:ping_max={file}:ping:MAX',
+               "AREA:ping_max#$HalfBlue",
+               "AREA:ping_min#$Canvas",
+               "LINE1:ping_avg#$FullBlue:Ping",
+               'GPRINT:ping_min:MIN:%4.1lf ms Min,',
+               'GPRINT:ping_avg:AVERAGE:%4.1lf ms Avg,',
+               'GPRINT:ping_max:MAX:%4.1lf ms Max,',
+               'GPRINT:ping_avg:LAST:%4.1lf ms Last');
+       $GraphDefs['power'] = array(
+               '-v', 'Watt',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Watt",
+               'GPRINT:min:MIN:%5.1lf%sW Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%sW Avg,',
+               'GPRINT:max:MAX:%5.1lf%sW Max,',
+               'GPRINT:avg:LAST:%5.1lf%sW Last\l');
+       $GraphDefs['processes'] = array(
+               "DEF:running_avg={file}:running:AVERAGE",
+               "DEF:running_min={file}:running:MIN",
+               "DEF:running_max={file}:running:MAX",
+               "DEF:sleeping_avg={file}:sleeping:AVERAGE",
+               "DEF:sleeping_min={file}:sleeping:MIN",
+               "DEF:sleeping_max={file}:sleeping:MAX",
+               "DEF:zombies_avg={file}:zombies:AVERAGE",
+               "DEF:zombies_min={file}:zombies:MIN",
+               "DEF:zombies_max={file}:zombies:MAX",
+               "DEF:stopped_avg={file}:stopped:AVERAGE",
+               "DEF:stopped_min={file}:stopped:MIN",
+               "DEF:stopped_max={file}:stopped:MAX",
+               "DEF:paging_avg={file}:paging:AVERAGE",
+               "DEF:paging_min={file}:paging:MIN",
+               "DEF:paging_max={file}:paging:MAX",
+               "DEF:blocked_avg={file}:blocked:AVERAGE",
+               "DEF:blocked_min={file}:blocked:MIN",
+               "DEF:blocked_max={file}:blocked:MAX",
+               'CDEF:paging_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,blocked_avg,paging_avg,+,+,+,+,+',
+               'CDEF:blocked_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,blocked_avg,+,+,+,+',
+               'CDEF:zombies_acc=sleeping_avg,running_avg,stopped_avg,zombies_avg,+,+,+',
+               'CDEF:stopped_acc=sleeping_avg,running_avg,stopped_avg,+,+',
+               'CDEF:running_acc=sleeping_avg,running_avg,+',
+               'CDEF:sleeping_acc=sleeping_avg',
+               "AREA:paging_acc#$HalfYellow",
+               "AREA:blocked_acc#$HalfCyan",
+               "AREA:zombies_acc#$HalfRed",
+               "AREA:stopped_acc#$HalfMagenta",
+               "AREA:running_acc#$HalfGreen",
+               "AREA:sleeping_acc#$HalfBlue",
+               "LINE1:paging_acc#$FullYellow:Paging  ",
+               'GPRINT:paging_min:MIN:%5.1lf Min,',
+               'GPRINT:paging_avg:AVERAGE:%5.1lf Average,',
+               'GPRINT:paging_max:MAX:%5.1lf Max,',
+               'GPRINT:paging_avg:LAST:%5.1lf Last\l',
+               "LINE1:blocked_acc#$FullCyan:Blocked ",
+               'GPRINT:blocked_min:MIN:%5.1lf Min,',
+               'GPRINT:blocked_avg:AVERAGE:%5.1lf Average,',
+               'GPRINT:blocked_max:MAX:%5.1lf Max,',
+               'GPRINT:blocked_avg:LAST:%5.1lf Last\l',
+               "LINE1:zombies_acc#$FullRed:Zombies ",
+               'GPRINT:zombies_min:MIN:%5.1lf Min,',
+               'GPRINT:zombies_avg:AVERAGE:%5.1lf Average,',
+               'GPRINT:zombies_max:MAX:%5.1lf Max,',
+               'GPRINT:zombies_avg:LAST:%5.1lf Last\l',
+               "LINE1:stopped_acc#$FullMagenta:Stopped ",
+               'GPRINT:stopped_min:MIN:%5.1lf Min,',
+               'GPRINT:stopped_avg:AVERAGE:%5.1lf Average,',
+               'GPRINT:stopped_max:MAX:%5.1lf Max,',
+               'GPRINT:stopped_avg:LAST:%5.1lf Last\l',
+               "LINE1:running_acc#$FullGreen:Running ",
+               'GPRINT:running_min:MIN:%5.1lf Min,',
+               'GPRINT:running_avg:AVERAGE:%5.1lf Average,',
+               'GPRINT:running_max:MAX:%5.1lf Max,',
+               'GPRINT:running_avg:LAST:%5.1lf Last\l',
+               "LINE1:sleeping_acc#$FullBlue:Sleeping",
+               'GPRINT:sleeping_min:MIN:%5.1lf Min,',
+               'GPRINT:sleeping_avg:AVERAGE:%5.1lf Average,',
+               'GPRINT:sleeping_max:MAX:%5.1lf Max,',
+               'GPRINT:sleeping_avg:LAST:%5.1lf Last\l');
+       $GraphDefs['ps_count'] = array(
+               '-v', 'Processes',
+               'DEF:procs_avg={file}:processes:AVERAGE',
+               'DEF:procs_min={file}:processes:MIN',
+               'DEF:procs_max={file}:processes:MAX',
+               'DEF:thrds_avg={file}:threads:AVERAGE',
+               'DEF:thrds_min={file}:threads:MIN',
+               'DEF:thrds_max={file}:threads:MAX',
+               "AREA:thrds_avg#$HalfBlue",
+               "AREA:procs_avg#$HalfRed",
+               "LINE1:thrds_avg#$FullBlue:Threads  ",
+               'GPRINT:thrds_min:MIN:%5.1lf Min,',
+               'GPRINT:thrds_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:thrds_max:MAX:%5.1lf Max,',
+               'GPRINT:thrds_avg:LAST:%5.1lf Last\l',
+               "LINE1:procs_avg#$FullRed:Processes",
+               'GPRINT:procs_min:MIN:%5.1lf Min,',
+               'GPRINT:procs_avg:AVERAGE:%5.1lf Avg,',
+               'GPRINT:procs_max:MAX:%5.1lf Max,',
+               'GPRINT:procs_avg:LAST:%5.1lf Last\l');
+       $GraphDefs['ps_cputime'] = array(
+               '-v', 'Jiffies',
+               'DEF:user_avg_raw={file}:user:AVERAGE',
+               'DEF:user_min_raw={file}:user:MIN',
+               'DEF:user_max_raw={file}:user:MAX',
+               'DEF:syst_avg_raw={file}:syst:AVERAGE',
+               'DEF:syst_min_raw={file}:syst:MIN',
+               'DEF:syst_max_raw={file}:syst:MAX',
+               'CDEF:user_avg=user_avg_raw,1000000,/',
+               'CDEF:user_min=user_min_raw,1000000,/',
+               'CDEF:user_max=user_max_raw,1000000,/',
+               'CDEF:syst_avg=syst_avg_raw,1000000,/',
+               'CDEF:syst_min=syst_min_raw,1000000,/',
+               'CDEF:syst_max=syst_max_raw,1000000,/',
+               'CDEF:user_syst=syst_avg,UN,0,syst_avg,IF,user_avg,+',
+               "AREA:user_syst#$HalfBlue",
+               "AREA:syst_avg#$HalfRed",
+               "LINE1:user_syst#$FullBlue:User  ",
+               'GPRINT:user_min:MIN:%5.1lf%s Min,',
+               'GPRINT:user_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:user_max:MAX:%5.1lf%s Max,',
+               'GPRINT:user_avg:LAST:%5.1lf%s Last\l',
+               "LINE1:syst_avg#$FullRed:System",
+               'GPRINT:syst_min:MIN:%5.1lf%s Min,',
+               'GPRINT:syst_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:syst_max:MAX:%5.1lf%s Max,',
+               'GPRINT:syst_avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['ps_pagefaults'] = array(
+               '-v', 'Pagefaults/s',
+               'DEF:minor_avg={file}:minflt:AVERAGE',
+               'DEF:minor_min={file}:minflt:MIN',
+               'DEF:minor_max={file}:minflt:MAX',
+               'DEF:major_avg={file}:majflt:AVERAGE',
+               'DEF:major_min={file}:majflt:MIN',
+               'DEF:major_max={file}:majflt:MAX',
+               'CDEF:minor_major=major_avg,UN,0,major_avg,IF,minor_avg,+',
+               "AREA:minor_major#$HalfBlue",
+               "AREA:major_avg#$HalfRed",
+               "LINE1:minor_major#$FullBlue:Minor",
+               'GPRINT:minor_min:MIN:%5.1lf%s Min,',
+               'GPRINT:minor_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:minor_max:MAX:%5.1lf%s Max,',
+               'GPRINT:minor_avg:LAST:%5.1lf%s Last\l',
+               "LINE1:major_avg#$FullRed:Major",
+               'GPRINT:major_min:MIN:%5.1lf%s Min,',
+               'GPRINT:major_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:major_max:MAX:%5.1lf%s Max,',
+               'GPRINT:major_avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['ps_rss'] = array(
+               '-v', 'Bytes',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:avg#$HalfBlue",
+               "LINE1:avg#$FullBlue:RSS",
+               'GPRINT:min:MIN:%5.1lf%s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['ps_state'] = array(
+               '-v', 'Processes',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Processes",
+               'GPRINT:min:MIN:%6.2lf Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+               'GPRINT:max:MAX:%6.2lf Max,',
+               'GPRINT:avg:LAST:%6.2lf Last\l');
+       $GraphDefs['qtype'] = array(
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Queries/s",
+               'GPRINT:min:MIN:%9.3lf Min,',
+               'GPRINT:avg:AVERAGE:%9.3lf Average,',
+               'GPRINT:max:MAX:%9.3lf Max,',
+               'GPRINT:avg:LAST:%9.3lf Last\l');
+       $GraphDefs['rcode'] = array(
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Queries/s",
+               'GPRINT:min:MIN:%9.3lf Min,',
+               'GPRINT:avg:AVERAGE:%9.3lf Average,',
+               'GPRINT:max:MAX:%9.3lf Max,',
+               'GPRINT:avg:LAST:%9.3lf Last\l');
+       $GraphDefs['swap'] = array(
+               '-v', 'Bytes', '-b', '1024',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Bytes",
+               'GPRINT:min:MIN:%6.2lf%sByte Min,',
+               'GPRINT:avg:AVERAGE:%6.2lf%sByte Avg,',
+               'GPRINT:max:MAX:%6.2lf%sByte Max,',
+               'GPRINT:avg:LAST:%6.2lf%sByte Last\l');
+       $GraphDefs['old_swap'] = array(
+               'DEF:used_avg={file}:used:AVERAGE',
+               'DEF:used_min={file}:used:MIN',
+               'DEF:used_max={file}:used:MAX',
+               'DEF:free_avg={file}:free:AVERAGE',
+               'DEF:free_min={file}:free:MIN',
+               'DEF:free_max={file}:free:MAX',
+               'DEF:cach_avg={file}:cached:AVERAGE',
+               'DEF:cach_min={file}:cached:MIN',
+               'DEF:cach_max={file}:cached:MAX',
+               'DEF:resv_avg={file}:resv:AVERAGE',
+               'DEF:resv_min={file}:resv:MIN',
+               'DEF:resv_max={file}:resv:MAX',
+               'CDEF:cach_avg_notnull=cach_avg,UN,0,cach_avg,IF',
+               'CDEF:resv_avg_notnull=resv_avg,UN,0,resv_avg,IF',
+               'CDEF:used_acc=used_avg',
+               'CDEF:resv_acc=used_acc,resv_avg_notnull,+',
+               'CDEF:cach_acc=resv_acc,cach_avg_notnull,+',
+               'CDEF:free_acc=cach_acc,free_avg,+',
+               "AREA:free_acc#$HalfGreen",
+               "AREA:cach_acc#$HalfBlue",
+               "AREA:resv_acc#$HalfYellow",
+               "AREA:used_acc#$HalfRed",
+               "LINE1:free_acc#$FullGreen:Free    ",
+               'GPRINT:free_min:MIN:%5.1lf%s Min,',
+               'GPRINT:free_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:free_max:MAX:%5.1lf%s Max,',
+               'GPRINT:free_avg:LAST:%5.1lf%s Last\n',
+               "LINE1:cach_acc#$FullBlue:Cached  ",
+               'GPRINT:cach_min:MIN:%5.1lf%s Min,',
+               'GPRINT:cach_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:cach_max:MAX:%5.1lf%s Max,',
+               'GPRINT:cach_avg:LAST:%5.1lf%s Last\l',
+               "LINE1:resv_acc#$FullYellow:Reserved",
+               'GPRINT:resv_min:MIN:%5.1lf%s Min,',
+               'GPRINT:resv_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:resv_max:MAX:%5.1lf%s Max,',
+               'GPRINT:resv_avg:LAST:%5.1lf%s Last\n',
+               "LINE1:used_acc#$FullRed:Used    ",
+               'GPRINT:used_min:MIN:%5.1lf%s Min,',
+               'GPRINT:used_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:used_max:MAX:%5.1lf%s Max,',
+               'GPRINT:used_avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['tcp_connections'] = array(
+               '-v', 'Connections',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Connections",
+               'GPRINT:min:MIN:%4.1lf Min,',
+               'GPRINT:avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:max:MAX:%4.1lf Max,',
+               'GPRINT:avg:LAST:%4.1lf Last\l');
+       $GraphDefs['temperature'] = array(
+               '-v', 'Celsius',
+               'DEF:temp_avg={file}:value:AVERAGE',
+               'DEF:temp_min={file}:value:MIN',
+               'DEF:temp_max={file}:value:MAX',
+               'CDEF:average=temp_avg,0.2,*,PREV,UN,temp_avg,PREV,IF,0.8,*,+',
+               "AREA:temp_max#$HalfRed",
+               "AREA:temp_min#$Canvas",
+               "LINE1:temp_avg#$FullRed:Temperature",
+               'GPRINT:temp_min:MIN:%4.1lf Min,',
+               'GPRINT:temp_avg:AVERAGE:%4.1lf Avg,',
+               'GPRINT:temp_max:MAX:%4.1lf Max,',
+               'GPRINT:temp_avg:LAST:%4.1lf Last\l');
+       $GraphDefs['timeleft'] = array(
+               '-v', 'Minutes',
+               'DEF:avg={file}:timeleft:AVERAGE',
+               'DEF:min={file}:timeleft:MIN',
+               'DEF:max={file}:timeleft:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Time left [min]",
+               'GPRINT:min:MIN:%5.1lf%s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['time_offset'] = array( # NTPd
+               'DEF:s_avg={file}:seconds:AVERAGE',
+               'DEF:s_min={file}:seconds:MIN',
+               'DEF:s_max={file}:seconds:MAX',
+               "AREA:s_max#$HalfBlue",
+               "AREA:s_min#$Canvas",
+               "LINE1:s_avg#$FullBlue:{inst}",
+               'GPRINT:s_min:MIN:%7.3lf%s Min,',
+               'GPRINT:s_avg:AVERAGE:%7.3lf%s Avg,',
+               'GPRINT:s_max:MAX:%7.3lf%s Max,',
+               'GPRINT:s_avg:LAST:%7.3lf%s Last');
+       $GraphDefs['if_octets'] = array(
+               '-v', 'Bits/s', '--units=si',
+               'DEF:out_min_raw={file}:tx:MIN',
+               'DEF:out_avg_raw={file}:tx:AVERAGE',
+               'DEF:out_max_raw={file}:tx:MAX',
+               'DEF:inc_min_raw={file}:rx:MIN',
+               'DEF:inc_avg_raw={file}:rx:AVERAGE',
+               'DEF:inc_max_raw={file}:rx:MAX',
+               'CDEF:out_min=out_min_raw,8,*',
+               'CDEF:out_avg=out_avg_raw,8,*',
+               'CDEF:out_max=out_max_raw,8,*',
+               'CDEF:inc_min=inc_min_raw,8,*',
+               'CDEF:inc_avg=inc_avg_raw,8,*',
+               'CDEF:inc_max=inc_max_raw,8,*',
+               'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+               'CDEF:mytime=out_avg_raw,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:out_avg_sample=out_avg_raw,UN,0,out_avg_raw,IF,sample_len,*',
+               'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+               'CDEF:inc_avg_sample=inc_avg_raw,UN,0,inc_avg_raw,IF,sample_len,*',
+               'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+               "AREA:out_avg#$HalfGreen",
+               "AREA:inc_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:out_avg#$FullGreen:Outgoing",
+               'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:out_max:MAX:%5.1lf%s Max,',
+               'GPRINT:out_avg:LAST:%5.1lf%s Last',
+               'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+               "LINE1:inc_avg#$FullBlue:Incoming",
+//                     'GPRINT:inc_min:MIN:%5.1lf %s Min,',
+               'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:inc_max:MAX:%5.1lf%s Max,',
+               'GPRINT:inc_avg:LAST:%5.1lf%s Last',
+               'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l');
+       $GraphDefs['cpufreq'] = array(
+               'DEF:cpufreq_avg={file}:value:AVERAGE',
+               'DEF:cpufreq_min={file}:value:MIN',
+               'DEF:cpufreq_max={file}:value:MAX',
+               "AREA:cpufreq_max#$HalfBlue",
+               "AREA:cpufreq_min#$Canvas",
+               "LINE1:cpufreq_avg#$FullBlue:Frequency",
+               'GPRINT:cpufreq_min:MIN:%5.1lf%s Min,',
+               'GPRINT:cpufreq_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:cpufreq_max:MAX:%5.1lf%s Max,',
+               'GPRINT:cpufreq_avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['multimeter'] = array(
+               'DEF:multimeter_avg={file}:value:AVERAGE',
+               'DEF:multimeter_min={file}:value:MIN',
+               'DEF:multimeter_max={file}:value:MAX',
+               "AREA:multimeter_max#$HalfBlue",
+               "AREA:multimeter_min#$Canvas",
+               "LINE1:multimeter_avg#$FullBlue:Multimeter",
+               'GPRINT:multimeter_min:MIN:%4.1lf Min,',
+               'GPRINT:multimeter_avg:AVERAGE:%4.1lf Average,',
+               'GPRINT:multimeter_max:MAX:%4.1lf Max,',
+               'GPRINT:multimeter_avg:LAST:%4.1lf Last\l');
+       $GraphDefs['users'] = array(
+               '-v', 'Users',
+               'DEF:users_avg={file}:users:AVERAGE',
+               'DEF:users_min={file}:users:MIN',
+               'DEF:users_max={file}:users:MAX',
+               "AREA:users_max#$HalfBlue",
+               "AREA:users_min#$Canvas",
+               "LINE1:users_avg#$FullBlue:Users",
+               'GPRINT:users_min:MIN:%4.1lf Min,',
+               'GPRINT:users_avg:AVERAGE:%4.1lf Average,',
+               'GPRINT:users_max:MAX:%4.1lf Max,',
+               'GPRINT:users_avg:LAST:%4.1lf Last\l');
+       $GraphDefs['voltage'] = array(
+               '-v', 'Voltage',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Voltage",
+               'GPRINT:min:MIN:%5.1lf%sV Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%sV Avg,',
+               'GPRINT:max:MAX:%5.1lf%sV Max,',
+               'GPRINT:avg:LAST:%5.1lf%sV Last\l');
+       $GraphDefs['vmpage_action'] = array(
+               '-v', 'Actions',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:max#$HalfBlue",
+               "AREA:min#$Canvas",
+               "LINE1:avg#$FullBlue:Action",
+               'GPRINT:min:MIN:%5.1lf%sV Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%sV Avg,',
+               'GPRINT:max:MAX:%5.1lf%sV Max,',
+               'GPRINT:avg:LAST:%5.1lf%sV Last\l');
+       $GraphDefs['vmpage_faults'] = $GraphDefs['ps_pagefaults'];
+       $GraphDefs['vmpage_io'] = array(
+               '-v', 'Bytes/s',
+               'DEF:out_min={file}:out:MIN',
+               'DEF:out_avg={file}:out:AVERAGE',
+               'DEF:out_max={file}:out:MAX',
+               'DEF:inc_min={file}:in:MIN',
+               'DEF:inc_avg={file}:in:AVERAGE',
+               'DEF:inc_max={file}:in:MAX',
+               'CDEF:overlap=out_avg,inc_avg,GT,inc_avg,out_avg,IF',
+               'CDEF:mytime=out_avg,TIME,TIME,IF',
+               'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+               'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+               'CDEF:out_avg_sample=out_avg,UN,0,out_avg,IF,sample_len,*',
+               'CDEF:out_avg_sum=PREV,UN,0,PREV,IF,out_avg_sample,+',
+               'CDEF:inc_avg_sample=inc_avg,UN,0,inc_avg,IF,sample_len,*',
+               'CDEF:inc_avg_sum=PREV,UN,0,PREV,IF,inc_avg_sample,+',
+               "AREA:out_avg#$HalfGreen",
+               "AREA:inc_avg#$HalfBlue",
+               "AREA:overlap#$HalfBlueGreen",
+               "LINE1:out_avg#$FullGreen:Written",
+               'GPRINT:out_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:out_max:MAX:%5.1lf%s Max,',
+               'GPRINT:out_avg:LAST:%5.1lf%s Last',
+               'GPRINT:out_avg_sum:LAST:(ca. %5.1lf%sB Total)\l',
+               "LINE1:inc_avg#$FullBlue:Read   ",
+               'GPRINT:inc_avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:inc_max:MAX:%5.1lf%s Max,',
+               'GPRINT:inc_avg:LAST:%5.1lf%s Last',
+               'GPRINT:inc_avg_sum:LAST:(ca. %5.1lf%sB Total)\l');
+       $GraphDefs['vmpage_number'] = array(
+               '-v', 'Count',
+               'DEF:avg={file}:value:AVERAGE',
+               'DEF:min={file}:value:MIN',
+               'DEF:max={file}:value:MAX',
+               "AREA:avg#$HalfBlue",
+               "LINE1:avg#$FullBlue:Count",
+               'GPRINT:min:MIN:%5.1lf%s Min,',
+               'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+               'GPRINT:max:MAX:%5.1lf%s Max,',
+               'GPRINT:avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['vs_threads'] = array(
+               "DEF:total_avg={file}:total:AVERAGE",
+               "DEF:total_min={file}:total:MIN",
+               "DEF:total_max={file}:total:MAX",
+               "DEF:running_avg={file}:running:AVERAGE",
+               "DEF:running_min={file}:running:MIN",
+               "DEF:running_max={file}:running:MAX",
+               "DEF:uninterruptible_avg={file}:uninterruptible:AVERAGE",
+               "DEF:uninterruptible_min={file}:uninterruptible:MIN",
+               "DEF:uninterruptible_max={file}:uninterruptible:MAX",
+               "DEF:onhold_avg={file}:onhold:AVERAGE",
+               "DEF:onhold_min={file}:onhold:MIN",
+               "DEF:onhold_max={file}:onhold:MAX",
+               "LINE1:total_avg#$FullYellow:Total   ",
+               'GPRINT:total_min:MIN:%5.1lf Min,',
+               'GPRINT:total_avg:AVERAGE:%5.1lf Avg.,',
+               'GPRINT:total_max:MAX:%5.1lf Max,',
+               'GPRINT:total_avg:LAST:%5.1lf Last\l',
+               "LINE1:running_avg#$FullRed:Running ",
+               'GPRINT:running_min:MIN:%5.1lf Min,',
+               'GPRINT:running_avg:AVERAGE:%5.1lf Avg.,',
+               'GPRINT:running_max:MAX:%5.1lf Max,',
+               'GPRINT:running_avg:LAST:%5.1lf Last\l',
+               "LINE1:uninterruptible_avg#$FullGreen:Unintr  ",
+               'GPRINT:uninterruptible_min:MIN:%5.1lf Min,',
+               'GPRINT:uninterruptible_avg:AVERAGE:%5.1lf Avg.,',
+               'GPRINT:uninterruptible_max:MAX:%5.1lf Max,',
+               'GPRINT:uninterruptible_avg:LAST:%5.1lf Last\l',
+               "LINE1:onhold_avg#$FullBlue:Onhold  ",
+               'GPRINT:onhold_min:MIN:%5.1lf Min,',
+               'GPRINT:onhold_avg:AVERAGE:%5.1lf Avg.,',
+               'GPRINT:onhold_max:MAX:%5.1lf Max,',
+               'GPRINT:onhold_avg:LAST:%5.1lf Last\l');
+       $GraphDefs['vs_memory'] = array(
+               'DEF:vm_avg={file}:vm:AVERAGE',
+               'DEF:vm_min={file}:vm:MIN',
+               'DEF:vm_max={file}:vm:MAX',
+               'DEF:vml_avg={file}:vml:AVERAGE',
+               'DEF:vml_min={file}:vml:MIN',
+               'DEF:vml_max={file}:vml:MAX',
+               'DEF:rss_avg={file}:rss:AVERAGE',
+               'DEF:rss_min={file}:rss:MIN',
+               'DEF:rss_max={file}:rss:MAX',
+               'DEF:anon_avg={file}:anon:AVERAGE',
+               'DEF:anon_min={file}:anon:MIN',
+               'DEF:anon_max={file}:anon:MAX',
+               "LINE1:vm_avg#$FullYellow:VM     ",
+               'GPRINT:vm_min:MIN:%5.1lf%s Min,',
+               'GPRINT:vm_avg:AVERAGE:%5.1lf%s Avg.,',
+               'GPRINT:vm_max:MAX:%5.1lf%s Avg.,',
+               'GPRINT:vm_avg:LAST:%5.1lf%s Last\l',
+               "LINE1:vml_avg#$FullRed:Locked ",
+               'GPRINT:vml_min:MIN:%5.1lf%s Min,',
+               'GPRINT:vml_avg:AVERAGE:%5.1lf%s Avg.,',
+               'GPRINT:vml_max:MAX:%5.1lf%s Avg.,',
+               'GPRINT:vml_avg:LAST:%5.1lf%s Last\l',
+               "LINE1:rss_avg#$FullGreen:RSS    ",
+               'GPRINT:rss_min:MIN:%5.1lf%s Min,',
+               'GPRINT:rss_avg:AVERAGE:%5.1lf%s Avg.,',
+               'GPRINT:rss_max:MAX:%5.1lf%s Avg.,',
+               'GPRINT:rss_avg:LAST:%5.1lf%s Last\l',
+               "LINE1:anon_avg#$FullBlue:Anon.  ",
+               'GPRINT:anon_min:MIN:%5.1lf%s Min,',
+               'GPRINT:anon_avg:AVERAGE:%5.1lf%s Avg.,',
+               'GPRINT:anon_max:MAX:%5.1lf%s Avg.,',
+               'GPRINT:anon_avg:LAST:%5.1lf%s Last\l');
+       $GraphDefs['vs_processes'] = array(
+               '-v', 'Processes',
+               'DEF:proc_avg={file}:value:AVERAGE',
+               'DEF:proc_min={file}:value:MIN',
+               'DEF:proc_max={file}:value:MAX',
+               "AREA:proc_max#$HalfBlue",
+               "AREA:proc_min#$Canvas",
+               "LINE1:proc_avg#$FullBlue:Processes",
+               'GPRINT:proc_min:MIN:%4.1lf Min,',
+               'GPRINT:proc_avg:AVERAGE:%4.1lf Avg.,',
+               'GPRINT:proc_max:MAX:%4.1lf Max,',
+               'GPRINT:proc_avg:LAST:%4.1lf Last\l');
+       $GraphDefs['if_multicast'] = $GraphDefs['ipt_packets'];
+       $GraphDefs['if_tx_errors'] = $GraphDefs['if_rx_errors'];
+
+       $MetaGraphDefs['files_count']       = 'meta_graph_files_count';
+       $MetaGraphDefs['files_size']        = 'meta_graph_files_size';
+       $MetaGraphDefs['cpu']               = 'meta_graph_cpu';
+       $MetaGraphDefs['if_rx_errors']      = 'meta_graph_if_rx_errors';
+       $MetaGraphDefs['if_tx_errors']      = 'meta_graph_if_rx_errors';
+       $MetaGraphDefs['memory']            = 'meta_graph_memory';
+       $MetaGraphDefs['vs_memory']         = 'meta_graph_vs_memory';
+       $MetaGraphDefs['vs_threads']        = 'meta_graph_vs_threads';
+       $MetaGraphDefs['nfs_procedure']     = 'meta_graph_nfs_procedure';
+       $MetaGraphDefs['ps_state']          = 'meta_graph_ps_state';
+       $MetaGraphDefs['swap']              = 'meta_graph_swap';
+       $MetaGraphDefs['apache_scoreboard'] = 'meta_graph_apache_scoreboard';
+       $MetaGraphDefs['mysql_commands']    = 'meta_graph_mysql_commands';
+       $MetaGraphDefs['mysql_handler']     = 'meta_graph_mysql_commands';
+       $MetaGraphDefs['tcp_connections']   = 'meta_graph_tcp_connections';
+       $MetaGraphDefs['dns_opcode']        = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_qtype']         = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_qtype_cached']  = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_rcode']         = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_request']       = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_resolver']      = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_update']        = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_zops']          = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_response']      = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_query']         = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_reject']        = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_notify']        = 'meta_graph_dns_event';
+       $MetaGraphDefs['dns_transfer']      = 'meta_graph_dns_event';
+
+       if (function_exists('load_graph_definitions_local'))
+               load_graph_definitions_local($logarithmic, $tinylegend);
+
+       if ($logarithmic)
+               foreach ($GraphDefs as &$GraphDef)
+                       array_unshift($GraphDef, '-o');
+       if ($tinylegend)
+               foreach ($GraphDefs as &$GraphDef)
+                       for ($i = count($GraphDef)-1; $i >=0; $i--)
+                               if (strncmp('GPRINT:', $GraphDef[$i], 7) == 0)
+                                       unset($GraphDef[$i]);
+}
+
+function meta_graph_files_count($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['rrd_opts'] = array('-v', 'Mails');
+
+       $files = array();
+       $opts['colors'] = array(
+               'incoming' => '00e000',
+               'active'   => 'a0e000',
+               'deferred' => 'a00050'
+       );
+
+       $type_instances = array('incoming', 'active', 'deferred');
+       while (list($k, $inst) = each($type_instances)) {
+               $file  = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_files_size($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['rrd_opts'] = array('-v', 'Bytes');
+
+       $files = array();
+       $opts['colors'] = array(
+               'incoming' => '00e000',
+               'active'   => 'a0e000',
+               'deferred' => 'a00050'
+       );
+
+       $type_instances = array('incoming', 'active', 'deferred');
+       while (list($k, $inst) = each($type_instances)) {
+               $file  = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_cpu($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['rrd_opts'] = array('-v', 'Percent', '-r', '-u', '100');
+
+       $files = array();
+       $opts['colors'] = array(
+               'idle'      => 'ffffff',
+               'nice'      => '00e000',
+               'user'      => '0000ff',
+               'wait'      => 'ffb000',
+               'system'    => 'ff0000',
+               'softirq'   => 'ff00ff',
+               'interrupt' => 'a000a0',
+               'steal'     => '000000'
+       );
+
+       $type_instances = array('idle', 'wait', 'nice', 'user', 'system', 'softirq', 'interrupt', 'steal');
+       while (list($k, $inst) = each($type_instances)) {
+               $file  = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_memory($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%5.1lf%s';
+       $opts['rrd_opts']      = array('-b', '1024', '-v', 'Bytes');
+
+       $files = array();
+       $opts['colors'] = array(
+               // Linux - System memoery
+               'free'     => '00e000',
+               'cached'   => '0000ff',
+               'buffered' => 'ffb000',
+               'used'     => 'ff0000',
+               // Bind - Server memory
+               'TotalUse'    => '00e000',
+               'InUse'       => 'ff0000',
+               'BlockSize'   => '8888dd',
+               'ContextSize' => '444499',
+               'Lost'        => '222222'
+       );
+
+       $type_instances = array('free', 'cached', 'buffered', 'used',   'TotalUse', 'InUse', 'BlockSize', 'ContextSize', 'Lost');
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       if ($plugin == 'bind')
+               return collectd_draw_meta_line($opts, $sources);
+       else
+               return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_vs_threads($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%5.1lf%s';
+       $opts['rrd_opts']      = array('-v', 'Threads');
+
+       $files = array();
+       $opts['colors'] = array(
+               'total'   => 'F0A000',
+               'running'  => 'FF0000',
+               'onhold'  => '00E000',
+               'uninterruptable' => '0000FF'
+       );
+
+       $type_instances = array('total', 'running', 'onhold', 'uninterruptable');
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_line($opts, $sources);
+}
+
+function meta_graph_vs_memory($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%5.1lf%s';
+       $opts['rrd_opts']      = array('-b', '1024', '-v', 'Bytes');
+
+       $files = array();
+       $opts['colors'] = array(
+               'vm'   => 'F0A000',
+               'vml'  => 'FF0000',
+               'rss'  => '00E000',
+               'anon' => '0000FF'
+       );
+
+       $type_instances = array('anon', 'rss', 'vml', 'vm');
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_line($opts, $sources);
+}
+
+function meta_graph_if_rx_errors($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%5.2lf';
+       $opts['rrd_opts']      = array('-v', 'Errors/s');
+
+       $files = array();
+
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_mysql_commands($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['rrd_opts'] = array('-v', 'Issues/s');
+       $opts['number_format'] = '%5.2lf';
+
+       $files = array();
+
+       while (list($k, $inst) = each($type_instances)) {
+               $file  = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_nfs_procedure($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%5.1lf%s';
+       $opts['rrd_opts'] = array('-v', 'Ops/s');
+
+       $files = array();
+
+       while (list($k, $inst) = each($type_instances)) {
+               $file  = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_ps_state($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['rrd_opts'] = array('-v', 'Processes');
+
+       $files = array();
+       $opts['colors'] = array(
+               'running'  => '00e000',
+               'sleeping' => '0000ff',
+               'paging'   => 'ffb000',
+               'zombies'  => 'ff0000',
+               'blocked'  => 'ff00ff',
+               'stopped'  => 'a000a0'
+       );
+
+       $type_instances = array('paging', 'blocked', 'zombies', 'stopped', 'running', 'sleeping');
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_swap($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%5.1lf%s';
+       $opts['rrd_opts']      = array('-b', '1024', '-v', 'Bytes');
+
+       $files = array();
+       $opts['colors'] = array(
+               'free'     => '00e000',
+               'cached'   => '0000ff',
+               'used'     => 'ff0000'
+       );
+
+       $type_instances = array('free', 'cached', 'used');
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_apache_scoreboard($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%6.2lf%s';
+       $opts['rrd_opts']      = array('-v', 'Processes');
+
+       $files = array();
+       $opts['colors'] = array(
+               'open'         => '00e000',
+               'waiting'      => '0000ff',
+               'starting'     => 'a00000',
+               'reading'      => 'ff0000',
+               'sending'      => '00ff00',
+               'keepalive'    => 'f000f0',
+               'dnslookup'    => '00a000',
+               'logging'      => '008080',
+               'closing'      => 'a000a0',
+               'finishing'    => '000080',
+               'idle_cleanup' => '000000',
+       );
+
+       $type_instances = array(/* 'open',*/ 'waiting', 'starting', 'reading', 'sending', 'keepalive', 'dnslookup', 'logging', 'closing', 'finishing', 'idle_cleanup');
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file, 'ds'=>'value');
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_tcp_connections($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['number_format'] = '%6.2lf%s';
+       $opts['rrd_opts']      = array('-v', 'Connections');
+
+       $files = array();
+       $opts['colors'] = array(
+               'ESTABLISHED' => '00e000',
+               'SYN_SENT'    => '00e0ff',
+               'SYN_RECV'    => '00e0a0',
+               'FIN_WAIT1'   => 'f000f0',
+               'FIN_WAIT2'   => 'f000a0',
+               'TIME_WAIT'   => 'ffb000',
+               'CLOSE'       => '0000f0',
+               'CLOSE_WAIT'  => '0000a0',
+               'LAST_ACK'    => '000080',
+               'LISTEN'      => 'ff0000',
+               'CLOSING'     => '000000'
+       );
+
+       $type_instances = array('ESTABLISHED', 'SYN_SENT', 'SYN_RECV', 'FIN_WAIT1', 'FIN_WAIT2', 'TIME_WAIT', 'CLOSE', 'CLOSE_WAIT', 'LAST_ACK', 'CLOSING', 'LISTEN');
+       while (list($k, $inst) = each($type_instances)) {
+               $file = '';
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file, 'ds'=>'value');
+       }
+
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+function meta_graph_dns_event($host, $plugin, $plugin_instance, $type, $type_instances, $opts = array()) {
+       global $config;
+       $sources = array();
+
+       $title = "$host/$plugin".(!is_null($plugin_instance) ? "-$plugin_instance" : '')."/$type";
+       if (!isset($opts['title']))
+               $opts['title'] = $title;
+       $opts['rrd_opts'] = array('-v', 'Events', '-r', '-l', '0');
+
+       $files = array();
+//     $opts['colors'] = array(
+//     );
+
+//     $type_instances = array('IQUERY', 'NOTIFY');
+       while (list($k, $inst) = each($type_instances)) {
+               $file  = '';
+               $title = $opts['title'];
+               foreach ($config['datadirs'] as $datadir)
+                       if (is_file($datadir.'/'.$title.'-'.$inst.'.rrd')) {
+                               $file = $datadir.'/'.$title.'-'.$inst.'.rrd';
+                               break;
+                       }
+               if ($file == '')
+                       continue;
+
+               $sources[] = array('name'=>$inst, 'file'=>$file);
+       }
+       return collectd_draw_meta_stack($opts, $sources);
+}
+
+?>
diff --git a/contrib/php-collection/functions.php b/contrib/php-collection/functions.php
new file mode 100644 (file)
index 0000000..fa2badc
--- /dev/null
@@ -0,0 +1,841 @@
+<?php // vim:fenc=utf-8:filetype=php:ts=4
+/*
+ * Copyright (C) 2009  Bruno Prémont <bonbons AT linux-vserver.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+define('REGEXP_HOST', '/^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/');
+define('REGEXP_PLUGIN', '/^[a-zA-Z0-9_.-]+$/');
+
+/**
+ * Read input variable from GET, POST or COOKIE taking
+ * care of magic quotes
+ * @name Name of value to return
+ * @array User-input array ($_GET, $_POST or $_COOKIE)
+ * @default Default value
+ * @return $default if name in unknown in $array, otherwise
+ *         input value with magic quotes stripped off
+ */
+function read_var($name, &$array, $default = null) {
+       if (isset($array[$name])) {
+               if (is_array($array[$name])) {
+                       if (get_magic_quotes_gpc()) {
+                               $ret = array();
+                               while (list($k, $v) = each($array[$name]))
+                                       $ret[stripslashes($k)] = stripslashes($v);
+                               return $ret;
+                       } else
+                               return $array[$name];
+               } else if (is_string($array[$name]) && get_magic_quotes_gpc()) {
+                       return stripslashes($array[$name]);
+               } else
+                       return $array[$name];
+       } else
+               return $default;
+}
+
+/**
+ * Alphabetically compare host names, comparing label
+ * from tld to node name
+ */
+function collectd_compare_host($a, $b) {
+       $ea = explode('.', $a);
+       $eb = explode('.', $b);
+       $i = count($ea) - 1;
+       $j = count($eb) - 1;
+       while ($i >= 0 && $j >= 0)
+               if (($r = strcmp($ea[$i--], $eb[$j--])) != 0)
+                       return $r;
+       return 0;
+}
+
+function collectd_walk(&$options) {
+       global $config;
+
+       foreach($config['datadirs'] as $datadir)
+               if ($dh = @opendir($datadir)) {
+                       while (($hdent = readdir($dh)) !== false) {
+                               if ($hdent == '.' || $hdent == '..' || !is_dir($datadir.'/'.$hdent))
+                                       continue;
+                               if (!preg_match(REGEXP_HOST, $hdent))
+                                       continue;
+                               if (isset($options['cb_host']) && ($options['cb_host'] === false || !$options['cb_host']($options, $hdent)))
+                                       continue;
+
+                               if ($dp = @opendir($datadir.'/'.$hdent)) {
+                                       while (($pdent = readdir($dp)) !== false) {
+                                               if ($pdent == '.' || $pdent == '..' || !is_dir($datadir.'/'.$hdent.'/'.$pdent))
+                                                       continue;
+                                               if ($i = strpos($pdent, '-')) {
+                                                       $plugin = substr($pdent, 0, $i);
+                                                       $pinst  = substr($pdent, $i+1);
+                                               } else {
+                                                       $plugin = $pdent;
+                                                       $pinst  = '';
+                                               }
+                                               if (isset($options['cb_plugin']) && ($options['cb_plugin'] === false || !$options['cb_plugin']($options, $hdent, $plugin)))
+                                                       continue;
+                                               if (isset($options['cb_pinst']) && ($options['cb_pinst'] === false || !$options['cb_pinst']($options, $hdent, $plugin, $pinst)))
+                                                       continue;
+
+                                               if ($dt = @opendir($datadir.'/'.$hdent.'/'.$pdent)) {
+                                                       while (($tdent = readdir($dt)) !== false) {
+                                                               if ($tdent == '.' || $tdent == '..' || !is_file($datadir.'/'.$hdent.'/'.$pdent.'/'.$tdent))
+                                                                       continue;
+                                                               if (substr($tdent, strlen($tdent)-4) != '.rrd')
+                                                                       continue;
+                                                               $tdent = substr($tdent, 0, strlen($tdent)-4);
+                                                               if ($i = strpos($tdent, '-')) {
+                                                                       $type  = substr($tdent, 0, $i);
+                                                                       $tinst = substr($tdent, $i+1);
+                                                               } else {
+                                                                       $type  = $tdent;
+                                                                       $tinst = '';
+                                                               }
+                                                               if (isset($options['cb_type']) && ($options['cb_type'] === false || !$options['cb_type']($options, $hdent, $plugin, $pinst, $type)))
+                                                                       continue;
+                                                               if (isset($options['cb_tinst']) && ($options['cb_tinst'] === false || !$options['cb_tinst']($options, $hdent, $plugin, $pinst, $type, $tinst)))
+                                                                       continue;
+                                                       }
+                                                       closedir($dt);
+                                               }
+                                       }
+                                       closedir($dp);
+                               }
+                       }
+                       closedir($dh);
+               } else
+                       error_log('Failed to open datadir: '.$datadir);
+               return true;
+}
+
+function _collectd_list_cb_host(&$options, $host) {
+       if ($options['cb_plugin'] === false) {
+               $options['result'][] = $host;
+               return false;
+       } else if (isset($options['filter_host'])) {
+               if ($options['filter_host'] == '@all') {
+                       return true; // We take anything
+               } else if (substr($options['filter_host'], 0, 2) == '@.') {
+                       if ($host == substr($options['filter_host'], 2) || substr($host, 0, 1-strlen($options['filter_host'])) == substr($options['filter_host'], 1))
+                               return true; // Host part of domain
+                       else
+                               return false;
+               } else if ($options['filter_host'] == $host) {
+                       return true;
+               } else
+                       return false;
+       } else
+               return true;
+}
+
+function _collectd_list_cb_plugin(&$options, $host, $plugin) {
+       if ($options['cb_pinst'] === false) {
+               $options['result'][] = $plugin;
+               return false;
+       } else if (isset($options['filter_plugin'])) {
+               if ($options['filter_plugin'] == '@all')
+                       return true;
+               else if ($options['filter_plugin'] == $plugin)
+                       return true;
+               else
+                       return false;
+       } else
+               return true;
+}
+
+function _collectd_list_cb_pinst(&$options, $host, $plugin, $pinst) {
+       if ($options['cb_type'] === false) {
+               $options['result'][] = $pinst;
+               return false;
+       } else if (isset($options['filter_pinst'])) {
+               if ($options['filter_pinst'] == '@all')
+                       return true;
+               else if (strncmp($options['filter_pinst'], '@merge_', 7) == 0)
+                       return true;
+               else if ($options['filter_pinst'] == $pinst)
+                       return true;
+               else
+                       return false;
+       } else
+               return true;
+}
+
+function _collectd_list_cb_type(&$options, $host, $plugin, $pinst, $type) {
+       if ($options['cb_tinst'] === false) {
+               $options['result'][] = $type;
+               return false;
+       } else if (isset($options['filter_type'])) {
+               if ($options['filter_type'] == '@all')
+                       return true;
+               else if ($options['filter_type'] == $type)
+                       return true;
+               else
+                       return false;
+       } else
+               return true;
+}
+
+function _collectd_list_cb_tinst(&$options, $host, $plugin, $pinst, $type, $tinst) {
+       $options['result'][] = $tinst;
+       return false;
+}
+
+function _collectd_list_cb_graph(&$options, $host, $plugin, $pinst, $type, $tinst) {
+       if (isset($options['filter_tinst'])) {
+               if ($options['filter_tinst'] == '@all') {
+               } else if ($options['filter_tinst'] == $tinst) {
+               } else if (strncmp($options['filter_tinst'], '@merge', 6) == 0) {
+                       // Need to exclude @merge with non-existent meta graph
+               } else
+                       return false;
+       }
+       if (isset($options['filter_pinst']) && strncmp($options['filter_pinst'], '@merge', 6) == 0)
+               $pinst = $options['filter_pinst'];
+       if (isset($options['filter_tinst']) && strncmp($options['filter_tinst'], '@merge', 6) == 0)
+               $tinst = $options['filter_tinst'];
+       $ident = collectd_identifier($host, $plugin, $pinst, $type, $tinst);
+       if (!in_array($ident, $options['ridentifiers'])) {
+               $options['ridentifiers'][] = $ident;
+               $options['result'][] = array('host'=>$host, 'plugin'=>$plugin, 'pinst'=>$pinst, 'type'=>$type, 'tinst'=>$tinst);
+       }
+}
+
+/**
+ * Fetch list of hosts found in collectd's datadirs.
+ * @return Sorted list of hosts (sorted by label from rigth to left)
+ */
+function collectd_list_hosts() {
+       $options = array(
+               'result' => array(),
+               'cb_host' => '_collectd_list_cb_host',
+               'cb_plugin' => false,
+               'cb_pinst' => false,
+               'cb_type' => false,
+               'cb_tinst' => false
+       );
+       collectd_walk($options);
+       $hosts = array_unique($options['result']);
+       usort($hosts, 'collectd_compare_host');
+       return $hosts;
+}
+
+/**
+ * Fetch list of plugins found in collectd's datadirs for given host.
+ * @arg_host Name of host for which to return plugins
+ * @return Sorted list of plugins (sorted alphabetically)
+ */
+function collectd_list_plugins($arg_host, $arg_plugin = null) {
+       $options = array(
+               'result' => array(),
+               'cb_host' => '_collectd_list_cb_host',
+               'cb_plugin' => '_collectd_list_cb_plugin',
+               'cb_pinst' => is_null($arg_plugin) ? false : '_collectd_list_cb_pinst',
+               'cb_type' => false,
+               'cb_tinst' => false,
+               'filter_host' => $arg_host,
+               'filter_plugin' => $arg_plugin
+       );
+       collectd_walk($options);
+       $plugins = array_unique($options['result']);
+       sort($plugins);
+       return $plugins;
+}
+
+/**
+ * Fetch list of types found in collectd's datadirs for given host+plugin+instance
+ * @arg_host Name of host
+ * @arg_plugin Name of plugin
+ * @arg_pinst Plugin instance
+ * @return Sorted list of types (sorted alphabetically)
+ */
+function collectd_list_types($arg_host, $arg_plugin, $arg_pinst, $arg_type = null) {
+       $options = array(
+               'result' => array(),
+               'cb_host' => '_collectd_list_cb_host',
+               'cb_plugin' => '_collectd_list_cb_plugin',
+               'cb_pinst' => '_collectd_list_cb_pinst',
+               'cb_type' => '_collectd_list_cb_type',
+               'cb_tinst' => is_null($arg_type) ? false : '_collectd_list_cb_tinst',
+               'filter_host' => $arg_host,
+               'filter_plugin' => $arg_plugin,
+               'filter_pinst' => $arg_pinst,
+               'filter_type' => $arg_type
+       );
+       collectd_walk($options);
+       $types = array_unique($options['result']);
+       sort($types);
+       return $types;
+}
+
+function collectd_list_graphs($arg_host, $arg_plugin, $arg_pinst, $arg_type, $arg_tinst) {
+       $options = array(
+               'result' => array(),
+               'ridentifiers' => array(),
+               'cb_host' => '_collectd_list_cb_host',
+               'cb_plugin' => '_collectd_list_cb_plugin',
+               'cb_pinst' => '_collectd_list_cb_pinst',
+               'cb_type' => '_collectd_list_cb_type',
+               'cb_tinst' => '_collectd_list_cb_graph',
+               'filter_host' => $arg_host,
+               'filter_plugin' => $arg_plugin,
+               'filter_pinst' => $arg_pinst,
+               'filter_type' => $arg_type,
+               'filter_tinst' => $arg_tinst == '@' ? '@merge' : $arg_tinst
+       );
+       collectd_walk($options);
+       return $options['result'];
+}
+
+/**
+ * Parse symlinks in order to get an identifier that collectd understands
+ * (e.g. virtualisation is collected on host for individual VMs and can be
+ *  symlinked to the VM's hostname, support FLUSH for these by flushing
+ *  on the host-identifier instead of VM-identifier)
+ * @host Host name
+ * @plugin Plugin name
+ * @pinst Plugin instance
+ * @type Type name
+ * @tinst Type instance
+ * @return Identifier that collectd's FLUSH command understands
+ */
+function collectd_identifier($host, $plugin, $pinst, $type, $tinst) {
+       global $config;
+       $rrd_realpath    = null;
+       $orig_identifier = sprintf('%s/%s%s%s/%s%s%s', $host, $plugin, strlen($pinst) ? '-' : '', $pinst, $type, strlen($tinst) ? '-' : '', $tinst);
+       $identifier      = null;
+       foreach ($config['datadirs'] as $datadir)
+               if (is_file($datadir.'/'.$orig_identifier.'.rrd')) {
+                       $rrd_realpath = realpath($datadir.'/'.$orig_identifier.'.rrd');
+                       break;
+               }
+       if ($rrd_realpath) {
+               $identifier   = basename($rrd_realpath);
+               $identifier   = substr($identifier, 0, strlen($identifier)-4);
+               $rrd_realpath = dirname($rrd_realpath);
+               $identifier   = basename($rrd_realpath).'/'.$identifier;
+               $rrd_realpath = dirname($rrd_realpath);
+               $identifier   = basename($rrd_realpath).'/'.$identifier;
+       }
+
+       if (is_null($identifier))
+               return $orig_identifier;
+       else
+               return $identifier;
+}
+
+/**
+ * Tell collectd that it should FLUSH all data it has regarding the
+ * graph we are about to generate.
+ * @host Host name
+ * @plugin Plugin name
+ * @pinst Plugin instance
+ * @type Type name
+ * @tinst Type instance
+ */
+function collectd_flush($identifier) {
+       global $config;
+
+       if (!$config['collectd_sock'])
+               return false;
+       if (is_null($identifier) || (is_array($identifier) && count($identifier) == 0) || !(is_string($identifier) || is_array($identifier)))
+               return false;
+
+       $u_errno  = 0;
+       $u_errmsg = '';
+       if ($socket = @fsockopen($config['collectd_sock'], 0, $u_errno, $u_errmsg)) {
+               $cmd = 'FLUSH plugin=rrdtool';
+               if (is_array($identifier)) {
+                       foreach ($identifier as $val)
+                               $cmd .= sprintf(' identifier="%s"', $val);
+               } else
+                       $cmd .= sprintf(' identifier="%s"', $identifier);
+               $cmd .= "\n";
+
+               $r = fwrite($socket, $cmd, strlen($cmd));
+               if ($r === false || $r != strlen($cmd))
+                       error_log(sprintf("graph.php: Failed to write whole command to unix-socket: %d out of %d written", $r === false ? -1 : $r, strlen($cmd)));
+
+               $resp = fgets($socket);
+               if ($resp === false)
+                       error_log(sprintf("graph.php: Failed to read response from collectd for command: %s", trim($cmd)));
+
+               $n = (int)$resp;
+               while ($n-- > 0)
+                       fgets($socket);
+
+               fclose($socket);
+       } else
+               error_log(sprintf("graph.php: Failed to open unix-socket to collectd: %d: %s", $u_errno, $u_errmsg));
+}
+
+class CollectdColor {
+       private $r = 0;
+       private $g = 0;
+       private $b = 0;
+
+       function __construct($value = null) {
+               if (is_null($value)) {
+               } else if (is_array($value)) {
+                       if (isset($value['r']))
+                               $this->r = $value['r'] > 0 ? ($value['r'] > 1 ? 1 : $value['r']) : 0;
+                       if (isset($value['g']))
+                               $this->g = $value['g'] > 0 ? ($value['g'] > 1 ? 1 : $value['g']) : 0;
+                       if (isset($value['b']))
+                               $this->b = $value['b'] > 0 ? ($value['b'] > 1 ? 1 : $value['b']) : 0;
+               } else if (is_string($value)) {
+                       $matches = array();
+                       if ($value == 'random') {
+                               $this->randomize();
+                       } else if (preg_match('/([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])([0-9A-Fa-f][0-9A-Fa-f])/', $value, $matches)) {
+                               $this->r = ('0x'.$matches[1]) / 255.0;
+                               $this->g = ('0x'.$matches[2]) / 255.0;
+                               $this->b = ('0x'.$matches[3]) / 255.0;
+                       }
+               } else if (is_a($value, 'CollectdColor')) {
+                       $this->r = $value->r;
+                       $this->g = $value->g;
+                       $this->b = $value->b;
+               }
+       }
+
+       function randomize() {
+               $this->r = rand(0, 255) / 255.0;
+               $this->g = rand(0, 255) / 255.0;
+               $this->b = 0.0;
+               $min = 0.0;
+               $max = 1.0;
+
+               if (($this->r + $this->g) < 1.0) {
+                       $min = 1.0 - ($this->r + $this->g);
+               } else {
+                       $max = 2.0 - ($this->r + $this->g);
+               }
+               $this->b = $min + ((rand(0, 255)/255.0) * ($max - $min));
+       }
+
+       function fade($bkgnd = null, $alpha = 0.25) {
+               if (is_null($bkgnd) || !is_a($bkgnd, 'CollectdColor')) {
+                       $bg_r = 1.0;
+                       $bg_g = 1.0;
+                       $bg_b = 1.0;
+               } else {
+                       $bg_r = $bkgnd->r;
+                       $bg_g = $bkgnd->g;
+                       $bg_b = $bkgnd->b;
+               }
+
+               $this->r = $alpha * $this->r + ((1.0 - $alpha) * $bg_r);
+               $this->g = $alpha * $this->g + ((1.0 - $alpha) * $bg_g);
+               $this->b = $alpha * $this->b + ((1.0 - $alpha) * $bg_b);
+       }
+
+       function as_array() {
+               return array('r'=>$this->r, 'g'=>$this->g, 'b'=>$this->b);
+       }
+
+       function as_string() {
+               $r = (int)($this->r*255);
+               $g = (int)($this->g*255);
+               $b = (int)($this->b*255);
+               return sprintf('%02x%02x%02x', $r > 255 ? 255 : $r, $g > 255 ? 255 : $g, $b > 255 ? 255 : $b);
+       }
+}
+
+
+/**
+ * Helper function to strip quotes from RRD output
+ * @str RRD-Info generated string
+ * @return String with one surrounding pair of quotes stripped
+ */
+function rrd_strip_quotes($str) {
+       if ($str[0] == '"' && $str[strlen($str)-1] == '"')
+               return substr($str, 1, strlen($str)-2);
+       else
+               return $str;
+}
+
+function rrd_escape($str) {
+       return str_replace(array('\\', ':'), array('\\\\', '\\:'), $str);
+}
+
+/**
+ * Determine useful information about RRD file
+ * @file Name of RRD file to analyse
+ * @return Array describing the RRD file
+ */
+function rrd_info($file) {
+       $info = array('filename'=>$file);
+
+       $rrd = popen(RRDTOOL.' info '.escapeshellarg($file), 'r');
+       if ($rrd) {
+               while (($s = fgets($rrd)) !== false) {
+                       $p = strpos($s, '=');
+                       if ($p === false)
+                               continue;
+                       $key = trim(substr($s, 0, $p));
+                       $value = trim(substr($s, $p+1));
+                       if (strncmp($key,'ds[', 3) == 0) {
+                               /* DS definition */
+                               $p = strpos($key, ']');
+                               $ds = substr($key, 3, $p-3);
+                               if (!isset($info['DS']))
+                                       $info['DS'] = array();
+                               $ds_key = substr($key, $p+2);
+
+                               if (strpos($ds_key, '[') === false) {
+                                       if (!isset($info['DS']["$ds"]))
+                                               $info['DS']["$ds"] = array();
+                                       $info['DS']["$ds"]["$ds_key"] = rrd_strip_quotes($value);
+                               }
+                       } else if (strncmp($key, 'rra[', 4) == 0) {
+                               /* RRD definition */
+                               $p = strpos($key, ']');
+                               $rra = substr($key, 4, $p-4);
+                               if (!isset($info['RRA']))
+                                       $info['RRA'] = array();
+                               $rra_key = substr($key, $p+2);
+
+                               if (strpos($rra_key, '[') === false) {
+                                       if (!isset($info['RRA']["$rra"]))
+                                               $info['RRA']["$rra"] = array();
+                                       $info['RRA']["$rra"]["$rra_key"] = rrd_strip_quotes($value);
+                               }
+                       } else if (strpos($key, '[') === false) {
+                               $info[$key] = rrd_strip_quotes($value);
+                       }
+               }
+               pclose($rrd);
+       }
+       return $info;
+}
+
+function rrd_get_color($code, $line = true) {
+       global $config;
+       $name = ($line ? 'f_' : 'h_').$code;
+       if (!isset($config['rrd_colors'][$name])) {
+               $c_f = new CollectdColor('random');
+               $c_h = new CollectdColor($c_f);
+               $c_h->fade();
+               $config['rrd_colors']['f_'.$code] = $c_f->as_string();
+               $config['rrd_colors']['h_'.$code] = $c_h->as_string();
+       }
+       return $config['rrd_colors'][$name];
+}
+
+/**
+ * Draw RRD file based on it's structure
+ * @host
+ * @plugin
+ * @pinst
+ * @type
+ * @tinst
+ * @opts
+ * @return Commandline to call RRDGraph in order to generate the final graph
+ */
+function collectd_draw_rrd($host, $plugin, $pinst = null, $type, $tinst = null, $opts = array()) {
+       global $config;
+       $timespan_def = null;
+       if (!isset($opts['timespan']))
+               $timespan_def = reset($config['timespan']);
+       else foreach ($config['timespan'] as &$ts)
+               if ($ts['name'] == $opts['timespan'])
+                       $timespan_def = $ts;
+
+       if (!isset($opts['rrd_opts']))
+               $opts['rrd_opts'] = array();
+       if (isset($opts['logarithmic']) && $opts['logarithmic'])
+               array_unshift($opts['rrd_opts'], '-o');
+
+       $rrdinfo = null;
+       $rrdfile = sprintf('%s/%s%s%s/%s%s%s', $host, $plugin, is_null($pinst) ? '' : '-', $pinst, $type, is_null($tinst) ? '' : '-', $tinst);
+       foreach ($config['datadirs'] as $datadir)
+               if (is_file($datadir.'/'.$rrdfile.'.rrd')) {
+                       $rrdinfo = rrd_info($datadir.'/'.$rrdfile.'.rrd');
+                       if (isset($rrdinfo['RRA']) && is_array($rrdinfo['RRA']))
+                               break;
+                       else
+                               $rrdinfo = null;
+               }
+
+       if (is_null($rrdinfo))
+               return false;
+
+       $graph = array();
+       $has_avg = false;
+       $has_max = false;
+       $has_min = false;
+       reset($rrdinfo['RRA']);
+       $l_max = 0;
+       while (list($k, $v) = each($rrdinfo['RRA'])) {
+               if ($v['cf'] == 'MAX')
+                       $has_max = true;
+               else if ($v['cf'] == 'AVERAGE')
+                       $has_avg = true;
+               else if ($v['cf'] == 'MIN')
+                       $has_min = true;
+       }
+       reset($rrdinfo['DS']);
+       while (list($k, $v) = each($rrdinfo['DS'])) {
+               if (strlen($k) > $l_max)
+                       $l_max = strlen($k);
+               if ($has_min)
+                       $graph[] = sprintf('DEF:%s_min=%s:%s:MIN', $k, rrd_escape($rrdinfo['filename']), $k);
+               if ($has_avg)
+                       $graph[] = sprintf('DEF:%s_avg=%s:%s:AVERAGE', $k, rrd_escape($rrdinfo['filename']), $k);
+               if ($has_max)
+                       $graph[] = sprintf('DEF:%s_max=%s:%s:MAX', $k, rrd_escape($rrdinfo['filename']), $k);
+       }
+       if ($has_min && $has_max || $has_min && $has_avg || $has_avg && $has_max) {
+               $n = 1;
+               reset($rrdinfo['DS']);
+               while (list($k, $v) = each($rrdinfo['DS'])) {
+                       $graph[] = sprintf('LINE:%s_%s', $k, $has_min ? 'min' : 'avg');
+                       $graph[] = sprintf('CDEF:%s_var=%s_%s,%s_%s,-', $k, $k, $has_max ? 'max' : 'avg', $k, $has_min ? 'min' : 'avg');
+                       $graph[] = sprintf('AREA:%s_var#%s::STACK', $k, rrd_get_color($n++, false));
+               }
+       }
+
+       reset($rrdinfo['DS']);
+       $n = 1;
+       while (list($k, $v) = each($rrdinfo['DS'])) {
+               $graph[] = sprintf('LINE1:%s_avg#%s:%s ', $k, rrd_get_color($n++, true), $k.substr('                  ', 0, $l_max-strlen($k)));
+               if (isset($opts['tinylegend']) && $opts['tinylegend'])
+                       continue;
+               if ($has_avg)
+                       $graph[] = sprintf('GPRINT:%s_avg:AVERAGE:%%5.1lf%%s Avg%s', $k, $has_max || $has_min || $has_avg ? ',' : "\\l");
+               if ($has_min)
+                       $graph[] = sprintf('GPRINT:%s_min:MIN:%%5.1lf%%s Max%s', $k, $has_max || $has_avg ? ',' : "\\l");
+               if ($has_max)
+                       $graph[] = sprintf('GPRINT:%s_max:MAX:%%5.1lf%%s Max%s', $k, $has_avg ? ',' : "\\l");
+               if ($has_avg)
+                       $graph[] = sprintf('GPRINT:%s_avg:LAST:%%5.1lf%%s Last\\l', $k);
+       }
+
+       $rrd_cmd = array(RRDTOOL, 'graph', '-', '-a', 'PNG', '-w', $config['rrd_width'], '-h', $config['rrd_height'], '-s', -1*$timespan_def['seconds'], '-t', $rrdfile);
+       $rrd_cmd = array_merge($rrd_cmd, $config['rrd_opts'], $opts['rrd_opts'], $graph);
+
+       $cmd = RRDTOOL;
+       for ($i = 1; $i < count($rrd_cmd); $i++)
+               $cmd .= ' '.escapeshellarg($rrd_cmd[$i]);
+
+       return $cmd;
+}
+
+/**
+ * Draw RRD file based on it's structure
+ * @timespan
+ * @host
+ * @plugin
+ * @pinst
+ * @type
+ * @tinst
+ * @opts
+ * @return Commandline to call RRDGraph in order to generate the final graph
+ */
+function collectd_draw_generic($timespan, $host, $plugin, $pinst = null, $type, $tinst = null) {
+       global $config, $GraphDefs;
+       $timespan_def = null;
+       foreach ($config['timespan'] as &$ts)
+               if ($ts['name'] == $timespan)
+                       $timespan_def = $ts;
+       if (is_null($timespan_def))
+               $timespan_def = reset($config['timespan']);
+
+       if (!isset($GraphDefs[$type]))
+               return false;
+
+       $rrd_file = sprintf('%s/%s%s%s/%s%s%s', $host, $plugin, is_null($pinst) ? '' : '-', $pinst, $type, is_null($tinst) ? '' : '-', $tinst);
+       $rrd_cmd  = array(RRDTOOL, 'graph', '-', '-a', 'PNG', '-w', $config['rrd_width'], '-h', $config['rrd_height'], '-s', -1*$timespan_def['seconds'], '-t', $rrd_file);
+       $rrd_cmd  = array_merge($rrd_cmd, $config['rrd_opts']);
+       $rrd_args = $GraphDefs[$type];
+
+       foreach ($config['datadirs'] as $datadir) {
+               $file = $datadir.'/'.$rrd_file.'.rrd';
+               if (!is_file($file))
+                       continue;
+
+               $file = str_replace(":", "\\:", $file);
+               $rrd_args = str_replace('{file}', rrd_escape($file), $rrd_args);
+
+               $rrdgraph = array_merge($rrd_cmd, $rrd_args);
+               $cmd = RRDTOOL;
+               for ($i = 1; $i < count($rrdgraph); $i++)
+                       $cmd .= ' '.escapeshellarg($rrdgraph[$i]);
+
+               return $cmd;
+       }
+       return false;
+}
+
+/**
+ * Draw stack-graph for set of RRD files
+ * @opts Graph options like colors
+ * @sources List of array(name, file, ds)
+ * @return Commandline to call RRDGraph in order to generate the final graph
+ */
+function collectd_draw_meta_stack(&$opts, &$sources) {
+       global $config;
+       $timespan_def = null;
+       if (!isset($opts['timespan']))
+               $timespan_def = reset($config['timespan']);
+       else foreach ($config['timespan'] as &$ts)
+               if ($ts['name'] == $opts['timespan'])
+                       $timespan_def = $ts;
+
+       if (!isset($opts['title']))
+               $opts['title'] = 'Unknown title';
+       if (!isset($opts['rrd_opts']))
+               $opts['rrd_opts'] = array();
+       if (!isset($opts['colors']))
+               $opts['colors'] = array();
+       if (isset($opts['logarithmic']) && $opts['logarithmic'])
+               array_unshift($opts['rrd_opts'], '-o');
+
+       $cmd = array(RRDTOOL, 'graph', '-', '-a', 'PNG', '-w', $config['rrd_width'], '-h', $config['rrd_height'], '-s', -1*$timespan_def['seconds'], '-t', $opts['title']);
+       $cmd = array_merge($cmd, $config['rrd_opts'], $opts['rrd_opts']);
+       $max_inst_name = 0;
+
+       foreach($sources as &$inst_data) {
+               $inst_name = str_replace('!', '_', $inst_data['name']);
+               $file      = $inst_data['file'];
+               $ds        = isset($inst_data['ds']) ? $inst_data['ds'] : 'value';
+
+               if (strlen($inst_name) > $max_inst_name)
+                       $max_inst_name = strlen($inst_name);
+
+               if (!is_file($file))
+                       continue;
+
+               $cmd[] = 'DEF:'.$inst_name.'_min='.rrd_escape($file).':'.$ds.':MIN';
+               $cmd[] = 'DEF:'.$inst_name.'_avg='.rrd_escape($file).':'.$ds.':AVERAGE';
+               $cmd[] = 'DEF:'.$inst_name.'_max='.rrd_escape($file).':'.$ds.':MAX';
+               $cmd[] = 'CDEF:'.$inst_name.'_nnl='.$inst_name.'_avg,UN,0,'.$inst_name.'_avg,IF';
+       }
+       $inst_data = end($sources);
+       $inst_name = $inst_data['name'];
+       $cmd[] = 'CDEF:'.$inst_name.'_stk='.$inst_name.'_nnl';
+
+       $inst_data1 = end($sources);
+       while (($inst_data0 = prev($sources)) !== false) {
+               $inst_name0 = str_replace('!', '_', $inst_data0['name']);
+               $inst_name1 = str_replace('!', '_', $inst_data1['name']);
+
+               $cmd[] = 'CDEF:'.$inst_name0.'_stk='.$inst_name0.'_nnl,'.$inst_name1.'_stk,+';
+               $inst_data1 = $inst_data0;
+       }
+
+       foreach($sources as &$inst_data) {
+               $inst_name = str_replace('!', '_', $inst_data['name']);
+               $legend = sprintf('%s', $inst_data['name']);
+               while (strlen($legend) < $max_inst_name)
+                       $legend .= ' ';
+               $number_format = isset($opts['number_format']) ? $opts['number_format'] : '%6.1lf';
+
+               if (isset($opts['colors'][$inst_name]))
+                       $line_color = new CollectdColor($opts['colors'][$inst_name]);
+               else
+                       $line_color = new CollectdColor('random');
+               $area_color = new CollectdColor($line_color);
+               $area_color->fade();
+
+               $cmd[] = 'AREA:'.$inst_name.'_stk#'.$area_color->as_string();
+               $cmd[] = 'LINE1:'.$inst_name.'_stk#'.$line_color->as_string().':'.$legend;
+               if (!(isset($opts['tinylegend']) && $opts['tinylegend'])) {
+                       $cmd[] = 'GPRINT:'.$inst_name.'_min:MIN:'.$number_format.' Min,';
+                       $cmd[] = 'GPRINT:'.$inst_name.'_avg:AVERAGE:'.$number_format.' Avg,';
+                       $cmd[] = 'GPRINT:'.$inst_name.'_max:MAX:'.$number_format.' Max,';
+                       $cmd[] = 'GPRINT:'.$inst_name.'_avg:LAST:'.$number_format.' Last\\l';
+               }
+       }
+
+       $rrdcmd = RRDTOOL;
+       for ($i = 1; $i < count($cmd); $i++)
+               $rrdcmd .= ' '.escapeshellarg($cmd[$i]);
+       return $rrdcmd;
+}
+
+/**
+ * Draw stack-graph for set of RRD files
+ * @opts Graph options like colors
+ * @sources List of array(name, file, ds)
+ * @return Commandline to call RRDGraph in order to generate the final graph
+ */
+function collectd_draw_meta_line(&$opts, &$sources) {
+       global $config;
+       $timespan_def = null;
+       if (!isset($opts['timespan']))
+               $timespan_def = reset($config['timespan']);
+       else foreach ($config['timespan'] as &$ts)
+               if ($ts['name'] == $opts['timespan'])
+                       $timespan_def = $ts;
+
+       if (!isset($opts['title']))
+               $opts['title'] = 'Unknown title';
+       if (!isset($opts['rrd_opts']))
+               $opts['rrd_opts'] = array();
+       if (!isset($opts['colors']))
+               $opts['colors'] = array();
+       if (isset($opts['logarithmic']) && $opts['logarithmic'])
+               array_unshift($opts['rrd_opts'], '-o');
+
+       $cmd = array(RRDTOOL, 'graph', '-', '-a', 'PNG', '-w', $config['rrd_width'], '-h', $config['rrd_height'], '-s', -1*$timespan_def['seconds'], '-t', $opts['title']);
+       $cmd = array_merge($cmd, $config['rrd_opts'], $opts['rrd_opts']);
+       $max_inst_name = 0;
+
+       foreach ($sources as &$inst_data) {
+               $inst_name = str_replace('!', '_', $inst_data['name']);
+               $file      = $inst_data['file'];
+               $ds        = isset($inst_data['ds']) ? $inst_data['ds'] : 'value';
+
+               if (strlen($inst_name) > $max_inst_name)
+                       $max_inst_name = strlen($inst_name);
+
+               if (!is_file($file))
+                       continue;
+
+               $cmd[] = 'DEF:'.$inst_name.'_min='.rrd_escape($file).':'.$ds.':MIN';
+               $cmd[] = 'DEF:'.$inst_name.'_avg='.rrd_escape($file).':'.$ds.':AVERAGE';
+               $cmd[] = 'DEF:'.$inst_name.'_max='.rrd_escape($file).':'.$ds.':MAX';
+       }
+
+       foreach ($sources as &$inst_data) {
+               $inst_name = str_replace('!', '_', $inst_data['name']);
+               $legend = sprintf('%s', $inst_name);
+               while (strlen($legend) < $max_inst_name)
+                       $legend .= ' ';
+               $number_format = isset($opts['number_format']) ? $opts['number_format'] : '%6.1lf';
+
+               if (isset($opts['colors'][$inst_name]))
+                       $line_color = new CollectdColor($opts['colors'][$inst_name]);
+               else
+                       $line_color = new CollectdColor('random');
+
+               $cmd[] = 'LINE1:'.$inst_name.'_avg#'.$line_color->as_string().':'.$legend;
+               if (!(isset($opts['tinylegend']) && $opts['tinylegend'])) {
+                       $cmd[] = 'GPRINT:'.$inst_name.'_min:MIN:'.$number_format.' Min,';
+                       $cmd[] = 'GPRINT:'.$inst_name.'_avg:AVERAGE:'.$number_format.' Avg,';
+                       $cmd[] = 'GPRINT:'.$inst_name.'_max:MAX:'.$number_format.' Max,';
+                       $cmd[] = 'GPRINT:'.$inst_name.'_avg:LAST:'.$number_format.' Last\\l';
+               }
+       }
+
+       $rrdcmd = RRDTOOL;
+       for ($i = 1; $i < count($cmd); $i++)
+               $rrdcmd .= ' '.escapeshellarg($cmd[$i]);
+       return $rrdcmd;
+}
+
+?>
diff --git a/contrib/php-collection/graph.php b/contrib/php-collection/graph.php
new file mode 100644 (file)
index 0000000..fdfcbaa
--- /dev/null
@@ -0,0 +1,217 @@
+<?php // vim:fenc=utf-8:filetype=php:ts=4
+/*
+ * Copyright (C) 2009  Bruno Prémont <bonbons AT linux-vserver.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+error_reporting(E_ALL | E_NOTICE | E_WARNING);
+
+require('config.php');
+require('functions.php');
+require('definitions.php');
+
+function makeTextBlock($text, $fontfile, $fontsize, $width) {
+       // TODO: handle explicit line-break!
+       $words = explode(' ', $text);
+       $lines = array($words[0]);
+       $currentLine = 0;
+       foreach ($words as $word) {
+               $lineSize = imagettfbbox($fontsize, 0, $fontfile, $lines[$currentLine] . ' ' . $word);
+               if($lineSize[2] - $lineSize[0] < $width) {
+                       $lines[$currentLine] .= ' ' . $word;
+               } else {
+                       $currentLine++;
+                       $lines[$currentLine] = $word;
+               }
+       }
+       error_log(sprintf('Handles message "%s", %d words => %d/%d lines', $text, count($words), $currentLine, count($lines)));
+       return implode("\n", $lines);
+}
+
+/**
+ * No RRD files found that could match request
+ * @code HTTP error code
+ * @code_msg Short text description of HTTP error code
+ * @title Title for fake RRD graph
+ * @msg Complete error message to display in place of graph content
+ */
+function error($code, $code_msg, $title, $msg) {
+       global $config;
+       header(sprintf("HTTP/1.0 %d %s", $code, $code_msg));
+       header("Pragma: no-cache");
+       header("Expires: Mon, 01 Jan 2008 00:00:00 CET");
+       header("Content-Type: image/png");
+       $w = $config['rrd_width']+81;
+       $h = $config['rrd_height']+79;
+
+       $png     = imagecreate($w, $h);
+       $c_bkgnd = imagecolorallocate($png, 240, 240, 240);
+       $c_fgnd  = imagecolorallocate($png, 255, 255, 255);
+       $c_blt   = imagecolorallocate($png, 208, 208, 208);
+       $c_brb   = imagecolorallocate($png, 160, 160, 160);
+       $c_grln  = imagecolorallocate($png, 114, 114, 114);
+       $c_grarr = imagecolorallocate($png, 128,  32,  32);
+       $c_txt   = imagecolorallocate($png, 0, 0, 0);
+       $c_etxt  = imagecolorallocate($png, 64, 0, 0);
+
+       if (function_exists('imageantialias'))
+               imageantialias($png, true);
+       imagefilledrectangle($png, 0,   0, $w, $h, $c_bkgnd);
+       imagefilledrectangle($png, 51, 33, $w-31, $h-47, $c_fgnd);
+       imageline($png,  51,  30,  51, $h-43, $c_grln);
+       imageline($png,  48, $h-46, $w-28, $h-46, $c_grln);
+       imagefilledpolygon($png, array(49, 30,    51, 26,    53, 30), 3, $c_grarr);
+       imagefilledpolygon($png, array($w-28, $h-48,  $w-24, $h-46,  $w-28, $h-44), 3, $c_grarr);
+       imageline($png,    0,    0,   $w,    0, $c_blt);
+       imageline($png,    0,    1,   $w,    1, $c_blt);
+       imageline($png,    0,    0,    0,   $h, $c_blt);
+       imageline($png,    1,    0,    1,   $h, $c_blt);
+       imageline($png, $w-1,    0, $w-1,   $h, $c_brb);
+       imageline($png, $w-2,    1, $w-2,   $h, $c_brb);
+       imageline($png,    1, $h-2,   $w, $h-2, $c_brb);
+       imageline($png,    0, $h-1,   $w, $h-1, $c_brb);
+
+       imagestring($png, 4, ceil(($w-strlen($title)*imagefontwidth(4)) / 2), 10, $title, $c_txt);
+       imagestring($png, 5, 60, 35, sprintf('%s [%d]', $code_msg, $code), $c_etxt);
+       if (function_exists('imagettfbbox') && is_file($config['error_font'])) {
+               // Detailed error message
+               $fmt_msg = makeTextBlock($msg, $errorfont, 10, $w-86);
+               $fmtbox  = imagettfbbox(12, 0, $errorfont, $fmt_msg);
+               imagettftext($png, 10, 0, 55, 35+3+imagefontwidth(5)-$fmtbox[7]+$fmtbox[1], $c_txt, $errorfont, $fmt_msg);
+       } else {
+               imagestring($png, 4, 53, 35+6+imagefontwidth(5), $msg, $c_txt);
+       }
+
+       imagepng($png);
+       imagedestroy($png);
+}
+
+/**
+ * No RRD files found that could match request
+ */
+function error404($title, $msg) {
+       return error(404, "Not found", $title, $msg);
+}
+
+/**
+ * Incomplete / invalid request
+ */
+function error400($title, $msg) {
+       return error(400, "Bad request", $title, $msg);
+}
+
+/**
+ * Incomplete / invalid request
+ */
+function error500($title, $msg) {
+       return error(500, "Internal error", $title, $msg);
+}
+
+// Process input arguments
+$host     = read_var('host', $_GET, null);
+if (is_null($host))
+       return error400("?/?-?/?", "Missing host name");
+else if (!is_string($host))
+       return error400("?/?-?/?", "Expecting exactly 1 host name");
+else if (strlen($host) == 0)
+       return error400("?/?-?/?", "Host name may not be blank");
+
+$plugin   = read_var('plugin', $_GET, null);
+if (is_null($plugin))
+       return error400($host.'/?-?/?', "Missing plugin name");
+else if (!is_string($plugin))
+       return error400($host.'/?-?/?', "Plugin name must be a string");
+else if (strlen($plugin) == 0)
+       return error400($host.'/?-?/?', "Plugin name may not be blank");
+
+$pinst    = read_var('plugin_instance', $_GET, '');
+if (!is_string($pinst))
+       return error400($host.'/'.$plugin.'-?/?', "Plugin instance name must be a string");
+
+$type     = read_var('type', $_GET, '');
+if (is_null($type))
+       return error400($host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/?', "Missing type name");
+else if (!is_string($type))
+       return error400($host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/?', "Type name must be a string");
+else if (strlen($type) == 0)
+       return error400($host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/?', "Type name may not be blank");
+
+$tinst    = read_var('type_instance', $_GET, '');
+
+$graph_identifier = $host.'/'.$plugin.(strlen($pinst) ? '-'.$pinst : '').'/'.$type.(strlen($tinst) ? '-'.$tinst : '-*');
+
+$timespan = read_var('timespan', $_GET, $config['timespan'][0]['name']);
+$timespan_ok = false;
+foreach ($config['timespan'] as &$ts)
+       if ($ts['name'] == $timespan)
+               $timespan_ok = true;
+if (!$timespan_ok)
+       return error400($graph_identifier, "Unknown timespan requested");
+
+$logscale   = (boolean)read_var('logarithmic', $_GET, false);
+$tinylegend = (boolean)read_var('tinylegend', $_GET, false);
+
+// Check that at least 1 RRD exists for the specified request
+$all_tinst = collectd_list_types($host, $plugin, $pinst, $type);
+if (count($all_tinst) == 0)
+       return error404($graph_identifier, "No rrd file found for graphing");
+
+// Now that we are read, do the bulk work
+load_graph_definitions($logscale, $tinylegend);
+
+$pinst = strlen($pinst) == 0 ? null : $pinst;
+$tinst = strlen($tinst) == 0 ? null : $tinst;
+
+$opts  = array();
+$opts['timespan'] = $timespan;
+if ($logscale)
+       $opts['logarithmic'] = 1;
+if ($tinylegend)
+       $opts['tinylegend']  = 1;
+
+$rrd_cmd = false;
+if ((is_null($tinst) || $tinst == '@merge') && isset($MetaGraphDefs[$type])) {
+       $identifiers = array();
+       foreach ($all_tinst as &$atinst)
+               $identifiers[] = collectd_identifier($host, $plugin, is_null($pinst) ? '' : $pinst, $type, $atinst);
+       collectd_flush($identifiers);
+       $rrd_cmd = $MetaGraphDefs[$type]($host, $plugin, $pinst, $type, $all_tinst, $opts);
+} else {
+       if (!in_array(is_null($tinst) ? '' : $tinst, $all_tinst))
+               return error404($host.'/'.$plugin.(!is_null($pinst) ? '-'.$pinst : '').'/'.$type.(!is_null($tinst) ? '-'.$tinst : ''), "No rrd file found for graphing");
+       collectd_flush(collectd_identifier($host, $plugin, is_null($pinst) ? '' : $pinst, $type, is_null($tinst) ? '' : $tinst));
+       if (isset($GraphDefs[$type]))
+               $rrd_cmd = collectd_draw_generic($timespan, $host, $plugin, $pinst, $type, $tinst);
+       else
+               $rrd_cmd = collectd_draw_rrd($host, $plugin, $pinst, $type, $tinst);
+}
+
+if (isset($_GET['debug'])) {
+       header('Content-Type: text/plain; charset=utf-8');
+       printf("Would have executed:\n%s\n", $rrd_cmd);
+       return 0;
+} else if ($rrd_cmd) {
+       header('Content-Type: image/png');
+       header('Cache-Control: max-age=60');
+       $rt = 0;
+       passthru($rrd_cmd, $rt);
+       if ($rt != 0)
+               return error500($graph_identifier, "RRD failed to generate the graph: ".$rt);
+       return $rt;
+} else {
+       return error500($graph_identifier, "Failed to tell RRD how to generate the graph");
+}
+
+?>
diff --git a/contrib/php-collection/index.php b/contrib/php-collection/index.php
new file mode 100644 (file)
index 0000000..5953fbd
--- /dev/null
@@ -0,0 +1,330 @@
+<?php // vim:fenc=utf-8:filetype=php:ts=4
+/*
+ * Copyright (C) 2009  Bruno Prémont <bonbons AT linux-vserver.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+error_reporting(E_ALL | E_NOTICE | E_WARNING);
+
+require('config.php');
+require('functions.php');
+
+/**
+ * Send back new list content
+ * @items Array of options values to return to browser
+ * @method Name of Javascript method that will be called to process data
+ */
+function dhtml_response_list(&$items, $method) {
+       header("Content-Type: text/xml");
+
+       print('<?xml version="1.0" encoding="utf-8" ?>'."\n");
+       print("<response>\n");
+       printf(" <method>%s</method>\n", htmlspecialchars($method));
+       print(" <result>\n");
+       foreach ($items as &$item)
+               printf('  <option>%s</option>'."\n", htmlspecialchars($item));
+       print(" </result>\n");
+       print("</response>");
+}
+
+function dhtml_response_graphs(&$graphs, $method) {
+       header("Content-Type: text/xml");
+
+       print('<?xml version="1.0" encoding="utf-8" ?>'."\n");
+       print("<response>\n");
+       printf(" <method>%s</method>\n", htmlspecialchars($method));
+       print(" <result>\n");
+       foreach ($graphs as &$graph)
+               printf('  <graph host="%s" plugin="%s" plugin_instance="%s" type="%s" type_instance="%s" timespan="%s" logarithmic="%d" tinyLegend="%d" />'."\n",
+                      htmlspecialchars($graph['host']), htmlspecialchars($graph['plugin']), htmlspecialchars($graph['pinst']),
+                      htmlspecialchars($graph['type']), htmlspecialchars($graph['tinst']), htmlspecialchars($graph['timespan']),
+                      htmlspecialchars($graph['logarithmic']), htmlspecialchars($graph['tinyLegend']));
+       print(" </result>\n");
+       print("</response>");
+}
+
+/**
+ * Product page body with selection fields
+ */
+function build_page() {
+       global $config;
+
+       if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/compatible; MSIE [0-9]+.[0-9];/', $_SERVER['HTTP_USER_AGENT'])) {
+               // Internet Explorer does not support XHTML
+               header("Content-Type: text/html");
+
+               print('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">');
+               print('<html lang="en">'."\n");
+       } else {
+               header("Content-Type: application/xhtml+xml");
+
+               print('<?xml version="1.0" encoding="utf-8" ?>'."\n");
+               print('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'."\n");
+               print('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">'."\n");
+       }
+       $url_base = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
+?>
+       <head>
+               <title>Collectd graph viewer</title>
+               <link rel="icon" href="favicon.png" type="image/png" />
+               <style type="text/css">
+                       body, html { background-color: #EEEEEE; color: #000000; }
+                       h1 { text-align: center; }
+                       div.body { margin: auto; width: <?php echo isset($config['rrd_width']) ? 110+(int)$config['rrd_width'] : 600; ?>px; background: #FFFFFF; border: 1px solid #DDDDDD; }
+                       p.error { color: #CC0000; margin: 0em; }
+                       div.selector { margin: 0.5em 2em; }
+                       div.selectorbox { padding: 5px; border: 1px solid #CCCCCC; background-color: #F8F8F8; }
+                       div.selectorbox table { border: none; }
+                       div.selectorbox table td.s1 { border-bottom: 1px dashed #F0F0F0; padding-right: 1em; vertical-align: middle; }
+                       div.selectorbox table td.s2 { border-bottom: 1px dashed #F0F0F0; vertical-align: middle; }
+                       div.selectorbox table td.s3 { vertical-align: middle; }
+                       div.selectorbox table td.sc { padding: 0.5em 2em; text-align: center; }
+                       a img { border: none; }
+                       div.graphs { border-top: 1px solid #DDDDDD; padding: 5px; overflow: auto; }
+                       div.graphs_t { position: relative; }
+                       div.graph { text-align: right; }
+                       div.selector select { width: 100%; }
+                       table.toolbox { border: 1px solid #5500dd; padding: 0px; margin: 0px; background: #ffffff;}
+                       table.toolbox td.c1 { vertical-align: middle; text-align: left; padding-left: 0.3em; padding-right: 1em; border-right: 1px solid #5500dd; }
+                       table.toolbox td.c2 { vertical-align: middle; text-align: center; padding-left: 5px; padding-right: 5px; }
+               </style>
+               <script type="text/javascript">// <![CDATA[
+var dhtml_url = '<?php echo addslashes($url_base.basename($_SERVER['PHP_SELF'])); ?>';
+var graph_url = '<?php echo addslashes($url_base.'graph.php'); ?>';
+//             ]]></script>
+               <script type="text/javascript" src="<?php echo htmlspecialchars($url_base.'browser.js'); ?>"></script>
+       </head>
+
+       <body onload="ListRefreshHost(); GraphListRefresh(); "><div class="body">
+               <h1><img src="collectd-logo.png" align="bottom" alt="" /> Collectd browser for system statistics graphs</h1>
+               <div class="selector"><a href="javascript:toggleDiv('selector')"><span id="selector_sw">Hide</span> graph selection tool</a><div id="selector" class="selectorbox">
+                       <table>
+                               <tr>
+                                       <td class="s1">Host:</td>
+                                       <td class="s2"><select id="host_list"   name="host"   disabled="disabled" onchange="ListRefreshPlugin()">
+                                       </select></td>
+                                       <td class="s3"><a href="javascript:ListRefreshHost()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh host list" /></a></td>
+                               </tr>
+                               <tr>
+                                       <td class="s1">Plugin:</td>
+                                       <td class="s2"><select id="plugin_list" name="plugin" disabled="disabled" onchange="ListRefreshPluginInstance()">
+                                       </select></td>
+                                       <td class="s3"><a href="javascript:ListRefreshPlugin()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh plugin list" /></a></td>
+                               </tr>
+                               <tr>
+                                       <td class="s1">Plugin instance:</td>
+                                       <td class="s2"><select id="pinst_list"  name="pinst"  disabled="disabled" onchange="ListRefreshType()">
+                                       </select></td>
+                                       <td class="s3"><a href="javascript:ListRefreshPluginInstance()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh plugin instance list" /></a></td>
+                               </tr>
+                               <tr>
+                                       <td class="s1">Type:</td>
+                                       <td class="s2"><select id="type_list"   name="type"   disabled="disabled" onchange="ListRefreshTypeInstance()">
+                                       </select></td>
+                                       <td class="s3"><a href="javascript:ListRefreshType()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh type list" /></a></td>
+                               </tr>
+                               <tr>
+                                       <td class="s1">Type instance:</td>
+                                       <td class="s2"><select id="tinst_list"  name="tinst"  disabled="disabled" onchange="RefreshButtons()">
+                                       </select></td>
+                                       <td class="s3"><a href="javascript:ListRefreshTypeInstance()"><img src="refresh.png" width="16" height="16" alt="R" title="Refresh type instance list" /></a></td>
+                               </tr>
+                               <tr>
+                                       <td class="s1">Graph settings:</td>
+                                       <td class="s2"><select id="timespan" name="timespan">
+<?php                          foreach ($config['timespan'] as &$timespan)
+                                               printf("\t\t\t\t\t\t<option value=\"%s\">%s</option>\n", htmlspecialchars($timespan['name']), htmlspecialchars($timespan['label']));
+?>                                     </select>
+                                       <br /><label><input id="logarithmic"  name="logarithmic" type="checkbox" value="1" /> Logarithmic scale</label>
+                                       <br /><label><input id="tinylegend"  name="tinylegend" type="checkbox" value="1" /> Minimal legend</label></td>
+                                       <td class="s3"></td>
+                               </tr>
+                               <tr>
+                                       <td class="sc" colspan="3"><input id="btnAdd"     name="btnAdd"     type="button" disabled="disabled" onclick="GraphAppend()" value="Add graph" />
+                                       <input id="btnClear"   name="btnClear"   type="button" disabled="disabled" onclick="GraphDropAll()" value="Remove all graphs" />
+                                       <input id="btnRefresh" name="btnRefresh" type="button" disabled="disabled" onclick="GraphRefreshAll()" value="Refresh all graphs" /></td>
+                               </tr>
+                               <tr>
+                                       <td class="s1" rowspan="2">Graph list favorites:</td>
+                                       <td class="s3"><input type="text" style="width: 100%" maxlength="30" id="GraphListName" name="GraphListName" value="default" onchange="GraphListCheckName(false)" /></td>
+                                       <td class="s3"><a href="javascript:GraphSave()"><img src="save.png" width="16" height="16" alt="S" title="Save graph list to cookie" /></a></td>
+                               </tr>
+                               <tr>
+                                       <td class="s2"><select id="GraphList" name="GraphList" onfocus="GraphListRefresh()">
+                                               <option value="default">default</option>
+                                       </select></td>
+                                       <td class="s3"><a href="javascript:GraphLoad()"><img src="load.png" width="16" height="16" alt="L" title="Load graph list from cookie" /></a><a href="javascript:GraphDrop()"><img src="delete.png" width="16" height="16" alt="D" title="Delete graph list from cookie" /></a></td>
+                               </tr>
+                       </table>
+               </div></div>
+               <div class="graphs"><div id="graphs" class="graphs_t">
+                       <div id="nograph">Please use above graph selection tool to add graphs to this area.<?php
+                       // Config checking
+                       if (!isset($config['datadirs']))
+                               echo '<p class="error">Config error: $config["datadirs"] is not set</p>';
+                       else if (!is_array($config['datadirs']))
+                               echo '<p class="error">Config error: $config["datadirs"] is not an array</p>';
+                       else if (count($config['datadirs']) == 0)
+                               echo '<p class="error">Config error: $config["datadirs"] is empty</p>';
+                       else foreach ($config['datadirs'] as $datadir)
+                               if (!is_dir($datadir))
+                                       echo '<p class="error">Config error: $config["datadirs"], '.htmlspecialchars($datadir).' does not exist</p>';
+                       if (!isset($config['rrd_width']))
+                               echo '<p class="error">Config error: $config["rrd_width"] is not set</p>';
+                       else if (10 > (int)$config['rrd_width'])
+                               echo '<p class="error">Config error: $config["rrd_width"] is invalid. Integer >= 10 expected</p>';
+                       if (!isset($config['rrd_height']))
+                               echo '<p class="error">Config error: $config["rrd_height"] is not set</p>';
+                       else if (10 > (int)$config['rrd_height'])
+                               echo '<p class="error">Config error: $config["rrd_height"] is invalid. Integer >= 10 expected</p>';
+                       if (!isset($config['rrd_opts']))
+                               echo '<p class="error">Config error: $config["rrd_opts"] is not set</p>';
+                       else if (!is_array($config['rrd_opts']))
+                               echo '<p class="error">Config error: $config["rrd_opts"] is not an array</p>';
+                       if (!isset($config['timespan']))
+                               echo '<p class="error">Config error: $config["timespan"] is not set</p>';
+                       else if (!is_array($config['timespan']))
+                               echo '<p class="error">Config error: $config["timespan"] is not an array</p>';
+                       else if (count($config['timespan']) == 0)
+                               echo '<p class="error">Config error: $config["timespan"] is empty</p>';
+                       else foreach ($config['timespan'] as &$timespan)
+                               if (!is_array($timespan) || !isset($timespan['name']) || !isset($timespan['label']) || !isset($timespan['seconds']) || 10 > (int)$timespan['seconds'])
+                                       echo '<p class="error">Config error: $config["timespan"], invalid entry found</p>';
+                       if (!is_null($config['collectd_sock']) && strncmp('unix://', $config['collectd_sock'], 7) != 0)
+                               echo '<p class="error">Config error: $config["collectd_sock"] is not valid</p>';
+                       if (!defined('RRDTOOL'))
+                               echo '<p class="error">Config error: RRDTOOL is not defined</p>';
+                       else if (!is_executable(RRDTOOL))
+                               echo '<p class="error">Config error: RRDTOOL ('.htmlspecialchars(RRDTOOL).') is not executable</p>';
+                       ?></div>
+               </div></div>
+               <input type="hidden" name="ge_graphid" id="ge_graphid" value="" />
+               <table id="ge" class="toolbox" style="position: absolute; display: none; " cellspacing="1" cellpadding="0">
+                       <tr>
+                               <td class="c1" rowspan="3"><select id="ge_timespan" name="ge_timespan" onchange="GraphAdjust(null)"><?php
+                               foreach ($config['timespan'] as &$timespan)
+                                       printf("\t\t\t\t\t\t<option value=\"%s\">%s</option>\n", htmlspecialchars($timespan['name']), htmlspecialchars($timespan['label']));
+                               ?></select><br />
+                               <label><input id="ge_logarithmic"  name="ge_logarithmic" type="checkbox" value="1" onchange="GraphAdjust(null)" /> Logarithmic scale</label><br />
+                               <label><input id="ge_tinylegend"  name="ge_tinylegend" type="checkbox" value="1" onchange="GraphAdjust(null)" /> Minimal legend</label></td>
+                               <td class="c2"><a href="javascript:GraphMoveUp(null)"><img src="move-up.png" alt="UP" title="Move graph up"/></a></td>
+                       </tr>
+                       <tr>
+                               <td class="c2"><a href="javascript:GraphRefresh(null)"><img src="refresh.png" alt="R" title="Refresh graph"/></a>&nbsp;<a href="javascript:GraphRemove(null)"><img src="delete.png" alt="RM" title="Remove graph"/></a></td>
+                       </tr>
+                       <tr>
+                               <td class="c2"><a href="javascript:GraphMoveDown(null)"><img src="move-down.png" alt="DN" title="Move graph down"/></a></td>
+                       </tr>
+               </table>
+       </div></body>
+</html><?php
+}
+
+
+/*
+ * Select action based on user input
+ */
+$action = read_var('action', $_POST, 'overview');
+switch ($action) {
+       case 'list_hosts':
+               // Generate a list of hosts
+               $hosts = collectd_list_hosts();
+               if (count($hosts) > 1)
+                       array_unshift($hosts, '@all');
+               return dhtml_response_list($hosts, 'ListOfHost');
+
+       case 'list_plugins':
+               // Generate list of plugins for selected hosts
+               $arg_hosts = read_var('host', $_POST, '');
+               if (is_array($arg_hosts))
+                       $arg_hosts = reset($arg_hosts);
+               $plugins = collectd_list_plugins($arg_hosts);
+               if (count($plugins) > 1)
+                       array_unshift($plugins, '@all');
+               return dhtml_response_list($plugins, 'ListOfPlugin');
+
+       case 'list_pinsts':
+               // Generate list of plugin_instances for selected hosts and plugin
+               $arg_hosts = read_var('host', $_POST, '');
+               if (is_array($arg_hosts))
+                       $arg_hosts = reset($arg_hosts);
+               $arg_plugin = read_var('plugin', $_POST, '');
+               $pinsts = collectd_list_plugins($arg_hosts, $arg_plugin);
+               if (count($pinsts) > 1)
+                       array_unshift($pinsts, '@all' /* , '@merge_sum', '@merge_avg', '@merge_stack', '@merge_line' */);
+               return dhtml_response_list($pinsts, 'ListOfPluginInstance');
+
+       case 'list_types':
+               // Generate list of types for selected hosts, plugin and plugin-instance
+               $arg_hosts  = read_var('host', $_POST, '');
+               if (is_array($arg_hosts))
+                       $arg_hosts = reset($arg_hosts);
+               $arg_plugin = read_var('plugin', $_POST, '');
+               $arg_pinst  = read_var('plugin_instance', $_POST, '');
+               $types = collectd_list_types($arg_hosts, $arg_plugin, $arg_pinst);
+               if (count($types) > 1)
+                       array_unshift($types, '@all');
+               return dhtml_response_list($types, 'ListOfType');
+
+       case 'list_tinsts':
+               // Generate list of types for selected hosts, plugin and plugin-instance
+               $arg_hosts  = read_var('host', $_POST, '');
+               if (is_array($arg_hosts))
+                       $arg_hosts = reset($arg_hosts);
+               $arg_plugin = read_var('plugin', $_POST, '');
+               $arg_pinst  = read_var('plugin_instance', $_POST, '');
+               $arg_type   = read_var('type', $_POST, '');
+               $tinsts = collectd_list_types($arg_hosts, $arg_plugin, $arg_pinst, $arg_type);
+               if (count($tinsts))
+                       if ($arg_type != '@all') {
+                               require('definitions.php');
+                               load_graph_definitions();
+                               if (isset($MetaGraphDefs[$arg_type]))
+                                       array_unshift($tinsts, '@merge');
+                               if (count($tinsts) > 1)
+                                       array_unshift($tinsts, '@all');
+                       } else {
+                               array_unshift($tinsts, /* '@merge_sum', '@merge_avg', '@merge_stack', '@merge_line', */ '@merge');
+                               if (count($tinsts) > 1)
+                                       array_unshift($tinsts, '@all');
+                       }
+               return dhtml_response_list($tinsts, 'ListOfTypeInstance');
+
+       case 'list_graphs':
+               // Generate list of types for selected hosts, plugin and plugin-instance
+               $arg_hosts  = read_var('host', $_POST, '');
+               if (is_array($arg_hosts))
+                       $arg_hosts = reset($arg_hosts);
+               $arg_plugin = read_var('plugin', $_POST, '');
+               $arg_pinst  = read_var('plugin_instance', $_POST, '');
+               $arg_type   = read_var('type', $_POST, '');
+               $arg_tinst  = read_var('type_instance', $_POST, '');
+               $arg_log    = (int)read_var('logarithmic', $_POST, '0');
+               $arg_legend = (int)read_var('tinyLegend', $_POST, '0');
+               $arg_period = read_var('timespan', $_POST, '');
+               $graphs = collectd_list_graphs($arg_hosts, $arg_plugin, $arg_pinst, $arg_type, $arg_tinst);
+               foreach ($graphs as &$graph) {
+                       $graph['logarithmic'] = $arg_log;
+                       $graph['tinyLegend']  = $arg_legend;
+                       $graph['timespan']    = $arg_period;
+               }
+               return dhtml_response_graphs($graphs, 'ListOfGraph');
+
+       case 'overview':
+       default:
+               return build_page();
+               break;
+}
+?>
diff --git a/contrib/postgresql/collectd_insert.sql b/contrib/postgresql/collectd_insert.sql
new file mode 100644 (file)
index 0000000..bee182c
--- /dev/null
@@ -0,0 +1,234 @@
+-- collectd - contrib/postgresql/collectd_insert.sql
+-- Copyright (C) 2012 Sebastian 'tokkee' Harl
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions
+-- are met:
+--
+-- - Redistributions of source code must retain the above copyright
+--   notice, this list of conditions and the following disclaimer.
+--
+-- - Redistributions in binary form must reproduce the above copyright
+--   notice, this list of conditions and the following disclaimer in the
+--   documentation and/or other materials provided with the distribution.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+
+-- Description:
+-- ------------
+--
+-- This is a sample database setup that may be used to write data collected by
+-- collectd to a PostgreSQL database. We're using two tables, 'identifiers'
+-- and 'values' to store the value-list identifier and the actual values
+-- respectively.
+--
+-- The 'values' table is partitioned to improve performance and maintenance.
+-- Please note that additional maintenance scripts are required in order to
+-- keep the setup running -- see the comments below for details.
+--
+-- The function 'collectd_insert' may be used to actually insert values
+-- submitted by collectd into those tables.
+--
+-- Sample configuration:
+-- ---------------------
+--
+-- <Plugin postgresql>
+--     <Writer sqlstore>
+--         Statement "SELECT collectd_insert($1, $2, $3, $4, $5, $6, $7, $8, $9);"
+--     </Writer>
+--     <Database foo>
+--         # ...
+--         Writer sqlstore
+--     </Database>
+-- </Plugin>
+
+CREATE TABLE identifiers (
+    id integer NOT NULL,
+    host character varying(64) NOT NULL,
+    plugin character varying(64) NOT NULL,
+    plugin_inst character varying(64) DEFAULT NULL::character varying,
+    type character varying(64) NOT NULL,
+    type_inst character varying(64) DEFAULT NULL::character varying
+);
+CREATE SEQUENCE identifiers_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+ALTER SEQUENCE identifiers_id_seq OWNED BY identifiers.id;
+ALTER TABLE ONLY identifiers
+    ALTER COLUMN id SET DEFAULT nextval('identifiers_id_seq'::regclass);
+ALTER TABLE ONLY identifiers
+    ADD CONSTRAINT identifiers_host_plugin_plugin_inst_type_type_inst_key
+        UNIQUE (host, plugin, plugin_inst, type, type_inst);
+ALTER TABLE ONLY identifiers
+    ADD CONSTRAINT identifiers_pkey PRIMARY KEY (id);
+
+-- optionally, create indexes for the identifier fields
+CREATE INDEX identifiers_host ON identifiers USING btree (host);
+CREATE INDEX identifiers_plugin ON identifiers USING btree (plugin);
+CREATE INDEX identifiers_plugin_inst ON identifiers USING btree (plugin_inst);
+CREATE INDEX identifiers_type ON identifiers USING btree (type);
+CREATE INDEX identifiers_type_inst ON identifiers USING btree (type_inst);
+
+CREATE TABLE "values" (
+    id integer NOT NULL,
+    tstamp timestamp with time zone NOT NULL,
+    name character varying(64) NOT NULL,
+    value double precision NOT NULL
+);
+
+CREATE OR REPLACE VIEW collectd
+    AS SELECT host, plugin, plugin_inst, type, type_inst,
+            host
+                || '/' || plugin
+                || CASE
+                    WHEN plugin_inst IS NOT NULL THEN '-'
+                    ELSE ''
+                END
+                || coalesce(plugin_inst, '')
+                || '/' || type
+                || CASE
+                    WHEN type_inst IS NOT NULL THEN '-'
+                    ELSE ''
+                END
+                || coalesce(type_inst, '') AS identifier,
+            tstamp, name, value
+        FROM identifiers
+            JOIN values
+            ON values.id = identifiers.id;
+
+-- partition "values" by day (or week, month, ...)
+
+-- create the child tables for today and the next 'days' days:
+-- this may, for example, be used in a daily cron-job (or similar) to create
+-- the tables for the next couple of days
+CREATE OR REPLACE FUNCTION values_update_childs(
+        integer
+    ) RETURNS SETOF text
+    LANGUAGE plpgsql
+    AS $_$
+DECLARE
+    days alias for $1;
+    cur_day date;
+    next_day date;
+    i integer;
+BEGIN
+    IF days < 1 THEN
+        RAISE EXCEPTION 'Cannot have negative number of days';
+    END IF;
+
+    i := 0;
+    LOOP
+        EXIT WHEN i > days;
+
+        SELECT CAST ('now'::date + i * '1day'::interval AS date) INTO cur_day;
+        SELECT CAST ('now'::date + (i + 1) * '1day'::interval AS date) INTO next_day;
+
+        i := i + 1;
+
+        BEGIN
+            EXECUTE 'CREATE TABLE "values$' || cur_day || '" (
+                CHECK (tstamp >= TIMESTAMP ''' || cur_day || ''' '
+                    || 'AND tstamp < TIMESTAMP ''' || next_day || ''')
+            ) INHERITS (values)';
+        EXCEPTION WHEN duplicate_table THEN
+            CONTINUE;
+        END;
+
+        RETURN NEXT 'values$' || cur_day::text;
+
+        EXECUTE 'ALTER TABLE ONLY "values$' || cur_day || '"
+            ADD CONSTRAINT "values_' || cur_day || '_pkey"
+                PRIMARY KEY (id, tstamp, name, value)';
+        EXECUTE 'ALTER TABLE ONLY "values$' || cur_day || '"
+            ADD CONSTRAINT "values_' || cur_day || '_id_fkey"
+                FOREIGN KEY (id) REFERENCES identifiers(id)';
+    END LOOP;
+    RETURN;
+END;
+$_$;
+
+-- create initial child tables
+SELECT values_update_childs(2);
+
+CREATE OR REPLACE FUNCTION values_insert_trigger()
+    RETURNS trigger
+    LANGUAGE plpgsql
+    AS $_$
+DECLARE
+    child_tbl character varying;
+BEGIN
+    SELECT 'values$' || CAST (NEW.tstamp AS DATE) INTO child_tbl;
+    -- Rather than using 'EXECUTE', some if-cascade checking the date may also
+    -- be used. However, this would require frequent updates of the trigger
+    -- function while this example works automatically.
+    EXECUTE 'INSERT INTO "' || child_tbl || '" VALUES ($1.*)' USING NEW;
+    RETURN NULL;
+END;
+$_$;
+
+CREATE TRIGGER insert_values_trigger
+    BEFORE INSERT ON values
+    FOR EACH ROW EXECUTE PROCEDURE values_insert_trigger();
+
+-- when querying values make sure to enable constraint exclusion
+-- SET constraint_exclusion = on;
+
+CREATE OR REPLACE FUNCTION collectd_insert(
+        timestamp with time zone, character varying,
+        character varying, character varying,
+        character varying, character varying,
+        character varying[], character varying[], double precision[]
+    ) RETURNS void
+    LANGUAGE plpgsql
+    AS $_$
+DECLARE
+    p_time alias for $1;
+    p_host alias for $2;
+    p_plugin alias for $3;
+    p_plugin_instance alias for $4;
+    p_type alias for $5;
+    p_type_instance alias for $6;
+    p_value_names alias for $7;
+    -- don't use the type info; for 'StoreRates true' it's 'gauge' anyway
+    -- p_type_names alias for $8;
+    p_values alias for $9;
+    ds_id integer;
+    i integer;
+BEGIN
+    SELECT id INTO ds_id
+        FROM identifiers
+        WHERE host = p_host
+            AND plugin = p_plugin
+            AND COALESCE(plugin_inst, '') = COALESCE(p_plugin_instance, '')
+            AND type = p_type
+            AND COALESCE(type_inst, '') = COALESCE(p_type_instance, '');
+    IF NOT FOUND THEN
+        INSERT INTO identifiers (host, plugin, plugin_inst, type, type_inst)
+            VALUES (p_host, p_plugin, p_plugin_instance, p_type, p_type_instance)
+            RETURNING id INTO ds_id;
+    END IF;
+    i := 1;
+    LOOP
+        EXIT WHEN i > array_upper(p_value_names, 1);
+        INSERT INTO values (id, tstamp, name, value)
+            VALUES (ds_id, p_time, p_value_names[i], p_values[i]);
+        i := i + 1;
+    END LOOP;
+END;
+$_$;
+
+-- vim: set expandtab :
diff --git a/contrib/python/getsigchld.py b/contrib/python/getsigchld.py
new file mode 100644 (file)
index 0000000..557adc0
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+###############################################################################
+#         WARNING! Importing this script will break the exec plugin!          #
+###############################################################################
+# Use this if you want to create new processes from your python scripts.      #
+# Normally you will get a OSError exception when the new process terminates   #
+# because collectd will ignore the SIGCHLD python is waiting for.             #
+# This script will restore the default SIGCHLD behavior so python scripts can #
+# create new processes without errors.                                        #
+###############################################################################
+#         WARNING! Importing this script will break the exec plugin!          #
+###############################################################################
+
+import signal
+import collectd
+
+def init():
+       signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+
+collectd.register_init(init)
diff --git a/contrib/redhat/collectd.spec b/contrib/redhat/collectd.spec
new file mode 100644 (file)
index 0000000..9d491ff
--- /dev/null
@@ -0,0 +1,2556 @@
+#
+# q: What is this ?
+# a: A specfile for building RPM packages of current collectd releases, for
+#    RHEL/CentOS versions 5, 6 and 7. By default all the plugins which are
+#    buildable based on the libraries available in the distribution + the
+#    EPEL repository, will be built. Plugins depending on external libs will
+#    be packaged in separate RPMs.
+#
+# q: And how can I do that ?
+# a: By following these instructions, using mock:
+#
+# - install and configure mock (https://fedoraproject.org/wiki/Projects/Mock)
+#
+# - enable the EPEL repository (http://dl.fedoraproject.org/pub/epel/) in the
+#   configuration files for your target systems (/etc/mock/*.cfg).
+#
+# - fetch the desired collectd release file from https://collectd.org/files/
+#   and save it in your ~/rpmbuild/SOURCES/ directory (or build your own out of
+#   the git repository: ./build.sh && ./configure && make-dist-bz2)
+#
+# - copy this file in your ~/rpmbuild/SPECS/ directory. Make sure the
+#   "Version:" tag matches the version from the tarball.
+#
+# - build the SRPM first:
+#   mock -r centos-6-x86_64 --buildsrpm --spec ~/rpmbuild/SPECS/collectd.spec \
+#     --sources ~/rpmbuild/SOURCES/
+#
+# - then build the RPMs:
+#   mock -r centos-6-x86_64 --no-clean --rebuild \
+#     /var/lib/mock/centos-6-x86_64/result/collectd-X.Y.Z-NN.src.rpm
+#
+# - you can also optionally enable/disable plugins which are disabled/enabled
+#   by default:
+#   mock -r centos-6-x86_64 --no-clean --without=java --with=oracle --rebuild \
+#     /var/lib/mock/centos-6-x86_64/result/collectd-X.Y.Z-NN.src.rpm
+#
+
+%global _hardened_build 1
+%{?perl_default_filter}
+
+# plugins only buildable on RHEL6
+# (NB: %{elN} macro is not available on RHEL < 6)
+%{?el6:%global _has_libyajl 1}
+%{?el6:%global _has_recent_libpcap 1}
+%{?el6:%global _has_recent_sockios_h 1}
+%{?el6:%global _has_recent_libganglia 1}
+%{?el6:%global _has_working_libiptc 1}
+%{?el6:%global _has_ip_vs_h 1}
+%{?el6:%global _has_lvm2app_h 1}
+%{?el6:%global _has_libmodbus 1}
+%{?el6:%global _has_libudev 1}
+%{?el6:%global _has_iproute 1}
+%{?el6:%global _has_atasmart 1}
+%{?el6:%global _has_hiredis 1}
+%{?el6:%global _has_asm_msr_index 1}
+
+%{?el7:%global _has_libyajl 1}
+%{?el7:%global _has_recent_libpcap 1}
+%{?el7:%global _has_recent_sockios_h 1}
+%{?el7:%global _has_working_libiptc 1}
+%{?el7:%global _has_ip_vs_h 1}
+%{?el7:%global _has_lvm2app_h 1}
+%{?el7:%global _has_libudev 1}
+%{?el7:%global _has_recent_librrd 1}
+%{?el7:%global _has_varnish4 1}
+%{?el7:%global _has_broken_libmemcached 1}
+%{?el7:%global _has_iproute 1}
+%{?el7:%global _has_atasmart 1}
+%{?el7:%global _has_hiredis 1}
+%{?el7:%global _has_asm_msr_index 1}
+
+# plugins enabled by default
+%define with_aggregation 0%{!?_without_aggregation:1}
+%define with_amqp 0%{!?_without_amqp:1}
+%define with_apache 0%{!?_without_apache:1}
+%define with_apcups 0%{!?_without_apcups:1}
+%define with_ascent 0%{!?_without_ascent:1}
+%define with_battery 0%{!?_without_battery:1}
+%define with_bind 0%{!?_without_bind:1}
+%define with_ceph 0%{!?_without_ceph:0%{?_has_libyajl}}
+%define with_cgroups 0%{!?_without_cgroups:1}
+%define with_conntrack 0%{!?_without_conntrack:1}
+%define with_contextswitch 0%{!?_without_contextswitch:1}
+%define with_cpu 0%{!?_without_cpu:1}
+%define with_cpufreq 0%{!?_without_cpufreq:1}
+%define with_csv 0%{!?_without_csv:1}
+%define with_curl 0%{!?_without_curl:1}
+%define with_curl_json 0%{!?_without_curl_json:0%{?_has_libyajl}}
+%define with_curl_xml 0%{!?_without_curl_xml:1}
+%define with_dbi 0%{!?_without_dbi:1}
+%define with_df 0%{!?_without_df:1}
+%define with_disk 0%{!?_without_disk:1}
+%define with_dns 0%{!?_without_dns:0%{?_has_recent_libpcap}}
+%define with_drbd 0%{!?_without_drbd:1}
+%define with_email 0%{!?_without_email:1}
+%define with_entropy 0%{!?_without_entropy:1}
+%define with_ethstat 0%{!?_without_ethstat:0%{?_has_recent_sockios_h}}
+%define with_exec 0%{!?_without_exec:1}
+%define with_fhcount 0%{!?_without_fhcount:1}
+%define with_filecount 0%{!?_without_filecount:1}
+%define with_fscache 0%{!?_without_fscache:1}
+%define with_gmond 0%{!?_without_gmond:0%{?_has_recent_libganglia}}
+%define with_hddtemp 0%{!?_without_hddtemp:1}
+%define with_interface 0%{!?_without_interface:1}
+%define with_ipc 0%{!?_without_ipc:1}
+%define with_ipmi 0%{!?_without_ipmi:1}
+%define with_iptables 0%{!?_without_iptables:0%{?_has_working_libiptc}}
+%define with_ipvs 0%{!?_without_ipvs:0%{?_has_ip_vs_h}}
+%define with_irq 0%{!?_without_irq:1}
+%define with_java 0%{!?_without_java:1}
+%define with_virt 0%{!?_without_virt:1}
+%define with_load 0%{!?_without_load:1}
+%define with_logfile 0%{!?_without_logfile:1}
+%define with_log_logstash 0%{!?_without_log_logstash:0%{?_has_libyajl}}
+%define with_lvm 0%{!?_without_lvm:0%{?_has_lvm2app_h}}
+%define with_madwifi 0%{!?_without_madwifi:1}
+%define with_mbmon 0%{!?_without_mbmon:1}
+%define with_md 0%{!?_without_md:1}
+%define with_memcachec 0%{!?_without_memcachec:0%{!?_has_broken_libmemcached:1}}
+%define with_memcached 0%{!?_without_memcached:1}
+%define with_memory 0%{!?_without_memory:1}
+%define with_multimeter 0%{!?_without_multimeter:1}
+%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}}
+%define with_mysql 0%{!?_without_mysql:1}
+%define with_netlink 0%{!?_without_netlink:0%{?_has_iproute}}
+%define with_network 0%{!?_without_network:1}
+%define with_nfs 0%{!?_without_nfs:1}
+%define with_nginx 0%{!?_without_nginx:1}
+%define with_notify_desktop 0%{!?_without_notify_desktop:1}
+%define with_notify_email 0%{!?_without_notify_email:1}
+%define with_ntpd 0%{!?_without_ntpd:1}
+%define with_numa 0%{!?_without_numa:1}
+%define with_nut 0%{!?_without_nut:1}
+%define with_olsrd 0%{!?_without_olsrd:1}
+%define with_openldap 0%{!?_without_openldap:1}
+%define with_openvpn 0%{!?_without_openvpn: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_protocols 0%{!?_without_protocols:1}
+%define with_python 0%{!?_without_python:1}
+%define with_redis 0%{!?_without_redis:0%{?_has_hiredis}}
+%define with_rrdcached 0%{!?_without_rrdcached:0%{?_has_recent_librrd}}
+%define with_rrdtool 0%{!?_without_rrdtool:1}
+%define with_sensors 0%{!?_without_sensors:1}
+%define with_serial 0%{!?_without_serial:1}
+%define with_smart 0%{!?_without_smart:0%{?_has_atasmart}}
+%define with_snmp 0%{!?_without_snmp:1}
+%define with_statsd 0%{!?_without_statsd:1}
+%define with_swap 0%{!?_without_swap:1}
+%define with_syslog 0%{!?_without_syslog:1}
+%define with_table 0%{!?_without_table:1}
+%define with_tail 0%{!?_without_tail:1}
+%define with_tail_csv 0%{!?_without_tail_csv:1}
+%define with_tcpconns 0%{!?_without_tcpconns:1}
+%define with_teamspeak2 0%{!?_without_teamspeak2:1}
+%define with_ted 0%{!?_without_ted:1}
+%define with_thermal 0%{!?_without_thermal:1}
+%define with_threshold 0%{!?_without_threshold:1}
+%define with_turbostat 0%{!?_without_turbostat:0%{?_has_asm_msr_index}}
+%define with_unixsock 0%{!?_without_unixsock:1}
+%define with_uptime 0%{!?_without_uptime:1}
+%define with_users 0%{!?_without_users:1}
+%define with_uuid 0%{!?_without_uuid:1}
+%define with_varnish 0%{!?_without_varnish:0%{!?_has_varnish4:1}}
+%define with_vmem 0%{!?_without_vmem:1}
+%define with_vserver 0%{!?_without_vserver:1}
+%define with_wireless 0%{!?_without_wireless:1}
+%define with_write_graphite 0%{!?_without_write_graphite:1}
+%define with_write_http 0%{!?_without_write_http:1}
+%define with_write_log 0%{!?_without_write_log:1}
+%define with_write_redis 0%{!?_without_write_redis:0%{?_has_hiredis}}
+%define with_write_riemann 0%{!?_without_write_riemann:1}
+%define with_write_sensu 0%{!?_without_write_sensu:1}
+%define with_write_tsdb 0%{!?_without_write_tsdb:1}
+%define with_zfs_arc 0%{!?_without_zfs_arc:1}
+%define with_zookeeper 0%{!?_without_zookeeper:1}
+
+# Plugins not built by default because of dependencies on libraries not
+# available in RHEL or EPEL:
+
+# plugin apple_sensors disabled, requires a Mac
+%define with_apple_sensors 0%{!?_without_apple_sensors:0}
+# plugin aquaero disabled, requires a libaquaero5
+%define with_aquaero 0%{!?_without_aquaero:0}
+# plugin barometer disabled, requires a libi2c
+%define with_barometer 0%{!?_without_barometer:0}
+# plugin lpar disabled, requires AIX
+%define with_lpar 0%{!?_without_lpar:0}
+# plugin mic disabled, requires Mic
+%define with_mic 0%{!?_without_mic:0}
+# plugin netapp disabled, requires libnetapp
+%define with_netapp 0%{!?_without_netapp:0}
+# plugin onewire disabled, requires libowfs
+%define with_onewire 0%{!?_without_onewire:0}
+# plugin oracle disabled, requires Oracle
+%define with_oracle 0%{!?_without_oracle:0}
+# plugin oracle disabled, requires BSD
+%define with_pf 0%{!?_without_pf:0}
+# plugin routeros disabled, requires librouteros
+%define with_routeros 0%{!?_without_routeros:0}
+# plugin sigrok disabled, requires libsigrok
+%define with_sigrok 0%{!?_without_sigrok:0}
+# plugin tape disabled, requires libkstat
+%define with_tape 0%{!?_without_tape:0}
+# plugin tokyotyrant disabled, requires tcrdb.h
+%define with_tokyotyrant 0%{!?_without_tokyotyrant:0}
+# plugin write_kafka disabled, requires librdkafka
+%define with_write_kafka 0%{!?_without_write_kafka:0}
+# plugin write_mongodb disabled, requires libmongoc
+%define with_write_mongodb 0%{!?_without_write_mongodb:0}
+# plugin xmms disabled, requires xmms
+%define with_xmms 0%{!?_without_xmms:0}
+
+Summary:       statistics collection and monitoring daemon
+Name:          collectd
+Version:       5.5.0
+Release:       1%{?dist}
+URL:           http://collectd.org
+Source:                http://collectd.org/files/%{name}-%{version}.tar.bz2
+License:       GPLv2
+Group:         System Environment/Daemons
+BuildRoot:     %{_tmppath}/%{name}-%{version}-root
+BuildRequires: libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel
+Vendor:                collectd development team <collectd@verplant.org>
+
+%if 0%{?el7:1}
+Requires(pre):         initscripts
+Requires(post):                systemd
+Requires(preun):       systemd
+Requires(postun):      systemd
+%else
+Requires(post):                chkconfig
+Requires(preun):       chkconfig, initscripts
+Requires(postun):      initscripts
+%endif
+
+%description
+collectd is a small daemon which collects system information periodically and
+provides mechanisms to monitor and store the values in a variety of ways. It
+is written in C for performance. Since the daemon doesn't need to start up
+every time it wants to update the values it's very fast and easy on the
+system. Also, the statistics are very fine grained since the files are updated
+every 10 seconds by default.
+
+%if %{with_amqp}
+%package amqp
+Summary:       AMQP plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: librabbitmq-devel
+%description amqp
+The AMQP plugin transmits or receives values collected by collectd via the
+Advanced Message Queuing Protocol (AMQP).
+%endif
+
+%if %{with_apache}
+%package apache
+Summary:       Apache plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: curl-devel
+%description apache
+This plugin collects data provided by Apache's `mod_status'.
+%endif
+
+%if %{with_aquaero}
+%package aquaero
+Summary:       aquaero plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%description aquaero
+Various sensors in the Aquaero 5 watercooling board made by Aquacomputer.
+%endif
+
+%if %{with_ascent}
+%package ascent
+Summary:       Ascent plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libxml2-devel, curl-devel
+%description ascent
+The Ascent plugin reads and parses the statistics page of Ascent, a free and
+open-source server software for the game World of Warcraft by Blizzard
+Entertainment.
+%endif
+
+%if %{with_barometer}
+%package barometer
+Summary:       barometer plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%description barometer
+Collects pressure and temperature from digital barometers.
+%endif
+
+%if %{with_bind}
+%package bind
+Summary:       Bind plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libxml2-devel, curl-devel
+%description bind
+The BIND plugin retrieves this information that's encoded in XML and provided
+via HTTP and submits the values to collectd.
+%endif
+
+%if %{with_ceph}
+%package ceph
+Summary:       Ceph plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: yajl-devel
+%description ceph
+Ceph plugin for collectd
+%endif
+
+%if %{with_curl}
+%package curl
+Summary:       Curl plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: curl-devel
+%description curl
+The cURL plugin uses libcurl to read files and then parses them according to
+the configuration.
+%endif
+
+%if %{with_curl_json}
+%package curl_json
+Summary:       Curl_json plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: curl-devel, yajl-devel
+%description curl_json
+The cURL-JSON plugin queries JavaScript Object Notation (JSON) data using the
+cURL library and parses it according to the user's configuration.
+%endif
+
+%if %{with_curl_xml}
+%package curl_xml
+Summary:       Curl_xml plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: curl-devel, libxml2-devel
+%description curl_xml
+The cURL-XML plugin reads files using libcurl and parses it as Extensible
+Markup Language (XML).
+%endif
+
+%if %{with_dbi}
+%package dbi
+Summary:       DBI plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libdbi-devel
+%description dbi
+The DBI plugin uses libdbi, a database abstraction library, to execute SQL
+statements on a database and read back the result.
+%endif
+
+%if %{with_disk}
+%package disk
+Summary:       disk plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%{?_has_libudev:BuildRequires:  libudev-devel}
+%description disk
+The "disk" plugin collects information about the usage of physical disks and
+logical disks (partitions).
+%endif
+
+%if %{with_dns}
+%package dns
+Summary:       DNS plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}, libpcap >= 1.0
+BuildRequires: libpcap-devel >= 1.0
+%description dns
+The DNS plugin has a similar functionality to dnstop: It uses libpcap to get a
+copy of all traffic from/to port UDP/53 (that's the DNS port), interprets the
+packets and collects statistics of your DNS traffic.
+%endif
+
+%if %{with_email}
+%package email
+Summary:       Email plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}, spamassassin
+%description email
+This plugin collects data provided by spamassassin.
+%endif
+
+%if %{with_gmond}
+%package gmond
+Summary:       Gmond plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: ganglia-devel
+%description gmond
+The gmond plugin subscribes to a Multicast group to receive data from gmond,
+the client daemon of the Ganglia project.
+%endif
+
+%if %{with_hddtemp}
+%package hddtemp
+Summary:       Hddtemp plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}, hddtemp
+%description hddtemp
+The HDDTemp plugin collects the temperature of hard disks. The temperatures are
+provided via SMART and queried by the external hddtemp daemon.
+%endif
+
+%if %{with_ipmi}
+%package ipmi
+Summary:       IPMI plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: OpenIPMI-devel
+%description ipmi
+The IPMI plugin uses the OpenIPMI library to read hardware sensors from servers
+using the Intelligent Platform Management Interface (IPMI).
+%endif
+
+%if %{with_iptables}
+%package iptables
+Summary:       IPtables plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: iptables-devel
+%description iptables
+The IPtables plugin can gather statistics from your ip_tables based packet
+filter (aka. firewall) for both the IPv4 and the IPv6 protocol. It can collect
+the byte- and packet-counters of selected rules and submit them to collectd.
+%endif
+
+%if %{with_java}
+%package java
+Summary:       Java plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: java-devel, jpackage-utils
+Requires:      java, jpackage-utils
+%description java
+This plugin for collectd allows plugins to be written in Java and executed
+in an embedded JVM.
+%endif
+
+%if %{with_log_logstash}
+%package log_logstash
+Summary:       log_logstash plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: yajl-devel
+%description log_logstash
+This plugin logs in logstash JSON format
+%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_memcachec}
+%package memcachec
+Summary:       Memcachec plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libmemcached-devel
+%description memcachec
+The Memcachec plugin uses libmemcached to read statistics from a Memcached
+instance. Note that another plugin, named `memcached', exists and does a
+similar job, without requiring the installation of libmemcached.
+%endif
+
+%if %{with_mic}
+%package mic
+Summary:       mic plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%description mic
+The mic plugin collects CPU usage, memory usage, temperatures and power
+consumption from Intel Many Integrated Core (MIC) CPUs.
+%endif
+
+%if %{with_modbus}
+%package modbus
+Summary:       modbus plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libmodbus-devel
+%description modbus
+The modbus plugin collects values from Modbus/TCP enabled devices
+%endif
+
+%if %{with_mysql}
+%package mysql
+Summary:       MySQL plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: mysql-devel
+%description mysql
+MySQL querying plugin. This plugin provides data of issued commands, called
+handlers and database traffic.
+%endif
+
+%if %{with_netlink}
+%package netlink
+Summary:       netlink plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libmnl-devel, iproute-devel
+%description netlink
+The netlink plugin collects detailed network interface and routing statistics.
+%endif
+
+%if %{with_nginx}
+%package nginx
+Summary:       Nginx plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: curl-devel
+%description nginx
+This plugin gets data provided by nginx.
+%endif
+
+%if %{with_notify_desktop}
+%package notify_desktop
+Summary:       Notify_desktop plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libnotify-devel, gtk2-devel
+%description notify_desktop
+The Notify Desktop plugin uses libnotify to display notifications to the user
+via the desktop notification specification, i. e. on an X display.
+%endif
+
+%if %{with_notify_email}
+%package notify_email
+Summary:       Notify_email plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libesmtp-devel
+%description notify_email
+The Notify Email plugin uses libESMTP to send notifications to a configured
+email address.
+%endif
+
+%if %{with_nut}
+%package nut
+Summary:       Nut plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: nut-devel
+%description nut
+This plugin for collectd provides Network UPS Tools support.
+%endif
+
+%if %{with_openldap}
+%package openldap
+Summary:       Openldap plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: openldap-devel
+%description openldap
+This plugin reads monitoring information from OpenLDAP's cn=Monitor subtree.
+%endif
+
+%if %{with_perl}
+%package perl
+Summary:       Perl plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+Requires:      perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
+       %if 0%{?rhel} >= 6
+BuildRequires: perl-ExtUtils-Embed
+       %else
+BuildRequires: perl
+       %endif
+%description perl
+The Perl plugin embeds a Perl interpreter into collectd and exposes the
+application programming interface (API) to Perl-scripts.
+%endif
+
+%if %{with_pinba}
+%package pinba
+Summary:       Pinba plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: protobuf-c-devel
+%description pinba
+The Pinba plugin receives and dispatches timing values from Pinba, a profiling
+extension for PHP.
+%endif
+
+%if %{with_ping}
+%package ping
+Summary:       Ping plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: liboping-devel
+%description ping
+The Ping plugin measures network latency using ICMP “echo requests”, usually
+known as “ping”.
+%endif
+
+%if %{with_postgresql}
+%package postgresql
+Summary:       PostgreSQL plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: postgresql-devel
+%description postgresql
+The PostgreSQL plugin connects to and executes SQL statements on a PostgreSQL
+database.
+%endif
+
+%if %{with_python}
+%package python
+Summary:       Python plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+       %if 0%{?rhel} >= 6
+BuildRequires: python-devel
+       %else
+BuildRequires: python26-devel
+       %endif
+%description python
+The Python plugin embeds a Python interpreter into collectd and exposes the
+application programming interface (API) to Python-scripts.
+%endif
+
+%if %{with_redis}
+%package redis
+Summary:       Redis plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: hiredis-devel
+%description redis
+The Redis plugin connects to one or more instances of Redis, a key-value store,
+and collects usage information using the hiredis library.
+%endif
+
+%if %{with_rrdcached}
+%package rrdcached
+Summary:        RRDCached plugin for collectd
+Group:          System Environment/Daemons
+Requires:       %{name}%{?_isa} = %{version}-%{release}, rrdtool >= 1.4
+BuildRequires:  rrdtool-devel
+%description rrdcached
+The RRDCacheD plugin connects to the “RRD caching daemon”, rrdcached and
+submits updates for RRD files to that daemon.
+%endif
+
+%if %{with_rrdtool}
+%package rrdtool
+Summary:       RRDtool plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: rrdtool-devel
+%description rrdtool
+The RRDtool plugin writes values to RRD-files using librrd.
+%endif
+
+%if %{with_sensors}
+%package sensors
+Summary:       Sensors plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: lm_sensors-devel
+%description sensors
+This plugin for collectd provides querying of sensors supported by lm_sensors.
+%endif
+
+%if %{with_sigrok}
+%package sigrok
+Summary:       sigrok plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%description sigrok
+Uses libsigrok as a backend, allowing any sigrok-supported device to have its
+measurements fed to collectd. This includes multimeters, sound level meters,
+thermometers, and much more.
+%endif
+
+%if %{with_smart}
+%package smart
+Summary:       SMART plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libatasmart-devel
+%description smart
+Collect SMART statistics, notably load cycle count, temperature and bad
+sectors.
+%endif
+
+%if %{with_snmp}
+%package snmp
+Summary:       SNMP plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: net-snmp-devel
+%description snmp
+This plugin for collectd allows querying of network equipment using SNMP.
+%endif
+
+%if %{with_varnish}
+%package varnish
+Summary:       Varnish plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: varnish-libs-devel
+%description varnish
+The Varnish plugin collects information about Varnish, an HTTP accelerator.
+%endif
+
+%if %{with_virt}
+%package virt
+Summary:       Virt plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libvirt-devel
+%description virt
+This plugin collects information from virtualized guests.
+%endif
+
+%if %{with_write_http}
+%package write_http
+Summary:       Write-HTTP plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: curl-devel
+%description write_http
+The Write-HTTP plugin sends the values collected by collectd to a web-server
+using HTTP POST requests.
+%endif
+
+%if %{with_write_kafka}
+%package write_kafka
+Summary:       Write-kafka plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: rdkafka-devel
+%description write_kafka
+The write_kafka plugin sends values to kafka, a distributed messaging system.
+%endif
+
+%if %{with_write_redis}
+%package write_redis
+Summary:       Write-Redis plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: hiredis-devel
+%description write_redis
+The Write Redis plugin stores values in Redis, a “data structures server”.
+%endif
+
+%if %{with_write_riemann}
+%package write_riemann
+Summary:       riemann plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: protobuf-c-devel
+%description write_riemann
+The riemann plugin submits values to Riemann, an event stream processor.
+%endif
+
+%package collection3
+Summary:       Web-based viewer for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+Requires: httpd
+%description collection3
+collection3 is a graphing front-end for the RRD files created by and filled
+with collectd. It is written in Perl and should be run as an CGI-script.
+Graphs are generated on-the-fly, so no cron job or similar is necessary.
+
+%package php-collection
+Summary:       collect php webfrontent
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}-%{release}
+Requires:      httpd
+Requires:      php
+Requires:      php-rrdtool
+%description php-collection
+PHP graphing frontend for RRD files created by and filled with collectd.
+
+%package contrib
+Summary:       Contrib files for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+%description contrib
+All the files found under contrib/ in the source tree are bundled in this
+package.
+
+%package -n libcollectdclient
+Summary:       Collectd client library
+Group:         System Environment/Daemons
+%description -n libcollectdclient
+Collectd client library
+
+%package -n libcollectdclient-devel
+Summary:       Development files for libcollectdclient
+Group:         System Environment/Daemons
+Requires:      pkgconfig
+Requires:      libcollectdclient%{?_isa} = %{version}-%{release}
+%description -n libcollectdclient-devel
+Development files for libcollectdclient
+
+%package -n collectd-utils
+Summary:       Collectd utilities
+Group:         System Environment/Daemons
+Requires:      libcollectdclient%{?_isa} = %{version}-%{release}
+Requires:      collectd%{?_isa} = %{version}-%{release}
+%description -n collectd-utils
+Collectd utilities
+
+%prep
+%setup -q
+
+%build
+%if %{with_aggregation}
+%define _with_aggregation --enable-aggregation
+%else
+%define _with_aggregation --disable-aggregation
+%endif
+
+%if %{with_amqp}
+%define _with_amqp --enable-amqp
+%else
+%define _with_amqp --disable-amqp
+%endif
+
+%if %{with_apache}
+%define _with_apache --enable-apache
+%else
+%define _with_apache --disable-apache
+%endif
+
+%if %{with_apcups}
+%define _with_apcups --enable-apcups
+%else
+%define _with_apcups --disable-apcups
+%endif
+
+%if %{with_apple_sensors}
+%define _with_apple_sensors --enable-apple_sensors
+%else
+%define _with_apple_sensors --disable-apple_sensors
+%endif
+
+%if %{with_aquaero}
+%define _with_aquaero --enable-aquaero
+%else
+%define _with_aquaero --disable-aquaero
+%endif
+
+%if %{with_ascent}
+%define _with_ascent --enable-ascent
+%else
+%define _with_ascent --disable-ascent
+%endif
+
+%if %{with_barometer}
+%define _with_barometer --enable-barometer
+%else
+%define _with_barometer --disable-barometer
+%endif
+
+%if %{with_battery}
+%define _with_battery --enable-battery
+%else
+%define _with_battery --disable-battery
+%endif
+
+%if %{with_bind}
+%define _with_bind --enable-bind
+%else
+%define _with_bind --disable-bind
+%endif
+
+%if %{with_cgroups}
+%define _with_cgroups --enable-cgroups
+%else
+%define _with_cgroups --disable-cgroups
+%endif
+
+%if %{with_conntrack}
+%define _with_conntrack --enable-conntrack
+%else
+%define _with_conntrack --disable-conntrack
+%endif
+
+%if %{with_contextswitch}
+%define _with_contextswitch --enable-contextswitch
+%else
+%define _with_contextswitch --disable-contextswitch
+%endif
+
+%if %{with_cpu}
+%define _with_cpu --enable-cpu
+%else
+%define _with_cpu --disable-cpu
+%endif
+
+%if %{with_cpufreq}
+%define _with_cpufreq --enable-cpufreq
+%else
+%define _with_cpufreq --disable-cpufreq
+%endif
+
+%if %{with_csv}
+%define _with_csv --enable-csv
+%else
+%define _with_csv --disable-csv
+%endif
+
+%if %{with_ceph}
+%define _with_ceph --enable-ceph
+%else
+%define _with_ceph --disable-ceph
+%endif
+
+%if %{with_curl}
+%define _with_curl --enable-curl
+%else
+%define _with_curl --disable-curl
+%endif
+
+%if %{with_curl_json}
+%define _with_curl_json --enable-curl_json
+%else
+%define _with_curl_json --disable-curl_json
+%endif
+
+%if %{with_curl_xml}
+%define _with_curl_xml --enable-curl_xml
+%else
+%define _with_curl_xml --disable-curl_xml
+%endif
+
+%if %{with_dbi}
+%define _with_dbi --enable-dbi
+%else
+%define _with_dbi --disable-dbi
+%endif
+
+%if %{with_df}
+%define _with_df --enable-df
+%else
+%define _with_df --disable-df
+%endif
+
+%if %{with_disk}
+%define _with_disk --enable-disk
+%else
+%define _with_disk --disable-disk
+%endif
+
+%if %{with_dns}
+%define _with_dns --enable-dns
+%else
+%define _with_dns --disable-dns
+%endif
+
+%if %{with_drbd}
+%define _with_drbd --enable-drbd
+%else
+%define _with_drbd --disable-drbd
+%endif
+
+%if %{with_email}
+%define _with_email --enable-email
+%else
+%define _with_email --disable-email
+%endif
+
+%if %{with_entropy}
+%define _with_entropy --enable-entropy
+%else
+%define _with_entropy --disable-entropy
+%endif
+
+%if %{with_ethstat}
+%define _with_ethstat --enable-ethstat
+%else
+%define _with_ethstat --disable-ethstat
+%endif
+
+%if %{with_exec}
+%define _with_exec --enable-exec
+%else
+%define _with_exec --disable-exec
+%endif
+
+%if %{with_fhcount}
+%define _with_fhcount --enable-fhcount
+%else
+%define _with_fhcount --disable-fhcount
+%endif
+
+%if %{with_filecount}
+%define _with_filecount --enable-filecount
+%else
+%define _with_filecount --disable-filecount
+%endif
+
+%if %{with_fscache}
+%define _with_fscache --enable-fscache
+%else
+%define _with_fscache --disable-fscache
+%endif
+
+%if %{with_gmond}
+%define _with_gmond --enable-gmond
+%else
+%define _with_gmond --disable-gmond
+%endif
+
+%if %{with_hddtemp}
+%define _with_hddtemp --enable-hddtemp
+%else
+%define _with_hddtemp --disable-hddtemp
+%endif
+
+%if %{with_interface}
+%define _with_interface --enable-interface
+%else
+%define _with_interface --disable-interface
+%endif
+
+%if %{with_ipc}
+%define _with_ipc --enable-ipc
+%else
+%define _with_ipc --disable-ipc
+%endif
+
+%if %{with_ipmi}
+%define _with_ipmi --enable-ipmi
+%else
+%define _with_ipmi --disable-ipmi
+%endif
+
+%if %{with_iptables}
+%define _with_iptables --enable-iptables
+%else
+%define _with_iptables --disable-iptables
+%endif
+
+%if %{with_ipvs}
+%define _with_ipvs --enable-ipvs
+%else
+%define _with_ipvs --disable-ipvs
+%endif
+
+%if %{with_irq}
+%define _with_irq --enable-irq
+%else
+%define _with_irq --disable-irq
+%endif
+
+%if %{with_java}
+%define _with_java --enable-java --with-java=%{java_home}/
+%else
+%define _with_java --disable-java
+%endif
+
+%if %{with_virt}
+%define _with_virt --enable-virt
+%else
+%define _with_virt --disable-virt
+%endif
+
+%if %{with_load}
+%define _with_load --enable-load
+%else
+%define _with_load --disable-load
+%endif
+
+%if %{with_logfile}
+%define _with_logfile --enable-logfile
+%else
+%define _with_logfile --disable-logfile
+%endif
+
+%if %{with_log_logstash}
+%define _with_log_logstash --enable-log_logstash
+%else
+%define _with_log_logstash --disable-log_logstash
+%endif
+
+%if %{with_lpar}
+%define _with_lpar --enable-lpar
+%else
+%define _with_lpar --disable-lpar
+%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
+%define _with_madwifi --disable-madwifi
+%endif
+
+%if %{with_mbmon}
+%define _with_mbmon --enable-mbmon
+%else
+%define _with_mbmon --disable-mbmon
+%endif
+
+%if %{with_md}
+%define _with_md --enable-md
+%else
+%define _with_md --disable-md
+%endif
+
+%if %{with_memcachec}
+%define _with_memcachec --enable-memcachec
+%else
+%define _with_memcachec --disable-memcachec
+%endif
+
+%if %{with_memcached}
+%define _with_memcached --enable-memcached
+%else
+%define _with_memcached --disable-memcached
+%endif
+
+%if %{with_memory}
+%define _with_memory --enable-memory
+%else
+%define _with_memory --disable-memory
+%endif
+
+%if %{with_mic}
+%define _with_mic --enable-mic
+%else
+%define _with_mic --disable-mic
+%endif
+
+%if %{with_modbus}
+%define _with_modbus --enable-modbus
+%else
+%define _with_modbus --disable-modbus
+%endif
+
+%if %{with_multimeter}
+%define _with_multimeter --enable-multimeter
+%else
+%define _with_multimeter --disable-multimeter
+%endif
+
+%if %{with_mysql}
+%define _with_mysql --enable-mysql
+%else
+%define _with_mysql --disable-mysql
+%endif
+
+%if %{with_netapp}
+%define _with_netapp --enable-netapp
+%else
+%define _with_netapp --disable-netapp
+%endif
+
+%if %{with_netlink}
+%define _with_netlink --enable-netlink
+%else
+%define _with_netlink --disable-netlink
+%endif
+
+%if %{with_network}
+%define _with_network --enable-network
+%else
+%define _with_network --disable-network
+%endif
+
+%if %{with_nfs}
+%define _with_nfs --enable-nfs
+%else
+%define _with_nfs --disable-nfs
+%endif
+
+%if %{with_nginx}
+%define _with_nginx --enable-nginx
+%else
+%define _with_nginx --disable-nginx
+%endif
+
+%if %{with_notify_desktop}
+%define _with_notify_desktop --enable-notify_desktop
+%else
+%define _with_notify_desktop --disable-notify_desktop
+%endif
+
+%if %{with_notify_email}
+%define _with_notify_email --enable-notify_email
+%else
+%define _with_notify_email --disable-notify_email
+%endif
+
+%if %{with_ntpd}
+%define _with_ntpd --enable-ntpd
+%else
+%define _with_ntpd --disable-ntpd
+%endif
+
+%if %{with_numa}
+%define _with_numa --enable-numa
+%else
+%define _with_numa --disable-numa
+%endif
+
+%if %{with_nut}
+%define _with_nut --enable-nut
+%else
+%define _with_nut --disable-nut
+%endif
+
+%if %{with_olsrd}
+%define _with_olsrd --enable-olsrd
+%else
+%define _with_olsrd --disable-olsrd
+%endif
+
+%if %{with_onewire}
+%define _with_onewire --enable-onewire
+%else
+%define _with_onewire --disable-onewire
+%endif
+
+%if %{with_openldap}
+%define _with_openldap --enable-openldap
+%else
+%define _with_openldap --disable-openldap
+%endif
+
+%if %{with_openvpn}
+%define _with_openvpn --enable-openvpn
+%else
+%define _with_openvpn --disable-openvpn
+%endif
+
+%if %{with_oracle}
+%define _with_oracle --enable-oracle
+%else
+%define _with_oracle --disable-oracle
+%endif
+
+%if %{with_perl}
+%define _with_perl --enable-perl --with-perl-bindings="INSTALLDIRS=vendor"
+%else
+%define _with_perl --disable-perl
+%endif
+
+%if %{with_pf}
+%define _with_pf --enable-pf
+%else
+%define _with_pf --disable-pf
+%endif
+
+%if %{with_pinba}
+%define _with_pinba --enable-pinba
+%else
+%define _with_pinba --disable-pinba
+%endif
+
+%if %{with_ping}
+%define _with_ping --enable-ping
+%else
+%define _with_ping --disable-ping
+%endif
+
+%if %{with_postgresql}
+%define _with_postgresql --enable-postgresql
+%else
+%define _with_postgresql --disable-postgresql
+%endif
+
+%if %{with_powerdns}
+%define _with_powerdns --enable-powerdns
+%else
+%define _with_powerdns --disable-powerdns
+%endif
+
+%if %{with_processes}
+%define _with_processes --enable-processes
+%else
+%define _with_processes --disable-processes
+%endif
+
+%if %{with_protocols}
+%define _with_protocols --enable-protocols
+%else
+%define _with_protocols --disable-protocols
+%endif
+
+%if %{with_python}
+       %if 0%{?rhel} >= 6
+%define _with_python --enable-python
+       %else
+%define _with_python --enable-python --with-python=%{_bindir}/python2.6
+       %endif
+%else
+%define _with_python --disable-python
+%endif
+
+%if %{with_redis}
+%define _with_redis --enable-redis
+%else
+%define _with_redis --disable-redis
+%endif
+
+%if %{with_routeros}
+%define _with_routeros --enable-routeros
+%else
+%define _with_routeros --disable-routeros
+%endif
+
+%if %{with_rrdcached}
+%define _with_rrdcached --enable-rrdcached
+%else
+%define _with_rrdcached --disable-rrdcached
+%endif
+
+%if %{with_rrdtool}
+%define _with_rrdtool --enable-rrdtool
+%else
+%define _with_rrdtool --disable-rrdtool
+%endif
+
+%if %{with_sensors}
+%define _with_sensors --enable-sensors
+%else
+%define _with_sensors --disable-sensors
+%endif
+
+%if %{with_serial}
+%define _with_serial --enable-serial
+%else
+%define _with_serial --disable-serial
+%endif
+
+%if %{with_sigrok}
+%define _with_sigrok --enable-sigrok
+%else
+%define _with_sigrok --disable-sigrok
+%endif
+
+%if %{with_smart}
+%define _with_smart --enable-smart
+%else
+%define _with_smart --disable-smart
+%endif
+
+%if %{with_snmp}
+%define _with_snmp --enable-snmp
+%else
+%define _with_snmp --disable-snmp
+%endif
+
+%if %{with_statsd}
+%define _with_statsd --enable-statsd
+%else
+%define _with_statsd --disable-statsd
+%endif
+
+%if %{with_swap}
+%define _with_swap --enable-swap
+%else
+%define _with_swap --disable-swap
+%endif
+
+%if %{with_syslog}
+%define _with_syslog --enable-syslog
+%else
+%define _with_syslog --disable-syslog
+%endif
+
+%if %{with_table}
+%define _with_table --enable-table
+%else
+%define _with_table --disable-table
+%endif
+
+%if %{with_tail}
+%define _with_tail --enable-tail
+%else
+%define _with_tail --disable-tail
+%endif
+
+%if %{with_tail_csv}
+%define _with_tail_csv --enable-tail_csv
+%else
+%define _with_tail_csv --disable-tail_csv
+%endif
+
+%if %{with_tape}
+%define _with_tape --enable-tape
+%else
+%define _with_tape --disable-tape
+%endif
+
+%if %{with_tcpconns}
+%define _with_tcpconns --enable-tcpconns
+%else
+%define _with_tcpconns --disable-tcpconns
+%endif
+
+%if %{with_teamspeak2}
+%define _with_teamspeak2 --enable-teamspeak2
+%else
+%define _with_teamspeak2 --disable-teamspeak2
+%endif
+
+%if %{with_ted}
+%define _with_ted --enable-ted
+%else
+%define _with_ted --disable-ted
+%endif
+
+%if %{with_thermal}
+%define _with_thermal --enable-thermal
+%else
+%define _with_thermal --disable-thermal
+%endif
+
+%if %{with_threshold}
+%define _with_threshold --enable-threshold
+%else
+%define _with_threshold --disable-threshold
+%endif
+
+%if %{with_tokyotyrant}
+%define _with_tokyotyrant --enable-tokyotyrant
+%else
+%define _with_tokyotyrant --disable-tokyotyrant
+%endif
+
+%if %{with_turbostat}
+%define _with_turbostat --enable-turbostat
+%else
+%define _with_turbostat --disable-turbostat
+%endif
+
+%if %{with_unixsock}
+%define _with_unixsock --enable-unixsock
+%else
+%define _with_unixsock --disable-unixsock
+%endif
+
+%if %{with_uptime}
+%define _with_uptime --enable-uptime
+%else
+%define _with_uptime --disable-uptime
+%endif
+
+%if %{with_users}
+%define _with_users --enable-users
+%else
+%define _with_users --disable-users
+%endif
+
+%if %{with_uuid}
+%define _with_uuid --enable-uuid
+%else
+%define _with_uuid --disable-uuid
+%endif
+
+%if %{with_varnish}
+%define _with_varnish --enable-varnish
+%else
+%define _with_varnish --disable-varnish
+%endif
+
+%if %{with_vmem}
+%define _with_vmem --enable-vmem
+%else
+%define _with_vmem --disable-vmem
+%endif
+
+%if %{with_vserver}
+%define _with_vserver --enable-vserver
+%else
+%define _with_vserver --disable-vserver
+%endif
+
+%if %{with_wireless}
+%define _with_wireless --enable-wireless
+%else
+%define _with_wireless --disable-wireless
+%endif
+
+%if %{with_write_graphite}
+%define _with_write_graphite --enable-write_graphite
+%else
+%define _with_write_graphite --disable-write_graphite
+%endif
+
+%if %{with_write_http}
+%define _with_write_http --enable-write_http
+%else
+%define _with_write_http --disable-write_http
+%endif
+
+%if %{with_write_kafka}
+%define _with_write_kafka --enable-write_kafka
+%else
+%define _with_write_kafka --disable-write_kafka
+%endif
+
+%if %{with_write_log}
+%define _with_write_log --enable-write_log
+%else
+%define _with_write_log --disable-write_log
+%endif
+
+%if %{with_write_mongodb}
+%define _with_write_mongodb --enable-write_mongodb
+%else
+%define _with_write_mongodb --disable-write_mongodb
+%endif
+
+%if %{with_write_redis}
+%define _with_write_redis --enable-write_redis
+%else
+%define _with_write_redis --disable-write_redis
+%endif
+
+%if %{with_write_riemann}
+%define _with_write_riemann --enable-write_riemann
+%else
+%define _with_write_riemann --disable-write_riemann
+%endif
+
+%if %{with_write_sensu}
+%define _with_write_sensu --enable-write_sensu
+%else
+%define _with_write_sensu --disable-write_sensu
+%endif
+
+%if %{with_write_tsdb}
+%define _with_write_tsdb --enable-write_tsdb
+%else
+%define _with_write_tsdb --disable-write_tsdb
+%endif
+
+%if %{with_xmms}
+%define _with_xmms --enable-xmms
+%else
+%define _with_xmms --disable-xmms
+%endif
+
+%if %{with_zfs_arc}
+%define _with_zfs_arc --enable-zfs_arc
+%else
+%define _with_zfs_arc --disable-zfs_arc
+%endif
+
+%if %{with_zookeeper}
+%define _with_zookeeper --enable-zookeeper
+%else
+%define _with_zookeeper --disable-zookeeper
+%endif
+
+%configure CFLAGS="%{optflags} -DLT_LAZY_OR_NOW=\"RTLD_LAZY|RTLD_GLOBAL\"" \
+       --disable-static \
+       --without-included-ltdl \
+       --enable-all-plugins=yes \
+       --enable-match_empty_counter \
+       --enable-match_hashed \
+       --enable-match_regex \
+       --enable-match_timediff \
+       --enable-match_value \
+       --enable-target_notification \
+       --enable-target_replace \
+       --enable-target_scale \
+       --enable-target_set \
+       --enable-target_v5upgrade \
+       %{?_with_aggregation} \
+       %{?_with_amqp} \
+       %{?_with_apache} \
+       %{?_with_apcups} \
+       %{?_with_apple_sensors} \
+       %{?_with_aquaero} \
+       %{?_with_ascent} \
+       %{?_with_barometer} \
+       %{?_with_battery} \
+       %{?_with_bind} \
+       %{?_with_ceph} \
+       %{?_with_cgroups} \
+       %{?_with_conntrack} \
+       %{?_with_contextswitch} \
+       %{?_with_cpu} \
+       %{?_with_cpufreq} \
+       %{?_with_csv} \
+       %{?_with_curl} \
+       %{?_with_curl_json} \
+       %{?_with_curl_xml} \
+       %{?_with_dbi} \
+       %{?_with_df} \
+       %{?_with_disk} \
+       %{?_with_dns} \
+       %{?_with_drbd} \
+       %{?_with_email} \
+       %{?_with_entropy} \
+       %{?_with_ethstat} \
+       %{?_with_exec} \
+       %{?_with_fhcount} \
+       %{?_with_filecount} \
+       %{?_with_fscache} \
+       %{?_with_gmond} \
+       %{?_with_hddtemp} \
+       %{?_with_interface} \
+       %{?_with_ipc} \
+       %{?_with_ipmi} \
+       %{?_with_iptables} \
+       %{?_with_ipvs} \
+       %{?_with_java} \
+       %{?_with_virt} \
+       %{?_with_log_logstash} \
+       %{?_with_lpar} \
+       %{?_with_lvm} \
+       %{?_with_memcachec} \
+       %{?_with_mic} \
+       %{?_with_modbus} \
+       %{?_with_multimeter} \
+       %{?_with_mysql} \
+       %{?_with_netapp} \
+       %{?_with_netlink} \
+       %{?_with_nginx} \
+       %{?_with_notify_desktop} \
+       %{?_with_notify_email} \
+       %{?_with_nut} \
+       %{?_with_onewire} \
+       %{?_with_openldap} \
+       %{?_with_oracle} \
+       %{?_with_perl} \
+       %{?_with_pf} \
+       %{?_with_pinba} \
+       %{?_with_ping} \
+       %{?_with_postgresql} \
+       %{?_with_python} \
+       %{?_with_redis} \
+       %{?_with_routeros} \
+       %{?_with_rrdcached} \
+       %{?_with_rrdtool} \
+       %{?_with_sensors} \
+       %{?_with_sigrok} \
+       %{?_with_smart} \
+       %{?_with_snmp} \
+       %{?_with_tape} \
+       %{?_with_tokyotyrant} \
+       %{?_with_varnish} \
+       %{?_with_write_http} \
+       %{?_with_write_kafka} \
+       %{?_with_write_mongodb} \
+       %{?_with_write_redis} \
+       %{?_with_xmms} \
+       %{?_with_zfs_arc} \
+       %{?_with_zookeeper} \
+       %{?_with_irq} \
+       %{?_with_load} \
+       %{?_with_logfile} \
+       %{?_with_madwifi} \
+       %{?_with_mbmon} \
+       %{?_with_md} \
+       %{?_with_memcached} \
+       %{?_with_memory} \
+       %{?_with_network} \
+       %{?_with_nfs} \
+       %{?_with_ntpd} \
+       %{?_with_numa} \
+       %{?_with_olsrd} \
+       %{?_with_openvpn} \
+       %{?_with_powerdns} \
+       %{?_with_processes} \
+       %{?_with_protocols} \
+       %{?_with_serial} \
+       %{?_with_statsd} \
+       %{?_with_swap} \
+       %{?_with_syslog} \
+       %{?_with_table} \
+       %{?_with_tail} \
+       %{?_with_tail_csv} \
+       %{?_with_tcpconns} \
+       %{?_with_teamspeak2} \
+       %{?_with_ted} \
+       %{?_with_thermal} \
+       %{?_with_threshold} \
+       %{?_with_turbostat} \
+       %{?_with_unixsock} \
+       %{?_with_uptime} \
+       %{?_with_users} \
+       %{?_with_uuid} \
+       %{?_with_vmem} \
+       %{?_with_vserver} \
+       %{?_with_wireless}\
+       %{?_with_write_graphite} \
+       %{?_with_write_http} \
+       %{?_with_write_log} \
+       %{?_with_write_riemann} \
+       %{?_with_write_sensu} \
+       %{?_with_write_tsdb}
+
+
+%{__make} %{?_smp_mflags}
+
+
+%install
+rm -rf %{buildroot}
+%{__make} install DESTDIR=%{buildroot}
+%if 0%{?el7:1}
+%{__install} -Dp -m0644 contrib/systemd.collectd.service %{buildroot}%{_unitdir}/collectd.service
+%else
+%{__install} -Dp -m0755 contrib/redhat/init.d-collectd %{buildroot}%{_initrddir}/collectd
+%endif
+%{__install} -Dp -m0644 src/collectd.conf %{buildroot}%{_sysconfdir}/collectd.conf
+%{__install} -d %{buildroot}%{_sharedstatedir}/collectd/
+%{__install} -d %{buildroot}%{_sysconfdir}/collectd.d/
+
+%{__mkdir} -p %{buildroot}%{_localstatedir}/www
+%{__mkdir} -p %{buildroot}/%{_sysconfdir}/httpd/conf.d
+
+%{__mv} contrib/collection3 %{buildroot}%{_localstatedir}/www
+%{__mv} contrib/redhat/collection3.conf %{buildroot}/%{_sysconfdir}/httpd/conf.d/
+
+%{__mv} contrib/php-collection %{buildroot}%{_localstatedir}/www
+%{__mv} contrib/redhat/php-collection.conf %{buildroot}/%{_sysconfdir}/httpd/conf.d/
+
+### Clean up docs
+find contrib/ -type f -exec %{__chmod} a-x {} \;
+# *.la files shouldn't be distributed.
+rm -f %{buildroot}/%{_libdir}/{collectd/,}*.la
+
+# Remove Perl hidden .packlist files.
+find %{buildroot} -type f -name .packlist -delete
+# Remove Perl temporary file perllocal.pod
+find %{buildroot} -type f -name perllocal.pod -delete
+
+%if ! %{with_java}
+rm -f %{buildroot}%{_datadir}/collectd/java/collectd-api.jar
+rm -f %{buildroot}%{_datadir}/collectd/java/generic-jmx.jar
+rm -f %{buildroot}%{_mandir}/man5/collectd-java.5*
+%endif
+
+%if ! %{with_perl}
+rm -f %{buildroot}%{_mandir}/man5/collectd-perl.5*
+rm -f %{buildroot}%{_mandir}/man3/Collectd::Unixsock.3pm*
+rm -fr %{buildroot}/usr/lib/perl5/
+%endif
+
+%if ! %{with_postgresql}
+rm -f %{buildroot}%{_datadir}/collectd/postgresql_default.conf
+%endif
+
+%if ! %{with_python}
+rm -f %{buildroot}%{_mandir}/man5/collectd-python.5*
+%endif
+
+%if ! %{with_snmp}
+rm -f %{buildroot}%{_mandir}/man5/collectd-snmp.5*
+%endif
+
+
+%clean
+rm -rf %{buildroot}
+
+%pre
+%if 0%{?el7:1}
+# stop sysv-based instance before upgrading to systemd
+if [ $1 -eq 2 ] && [ -f /var/lock/subsys/collectd ]; then
+       SYSTEMCTL_SKIP_REDIRECT=1 %{_initddir}/collectd stop >/dev/null 2>&1 || :
+fi
+%endif
+
+%post
+%if 0%{?el7:1}
+if [ $1 -eq 2 ]; then
+       /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+fi
+%systemd_post collectd.service
+%else
+/sbin/chkconfig --add collectd || :
+%endif
+
+%preun
+%if 0%{?el7:1}
+%systemd_preun collectd.service
+%else
+# stop collectd only when uninstalling
+if [ $1 -eq 0 ]; then
+       /sbin/service collectd stop >/dev/null 2>&1 || :
+       /sbin/chkconfig --del collectd || :
+fi
+%endif
+
+%postun
+%if 0%{?el7:1}
+%systemd_postun_with_restart collectd.service
+%else
+# restart collectd only when upgrading
+if [ $1 -eq 1 ]; then
+       /sbin/service collectd condrestart >/dev/null 2>&1 || :
+fi
+%endif
+
+%post -n libcollectdclient -p /sbin/ldconfig
+%postun -n libcollectdclient -p /sbin/ldconfig
+
+
+%files
+%doc AUTHORS COPYING ChangeLog README
+%config(noreplace) %{_sysconfdir}/collectd.conf
+%if 0%{?el7:1}
+%{_unitdir}/collectd.service
+%else
+%{_initrddir}/collectd
+%endif
+%{_sbindir}/collectd
+%{_sbindir}/collectdmon
+%{_datadir}/collectd/types.db
+%{_sharedstatedir}/collectd
+%{_mandir}/man1/collectd.1*
+%{_mandir}/man1/collectdmon.1*
+%{_mandir}/man5/collectd-email.5*
+%{_mandir}/man5/collectd-exec.5*
+%{_mandir}/man5/collectd-threshold.5*
+%{_mandir}/man5/collectd-unixsock.5*
+%{_mandir}/man5/collectd.conf.5*
+%{_mandir}/man5/types.db.5*
+
+# all plugins bundled with the main collectd package
+%{_libdir}/%{name}/match_empty_counter.so
+%{_libdir}/%{name}/match_hashed.so
+%{_libdir}/%{name}/match_regex.so
+%{_libdir}/%{name}/match_timediff.so
+%{_libdir}/%{name}/match_value.so
+%{_libdir}/%{name}/target_notification.so
+%{_libdir}/%{name}/target_replace.so
+%{_libdir}/%{name}/target_scale.so
+%{_libdir}/%{name}/target_set.so
+%{_libdir}/%{name}/target_v5upgrade.so
+
+%if %{with_aggregation}
+%{_libdir}/%{name}/aggregation.so
+%endif
+%if %{with_apcups}
+%{_libdir}/%{name}/apcups.so
+%endif
+%if %{with_battery}
+%{_libdir}/%{name}/battery.so
+%endif
+%if %{with_cgroups}
+%{_libdir}/%{name}/cgroups.so
+%endif
+%if %{with_conntrack}
+%{_libdir}/%{name}/conntrack.so
+%endif
+%if %{with_contextswitch}
+%{_libdir}/%{name}/contextswitch.so
+%endif
+%if %{with_cpu}
+%{_libdir}/%{name}/cpu.so
+%endif
+%if %{with_cpufreq}
+%{_libdir}/%{name}/cpufreq.so
+%endif
+%if %{with_csv}
+%{_libdir}/%{name}/csv.so
+%endif
+%if %{with_df}
+%{_libdir}/%{name}/df.so
+%endif
+%if %{with_drbd}
+%{_libdir}/%{name}/drbd.so
+%endif
+%if %{with_ethstat}
+%{_libdir}/%{name}/ethstat.so
+%endif
+%if %{with_entropy}
+%{_libdir}/%{name}/entropy.so
+%endif
+%if %{with_exec}
+%{_libdir}/%{name}/exec.so
+%endif
+%if %{with_fhcount}
+%{_libdir}/%{name}/fhcount.so
+%endif
+%if %{with_filecount}
+%{_libdir}/%{name}/filecount.so
+%endif
+%if %{with_fscache}
+%{_libdir}/%{name}/fscache.so
+%endif
+%if %{with_interface}
+%{_libdir}/%{name}/interface.so
+%endif
+%if %{with_ipc}
+%{_libdir}/%{name}/ipc.so
+%endif
+%if %{with_ipvs}
+%{_libdir}/%{name}/ipvs.so
+%endif
+%if %{with_irq}
+%{_libdir}/%{name}/irq.so
+%endif
+%if %{with_load}
+%{_libdir}/%{name}/load.so
+%endif
+%if %{with_logfile}
+%{_libdir}/%{name}/logfile.so
+%endif
+%if %{with_madwifi}
+%{_libdir}/%{name}/madwifi.so
+%endif
+%if %{with_mbmon}
+%{_libdir}/%{name}/mbmon.so
+%endif
+%if %{with_md}
+%{_libdir}/%{name}/md.so
+%endif
+%if %{with_memcached}
+%{_libdir}/%{name}/memcached.so
+%endif
+%if %{with_memory}
+%{_libdir}/%{name}/memory.so
+%endif
+%if %{with_multimeter}
+%{_libdir}/%{name}/multimeter.so
+%endif
+%if %{with_network}
+%{_libdir}/%{name}/network.so
+%endif
+%if %{with_nfs}
+%{_libdir}/%{name}/nfs.so
+%endif
+%if %{with_ntpd}
+%{_libdir}/%{name}/ntpd.so
+%endif
+%if %{with_numa}
+%{_libdir}/%{name}/numa.so
+%endif
+%if %{with_openvpn}
+%{_libdir}/%{name}/openvpn.so
+%endif
+%if %{with_olsrd}
+%{_libdir}/%{name}/olsrd.so
+%endif
+%if %{with_powerdns}
+%{_libdir}/%{name}/powerdns.so
+%endif
+%if %{with_processes}
+%{_libdir}/%{name}/processes.so
+%endif
+%if %{with_protocols}
+%{_libdir}/%{name}/protocols.so
+%endif
+%if %{with_serial}
+%{_libdir}/%{name}/serial.so
+%endif
+%if %{with_statsd}
+%{_libdir}/%{name}/statsd.so
+%endif
+%if %{with_swap}
+%{_libdir}/%{name}/swap.so
+%endif
+%if %{with_syslog}
+%{_libdir}/%{name}/syslog.so
+%endif
+%if %{with_table}
+%{_libdir}/%{name}/table.so
+%endif
+%if %{with_tail}
+%{_libdir}/%{name}/tail.so
+%endif
+%if %{with_tail_csv}
+%{_libdir}/%{name}/tail_csv.so
+%endif
+%if %{with_tcpconns}
+%{_libdir}/%{name}/tcpconns.so
+%endif
+%if %{with_teamspeak2}
+%{_libdir}/%{name}/teamspeak2.so
+%endif
+%if %{with_ted}
+%{_libdir}/%{name}/ted.so
+%endif
+%if %{with_thermal}
+%{_libdir}/%{name}/thermal.so
+%endif
+%if %{with_threshold}
+%{_libdir}/%{name}/threshold.so
+%endif
+%if %{with_turbostat}
+%{_libdir}/%{name}/turbostat.so
+%endif
+%if %{with_unixsock}
+%{_libdir}/%{name}/unixsock.so
+%endif
+%if %{with_uptime}
+%{_libdir}/%{name}/uptime.so
+%endif
+%if %{with_users}
+%{_libdir}/%{name}/users.so
+%endif
+%if %{with_uuid}
+%{_libdir}/%{name}/uuid.so
+%endif
+%if %{with_vmem}
+%{_libdir}/%{name}/vmem.so
+%endif
+%if %{with_vserver}
+%{_libdir}/%{name}/vserver.so
+%endif
+%if %{with_wireless}
+%{_libdir}/%{name}/wireless.so
+%endif
+%if %{with_write_graphite}
+%{_libdir}/%{name}/write_graphite.so
+%endif
+%if %{with_write_log}
+%{_libdir}/%{name}/write_log.so
+%endif
+%if %{with_write_sensu}
+%{_libdir}/%{name}/write_sensu.so
+%endif
+%if %{with_write_tsdb}
+%{_libdir}/%{name}/write_tsdb.so
+%endif
+%if %{with_zfs_arc}
+%{_libdir}/%{name}/zfs_arc.so
+%endif
+%if %{with_zookeeper}
+%{_libdir}/%{name}/zookeeper.so
+%endif
+
+%files -n libcollectdclient-devel
+%{_includedir}/collectd/client.h
+%{_includedir}/collectd/network.h
+%{_includedir}/collectd/network_buffer.h
+%{_includedir}/collectd/lcc_features.h
+%{_libdir}/pkgconfig/libcollectdclient.pc
+
+%files -n libcollectdclient
+%{_libdir}/libcollectdclient.so
+%{_libdir}/libcollectdclient.so.*
+
+%files -n collectd-utils
+%{_bindir}/collectd-nagios
+%{_bindir}/collectd-tg
+%{_bindir}/collectdctl
+%{_mandir}/man1/collectdctl.1*
+%{_mandir}/man1/collectd-nagios.1*
+%{_mandir}/man1/collectd-tg.1*
+
+%if %{with_amqp}
+%files amqp
+%{_libdir}/%{name}/amqp.so
+%endif
+
+%if %{with_apache}
+%files apache
+%{_libdir}/%{name}/apache.so
+%endif
+
+%if %{with_aquaero}
+%files aquaero
+%{_libdir}/%{name}/aquaero.so
+%endif
+
+%if %{with_ascent}
+%files ascent
+%{_libdir}/%{name}/ascent.so
+%endif
+
+%if %{with_barometer}
+%files barometer
+%{_libdir}/%{name}/barometer.so
+%endif
+
+%if %{with_bind}
+%files bind
+%{_libdir}/%{name}/bind.so
+%endif
+
+%if %{with_ceph}
+%files ceph
+%{_libdir}/%{name}/ceph.so
+%endif
+
+%if %{with_curl}
+%files curl
+%{_libdir}/%{name}/curl.so
+%endif
+
+%if %{with_curl_json}
+%files curl_json
+%{_libdir}/%{name}/curl_json.so
+%endif
+
+%if %{with_curl_xml}
+%files curl_xml
+%{_libdir}/%{name}/curl_xml.so
+%endif
+
+%if %{with_disk}
+%files disk
+%{_libdir}/%{name}/disk.so
+%endif
+
+%if %{with_dns}
+%files dns
+%{_libdir}/%{name}/dns.so
+%endif
+
+%if %{with_dbi}
+%files dbi
+%{_libdir}/%{name}/dbi.so
+%endif
+
+%if %{with_email}
+%files email
+%{_libdir}/%{name}/email.so
+%endif
+
+%if %{with_gmond}
+%files gmond
+%{_libdir}/%{name}/gmond.so
+%endif
+
+%if %{with_hddtemp}
+%files hddtemp
+%{_libdir}/%{name}/hddtemp.so
+%endif
+
+%if %{with_ipmi}
+%files ipmi
+%{_libdir}/%{name}/ipmi.so
+%endif
+
+%if %{with_iptables}
+%files iptables
+%{_libdir}/%{name}/iptables.so
+%endif
+
+%if %{with_java}
+%files java
+%{_datadir}/collectd/java/collectd-api.jar
+%{_datadir}/collectd/java/generic-jmx.jar
+%{_libdir}/%{name}/java.so
+%{_mandir}/man5/collectd-java.5*
+%endif
+
+%if %{with_virt}
+%files virt
+%{_libdir}/%{name}/virt.so
+%endif
+
+%if %{with_log_logstash}
+%files log_logstash
+%{_libdir}/%{name}/log_logstash.so
+%endif
+
+%if %{with_lvm}
+%files lvm
+%{_libdir}/%{name}/lvm.so
+%endif
+
+%if %{with_memcachec}
+%files memcachec
+%{_libdir}/%{name}/memcachec.so
+%endif
+
+%if %{with_mic}
+%files mic
+%{_libdir}/%{name}/mic.so
+%endif
+
+%if %{with_modbus}
+%files modbus
+%{_libdir}/%{name}/modbus.so
+%endif
+
+%if %{with_mysql}
+%files mysql
+%{_libdir}/%{name}/mysql.so
+%endif
+
+%if %{with_netlink}
+%files netlink
+%{_libdir}/%{name}/netlink.so
+%endif
+
+%if %{with_nginx}
+%files nginx
+%{_libdir}/%{name}/nginx.so
+%endif
+
+%if %{with_notify_desktop}
+%files notify_desktop
+%{_libdir}/%{name}/notify_desktop.so
+%endif
+
+%if %{with_notify_email}
+%files notify_email
+%{_libdir}/%{name}/notify_email.so
+%endif
+
+%if %{with_nut}
+%files nut
+%{_libdir}/%{name}/nut.so
+%endif
+
+%if %{with_openldap}
+%files openldap
+%{_libdir}/%{name}/openldap.so
+%endif
+
+%if %{with_perl}
+%files perl
+%{perl_vendorlib}/Collectd.pm
+%{perl_vendorlib}/Collectd/
+%{_mandir}/man3/Collectd::Unixsock.3pm*
+%{_mandir}/man5/collectd-perl.5*
+%{_libdir}/%{name}/perl.so
+%endif
+
+%if %{with_pinba}
+%files pinba
+%{_libdir}/%{name}/pinba.so
+%endif
+
+%if %{with_ping}
+%files ping
+%{_libdir}/%{name}/ping.so
+%endif
+
+%if %{with_postgresql}
+%files postgresql
+%{_datadir}/collectd/postgresql_default.conf
+%{_libdir}/%{name}/postgresql.so
+%endif
+
+%if %{with_python}
+%files python
+%{_mandir}/man5/collectd-python*
+%{_libdir}/%{name}/python.so
+%endif
+
+%if %{with_redis}
+%files redis
+%{_libdir}/%{name}/redis.so
+%endif
+
+%if %{with_rrdcached}
+%files rrdcached
+%{_libdir}/%{name}/rrdcached.so
+%endif
+
+%if %{with_rrdtool}
+%files rrdtool
+%{_libdir}/%{name}/rrdtool.so
+%endif
+
+%if %{with_sensors}
+%files sensors
+%{_libdir}/%{name}/sensors.so
+%endif
+
+%if %{with_sigrok}
+%files sigrok
+%{_libdir}/%{name}/sigrok.so
+%endif
+
+%if %{with_smart}
+%files smart
+%{_libdir}/%{name}/smart.so
+%endif
+
+%if %{with_snmp}
+%files snmp
+%{_mandir}/man5/collectd-snmp.5*
+%{_libdir}/%{name}/snmp.so
+%endif
+
+%if %{with_varnish}
+%files varnish
+%{_libdir}/%{name}/varnish.so
+%endif
+
+%if %{with_write_http}
+%files write_http
+%{_libdir}/%{name}/write_http.so
+%endif
+
+%if %{with_write_kafka}
+%files write_kafka
+%{_libdir}/%{name}/write_kafka.so
+%endif
+
+%if %{with_write_redis}
+%files write_redis
+%{_libdir}/%{name}/write_redis.so
+%endif
+
+%if %{with_write_riemann}
+%files write_riemann
+%{_libdir}/%{name}/write_riemann.so
+%endif
+
+%files collection3
+%{_localstatedir}/www/collection3
+%{_sysconfdir}/httpd/conf.d/collection3.conf
+
+%files php-collection
+%{_localstatedir}/www/php-collection
+%{_sysconfdir}/httpd/conf.d/php-collection.conf
+
+%files contrib
+%doc contrib/
+
+%changelog
+* Wed May 27 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
+- New upstream version
+- New plugins enabled by default: ceph, drbd, log_logstash, write_tsdb, smart,
+  openldap, redis, write_redis, zookeeper, write_log, write_sensu, ipc,
+  turbostat, fhcount
+- New plugins disabled by default: barometer, write_kafka
+- Enable zfs_arc, now supported on Linux
+- Install disk plugin in a dedicated package, as it depends on libudev
+- use systemd on EL7, sysvinit on EL6 & EL5
+- Install collectdctl, collectd-tg and collectd-nagios in collectd-utils.rpm
+- Add build-dependency on libcap-devel
+
+* Mon Aug 19 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.4.0-1
+- New upstream version
+- Build netlink plugin by default
+- Enable cgroups, lvm and statsd plugins
+- Enable (but don't build by default) mic, aquaero and sigrok plugins
+
+* Tue Aug 06 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.3.1-1
+- New upstream version
+- Added RHEL5 support:
+  * conditionally disable plugins not building on this platform
+  * add/specify some build dependencies and options
+  * replace some RPM macros not available on this platform
+- Removed duplicate --enable-aggregation
+- Added some comments & usage examples
+- Replaced a couple of "Buildrequires" by "BuildRequires"
+- Enabled modbus plugin on RHEL6
+- Enabled netlink plugin on RHEL6 and RHEL7
+- Allow perl plugin to build on RHEL5
+- Add support for RHEL7
+- Misc perl-related improvements:
+  * prevent rpmbuild from extracting dependencies from files in /usr/share/doc
+  * don't package collection3 and php-collection twice
+  * keep perl scripts from contrib/ in collectd-contrib
+
+* Wed Apr 10 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.3.0-1
+- New upstream version
+- Enabled write_riemann plugin
+- Enabled tail_csv plugin
+- Installed collectd-tc manpage
+
+* Fri Jan 11 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.2.0-3
+- remove dependency on libstatgrab, which isn't required on linux
+
+* Thu Jan 03 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.2.0-2
+- collection3 and php-collection viewers are now in separate packages
+
+* Fri Dec 21 2012 Marc Fournier <marc.fournier@camptocamp.com> 5.2.0-1
+- New upstream version
+- Enabled aggregation plugin
+- Installed collectd-tc
+- Added network.h and network_buffer.h to libcollectdclient-devel
+- Moved libxml2-devel and libcurl-devel BRs to relevant plugins sections
+- Moved libcollectdclient.so from libcollectdclient-devel to libcollectdclient
+- Added rrdcached and redis plugin descriptions
+- Mentioned new pf plugin in disabled plugins list
+
+* Sun Nov 18 2012 Ruben Kerkhof <ruben@tilaa.nl> 5.1.0-3
+- Follow Fedora Packaging Guidelines in java subpackage
+
+* Sat Nov 17 2012 Ruben Kerkhof <ruben@tilaa.nl> 5.1.0-2
+- Move perl stuff to perl_vendorlib
+- Replace hardcoded paths with macros
+- Remove unnecessary Requires
+- Removed .a and .la files
+- Some other small cleanups
+
+* Fri Nov 16 2012 Marc Fournier <marc.fournier@camptocamp.com> 5.1.0-1
+- New upstream version
+- Changes to support 5.1.0
+- Enabled all buildable plugins based on libraries available on EL6 + EPEL
+- All plugins requiring external libraries are now shipped in separate
+  packages.
+- No longer treat Java plugin as an exception, correctly set $JAVA_HOME during
+  the build process + ensure build deps are installed.
+- Dropped per-plugin configuration files, as they tend to diverge from upstream
+  defaults.
+- Moved perl stuff to /usr/share/perl5/
+- Don't alter Interval and ReadThreads by default, let the user change this
+  himself.
+- Initscript improvements:
+  * checks configuration before (re)starting, based on debian's initscript
+  * use /etc/sysconfig instdead of /etc/default
+  * include optional $ARGS in arguments passed to collectd.
+- Drop collection.cgi from main package, as it's been obsoleted by collection3
+- Moved contrib/ to its own package, to avoid cluttering the main package with
+  non-essential stuff.
+- Replaced BuildPrereq by BuildRequires
+
+* Mon Jan 03 2011 Monetate <jason.stelzer@monetate.com> 5.0.1
+- New upstream version
+- Changes to support 5.0.1
+
+* Mon Jan 04 2010 Rackspace <stu.hood@rackspace.com> 4.9.0
+- New upstream version
+- Changes to support 4.9.0
+- Added support for Java/GenericJMX plugin
+
+* Mon Mar 17 2008 RightScale <support@rightscale.com> 4.3.1
+- New upstream version
+- Changes to support 4.3.1
+- Added More Prereqs to support more plugins
+- Added support for perl plugin
+
+* Mon Aug 06 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.6
+- New upstream version
+
+* Wed Jul 25 2007 Kjell Randa <Kjell.Randa@broadpark.no> 4.0.5
+- New major releas
+- Changes to support 4.0.5
+
+* Thu Jan 11 2007 Iain Lea <iain@bricbrac.de> 3.11.0-0
+- fixed spec file to build correctly on fedora core
+- added improved init.d script to work with chkconfig
+- added %%post and %%postun to call chkconfig automatically
+
+* Sun Jul 09 2006 Florian octo Forster <octo@verplant.org> 3.10.0-1
+- New upstream version
+
+* Sun Jun 25 2006 Florian octo Forster <octo@verplant.org> 3.9.4-1
+- New upstream version
+
+* Thu Jun 01 2006 Florian octo Forster <octo@verplant.org> 3.9.3-1
+- New upstream version
+
+* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.9.2-1
+- New upstream version
+
+* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.8.5-1
+- New upstream version
+
+* Fri Apr 21 2006 Florian octo Forster <octo@verplant.org> 3.9.1-1
+- New upstream version
+
+* Fri Apr 14 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
+- New upstream version
+- Added the `apache' package.
+
+* Tue Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
+- New upstream version
+
+* Mon Mar 13 2006 Florian octo Forster <octo@verplant.org> 3.8.1-1
+- New upstream version
+
+* Thu Mar 09 2006 Florian octo Forster <octo@verplant.org> 3.8.0-1
+- New upstream version
+
+* Sat Feb 18 2006 Florian octo Forster <octo@verplant.org> 3.7.2-1
+- Include `tape.so' so the build doesn't terminate because of missing files..
+- New upstream version
+
+* Sat Feb 04 2006 Florian octo Forster <octo@verplant.org> 3.7.1-1
+- New upstream version
+
+* Mon Jan 30 2006 Florian octo Forster <octo@verplant.org> 3.7.0-1
+- New upstream version
+- Removed the extra `hddtemp' package
+
+* Tue Jan 24 2006 Florian octo Forster <octo@verplant.org> 3.6.2-1
+- New upstream version
+
+* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.1-1
+- New upstream version
+
+* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.0-1
+- New upstream version
+- Added config file, `collectd.conf(5)', `df.so'
+- Added package `collectd-mysql', dependency on `mysqlclient10 | mysql'
+
+* Wed Dec 07 2005 Florian octo Forster <octo@verplant.org> 3.5.0-1
+- New upstream version
+
+* Sat Nov 26 2005 Florian octo Forster <octo@verplant.org> 3.4.0-1
+- New upstream version
+
+* Sat Nov 05 2005 Florian octo Forster <octo@verplant.org> 3.3.0-1
+- New upstream version
+
+* Wed Oct 26 2005 Florian octo Forster <octo@verplant.org> 3.2.0-1
+- New upstream version
+- Added statement to remove the `*.la' files. This fixes a problem when
+  `Unpackaged files terminate build' is in effect.
+- Added `processes.so*' to the main package
+
+* Fri Oct 14 2005 Florian octo Forster <octo@verplant.org> 3.1.0-1
+- New upstream version
+- Added package `collectd-hddtemp'
+
+* Fri Sep 30 2005 Florian octo Forster <octo@verplant.org> 3.0.0-1
+- New upstream version
+- Split the package into `collectd' and `collectd-sensors'
+
+* Fri Sep 16 2005 Florian octo Forster <octo@verplant.org> 2.1.0-1
+- New upstream version
+
+* Sat Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
+- New upstream version
+
+* Mon Aug 29 2005 Florian octo Forster <octo@verplant.org> 1.8.0-1
+- New upstream version
+
+* Thu Aug 25 2005 Florian octo Forster <octo@verplant.org> 1.7.0-1
+- New upstream version
+
+* Sun Aug 21 2005 Florian octo Forster <octo@verplant.org> 1.6.0-1
+- New upstream version
+
+* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5.1-1
+- New upstream version
+
+* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5-1
+- New upstream version
+
+* Mon Jul 11 2005 Florian octo Forster <octo@verplant.org> 1.4.2-1
+- New upstream version
+
+* Sat Jul 09 2005 Florian octo Forster <octo@verplant.org> 1.4-1
+- Built on RedHat 7.3
diff --git a/contrib/redhat/collection3.conf b/contrib/redhat/collection3.conf
new file mode 100644 (file)
index 0000000..91596b4
--- /dev/null
@@ -0,0 +1,5 @@
+Alias /collection3/ /var/www/collection3/
+<Directory /var/www/collection3/>
+    Options +Indexes
+    AllowOverride all
+</Directory>
diff --git a/contrib/redhat/init.d-collectd b/contrib/redhat/init.d-collectd
new file mode 100644 (file)
index 0000000..829eda5
--- /dev/null
@@ -0,0 +1,106 @@
+#!/bin/bash
+#
+# collectd    Startup script for the Collectd statistics gathering daemon
+# chkconfig: - 99 01
+# description: Collectd is a statistics gathering daemon used to collect \
+#   system information ie. cpu, memory, disk, network
+# processname: collectd
+# config: /etc/collectd.conf
+# config: /etc/sysconfig/collectd
+# pidfile: /var/run/collectd.pid
+
+# Source function library.
+. /etc/init.d/functions
+
+RETVAL=0
+ARGS=""
+prog="collectdmon"
+service="collectd"
+CONFIG=/etc/collectd.conf
+COLLECTD=/usr/sbin/collectd
+COLLECTDMONPIDDIR="/var/run"
+COLLECTDMONPID="$COLLECTDMONPIDDIR/collectdmon.pid"
+
+MAXWAIT=30
+
+if [ -r /etc/sysconfig/$service ]; then
+       . /etc/sysconfig/$service
+fi
+
+if [[ ! -d $COLLECTDMONPIDDIR ]]; then
+       mkdir -p $COLLECTDMONPIDDIR
+       [ -n "${RUNAS}" ] && chown "${RUNAS}:" "$COLLECTDMONPIDDIR"
+fi
+
+check_config() {
+        if test ! -r "$CONFIG"; then
+                return 2
+        fi
+        if ! $COLLECTD -t -C "$CONFIG"; then
+                return 1
+        fi
+        return 0
+}
+
+start () {
+       echo -n $"Starting collectd: "
+       check_config
+       rc="$?"
+       if test "$rc" -ne 0; then
+               RETVAL=6
+               echo $"not starting due to configuration error"
+               failure $"not starting $service due to configuration error"
+       else
+               daemon --user "${RUNAS:-root}" $prog -P $COLLECTDMONPID -c $COLLECTD -- -C "$CONFIG" $ARGS
+               RETVAL=$?
+               echo
+               [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$service
+       fi
+}
+
+stop () {
+       echo -n $"Stopping collectd: "
+       killproc -p $COLLECTDMONPID -d $MAXWAIT $prog
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$service
+}
+
+restart () {
+       check_config
+       rc="$?"
+       if test "$rc" -ne 0; then
+               RETVAL=6
+               echo $"not restarting due to configuration error"
+               failure $"not restarting $service due to configuration error"
+       else
+               stop
+               start
+       fi
+}
+
+# See how we were called.
+case "$1" in
+  start)
+       start
+       ;;
+  stop)
+       stop
+       ;;
+  status)
+       status -p $COLLECTDMONPID $prog
+       ;;
+  restart|reload)
+       restart
+       ;;
+  condrestart)
+       [ -f /var/lock/subsys/$service ] && restart || :
+       ;;
+  *)
+       echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
+       exit 1
+esac
+
+exit $?
+
+# vim:syntax=sh
diff --git a/contrib/redhat/php-collection.conf b/contrib/redhat/php-collection.conf
new file mode 100644 (file)
index 0000000..88bb609
--- /dev/null
@@ -0,0 +1,6 @@
+Alias /php-collection/ /var/www/php-collection/
+<Directory /var/www/php-collection/>
+    DirectoryIndex index.php
+    Options -Indexes
+    AddType application/x-httpd-php .php
+</Directory>
diff --git a/contrib/rrd_filter.px b/contrib/rrd_filter.px
new file mode 100755 (executable)
index 0000000..d28f9f2
--- /dev/null
@@ -0,0 +1,874 @@
+#!/usr/bin/perl
+
+# collectd - contrib/rrd_filter.px
+# Copyright (C) 2007-2008  Florian octo Forster
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; only version 2 of the License is applicable.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#
+# Authors:
+#   Florian octo Forster <octo at verplant.org>
+
+use strict;
+use warnings;
+
+=head1 NAME
+
+rrd_filter.px - Perform same advanced non-standard operations on an RRD file.
+
+=head1 SYNOPSYS
+
+  rrd_filter.px -i input.rrd -o output.rrd [options]
+
+=head1 DEPENDENCIES
+
+rrd_filter.px requires the RRDTool binary, Perl and the included
+L<Getopt::Long> module.
+
+=cut
+
+use Getopt::Long ('GetOptions');
+
+our $InFile;
+our $InDS = [];
+our $OutFile;
+our $OutDS = [];
+
+our $NewDSes = [];
+our $NewRRAs = [];
+
+our $Step = 0;
+
+our $Scale = 1.0;
+our $Shift = 0.0;
+
+our $Debug = 0;
+
+=head1 OPTIONS
+
+The following options can be passed on the command line:
+
+=over 4
+
+=item B<--infile> I<file>
+
+=item B<-i> I<file>
+
+Reads from I<file>. If I<file> ends in C<.rrd>, then C<rrdtool dump> is invoked
+to create an XML dump of the RRD file. Otherwise the XML dump is expected
+directly. The special filename C<-> can be used to read from STDIN.
+
+=item B<--outfile> I<file>
+
+=item B<-o> I<file>
+
+Writes output to I<file>. If I<file> ends in C<.rrd>, then C<rrdtool restore>
+is invoked to create a binary RRD file. Otherwise an XML output is written. The
+special filename C<-> can be used to write to STDOUT.
+
+=item B<--map> I<in_ds>:I<out_ds>
+
+=item B<-m> I<in_ds>:I<out_ds>
+
+Writes the datasource I<in_ds> to the output and renames it to I<out_ds>. This
+is useful to extract one DS from an RRD file.
+
+=item B<--step> I<seconds>
+
+=item B<-s> I<seconds>
+
+Changes the step of the output RRD file to be I<seconds>. The new stepsize must
+be a multiple of the old stepsize of the other way around. When increasing the
+stepsize the number of PDPs in each RRA must be dividable by the factor by
+which the stepsize is increased. The length of CDPs and the absolute length of
+RRAs (and thus the data itself) is not altered.
+
+Examples:
+
+  step =  10, rra_steps = 12   =>   step = 60, rra_steps =  2
+  step = 300, rra_steps =  1   =>   step = 10, rra_steps = 30
+
+=item B<--rra> B<RRA>:I<CF>:I<XFF>:I<steps>:I<rows>
+
+=item B<-a> B<RRA>:I<CF>:I<XFF>:I<steps>:I<rows>
+
+Inserts a new RRA in the generated RRD file. This is done B<after> the step has
+been adjusted, take that into account when specifying I<steps> and I<rows>. For
+an explanation of the format please see L<rrdcreate(1)>.
+
+=item B<--scale> I<factor>
+
+Scales the values by the factor I<factor>, i.E<nbsp>e. all values are
+multiplied by I<factor>.
+
+=item B<--shift> I<offset>
+
+Shifts all values by I<offset>, i.E<nbsp>e. I<offset> is added to all values.
+
+=back
+
+=cut
+
+GetOptions ("infile|i=s" => \$InFile,
+       "outfile|o=s" => \$OutFile,
+       'map|m=s' => sub
+       {
+               my ($in_ds, $out_ds) = split (':', $_[1]);
+               if (!defined ($in_ds) || !defined ($out_ds))
+               {
+                       print STDERR "Argument for `map' incorrect! The format is `--map in_ds:out_ds'\n";
+                       exit (1);
+               }
+               push (@$InDS, $in_ds);
+               push (@$OutDS, $out_ds);
+       },
+       'step|s=i' => \$Step,
+       'ds|d=s' => sub
+       {
+               #DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heartbeat:min:max
+               my ($ds, $name, $type, $hb, $min, $max) = split (':', $_[1]);
+               if (($ds ne 'DS') || !defined ($max))
+               {
+                       print STDERR "Please use the standard RRDTool syntax when adding DSes. I. e. DS:<name>:<type>:<heartbeat>:<min>:<max>.\n";
+                       exit (1);
+               }
+               push (@$NewDSes, {name => $name, type => $type, heartbeat => $hb, min => $min, max => $max});
+       },
+       'rra|a=s' => sub
+       {
+               my ($rra, $cf, $xff, $steps, $rows) = split (':', $_[1]);
+               if (($rra ne 'RRA') || !defined ($rows))
+               {
+                       print STDERR "Please use the standard RRDTool syntax when adding RRAs. I. e. RRA:<cf><xff>:<steps>:<rows>.\n";
+                       exit (1);
+               }
+               push (@$NewRRAs, {cf => $cf, xff => $xff, steps => $steps, rows => $rows});
+       },
+       'scale=f' => \$Scale,
+       'shift=f' => \$Shift
+) or exit (1);
+
+if (!$InFile || !$OutFile)
+{
+       print STDERR "Usage: $0 -i <infile> -m <in_ds>:<out_ds> -s <step>\n";
+       exit (1);
+}
+if ((1 + @$InDS) != (1 + @$OutDS))
+{
+       print STDERR "You need the same amount of in- and out-DSes\n";
+       exit (1);
+}
+main ($InFile, $OutFile);
+exit (0);
+
+{
+my $ds_index;
+my $current_index;
+# state 0 == searching for DS index
+# state 1 == parse RRA header
+# state 2 == parse values
+my $state;
+my $out_cache;
+sub handle_line_dsmap
+{
+       my $line = shift;
+       my $index = shift;
+       my $ret = '';
+
+       if ((@$InDS == 0) || (@$OutDS == 0))
+       {
+               post_line ($line, $index + 1);
+               return;
+       }
+
+       if (!defined ($state))
+       {
+               $current_index = -1;
+               $state = 0;
+               $out_cache = [];
+
+               # $ds_index->[new_index] = old_index
+               $ds_index = [];
+               for (my $i = 0; $i < @$InDS; $i++)
+               {
+                       print STDOUT "DS map $i: $InDS->[$i] -> $OutDS->[$i]\n" if ($Debug);
+                       $ds_index->[$i] = -1;
+               }
+       }
+
+       if ($state == 0)
+       {
+               if ($line =~ m/<ds>/)
+               {
+                       $current_index++;
+                       $out_cache->[$current_index] = $line;
+               }
+               elsif ($line =~ m#<name>\s*([^<\s]+)\s*</name>#)
+               {
+                       # old_index == $current_index
+                       # new_index == $i
+                       for (my $i = 0; $i < @$InDS; $i++)
+                       {
+                               next if ($ds_index->[$i] >= 0);
+
+                               if ($1 eq $InDS->[$i])
+                               {
+                                       $line =~ s#<name>\s*([^<\s]+)\s*</name>#<name> $OutDS->[$i] </name>#;
+                                       $ds_index->[$i] = $current_index;
+                                       last;
+                               }
+                       }
+
+                       $out_cache->[$current_index] .= $line;
+               }
+               elsif ($line =~ m#<last_ds>\s*([^\s>]+)\s*</last_ds>#i)
+               {
+                       $out_cache->[$current_index] .= "\t\t<last_ds> NaN </last_ds>\n";
+               }
+               elsif ($line =~ m#<value>\s*([^\s>]+)\s*</value>#i)
+               {
+                       $out_cache->[$current_index] .= "\t\t<value> NaN </value>\n";
+               }
+               elsif ($line =~ m#</ds>#)
+               {
+                       $out_cache->[$current_index] .= $line;
+               }
+               elsif ($line =~ m#<rra>#)
+               {
+                       # Print out all the DS definitions we need
+                       for (my $new_index = 0; $new_index < @$InDS; $new_index++)
+                       {
+                               my $old_index = $ds_index->[$new_index];
+                               while ($out_cache->[$old_index] =~ m/^(.*)$/gm)
+                               {
+                                       post_line ("$1\n", $index + 1);
+                               }
+                       }
+
+                       # Clear the cache - it's used in state1, too.
+                       for (my $i = 0; $i <= $current_index; $i++)
+                       {
+                               $out_cache->[$i] = '';
+                       }
+
+                       $ret .= $line;
+                       $current_index = -1;
+                       $state = 1;
+               }
+               elsif ($current_index == -1)
+               {
+                       # Print all the lines before the first DS definition
+                       $ret .= $line;
+               }
+               else
+               {
+                       # Something belonging to a DS-definition
+                       $out_cache->[$current_index] .= $line;
+               }
+       }
+       elsif ($state == 1)
+       {
+               if ($line =~ m#<ds>#)
+               {
+                       $current_index++;
+                       $out_cache->[$current_index] .= $line;
+               }
+               elsif ($line =~ m#<value>\s*([^\s>]+)\s*</value>#i)
+               {
+                       $out_cache->[$current_index] .= "\t\t\t<value> NaN </value>\n";
+               }
+               elsif ($line =~ m#</cdp_prep>#)
+               {
+                       # Print out all the DS definitions we need
+                       for (my $new_index = 0; $new_index < @$InDS; $new_index++)
+                       {
+                               my $old_index = $ds_index->[$new_index];
+                               while ($out_cache->[$old_index] =~ m/^(.*)$/gm)
+                               {
+                                       post_line ("$1\n", $index + 1);
+                               }
+                       }
+
+                       # Clear the cache
+                       for (my $i = 0; $i <= $current_index; $i++)
+                       {
+                               $out_cache->[$i] = '';
+                       }
+
+                       $ret .= $line;
+                       $current_index = -1;
+               }
+               elsif ($line =~ m#<database>#)
+               {
+                       $ret .= $line;
+                       $state = 2;
+               }
+               elsif ($current_index == -1)
+               {
+                       # Print all the lines before the first DS definition
+                       # and after cdp_prep
+                       $ret .= $line;
+               }
+               else
+               {
+                       # Something belonging to a DS-definition
+                       $out_cache->[$current_index] .= $line;
+               }
+       }
+       elsif ($state == 2)
+       {
+               if ($line =~ m#</database>#)
+               {
+                       $ret .= $line;
+                       $current_index = -1;
+                       $state = 1;
+               }
+               else
+               {
+                       my @values = ();
+                       my $i;
+                       
+                       $ret .= "\t\t";
+
+                       if ($line =~ m#(<!-- .*? -->)#)
+                       {
+                               $ret .= "$1 ";
+                       }
+                       $ret .= "<row> ";
+
+                       $i = 0;
+                       while ($line =~ m#<v>\s*([^<\s]+)\s*</v>#g)
+                       {
+                               $values[$i] = $1;
+                               $i++;
+                       }
+
+                       for (my $new_index = 0; $new_index < @$InDS; $new_index++)
+                       {
+                               my $old_index = $ds_index->[$new_index];
+                               $ret .= '<v> ' . $values[$old_index] . ' </v> ';
+                       }
+                       $ret .= "</row>\n";
+               }
+       }
+       else
+       {
+               die;
+       }
+
+       if ($ret)
+       {
+               post_line ($ret, $index + 1);
+       }
+}} # handle_line_dsmap
+
+#
+# The _step_ handler
+#
+{
+my $step_factor_up;
+my $step_factor_down;
+sub handle_line_step
+{
+       my $line = shift;
+       my $index = shift;
+
+       if (!$Step)
+       {
+               post_line ($line, $index + 1);
+               return;
+       }
+
+       if ($Debug && !defined ($step_factor_up))
+       {
+               print STDOUT "New step: $Step\n";
+       }
+
+       $step_factor_up ||= 0;
+       $step_factor_down ||= 0;
+
+       if (($step_factor_up == 0) && ($step_factor_down == 0))
+       {
+               if ($line =~ m#<step>\s*(\d+)\s*</step>#i)
+               {
+                       my $old_step = 0 + $1;
+                       if ($Step < $old_step)
+                       {
+                               $step_factor_down = int ($old_step / $Step);
+                               if (($step_factor_down * $Step) != $old_step)
+                               {
+                                       print STDERR "The old step ($old_step seconds) "
+                                       . "is not a multiple of the new step "
+                                       . "($Step seconds).\n";
+                                       exit (1);
+                               }
+                               $line = "<step> $Step </step>\n";
+                       }
+                       elsif ($Step > $old_step)
+                       {
+                               $step_factor_up = int ($Step / $old_step);
+                               if (($step_factor_up * $old_step) != $Step)
+                               {
+                                       print STDERR "The new step ($Step seconds) "
+                                       . "is not a multiple of the old step "
+                                       . "($old_step seconds).\n";
+                                       exit (1);
+                               }
+                               $line = "<step> $Step </step>\n";
+                       }
+                       else
+                       {
+                               $Step = 0;
+                       }
+               }
+       }
+       elsif ($line =~ m#<pdp_per_row>\s*(\d+)\s*</pdp_per_row>#i)
+       {
+               my $old_val = 0 + $1;
+               my $new_val;
+               if ($step_factor_up)
+               {
+                       $new_val = int ($old_val / $step_factor_up);
+                       if (($new_val * $step_factor_up) != $old_val)
+                       {
+                               print STDERR "Can't divide number of PDPs per row ($old_val) by step-factor ($step_factor_up).\n";
+                               exit (1);
+                       }
+               }
+               else
+               {
+                       $new_val = $step_factor_down * $old_val;
+               }
+               $line = "<pdp_per_row> $new_val </pdp_per_row>\n";
+       }
+
+       post_line ($line, $index + 1);
+}} # handle_line_step
+
+#
+# The _add DS_ handler
+#
+{
+my $add_ds_done;
+sub handle_line_add_ds
+{
+  my $line = shift;
+  my $index = shift;
+
+  my $post = sub { for (@_) { post_line ($_, $index + 1); } };
+
+  if (!@$NewDSes)
+  {
+    $post->($line);
+    return;
+  }
+
+  if (!$add_ds_done && ($line =~ m#<rra>#i))
+  {
+    for (my $i = 0; $i < @$NewDSes; $i++)
+    {
+      my $ds = $NewDSes->[$i];
+      my $temp;
+
+      my $min;
+      my $max;
+
+      if ($Debug)
+      {
+       print STDOUT "Adding DS: name = $ds->{'name'}, type = $ds->{'type'}, heartbeat = $ds->{'heartbeat'}, min = $ds->{'min'}, max = $ds->{'max'}\n";
+      }
+
+      $min = 'NaN';
+      if (defined ($ds->{'min'}) && ($ds->{'min'} ne 'U'))
+      {
+       $min = sprintf ('%.10e', $ds->{'min'});
+      }
+      
+      $max = 'NaN';
+      if (defined ($ds->{'max'}) && ($ds->{'max'} ne 'U'))
+      {
+       $max = sprintf ('%.10e', $ds->{'max'});
+      }
+      
+
+      $post->("\t<ds>\n",
+      "\t\t<name> $ds->{'name'} </name>\n",
+      "\t\t<type> $ds->{'type'} </type>\n",
+      "\t\t<minimal_heartbeat> $ds->{'heartbeat'} </minimal_heartbeat>\n",
+      "\t\t<min> $min </min>\n",
+      "\t\t<max> $max </max>\n",
+      "\n",
+      "\t\t<!-- PDP Status -->\n",
+      "\t\t<last_ds> UNKN </last_ds>\n",
+      "\t\t<value> NaN </value>\n",
+      "\t\t<unknown_sec> 0 </unknown_sec>\n",
+      "\t</ds>\n",
+      "\n");
+    }
+
+    $add_ds_done = 1;
+  }
+  elsif ($add_ds_done && ($line =~ m#</ds>#i)) # inside a cdp_prep block
+  {
+    $post->("\t\t\t</ds>\n",
+       "\t\t\t<ds>\n",
+       "\t\t\t<primary_value> NaN </primary_value>\n",
+       "\t\t\t<secondary_value> NaN </secondary_value>\n",
+       "\t\t\t<value> NaN </value>\n",
+       "\t\t\t<unknown_datapoints> 0 </unknown_datapoints>\n");
+  }
+  elsif ($line =~ m#<row>#i)
+  {
+         my $insert = '<v> NaN </v>' x (0 + @$NewDSes);
+         $line =~ s#</row>#$insert</row>#i;
+  }
+
+  $post->($line);
+}} # handle_line_add_ds
+
+#
+# The _add RRA_ handler
+#
+{
+my $add_rra_done;
+my $num_ds;
+sub handle_line_add_rra
+{
+  my $line = shift;
+  my $index = shift;
+
+  my $post = sub { for (@_) { post_line ($_, $index + 1); } };
+
+  $num_ds ||= 0;
+
+  if (!@$NewRRAs || $add_rra_done)
+  {
+    $post->($line);
+    return;
+  }
+
+  if ($line =~ m#<ds>#i)
+  {
+    $num_ds++;
+  }
+  elsif ($line =~ m#<rra>#i)
+  {
+    for (my $i = 0; $i < @$NewRRAs; $i++)
+    {
+      my $rra = $NewRRAs->[$i];
+      my $temp;
+
+      if ($Debug)
+      {
+       print STDOUT "Adding RRA: CF = $rra->{'cf'}, xff = $rra->{'xff'}, steps = $rra->{'steps'}, rows = $rra->{'rows'}, num_ds = $num_ds\n";
+      }
+
+      $post->("\t<rra>\n",
+      "\t\t<cf> $rra->{'cf'} </cf>\n",
+      "\t\t<pdp_per_row> $rra->{'steps'} </pdp_per_row>\n",
+      "\t\t<params>\n",
+      "\t\t\t<xff> $rra->{'xff'} </xff>\n",
+      "\t\t</params>\n",
+      "\t\t<cdp_prep>\n");
+
+      for (my $j = 0; $j < $num_ds; $j++)
+      {
+       $post->("\t\t\t<ds>\n",
+       "\t\t\t\t<primary_value> NaN </primary_value>\n",
+       "\t\t\t\t<secondary_value> NaN </secondary_value>\n",
+       "\t\t\t\t<value> NaN </value>\n",
+       "\t\t\t\t<unknown_datapoints> 0 </unknown_datapoints>\n",
+       "\t\t\t</ds>\n");
+      }
+
+      $post->("\t\t</cdp_prep>\n", "\t\t<database>\n");
+      $temp = "\t\t\t<row>" . join ('', map { "<v> NaN </v>" } (1 .. $num_ds)) . "</row>\n";
+      for (my $j = 0; $j < $rra->{'rows'}; $j++)
+      {
+       $post->($temp);
+      }
+      $post->("\t\t</database>\n", "\t</rra>\n");
+    }
+
+    $add_rra_done = 1;
+  }
+
+  $post->($line);
+}} # handle_line_add_rra
+
+#
+# The _scale/shift_ handler
+#
+sub calculate_scale_shift 
+{
+  my $value = shift;
+  my $tag = shift;
+  my $scale = shift;
+  my $shift = shift;
+
+  if (lc ("$value") eq 'nan')
+  {
+    $value = 'NaN';
+    return ("<$tag> NaN </$tag>");
+  }
+
+  $value = ($scale * (0.0 + $value)) + $shift;
+  return (sprintf ("<%s> %1.10e </%s>", $tag, $value, $tag));
+}
+
+sub handle_line_scale_shift
+{
+  my $line = shift;
+  my $index = shift;
+
+  if (($Scale != 1.0) || ($Shift != 0.0))
+  {
+    $line =~ s#<(min|max|last_ds|value|primary_value|secondary_value|v)>\s*([^\s<]+)\s*</[^>]+>#calculate_scale_shift ($2, $1, $Scale, $Shift)#eg;
+  }
+
+  post_line ($line, $index + 1);
+}
+
+#
+# The _output_ handler
+#
+# This filter is unfinished!
+#
+{
+my $fh;
+sub set_output
+{
+       $fh = shift;
+}
+
+{
+my $previous_values;
+my $previous_differences;
+my $pdp_per_row;
+sub handle_line_peak_detect
+{
+  my $line = shift;
+  my $index = shift;
+
+  if (!$previous_values)
+  {
+    $previous_values = [];
+    $previous_differences = [];
+  }
+
+  if ($line =~ m#</database>#i)
+  {
+    $previous_values = [];
+    $previous_differences = [];
+    print STDERR "==============================================================================\n";
+  }
+  elsif ($line =~ m#<pdp_per_row>\s*([1-9][0-9]*)\s*</pdp_per_row>#)
+  {
+    $pdp_per_row = int ($1);
+    print STDERR "pdp_per_row = $pdp_per_row;\n";
+  }
+  elsif ($line =~ m#<row>#)
+  {
+    my @values = ();
+    while ($line =~ m#<v>\s*([^\s>]+)\s*</v>#ig)
+    {
+      if ($1 eq 'NaN')
+      {
+       push (@values, undef);
+      }
+      else
+      {
+       push (@values, 0.0 + $1);
+      }
+    }
+
+    for (my $i = 0; $i < @values; $i++)
+    {
+      if (!defined ($values[$i]))
+      {
+       $previous_values->[$i] = undef;
+      }
+      elsif (!defined ($previous_values->[$i]))
+      {
+       $previous_values->[$i] = $values[$i];
+      }
+      elsif (!defined ($previous_differences->[$i]))
+      {
+       $previous_differences->[$i] = abs ($previous_values->[$i] - $values[$i]);
+      }
+      else
+      {
+       my $divisor = ($previous_differences->[$i] < 1.0) ? 1.0 : $previous_differences->[$i];
+       my $difference = abs ($previous_values->[$i] - $values[$i]);
+       my $change = $pdp_per_row * $difference / $divisor;
+       if (($divisor > 10.0) &&  ($change > 10e5))
+       {
+         print STDERR "i = $i; average difference = " . $previous_differences->[$i]. "; current difference = " . $difference. "; change = $change;\n";
+       }
+       $previous_values->[$i] = $values[$i];
+       $previous_differences->[$i] = (0.95 * $previous_differences->[$i]) + (0.05 * $difference);
+      }
+    }
+  }
+
+  post_line ($line, $index + 1);
+}} # handle_line_peak_detect
+
+sub handle_line_output
+{
+       my $line = shift;
+       my $index = shift;
+
+       if (!defined ($fh))
+       {
+               post_line ($line, $index + 1);
+               return;
+       }
+       
+       print $fh $line;
+}} # handle_line_output
+
+#
+# Dispatching logic
+#
+{
+my @handlers = ();
+sub add_handler
+{
+       my $handler = shift;
+
+       die unless (ref ($handler) eq 'CODE');
+       push (@handlers, $handler);
+} # add_handler
+
+sub post_line
+{
+       my $line = shift;
+       my $index = shift;
+
+       if (0)
+       {
+               my $copy = $line;
+               chomp ($copy);
+               print "DEBUG: post_line ($copy, $index);\n";
+       }
+
+       if ($index > $#handlers)
+       {
+               return;
+       }
+       $handlers[$index]->($line, $index);
+}} # post_line
+
+sub handle_fh
+{
+  my $in_fh = shift;
+  my $out_fh = shift;
+
+  set_output ($out_fh);
+
+  if (@$InDS)
+  {
+    add_handler (\&handle_line_dsmap);
+  }
+
+  if ($Step)
+  {
+    add_handler (\&handle_line_step);
+  }
+
+  if (($Scale != 1.0) || ($Shift != 0.0))
+  {
+    add_handler (\&handle_line_scale_shift);
+  }
+
+  #add_handler (\&handle_line_peak_detect);
+
+  if (@$NewDSes)
+  {
+    add_handler (\&handle_line_add_ds);
+  }
+
+  if (@$NewRRAs)
+  {
+    add_handler (\&handle_line_add_rra);
+  }
+
+  add_handler (\&handle_line_output);
+
+  while (my $line = <$in_fh>)
+  {
+    post_line ($line, 0);
+  }
+} # handle_fh
+
+sub main
+{
+       my $in_file = shift;
+       my $out_file = shift;
+
+       my $in_fh;
+       my $out_fh;
+
+       my $in_needs_close = 1;
+       my $out_needs_close = 1;
+
+       if ($in_file =~ m/\.rrd$/i)
+       {
+               open ($in_fh,  '-|', 'rrdtool', 'dump', $in_file) or die ("open (rrdtool): $!");
+       }
+       elsif ($in_file eq '-')
+       {
+               $in_fh = \*STDIN;
+               $in_needs_close = 0;
+       }
+       else
+       {
+               open ($in_fh, '<', $in_file) or die ("open ($in_file): $!");
+       }
+
+       if ($out_file =~ m/\.rrd$/i)
+       {
+               open ($out_fh, '|-', 'rrdtool', 'restore', '-', $out_file) or die ("open (rrdtool): $!");
+       }
+       elsif ($out_file eq '-')
+       {
+               $out_fh = \*STDOUT;
+               $out_needs_close = 0;
+       }
+       else
+       {
+               open ($out_fh, '>', $out_file) or die ("open ($out_file): $!");
+       }
+
+       handle_fh ($in_fh, $out_fh);
+
+       if ($in_needs_close)
+       {
+               close ($in_fh);
+       }
+       if ($out_needs_close)
+       {
+               close ($out_fh);
+       }
+} # main
+
+=head1 LICENSE
+
+This script is licensed under the GNU general public license, versionE<nbsp>2
+(GPLv2).
+
+=head1 AUTHOR
+
+Florian octo Forster E<lt>octo at verplant.orgE<gt>
+
diff --git a/contrib/sles10.1/collectd.spec b/contrib/sles10.1/collectd.spec
new file mode 100644 (file)
index 0000000..2d558bd
--- /dev/null
@@ -0,0 +1,231 @@
+Summary:       Statistics collection daemon for filling RRD files.
+Name:           collectd
+Version:       3.11.1
+Release:       0.sl10.1
+Source:                http://collectd.org/files/%{name}-%{version}.tar.gz
+Source1:       collectd-init.d
+License:       GPL
+Group:         System Environment/Daemons
+BuildRoot:     %{_tmppath}/%{name}-%{version}-root
+BuildPrereq:   curl-devel, sensors, mysql-devel, rrdtool, libpcap
+Requires:      rrdtool
+Packager:      Florian octo Forster <octo@verplant.org>
+Vendor:                Florian octo Forster <octo@verplant.org>
+
+%description
+collectd is a small daemon written in C for performance.  It reads various
+system  statistics  and updates  RRD files,  creating  them if neccessary.
+Since the daemon doesn't need to startup every time it wants to update the
+files it's very fast and easy on the system. Also, the statistics are very
+fine grained since the files are updated every 10 seconds.
+
+%package apache
+Summary:       apache-plugin for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, curl
+%description apache
+This plugin collects data provided by Apache's `mod_status'.
+
+%package dns
+Summary:       dns-plugin for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, libpcap
+%description dns
+This plugin collects information about DNS traffic, queries and responses.
+
+%package mysql
+Summary:       mysql-module for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, mysql
+%description mysql
+MySQL  querying  plugin.  This plugins  provides data of  issued commands,
+called handlers and database traffic.
+
+%package sensors
+Summary:       libsensors-module for collectd.
+Group:         System Environment/Daemons
+Requires:      collectd = %{version}, sensors
+%description sensors
+This  plugin  for  collectd  provides  querying  of sensors  supported  by
+lm_sensors.
+
+%prep
+rm -rf $RPM_BUILD_ROOT
+%setup
+
+%build
+./configure --prefix=%{_prefix} --sbindir=%{_sbindir} --mandir=%{_mandir} --libdir=%{_libdir} --sysconfdir=%{_sysconfdir} --localstatedir=%{_localstatedir}
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+cp src/collectd.conf $RPM_BUILD_ROOT/etc/collectd.conf
+mkdir -p $RPM_BUILD_ROOT/var/lib/collectd
+rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}/*.a
+rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}/*.la
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/init.d
+cp %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/init.d/collectd
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+chkconfig collectd on
+/etc/init.d/collectd start
+
+%preun
+/etc/init.d/collectd stop
+chkconfig collectd off
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
+%doc contrib
+%config /etc/collectd.conf
+%attr(0755,root,root) /etc/init.d/collectd
+%attr(0755,root,root) %{_sbindir}/collectd
+%attr(0444,root,root) %{_mandir}/man1/*
+%attr(0444,root,root) %{_mandir}/man5/*
+%attr(0444,root,root) %{_libdir}/%{name}/apcups.so
+%attr(0444,root,root) %{_libdir}/%{name}/apple_sensors.so
+%attr(0444,root,root) %{_libdir}/%{name}/battery.so
+%attr(0444,root,root) %{_libdir}/%{name}/cpu.so
+%attr(0444,root,root) %{_libdir}/%{name}/cpufreq.so
+%attr(0444,root,root) %{_libdir}/%{name}/df.so
+%attr(0444,root,root) %{_libdir}/%{name}/disk.so
+%attr(0444,root,root) %{_libdir}/%{name}/email.so
+%attr(0444,root,root) %{_libdir}/%{name}/hddtemp.so
+%attr(0444,root,root) %{_libdir}/%{name}/irq.so
+%attr(0444,root,root) %{_libdir}/%{name}/load.so
+%attr(0444,root,root) %{_libdir}/%{name}/mbmon.so
+%attr(0444,root,root) %{_libdir}/%{name}/memory.so
+%attr(0444,root,root) %{_libdir}/%{name}/multimeter.so
+%attr(0444,root,root) %{_libdir}/%{name}/nfs.so
+%attr(0444,root,root) %{_libdir}/%{name}/ntpd.so
+%attr(0444,root,root) %{_libdir}/%{name}/ping.so
+%attr(0444,root,root) %{_libdir}/%{name}/processes.so
+%attr(0444,root,root) %{_libdir}/%{name}/serial.so
+%attr(0444,root,root) %{_libdir}/%{name}/swap.so
+%attr(0444,root,root) %{_libdir}/%{name}/tape.so
+%attr(0444,root,root) %{_libdir}/%{name}/traffic.so
+%attr(0444,root,root) %{_libdir}/%{name}/users.so
+%attr(0444,root,root) %{_libdir}/%{name}/vserver.so
+%attr(0444,root,root) %{_libdir}/%{name}/wireless.so
+
+%dir /var/lib/collectd
+
+%files apache
+%attr(0444,root,root) %{_libdir}/%{name}/apache.so
+
+%files dns
+%attr(0444,root,root) %{_libdir}/%{name}/dns.so
+
+%files mysql
+%attr(0444,root,root) %{_libdir}/%{name}/mysql.so
+
+%files sensors
+%attr(0444,root,root) %{_libdir}/%{name}/sensors.so
+
+%changelog
+* Sun Jul 09 2006 Florian octo Forster <octo@verplant.org> 3.10.0-1
+- New upstream version
+
+* Tue Jun 25 2006 Florian octo Forster <octo@verplant.org> 3.9.4-1
+- New upstream version
+
+* Tue Jun 01 2006 Florian octo Forster <octo@verplant.org> 3.9.3-1
+- New upstream version
+
+* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.9.2-1
+- New upstream version
+
+* Tue May 09 2006 Florian octo Forster <octo@verplant.org> 3.8.5-1
+- New upstream version
+
+* Fri Apr 21 2006 Florian octo Forster <octo@verplant.org> 3.9.1-1
+- New upstream version
+
+* Fri Apr 14 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
+- New upstream version
+- Added the `apache' package.
+
+* Thu Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
+- New upstream version
+
+* Thu Mar 13 2006 Florian octo Forster <octo@verplant.org> 3.8.1-1
+- New upstream version
+
+* Thu Mar 09 2006 Florian octo Forster <octo@verplant.org> 3.8.0-1
+- New upstream version
+
+* Sat Feb 18 2006 Florian octo Forster <octo@verplant.org> 3.7.2-1
+- Include `tape.so' so the build doesn't terminate because of missing files..
+- New upstream version
+
+* Sat Feb 04 2006 Florian octo Forster <octo@verplant.org> 3.7.1-1
+- New upstream version
+
+* Mon Jan 30 2006 Florian octo Forster <octo@verplant.org> 3.7.0-1
+- New upstream version
+- Removed the extra `hddtemp' package
+
+* Tue Jan 24 2006 Florian octo Forster <octo@verplant.org> 3.6.2-1
+- New upstream version
+
+* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.1-1
+- New upstream version
+
+* Fri Jan 20 2006 Florian octo Forster <octo@verplant.org> 3.6.0-1
+- New upstream version
+- Added config file, `collectd.conf(5)', `df.so'
+- Added package `collectd-mysql', dependency on `mysqlclient10 | mysql'
+
+* Wed Dec 07 2005 Florian octo Forster <octo@verplant.org> 3.5.0-1
+- New upstream version
+
+* Sat Nov 26 2005 Florian octo Forster <octo@verplant.org> 3.4.0-1
+- New upstream version
+
+* Sat Nov 05 2005 Florian octo Forster <octo@verplant.org> 3.3.0-1
+- New upstream version
+
+* Tue Oct 26 2005 Florian octo Forster <octo@verplant.org> 3.2.0-1
+- New upstream version
+- Added statement to remove the `*.la' files. This fixes a problem when
+  `Unpackaged files terminate build' is in effect.
+- Added `processes.so*' to the main package
+
+* Fri Oct 14 2005 Florian octo Forster <octo@verplant.org> 3.1.0-1
+- New upstream version
+- Added package `collectd-hddtemp'
+
+* Fri Sep 30 2005 Florian octo Forster <octo@verplant.org> 3.0.0-1
+- New upstream version
+- Split the package into `collectd' and `collectd-sensors'
+
+* Fri Sep 16 2005 Florian octo Forster <octo@verplant.org> 2.1.0-1
+- New upstream version
+
+* Mon Sep 10 2005 Florian octo Forster <octo@verplant.org> 2.0.0-1
+- New upstream version
+
+* Mon Aug 29 2005 Florian octo Forster <octo@verplant.org> 1.8.0-1
+- New upstream version
+
+* Sun Aug 25 2005 Florian octo Forster <octo@verplant.org> 1.7.0-1
+- New upstream version
+
+* Sun Aug 21 2005 Florian octo Forster <octo@verplant.org> 1.6.0-1
+- New upstream version
+
+* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5.1-1
+- New upstream version
+
+* Sun Jul 17 2005 Florian octo Forster <octo@verplant.org> 1.5-1
+- New upstream version
+
+* Mon Jul 11 2005 Florian octo Forster <octo@verplant.org> 1.4.2-1
+- New upstream version
+
+* Sat Jul 09 2005 Florian octo Forster <octo@verplant.org> 1.4-1
+- Built on RedHat 7.3
diff --git a/contrib/sles10.1/init.d-collectd b/contrib/sles10.1/init.d-collectd
new file mode 100755 (executable)
index 0000000..edc415e
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides:                    collectd
+# Required-Start:              $local_fs $remote_fs $network 
+# X-UnitedLinux-Should-Start:  $named $time apache mysql
+# Required-Stop:               $local_fs $remote_fs $network
+# X-UnitedLinux-Should-Stop:   
+# Default-Start:               3 5
+# Default-Stop:                        0 1 2 6
+# Short-Description:           Statistics daemon collectd
+# Description:                 Start the statistics daemon collectd
+### END INIT INFO
+
+
+#
+# load the configuration
+#
+test -s /etc/rc.status && . /etc/rc.status && rc_reset
+
+RETVAL=0
+ARGS=""
+prog="collectd"
+CONFIG=/etc/collectd.conf
+
+if [ -r /etc/default/$prog ]; then
+       . /etc/default/$prog
+fi
+
+start () {
+       echo -n $"Starting $prog: "
+       RETVAL=1
+       if [ -r "$CONFIG" ]
+       then
+               eval startproc /usr/sbin/collectd -C "$CONFIG"
+               RETVAL=$?
+               [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog
+       fi
+       rc_failed $RETVAL
+       rc_status -v
+}
+stop () {
+       echo -n $"Stopping $prog: "
+       killproc $prog
+       RETVAL=$?
+       rc_failed $RETVAL
+       rc_status -v
+       [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog
+}
+# See how we were called.
+case "$1" in
+  start)
+       start
+       ;;
+  stop)
+       stop
+       ;;
+  status)
+       status $prog
+       ;;
+  restart|reload)
+       stop
+       sleep 1
+       start
+       ;;
+  condrestart)
+       [ -f /var/lock/subsys/$prog ] && restart || :
+       ;;
+  *)
+       echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
+       exit 1
+esac
+
+rc_exit
+# vim:syntax=sh
diff --git a/contrib/snmp-data.conf b/contrib/snmp-data.conf
new file mode 100644 (file)
index 0000000..07381db
--- /dev/null
@@ -0,0 +1,524 @@
+<Plugin snmp>
+    #
+    # IF-MIB
+    # Interface statistics using the IF-MIB
+    #
+    <Data "ifmib_if_octets32">
+       Type "if_octets"
+       Table true
+       Instance "IF-MIB::ifDescr"
+       Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
+    </Data>
+    <Data "ifmib_if_octets64">
+       Type "if_octets"
+       Table true
+       Instance "IF-MIB::ifName"
+       Values "IF-MIB::ifHCInOctets" "IF-MIB::ifHCOutOctets"
+    </Data>
+    <Data "ifmib_if_packets32">
+       Type "if_packets"
+       Table true
+       Instance "IF-MIB::ifDescr"
+       Values "IF-MIB::ifInUcastPkts" "IF-MIB::ifOutUcastPkts"
+    </Data>
+    <Data "ifmib_if_packets64">
+       Type "if_packets"
+       Table true
+       Instance "IF-MIB::ifName"
+       Values "IF-MIB::ifHCInUcastPkts" "IF-MIB::ifHCOutUcastPkts"
+    </Data>
+    <Data "ifmib_if_errors32">
+       Type "if_errors"
+       Table true
+       Instance "IF-MIB::ifDescr"
+       Values "IF-MIB::ifInErrors" "IF-MIB::ifOutErrors"
+    </Data>
+    <Data "ifmib_if_errors64">
+       Type "if_errors"
+       Table true
+       Instance "IF-MIB::ifName"
+       Values "IF-MIB::ifHCInErrors" "IF-MIB::ifHCOutErrors"
+    </Data>
+
+    #
+    # UPS-MIB
+    # Statistics about your UPS using the UPS-MIB from the RFC1628.
+    #
+    # Battery branch
+    <Data "upsmib_timeleft_battery">
+       Type "timeleft"
+       Table false
+       Instance "battery"
+       Values ".1.3.6.1.2.1.33.1.2.3.0"
+    </Data>
+    <Data "upsmib_charge_battery">
+       Type "percent"
+       Table false
+       Instance "charge-battery"
+       Values ".1.3.6.1.2.1.33.1.2.4.0"
+    </Data>
+    <Data "upsmib_voltage_battery">
+       Type "voltage"
+       Table false
+       Instance "battery"
+       Values ".1.3.6.1.2.1.33.1.2.5.0"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_current_battery">
+       Type "current"
+       Table false
+       Instance "battery"
+       Values ".1.3.6.1.2.1.33.1.2.6.0"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_temperature_battery">
+       Type "temperature"
+       Table false
+       Instance "battery"
+       Values ".1.3.6.1.2.1.33.1.2.7.0"
+    </Data>
+    # Input branch
+    <Data "upsmib_frequency_input">
+       Type "frequency"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.2.1.33.1.3.3.1.2"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_voltage_input">
+       Type "voltage"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.2.1.33.1.3.3.1.3"
+    </Data>
+    <Data "upsmib_current_input">
+       Type "current"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.2.1.33.1.3.3.1.4"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_power_input">
+       Type "power"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.2.1.33.1.3.3.1.5"
+    </Data>
+    # Output branch
+    <Data "upsmib_frequency_output">
+       Type "frequency"
+       Table false
+       Instance "output"
+       Values ".1.3.6.1.2.1.33.1.4.2.0"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_voltage_output">
+       Type "voltage"
+       Table true
+       InstancePrefix "output"
+       Values ".1.3.6.1.2.1.33.1.4.4.1.2"
+    </Data>
+    <Data "upsmib_current_output">
+       Type "current"
+       Table true
+       InstancePrefix "output"
+       Values ".1.3.6.1.2.1.33.1.4.4.1.3"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_power_output">
+       Type "power"
+       Table true
+       InstancePrefix "output"
+       Values ".1.3.6.1.2.1.33.1.4.4.1.4"
+    </Data>
+    <Data "upsmib_load_output">
+       Type "percent"
+       Table true
+       InstancePrefix "load-output"
+       Values ".1.3.6.1.2.1.33.1.4.4.1.5"
+    </Data>
+    # Bypass branch
+    <Data "upsmib_frequency_bypass">
+       Type "frequency"
+       Table false
+       Instance "output"
+       Values ".1.3.6.1.2.1.33.1.5.1.0"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_voltage_bypass">
+       Type "voltage"
+       Table true
+       InstancePrefix "bypass"
+       Values ".1.3.6.1.2.1.33.1.5.3.1.2"
+    </Data>
+    <Data "upsmib_current_bypass">
+       Type "current"
+       Table true
+       InstancePrefix "bypass"
+       Values ".1.3.6.1.2.1.33.1.5.3.1.3"
+       Scale 0.1
+    </Data>
+    <Data "upsmib_power_bypass">
+       Type "power"
+       Table true
+       InstancePrefix "bypass"
+       Values ".1.3.6.1.2.1.33.1.5.3.1.4"
+    </Data>
+    # Special definitions for broken UPSes
+    <Data "upsmib_voltage_battery_unscaled">
+       Type "voltage"
+       Table false
+       Instance "battery"
+       Values ".1.3.6.1.2.1.33.1.2.5.0"
+    </Data>
+    <Data "upsmib_current_input_unscaled">
+       Type "current"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.2.1.33.1.3.3.1.4"
+    </Data>
+    <Data "upsmib_current_output_unscaled">
+       Type "current"
+       Table true
+       InstancePrefix "output"
+       Values ".1.3.6.1.2.1.33.1.4.4.1.3"
+    </Data>
+
+    #
+    # Riello UPS
+    # Temperatures for UPSes by Riello, <http://www.riello-ups.de/>
+    #
+    <Data "riello_temperature_system">
+       Type "temperature"
+       Table false
+       Instance "system"
+       Values ".1.3.6.1.4.1.5491.1.51.1.5.4.0"
+    </Data>
+    <Data "riello_temperature_rectifier">
+       Type "temperature"
+       Table false
+       Instance "rectifier"
+       Values ".1.3.6.1.4.1.5491.1.51.1.5.5.0"
+    </Data>
+    <Data "riello_temperature_inverter">
+       Type "temperature"
+       Table false
+       Instance "inverter"
+       Values ".1.3.6.1.4.1.5491.1.51.1.5.6.0"
+    </Data>
+
+    #
+    # PowerPlus UPS, manufactured by Gamatronic, <http://www.gamatronic.com/>,
+    # distributed in Germany by AdPoS, <http://adpos-usv.de/>
+    #
+    # Global inputs
+    <Data "powerplus_voltage_input">
+       Type "voltage"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.4.1.6050.5.4.1.1.2"
+    </Data>
+    <Data "powerplus_current_input">
+       Type "current"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.4.1.6050.5.4.1.1.3"
+    </Data>
+    <Data "powerplus_power_apparent_input">
+       Type "power"
+       Table true
+       InstancePrefix "apparent-input"
+       Values ".1.3.6.1.4.1.6050.5.4.1.1.4"
+       Scale 100.0
+    </Data>
+    <Data "powerplus_power_active_input">
+       Type "power"
+       Table true
+       InstancePrefix "active-input"
+       Values ".1.3.6.1.4.1.6050.5.4.1.1.5"
+       Scale 100.0
+    </Data>
+    <Data "powerplus_performance_factor_input">
+       Type "percent"
+       Table true
+       InstancePrefix "performance_factor-input"
+       Values ".1.3.6.1.4.1.6050.5.4.1.1.6"
+    </Data>
+    # Global outputs
+    <Data "powerplus_voltage_output">
+       Type "voltage"
+       Table true
+       InstancePrefix "output"
+       Values ".1.3.6.1.4.1.6050.5.5.1.1.2"
+    </Data>
+    <Data "powerplus_current_output">
+       Type "current"
+       Table true
+       InstancePrefix "output"
+       Values ".1.3.6.1.4.1.6050.5.5.1.1.3"
+    </Data>
+    <Data "powerplus_power_apparent_output">
+       Type "power"
+       Table true
+       InstancePrefix "apparent-output"
+       Values ".1.3.6.1.4.1.6050.5.5.1.1.4"
+       Scale 100.0
+    </Data>
+    <Data "powerplus_power_active_output">
+       Type "power"
+       Table true
+       InstancePrefix "active-output"
+       Values ".1.3.6.1.4.1.6050.5.5.1.1.5"
+       Scale 100.0
+    </Data>
+    <Data "powerplus_load_level_output">
+       Type "percent"
+       Table true
+       InstancePrefix "load_level-output"
+       Values ".1.3.6.1.4.1.6050.5.5.1.1.6"
+    </Data>
+    <Data "powerplus_active_load_level_output">
+       Type "percent"
+       Table true
+       InstancePrefix "active_load_level-output"
+       Values ".1.3.6.1.4.1.6050.5.5.1.1.7"
+    </Data>
+    <Data "powerplus_performance_factor_output">
+       Type "percent"
+       Table true
+       InstancePrefix "performance_factor-output"
+       Values ".1.3.6.1.4.1.6050.5.5.1.1.8"
+    </Data>
+    # Global DC
+    <Data "powerplus_global_dc_positive">
+       Type "voltage"
+       Table false
+       Instance "dc_positive-global"
+       Values ".1.3.6.1.4.1.6050.5.6.1.0"
+    </Data>
+    <Data "powerplus_global_dc_negative">
+       Type "voltage"
+       Table false
+       Instance "dc_negative-global"
+       Values ".1.3.6.1.4.1.6050.5.6.2.0"
+    </Data>
+    <Data "powerplus_global_dc_total">
+       Type "voltage"
+       Table false
+       Instance "dc_total-global"
+       Values ".1.3.6.1.4.1.6050.5.6.3.0"
+    </Data>
+
+    #
+    # NetApp
+    # Some simple statistics of storage systems by NetApp.
+    #
+    <Data "netapp_cpu_system">
+       Type "cpu"
+       Table false
+       Instance "system"
+       Values ".1.3.6.1.4.1.789.1.2.1.2.0"
+    </Data>
+    <Data "netapp_cpu_idle">
+       Type "cpu"
+       Table false
+       Instance "idle"
+       Values ".1.3.6.1.4.1.789.1.2.1.4.0"
+    </Data>
+    <Data "netapp_if_octets">
+       Type "if_octets"
+       Table false
+       Instance "net"
+       Values ".1.3.6.1.4.1.789.1.2.2.12.0" ".1.3.6.1.4.1.789.1.2.2.14.0"
+    </Data>
+
+    #
+    # Juniper SSL
+    # Some stats of an SSL-appliance by Juniper.
+    #
+    <Data "juniperssl_users_web">
+       Type "users"
+       Table false
+       Instance "web"
+       Values ".1.3.6.1.4.1.12532.2.0"
+    </Data>
+    <Data "juniperssl_users_mail">
+       Type "users"
+       Table false
+       Instance "mail"
+       Values ".1.3.6.1.4.1.12532.3.0"
+    </Data>
+    <Data "juniperssl_percent_logfull">
+       Type "percent"
+       Table false
+       Instance "logfull"
+       Values ".1.3.6.1.4.1.12532.1.0"
+    </Data>
+    <Data "juniperssl_percent_diskfull">
+       Type "percent"
+       Table false
+       Instance "diskfull"
+       Values ".1.3.6.1.4.1.12532.25.0"
+    </Data>
+
+
+    #
+    # WuT
+    # Some thermometers and digital IO devices from WuT
+    # <http://www.wut.de/>
+    #
+    <Data "wut_an8graph">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.5040.1.2.6.3.2.1.1.2"
+       Values ".1.3.6.1.4.1.5040.1.2.6.1.4.1.1"
+       Scale 0.1
+    </Data>
+    <Data "wut_an2graph">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.5040.1.2.7.3.2.1.1.2"
+       Values ".1.3.6.1.4.1.5040.1.2.7.1.4.1.1"
+       Scale 0.1
+    </Data>
+    <Data "wut_an1graph">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.5040.1.2.8.3.2.1.1.2"
+       Values ".1.3.6.1.4.1.5040.1.2.8.1.4.1.1"
+       Scale 0.1
+    </Data>
+    <Data "wut_thermo8">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.5040.1.2.1.3.2.1.1.2"
+       Values ".1.3.6.1.4.1.5040.1.2.1.1.4.1.1"
+       Scale 0.1
+    </Data>
+    <Data "wut_thermo2">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.5040.1.2.2.3.2.1.1.2"
+       Values ".1.3.6.1.4.1.5040.1.2.2.1.4.1.1"
+       Scale 0.1
+    </Data>
+    <Data "wut_thermo1">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.5040.1.2.3.3.2.1.1.2"
+       Values ".1.3.6.1.4.1.5040.1.2.3.1.4.1.1"
+       Scale 0.1
+    </Data>
+
+    #
+    # Infratec
+    # Rack monitoring devices by Infratec, <http://www.infratec-ag.de/>
+    #
+    # Model H2-17
+    <Data "infratec_h2_17_temperature">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.4519.10.4.1.1.2"
+       Values ".1.3.6.1.4.1.4519.10.4.1.1.3"
+    </Data>
+    <Data "infratec_h2_17_humidity">
+       Type "humidity"
+       Table true
+       Instance ".1.3.6.1.4.1.4519.10.5.1.1.2"
+       Values ".1.3.6.1.4.1.4519.10.5.1.1.3"
+    </Data>
+    <Data "infratec_h2_17_voltage">
+       Type "voltage"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.4.1.4519.10.6.1.1.3"
+    </Data>
+    # Model H2-30
+    <Data "infratec_h2_30_temperature">
+       Type "temperature"
+       Table true
+       Instance ".1.3.6.1.4.1.1909.10.4.1.1.2"
+       Values ".1.3.6.1.4.1.1909.10.4.1.1.3"
+    </Data>
+    <Data "infratec_h2_30_humidity">
+       Type "humidity"
+       Table true
+       Instance ".1.3.6.1.4.1.1909.10.5.1.1.2"
+       Values ".1.3.6.1.4.1.1909.10.5.1.1.3"
+    </Data>
+    <Data "infratec_h2_30_voltage">
+       Type "voltage"
+       Table true
+       InstancePrefix "input"
+       Values ".1.3.6.1.4.1.1909.10.6.1.1.3"
+    </Data>
+
+    #
+    # Mikrotik RouterBoards
+    #
+    # Wireless statistics: station mode
+    <Data "mikrotik_wl_sta_bitrate_tx">
+        tYPE "Bitrate"
+        Table true
+        InstancePrefix "st-tx-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.1.1.5"
+        Values ".1.3.6.1.4.1.14988.1.1.1.1.1.2"
+    </Data>
+
+    <Data "mikrotik_wl_sta_bitrate_rx">
+        Type "bitrate"
+        Table true
+        InstancePrefix "st-rx-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.1.1.5"
+        Values ".1.3.6.1.4.1.14988.1.1.1.1.1.3"
+    </Data>
+
+    <Data "mikrotik_wl_sta_signal">
+        Type "signal_power"
+        Table true
+        InstancePrefix "st-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.1.1.5"
+        Values ".1.3.6.1.4.1.14988.1.1.1.1.1.4"
+    </Data>
+
+    # Wireless statistics: AP mode / registration table
+    <Data "mikrotik_wl_reg_signal">
+        Type "signal_power"
+        Table true
+        InstancePrefix "ap-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.2.1.1"
+        Values ".1.3.6.1.4.1.14988.1.1.1.2.1.3"
+    </Data>
+
+    <Data "mikrotik_wl_reg_octets">
+        Type "if_octets"
+        Table true
+        InstancePrefix "ap-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.2.1.1"
+        Values ".1.3.6.1.4.1.14988.1.1.1.2.1.5" ".1.3.6.1.4.1.14988.1.1.1.2.1.4"
+    </Data>
+
+    <Data "mikrotik_wl_reg_packets">
+        Type "if_packets"
+        Table true
+        InstancePrefix "ap-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.2.1.1"
+        Values ".1.3.6.1.4.1.14988.1.1.1.2.1.7" ".1.3.6.1.4.1.14988.1.1.1.2.1.6"
+    </Data>
+
+    <Data "mikrotik_wl_reg_bitrate_tx">
+        Type "bitrate"
+        Table true
+        InstancePrefix "ap-tx-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.2.1.1"
+        Values ".1.3.6.1.4.1.14988.1.1.1.2.1.8"
+    </Data>
+
+    <Data "mikrotik_wl_reg_bitrate_rx">
+        Type "bitrate"
+        Table true
+        InstancePrefix "ap-rx-"
+        Instance ".1.3.6.1.4.1.14988.1.1.1.2.1.1"
+        Values ".1.3.6.1.4.1.14988.1.1.1.2.1.9"
+    </Data>
+</Plugin>
diff --git a/contrib/snmp-probe-host.px b/contrib/snmp-probe-host.px
new file mode 100755 (executable)
index 0000000..d1a7a88
--- /dev/null
@@ -0,0 +1,439 @@
+#!/usr/bin/perl
+#
+# collectd - snmp-probe-host.px
+# Copyright (C) 2008,2009  Florian octo Forster
+# Copyright (C) 2009       noris network AG
+#
+# 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 noris.net>
+#
+
+use strict;
+use warnings;
+use SNMP;
+use Config::General ('ParseConfig');
+use Getopt::Long ('GetOptions');
+use Socket6;
+
+our %ExcludeOptions =
+(
+  'IF-MIB64' => qr/^\.?1\.3\.6\.1\.2\.1\.31/,
+  'IF-MIB32' => qr/^\.?1\.3\.6\.1\.2\.1\.2/
+);
+
+sub get_config
+{
+  my %conf;
+  my $file = shift;
+
+  %conf = ParseConfig (-ConfigFile => $file,
+    -LowerCaseNames => 1,
+    -UseApacheInclude => 1,
+    -IncludeDirectories => 1,
+    ($Config::General::VERSION >= 2.38) ? (-IncludeAgain => 0) : (),
+    -MergeDuplicateBlocks => 1,
+    -CComments => 0);
+  if (!%conf)
+  {
+    return;
+  }
+  return (\%conf);
+} # get_config
+
+sub probe_one
+{
+  my $sess = shift;
+  my $conf = shift;
+  my $excludes = @_ ? shift : [];
+  my @oids;
+  my $cmd = 'GET';
+  my $vl;
+
+  if (!$conf->{'table'} || !$conf->{'values'})
+  {
+    warn "No 'table' or 'values' setting";
+    return;
+  }
+
+  @oids = split (/"\s*"/, $conf->{'values'});
+  if ($conf->{'table'} =~ m/^(true|yes|on)$/i)
+  {
+    $cmd = 'GETNEXT';
+    if (defined ($conf->{'instance'}))
+    {
+      push (@oids, $conf->{'instance'});
+    }
+  }
+
+  require Data::Dumper;
+
+  #print "probe_one: \@oids = (" . join (', ', @oids) . ");\n";
+  for (@oids)
+  {
+    my $oid_orig = $_;
+    my $vb;
+    my $status;
+
+    if ($oid_orig =~ m/[^0-9\.]/)
+    {
+      my $tmp = SNMP::translateObj ($oid_orig);
+      if (!defined ($tmp))
+      {
+        warn ("Cannot translate OID $oid_orig");
+        return;
+      }
+      $oid_orig = $tmp;
+    }
+
+    for (@$excludes)
+    {
+      if ($oid_orig =~ $_)
+      {
+        return;
+      }
+    }
+
+    $vb = SNMP::Varbind->new ([$oid_orig]);
+
+    if ($cmd eq 'GET')
+    {
+      $status = $sess->get ($vb);
+      if ($sess->{'ErrorNum'} != 0)
+      {
+        return;
+      }
+      if (!defined ($status))
+      {
+        return;
+      }
+      if ("$status" eq 'NOSUCHOBJECT')
+      {
+        return;
+      }
+    }
+    else
+    {
+      my $oid_copy;
+
+      $status = $sess->getnext ($vb);
+      if ($sess->{'ErrorNum'} != 0)
+      {
+        return;
+      }
+
+      $oid_copy = $vb->[0];
+      if ($oid_copy =~ m/[^0-9\.]/)
+      {
+        my $tmp = SNMP::translateObj ($oid_copy);
+        if (!defined ($tmp))
+        {
+          warn ("Cannot translate OID $oid_copy");
+          return;
+        }
+        $oid_copy = $tmp;
+      }
+
+      #print "$oid_orig > $oid_copy ?\n";
+      if (substr ($oid_copy, 0, length ($oid_orig)) ne $oid_orig)
+      {
+        return;
+      }
+    }
+
+    #print STDOUT Data::Dumper->Dump ([$oid_orig, $status], [qw(oid_orig status)]);
+  } # for (@oids)
+
+  return (1);
+} # probe_one
+
+sub probe_all
+{
+  my $host = shift;
+  my $community = shift;
+  my $data = shift;
+  my $excludes = @_ ? shift : [];
+  my $version = 2;
+  my @valid_data = ();
+  my $begin;
+  my $address;
+
+  {
+    my @status;
+
+    @status = getaddrinfo ($host, 'snmp');
+    while (@status >= 5)
+    {
+      my $family    = shift (@status);
+      my $socktype  = shift (@status);
+      my $proto     = shift (@status);
+      my $saddr     = shift (@status);
+      my $canonname = shift (@status);
+      my $host;
+      my $port;
+
+      ($host, $port) = getnameinfo ($saddr, NI_NUMERICHOST);
+      if (defined ($port))
+      {
+        $address = $host;
+      }
+      else
+      {
+        warn ("getnameinfo failed: $host");
+      }
+    }
+  }
+  if (!$address)
+  {
+    return;
+  }
+
+  while ($version > 0)
+  {
+    my $sess;
+
+    $sess = new SNMP::Session (DestHost => $host,
+      Community => $community,
+      Version => $version,
+      Timeout => 1000000,
+      UseNumeric => 1);
+    if (!$sess)
+    {
+      $version--;
+      next;
+    }
+
+    $begin = time ();
+
+    for (keys %$data)
+    {
+      my $name = $_;
+      if (probe_one ($sess, $data->{$name}, $excludes))
+      {
+        push (@valid_data, $name);
+      }
+
+      if ((@valid_data == 0) && ((time () - $begin) > 10))
+      {
+        # break for loop
+        last;
+      }
+    }
+
+    if (@valid_data)
+    {
+      # break while loop
+      last;
+    }
+
+    $version--;
+  } # while ($version > 0)
+
+  print <<EOF;
+  <Host "$host">
+    Address "$address"
+    Version $version
+    Community "$community"
+EOF
+  for (sort (@valid_data))
+  {
+    print "    Collect \"$_\"\n";
+  }
+  if (!@valid_data)
+  {
+    print <<EOF;
+# WARNING: Autoconfiguration failed.
+# TODO: Add one or more `Collect' statements here:
+#   Collect "foo"
+EOF
+  }
+  print <<EOF;
+    Interval 60
+  </Host>
+EOF
+} # probe_all
+
+sub exit_usage
+{
+  print <<USAGE;
+Usage: snmp-probe-host.px --host <host> [options]
+
+Options are:
+  -H | --host          Hostname of the device to probe.
+  -C | --config        Path to config file holding the SNMP data blocks.
+  -c | --community     SNMP community to use. Default: `public'.
+  -h | --help          Print this information and exit.
+  -x | --exclude       Exclude a specific MIB. Call with "help" for more
+                       information.
+
+USAGE
+  exit (1);
+}
+
+sub exit_usage_exclude
+{
+  print "Available exclude MIBs:\n\n";
+  for (sort (keys %ExcludeOptions))
+  {
+    print "  $_\n";
+  }
+  print "\n";
+  exit (1);
+}
+
+=head1 NAME
+
+snmp-probe-host.px - Find out what information an SNMP device provides.
+
+=head1 SYNOPSIS
+
+  ./snmp-probe-host.px --host switch01.mycompany.com --community ei2Acoum
+
+=head1 DESCRIPTION
+
+The C<snmp-probe-host.px> script can be used to automatically generate SNMP
+configuration snippets for collectd's snmp plugin (see L<collectd-snmp(5)>).
+
+This script parses the collectd configuration and detecs all "data" blocks that
+are defined for the SNMP plugin. It then queries the device specified on the
+command line for all OIDs and registeres which OIDs could be answered correctly
+and which resulted in an error. With that information the script figures out
+which "data" blocks can be used with this hosts and prints an appropriate
+"host" block to standard output.
+
+The script first tries to contact the device via SNMPv2. If after ten seconds
+no working "data" block has been found, it will try to downgrade to SNMPv1.
+This is a bit a hack, but works for now.
+
+=cut
+
+my $host;
+my $file = '/etc/collectd/collectd.conf';
+my $community = 'public';
+my $conf;
+my $working_data;
+my @excludes = ();
+
+=head1 OPTIONS
+
+The following command line options are accepted:
+
+=over 4
+
+=item B<--host> I<hostname>
+
+Hostname of the device. This B<should> be a fully qualified domain name (FQDN),
+but anything the system can resolve to an IP address will word. B<Required
+argument>.
+
+=item B<--config> I<config file>
+
+Sets the name of the collectd config file which defined the SNMP "data" blocks.
+Due to limitations of the config parser used in this script
+(C<Config::General>), C<Include> statements cannot be parsed correctly.
+Defaults to F</etc/collectd/collectd.conf>.
+
+=item B<--community> I<community>
+
+SNMP community to use. Should be pretty straight forward.
+
+=item B<--exclude> I<MIB>
+
+This option can be used to exclude specific data from being enabled in the
+generated config. Currently the following MIBs are understood:
+
+=over 4
+
+=item B<IF-MIB>
+
+Exclude interface information, such as I<ifOctets> and I<ifPackets>.
+
+=back
+
+=back
+
+=cut
+
+GetOptions ('H|host|hostname=s' => \$host,
+  'C|conf|config=s' => \$file,
+  'c|community=s' => \$community,
+  'x|exclude=s' => \@excludes,
+  'h|help' => \&exit_usage) or die;
+
+if (!$host)
+{
+  print STDERR "No hostname given. Please use `--host'.\n";
+  exit (1);
+}
+
+if (@excludes)
+{
+  my $tmp = join (',', @excludes);
+  my @tmp = split (/\s*,\s*/, $tmp);
+
+  @excludes = ();
+  for (@tmp)
+  {
+    my $mib = uc ($_);
+    if ($mib eq 'HELP')
+    {
+      exit_usage_exclude ();
+    }
+    elsif (!exists ($ExcludeOptions{$mib}))
+    {
+      print STDERR "No such MIB: $mib\n";
+      exit_usage_exclude ();
+    }
+    push (@excludes, $ExcludeOptions{$mib});
+  }
+}
+
+$conf = get_config ($file) or die ("Cannot read config");
+
+if (!defined ($conf->{'plugin'})
+  || !defined ($conf->{'plugin'}{'snmp'})
+  || !defined ($conf->{'plugin'}{'snmp'}{'data'}))
+{
+  print STDERR "Error: No <plugin>, <snmp>, or <data> block found.\n";
+  exit (1);
+}
+
+probe_all ($host, $community, $conf->{'plugin'}{'snmp'}{'data'}, \@excludes);
+
+exit (0);
+
+=head1 BUGS
+
+=over 4
+
+=item
+
+C<Include> statements in the config file are not handled correctly.
+
+=item
+
+SNMPv2 / SNMPv1 detection is a hack.
+
+=back
+
+=head1 AUTHOR
+
+Copyright (c) 2008 by Florian octo Forster
+E<lt>octoE<nbsp>atE<nbsp>noris.netE<gt>. Licensed under the terms of the GPLv2.
+Written for the norisE<nbsp>networkE<nbsp>AG L<http://noris.net/>.
+
+=cut
+
+# vim: set sw=2 sts=2 ts=8 et :
diff --git a/contrib/solaris-smf/README b/contrib/solaris-smf/README
new file mode 100644 (file)
index 0000000..dfd990b
--- /dev/null
@@ -0,0 +1,331 @@
+SMF is the way Solaris 10 and later preferably manages services. It is intended
+to replace the old init.d process and provides advances features, such as
+automatic restarting of failing services.
+
+The following blog entry by Piotr Hosowicz describes the process in more
+detail. The original entry can be found at
+<http://phosowicz.jogger.pl/2008/12/21/smf-izing-collectd/>.
+
+The files in this directory are:
+
+  README          This file
+  collectd        Start / stop script
+  collectd.xml    SMF manifest for collectd.
+
+------------------------------------------------------------------------
+
+      SMF-izing collectd <#>
+
+Wpis na 0. poziomie, wysłany 21 grudnia 2008 o 16:30:49.
+
+My two previous blog entries were about building and running collectd
+<http://collectd.org/> on Sun Solaris 10. After the first one Octo
+contacted me and was so kind as to release a packaged version for x86_64
+<http://collectd.org/download.shtml#solaris>. I have put aside the build
+I rolled on my own and decided to install and run the packaged one on
+the production servers. This blog entry is about SMF-izing the collectd
+daemon.
+
+A few words about the SMF – the Solaris'es Service Management Facility.
+I think it appeared in Solaris 10. From then on the good old |/etc/rcN.d
+|| /etc/init.d| services are called /legacy services/. They still can be
+run, but are not fully supported by SMF. SMF enables you to start and
+stop services in the unified way, can direct you to man pages in case a
+service enters maintenance mode, resolves dependencies between services,
+can store properties of services and so on. A nice feature is that SMF
+will take care of restarting services in case they terminate
+unexpectedly, we will use it at the end to check that things are working
+as they should.
+
+The 3V|L thing about SMF is that each service needs so called SMF
+manifest written in XML and a script or scripts that are executed, when
+the service needs to be stopped or started. It can be one script, which
+should accept respective parameters. Even more 3V|L is the fact that the
+manifest is imported into the SMF database and kept there in SQLite format.
+
+Below you will find collectd manifest and the script. I will post them
+to collectd mailing list in matter of minutes with this blog entry
+serving as a README. Please read all down to the bottom, including the
+remarks.
+
+Manifest (based on the work of Kangurek, thanks!), see the "collectd.xml"
+file:
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<service_bundle type='manifest' name='collectd'>
+<service
+        name='application/collectd'
+        type='service'
+        version='1'>
+       <create_default_instance enabled='true' />
+       <single_instance/>
+        <dependency
+                name='network'
+                grouping='require_all'
+                restart_on='none'
+                type='service'>
+                <service_fmri value='svc:/milestone/network:default' />
+        </dependency> 
+        <dependency
+                name='filesystem-local'
+                grouping='require_all'
+                restart_on='none'
+                type='service'>
+                <service_fmri value='svc:/system/filesystem/local:default' />
+        </dependency> 
+        <exec_method
+                type='method'
+                name='start'
+                exec='/lib/svc/method/collectd start'
+                timeout_seconds='60'>
+           <method_context>
+               <method_credential user='root' group='root' />
+           </method_context>
+       </exec_method>
+        <exec_method
+                type='method'
+                name='stop'
+                exec='/lib/svc/method/collectd stop'
+                timeout_seconds='60'>
+           <method_context>
+               <method_credential user='root' group='root' />
+           </method_context>
+       </exec_method>
+        <stability value='Evolving' />
+</service>
+</service_bundle>
+
+Script, see the "collectd" file:
+
+#!/sbin/sh
+PIDFILE=/opt/collectd/var/run/collectd.pid
+DAEMON=/opt/collectd/sbin/collectd
+. /lib/svc/share/smf_include.sh
+case "$1" in
+  start)
+    if [ -f $PIDFILE ] ; then
+      echo "Already running. Stale PID file?"
+      PID=`cat $PIDFILE`
+      echo "$PIDFILE contains $PID"
+      ps -p $PID
+      exit $SMF_EXIT_ERR_FATAL
+    fi
+    $DAEMON
+    if [ $? -ne 0 ] ; then
+      echo $DAEMON faild to start
+      exit $SMF_EXIT_ERR_FATAL
+    fi
+  ;;
+  stop)
+    PID=`cat $PIDFILE 2>/dev/null`
+    kill -15 $PID 2>/dev/null
+    pwait $PID 1> /dev/null 2>/dev/null
+  ;;
+  restart)
+    $0 stop
+    $0 start
+  ;;
+  status)
+    ps -ef | grep collectd | grep -v status | grep -v grep
+  ;;
+  *)
+    echo "Usage: $0 [ start | stop | restart | status ]"
+    exit 1
+  ;;
+esac
+exit $SMF_EXIT_OK
+
+So you have two files: |collectd| script and |collectd.xml| manifest.
+What do you do with these files?
+
+First – before you begin – make sure that collectd is not running, close
+it down. My script above assumes that you are using the default place
+for PID file. Second: remove / move away collectd's |/etc/rcN.d| and
+|/etc/init.d| stuff, you won't need it from now on, because collectd
+will be SMF-ized. Tada!
+
+Next – install the script in place. It took me a minute or two to figure
+out why Solaris'es |install| tool does not work as expected. It turned
+out that the switches and parameters must be in exactly same order as in
+man page, especially the -c parameter must be first:
+
+|# install -c /lib/svc/method/ -m 755 -u root -g bin collectd|
+
+Now is the moment to test once again that the script is working OK. Try
+running:
+
+|# /lib/svc/method/collectd start
+# /lib/svc/method/collectd stop
+# /lib/svc/method/collectd restart
+|
+
+|pgrep| and |kill| are your friends here, also collectd logs. At last
+stop the collectd service and continue.
+
+Now is the time to /slurp/ attached XML manifest into the SMF database.
+This is done using the |svccfg| tool. Transcript follows:
+
+|# svccfg
+svc:> validate collectd.xml
+svc:> import collectd.xml
+svc:>
+|
+
+It is good to run |validate| command first, especially if you copied and
+pasted the XML manifest from this HTML document opened in your
+browser!!! Second thing worth noting is that |svccfg| starts the service
+immediately upon importing the manifest. It might be not what you want.
+For example it will start collecting data on remote collectd server if
+you use network plugin and it will do it under the hostname, that is not
+right. So be sure to configure collectd prior to running it from SMF.
+
+Now a few words about SMF tools. To see the state of all services issue
+|svcs -a| command. To see state of collectd service issue |svcs
+collectd| command. Quite normal states are enabled and disabled. If you
+see maintenance state then something is wrong. Be sure that you stopped
+all non-SMF collectd processes before you follow the procedure described
+here. To stop collectd the SMF way issue the |svcadm disable
+collectd|command. To start collectd the SMF way issue the |svcadm enable
+collectd|command. Be aware that setting it this way makes the change
+persistent across OS reboots, if you want to enable / disable the
+service only temporarily then add |-t| switch after the |enable| /
+|disable| keywords.
+
+And now is time for a grand finale – seeing if SMF can take care of
+collectd in case it crashes. See PID of collectd either using |pgrep| or
+seeing the contents of the PID file and kill it using |kill|. Then check
+with |svcs collectd| command that SMF has restarted collectd soon
+afterwards. You should see that the service is once again enabled in the
+first column, without your intervention.
+
+Things that could or should be clarified:
+
+    * How hard is it to correct mistakes in manifests? Does svccfg just
+      overwrite entries for specified service FMRI or does it require to
+      delete bad entry (and how to do it?!) and import the correct one?
+    * How does SMF know that a service has crashed / terminated? I
+      attended Sun's trainings and the trainer didn't know how to
+      explain this, we formed a hypothesis that it watches new PIDs
+      after starting a service or something like that. I think it is a
+      bad hypothesis, because SMF can watch PID for the startup script
+      itself but I think not the processes launched inside the script. I
+      have a slight idea that it is done based on so called contracts.
+
+------------------------------------------------------------------------
+
+
+        Komentarze do notki “SMF-izing collectd” <#comments>
+
+
+        Zostaw odpowiedź
+
+Nick
+
+------------------------------------------------------------------------
+
+
+    Archiwum
+
+    * Grudzień 2008 (5) </2008/12/>
+    * Październik 2008 (4) </2008/10/>
+    * Wrzesień 2008 (7) </2008/09/>
+    * Sierpień 2008 (5) </2008/08/>
+    * Lipiec 2008 (12) </2008/07/>
+    * Czerwiec 2008 (11) </2008/06/>
+    * Maj 2008 (3) </2008/05/>
+    * Kwiecień 2008 (10) </2008/04/>
+    * Marzec 2008 (3) </2008/03/>
+    * Luty 2008 (1) </2008/02/>
+    * Styczeń 2008 (1) </2008/01/>
+    * Listopad 2007 (4) </2007/11/>
+    * Październik 2007 (6) </2007/10/>
+    * Wrzesień 2007 (10) </2007/09/>
+    * Sierpień 2007 (3) </2007/08/>
+    * Lipiec 2007 (8) </2007/07/>
+    * Czerwiec 2007 (10) </2007/06/>
+    * Maj 2007 (12) </2007/05/>
+    * Kwiecień 2007 (17) </2007/04/>
+
+
+    Kategorie
+
+    * Film (8) <http://phosowicz.jogger.pl/kategoria/film/>
+    * Książki (35) <http://phosowicz.jogger.pl/kategoria/ksiazki/>
+    * Muzyka (15) <http://phosowicz.jogger.pl/kategoria/muzyka/>
+    * Ogólne (20) <http://phosowicz.jogger.pl/kategoria/ogolne/>
+    * Polityka (59) <http://phosowicz.jogger.pl/kategoria/polityka/>
+    * Sprzedam (5) <http://phosowicz.jogger.pl/kategoria/sprzedam/>
+    * Techblog (20) <http://phosowicz.jogger.pl/kategoria/techblog/>
+    * Technikalia (34) <http://phosowicz.jogger.pl/kategoria/technikalia/>
+    * Wystawy (3) <http://phosowicz.jogger.pl/kategoria/wystawy/>
+
+
+    Czytuję
+
+    * ArsTechnica.com <http://arstechnica.com/>
+    * Fund. Orientacja <http://www.abcnet.com.pl/>
+    * Techblog Jogger'a <http://techblog.pl/>
+    * The Register <http://www.theregister.co.uk/>
+
+
+    Inne blogi
+
+    * Bloody.Users <http://bloody.users.jogger.pl/>
+    * Dandys <http://dandys.jogger.pl/>
+    * Derin <http://derin.jogger.pl>
+    * Kefir87 <http://kefir87.jogger.pl/>
+    * Klisu <http://klisu.jogger.pl/>
+    * Kwantowe Krajobrazy <http://kwantowekrajobrazy.jogger.pl/>
+    * Paczor <http://paczor.fubar.pl/>
+    * Prestidigitator <http://prestidigitator.jogger.pl>
+    * Remiq <http://remiq.jogger.pl>
+    * Torero <http://torero.jogger.pl/>
+    * Zdzichubg <http://zdzichubg.jogger.pl/>
+
+
+    Inne moje strony
+
+    * www.delphi.org.pl <http://www.delphi.org.pl>
+    * www.hosowicz.com <http://www.hosowicz.com>
+
+
+    Pajacyk.pl
+
+    * Nakarm dzieci! <http://pajacyk.pl/>
+
+
+    Meta
+
+    * Panel administracyjny <https://login.jogger.pl/>
+
+
+------------------------------------------------------------------------
+
+phosowicz is powered by Jogger <http://jogger.pl> and K2
+<http://binarybonsai.com/k2/> by Michael <http://binarybonsai.com> and
+Chris <http://chrisjdavis.org>, ported by Patryk Zawadzki.
+<http://patrys.jogger.pl/>
+Notki w RSS <http://phosowicz.jogger.pl/rss/content/html/20>
+
diff --git a/contrib/solaris-smf/collectd b/contrib/solaris-smf/collectd
new file mode 100755 (executable)
index 0000000..5ffdb24
--- /dev/null
@@ -0,0 +1,42 @@
+#!/sbin/sh
+
+PIDFILE=/opt/collectd/var/run/collectd.pid
+DAEMON=/opt/collectd/sbin/collectd
+
+. /lib/svc/share/smf_include.sh
+
+case "$1" in
+  start)
+    if [ -f $PIDFILE ] ; then
+      echo "Already running. Stale PID file?"
+      PID=`cat $PIDFILE`
+      echo "$PIDFILE contains $PID"
+      ps -p $PID
+      exit $SMF_EXIT_ERR_FATAL
+    fi
+    $DAEMON
+    if [ $? -ne 0 ] ; then
+      echo $DAEMON faild to start
+      exit $SMF_EXIT_ERR_FATAL
+    fi
+  ;;
+  stop)
+    PID=`cat $PIDFILE 2>/dev/null`
+    kill -15 $PID 2>/dev/null
+    pwait $PID 1> /dev/null 2>/dev/null
+  ;;
+  restart)
+    $0 stop
+    $0 start
+  ;;
+  status)
+    ps -ef | grep collectd | grep -v status | grep -v grep
+  ;;
+  *)
+    echo "Usage: $0 [ start | stop | restart | status ]"
+    exit 1
+  ;;
+esac
+
+
+exit $SMF_EXIT_OK
diff --git a/contrib/solaris-smf/collectd.xml b/contrib/solaris-smf/collectd.xml
new file mode 100644 (file)
index 0000000..d1ae3a4
--- /dev/null
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+
+<service_bundle type='manifest' name='collectd'>
+<service
+        name='application/collectd'
+        type='service'
+        version='1'>
+
+       <create_default_instance enabled='true' />
+       
+       <single_instance/>
+
+        <dependency
+                name='network'
+                grouping='require_all'
+                restart_on='none'
+                type='service'>
+                <service_fmri value='svc:/milestone/network:default' />
+        </dependency> 
+
+        <dependency
+                name='filesystem-local'
+                grouping='require_all'
+                restart_on='none'
+                type='service'>
+                <service_fmri value='svc:/system/filesystem/local:default' />
+        </dependency> 
+
+        <exec_method
+                type='method'
+                name='start'
+                exec='/lib/svc/method/collectd start'
+                timeout_seconds='60'>
+           <method_context>
+               <method_credential user='root' group='root' />
+           </method_context>
+       </exec_method>
+
+
+        <exec_method
+                type='method'
+                name='stop'
+                exec='/lib/svc/method/collectd stop'
+                timeout_seconds='60'>
+           <method_context>
+               <method_credential user='root' group='root' />
+           </method_context>
+       </exec_method>
+
+        <stability value='Evolving' />
+
+</service>
+
+</service_bundle>
+
diff --git a/contrib/systemd.collectd.service b/contrib/systemd.collectd.service
new file mode 100644 (file)
index 0000000..b046192
--- /dev/null
@@ -0,0 +1,23 @@
+[Unit]
+Description=Collectd
+After=local-fs.target network.target
+Requires=local-fs.target network.target
+
+[Service]
+ExecStart=/usr/sbin/collectd
+
+# Tell systemd it will receive a notification from collectd over it's control
+# socket once the daemon is ready. See systemd.service(5) for more details.
+Type=notify
+NotifyAccess=main
+
+# Restart the collectd daemon after a 10 seconds delay, in case it crashes.
+Restart=always
+RestartSec=10
+
+# Send all console messages to syslog.
+StandardOutput=syslog
+StandardError=syslog
+
+[Install]
+WantedBy=multi-user.target
diff --git a/contrib/upstart.collectd.conf b/contrib/upstart.collectd.conf
new file mode 100644 (file)
index 0000000..f833edf
--- /dev/null
@@ -0,0 +1,51 @@
+description "start/stop/control collectd"
+# http://collectd.org/
+# Upstart is the replacement init system used in Debian, Ubuntu,
+# and in Fedora. Refer to http://upstart.ubuntu.com/cookbook/
+#
+# Normally this file will live as `/etc/init/collectd.conf`
+
+usage "initctl <start|stop> collectd"
+author "Dave Cottlehuber <dch@jsonified.com>"
+version "1.1"
+
+# There are a number of alternative start sequences however
+# most of those do not work on all Ubuntu flavours and releases.
+start on started networking and filesystem
+stop on runlevel [!2345]
+
+# collectd itself will run with reduced privileges, but not
+# all plugins will. Test and edit as required.
+# An alternative configuration is as a user script in ~/.init/ however
+# these cannot be started at boot time by the system without
+# arcane trickery. Also a root user will not see these tasks/jobs
+# by default. set*id is a reasonable and secure compromise.
+# These options are not supported on early upstart versions.
+#setuid nobody
+#setgid nobody
+
+# Other parameters such as the path to the configuration file
+# will have been compiled into the binary. These are trivially
+# added as environment variables below, and then into both
+# `pre-start` command check before collectd runs, and subsequent
+# `exec` command parameters below. Remember that upstart runs all
+# shell commands via `sh -e`.
+env DAEMON=/usr/sbin/collectd
+
+# Tell upstart to wait for collectd to SIGSTOP itself, signaling it is ready
+# to run. Warning: this only works with collectd 5.5 and newer. You'll have to
+# use "expect fork" instead, if using collectd 5.4 and older.
+expect stop
+
+# prevent thrashing - 10 restarts in 5 seconds
+respawn
+respawn limit 10 5
+
+# Uncomment to make a log available in /var/log/upstart/collectd.log
+# (not supported on early upstart versions).
+#console log
+
+# The daemon will not start if the configuration is invalid.
+pre-start exec $DAEMON -t
+# Let's start!
+exec $DAEMON
diff --git a/contrib/wiki2changelog.pl b/contrib/wiki2changelog.pl
new file mode 100755 (executable)
index 0000000..b8fc965
--- /dev/null
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+=head1 NAME
+
+wiki2changelog.pl
+
+=head1 DESCRIPTION
+
+This script takes the change log from one of the "Version x.y" pages in
+collectd's wiki and converts it to the format used by the "ChangeLog" file.
+This is usually done as part of the release process.
+
+=cut
+
+our $TextWidth = 80;
+
+sub format_entry
+{
+       my $in = shift;
+       my $out = '';
+
+       my $line = "\t*";
+       my $line_len = 9;
+
+       for (split (' ', $in)) {
+               my $word = $_;
+               my $word_len = 1 + length $word;
+
+               if (($line_len + $word_len) > $TextWidth) {
+                       $out .= "$line\n";
+                       $line = "\t ";
+                       $line_len = 9;
+               }
+
+               $line .= " $word";
+               $line_len += $word_len;
+       }
+
+       if ($line_len != 9) {
+               $out .= "$line\n";
+       }
+
+       return $out;
+}
+
+while (<>)
+{
+       chomp;
+       my $line = $_;
+
+       if ($line =~ m#^\* (.*)#) {
+               $line = $1;
+       } else {
+               next;
+       }
+
+       $line =~ s#&lt;#<#g;
+       $line =~ s#&gt;#>#g;
+       $line =~ s#&nbsp;# #g;
+       $line =~ s#&quot;#"#g;
+
+       $line =~ s#\{\{Plugin\|([^}]+)\}\}#$1 plugin#g;
+       $line =~ s@\{\{Issue\|([^}]+)\}\}@#$1@g;
+       $line =~ s#\[\[[^|]+\|([^\]]+)\]\]#$1#g;
+       $line =~ s#\[\[([^|]+)\]\]#$1#g;
+
+       $line =~ s#'''(.*?)'''#*$1*#g;
+       $line =~ s#''(.*?)''#$1#g;
+       $line =~ s#<code>(.*?)</code>#"$1"#gi;
+
+       print format_entry($line);
+}
diff --git a/depcomp b/depcomp
new file mode 100755 (executable)
index 0000000..df8eea7
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,630 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
+# Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by `PROGRAMS ARGS'.
+  object      Object file output by `PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputing dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+   # This is just like msvisualcpp but w/o cygpath translation.
+   # Just convert the backslash-escaped backslashes to single forward
+   # slashes to satisfy depend.m4
+   cygpath_u="sed s,\\\\\\\\,/,g"
+   depmode=msvisualcpp
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> "$depfile"
+    echo >> "$depfile"
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+    # That's a tab and a space in the [].
+    sed -e 's,^.*\.[a-z]*:[     ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add `dependent.h:' lines.
+    sed -ne '2,${
+              s/^ *//
+              s/ \\*$//
+              s/$/:/
+              p
+            }' "$tmpdepfile" >> "$depfile"
+  else
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      # With Tru64 cc, shared objects can also be used to make a
+      # static library.  This mechanism is used in libtool 1.4 series to
+      # handle both shared and static libraries in a single compilation.
+      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+      #
+      # With libtool 1.5 this exception was removed, and libtool now
+      # generates 2 separate objects for the 2 libraries.  These two
+      # compilations output dependencies in $dir.libs/$base.o.d and
+      # in $dir$base.o.d.  We have to check for both files, because
+      # one of the two compilations can be disabled.  We should prefer
+      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+      # automatically cleaned when .libs/ is deleted, while ignoring
+      # the former would cause a distcleancheck panic.
+      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
+      tmpdepfile2=$dir$base.o.d          # libtool 1.5
+      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
+      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1=$dir$base.o.d
+      tmpdepfile2=$dir$base.d
+      tmpdepfile3=$dir$base.d
+      tmpdepfile4=$dir$base.d
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+      exit $stat
+   fi
+
+   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+   do
+     test -f "$tmpdepfile" && break
+   done
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[   ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+       set fnord "$@"
+       shift
+       shift
+       ;;
+    *)
+       set fnord "$@" "$arg"
+       shift
+       shift
+       ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::     \1 \\:p' >> "$depfile"
+  echo "       " >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/install-sh b/install-sh
new file mode 100755 (executable)
index 0000000..6781b98
--- /dev/null
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# 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
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""       $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+       shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+       case $mode in
+         *' '* | *'    '* | *'
+'*       | *'*'* | *'?'* | *'['*)
+           echo "$0: invalid mode: $mode" >&2
+           exit 1;;
+       esac
+       shift;;
+
+    -o) chowncmd="$chownprog $2"
+       shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+       shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)        shift
+       break;;
+
+    -*)        echo "$0: invalid option: $1" >&2
+       exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+       echo "$0: $dst_arg: Is a directory" >&2
+       exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+       (dirname "$dst") 2>/dev/null ||
+       expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+            X"$dst" : 'X\(//\)[^/]' \| \
+            X"$dst" : 'X\(//\)$' \| \
+            X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+       echo X"$dst" |
+           sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)[^/].*/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\).*/{
+                  s//\1/
+                  q
+                }
+                s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+       # Create intermediate dirs using mode 755 as modified by the umask.
+       # This is like FreeBSD 'install' as of 1997-10-28.
+       umask=`umask`
+       case $stripcmd.$umask in
+         # Optimize common cases.
+         *[2367][2367]) mkdir_umask=$umask;;
+         .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+         *[0-7])
+           mkdir_umask=`expr $umask + 22 \
+             - $umask % 100 % 40 + $umask % 20 \
+             - $umask % 10 % 4 + $umask % 2
+           `;;
+         *) mkdir_umask=$umask,go-w;;
+       esac
+
+       # With -d, create the new directory with the user-specified mode.
+       # Otherwise, rely on $mkdir_umask.
+       if test -n "$dir_arg"; then
+         mkdir_mode=-m$mode
+       else
+         mkdir_mode=
+       fi
+
+       posix_mkdir=false
+       case $umask in
+         *[123567][0-7][0-7])
+           # POSIX mkdir -p sets u+wx bits regardless of umask, which
+           # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+           ;;
+         *)
+           tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+           trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+           if (umask $mkdir_umask &&
+               exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+           then
+             if test -z "$dir_arg" || {
+                  # Check for POSIX incompatibilities with -m.
+                  # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                  # other-writeable bit of parent directory when it shouldn't.
+                  # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                  ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                  case $ls_ld_tmpdir in
+                    d????-?r-*) different_mode=700;;
+                    d????-?--*) different_mode=755;;
+                    *) false;;
+                  esac &&
+                  $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                    ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                    test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                  }
+                }
+             then posix_mkdir=:
+             fi
+             rmdir "$tmpdir/d" "$tmpdir"
+           else
+             # Remove any dirs left behind by ancient mkdir implementations.
+             rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+           fi
+           trap '' 0;;
+       esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+       umask $mkdir_umask &&
+       $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+       /*) prefix='/';;
+       -*) prefix='./';;
+       *)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+       test -z "$d" && continue
+
+       prefix=$prefix$d
+       if test -d "$prefix"; then
+         prefixes=
+       else
+         if $posix_mkdir; then
+           (umask=$mkdir_umask &&
+            $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+           # Don't fail if two instances are running concurrently.
+           test -d "$prefix" || exit 1
+         else
+           case $prefix in
+             *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+             *) qprefix=$prefix;;
+           esac
+           prefixes="$prefixes '$qprefix'"
+         fi
+       fi
+       prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+       # Don't fail if two instances are running concurrently.
+       (umask $mkdir_umask &&
+        eval "\$doit_exec \$mkdirprog $prefixes") ||
+         test -d "$dstdir" || exit 1
+       obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"    2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+       # Now remove or move aside any old file at destination location.
+       # We try this two ways since rm can't unlink itself on some
+       # systems and the destination file might be busy for other
+       # reasons.  In this case, the final cleanup might fail but the new
+       # file should still install successfully.
+       {
+         test ! -f "$dst" ||
+         $doit $rmcmd -f "$dst" 2>/dev/null ||
+         { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+           { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+         } ||
+         { echo "$0: cannot unlink or rename $dst" >&2
+           (exit 1); exit 1
+         }
+       } &&
+
+       # Now rename the file to the real destination.
+       $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libltdl/COPYING.LIB b/libltdl/COPYING.LIB
new file mode 100644 (file)
index 0000000..ba2be48
--- /dev/null
@@ -0,0 +1,515 @@
+
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+^L
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+^L
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+^L
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+^L
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+^L
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+^L
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+^L
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+^L
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+    <one line to give the library's name and a brief idea of what it
+does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+
+Also add information on how to contact you by electronic and paper
+mail.
+
+You should also get your employer (if you work as a programmer) or
+your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James
+Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/libltdl/Makefile.am b/libltdl/Makefile.am
new file mode 100644 (file)
index 0000000..4a5e945
--- /dev/null
@@ -0,0 +1,164 @@
+## Makefile.am -- Process this file with automake to produce Makefile.in
+##
+##   Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+##   Written by Gary V. Vaughan, 2003
+##
+##   NOTE: The canonical source of this file is maintained with the
+##   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+##
+## GNU Libltdl is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2 of the License, or (at your option) any later version.
+##
+## As a special exception to the GNU Lesser General Public License,
+## if you distribute this file as part of a program or library that
+## is built using GNU libtool, you may include this file under the
+## same distribution terms that you use for the rest of that program.
+##
+## GNU Libltdl 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU LesserGeneral Public
+## License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+## copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
+## or obtained by writing to the Free Software Foundation, Inc.,
+## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#####
+
+ACLOCAL_AMFLAGS = -I m4
+AUTOMAKE_OPTIONS = foreign
+AM_CPPFLAGS =
+AM_LDFLAGS =
+BUILT_SOURCES =
+include_HEADERS =
+noinst_LTLIBRARIES =
+lib_LTLIBRARIES =
+EXTRA_LTLIBRARIES =
+EXTRA_DIST =
+CLEANFILES =
+MOSTLYCLEANFILES =
+
+# -I$(srcdir) is needed for user that built libltdl with a sub-Automake
+# (not as a sub-package!) using 'nostdinc':
+AM_CPPFLAGS           += -DLT_CONFIG_H='<$(LT_CONFIG_H)>' \
+                         -DLTDL -I. -I$(srcdir) -Ilibltdl \
+                         -I$(srcdir)/libltdl -I$(srcdir)/libltdl
+AM_LDFLAGS            += -no-undefined
+LTDL_VERSION_INFO      = -version-info 10:0:3
+
+noinst_LTLIBRARIES     += $(LT_DLLOADERS)
+
+if INSTALL_LTDL
+ltdlincludedir         = $(includedir)/libltdl
+ltdlinclude_HEADERS    = libltdl/lt_system.h \
+                         libltdl/lt_error.h \
+                         libltdl/lt_dlloader.h
+include_HEADERS               += ltdl.h
+lib_LTLIBRARIES               += libltdl.la
+endif
+
+if CONVENIENCE_LTDL
+noinst_LTLIBRARIES     += libltdlc.la
+endif
+
+libltdl_la_SOURCES = libltdl/lt__alloc.h \
+                         libltdl/lt__dirent.h \
+                         libltdl/lt__glibc.h \
+                         libltdl/lt__private.h \
+                         libltdl/lt__strl.h \
+                         libltdl/lt_dlloader.h \
+                         libltdl/lt_error.h \
+                         libltdl/lt_system.h \
+                         libltdl/slist.h \
+                         loaders/preopen.c \
+                         lt__alloc.c \
+                         lt_dlloader.c \
+                         lt_error.c \
+                         ltdl.c \
+                         ltdl.h \
+                         slist.c
+
+EXTRA_DIST            += lt__dirent.c \
+                         lt__strl.c
+
+libltdl_la_CPPFLAGS    = -DLTDLOPEN=$(LTDLOPEN) $(AM_CPPFLAGS)
+libltdl_la_LDFLAGS     = $(AM_LDFLAGS) $(LTDL_VERSION_INFO) $(LT_DLPREOPEN)
+libltdl_la_LIBADD      = $(LTLIBOBJS)
+libltdl_la_DEPENDENCIES        = $(LT_DLLOADERS) $(LTLIBOBJS)
+
+libltdlc_la_SOURCES    = $(libltdl_la_SOURCES)
+libltdlc_la_CPPFLAGS   = -DLTDLOPEN=$(LTDLOPEN)c $(AM_CPPFLAGS)
+libltdlc_la_LDFLAGS    = $(AM_LDFLAGS) $(LT_DLPREOPEN)
+libltdlc_la_LIBADD     = $(libltdl_la_LIBADD)
+libltdlc_la_DEPENDENCIES= $(libltdl_la_DEPENDENCIES)
+
+## The loaders are preopened by libltdl, itself always built from
+## pic-objects (either as a shared library, or a convenience library),
+## so the loaders themselves must be made from pic-objects too.  We
+## use convenience libraries for that purpose:
+EXTRA_LTLIBRARIES             += dlopen.la \
+                                 dld_link.la \
+                                 dyld.la \
+                                 load_add_on.la \
+                                 loadlibrary.la \
+                                 shl_load.la
+
+dlopen_la_SOURCES      = loaders/dlopen.c
+dlopen_la_LDFLAGS      = -module -avoid-version
+dlopen_la_LIBADD       = $(LIBADD_DLOPEN)
+
+dld_link_la_SOURCES    = loaders/dld_link.c
+dld_link_la_LDFLAGS    = -module -avoid-version
+dld_link_la_LIBADD     = -ldld
+
+dyld_la_SOURCES                = loaders/dyld.c
+dyld_la_LDFLAGS                = -module -avoid-version
+
+load_add_on_la_SOURCES = loaders/load_add_on.c
+load_add_on_la_LDFLAGS = -module -avoid-version
+
+loadlibrary_la_SOURCES = loaders/loadlibrary.c
+loadlibrary_la_LDFLAGS = -module -avoid-version
+
+shl_load_la_SOURCES    = loaders/shl_load.c
+shl_load_la_LDFLAGS    = -module -avoid-version
+shl_load_la_LIBADD     = $(LIBADD_SHL_LOAD)
+
+## Make sure these will be cleaned even when they're not built by default:
+CLEANFILES                    += libltdl.la \
+                                 libltdlc.la \
+                                 libdlloader.la
+
+## Automake-1.9.6 doesn't clean subdir AC_LIBOBJ compiled objects
+## automatically:
+CLEANFILES            += $(LIBOBJS) $(LTLIBOBJS)
+
+EXTRA_DIST            += COPYING.LIB \
+                         configure.ac \
+                         Makefile.am \
+                         aclocal.m4 \
+                         Makefile.in \
+                         configure \
+                         config-h.in \
+                         README
+
+## --------------------------- ##
+## Gnulib Makefile.am snippets ##
+## --------------------------- ##
+
+BUILT_SOURCES  += $(ARGZ_H)
+EXTRA_DIST     += argz_.h \
+                  argz.c
+
+# We need the following in order to create an <argz.h> when the system
+# doesn't have one that works with the given compiler.
+all-local $(lib_OBJECTS): $(ARGZ_H)
+argz.h: argz_.h
+       $(mkinstalldirs) . 
+       cp $(srcdir)/argz_.h $@-t
+       mv $@-t $@
+MOSTLYCLEANFILES += argz.h \
+                   argz.h-t
diff --git a/libltdl/Makefile.in b/libltdl/Makefile.in
new file mode 100644 (file)
index 0000000..f9bab23
--- /dev/null
@@ -0,0 +1,1209 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#####
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@INSTALL_LTDL_TRUE@am__append_1 = ltdl.h
+@INSTALL_LTDL_TRUE@am__append_2 = libltdl.la
+@CONVENIENCE_LTDL_TRUE@am__append_3 = libltdlc.la
+subdir = .
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+       $(top_srcdir)/configure $(am__configure_deps) \
+       $(srcdir)/config-h.in lt__dirent.c lt__strl.c argz.c \
+       $(top_srcdir)/config/depcomp $(am__include_HEADERS_DIST) \
+       $(am__ltdlinclude_HEADERS_DIST) COPYING.LIB README \
+       config/compile config/config.guess config/config.sub \
+       config/depcomp config/install-sh  \
+       config/missing  config/ltmain.sh \
+       $(top_srcdir)/config/compile $(top_srcdir)/config/config.guess \
+       $(top_srcdir)/config/config.sub \
+       $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \
+       $(top_srcdir)/config/missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/argz.m4 \
+       $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltdl.m4 \
+       $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+       $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+       $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" \
+       "$(DESTDIR)$(ltdlincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
+dld_link_la_DEPENDENCIES =
+am_dld_link_la_OBJECTS = dld_link.lo
+dld_link_la_OBJECTS = $(am_dld_link_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+dld_link_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(dld_link_la_LDFLAGS) $(LDFLAGS) -o $@
+am__DEPENDENCIES_1 =
+dlopen_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_dlopen_la_OBJECTS = dlopen.lo
+dlopen_la_OBJECTS = $(am_dlopen_la_OBJECTS)
+dlopen_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(dlopen_la_LDFLAGS) $(LDFLAGS) -o $@
+dyld_la_LIBADD =
+am_dyld_la_OBJECTS = dyld.lo
+dyld_la_OBJECTS = $(am_dyld_la_OBJECTS)
+dyld_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(dyld_la_LDFLAGS) $(LDFLAGS) -o $@
+am_libltdl_la_OBJECTS = libltdl_la-preopen.lo libltdl_la-lt__alloc.lo \
+       libltdl_la-lt_dlloader.lo libltdl_la-lt_error.lo \
+       libltdl_la-ltdl.lo libltdl_la-slist.lo
+libltdl_la_OBJECTS = $(am_libltdl_la_OBJECTS)
+libltdl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(libltdl_la_LDFLAGS) $(LDFLAGS) -o $@
+@INSTALL_LTDL_TRUE@am_libltdl_la_rpath = -rpath $(libdir)
+am__objects_1 = libltdlc_la-preopen.lo libltdlc_la-lt__alloc.lo \
+       libltdlc_la-lt_dlloader.lo libltdlc_la-lt_error.lo \
+       libltdlc_la-ltdl.lo libltdlc_la-slist.lo
+am_libltdlc_la_OBJECTS = $(am__objects_1)
+libltdlc_la_OBJECTS = $(am_libltdlc_la_OBJECTS)
+libltdlc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(libltdlc_la_LDFLAGS) $(LDFLAGS) -o $@
+@CONVENIENCE_LTDL_TRUE@am_libltdlc_la_rpath =
+load_add_on_la_LIBADD =
+am_load_add_on_la_OBJECTS = load_add_on.lo
+load_add_on_la_OBJECTS = $(am_load_add_on_la_OBJECTS)
+load_add_on_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(load_add_on_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+loadlibrary_la_LIBADD =
+am_loadlibrary_la_OBJECTS = loadlibrary.lo
+loadlibrary_la_OBJECTS = $(am_loadlibrary_la_OBJECTS)
+loadlibrary_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(loadlibrary_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+shl_load_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am_shl_load_la_OBJECTS = shl_load.lo
+shl_load_la_OBJECTS = $(am_shl_load_la_OBJECTS)
+shl_load_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(shl_load_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(dld_link_la_SOURCES) $(dlopen_la_SOURCES) \
+       $(dyld_la_SOURCES) $(libltdl_la_SOURCES) \
+       $(libltdlc_la_SOURCES) $(load_add_on_la_SOURCES) \
+       $(loadlibrary_la_SOURCES) $(shl_load_la_SOURCES)
+DIST_SOURCES = $(dld_link_la_SOURCES) $(dlopen_la_SOURCES) \
+       $(dyld_la_SOURCES) $(libltdl_la_SOURCES) \
+       $(libltdlc_la_SOURCES) $(load_add_on_la_SOURCES) \
+       $(loadlibrary_la_SOURCES) $(shl_load_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__include_HEADERS_DIST = ltdl.h
+am__ltdlinclude_HEADERS_DIST = libltdl/lt_system.h libltdl/lt_error.h \
+       libltdl/lt_dlloader.h
+HEADERS = $(include_HEADERS) $(ltdlinclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+       $(LISP)config-h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+AM_RECURSIVE_TARGETS = cscope
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  if test -d "$(distdir)"; then \
+    find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+      && rm -rf "$(distdir)" \
+      || { sleep 5 && rm -rf "$(distdir)"; }; \
+  else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+DIST_TARGETS = dist-gzip
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+  | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I m4
+AUTOMAKE_OPTIONS = foreign
+
+# -I$(srcdir) is needed for user that built libltdl with a sub-Automake
+# (not as a sub-package!) using 'nostdinc':
+AM_CPPFLAGS = -DLT_CONFIG_H='<$(LT_CONFIG_H)>' -DLTDL -I. -I$(srcdir) \
+       -Ilibltdl -I$(srcdir)/libltdl -I$(srcdir)/libltdl
+AM_LDFLAGS = -no-undefined
+BUILT_SOURCES = $(ARGZ_H)
+include_HEADERS = $(am__append_1)
+noinst_LTLIBRARIES = $(LT_DLLOADERS) $(am__append_3)
+lib_LTLIBRARIES = $(am__append_2)
+EXTRA_LTLIBRARIES = dlopen.la dld_link.la dyld.la load_add_on.la \
+       loadlibrary.la shl_load.la
+EXTRA_DIST = lt__dirent.c lt__strl.c COPYING.LIB configure.ac \
+       Makefile.am aclocal.m4 Makefile.in configure config-h.in \
+       README argz_.h argz.c
+CLEANFILES = libltdl.la libltdlc.la libdlloader.la $(LIBOBJS) \
+       $(LTLIBOBJS)
+MOSTLYCLEANFILES = argz.h argz.h-t
+LTDL_VERSION_INFO = -version-info 10:0:3
+@INSTALL_LTDL_TRUE@ltdlincludedir = $(includedir)/libltdl
+@INSTALL_LTDL_TRUE@ltdlinclude_HEADERS = libltdl/lt_system.h \
+@INSTALL_LTDL_TRUE@                      libltdl/lt_error.h \
+@INSTALL_LTDL_TRUE@                      libltdl/lt_dlloader.h
+
+libltdl_la_SOURCES = libltdl/lt__alloc.h \
+                         libltdl/lt__dirent.h \
+                         libltdl/lt__glibc.h \
+                         libltdl/lt__private.h \
+                         libltdl/lt__strl.h \
+                         libltdl/lt_dlloader.h \
+                         libltdl/lt_error.h \
+                         libltdl/lt_system.h \
+                         libltdl/slist.h \
+                         loaders/preopen.c \
+                         lt__alloc.c \
+                         lt_dlloader.c \
+                         lt_error.c \
+                         ltdl.c \
+                         ltdl.h \
+                         slist.c
+
+libltdl_la_CPPFLAGS = -DLTDLOPEN=$(LTDLOPEN) $(AM_CPPFLAGS)
+libltdl_la_LDFLAGS = $(AM_LDFLAGS) $(LTDL_VERSION_INFO) $(LT_DLPREOPEN)
+libltdl_la_LIBADD = $(LTLIBOBJS)
+libltdl_la_DEPENDENCIES = $(LT_DLLOADERS) $(LTLIBOBJS)
+libltdlc_la_SOURCES = $(libltdl_la_SOURCES)
+libltdlc_la_CPPFLAGS = -DLTDLOPEN=$(LTDLOPEN)c $(AM_CPPFLAGS)
+libltdlc_la_LDFLAGS = $(AM_LDFLAGS) $(LT_DLPREOPEN)
+libltdlc_la_LIBADD = $(libltdl_la_LIBADD)
+libltdlc_la_DEPENDENCIES = $(libltdl_la_DEPENDENCIES)
+dlopen_la_SOURCES = loaders/dlopen.c
+dlopen_la_LDFLAGS = -module -avoid-version
+dlopen_la_LIBADD = $(LIBADD_DLOPEN)
+dld_link_la_SOURCES = loaders/dld_link.c
+dld_link_la_LDFLAGS = -module -avoid-version
+dld_link_la_LIBADD = -ldld
+dyld_la_SOURCES = loaders/dyld.c
+dyld_la_LDFLAGS = -module -avoid-version
+load_add_on_la_SOURCES = loaders/load_add_on.c
+load_add_on_la_LDFLAGS = -module -avoid-version
+loadlibrary_la_SOURCES = loaders/loadlibrary.c
+loadlibrary_la_LDFLAGS = -module -avoid-version
+shl_load_la_SOURCES = loaders/shl_load.c
+shl_load_la_LDFLAGS = -module -avoid-version
+shl_load_la_LIBADD = $(LIBADD_SHL_LOAD)
+all: $(BUILT_SOURCES) config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+am--refresh: Makefile
+       @:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+             $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+       @test -f $@ || rm -f stamp-h1
+       @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config-h.in $(top_builddir)/config.status
+       @rm -f stamp-h1
+       cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config-h.in:  $(am__configure_deps) 
+       ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+       rm -f stamp-h1
+       touch $@
+
+distclean-hdr:
+       -rm -f config.h stamp-h1
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+       list2=; for p in $$list; do \
+         if test -f $$p; then \
+           list2="$$list2 $$p"; \
+         else :; fi; \
+       done; \
+       test -z "$$list2" || { \
+         echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+       }
+
+uninstall-libLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+       for p in $$list; do \
+         $(am__strip_dir) \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+       done
+
+clean-libLTLIBRARIES:
+       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+       @list='$(lib_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+       @list='$(noinst_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
+
+dld_link.la: $(dld_link_la_OBJECTS) $(dld_link_la_DEPENDENCIES) $(EXTRA_dld_link_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(dld_link_la_LINK)  $(dld_link_la_OBJECTS) $(dld_link_la_LIBADD) $(LIBS)
+
+dlopen.la: $(dlopen_la_OBJECTS) $(dlopen_la_DEPENDENCIES) $(EXTRA_dlopen_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(dlopen_la_LINK)  $(dlopen_la_OBJECTS) $(dlopen_la_LIBADD) $(LIBS)
+
+dyld.la: $(dyld_la_OBJECTS) $(dyld_la_DEPENDENCIES) $(EXTRA_dyld_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(dyld_la_LINK)  $(dyld_la_OBJECTS) $(dyld_la_LIBADD) $(LIBS)
+
+libltdl.la: $(libltdl_la_OBJECTS) $(libltdl_la_DEPENDENCIES) $(EXTRA_libltdl_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(libltdl_la_LINK) $(am_libltdl_la_rpath) $(libltdl_la_OBJECTS) $(libltdl_la_LIBADD) $(LIBS)
+
+libltdlc.la: $(libltdlc_la_OBJECTS) $(libltdlc_la_DEPENDENCIES) $(EXTRA_libltdlc_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(libltdlc_la_LINK) $(am_libltdlc_la_rpath) $(libltdlc_la_OBJECTS) $(libltdlc_la_LIBADD) $(LIBS)
+
+load_add_on.la: $(load_add_on_la_OBJECTS) $(load_add_on_la_DEPENDENCIES) $(EXTRA_load_add_on_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(load_add_on_la_LINK)  $(load_add_on_la_OBJECTS) $(load_add_on_la_LIBADD) $(LIBS)
+
+loadlibrary.la: $(loadlibrary_la_OBJECTS) $(loadlibrary_la_DEPENDENCIES) $(EXTRA_loadlibrary_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(loadlibrary_la_LINK)  $(loadlibrary_la_OBJECTS) $(loadlibrary_la_LIBADD) $(LIBS)
+
+shl_load.la: $(shl_load_la_OBJECTS) $(shl_load_la_DEPENDENCIES) $(EXTRA_shl_load_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(shl_load_la_LINK)  $(shl_load_la_OBJECTS) $(shl_load_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/argz.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/lt__dirent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/lt__strl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dld_link.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlopen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dyld.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdl_la-lt__alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdl_la-lt_dlloader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdl_la-lt_error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdl_la-ltdl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdl_la-preopen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdl_la-slist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdlc_la-lt__alloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdlc_la-lt_dlloader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdlc_la-lt_error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdlc_la-ltdl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdlc_la-preopen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libltdlc_la-slist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_add_on.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loadlibrary.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shl_load.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+dld_link.lo: loaders/dld_link.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dld_link.lo -MD -MP -MF $(DEPDIR)/dld_link.Tpo -c -o dld_link.lo `test -f 'loaders/dld_link.c' || echo '$(srcdir)/'`loaders/dld_link.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/dld_link.Tpo $(DEPDIR)/dld_link.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/dld_link.c' object='dld_link.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dld_link.lo `test -f 'loaders/dld_link.c' || echo '$(srcdir)/'`loaders/dld_link.c
+
+dlopen.lo: loaders/dlopen.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dlopen.lo -MD -MP -MF $(DEPDIR)/dlopen.Tpo -c -o dlopen.lo `test -f 'loaders/dlopen.c' || echo '$(srcdir)/'`loaders/dlopen.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/dlopen.Tpo $(DEPDIR)/dlopen.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/dlopen.c' object='dlopen.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dlopen.lo `test -f 'loaders/dlopen.c' || echo '$(srcdir)/'`loaders/dlopen.c
+
+dyld.lo: loaders/dyld.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dyld.lo -MD -MP -MF $(DEPDIR)/dyld.Tpo -c -o dyld.lo `test -f 'loaders/dyld.c' || echo '$(srcdir)/'`loaders/dyld.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/dyld.Tpo $(DEPDIR)/dyld.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/dyld.c' object='dyld.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dyld.lo `test -f 'loaders/dyld.c' || echo '$(srcdir)/'`loaders/dyld.c
+
+libltdl_la-preopen.lo: loaders/preopen.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdl_la-preopen.lo -MD -MP -MF $(DEPDIR)/libltdl_la-preopen.Tpo -c -o libltdl_la-preopen.lo `test -f 'loaders/preopen.c' || echo '$(srcdir)/'`loaders/preopen.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdl_la-preopen.Tpo $(DEPDIR)/libltdl_la-preopen.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/preopen.c' object='libltdl_la-preopen.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdl_la-preopen.lo `test -f 'loaders/preopen.c' || echo '$(srcdir)/'`loaders/preopen.c
+
+libltdl_la-lt__alloc.lo: lt__alloc.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdl_la-lt__alloc.lo -MD -MP -MF $(DEPDIR)/libltdl_la-lt__alloc.Tpo -c -o libltdl_la-lt__alloc.lo `test -f 'lt__alloc.c' || echo '$(srcdir)/'`lt__alloc.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdl_la-lt__alloc.Tpo $(DEPDIR)/libltdl_la-lt__alloc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lt__alloc.c' object='libltdl_la-lt__alloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdl_la-lt__alloc.lo `test -f 'lt__alloc.c' || echo '$(srcdir)/'`lt__alloc.c
+
+libltdl_la-lt_dlloader.lo: lt_dlloader.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdl_la-lt_dlloader.lo -MD -MP -MF $(DEPDIR)/libltdl_la-lt_dlloader.Tpo -c -o libltdl_la-lt_dlloader.lo `test -f 'lt_dlloader.c' || echo '$(srcdir)/'`lt_dlloader.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdl_la-lt_dlloader.Tpo $(DEPDIR)/libltdl_la-lt_dlloader.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lt_dlloader.c' object='libltdl_la-lt_dlloader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdl_la-lt_dlloader.lo `test -f 'lt_dlloader.c' || echo '$(srcdir)/'`lt_dlloader.c
+
+libltdl_la-lt_error.lo: lt_error.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdl_la-lt_error.lo -MD -MP -MF $(DEPDIR)/libltdl_la-lt_error.Tpo -c -o libltdl_la-lt_error.lo `test -f 'lt_error.c' || echo '$(srcdir)/'`lt_error.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdl_la-lt_error.Tpo $(DEPDIR)/libltdl_la-lt_error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lt_error.c' object='libltdl_la-lt_error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdl_la-lt_error.lo `test -f 'lt_error.c' || echo '$(srcdir)/'`lt_error.c
+
+libltdl_la-ltdl.lo: ltdl.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdl_la-ltdl.lo -MD -MP -MF $(DEPDIR)/libltdl_la-ltdl.Tpo -c -o libltdl_la-ltdl.lo `test -f 'ltdl.c' || echo '$(srcdir)/'`ltdl.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdl_la-ltdl.Tpo $(DEPDIR)/libltdl_la-ltdl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ltdl.c' object='libltdl_la-ltdl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdl_la-ltdl.lo `test -f 'ltdl.c' || echo '$(srcdir)/'`ltdl.c
+
+libltdl_la-slist.lo: slist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdl_la-slist.lo -MD -MP -MF $(DEPDIR)/libltdl_la-slist.Tpo -c -o libltdl_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdl_la-slist.Tpo $(DEPDIR)/libltdl_la-slist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='slist.c' object='libltdl_la-slist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdl_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c
+
+libltdlc_la-preopen.lo: loaders/preopen.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdlc_la-preopen.lo -MD -MP -MF $(DEPDIR)/libltdlc_la-preopen.Tpo -c -o libltdlc_la-preopen.lo `test -f 'loaders/preopen.c' || echo '$(srcdir)/'`loaders/preopen.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdlc_la-preopen.Tpo $(DEPDIR)/libltdlc_la-preopen.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/preopen.c' object='libltdlc_la-preopen.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdlc_la-preopen.lo `test -f 'loaders/preopen.c' || echo '$(srcdir)/'`loaders/preopen.c
+
+libltdlc_la-lt__alloc.lo: lt__alloc.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdlc_la-lt__alloc.lo -MD -MP -MF $(DEPDIR)/libltdlc_la-lt__alloc.Tpo -c -o libltdlc_la-lt__alloc.lo `test -f 'lt__alloc.c' || echo '$(srcdir)/'`lt__alloc.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdlc_la-lt__alloc.Tpo $(DEPDIR)/libltdlc_la-lt__alloc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lt__alloc.c' object='libltdlc_la-lt__alloc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdlc_la-lt__alloc.lo `test -f 'lt__alloc.c' || echo '$(srcdir)/'`lt__alloc.c
+
+libltdlc_la-lt_dlloader.lo: lt_dlloader.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdlc_la-lt_dlloader.lo -MD -MP -MF $(DEPDIR)/libltdlc_la-lt_dlloader.Tpo -c -o libltdlc_la-lt_dlloader.lo `test -f 'lt_dlloader.c' || echo '$(srcdir)/'`lt_dlloader.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdlc_la-lt_dlloader.Tpo $(DEPDIR)/libltdlc_la-lt_dlloader.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lt_dlloader.c' object='libltdlc_la-lt_dlloader.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdlc_la-lt_dlloader.lo `test -f 'lt_dlloader.c' || echo '$(srcdir)/'`lt_dlloader.c
+
+libltdlc_la-lt_error.lo: lt_error.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdlc_la-lt_error.lo -MD -MP -MF $(DEPDIR)/libltdlc_la-lt_error.Tpo -c -o libltdlc_la-lt_error.lo `test -f 'lt_error.c' || echo '$(srcdir)/'`lt_error.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdlc_la-lt_error.Tpo $(DEPDIR)/libltdlc_la-lt_error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='lt_error.c' object='libltdlc_la-lt_error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdlc_la-lt_error.lo `test -f 'lt_error.c' || echo '$(srcdir)/'`lt_error.c
+
+libltdlc_la-ltdl.lo: ltdl.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdlc_la-ltdl.lo -MD -MP -MF $(DEPDIR)/libltdlc_la-ltdl.Tpo -c -o libltdlc_la-ltdl.lo `test -f 'ltdl.c' || echo '$(srcdir)/'`ltdl.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdlc_la-ltdl.Tpo $(DEPDIR)/libltdlc_la-ltdl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ltdl.c' object='libltdlc_la-ltdl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdlc_la-ltdl.lo `test -f 'ltdl.c' || echo '$(srcdir)/'`ltdl.c
+
+libltdlc_la-slist.lo: slist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libltdlc_la-slist.lo -MD -MP -MF $(DEPDIR)/libltdlc_la-slist.Tpo -c -o libltdlc_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/libltdlc_la-slist.Tpo $(DEPDIR)/libltdlc_la-slist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='slist.c' object='libltdlc_la-slist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libltdlc_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libltdlc_la-slist.lo `test -f 'slist.c' || echo '$(srcdir)/'`slist.c
+
+load_add_on.lo: loaders/load_add_on.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT load_add_on.lo -MD -MP -MF $(DEPDIR)/load_add_on.Tpo -c -o load_add_on.lo `test -f 'loaders/load_add_on.c' || echo '$(srcdir)/'`loaders/load_add_on.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/load_add_on.Tpo $(DEPDIR)/load_add_on.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/load_add_on.c' object='load_add_on.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o load_add_on.lo `test -f 'loaders/load_add_on.c' || echo '$(srcdir)/'`loaders/load_add_on.c
+
+loadlibrary.lo: loaders/loadlibrary.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT loadlibrary.lo -MD -MP -MF $(DEPDIR)/loadlibrary.Tpo -c -o loadlibrary.lo `test -f 'loaders/loadlibrary.c' || echo '$(srcdir)/'`loaders/loadlibrary.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/loadlibrary.Tpo $(DEPDIR)/loadlibrary.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/loadlibrary.c' object='loadlibrary.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o loadlibrary.lo `test -f 'loaders/loadlibrary.c' || echo '$(srcdir)/'`loaders/loadlibrary.c
+
+shl_load.lo: loaders/shl_load.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT shl_load.lo -MD -MP -MF $(DEPDIR)/shl_load.Tpo -c -o shl_load.lo `test -f 'loaders/shl_load.c' || echo '$(srcdir)/'`loaders/shl_load.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/shl_load.Tpo $(DEPDIR)/shl_load.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='loaders/shl_load.c' object='shl_load.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o shl_load.lo `test -f 'loaders/shl_load.c' || echo '$(srcdir)/'`loaders/shl_load.c
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool config.lt
+install-includeHEADERS: $(include_HEADERS)
+       @$(NORMAL_INSTALL)
+       @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+       fi; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+         $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+       done
+
+uninstall-includeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+install-ltdlincludeHEADERS: $(ltdlinclude_HEADERS)
+       @$(NORMAL_INSTALL)
+       @list='$(ltdlinclude_HEADERS)'; test -n "$(ltdlincludedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(ltdlincludedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(ltdlincludedir)" || exit 1; \
+       fi; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(ltdlincludedir)'"; \
+         $(INSTALL_HEADER) $$files "$(DESTDIR)$(ltdlincludedir)" || exit $$?; \
+       done
+
+uninstall-ltdlincludeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(ltdlinclude_HEADERS)'; test -n "$(ltdlincludedir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       dir='$(DESTDIR)$(ltdlincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+       test ! -s cscope.files \
+         || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+       -rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+       -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       test -d "$(distdir)" || mkdir "$(distdir)"
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+       -test -n "$(am__skip_mode_fix)" \
+       || find "$(distdir)" -type d ! -perm -755 \
+               -exec chmod u+rwx,go+rx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__post_remove_distdir)
+
+dist-bzip2: distdir
+       tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+       $(am__post_remove_distdir)
+
+dist-lzip: distdir
+       tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+       $(am__post_remove_distdir)
+
+dist-xz: distdir
+       tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+       $(am__post_remove_distdir)
+
+dist-tarZ: distdir
+       @echo WARNING: "Support for shar distribution archives is" \
+                      "deprecated." >&2
+       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       $(am__post_remove_distdir)
+
+dist-shar: distdir
+       @echo WARNING: "Support for distribution archives compressed with" \
+                      "legacy program 'compress' is deprecated." >&2
+       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__post_remove_distdir)
+
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__post_remove_distdir)
+
+dist dist-all:
+       $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+       $(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+       *.tar.bz2*) \
+         bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+       *.tar.lz*) \
+         lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+       *.tar.xz*) \
+         xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir)
+       chmod u+w $(distdir)
+       mkdir $(distdir)/_build $(distdir)/_inst
+       chmod a-w $(distdir)
+       test -d $(distdir)/_build || exit 0; \
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && am__cwd=`pwd` \
+         && $(am__cd) $(distdir)/_build \
+         && ../configure \
+           $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+           --srcdir=.. --prefix="$$dc_install_base" \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+         && cd "$$am__cwd" \
+         || exit 1
+       $(am__post_remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+       @test -n '$(distuninstallcheck_dir)' || { \
+         echo 'ERROR: trying to run $@ with an empty' \
+              '$$(distuninstallcheck_dir)' >&2; \
+         exit 1; \
+       }; \
+       $(am__cd) '$(distuninstallcheck_dir)' || { \
+         echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+         exit 1; \
+       }; \
+       test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+check: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS) config.h
+installdirs:
+       for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(ltdlincludedir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+       clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(DEPDIR) ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-hdr distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-includeHEADERS install-ltdlincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -rf $(DEPDIR) ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+       uninstall-ltdlincludeHEADERS
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am clean \
+       clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \
+       clean-noinstLTLIBRARIES cscope cscopelist-am ctags ctags-am \
+       dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \
+       dist-tarZ dist-xz dist-zip distcheck distclean \
+       distclean-compile distclean-generic distclean-hdr \
+       distclean-libtool distclean-tags distcleancheck distdir \
+       distuninstallcheck dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-includeHEADERS install-info \
+       install-info-am install-libLTLIBRARIES \
+       install-ltdlincludeHEADERS install-man install-pdf \
+       install-pdf-am install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags tags-am uninstall uninstall-am uninstall-includeHEADERS \
+       uninstall-libLTLIBRARIES uninstall-ltdlincludeHEADERS
+
+
+# We need the following in order to create an <argz.h> when the system
+# doesn't have one that works with the given compiler.
+all-local $(lib_OBJECTS): $(ARGZ_H)
+argz.h: argz_.h
+       $(mkinstalldirs) . 
+       cp $(srcdir)/argz_.h $@-t
+       mv $@-t $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libltdl/README b/libltdl/README
new file mode 100644 (file)
index 0000000..90a0aef
--- /dev/null
@@ -0,0 +1,20 @@
+This is GNU libltdl, a system independent dlopen wrapper for GNU libtool.
+
+It supports the following dlopen interfaces:
+* dlopen (POSIX)
+* shl_load (HP-UX)
+* LoadLibrary (Win16 and Win32)
+* load_add_on (BeOS)
+* GNU DLD (emulates dynamic linking for static libraries)
+* dyld (darwin/Mac OS X)
+* libtool's dlpreopen
+--
+   Copyright (C) 1999, 2003, 2011 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1999
+
+   This file is part of GNU Libtool.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.  This file is offered as-is,
+without warranty of any kind.
diff --git a/libltdl/aclocal.m4 b/libltdl/aclocal.m4
new file mode 100644 (file)
index 0000000..6792da7
--- /dev/null
@@ -0,0 +1,1156 @@
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# Copyright (C) 2002-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.14'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.14.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.14.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
+      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
+      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
+      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                    [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+  [--enable-dependency-tracking],
+  [do not reject slow dependency extractors])
+AS_HELP_STRING(
+  [--disable-dependency-tracking],
+  [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each '.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+             [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+  [ok:ok],,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+             [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+                            [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                 [_AM_DEPENDENCIES([CC])],
+                 [m4_define([AC_PROG_CC],
+                            m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                 [_AM_DEPENDENCIES([CXX])],
+                 [m4_define([AC_PROG_CXX],
+                            m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+                 [_AM_DEPENDENCIES([OBJC])],
+                 [m4_define([AC_PROG_OBJC],
+                            m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+                 [_AM_DEPENDENCIES([OBJCXX])],
+                 [m4_define([AC_PROG_OBJCXX],
+                            m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.                 -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \   ]]*)
+    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$[*]" = "X"; then
+       # -L didn't work.
+       set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$[*]" != "X $srcdir/configure conftest.file" \
+       && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+       # If neither matched, then we have a broken ls.  This can happen
+       # if, for instance, CONFIG_SHELL is bash and it inherits a
+       # broken ls alias from the environment.  This has actually
+       # happened.  Such a system could not be considered "sane".
+       AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment])
+     fi
+     if test "$[2]" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+  [AC_MSG_CHECKING([that generated files are newer than configure])
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+       @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/argz.m4])
+m4_include([m4/libtool.m4])
+m4_include([m4/ltdl.m4])
+m4_include([m4/ltoptions.m4])
+m4_include([m4/ltsugar.m4])
+m4_include([m4/ltversion.m4])
+m4_include([m4/lt~obsolete.m4])
diff --git a/libltdl/argz.c b/libltdl/argz.c
new file mode 100644 (file)
index 0000000..8567723
--- /dev/null
@@ -0,0 +1,226 @@
+/* argz.c -- argz implementation for non-glibc systems
+
+   Copyright (C) 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#if defined(LTDL) && defined LT_CONFIG_H
+#  include LT_CONFIG_H
+#else
+#  include <config.h>
+#endif
+
+#include <argz.h>
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#define EOS_CHAR '\0'
+
+error_t
+argz_append (char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)
+{
+  size_t argz_len;
+  char  *argz;
+
+  assert (pargz);
+  assert (pargz_len);
+  assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
+
+  /* If nothing needs to be appended, no more work is required.  */
+  if (buf_len == 0)
+    return 0;
+
+  /* Ensure there is enough room to append BUF_LEN.  */
+  argz_len = *pargz_len + buf_len;
+  argz = (char *) realloc (*pargz, argz_len);
+  if (!argz)
+    return ENOMEM;
+
+  /* Copy characters from BUF after terminating '\0' in ARGZ.  */
+  memcpy (argz + *pargz_len, buf, buf_len);
+
+  /* Assign new values.  */
+  *pargz = argz;
+  *pargz_len = argz_len;
+
+  return 0;
+}
+
+
+error_t
+argz_create_sep (const char *str, int delim, char **pargz, size_t *pargz_len)
+{
+  size_t argz_len;
+  char *argz = 0;
+
+  assert (str);
+  assert (pargz);
+  assert (pargz_len);
+
+  /* Make a copy of STR, but replacing each occurrence of
+     DELIM with '\0'.  */
+  argz_len = 1+ strlen (str);
+  if (argz_len)
+    {
+      const char *p;
+      char *q;
+
+      argz = (char *) malloc (argz_len);
+      if (!argz)
+       return ENOMEM;
+
+      for (p = str, q = argz; *p != EOS_CHAR; ++p)
+       {
+         if (*p == delim)
+           {
+             /* Ignore leading delimiters, and fold consecutive
+                delimiters in STR into a single '\0' in ARGZ.  */
+             if ((q > argz) && (q[-1] != EOS_CHAR))
+               *q++ = EOS_CHAR;
+             else
+               --argz_len;
+           }
+         else
+           *q++ = *p;
+       }
+      /* Copy terminating EOS_CHAR.  */
+      *q = *p;
+    }
+
+  /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
+  if (!argz_len)
+    argz = (free (argz), (char *) 0);
+
+  /* Assign new values.  */
+  *pargz = argz;
+  *pargz_len = argz_len;
+
+  return 0;
+}
+
+
+error_t
+argz_insert (char **pargz, size_t *pargz_len, char *before, const char *entry)
+{
+  assert (pargz);
+  assert (pargz_len);
+  assert (entry && *entry);
+
+  /* No BEFORE address indicates ENTRY should be inserted after the
+     current last element.  */
+  if (!before)
+    return argz_append (pargz, pargz_len, entry, 1+ strlen (entry));
+
+  /* This probably indicates a programmer error, but to preserve
+     semantics, scan back to the start of an entry if BEFORE points
+     into the middle of it.  */
+  while ((before > *pargz) && (before[-1] != EOS_CHAR))
+    --before;
+
+  {
+    size_t entry_len   = 1+ strlen (entry);
+    size_t argz_len    = *pargz_len + entry_len;
+    size_t offset      = before - *pargz;
+    char   *argz       = (char *) realloc (*pargz, argz_len);
+
+    if (!argz)
+      return ENOMEM;
+
+    /* Make BEFORE point to the equivalent offset in ARGZ that it
+       used to have in *PARGZ incase realloc() moved the block.  */
+    before = argz + offset;
+
+    /* Move the ARGZ entries starting at BEFORE up into the new
+       space at the end -- making room to copy ENTRY into the
+       resulting gap.  */
+    memmove (before + entry_len, before, *pargz_len - offset);
+    memcpy  (before, entry, entry_len);
+
+    /* Assign new values.  */
+    *pargz = argz;
+    *pargz_len = argz_len;
+  }
+
+  return 0;
+}
+
+
+char *
+argz_next (char *argz, size_t argz_len, const char *entry)
+{
+  assert ((argz && argz_len) || (!argz && !argz_len));
+
+  if (entry)
+    {
+      /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
+        within the ARGZ vector.  */
+      assert ((!argz && !argz_len)
+             || ((argz <= entry) && (entry < (argz + argz_len))));
+
+      /* Move to the char immediately after the terminating
+        '\0' of ENTRY.  */
+      entry = 1+ strchr (entry, EOS_CHAR);
+
+      /* Return either the new ENTRY, or else NULL if ARGZ is
+        exhausted.  */
+      return (entry >= argz + argz_len) ? 0 : (char *) entry;
+    }
+  else
+    {
+      /* This should probably be flagged as a programmer error,
+        since starting an argz_next loop with the iterator set
+        to ARGZ is safer.  To preserve semantics, handle the NULL
+        case by returning the start of ARGZ (if any).  */
+      if (argz_len > 0)
+       return argz;
+      else
+       return 0;
+    }
+}
+
+
+void
+argz_stringify (char *argz, size_t argz_len, int sep)
+{
+  assert ((argz && argz_len) || (!argz && !argz_len));
+
+  if (sep)
+    {
+      --argz_len;              /* don't stringify the terminating EOS */
+      while (--argz_len > 0)
+       {
+         if (argz[argz_len] == EOS_CHAR)
+           argz[argz_len] = sep;
+       }
+    }
+}
+
diff --git a/libltdl/argz_.h b/libltdl/argz_.h
new file mode 100644 (file)
index 0000000..0557575
--- /dev/null
@@ -0,0 +1,68 @@
+/* lt__argz.h -- internal argz interface for non-glibc systems
+
+   Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#if !defined(LT__ARGZ_H)
+#define LT__ARGZ_H 1
+
+#include <stdlib.h>
+#define __need_error_t
+#include <errno.h>
+#include <sys/types.h>
+
+#if defined(LTDL)
+#  include "lt__glibc.h"
+#  include "lt_system.h"
+#else
+#  define LT_SCOPE
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+LT_SCOPE error_t argz_append   (char **pargz, size_t *pargz_len,
+                                const char *buf, size_t buf_len);
+LT_SCOPE error_t argz_create_sep(const char *str, int delim,
+                                char **pargz, size_t *pargz_len);
+LT_SCOPE error_t argz_insert   (char **pargz, size_t *pargz_len,
+                                char *before, const char *entry);
+LT_SCOPE char *         argz_next      (char *argz, size_t argz_len,
+                                const char *entry);
+LT_SCOPE void   argz_stringify (char *argz, size_t argz_len, int sep);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if !defined(LTDL)
+#  undef LT_SCOPE
+#endif
+
+#endif /*!defined(LT__ARGZ_H)*/
diff --git a/libltdl/config-h.in b/libltdl/config-h.in
new file mode 100644 (file)
index 0000000..23eab00
--- /dev/null
@@ -0,0 +1,178 @@
+/* config-h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the `argz_add' function. */
+#undef HAVE_ARGZ_ADD
+
+/* Define to 1 if you have the `argz_append' function. */
+#undef HAVE_ARGZ_APPEND
+
+/* Define to 1 if you have the `argz_count' function. */
+#undef HAVE_ARGZ_COUNT
+
+/* Define to 1 if you have the `argz_create_sep' function. */
+#undef HAVE_ARGZ_CREATE_SEP
+
+/* Define to 1 if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define to 1 if you have the `argz_insert' function. */
+#undef HAVE_ARGZ_INSERT
+
+/* Define to 1 if you have the `argz_next' function. */
+#undef HAVE_ARGZ_NEXT
+
+/* Define to 1 if you have the `argz_stringify' function. */
+#undef HAVE_ARGZ_STRINGIFY
+
+/* Define to 1 if you have the `closedir' function. */
+#undef HAVE_CLOSEDIR
+
+/* Define to 1 if you have the declaration of `cygwin_conv_path', and to 0 if
+   you don't. */
+#undef HAVE_DECL_CYGWIN_CONV_PATH
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the GNU dld library. */
+#undef HAVE_DLD
+
+/* Define to 1 if you have the <dld.h> header file. */
+#undef HAVE_DLD_H
+
+/* Define to 1 if you have the `dlerror' function. */
+#undef HAVE_DLERROR
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <dl.h> header file. */
+#undef HAVE_DL_H
+
+/* Define if you have the _dyld_func_lookup function. */
+#undef HAVE_DYLD
+
+/* Define to 1 if the system has the type `error_t'. */
+#undef HAVE_ERROR_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have the libdl library or equivalent. */
+#undef HAVE_LIBDL
+
+/* Define if libdlloader will be built on this platform */
+#undef HAVE_LIBDLLOADER
+
+/* Define to 1 if you have the <mach-o/dyld.h> header file. */
+#undef HAVE_MACH_O_DYLD_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `opendir' function. */
+#undef HAVE_OPENDIR
+
+/* Define if libtool can extract symbol lists from object files. */
+#undef HAVE_PRELOADED_SYMBOLS
+
+/* Define to 1 if you have the `readdir' function. */
+#undef HAVE_READDIR
+
+/* Define if you have the shl_load function. */
+#undef HAVE_SHL_LOAD
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the <sys/dl.h> header file. */
+#undef HAVE_SYS_DL_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* This value is set to 1 to indicate that the system argz facility works */
+#undef HAVE_WORKING_ARGZ
+
+/* Define if the OS needs help to load dependent libraries for dlopen(). */
+#undef LTDL_DLOPEN_DEPLIBS
+
+/* Define to the system default library search path. */
+#undef LT_DLSEARCH_PATH
+
+/* The archive extension */
+#undef LT_LIBEXT
+
+/* The archive prefix */
+#undef LT_LIBPREFIX
+
+/* Define to the extension used for runtime loadable modules, say, ".so". */
+#undef LT_MODULE_EXT
+
+/* Define to the name of the environment variable that determines the run-time
+   module search path. */
+#undef LT_MODULE_PATH_VAR
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Define to the shared library suffix, say, ".dylib". */
+#undef LT_SHARED_EXT
+
+/* Define if dlsym() requires a leading underscore in symbol names. */
+#undef NEED_USCORE
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define so that glibc/gnulib argp.h does not typedef error_t. */
+#undef __error_t_defined
+
+/* Define to a type to use for `error_t' if it is not otherwise available. */
+#undef error_t
diff --git a/libltdl/config/compile b/libltdl/config/compile
new file mode 100755 (executable)
index 0000000..531136b
--- /dev/null
@@ -0,0 +1,347 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2012-10-14.11; # UTC
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" ""       $nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+  file=$1
+  case $file in
+    / | /[!/]*) # absolute file, and not a UNC file
+      if test -z "$file_conv"; then
+       # lazily determine how to convert abs files
+       case `uname -s` in
+         MINGW*)
+           file_conv=mingw
+           ;;
+         CYGWIN*)
+           file_conv=cygwin
+           ;;
+         *)
+           file_conv=wine
+           ;;
+       esac
+      fi
+      case $file_conv/,$2, in
+       *,$file_conv,*)
+         ;;
+       mingw/*)
+         file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+         ;;
+       cygwin/*)
+         file=`cygpath -m "$file" || echo "$file"`
+         ;;
+       wine/*)
+         file=`winepath -w "$file" || echo "$file"`
+         ;;
+      esac
+      ;;
+  esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+    if test -f "$dir/lib$lib.a"; then
+      found=yes
+      lib=$dir/lib$lib.a
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+  # Assume a capable shell
+  lib_path=
+  shared=:
+  linker_opts=
+  for arg
+  do
+    if test -n "$eat"; then
+      eat=
+    else
+      case $1 in
+       -o)
+         # configure might choose to run compile as 'compile cc -o foo foo.c'.
+         eat=1
+         case $2 in
+           *.o | *.[oO][bB][jJ])
+             func_file_conv "$2"
+             set x "$@" -Fo"$file"
+             shift
+             ;;
+           *)
+             func_file_conv "$2"
+             set x "$@" -Fe"$file"
+             shift
+             ;;
+         esac
+         ;;
+       -I)
+         eat=1
+         func_file_conv "$2" mingw
+         set x "$@" -I"$file"
+         shift
+         ;;
+       -I*)
+         func_file_conv "${1#-I}" mingw
+         set x "$@" -I"$file"
+         shift
+         ;;
+       -l)
+         eat=1
+         func_cl_dashl "$2"
+         set x "$@" "$lib"
+         shift
+         ;;
+       -l*)
+         func_cl_dashl "${1#-l}"
+         set x "$@" "$lib"
+         shift
+         ;;
+       -L)
+         eat=1
+         func_cl_dashL "$2"
+         ;;
+       -L*)
+         func_cl_dashL "${1#-L}"
+         ;;
+       -static)
+         shared=false
+         ;;
+       -Wl,*)
+         arg=${1#-Wl,}
+         save_ifs="$IFS"; IFS=','
+         for flag in $arg; do
+           IFS="$save_ifs"
+           linker_opts="$linker_opts $flag"
+         done
+         IFS="$save_ifs"
+         ;;
+       -Xlinker)
+         eat=1
+         linker_opts="$linker_opts $2"
+         ;;
+       -*)
+         set x "$@" "$1"
+         shift
+         ;;
+       *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+         func_file_conv "$1"
+         set x "$@" -Tp"$file"
+         shift
+         ;;
+       *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+         func_file_conv "$1" mingw
+         set x "$@" "$file"
+         shift
+         ;;
+       *)
+         set x "$@" "$1"
+         shift
+         ;;
+      esac
+    fi
+    shift
+  done
+  if test -n "$linker_opts"; then
+    linker_opts="-link$linker_opts"
+  fi
+  exec "$@" $linker_opts
+  exit 1
+}
+
+eat=
+
+case $1 in
+  '')
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
+    func_cl_wrapper "$@"      # Doesn't return...
+    ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+       # configure might choose to run compile as 'compile cc -o foo foo.c'.
+       # So we strip '-o arg' only if arg is an object.
+       eat=1
+       case $2 in
+         *.o | *.obj)
+           ofile=$2
+           ;;
+         *)
+           set x "$@" -o "$2"
+           shift
+           ;;
+       esac
+       ;;
+      *.c)
+       cfile=$1
+       set x "$@" "$1"
+       shift
+       ;;
+      *)
+       set x "$@" "$1"
+       shift
+       ;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no '-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # '.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libltdl/config/config.guess b/libltdl/config/config.guess
new file mode 100755 (executable)
index 0000000..b79252d
--- /dev/null
@@ -0,0 +1,1558 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright 1992-2013 Free Software Foundation, Inc.
+
+timestamp='2013-06-10'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2013 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+       # If the system lacks a compiler, then just pick glibc.
+       # We could probably try harder.
+       LIBC=gnu
+
+       eval $set_cc_for_build
+       cat <<-EOF > $dummy.c
+       #include <features.h>
+       #if defined(__UCLIBC__)
+       LIBC=uclibc
+       #elif defined(__dietlibc__)
+       LIBC=dietlibc
+       #else
+       LIBC=gnu
+       #endif
+       EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+       ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep -q __ELF__
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:Bitrig:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+       exitcode=$?
+       trap '' 0
+       exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+       echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    s390x:SunOS:*:*)
+       echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+       echo i386-pc-auroraux${UNAME_RELEASE}
+       exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+       eval $set_cc_for_build
+       SUN_ARCH="i386"
+       # If there is a compiler, see if it is configured for 64-bit objects.
+       # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+       # This test works for both compilers.
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               SUN_ARCH="x86_64"
+           fi
+       fi
+       echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+       echo m68k-milan-mint${UNAME_RELEASE}
+       exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+       echo m68k-hades-mint${UNAME_RELEASE}
+       exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+       echo m68k-unknown-mint${UNAME_RELEASE}
+       exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+       # DG/UX returns AViiON for all architectures
+       UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[4567])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                   sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                   case "${sc_cpu_version}" in
+                     523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                     528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                     532)                      # CPU_PA_RISC2_0
+                       case "${sc_kernel_bits}" in
+                         32) HP_ARCH="hppa2.0n" ;;
+                         64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                       esac ;;
+                   esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^            //' << EOF >$dummy.c
+
+               #define _HPUX_SOURCE
+               #include <stdlib.h>
+               #include <unistd.h>
+
+               int main ()
+               {
+               #if defined(_SC_KERNEL_BITS)
+                   long bits = sysconf(_SC_KERNEL_BITS);
+               #endif
+                   long cpu  = sysconf (_SC_CPU_VERSION);
+
+                   switch (cpu)
+                       {
+                       case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+                       case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+                       case CPU_PA_RISC2_0:
+               #if defined(_SC_KERNEL_BITS)
+                           switch (bits)
+                               {
+                               case 64: puts ("hppa2.0w"); break;
+                               case 32: puts ("hppa2.0n"); break;
+                               default: puts ("hppa2.0"); break;
+                               } break;
+               #else  /* !defined(_SC_KERNEL_BITS) */
+                           puts ("hppa2.0"); break;
+               #endif
+                       default: puts ("hppa1.0"); break;
+                       }
+                   exit (0);
+               }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep -q __LP64__
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+       exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+       exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+       exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+       exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+       FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+       echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    5000:UNIX_System_V:4.*:*)
+       FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+       FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+       echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       UNAME_PROCESSOR=`/usr/bin/uname -p`
+       case ${UNAME_PROCESSOR} in
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW64*:*)
+       echo ${UNAME_MACHINE}-pc-mingw64
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:MSYS*:*)
+       echo ${UNAME_MACHINE}-pc-msys
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:*)
+       case ${UNAME_MACHINE} in
+           x86)
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           authenticamd | genuineintel | EM64T)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+           IA64)
+               echo ia64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    8664:Windows_NT:*)
+       echo x86_64-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    aarch64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    aarch64_be:Linux:*:*)
+       UNAME_MACHINE=aarch64_be
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+       esac
+       objdump --private-headers /bin/sh | grep -q ld.so.1
+       if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    arm*:Linux:*:*)
+       eval $set_cc_for_build
+       if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+           | grep -q __ARM_EABI__
+       then
+           echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       else
+           if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+               | grep -q __ARM_PCS_VFP
+           then
+               echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+           else
+               echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+           fi
+       fi
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    cris:Linux:*:*)
+       echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+       exit ;;
+    crisv32:Linux:*:*)
+       echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+       exit ;;
+    frv:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    hexagon:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    i*86:Linux:*:*)
+       echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef ${UNAME_MACHINE}
+       #undef ${UNAME_MACHINE}el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=${UNAME_MACHINE}el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=${UNAME_MACHINE}
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+       ;;
+    or1k:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    or32:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    padre:Linux:*:*)
+       echo sparc-unknown-linux-${LIBC}
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-${LIBC}
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+         PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+         *)    echo hppa-unknown-linux-${LIBC} ;;
+       esac
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-${LIBC}
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-${LIBC}
+       exit ;;
+    ppc64le:Linux:*:*)
+       echo powerpc64le-unknown-linux-${LIBC}
+       exit ;;
+    ppcle:Linux:*:*)
+       echo powerpcle-unknown-linux-${LIBC}
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    tile*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+       exit ;;
+    x86_64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    xtensa*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+       # Unixware is an offshoot of SVR4, but it has its own version
+       # number series starting with 2...
+       # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+       # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+       # uname -m prints for DJGPP always 'pc', but it prints nothing about
+       # the processor, so we play safe by assuming i586.
+       # Note: whatever this is, it MUST be the same as what config.sub
+       # prints for the "djgpp" host, or else GDB configury will decide that
+       # this is a cross-build.
+       echo i586-pc-msdosdjgpp
+       exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+       OS_REL='.3'
+       test -r /etc/.relid \
+           && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+           && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*)  # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                       # says <Richard.M.Bartel@ccMail.Census.GOV>
+       echo i586-unisys-sysv4
+       exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+       exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    BePC:Haiku:*:*)    # Haiku running on Intel PC compatible.
+       echo i586-pc-haiku
+       exit ;;
+    x86_64:Haiku:*:*)
+       echo x86_64-unknown-haiku
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       eval $set_cc_for_build
+       if test "$UNAME_PROCESSOR" = unknown ; then
+           UNAME_PROCESSOR=powerpc
+       fi
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               case $UNAME_PROCESSOR in
+                   i386) UNAME_PROCESSOR=x86_64 ;;
+                   powerpc) UNAME_PROCESSOR=powerpc64 ;;
+               esac
+           fi
+       fi
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+       echo neo-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+       echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+    i*86:AROS:*:*)
+       echo ${UNAME_MACHINE}-pc-aros
+       exit ;;
+    x86_64:VMkernel:*:*)
+       echo ${UNAME_MACHINE}-unknown-esx
+       exit ;;
+esac
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+       "4"
+#else
+       ""
+#endif
+       ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/libltdl/config/config.sub b/libltdl/config/config.sub
new file mode 100755 (executable)
index 0000000..9633db7
--- /dev/null
@@ -0,0 +1,1791 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright 1992-2013 Free Software Foundation, Inc.
+
+timestamp='2013-08-10'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches with a ChangeLog entry to config-patches@gnu.org.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2013 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis | -knuth | -cray | -microblaze*)
+               os=
+               basic_machine=$1
+               ;;
+       -bluegene*)
+               os=-cnk
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*178)
+               os=-lynxos178
+               ;;
+       -lynx*5)
+               os=-lynxos5
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | aarch64 | aarch64_be \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arceb \
+       | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+       | avr | avr32 \
+       | be32 | be64 \
+       | bfin \
+       | c4x | c8051 | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | epiphany \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | hexagon \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | le32 | le64 \
+       | lm32 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64octeon | mips64octeonel \
+       | mips64orion | mips64orionel \
+       | mips64r5900 | mips64r5900el \
+       | mips64vr | mips64vrel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipsr5900 | mipsr5900el \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | moxie \
+       | mt \
+       | msp430 \
+       | nds32 | nds32le | nds32be \
+       | nios | nios2 | nios2eb | nios2el \
+       | ns16k | ns32k \
+       | open8 \
+       | or1k | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle \
+       | pyramid \
+       | rl78 | rx \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu \
+       | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+       | ubicom32 \
+       | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+       | we32k \
+       | x86 | xc16x | xstormy16 | xtensa \
+       | z8k | z80)
+               basic_machine=$basic_machine-unknown
+               ;;
+       c54x)
+               basic_machine=tic54x-unknown
+               ;;
+       c55x)
+               basic_machine=tic55x-unknown
+               ;;
+       c6x)
+               basic_machine=tic6x-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       strongarm | thumb | xscale)
+               basic_machine=arm-unknown
+               ;;
+       xgate)
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       xscaleeb)
+               basic_machine=armeb-unknown
+               ;;
+
+       xscaleel)
+               basic_machine=armel-unknown
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | aarch64-* | aarch64_be-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* | avr32-* \
+       | be32-* | be64-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* \
+       | c8051-* | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | hexagon-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | le32-* | le64-* \
+       | lm32-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+       | microblaze-* | microblazeel-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64octeon-* | mips64octeonel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64r5900-* | mips64r5900el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipsr5900-* | mipsr5900el-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nds32-* | nds32le-* | nds32be-* \
+       | nios-* | nios2-* | nios2eb-* | nios2el-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | open8-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+       | pyramid-* \
+       | rl78-* | romp-* | rs6000-* | rx-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+       | tahoe-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+       | tile*-* \
+       | tron-* \
+       | ubicom32-* \
+       | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+       | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* \
+       | xstormy16-* | xtensa*-* \
+       | ymp-* \
+       | z8k-* | z80-*)
+               ;;
+       # Recognize the basic CPU types without company name, with glob match.
+       xtensa*)
+               basic_machine=$basic_machine-unknown
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aros)
+               basic_machine=i386-pc
+               os=-aros
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       blackfin)
+               basic_machine=bfin-unknown
+               os=-linux
+               ;;
+       blackfin-*)
+               basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       bluegene*)
+               basic_machine=powerpc-ibm
+               os=-cnk
+               ;;
+       c54x-*)
+               basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       c55x-*)
+               basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       c6x-*)
+               basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       cegcc)
+               basic_machine=arm-unknown
+               os=-cegcc
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16 | cr16-*)
+               basic_machine=cr16-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dicos)
+               basic_machine=i686-pc
+               os=-dicos
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m68knommu)
+               basic_machine=m68k-unknown
+               os=-linux
+               ;;
+       m68knommu-*)
+               basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       microblaze*)
+               basic_machine=microblaze-xilinx
+               ;;
+       mingw64)
+               basic_machine=x86_64-pc
+               os=-mingw64
+               ;;
+       mingw32)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       mingw32ce)
+               basic_machine=arm-unknown
+               os=-mingw32ce
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       msys)
+               basic_machine=i686-pc
+               os=-msys
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       nacl)
+               basic_machine=le32-unknown
+               os=-nacl
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       neo-tandem)
+               basic_machine=neo-tandem
+               ;;
+       nse-tandem)
+               basic_machine=nse-tandem
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       parisc)
+               basic_machine=hppa-unknown
+               os=-linux
+               ;;
+       parisc-*)
+               basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc | ppcbe)    basic_machine=powerpc-unknown
+               ;;
+       ppc-* | ppcbe-*)
+               basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rdos | rdos64)
+               basic_machine=x86_64-pc
+               os=-rdos
+               ;;
+       rdos32)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       strongarm-* | thumb-*)
+               basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tile*)
+               basic_machine=$basic_machine-unknown
+               os=-linux-gnu
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       xscale-* | xscalee[bl]-*)
+               basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       z80-*-coff)
+               basic_machine=z80-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+       # First match some system type aliases
+       # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -auroraux)
+               os=-auroraux
+               ;;
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+             | -sym* | -kopensolaris* | -plan9* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* | -aros* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -bitrig* | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* | -cegcc* \
+             | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+             | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+       -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+       -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -dicos*)
+               os=-dicos
+               ;;
+       -nacl*)
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+       score-*)
+               os=-elf
+               ;;
+       spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+       c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       c8051-*)
+               os=-elf
+               ;;
+       hexagon-*)
+               os=-elf
+               ;;
+       tic54x-*)
+               os=-coff
+               ;;
+       tic55x-*)
+               os=-coff
+               ;;
+       tic6x-*)
+               os=-coff
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+       mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or1k-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -cnk*|-aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/libltdl/config/depcomp b/libltdl/config/depcomp
new file mode 100755 (executable)
index 0000000..4ebd5b3
--- /dev/null
@@ -0,0 +1,791 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2013-05-30.07; # UTC
+
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+    echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+    exit 1;
+    ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputting dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'.  Note that this directory component will
+# be either empty or ending with a '/' character.  This is deliberate.
+set_dir_from ()
+{
+  case $1 in
+    */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+      *) dir=;;
+  esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+  base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+  echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+  # If the compiler actually managed to produce a dependency file,
+  # post-process it.
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form 'foo.o: dependency.h'.
+    # Do two passes, one to just change these to
+    #   $object: dependency.h
+    # and one to simply output
+    #   dependency.h:
+    # which is needed to avoid the deleted-header problem.
+    { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+      sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+    } > "$depfile"
+    rm -f "$tmpdepfile"
+  else
+    make_dummy_depfile
+  fi
+}
+
+# A tabulation character.
+tab='  '
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+  # This is just like dashmstdout with a different argument.
+  dashmflag=-xM
+  depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+  # This is just like msvisualcpp but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+  # This is just like msvc7 but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+  # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+  gccflag=-qmakedep=gcc,-MF
+  depmode=gcc
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).  Also, it might not be
+##   supported by the other compilers which use the 'gcc' depmode.
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The second -e expression handles DOS-style file names with drive
+  # letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the "deleted header file" problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+## Some versions of gcc put a space before the ':'.  On the theory
+## that the space means something, we add a space to the output as
+## well.  hp depmode also adds that space, but also prefixes the VPATH
+## to the object.  Take care to not repeat it in the output.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like '#:fec' to the end of the
+    # dependency line.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+      | tr "$nl" ' ' >> "$depfile"
+    echo >> "$depfile"
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+      >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  set_dir_from "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  aix_post_process_depfile
+  ;;
+
+tcc)
+  # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+  # FIXME: That version still under development at the moment of writing.
+  #        Make that this statement remains true also for stable, released
+  #        versions.
+  # It will wrap lines (doesn't matter whether long or short) with a
+  # trailing '\', as in:
+  #
+  #   foo.o : \
+  #    foo.c \
+  #    foo.h \
+  #
+  # It will put a trailing '\' even on the last line, and will use leading
+  # spaces rather than leading tabs (at least since its commit 0394caf7
+  # "Emit spaces for -MD").
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+  # We have to change lines of the first kind to '$object: \'.
+  sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+  # And for each line of the second kind, we have to emit a 'dep.h:'
+  # dummy dependency, to avoid the deleted-header problem.
+  sed -n -e 's|^  *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file.  A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+  # Portland's C compiler understands '-MD'.
+  # Will always output deps to 'file.d' where file is the root name of the
+  # source file under compilation, even if file resides in a subdirectory.
+  # The object file name does not affect the name of the '.d' file.
+  # pgcc 10.2 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using '\' :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+  set_dir_from "$object"
+  # Use the source, not the object, to determine the base name, since
+  # that's sadly what pgcc will do too.
+  set_base_from "$source"
+  tmpdepfile=$base.d
+
+  # For projects that build the same source file twice into different object
+  # files, the pgcc approach of using the *source* file root name can cause
+  # problems in parallel builds.  Use a locking strategy to avoid stomping on
+  # the same $tmpdepfile.
+  lockdir=$base.d-lock
+  trap "
+    echo '$0: caught signal, cleaning up...' >&2
+    rmdir '$lockdir'
+    exit 1
+  " 1 2 13 15
+  numtries=100
+  i=$numtries
+  while test $i -gt 0; do
+    # mkdir is a portable test-and-set.
+    if mkdir "$lockdir" 2>/dev/null; then
+      # This process acquired the lock.
+      "$@" -MD
+      stat=$?
+      # Release the lock.
+      rmdir "$lockdir"
+      break
+    else
+      # If the lock is being held by a different process, wait
+      # until the winning process is done or we timeout.
+      while test -d "$lockdir" && test $i -gt 0; do
+        sleep 1
+        i=`expr $i - 1`
+      done
+    fi
+    i=`expr $i - 1`
+  done
+  trap - 1 2 13 15
+  if test $i -le 0; then
+    echo "$0: failed to acquire lock after $numtries attempts" >&2
+    echo "$0: check lockdir '$lockdir'" >&2
+    exit 1
+  fi
+
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  set_dir_from  "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add 'dependent.h:' lines.
+    sed -ne '2,${
+               s/^ *//
+               s/ \\*$//
+               s/$/:/
+               p
+             }' "$tmpdepfile" >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+  # The Tru64 compiler uses -MD to generate dependencies as a side
+  # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+  # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+  # dependencies in 'foo.d' instead, so we check for that too.
+  # Subdirectories are respected.
+  set_dir_from  "$object"
+  set_base_from "$object"
+
+  if test "$libtool" = yes; then
+    # Libtool generates 2 separate objects for the 2 libraries.  These
+    # two compilations output dependencies in $dir.libs/$base.o.d and
+    # in $dir$base.o.d.  We have to check for both files, because
+    # one of the two compilations can be disabled.  We should prefer
+    # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+    # automatically cleaned when .libs/ is deleted, while ignoring
+    # the former would cause a distcleancheck panic.
+    tmpdepfile1=$dir$base.o.d          # libtool 1.5
+    tmpdepfile2=$dir.libs/$base.o.d    # Likewise.
+    tmpdepfile3=$dir.libs/$base.d      # Compaq CCC V6.2-504
+    "$@" -Wc,-MD
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    tmpdepfile3=$dir$base.d
+    "$@" -MD
+  fi
+
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  # Same post-processing that is required for AIX mode.
+  aix_post_process_depfile
+  ;;
+
+msvc7)
+  if test "$libtool" = yes; then
+    showIncludes=-Wc,-showIncludes
+  else
+    showIncludes=-showIncludes
+  fi
+  "$@" $showIncludes > "$tmpdepfile"
+  stat=$?
+  grep -v '^Note: including file: ' "$tmpdepfile"
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The first sed program below extracts the file names and escapes
+  # backslashes for cygpath.  The second sed program outputs the file
+  # name when reading, but also accumulates all include files in the
+  # hold buffer in order to output them again at the end.  This only
+  # works with sed implementations that can handle large buffers.
+  sed < "$tmpdepfile" -n '
+/^Note: including file:  *\(.*\)/ {
+  s//\1/
+  s/\\/\\\\/g
+  p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+  s/.*/'"$tab"'/
+  G
+  p
+}' >> "$depfile"
+  echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+  rm -f "$tmpdepfile"
+  ;;
+
+msvc7msys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for ':'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
+  "$@" $dashmflag |
+    sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this sed invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  # makedepend may prepend the VPATH from the source file name to the object.
+  # No need to regex-escape $object, excess matching of '.' is harmless.
+  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process the last invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed '1,2d' "$tmpdepfile" \
+    | tr ' ' "$nl" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E \
+    | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+             -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+    | sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+        set fnord "$@"
+        shift
+        shift
+        ;;
+    *)
+        set fnord "$@" "$arg"
+        shift
+        shift
+        ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libltdl/config/install-sh b/libltdl/config/install-sh
new file mode 100755 (executable)
index 0000000..377bb86
--- /dev/null
@@ -0,0 +1,527 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-11-20.07; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# 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
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""       $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+       shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+       case $mode in
+         *' '* | *'    '* | *'
+'*       | *'*'* | *'?'* | *'['*)
+           echo "$0: invalid mode: $mode" >&2
+           exit 1;;
+       esac
+       shift;;
+
+    -o) chowncmd="$chownprog $2"
+       shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+       # Protect names problematic for 'test' and other utilities.
+       case $dst_arg in
+         -* | [=\(\)!]) dst_arg=./$dst_arg;;
+       esac
+       shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)        shift
+       break;;
+
+    -*)        echo "$0: invalid option: $1" >&2
+       exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+    # Protect names problematic for 'test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call 'install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names problematic for 'test' and other utilities.
+  case $src in
+    -* | [=\(\)!]) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+    dst=$dst_arg
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+       echo "$0: $dst_arg: Is a directory" >&2
+       exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+       (dirname "$dst") 2>/dev/null ||
+       expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+            X"$dst" : 'X\(//\)[^/]' \| \
+            X"$dst" : 'X\(//\)$' \| \
+            X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+       echo X"$dst" |
+           sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)[^/].*/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\).*/{
+                  s//\1/
+                  q
+                }
+                s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+       # Create intermediate dirs using mode 755 as modified by the umask.
+       # This is like FreeBSD 'install' as of 1997-10-28.
+       umask=`umask`
+       case $stripcmd.$umask in
+         # Optimize common cases.
+         *[2367][2367]) mkdir_umask=$umask;;
+         .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+         *[0-7])
+           mkdir_umask=`expr $umask + 22 \
+             - $umask % 100 % 40 + $umask % 20 \
+             - $umask % 10 % 4 + $umask % 2
+           `;;
+         *) mkdir_umask=$umask,go-w;;
+       esac
+
+       # With -d, create the new directory with the user-specified mode.
+       # Otherwise, rely on $mkdir_umask.
+       if test -n "$dir_arg"; then
+         mkdir_mode=-m$mode
+       else
+         mkdir_mode=
+       fi
+
+       posix_mkdir=false
+       case $umask in
+         *[123567][0-7][0-7])
+           # POSIX mkdir -p sets u+wx bits regardless of umask, which
+           # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+           ;;
+         *)
+           tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+           trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+           if (umask $mkdir_umask &&
+               exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+           then
+             if test -z "$dir_arg" || {
+                  # Check for POSIX incompatibilities with -m.
+                  # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                  # other-writable bit of parent directory when it shouldn't.
+                  # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                  ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                  case $ls_ld_tmpdir in
+                    d????-?r-*) different_mode=700;;
+                    d????-?--*) different_mode=755;;
+                    *) false;;
+                  esac &&
+                  $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                    ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                    test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                  }
+                }
+             then posix_mkdir=:
+             fi
+             rmdir "$tmpdir/d" "$tmpdir"
+           else
+             # Remove any dirs left behind by ancient mkdir implementations.
+             rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+           fi
+           trap '' 0;;
+       esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+       umask $mkdir_umask &&
+       $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+       /*) prefix='/';;
+       [-=\(\)!]*) prefix='./';;
+       *)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+       test X"$d" = X && continue
+
+       prefix=$prefix$d
+       if test -d "$prefix"; then
+         prefixes=
+       else
+         if $posix_mkdir; then
+           (umask=$mkdir_umask &&
+            $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+           # Don't fail if two instances are running concurrently.
+           test -d "$prefix" || exit 1
+         else
+           case $prefix in
+             *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+             *) qprefix=$prefix;;
+           esac
+           prefixes="$prefixes '$qprefix'"
+         fi
+       fi
+       prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+       # Don't fail if two instances are running concurrently.
+       (umask $mkdir_umask &&
+        eval "\$doit_exec \$mkdirprog $prefixes") ||
+         test -d "$dstdir" || exit 1
+       obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"    2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+       # Now remove or move aside any old file at destination location.
+       # We try this two ways since rm can't unlink itself on some
+       # systems and the destination file might be busy for other
+       # reasons.  In this case, the final cleanup might fail but the new
+       # file should still install successfully.
+       {
+         test ! -f "$dst" ||
+         $doit $rmcmd -f "$dst" 2>/dev/null ||
+         { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+           { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+         } ||
+         { echo "$0: cannot unlink or rename $dst" >&2
+           (exit 1); exit 1
+         }
+       } &&
+
+       # Now rename the file to the real destination.
+       $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libltdl/config/ltmain.sh b/libltdl/config/ltmain.sh
new file mode 100644 (file)
index 0000000..a356aca
--- /dev/null
@@ -0,0 +1,9661 @@
+
+# libtool (GNU libtool) 2.4.2
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
+# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#       --config             show all configuration variables
+#       --debug              enable verbose shell tracing
+#   -n, --dry-run            display commands without modifying any files
+#       --features           display basic configuration information and exit
+#       --mode=MODE          use operation mode MODE
+#       --preserve-dup-deps  don't remove duplicate dependency libraries
+#       --quiet, --silent    don't print informational messages
+#       --no-quiet, --no-silent
+#                            print informational messages (default)
+#       --no-warn            don't display warning messages
+#       --tag=TAG            use configuration variables from tag TAG
+#   -v, --verbose            print more informational messages than default
+#       --no-verbose         don't print the extra informational messages
+#       --version            print version information
+#   -h, --help, --help-all   print short, long, or detailed help message
+#
+# MODE must be one of the following:
+#
+#         clean              remove files from the build directory
+#         compile            compile a source file into a libtool object
+#         execute            automatically set library path, then run a program
+#         finish             complete the installation of libtool libraries
+#         install            install libraries or executables
+#         link               create a library or an executable
+#         uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.  When passed as first option,
+# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#         host-triplet:        $host
+#         shell:               $SHELL
+#         compiler:            $LTCC
+#         compiler flags:              $LTCFLAGS
+#         linker:              $LD (gnu? $with_gnu_ld)
+#         $progname:   (GNU libtool) 2.4.2 Debian-2.4.2-1.7ubuntu1
+#         automake:    $automake_version
+#         autoconf:    $autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+# GNU libtool home page: <http://www.gnu.org/software/libtool/>.
+# General help using GNU software: <http://www.gnu.org/gethelp/>.
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION="2.4.2 Debian-2.4.2-1.7ubuntu1"
+TIMESTAMP=""
+package_revision=1.3337
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# NLS nuisances: We save the old values to restore during execute mode.
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+         export $lt_var
+         lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+         lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+       fi"
+done
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
+
+$lt_unset CDPATH
+
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+
+
+: ${CP="cp -f"}
+test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77     # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS="  $lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname file append nondir_replacement
+# Compute the dirname of FILE.  If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+func_dirname ()
+{
+    func_dirname_result=`$ECHO "${1}" | $SED "$dirname"`
+    if test "X$func_dirname_result" = "X${1}"; then
+      func_dirname_result="${3}"
+    else
+      func_dirname_result="$func_dirname_result${2}"
+    fi
+} # func_dirname may be replaced by extended shell implementation
+
+
+# func_basename file
+func_basename ()
+{
+    func_basename_result=`$ECHO "${1}" | $SED "$basename"`
+} # func_basename may be replaced by extended shell implementation
+
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+    # Extract subdirectory from the argument.
+    func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"`
+    if test "X$func_dirname_result" = "X${1}"; then
+      func_dirname_result="${3}"
+    else
+      func_dirname_result="$func_dirname_result${2}"
+    fi
+    func_basename_result=`$ECHO "${1}" | $SED -e "$basename"`
+} # func_dirname_and_basename may be replaced by extended shell implementation
+
+
+# func_stripname prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+# func_strip_suffix prefix name
+func_stripname ()
+{
+    case ${2} in
+      .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+      *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+    esac
+} # func_stripname may be replaced by extended shell implementation
+
+
+# These SED scripts presuppose an absolute path with a trailing slash.
+pathcar='s,^/\([^/]*\).*$,\1,'
+pathcdr='s,^/[^/]*,,'
+removedotparts=':dotsl
+               s@/\./@/@g
+               t dotsl
+               s,/\.$,/,'
+collapseslashes='s@/\{1,\}@/@g'
+finalslash='s,/*$,/,'
+
+# func_normal_abspath PATH
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+#             value returned in "$func_normal_abspath_result"
+func_normal_abspath ()
+{
+  # Start from root dir and reassemble the path.
+  func_normal_abspath_result=
+  func_normal_abspath_tpath=$1
+  func_normal_abspath_altnamespace=
+  case $func_normal_abspath_tpath in
+    "")
+      # Empty path, that just means $cwd.
+      func_stripname '' '/' "`pwd`"
+      func_normal_abspath_result=$func_stripname_result
+      return
+    ;;
+    # The next three entries are used to spot a run of precisely
+    # two leading slashes without using negated character classes;
+    # we take advantage of case's first-match behaviour.
+    ///*)
+      # Unusual form of absolute path, do nothing.
+    ;;
+    //*)
+      # Not necessarily an ordinary path; POSIX reserves leading '//'
+      # and for example Cygwin uses it to access remote file shares
+      # over CIFS/SMB, so we conserve a leading double slash if found.
+      func_normal_abspath_altnamespace=/
+    ;;
+    /*)
+      # Absolute path, do nothing.
+    ;;
+    *)
+      # Relative path, prepend $cwd.
+      func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+    ;;
+  esac
+  # Cancel out all the simple stuff to save iterations.  We also want
+  # the path to end with a slash for ease of parsing, so make sure
+  # there is one (and only one) here.
+  func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"`
+  while :; do
+    # Processed it all yet?
+    if test "$func_normal_abspath_tpath" = / ; then
+      # If we ascended to the root using ".." the result may be empty now.
+      if test -z "$func_normal_abspath_result" ; then
+        func_normal_abspath_result=/
+      fi
+      break
+    fi
+    func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcar"`
+    func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+        -e "$pathcdr"`
+    # Figure out what to do with it
+    case $func_normal_abspath_tcomponent in
+      "")
+        # Trailing empty path component, ignore it.
+      ;;
+      ..)
+        # Parent dir; strip last assembled component from result.
+        func_dirname "$func_normal_abspath_result"
+        func_normal_abspath_result=$func_dirname_result
+      ;;
+      *)
+        # Actual path component, append it.
+        func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent
+      ;;
+    esac
+  done
+  # Restore leading double-slash if one was found on entry.
+  func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+# func_relative_path SRCDIR DSTDIR
+# generates a relative path from SRCDIR to DSTDIR, with a trailing
+# slash if non-empty, suitable for immediately appending a filename
+# without needing to append a separator.
+#             value returned in "$func_relative_path_result"
+func_relative_path ()
+{
+  func_relative_path_result=
+  func_normal_abspath "$1"
+  func_relative_path_tlibdir=$func_normal_abspath_result
+  func_normal_abspath "$2"
+  func_relative_path_tbindir=$func_normal_abspath_result
+
+  # Ascend the tree starting from libdir
+  while :; do
+    # check if we have found a prefix of bindir
+    case $func_relative_path_tbindir in
+      $func_relative_path_tlibdir)
+        # found an exact match
+        func_relative_path_tcancelled=
+        break
+        ;;
+      $func_relative_path_tlibdir*)
+        # found a matching prefix
+        func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+        func_relative_path_tcancelled=$func_stripname_result
+        if test -z "$func_relative_path_result"; then
+          func_relative_path_result=.
+        fi
+        break
+        ;;
+      *)
+        func_dirname $func_relative_path_tlibdir
+        func_relative_path_tlibdir=${func_dirname_result}
+        if test "x$func_relative_path_tlibdir" = x ; then
+          # Have to descend all the way to the root!
+          func_relative_path_result=../$func_relative_path_result
+          func_relative_path_tcancelled=$func_relative_path_tbindir
+          break
+        fi
+        func_relative_path_result=../$func_relative_path_result
+        ;;
+    esac
+  done
+
+  # Now calculate path; take care to avoid doubling-up slashes.
+  func_stripname '' '/' "$func_relative_path_result"
+  func_relative_path_result=$func_stripname_result
+  func_stripname '/' '/' "$func_relative_path_tcancelled"
+  if test "x$func_stripname_result" != x ; then
+    func_relative_path_result=${func_relative_path_result}/${func_stripname_result}
+  fi
+
+  # Normalisation. If bindir is libdir, return empty string,
+  # else relative path ending with a slash; either way, target
+  # file name can be directly appended.
+  if test ! -z "$func_relative_path_result"; then
+    func_stripname './' '' "$func_relative_path_result/"
+    func_relative_path_result=$func_stripname_result
+  fi
+}
+
+# The name of this program:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=${PATH_SEPARATOR-:}
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s,[].[^$\\*\/],\\&,g'
+
+# Sed substitution that converts a w32 file name or path
+# which contains forward slashes, into one that contains
+# (escaped) backslashes.  A very naive implementation.
+lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname: ${opt_mode+$opt_mode: }$*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*"
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+       # list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+       IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "$my_tmpdir"
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+       func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+       my_arg=`$ECHO "$1" | $SED \
+           -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+       eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+           $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+       eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+# func_tr_sh
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result.  All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+  case $1 in
+  [0-9]* | *[!a-zA-Z0-9_]*)
+    func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'`
+    ;;
+  * )
+    func_tr_sh_result=$1
+    ;;
+  esac
+}
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $opt_debug
+
+    $SED -n '/(C)/!b go
+       :more
+       /\./!{
+         N
+         s/\n# / /
+         b more
+       }
+       :go
+       /^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+       s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $opt_debug
+
+    $SED -n '/^# Usage:/,/^#  *.*--help/ {
+        s/^# //
+       s/^# *$//
+       s/\$progname/'$progname'/
+       p
+    }' < "$progpath"
+    echo
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help [NOEXIT]
+# Echo long help message to standard output and exit,
+# unless 'noexit' is passed as argument.
+func_help ()
+{
+    $opt_debug
+
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+       :print
+        s/^# //
+       s/^# *$//
+       s*\$progname*'$progname'*
+       s*\$host*'"$host"'*
+       s*\$SHELL*'"$SHELL"'*
+       s*\$LTCC*'"$LTCC"'*
+       s*\$LTCFLAGS*'"$LTCFLAGS"'*
+       s*\$LD*'"$LD"'*
+       s/\$with_gnu_ld/'"$with_gnu_ld"'/
+       s/\$automake_version/'"`(${AUTOMAKE-automake} --version) 2>/dev/null |$SED 1q`"'/
+       s/\$autoconf_version/'"`(${AUTOCONF-autoconf} --version) 2>/dev/null |$SED 1q`"'/
+       p
+       d
+     }
+     /^# .* home page:/b print
+     /^# General help using/b print
+     ' < "$progpath"
+    ret=$?
+    if test -z "$1"; then
+      exit $ret
+    fi
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    $opt_debug
+
+    func_error "missing argument for $1."
+    exit_cmd=exit
+}
+
+
+# func_split_short_opt shortopt
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+func_split_short_opt ()
+{
+    my_sed_short_opt='1s/^\(..\).*$/\1/;q'
+    my_sed_short_rest='1s/^..\(.*\)$/\1/;q'
+
+    func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"`
+    func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"`
+} # func_split_short_opt may be replaced by extended shell implementation
+
+
+# func_split_long_opt longopt
+# Set func_split_long_opt_name and func_split_long_opt_arg shell
+# variables after splitting LONGOPT at the `=' sign.
+func_split_long_opt ()
+{
+    my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q'
+    my_sed_long_arg='1s/^--[^=]*=//'
+
+    func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"`
+    func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"`
+} # func_split_long_opt may be replaced by extended shell implementation
+
+exit_cmd=:
+
+
+
+
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+nonopt=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_append var value
+# Append VALUE to the end of shell variable VAR.
+func_append ()
+{
+    eval "${1}=\$${1}\${2}"
+} # func_append may be replaced by extended shell implementation
+
+# func_append_quoted var value
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+func_append_quoted ()
+{
+    func_quote_for_eval "${2}"
+    eval "${1}=\$${1}\\ \$func_quote_for_eval_result"
+} # func_append_quoted may be replaced by extended shell implementation
+
+
+# func_arith arithmetic-term...
+func_arith ()
+{
+    func_arith_result=`expr "${@}"`
+} # func_arith may be replaced by extended shell implementation
+
+
+# func_len string
+# STRING may not start with a hyphen.
+func_len ()
+{
+    func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len`
+} # func_len may be replaced by extended shell implementation
+
+
+# func_lo2o object
+func_lo2o ()
+{
+    func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"`
+} # func_lo2o may be replaced by extended shell implementation
+
+
+# func_xform libobj-or-source
+func_xform ()
+{
+    func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'`
+} # func_xform may be replaced by extended shell implementation
+
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    echo "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      echo "enable shared libraries"
+    else
+      echo "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      echo "enable static libraries"
+    else
+      echo "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+       taglist="$taglist $tagname"
+
+       # Evaluate the configuration.  Be careful to quote the path
+       # and the sed script, to avoid splitting on whitespace, but
+       # also don't use non-portable quotes within backquotes within
+       # quotes we have to do it in 2 steps:
+       extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+       eval "$extractedcf"
+      else
+       func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+# Shorthand for --mode=foo, only valid as the first argument
+case $1 in
+clean|clea|cle|cl)
+  shift; set dummy --mode clean ${1+"$@"}; shift
+  ;;
+compile|compil|compi|comp|com|co|c)
+  shift; set dummy --mode compile ${1+"$@"}; shift
+  ;;
+execute|execut|execu|exec|exe|ex|e)
+  shift; set dummy --mode execute ${1+"$@"}; shift
+  ;;
+finish|finis|fini|fin|fi|f)
+  shift; set dummy --mode finish ${1+"$@"}; shift
+  ;;
+install|instal|insta|inst|ins|in|i)
+  shift; set dummy --mode install ${1+"$@"}; shift
+  ;;
+link|lin|li|l)
+  shift; set dummy --mode link ${1+"$@"}; shift
+  ;;
+uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+  shift; set dummy --mode uninstall ${1+"$@"}; shift
+  ;;
+esac
+
+
+
+# Option defaults:
+opt_debug=:
+opt_dry_run=false
+opt_config=false
+opt_preserve_dup_deps=false
+opt_features=false
+opt_finish=false
+opt_help=false
+opt_help_all=false
+opt_silent=:
+opt_warning=:
+opt_verbose=:
+opt_silent=false
+opt_verbose=false
+
+
+# Parse options once, thoroughly.  This comes as soon as possible in the
+# script to make things like `--version' happen as quickly as we can.
+{
+  # this just eases exit handling
+  while test $# -gt 0; do
+    opt="$1"
+    shift
+    case $opt in
+      --debug|-x)      opt_debug='set -x'
+                       func_echo "enabling shell trace mode"
+                       $opt_debug
+                       ;;
+      --dry-run|--dryrun|-n)
+                       opt_dry_run=:
+                       ;;
+      --config)
+                       opt_config=:
+func_config
+                       ;;
+      --dlopen|-dlopen)
+                       optarg="$1"
+                       opt_dlopen="${opt_dlopen+$opt_dlopen
+}$optarg"
+                       shift
+                       ;;
+      --preserve-dup-deps)
+                       opt_preserve_dup_deps=:
+                       ;;
+      --features)
+                       opt_features=:
+func_features
+                       ;;
+      --finish)
+                       opt_finish=:
+set dummy --mode finish ${1+"$@"}; shift
+                       ;;
+      --help)
+                       opt_help=:
+                       ;;
+      --help-all)
+                       opt_help_all=:
+opt_help=': help-all'
+                       ;;
+      --mode)
+                       test $# = 0 && func_missing_arg $opt && break
+                       optarg="$1"
+                       opt_mode="$optarg"
+case $optarg in
+  # Valid mode arguments:
+  clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+  # Catch anything else as an error
+  *) func_error "invalid argument for $opt"
+     exit_cmd=exit
+     break
+     ;;
+esac
+                       shift
+                       ;;
+      --no-silent|--no-quiet)
+                       opt_silent=false
+func_append preserve_args " $opt"
+                       ;;
+      --no-warning|--no-warn)
+                       opt_warning=false
+func_append preserve_args " $opt"
+                       ;;
+      --no-verbose)
+                       opt_verbose=false
+func_append preserve_args " $opt"
+                       ;;
+      --silent|--quiet)
+                       opt_silent=:
+func_append preserve_args " $opt"
+        opt_verbose=false
+                       ;;
+      --verbose|-v)
+                       opt_verbose=:
+func_append preserve_args " $opt"
+opt_silent=false
+                       ;;
+      --tag)
+                       test $# = 0 && func_missing_arg $opt && break
+                       optarg="$1"
+                       opt_tag="$optarg"
+func_append preserve_args " $opt $optarg"
+func_enable_tag "$optarg"
+                       shift
+                       ;;
+
+      -\?|-h)          func_usage                              ;;
+      --help)          func_help                               ;;
+      --version)       func_version                            ;;
+
+      # Separate optargs to long options:
+      --*=*)
+                       func_split_long_opt "$opt"
+                       set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"}
+                       shift
+                       ;;
+
+      # Separate non-argument short options:
+      -\?*|-h*|-n*|-v*)
+                       func_split_short_opt "$opt"
+                       set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"}
+                       shift
+                       ;;
+
+      --)              break                                   ;;
+      -*)              func_fatal_help "unrecognized option \`$opt'" ;;
+      *)               set dummy "$opt" ${1+"$@"};     shift; break  ;;
+    esac
+  done
+
+  # Validate options:
+
+  # save first non-option argument
+  if test "$#" -gt 0; then
+    nonopt="$opt"
+    shift
+  fi
+
+  # preserve --debug
+  test "$opt_debug" = : || func_append preserve_args " --debug"
+
+  case $host in
+    *cygwin* | *mingw* | *pw32* | *cegcc*)
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
+      ;;
+  esac
+
+  $opt_help || {
+    # Sanity checks first:
+    func_check_version_match
+
+    if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+      func_fatal_configuration "not configured to build any kind of library"
+    fi
+
+    # Darwin sucks
+    eval std_shrext=\"$shrext_cmds\"
+
+    # Only execute mode is allowed to have -dlopen flags.
+    if test -n "$opt_dlopen" && test "$opt_mode" != execute; then
+      func_error "unrecognized option \`-dlopen'"
+      $ECHO "$help" 1>&2
+      exit $EXIT_FAILURE
+    fi
+
+    # Change the help message to a mode-specific one.
+    generic_help="$help"
+    help="Try \`$progname --help --mode=$opt_mode' for more information."
+  }
+
+
+  # Bail if the options were screwed
+  $exit_cmd $EXIT_FAILURE
+}
+
+
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null \
+        | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+       for lalib_p_l in 1 2 3 4
+       do
+           read lalib_p_line
+           case "$lalib_p_line" in
+               \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+           esac
+       done
+       exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_dirname_and_basename "$1" "" "."
+    func_stripname '' '.exe' "$func_basename_result"
+    func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval cmd=\"$cmd\"
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)        . "$1" ;;
+    *)         . "./$1" ;;
+    esac
+}
+
+
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot.  Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+  func_resolve_sysroot_result=$1
+  case $func_resolve_sysroot_result in
+  =*)
+    func_stripname '=' '' "$func_resolve_sysroot_result"
+    func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+    ;;
+  esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+  case "$lt_sysroot:$1" in
+  ?*:"$lt_sysroot"*)
+    func_stripname "$lt_sysroot" '' "$1"
+    func_replace_sysroot_result="=$func_stripname_result"
+    ;;
+  *)
+    # Including no sysroot.
+    func_replace_sysroot_result=$1
+    ;;
+  esac
+}
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+       func_append_quoted CC_quoted "$arg"
+      done
+      CC_expanded=`func_echo_all $CC`
+      CC_quoted_expanded=`func_echo_all $CC_quoted`
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+      " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+       for z in $available_tags; do
+         if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+           # Evaluate the configuration.
+           eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+           CC_quoted=
+           for arg in $CC; do
+             # Double-quote args containing other shell metacharacters.
+             func_append_quoted CC_quoted "$arg"
+           done
+           CC_expanded=`func_echo_all $CC`
+           CC_quoted_expanded=`func_echo_all $CC_quoted`
+           case "$@ " in
+           " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+           " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+             # The compiler in the base compile command matches
+             # the one in the tagged configuration.
+             # Assume this is the tagged configuration we want.
+             tagname=$z
+             break
+             ;;
+           esac
+         fi
+       done
+       # If $tagname still isn't set, then no tagged configuration
+       # was found and let the user know that the "--tag" command
+       # line option must be used.
+       if test -z "$tagname"; then
+         func_echo "unable to infer tagged configuration"
+         func_fatal_error "specify a tag with \`--tag'"
+#      else
+#        func_verbose "using $tagname tagged configuration"
+       fi
+       ;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+
+##################################################
+# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
+##################################################
+
+# func_convert_core_file_wine_to_w32 ARG
+# Helper function used by file name conversion functions when $build is *nix,
+# and $host is mingw, cygwin, or some other w32 environment. Relies on a
+# correctly configured wine environment available, with the winepath program
+# in $build's $PATH.
+#
+# ARG is the $build file name to be converted to w32 format.
+# Result is available in $func_convert_core_file_wine_to_w32_result, and will
+# be empty on error (or when ARG is empty)
+func_convert_core_file_wine_to_w32 ()
+{
+  $opt_debug
+  func_convert_core_file_wine_to_w32_result="$1"
+  if test -n "$1"; then
+    # Unfortunately, winepath does not exit with a non-zero error code, so we
+    # are forced to check the contents of stdout. On the other hand, if the
+    # command is not found, the shell will set an exit code of 127 and print
+    # *an error message* to stdout. So we must check for both error code of
+    # zero AND non-empty stdout, which explains the odd construction:
+    func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
+    if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then
+      func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+        $SED -e "$lt_sed_naive_backslashify"`
+    else
+      func_convert_core_file_wine_to_w32_result=
+    fi
+  fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+  $opt_debug
+  # unfortunately, winepath doesn't convert paths, only file names
+  func_convert_core_path_wine_to_w32_result=""
+  if test -n "$1"; then
+    oldIFS=$IFS
+    IFS=:
+    for func_convert_core_path_wine_to_w32_f in $1; do
+      IFS=$oldIFS
+      func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+      if test -n "$func_convert_core_file_wine_to_w32_result" ; then
+        if test -z "$func_convert_core_path_wine_to_w32_result"; then
+          func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result"
+        else
+          func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+        fi
+      fi
+    done
+    IFS=$oldIFS
+  fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+  $opt_debug
+  if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+    func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+    if test "$?" -ne 0; then
+      # on failure, ensure result is empty
+      func_cygpath_result=
+    fi
+  else
+    func_cygpath_result=
+    func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'"
+  fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format.  Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+  $opt_debug
+  # awkward: cmd appends spaces to result
+  func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+    $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+  $opt_debug
+  if test -z "$2" && test -n "$1" ; then
+    func_error "Could not determine host file name corresponding to"
+    func_error "  \`$1'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback:
+    func_to_host_file_result="$1"
+  fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+  $opt_debug
+  if test -z "$4" && test -n "$3"; then
+    func_error "Could not determine the host path corresponding to"
+    func_error "  \`$3'"
+    func_error "Continuing, but uninstalled executables may not work."
+    # Fallback.  This is a deliberately simplistic "conversion" and
+    # should not be "improved".  See libtool.info.
+    if test "x$1" != "x$2"; then
+      lt_replace_pathsep_chars="s|$1|$2|g"
+      func_to_host_path_result=`echo "$3" |
+        $SED -e "$lt_replace_pathsep_chars"`
+    else
+      func_to_host_path_result="$3"
+    fi
+  fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+  $opt_debug
+  case $4 in
+  $1 ) func_to_host_path_result="$3$func_to_host_path_result"
+    ;;
+  esac
+  case $4 in
+  $2 ) func_append func_to_host_path_result "$3"
+    ;;
+  esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via `$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+  $opt_debug
+  $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result.  If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+  $opt_debug
+  case ,$2, in
+    *,"$to_tool_file_cmd",*)
+      func_to_tool_file_result=$1
+      ;;
+    *)
+      $to_tool_file_cmd "$1"
+      func_to_tool_file_result=$func_to_host_file_result
+      ;;
+  esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+  func_to_host_file_result="$1"
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_msys_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+    # LT_CYGPATH in this case.
+    func_to_host_file_result=`cygpath -m "$1"`
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format.  Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_file_wine_to_w32 "$1"
+    func_to_host_file_result="$func_convert_core_file_wine_to_w32_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    func_convert_core_msys_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_msys_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format.  Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set.  Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_file_result="$1"
+  if test -n "$1"; then
+    # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+    func_convert_core_file_wine_to_w32 "$1"
+    func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+    func_to_host_file_result="$func_cygpath_result"
+  fi
+  func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via `$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format.  If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+#   file name conversion function    : func_convert_file_X_to_Y ()
+#   path conversion function         : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same.  If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+  $opt_debug
+  if test -z "$to_host_path_cmd"; then
+    func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+    to_host_path_cmd="func_convert_path_${func_stripname_result}"
+  fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+  $opt_debug
+  func_init_to_host_path_cmd
+  $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+  func_to_host_path_result="$1"
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper.  Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from ARG.  MSYS
+    # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+    # and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_msys_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format.  Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format.  Requires a wine environment and
+# a working winepath.  Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_to_host_path_result="$func_convert_core_path_wine_to_w32_result"
+    func_convert_path_check : ";" \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+  fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format.  Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # See func_convert_path_msys_to_w32:
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format.  Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set.  Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+  $opt_debug
+  func_to_host_path_result="$1"
+  if test -n "$1"; then
+    # Remove leading and trailing path separator characters from
+    # ARG. msys behavior is inconsistent here, cygpath turns them
+    # into '.;' and ';.', and winepath ignores them completely.
+    func_stripname : : "$1"
+    func_to_host_path_tmp1=$func_stripname_result
+    func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+    func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+    func_to_host_path_result="$func_cygpath_result"
+    func_convert_path_check : : \
+      "$func_to_host_path_tmp1" "$func_to_host_path_result"
+    func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+  fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+       # do not "continue".  Instead, add this to base_compile
+       lastarg="$arg"
+       arg_mode=normal
+       ;;
+
+      target )
+       libobj="$arg"
+       arg_mode=normal
+       continue
+       ;;
+
+      normal )
+       # Accept any command-line options.
+       case $arg in
+       -o)
+         test -n "$libobj" && \
+           func_fatal_error "you cannot specify \`-o' more than once"
+         arg_mode=target
+         continue
+         ;;
+
+       -pie | -fpie | -fPIE)
+          func_append pie_flag " $arg"
+         continue
+         ;;
+
+       -shared | -static | -prefer-pic | -prefer-non-pic)
+         func_append later " $arg"
+         continue
+         ;;
+
+       -no-suppress)
+         suppress_opt=no
+         continue
+         ;;
+
+       -Xcompiler)
+         arg_mode=arg  #  the next one goes into the "base_compile" arg list
+         continue      #  The current "srcfile" will either be retained or
+         ;;            #  replaced later.  I would guess that would be a bug.
+
+       -Wc,*)
+         func_stripname '-Wc,' '' "$arg"
+         args=$func_stripname_result
+         lastarg=
+         save_ifs="$IFS"; IFS=','
+         for arg in $args; do
+           IFS="$save_ifs"
+           func_append_quoted lastarg "$arg"
+         done
+         IFS="$save_ifs"
+         func_stripname ' ' '' "$lastarg"
+         lastarg=$func_stripname_result
+
+         # Add the arguments to base_compile.
+         func_append base_compile " $lastarg"
+         continue
+         ;;
+
+       *)
+         # Accept the current argument as the source file.
+         # The previous "srcfile" becomes the current argument.
+         #
+         lastarg="$srcfile"
+         srcfile="$arg"
+         ;;
+       esac  #  case $arg
+       ;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_append_quoted base_compile "$lastarg"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+       func_basename "$srcfile"
+       libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+       test "$build_libtool_libs" != yes && \
+         func_fatal_configuration "can not build a shared library"
+       build_old_libs=no
+       continue
+       ;;
+
+      -static)
+       build_libtool_libs=no
+       build_old_libs=yes
+       continue
+       ;;
+
+      -prefer-pic)
+       pic_mode=yes
+       continue
+       ;;
+
+      -prefer-non-pic)
+       pic_mode=no
+       continue
+       ;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'   &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+       func_echo "Waiting for $lockfile to be removed"
+       sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+       $ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $opt_dry_run || $RM $removelist
+       exit $EXIT_FAILURE
+      fi
+      func_append removelist " $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    func_append removelist " $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+    srcfile=$func_to_tool_file_result
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+       command="$base_compile $qsrcfile $pic_flag"
+      else
+       # Don't build PIC code
+       command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+       # Place PIC objects in $objdir
+       func_append command " -o $lobj"
+      fi
+
+      func_show_eval_locale "$command" \
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $opt_dry_run || $RM $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+       func_show_eval '$MV "$output_obj" "$lobj"' \
+         'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+       suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+       # Don't build PIC code
+       command="$base_compile $qsrcfile$pie_flag"
+      else
+       command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+       func_append command " -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      func_append command "$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $opt_dry_run || $RM $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+       func_show_eval '$MV "$output_obj" "$obj"' \
+         'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+       removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+  test "$opt_mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $opt_mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to build PIC objects only
+  -prefer-non-pic   try to build non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+  -Wc,FLAG          pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix-dir PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -bindir BINDIR    specify path to binaries directory (for systems where
+                    libraries must be found in the PATH setting at runtime)
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+  -Wc,FLAG
+  -Xcompiler FLAG   pass linker-specific FLAG directly to the compiler
+  -Wl,FLAG
+  -Xlinker FLAG     pass linker-specific FLAG directly to the linker
+  -XCClinker FLAG   pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$opt_mode'"
+        ;;
+    esac
+
+    echo
+    $ECHO "Try \`$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+  if test "$opt_help" = :; then
+    func_mode_help
+  else
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+       func_mode_help
+      done
+    } | sed -n '1p; 2,$s/^Usage:/  or: /p'
+    {
+      func_help noexit
+      for opt_mode in compile link execute install finish uninstall clean; do
+       echo
+       func_mode_help
+      done
+    } |
+    sed '1d
+      /^When reporting/,/^Report/{
+       H
+       d
+      }
+      $x
+      /information about other modes/d
+      /more detailed .*MODE/d
+      s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+  fi
+  exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $opt_dlopen; do
+      test -f "$file" \
+       || func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+       func_resolve_sysroot "$file"
+       file=$func_resolve_sysroot_result
+
+       # Check to see that this really is a libtool archive.
+       func_lalib_unsafe_p "$file" \
+         || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+       # Read the libtool library.
+       dlname=
+       library_names=
+       func_source "$file"
+
+       # Skip this library if it cannot be dlopened.
+       if test -z "$dlname"; then
+         # Warn if it was a shared library.
+         test -n "$library_names" && \
+           func_warning "\`$file' was not linked with \`-export-dynamic'"
+         continue
+       fi
+
+       func_dirname "$file" "" "."
+       dir="$func_dirname_result"
+
+       if test -f "$dir/$objdir/$dlname"; then
+         func_append dir "/$objdir"
+       else
+         if test ! -f "$dir/$dlname"; then
+           func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+         fi
+       fi
+       ;;
+
+      *.lo)
+       # Just add the directory containing the .lo file.
+       func_dirname "$file" "" "."
+       dir="$func_dirname_result"
+       ;;
+
+      *)
+       func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+       continue
+       ;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+       eval "$shlibpath_var=\"\$dir\""
+      else
+       eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -* | *.la | *.lo ) ;;
+      *)
+       # Do a test to see if this is really a libtool program.
+       if func_ltwrapper_script_p "$file"; then
+         func_source "$file"
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       elif func_ltwrapper_executable_p "$file"; then
+         func_ltwrapper_scriptname "$file"
+         func_source "$func_ltwrapper_scriptname_result"
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       fi
+       ;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_append_quoted args "$file"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+       # Export the shlibpath_var.
+       eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+       eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+             else
+               $lt_unset $lt_var
+             fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+       eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+       echo "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$opt_mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libs=
+    libdirs=
+    admincmds=
+
+    for opt in "$nonopt" ${1+"$@"}
+    do
+      if test -d "$opt"; then
+       func_append libdirs " $opt"
+
+      elif test -f "$opt"; then
+       if func_lalib_unsafe_p "$opt"; then
+         func_append libs " $opt"
+       else
+         func_warning "\`$opt' is not a valid libtool archive"
+       fi
+
+      else
+       func_fatal_error "invalid argument \`$opt'"
+      fi
+    done
+
+    if test -n "$libs"; then
+      if test -n "$lt_sysroot"; then
+        sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+        sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+      else
+        sysroot_cmd=
+      fi
+
+      # Remove sysroot references
+      if $opt_dry_run; then
+        for lib in $libs; do
+          echo "removing references to $lt_sysroot and \`=' prefixes from $lib"
+        done
+      else
+        tmpdir=`func_mktempdir`
+        for lib in $libs; do
+         sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+           > $tmpdir/tmp-la
+         mv -f $tmpdir/tmp-la $lib
+       done
+        ${RM}r "$tmpdir"
+      fi
+    fi
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for libdir in $libdirs; do
+       if test -n "$finish_cmds"; then
+         # Do each command in the finish commands.
+         func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+       fi
+       if test -n "$finish_eval"; then
+         # Do the single finish_eval.
+         eval cmds=\"$finish_eval\"
+         $opt_dry_run || eval "$cmds" || func_append admincmds "
+       $cmds"
+       fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      echo "----------------------------------------------------------------------"
+      echo "Libraries have been installed in:"
+      for libdir in $libdirs; do
+       $ECHO "   $libdir"
+      done
+      echo
+      echo "If you ever happen to want to link against installed libraries"
+      echo "in a given directory, LIBDIR, you must either use libtool, and"
+      echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+      echo "flag during linking and do at least one of the following:"
+      if test -n "$shlibpath_var"; then
+       echo "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+       echo "     during execution"
+      fi
+      if test -n "$runpath_var"; then
+       echo "   - add LIBDIR to the \`$runpath_var' environment variable"
+       echo "     during linking"
+      fi
+      if test -n "$hardcode_libdir_flag_spec"; then
+       libdir=LIBDIR
+       eval flag=\"$hardcode_libdir_flag_spec\"
+
+       $ECHO "   - use the \`$flag' linker flag"
+      fi
+      if test -n "$admincmds"; then
+       $ECHO "   - have your system administrator run these commands:$admincmds"
+      fi
+      if test -f /etc/ld.so.conf; then
+       echo "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+      fi
+      echo
+
+      echo "See any operating system documentation about shared libraries for"
+      case $host in
+       solaris2.[6789]|solaris2.1[0-9])
+         echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+         echo "pages."
+         ;;
+       *)
+         echo "more information, such as the ld(1) and ld.so(8) manual pages."
+         ;;
+      esac
+      echo "----------------------------------------------------------------------"
+    fi
+    exit $EXIT_SUCCESS
+}
+
+test "$opt_mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       case $nonopt in *shtool*) :;; *) false;; esac; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    func_append install_prog "$func_quote_for_eval_result"
+    install_shared_prog=$install_prog
+    case " $install_prog " in
+      *[\\\ /]cp\ *) install_cp=: ;;
+      *) install_cp=false ;;
+    esac
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    no_mode=:
+    for arg
+    do
+      arg2=
+      if test -n "$dest"; then
+       func_append files " $dest"
+       dest=$arg
+       continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+       if $install_cp; then :; else
+         prev=$arg
+       fi
+       ;;
+      -g | -m | -o)
+       prev=$arg
+       ;;
+      -s)
+       stripme=" -s"
+       continue
+       ;;
+      -*)
+       ;;
+      *)
+       # If the previous option needed an argument, then skip it.
+       if test -n "$prev"; then
+         if test "x$prev" = x-m && test -n "$install_override_mode"; then
+           arg2=$install_override_mode
+           no_mode=false
+         fi
+         prev=
+       else
+         dest=$arg
+         continue
+       fi
+       ;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      func_append install_prog " $func_quote_for_eval_result"
+      if test -n "$arg2"; then
+       func_quote_for_eval "$arg2"
+      fi
+      func_append install_shared_prog " $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -n "$install_override_mode" && $no_mode; then
+      if $install_cp; then :; else
+       func_quote_for_eval "$install_override_mode"
+       func_append install_shared_prog " -m $func_quote_for_eval_result"
+      fi
+    fi
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+       func_fatal_help "no file or destination specified"
+      else
+       func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+       func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+       case $file in
+       *.lo) ;;
+       *)
+         func_fatal_help "\`$destdir' must be an absolute directory name"
+         ;;
+       esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+       # Do the static libraries later.
+       func_append staticlibs " $file"
+       ;;
+
+      *.la)
+       func_resolve_sysroot "$file"
+       file=$func_resolve_sysroot_result
+
+       # Check to see that this really is a libtool archive.
+       func_lalib_unsafe_p "$file" \
+         || func_fatal_help "\`$file' is not a valid libtool archive"
+
+       library_names=
+       old_library=
+       relink_command=
+       func_source "$file"
+
+       # Add the libdir to current_libdirs if it is the destination.
+       if test "X$destdir" = "X$libdir"; then
+         case "$current_libdirs " in
+         *" $libdir "*) ;;
+         *) func_append current_libdirs " $libdir" ;;
+         esac
+       else
+         # Note the libdir as a future libdir.
+         case "$future_libdirs " in
+         *" $libdir "*) ;;
+         *) func_append future_libdirs " $libdir" ;;
+         esac
+       fi
+
+       func_dirname "$file" "/" ""
+       dir="$func_dirname_result"
+       func_append dir "$objdir"
+
+       if test -n "$relink_command"; then
+         # Determine the prefix the user has applied to our future dir.
+         inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+         # Don't allow the user to place us outside of our expected
+         # location b/c this prevents finding dependent libraries that
+         # are installed to the same prefix.
+         # At present, this check doesn't affect windows .dll's that
+         # are installed into $libdir/../bin (currently, that works fine)
+         # but it's something to keep an eye on.
+         test "$inst_prefix_dir" = "$destdir" && \
+           func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+         if test -n "$inst_prefix_dir"; then
+           # Stick the inst_prefix_dir data into the link command.
+           relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+         else
+           relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+         fi
+
+         func_warning "relinking \`$file'"
+         func_show_eval "$relink_command" \
+           'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+       fi
+
+       # See the names of the shared library.
+       set dummy $library_names; shift
+       if test -n "$1"; then
+         realname="$1"
+         shift
+
+         srcname="$realname"
+         test -n "$relink_command" && srcname="$realname"T
+
+         # Install the shared library and build the symlinks.
+         func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+             'exit $?'
+         tstripme="$stripme"
+         case $host_os in
+         cygwin* | mingw* | pw32* | cegcc*)
+           case $realname in
+           *.dll.a)
+             tstripme=""
+             ;;
+           esac
+           ;;
+         esac
+         if test -n "$tstripme" && test -n "$striplib"; then
+           func_show_eval "$striplib $destdir/$realname" 'exit $?'
+         fi
+
+         if test "$#" -gt 0; then
+           # Delete the old symlinks, and create new ones.
+           # Try `ln -sf' first, because the `ln' binary might depend on
+           # the symlink we replace!  Solaris /bin/ln does not understand -f,
+           # so we also need to try rm && ln -s.
+           for linkname
+           do
+             test "$linkname" != "$realname" \
+               && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+           done
+         fi
+
+         # Do each command in the postinstall commands.
+         lib="$destdir/$realname"
+         func_execute_cmds "$postinstall_cmds" 'exit $?'
+       fi
+
+       # Install the pseudo-library for information purposes.
+       func_basename "$file"
+       name="$func_basename_result"
+       instname="$dir/$name"i
+       func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+       # Maybe install the static library, too.
+       test -n "$old_library" && func_append staticlibs " $dir/$old_library"
+       ;;
+
+      *.lo)
+       # Install (i.e. copy) a libtool object.
+
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         func_basename "$file"
+         destfile="$func_basename_result"
+         destfile="$destdir/$destfile"
+       fi
+
+       # Deduce the name of the destination old-style object file.
+       case $destfile in
+       *.lo)
+         func_lo2o "$destfile"
+         staticdest=$func_lo2o_result
+         ;;
+       *.$objext)
+         staticdest="$destfile"
+         destfile=
+         ;;
+       *)
+         func_fatal_help "cannot copy a libtool object to \`$destfile'"
+         ;;
+       esac
+
+       # Install the libtool object if requested.
+       test -n "$destfile" && \
+         func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+       # Install the old object if enabled.
+       if test "$build_old_libs" = yes; then
+         # Deduce the name of the old-style object file.
+         func_lo2o "$file"
+         staticobj=$func_lo2o_result
+         func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+       fi
+       exit $EXIT_SUCCESS
+       ;;
+
+      *)
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         func_basename "$file"
+         destfile="$func_basename_result"
+         destfile="$destdir/$destfile"
+       fi
+
+       # If the file is missing, and there is a .exe on the end, strip it
+       # because it is most likely a libtool script we actually want to
+       # install
+       stripped_ext=""
+       case $file in
+         *.exe)
+           if test ! -f "$file"; then
+             func_stripname '' '.exe' "$file"
+             file=$func_stripname_result
+             stripped_ext=".exe"
+           fi
+           ;;
+       esac
+
+       # Do a test to see if this is really a libtool program.
+       case $host in
+       *cygwin* | *mingw*)
+           if func_ltwrapper_executable_p "$file"; then
+             func_ltwrapper_scriptname "$file"
+             wrapper=$func_ltwrapper_scriptname_result
+           else
+             func_stripname '' '.exe' "$file"
+             wrapper=$func_stripname_result
+           fi
+           ;;
+       *)
+           wrapper=$file
+           ;;
+       esac
+       if func_ltwrapper_script_p "$wrapper"; then
+         notinst_deplibs=
+         relink_command=
+
+         func_source "$wrapper"
+
+         # Check the variables that should have been set.
+         test -z "$generated_by_libtool_version" && \
+           func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+         finalize=yes
+         for lib in $notinst_deplibs; do
+           # Check to see that each library is installed.
+           libdir=
+           if test -f "$lib"; then
+             func_source "$lib"
+           fi
+           libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test
+           if test -n "$libdir" && test ! -f "$libfile"; then
+             func_warning "\`$lib' has not been installed in \`$libdir'"
+             finalize=no
+           fi
+         done
+
+         relink_command=
+         func_source "$wrapper"
+
+         outputname=
+         if test "$fast_install" = no && test -n "$relink_command"; then
+           $opt_dry_run || {
+             if test "$finalize" = yes; then
+               tmpdir=`func_mktempdir`
+               func_basename "$file$stripped_ext"
+               file="$func_basename_result"
+               outputname="$tmpdir/$file"
+               # Replace the output file specification.
+               relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+               $opt_silent || {
+                 func_quote_for_expand "$relink_command"
+                 eval "func_echo $func_quote_for_expand_result"
+               }
+               if eval "$relink_command"; then :
+                 else
+                 func_error "error: relink \`$file' with the above command before installing it"
+                 $opt_dry_run || ${RM}r "$tmpdir"
+                 continue
+               fi
+               file="$outputname"
+             else
+               func_warning "cannot relink \`$file'"
+             fi
+           }
+         else
+           # Install the binary that we compiled earlier.
+           file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+         fi
+       fi
+
+       # remove .exe since cygwin /usr/bin/install will append another
+       # one anyway
+       case $install_prog,$host in
+       */usr/bin/install*,*cygwin*)
+         case $file:$destfile in
+         *.exe:*.exe)
+           # this is ok
+           ;;
+         *.exe:*)
+           destfile=$destfile.exe
+           ;;
+         *:*.exe)
+           func_stripname '' '.exe' "$destfile"
+           destfile=$func_stripname_result
+           ;;
+         esac
+         ;;
+       esac
+       func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+       $opt_dry_run || if test -n "$outputname"; then
+         ${RM}r "$tmpdir"
+       fi
+       ;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+      func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+      tool_oldlib=$func_to_tool_file_result
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+       func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$opt_mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+       my_dlsyms="${my_outputname}S.c"
+      else
+       func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+       # Discover the nlist of each of the dlfiles.
+       nlist="$output_objdir/${my_outputname}.nm"
+
+       func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+       # Parse the name list into a source file.
+       func_verbose "creating $output_objdir/$my_dlsyms"
+
+       $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+       if test "$dlself" = yes; then
+         func_verbose "generating symbol list for \`$output'"
+
+         $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+         # Add our own program objects to the symbol list.
+         progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+         for progfile in $progfiles; do
+           func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+           func_verbose "extracting global C symbols from \`$func_to_tool_file_result'"
+           $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
+         done
+
+         if test -n "$exclude_expsyms"; then
+           $opt_dry_run || {
+             eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+             eval '$MV "$nlist"T "$nlist"'
+           }
+         fi
+
+         if test -n "$export_symbols_regex"; then
+           $opt_dry_run || {
+             eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+             eval '$MV "$nlist"T "$nlist"'
+           }
+         fi
+
+         # Prepare the list of exported symbols
+         if test -z "$export_symbols"; then
+           export_symbols="$output_objdir/$outputname.exp"
+           $opt_dry_run || {
+             $RM $export_symbols
+             eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+             case $host in
+             *cygwin* | *mingw* | *cegcc* )
+                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+               ;;
+             esac
+           }
+         else
+           $opt_dry_run || {
+             eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+             eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+             eval '$MV "$nlist"T "$nlist"'
+             case $host in
+               *cygwin* | *mingw* | *cegcc* )
+                 eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                 eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+                 ;;
+             esac
+           }
+         fi
+       fi
+
+       for dlprefile in $dlprefiles; do
+         func_verbose "extracting global C symbols from \`$dlprefile'"
+         func_basename "$dlprefile"
+         name="$func_basename_result"
+          case $host in
+           *cygwin* | *mingw* | *cegcc* )
+             # if an import library, we need to obtain dlname
+             if func_win32_import_lib_p "$dlprefile"; then
+               func_tr_sh "$dlprefile"
+               eval "curr_lafile=\$libfile_$func_tr_sh_result"
+               dlprefile_dlbasename=""
+               if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+                 # Use subshell, to avoid clobbering current variable values
+                 dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+                 if test -n "$dlprefile_dlname" ; then
+                   func_basename "$dlprefile_dlname"
+                   dlprefile_dlbasename="$func_basename_result"
+                 else
+                   # no lafile. user explicitly requested -dlpreopen <import library>.
+                   $sharedlib_from_linklib_cmd "$dlprefile"
+                   dlprefile_dlbasename=$sharedlib_from_linklib_result
+                 fi
+               fi
+               $opt_dry_run || {
+                 if test -n "$dlprefile_dlbasename" ; then
+                   eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+                 else
+                   func_warning "Could not compute DLL name from $name"
+                   eval '$ECHO ": $name " >> "$nlist"'
+                 fi
+                 func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+                 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+                   $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+               }
+             else # not an import lib
+               $opt_dry_run || {
+                 eval '$ECHO ": $name " >> "$nlist"'
+                 func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+                 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+               }
+             fi
+           ;;
+           *)
+             $opt_dry_run || {
+               eval '$ECHO ": $name " >> "$nlist"'
+               func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+               eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+             }
+           ;;
+          esac
+       done
+
+       $opt_dry_run || {
+         # Make sure we have at least an empty file.
+         test -f "$nlist" || : > "$nlist"
+
+         if test -n "$exclude_expsyms"; then
+           $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+           $MV "$nlist"T "$nlist"
+         fi
+
+         # Try sorting and uniquifying the output.
+         if $GREP -v "^: " < "$nlist" |
+             if sort -k 3 </dev/null >/dev/null 2>&1; then
+               sort -k 3
+             else
+               sort +2
+             fi |
+             uniq > "$nlist"S; then
+           :
+         else
+           $GREP -v "^: " < "$nlist" > "$nlist"S
+         fi
+
+         if test -f "$nlist"S; then
+           eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+         else
+           echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+         fi
+
+         echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+extern LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+         case $need_lib_prefix in
+         no)
+           eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+           ;;
+         *)
+           eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+           ;;
+         esac
+         echo >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+       } # !$opt_dry_run
+
+       pic_flag_for_symtable=
+       case "$compile_command " in
+       *" -static "*) ;;
+       *)
+         case $host in
+         # compiling the symbol table file with pic_flag works around
+         # a FreeBSD bug that causes programs to crash when -lm is
+         # linked before any other PIC object.  But we must not use
+         # pic_flag when linking with -static.  The problem exists in
+         # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+         *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+           pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+         *-*-hpux*)
+           pic_flag_for_symtable=" $pic_flag"  ;;
+         *)
+           if test "X$my_pic_p" != Xno; then
+             pic_flag_for_symtable=" $pic_flag"
+           fi
+           ;;
+         esac
+         ;;
+       esac
+       symtab_cflags=
+       for arg in $LTCFLAGS; do
+         case $arg in
+         -pie | -fpie | -fPIE) ;;
+         *) func_append symtab_cflags " $arg" ;;
+         esac
+       done
+
+       # Now compile the dynamic symbol file.
+       func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+       # Clean up the generated files.
+       func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+       # Transform the symbol file into the correct name.
+       symfileobj="$output_objdir/${my_outputname}S.$objext"
+       case $host in
+       *cygwin* | *mingw* | *cegcc* )
+         if test -f "$output_objdir/$my_outputname.def"; then
+           compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+           finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+         else
+           compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+           finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+         fi
+         ;;
+       *)
+         compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+         finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+         ;;
+       esac
+       ;;
+      *)
+       func_fatal_error "unknown suffix for \`$my_dlsyms'"
+       ;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+      func_to_tool_file "$1" func_convert_file_msys_to_w32
+      win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
+       $SED -n -e '
+           1,100{
+               / I /{
+                   s,.*,import,
+                   p
+                   q
+               }
+           }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+  $opt_debug
+  sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+  $opt_debug
+  match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+  $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+    $SED '/^Contents of section '"$match_literal"':/{
+      # Place marker at beginning of archive member dllname section
+      s/.*/====MARK====/
+      p
+      d
+    }
+    # These lines can sometimes be longer than 43 characters, but
+    # are always uninteresting
+    /:[         ]*file format pe[i]\{,1\}-/d
+    /^In archive [^:]*:/d
+    # Ensure marker is printed
+    /^====MARK====/p
+    # Remove all lines with less than 43 characters
+    /^.\{43\}/!d
+    # From remaining lines, remove first 43 characters
+    s/^.\{43\}//' |
+    $SED -n '
+      # Join marker and all lines until next marker into a single line
+      /^====MARK====/ b para
+      H
+      $ b para
+      b
+      :para
+      x
+      s/\n//g
+      # Remove the marker
+      s/^====MARK====//
+      # Remove trailing dots and whitespace
+      s/[\. \t]*$//
+      # Print
+      /./p' |
+    # we now have a list, one entry per line, of the stringified
+    # contents of the appropriate section of all members of the
+    # archive which possess that section. Heuristic: eliminate
+    # all those which have a first or second character that is
+    # a '.' (that is, objdump's representation of an unprintable
+    # character.) This should work for all archives with less than
+    # 0x302f exports -- but will fail for DLLs whose name actually
+    # begins with a literal '.' or a single character followed by
+    # a '.'.
+    #
+    # Of those that remain, print the first one.
+    $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+  test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+  $opt_debug
+  func_to_tool_file "$1" func_convert_file_msys_to_w32
+  func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+  test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+#    $sharedlib_from_linklib_cmd
+# Result is available in the variable
+#    $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+  $opt_debug
+  if func_cygming_gnu_implib_p "$1" ; then
+    # binutils import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+  elif func_cygming_ms_implib_p "$1" ; then
+    # ms-generated import library
+    sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+  else
+    # unknown
+    sharedlib_from_linklib_result=""
+  fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    if test "$lock_old_archive_extraction" = yes; then
+      lockfile=$f_ex_an_ar_oldlib.lock
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+       func_echo "Waiting for $lockfile to be removed"
+       sleep 2
+      done
+    fi
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+                  'stat=$?; rm -f "$lockfile"; exit $stat'
+    if test "$lock_old_archive_extraction" = yes; then
+      $opt_dry_run || rm -f "$lockfile"
+    fi
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+       [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+       *) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+       *" $my_xlib_u "*)
+         func_arith $extracted_serial + 1
+         extracted_serial=$func_arith_result
+         my_xlib_u=lt$extracted_serial-$my_xlib ;;
+       *) break ;;
+       esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+       func_verbose "Extracting $my_xabs"
+       # Do not bother doing anything if just a dry run
+       $opt_dry_run || {
+         darwin_orig_dir=`pwd`
+         cd $my_xdir || exit $?
+         darwin_archive=$my_xabs
+         darwin_curdir=`pwd`
+         darwin_base_archive=`basename "$darwin_archive"`
+         darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+         if test -n "$darwin_arches"; then
+           darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+           darwin_arch=
+           func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+           for darwin_arch in  $darwin_arches ; do
+             func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+             cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+             cd "$darwin_curdir"
+             $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+           done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+           darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+           darwin_file=
+           darwin_files=
+           for darwin_file in $darwin_filelist; do
+             darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
+             $LIPO -create -output "$darwin_file" $darwin_files
+           done # $darwin_filelist
+           $RM -rf unfat-$$
+           cd "$darwin_orig_dir"
+         else
+           cd $darwin_orig_dir
+           func_extract_an_archive "$my_xdir" "$my_xabs"
+         fi # $darwin_arches
+       } # !$opt_dry_run
+       ;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+       ;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+       func_emit_wrapper_arg1=${1-no}
+
+       $ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    file=\"\$0\""
+
+    qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+    $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+    ECHO=\"$qECHO\"
+  fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+  lt_script_arg0=\$0
+  shift
+  for lt_opt
+  do
+    case \"\$lt_opt\" in
+    --lt-debug) lt_option_debug=1 ;;
+    --lt-dump-script)
+        lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+        test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+        lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+        cat \"\$lt_dump_D/\$lt_dump_F\"
+        exit 0
+      ;;
+    --lt-*)
+        \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+        exit 1
+      ;;
+    esac
+  done
+
+  # Print the debug banner immediately:
+  if test -n \"\$lt_option_debug\"; then
+    echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2
+  fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+  lt_dump_args_N=1;
+  for lt_arg
+  do
+    \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\"
+    lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+  done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+"
+  case $host in
+  # Backslashes separate directories on plain windows
+  *-*-mingw | *-*-os2* | *-cegcc*)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+    ;;
+
+  *)
+    $ECHO "\
+      if test -n \"\$lt_option_debug\"; then
+        \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2
+        func_lt_dump_args \${1+\"\$@\"} 1>&2
+      fi
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+    ;;
+  esac
+  $ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+  case \" \$* \" in
+  *\\ --lt-*)
+    for lt_wr_arg
+    do
+      case \$lt_wr_arg in
+      --lt-*) ;;
+      *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+      esac
+      shift
+    done ;;
+  esac
+  func_exec_program_core \${1+\"\$@\"}
+}
+
+  # Parse options
+  func_parse_lt_options \"\$0\" \${1+\"\$@\"}
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+  done
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+       if test "$fast_install" = yes; then
+         $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+         $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+       $ECHO \"\$relink_command_output\" >&2
+       $RM \"\$progdir/\$file\"
+       exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+       else
+         $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+       fi
+
+       $ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+       # fixup the dll searchpath if we need to.
+       #
+       # Fix the DLL searchpath if we need to.  Do this before prepending
+       # to shlibpath, because on Windows, both are PATH and uninstalled
+       # libraries must come first.
+       if test -n "$dllsearchpath"; then
+         $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+       fi
+
+       # Export our shlibpath_var if we have one.
+       if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+         $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+       fi
+
+       $ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+      func_exec_program \${1+\"\$@\"}
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+       cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+*/
+EOF
+           cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* declarations of non-ANSI functions */
+#if defined(__MINGW32__)
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined(__CYGWIN__)
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined (other platforms) ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined(_MSC_VER)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+# define S_IXUSR _S_IEXEC
+# ifndef _INTPTR_T_DEFINED
+#  define _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#elif defined(__MINGW32__)
+# define setmode _setmode
+# define stat    _stat
+# define chmod   _chmod
+# define getcwd  _getcwd
+# define putenv  _putenv
+#elif defined(__CYGWIN__)
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined (other platforms) ... */
+#endif
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+       (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#if defined(LT_DEBUGWRAPPER)
+static int lt_debug = 1;
+#else
+static int lt_debug = 0;
+#endif
+
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+           cat <<EOF
+volatile const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+           if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_path "$temp_rpath"
+             cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+           else
+             cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test -n "$dllsearchpath"; then
+              func_to_host_path "$dllsearchpath:"
+             cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_path_result";
+EOF
+           else
+             cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test "$fast_install" = yes; then
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+           else
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+           fi
+
+
+           cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+static const char *debug_opt            = LTWRAPPER_OPTION_PREFIX "debug";
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  newargz = XMALLOC (char *, argc + 1);
+
+  /* very simple arg parsing; don't want to rely on getopt
+   * also, copy all non cwrapper options to newargz, except
+   * argz[0], which is handled differently
+   */
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+       {
+EOF
+           case "$host" in
+             *mingw* | *cygwin* )
+               # make stdout use "unix" line endings
+               echo "          setmode(1,_O_BINARY);"
+               ;;
+             esac
+
+           cat <<"EOF"
+         lt_dump_script (stdout);
+         return 0;
+       }
+      if (strcmp (argv[i], debug_opt) == 0)
+       {
+          lt_debug = 1;
+          continue;
+       }
+      if (strcmp (argv[i], ltwrapper_option_prefix) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal (__FILE__, __LINE__,
+                   "unrecognized %s option: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+EOF
+           cat <<EOF
+  /* The GNU banner must be the first non-error debug message */
+  lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\n");
+EOF
+           cat <<"EOF"
+  lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
+
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (before symlink chase) at: %s\n",
+                 tmp_pathspec);
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  lt_debugprintf (__FILE__, __LINE__,
+                  "(main) found exe (after symlink chase) at: %s\n",
+                 actual_cwrapper_path);
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  lt_debugprintf (__FILE__, __LINE__,
+                 "(main) libtool target name: %s\n",
+                 target_name);
+EOF
+
+           cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+                   strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+           cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+           case $host_os in
+             mingw*)
+           cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+       *p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+       *p = '/';
+      }
+  }
+EOF
+           ;;
+           esac
+
+           cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  /* Update the DLL searchpath.  EXE_PATH_VALUE ($dllsearchpath) must
+     be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
+     because on Windows, both *_VARNAMEs are PATH but uninstalled
+     libraries must come first. */
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+
+  lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
+                 nonnull (lt_argv_zero));
+  for (i = 0; i < newargc; i++)
+    {
+      lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
+                     i, nonnull (newargz[i]));
+    }
+
+EOF
+
+           case $host_os in
+             mingw*)
+               cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  newargz = prepare_spawn (newargz);
+  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      lt_debugprintf (__FILE__, __LINE__,
+                     "(main) failed to launch target \"%s\": %s\n",
+                     lt_argv_zero, nonnull (strerror (errno)));
+      return 127;
+    }
+  return rval;
+EOF
+               ;;
+             *)
+               cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+               ;;
+           esac
+
+           cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal (__FILE__, __LINE__, "memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+                         string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+                  nonempty (path));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+                  nonempty (wrapper));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+       return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+       {
+         concat_name = xstrdup (wrapper);
+         if (check_executable (concat_name))
+           return concat_name;
+         XFREE (concat_name);
+       }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+       has_slash = 1;
+       break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+       {
+         for (p = path; *p; p = p_next)
+           {
+             const char *q;
+             size_t p_len;
+             for (q = p; *q; q++)
+               if (IS_PATH_SEPARATOR (*q))
+                 break;
+             p_len = q - p;
+             p_next = (*q == '\0' ? q : q + 1);
+             if (p_len == 0)
+               {
+                 /* empty path: current directory */
+                 if (getcwd (tmp, LT_PATHMAX) == NULL)
+                   lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+                              nonnull (strerror (errno)));
+                 tmp_len = strlen (tmp);
+                 concat_name =
+                   XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+                 memcpy (concat_name, tmp, tmp_len);
+                 concat_name[tmp_len] = '/';
+                 strcpy (concat_name + tmp_len + 1, wrapper);
+               }
+             else
+               {
+                 concat_name =
+                   XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+                 memcpy (concat_name, p, p_len);
+                 concat_name[p_len] = '/';
+                 strcpy (concat_name + p_len + 1, wrapper);
+               }
+             if (check_executable (concat_name))
+               return concat_name;
+             XFREE (concat_name);
+           }
+       }
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+              nonnull (strerror (errno)));
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      lt_debugprintf (__FILE__, __LINE__,
+                     "checking path component for symlinks: %s\n",
+                     tmp_pathspec);
+      if (lstat (tmp_pathspec, &s) == 0)
+       {
+         if (S_ISLNK (s.st_mode) != 0)
+           {
+             has_symlinks = 1;
+             break;
+           }
+
+         /* search backwards for last DIR_SEPARATOR */
+         p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+         while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+           p--;
+         if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+           {
+             /* no more DIR_SEPARATORS left */
+             break;
+           }
+         *p = '\0';
+       }
+      else
+       {
+         lt_fatal (__FILE__, __LINE__,
+                   "error accessing file \"%s\": %s",
+                   tmp_pathspec, nonnull (strerror (errno)));
+       }
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal (__FILE__, __LINE__,
+               "could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+       *str = '\0';
+    }
+  return str;
+}
+
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+  va_list args;
+  if (lt_debug)
+    {
+      (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+      va_start (args, fmt);
+      (void) vfprintf (stderr, fmt, args);
+      va_end (args);
+    }
+}
+
+static void
+lt_error_core (int exit_status, const char *file,
+              int line, const char *mode,
+              const char *message, va_list ap)
+{
+  fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *file, int line, const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
+  va_end (ap);
+}
+
+static const char *
+nonnull (const char *s)
+{
+  return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+  return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+                 "(lt_setenv) setting '%s' to '%s'\n",
+                  nonnull (name), nonnull (value));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    int len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      int orig_value_len = strlen (orig_value);
+      int add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+                 "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      int len = strlen (new_value);
+      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[len-1] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  lt_debugprintf (__FILE__, __LINE__,
+                 "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                  nonnull (name), nonnull (value));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+EOF
+           case $host_os in
+             mingw*)
+               cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XMALLOC (char *, argc + 1);
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+       new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+       {
+         int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+         size_t length;
+         unsigned int backslashes;
+         const char *s;
+         char *quoted_string;
+         char *p;
+
+         length = 0;
+         backslashes = 0;
+         if (quote_around)
+           length++;
+         for (s = string; *s != '\0'; s++)
+           {
+             char c = *s;
+             if (c == '"')
+               length += backslashes + 1;
+             length++;
+             if (c == '\\')
+               backslashes++;
+             else
+               backslashes = 0;
+           }
+         if (quote_around)
+           length += backslashes + 1;
+
+         quoted_string = XMALLOC (char, length + 1);
+
+         p = quoted_string;
+         backslashes = 0;
+         if (quote_around)
+           *p++ = '"';
+         for (s = string; *s != '\0'; s++)
+           {
+             char c = *s;
+             if (c == '"')
+               {
+                 unsigned int j;
+                 for (j = backslashes + 1; j > 0; j--)
+                   *p++ = '\\';
+               }
+             *p++ = c;
+             if (c == '\\')
+               backslashes++;
+             else
+               backslashes = 0;
+           }
+         if (quote_around)
+           {
+             unsigned int j;
+             for (j = backslashes; j > 0; j--)
+               *p++ = '\\';
+             *p++ = '"';
+           }
+         *p = '\0';
+
+         new_argv[i] = quoted_string;
+       }
+      else
+       new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
+EOF
+               ;;
+           esac
+
+            cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+           func_emit_wrapper yes |
+             $SED -n -e '
+s/^\(.\{79\}\)\(..*\)/\1\
+\2/
+h
+s/\([\\"]\)/\\\1/g
+s/$/\\n/
+s/\([^\n]*\).*/  fputs ("\1", f);/p
+g
+D'
+            cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+    $opt_debug
+    case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+    *import*) : ;;
+    *) false ;;
+    esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    bindir=
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+       test "$build_libtool_libs" != yes && \
+         func_fatal_configuration "can not build a shared library"
+       build_old_libs=no
+       break
+       ;;
+      -all-static | -static | -static-libtool-libs)
+       case $arg in
+       -all-static)
+         if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+           func_warning "complete static linking is impossible in this configuration"
+         fi
+         if test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       -static)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=built
+         ;;
+       -static-libtool-libs)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       esac
+       build_libtool_libs=no
+       build_old_libs=yes
+       break
+       ;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+       case $prev in
+       output)
+         func_append compile_command " @OUTPUT@"
+         func_append finalize_command " @OUTPUT@"
+         ;;
+       esac
+
+       case $prev in
+       bindir)
+         bindir="$arg"
+         prev=
+         continue
+         ;;
+       dlfiles|dlprefiles)
+         if test "$preload" = no; then
+           # Add the symbol object into the linking commands.
+           func_append compile_command " @SYMFILE@"
+           func_append finalize_command " @SYMFILE@"
+           preload=yes
+         fi
+         case $arg in
+         *.la | *.lo) ;;  # We handle these cases below.
+         force)
+           if test "$dlself" = no; then
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         self)
+           if test "$prev" = dlprefiles; then
+             dlself=yes
+           elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+             dlself=yes
+           else
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         *)
+           if test "$prev" = dlfiles; then
+             func_append dlfiles " $arg"
+           else
+             func_append dlprefiles " $arg"
+           fi
+           prev=
+           continue
+           ;;
+         esac
+         ;;
+       expsyms)
+         export_symbols="$arg"
+         test -f "$arg" \
+           || func_fatal_error "symbol file \`$arg' does not exist"
+         prev=
+         continue
+         ;;
+       expsyms_regex)
+         export_symbols_regex="$arg"
+         prev=
+         continue
+         ;;
+       framework)
+         case $host in
+           *-*-darwin*)
+             case "$deplibs " in
+               *" $qarg.ltframework "*) ;;
+               *) func_append deplibs " $qarg.ltframework" # this is fixed later
+                  ;;
+             esac
+             ;;
+         esac
+         prev=
+         continue
+         ;;
+       inst_prefix)
+         inst_prefix_dir="$arg"
+         prev=
+         continue
+         ;;
+       objectlist)
+         if test -f "$arg"; then
+           save_arg=$arg
+           moreargs=
+           for fil in `cat "$save_arg"`
+           do
+#            func_append moreargs " $fil"
+             arg=$fil
+             # A libtool-controlled object.
+
+             # Check to see that this really is a libtool object.
+             if func_lalib_unsafe_p "$arg"; then
+               pic_object=
+               non_pic_object=
+
+               # Read the .lo file
+               func_source "$arg"
+
+               if test -z "$pic_object" ||
+                  test -z "$non_pic_object" ||
+                  test "$pic_object" = none &&
+                  test "$non_pic_object" = none; then
+                 func_fatal_error "cannot find name of object for \`$arg'"
+               fi
+
+               # Extract subdirectory from the argument.
+               func_dirname "$arg" "/" ""
+               xdir="$func_dirname_result"
+
+               if test "$pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 pic_object="$xdir$pic_object"
+
+                 if test "$prev" = dlfiles; then
+                   if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+                     func_append dlfiles " $pic_object"
+                     prev=
+                     continue
+                   else
+                     # If libtool objects are unsupported, then we need to preload.
+                     prev=dlprefiles
+                   fi
+                 fi
+
+                 # CHECK ME:  I think I busted this.  -Ossama
+                 if test "$prev" = dlprefiles; then
+                   # Preload the old-style object.
+                   func_append dlprefiles " $pic_object"
+                   prev=
+                 fi
+
+                 # A PIC object.
+                 func_append libobjs " $pic_object"
+                 arg="$pic_object"
+               fi
+
+               # Non-PIC object.
+               if test "$non_pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 non_pic_object="$xdir$non_pic_object"
+
+                 # A standard non-PIC object
+                 func_append non_pic_objects " $non_pic_object"
+                 if test -z "$pic_object" || test "$pic_object" = none ; then
+                   arg="$non_pic_object"
+                 fi
+               else
+                 # If the PIC object exists, use it instead.
+                 # $xdir was prepended to $pic_object above.
+                 non_pic_object="$pic_object"
+                 func_append non_pic_objects " $non_pic_object"
+               fi
+             else
+               # Only an error if not doing a dry-run.
+               if $opt_dry_run; then
+                 # Extract subdirectory from the argument.
+                 func_dirname "$arg" "/" ""
+                 xdir="$func_dirname_result"
+
+                 func_lo2o "$arg"
+                 pic_object=$xdir$objdir/$func_lo2o_result
+                 non_pic_object=$xdir$func_lo2o_result
+                 func_append libobjs " $pic_object"
+                 func_append non_pic_objects " $non_pic_object"
+               else
+                 func_fatal_error "\`$arg' is not a valid libtool object"
+               fi
+             fi
+           done
+         else
+           func_fatal_error "link input file \`$arg' does not exist"
+         fi
+         arg=$save_arg
+         prev=
+         continue
+         ;;
+       precious_regex)
+         precious_files_regex="$arg"
+         prev=
+         continue
+         ;;
+       release)
+         release="-$arg"
+         prev=
+         continue
+         ;;
+       rpath | xrpath)
+         # We need an absolute path.
+         case $arg in
+         [\\/]* | [A-Za-z]:[\\/]*) ;;
+         *)
+           func_fatal_error "only absolute run-paths are allowed"
+           ;;
+         esac
+         if test "$prev" = rpath; then
+           case "$rpath " in
+           *" $arg "*) ;;
+           *) func_append rpath " $arg" ;;
+           esac
+         else
+           case "$xrpath " in
+           *" $arg "*) ;;
+           *) func_append xrpath " $arg" ;;
+           esac
+         fi
+         prev=
+         continue
+         ;;
+       shrext)
+         shrext_cmds="$arg"
+         prev=
+         continue
+         ;;
+       weak)
+         func_append weak_libs " $arg"
+         prev=
+         continue
+         ;;
+       xcclinker)
+         func_append linker_flags " $qarg"
+         func_append compiler_flags " $qarg"
+         prev=
+         func_append compile_command " $qarg"
+         func_append finalize_command " $qarg"
+         continue
+         ;;
+       xcompiler)
+         func_append compiler_flags " $qarg"
+         prev=
+         func_append compile_command " $qarg"
+         func_append finalize_command " $qarg"
+         continue
+         ;;
+       xlinker)
+         func_append linker_flags " $qarg"
+         func_append compiler_flags " $wl$qarg"
+         prev=
+         func_append compile_command " $wl$qarg"
+         func_append finalize_command " $wl$qarg"
+         continue
+         ;;
+       *)
+         eval "$prev=\"\$arg\""
+         prev=
+         continue
+         ;;
+       esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+       if test -n "$link_static_flag"; then
+         # See comment for -static flag below, for more details.
+         func_append compile_command " $link_static_flag"
+         func_append finalize_command " $link_static_flag"
+       fi
+       continue
+       ;;
+
+      -allow-undefined)
+       # FIXME: remove this flag sometime in the future.
+       func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+       ;;
+
+      -avoid-version)
+       avoid_version=yes
+       continue
+       ;;
+
+      -bindir)
+       prev=bindir
+       continue
+       ;;
+
+      -dlopen)
+       prev=dlfiles
+       continue
+       ;;
+
+      -dlpreopen)
+       prev=dlprefiles
+       continue
+       ;;
+
+      -export-dynamic)
+       export_dynamic=yes
+       continue
+       ;;
+
+      -export-symbols | -export-symbols-regex)
+       if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+         func_fatal_error "more than one -exported-symbols argument is not allowed"
+       fi
+       if test "X$arg" = "X-export-symbols"; then
+         prev=expsyms
+       else
+         prev=expsyms_regex
+       fi
+       continue
+       ;;
+
+      -framework)
+       prev=framework
+       continue
+       ;;
+
+      -inst-prefix-dir)
+       prev=inst_prefix
+       continue
+       ;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+       case $with_gcc/$host in
+       no/*-*-irix* | /*-*-irix*)
+         func_append compile_command " $arg"
+         func_append finalize_command " $arg"
+         ;;
+       esac
+       continue
+       ;;
+
+      -L*)
+       func_stripname "-L" '' "$arg"
+       if test -z "$func_stripname_result"; then
+         if test "$#" -gt 0; then
+           func_fatal_error "require no space between \`-L' and \`$1'"
+         else
+           func_fatal_error "need path for \`-L' option"
+         fi
+       fi
+       func_resolve_sysroot "$func_stripname_result"
+       dir=$func_resolve_sysroot_result
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         absdir=`cd "$dir" && pwd`
+         test -z "$absdir" && \
+           func_fatal_error "cannot determine absolute directory name of \`$dir'"
+         dir="$absdir"
+         ;;
+       esac
+       case "$deplibs " in
+       *" -L$dir "* | *" $arg "*)
+         # Will only happen for absolute or sysroot arguments
+         ;;
+       *)
+         # Preserve sysroot, but never include relative directories
+         case $dir in
+           [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
+           *) func_append deplibs " -L$dir" ;;
+         esac
+         func_append lib_search_path " $dir"
+         ;;
+       esac
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+         testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$dir:"*) ;;
+         ::) dllsearchpath=$dir;;
+         *) func_append dllsearchpath ":$dir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         ::) dllsearchpath=$testbindir;;
+         *) func_append dllsearchpath ":$testbindir";;
+         esac
+         ;;
+       esac
+       continue
+       ;;
+
+      -l*)
+       if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+           # These systems don't actually have a C or math library (as such)
+           continue
+           ;;
+         *-*-os2*)
+           # These systems don't actually have a C library (as such)
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C and math libraries are in the System framework
+           func_append deplibs " System.ltframework"
+           continue
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           test "X$arg" = "X-lc" && continue
+           ;;
+         esac
+       elif test "X$arg" = "X-lc_r"; then
+        case $host in
+        *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+          # Do not include libc_r directly, use -pthread flag.
+          continue
+          ;;
+        esac
+       fi
+       func_append deplibs " $arg"
+       continue
+       ;;
+
+      -module)
+       module=yes
+       continue
+       ;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot|--sysroot)
+       func_append compiler_flags " $arg"
+       func_append compile_command " $arg"
+       func_append finalize_command " $arg"
+       prev=xcompiler
+       continue
+       ;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+      |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+       func_append compiler_flags " $arg"
+       func_append compile_command " $arg"
+       func_append finalize_command " $arg"
+       case "$new_inherited_linker_flags " in
+           *" $arg "*) ;;
+           * ) func_append new_inherited_linker_flags " $arg" ;;
+       esac
+       continue
+       ;;
+
+      -multi_module)
+       single_module="${wl}-multi_module"
+       continue
+       ;;
+
+      -no-fast-install)
+       fast_install=no
+       continue
+       ;;
+
+      -no-install)
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+         # The PATH hackery in wrapper scripts is required on Windows
+         # and Darwin in order for the loader to find any dlls it needs.
+         func_warning "\`-no-install' is ignored for $host"
+         func_warning "assuming \`-no-fast-install' instead"
+         fast_install=no
+         ;;
+       *) no_install=yes ;;
+       esac
+       continue
+       ;;
+
+      -no-undefined)
+       allow_undefined=no
+       continue
+       ;;
+
+      -objectlist)
+       prev=objectlist
+       continue
+       ;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+       prev=precious_regex
+       continue
+       ;;
+
+      -release)
+       prev=release
+       continue
+       ;;
+
+      -rpath)
+       prev=rpath
+       continue
+       ;;
+
+      -R)
+       prev=xrpath
+       continue
+       ;;
+
+      -R*)
+       func_stripname '-R' '' "$arg"
+       dir=$func_stripname_result
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       =*)
+         func_stripname '=' '' "$dir"
+         dir=$lt_sysroot$func_stripname_result
+         ;;
+       *)
+         func_fatal_error "only absolute run-paths are allowed"
+         ;;
+       esac
+       case "$xrpath " in
+       *" $dir "*) ;;
+       *) func_append xrpath " $dir" ;;
+       esac
+       continue
+       ;;
+
+      -shared)
+       # The effects of -shared are defined in a previous loop.
+       continue
+       ;;
+
+      -shrext)
+       prev=shrext
+       continue
+       ;;
+
+      -static | -static-libtool-libs)
+       # The effects of -static are defined in a previous loop.
+       # We used to do the same as -all-static on platforms that
+       # didn't have a PIC flag, but the assumption that the effects
+       # would be equivalent was wrong.  It would break on at least
+       # Digital Unix and AIX.
+       continue
+       ;;
+
+      -thread-safe)
+       thread_safe=yes
+       continue
+       ;;
+
+      -version-info)
+       prev=vinfo
+       continue
+       ;;
+
+      -version-number)
+       prev=vinfo
+       vinfo_number=yes
+       continue
+       ;;
+
+      -weak)
+        prev=weak
+       continue
+       ;;
+
+      -Wc,*)
+       func_stripname '-Wc,' '' "$arg"
+       args=$func_stripname_result
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+         func_append arg " $func_quote_for_eval_result"
+         func_append compiler_flags " $func_quote_for_eval_result"
+       done
+       IFS="$save_ifs"
+       func_stripname ' ' '' "$arg"
+       arg=$func_stripname_result
+       ;;
+
+      -Wl,*)
+       func_stripname '-Wl,' '' "$arg"
+       args=$func_stripname_result
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+         func_append arg " $wl$func_quote_for_eval_result"
+         func_append compiler_flags " $wl$func_quote_for_eval_result"
+         func_append linker_flags " $func_quote_for_eval_result"
+       done
+       IFS="$save_ifs"
+       func_stripname ' ' '' "$arg"
+       arg=$func_stripname_result
+       ;;
+
+      -Xcompiler)
+       prev=xcompiler
+       continue
+       ;;
+
+      -Xlinker)
+       prev=xlinker
+       continue
+       ;;
+
+      -XCClinker)
+       prev=xcclinker
+       continue
+       ;;
+
+      # -msg_* for osf cc
+      -msg_*)
+       func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+       ;;
+
+      # Flags to be passed through unchanged, with rationale:
+      # -64, -mips[0-9]      enable 64-bit mode for the SGI compiler
+      # -r[0-9][0-9]*        specify processor for the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+      # +DA*, +DD*           enable 64-bit mode for the HP compiler
+      # -q*                  compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+      # -F/path              path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-*  profiling flags for GCC
+      # @file                GCC response files
+      # -tp=*                Portland pgcc target processor selection
+      # --sysroot=*          for sysroot support
+      # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+      -O*|-flto*|-fwhopr*|-fuse-linker-plugin)
+        func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        func_append compiler_flags " $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+       ;;
+
+      *.$objext)
+       # A standard object.
+       func_append objs " $arg"
+       ;;
+
+      *.lo)
+       # A libtool-controlled object.
+
+       # Check to see that this really is a libtool object.
+       if func_lalib_unsafe_p "$arg"; then
+         pic_object=
+         non_pic_object=
+
+         # Read the .lo file
+         func_source "$arg"
+
+         if test -z "$pic_object" ||
+            test -z "$non_pic_object" ||
+            test "$pic_object" = none &&
+            test "$non_pic_object" = none; then
+           func_fatal_error "cannot find name of object for \`$arg'"
+         fi
+
+         # Extract subdirectory from the argument.
+         func_dirname "$arg" "/" ""
+         xdir="$func_dirname_result"
+
+         if test "$pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           pic_object="$xdir$pic_object"
+
+           if test "$prev" = dlfiles; then
+             if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+               func_append dlfiles " $pic_object"
+               prev=
+               continue
+             else
+               # If libtool objects are unsupported, then we need to preload.
+               prev=dlprefiles
+             fi
+           fi
+
+           # CHECK ME:  I think I busted this.  -Ossama
+           if test "$prev" = dlprefiles; then
+             # Preload the old-style object.
+             func_append dlprefiles " $pic_object"
+             prev=
+           fi
+
+           # A PIC object.
+           func_append libobjs " $pic_object"
+           arg="$pic_object"
+         fi
+
+         # Non-PIC object.
+         if test "$non_pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           non_pic_object="$xdir$non_pic_object"
+
+           # A standard non-PIC object
+           func_append non_pic_objects " $non_pic_object"
+           if test -z "$pic_object" || test "$pic_object" = none ; then
+             arg="$non_pic_object"
+           fi
+         else
+           # If the PIC object exists, use it instead.
+           # $xdir was prepended to $pic_object above.
+           non_pic_object="$pic_object"
+           func_append non_pic_objects " $non_pic_object"
+         fi
+       else
+         # Only an error if not doing a dry-run.
+         if $opt_dry_run; then
+           # Extract subdirectory from the argument.
+           func_dirname "$arg" "/" ""
+           xdir="$func_dirname_result"
+
+           func_lo2o "$arg"
+           pic_object=$xdir$objdir/$func_lo2o_result
+           non_pic_object=$xdir$func_lo2o_result
+           func_append libobjs " $pic_object"
+           func_append non_pic_objects " $non_pic_object"
+         else
+           func_fatal_error "\`$arg' is not a valid libtool object"
+         fi
+       fi
+       ;;
+
+      *.$libext)
+       # An archive.
+       func_append deplibs " $arg"
+       func_append old_deplibs " $arg"
+       continue
+       ;;
+
+      *.la)
+       # A libtool-controlled library.
+
+       func_resolve_sysroot "$arg"
+       if test "$prev" = dlfiles; then
+         # This library was specified with -dlopen.
+         func_append dlfiles " $func_resolve_sysroot_result"
+         prev=
+       elif test "$prev" = dlprefiles; then
+         # The library was specified with -dlpreopen.
+         func_append dlprefiles " $func_resolve_sysroot_result"
+         prev=
+       else
+         func_append deplibs " $func_resolve_sysroot_result"
+       fi
+       continue
+       ;;
+
+      # Some other compiler argument.
+      *)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+       ;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+       func_append compile_command " $arg"
+       func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    func_to_tool_file "$output_objdir/"
+    tool_output_objdir=$func_to_tool_file_result
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_preserve_dup_deps ; then
+       case "$libs " in
+       *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+       esac
+      fi
+      func_append libs " $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+       for pre_post_dep in $predeps $postdeps; do
+         case "$pre_post_deps " in
+         *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
+         esac
+         func_append pre_post_deps " $pre_post_dep"
+       done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+       passes="conv dlpreopen link"
+       for file in $dlfiles $dlprefiles; do
+         case $file in
+         *.la) ;;
+         *)
+           func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+           ;;
+         esac
+       done
+       ;;
+    prog)
+       compile_deplibs=
+       finalize_deplibs=
+       alldeplibs=no
+       newdlfiles=
+       newdlprefiles=
+       passes="conv scan dlopen dlpreopen link"
+       ;;
+    *)  passes="conv"
+       ;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+       ## FIXME: Find the place where the list is rebuilt in the wrong
+       ##        order, and fix it there properly
+        tmp_deplibs=
+       for deplib in $deplibs; do
+         tmp_deplibs="$deplib $tmp_deplibs"
+       done
+       deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+        test "$linkmode,$pass" = "prog,scan"; then
+       libs="$deplibs"
+       deplibs=
+      fi
+      if test "$linkmode" = prog; then
+       case $pass in
+       dlopen) libs="$dlfiles" ;;
+       dlpreopen) libs="$dlprefiles" ;;
+       link)
+         libs="$deplibs %DEPLIBS%"
+         test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+         ;;
+       esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+       # Collect and forward deplibs of preopened libtool libs
+       for lib in $dlprefiles; do
+         # Ignore non-libtool-libs
+         dependency_libs=
+         func_resolve_sysroot "$lib"
+         case $lib in
+         *.la) func_source "$func_resolve_sysroot_result" ;;
+         esac
+
+         # Collect preopened libtool deplibs, except any this library
+         # has declared as weak libs
+         for deplib in $dependency_libs; do
+           func_basename "$deplib"
+            deplib_base=$func_basename_result
+           case " $weak_libs " in
+           *" $deplib_base "*) ;;
+           *) func_append deplibs " $deplib" ;;
+           esac
+         done
+       done
+       libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+       # Collect dlpreopened libraries
+       save_deplibs="$deplibs"
+       deplibs=
+      fi
+
+      for deplib in $libs; do
+       lib=
+       found=no
+       case $deplib in
+       -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+        |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+         if test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$deplib $compile_deplibs"
+           finalize_deplibs="$deplib $finalize_deplibs"
+         else
+           func_append compiler_flags " $deplib"
+           if test "$linkmode" = lib ; then
+               case "$new_inherited_linker_flags " in
+                   *" $deplib "*) ;;
+                   * ) func_append new_inherited_linker_flags " $deplib" ;;
+               esac
+           fi
+         fi
+         continue
+         ;;
+       -l*)
+         if test "$linkmode" != lib && test "$linkmode" != prog; then
+           func_warning "\`-l' is ignored for archives/objects"
+           continue
+         fi
+         func_stripname '-l' '' "$deplib"
+         name=$func_stripname_result
+         if test "$linkmode" = lib; then
+           searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+         else
+           searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+         fi
+         for searchdir in $searchdirs; do
+           for search_ext in .la $std_shrext .so .a; do
+             # Search the libtool library
+             lib="$searchdir/lib${name}${search_ext}"
+             if test -f "$lib"; then
+               if test "$search_ext" = ".la"; then
+                 found=yes
+               else
+                 found=no
+               fi
+               break 2
+             fi
+           done
+         done
+         if test "$found" != yes; then
+           # deplib doesn't seem to be a libtool library
+           if test "$linkmode,$pass" = "prog,link"; then
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             deplibs="$deplib $deplibs"
+             test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+           fi
+           continue
+         else # deplib is a libtool library
+           # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+           # We need to do some special things here, and not later.
+           if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+             case " $predeps $postdeps " in
+             *" $deplib "*)
+               if func_lalib_p "$lib"; then
+                 library_names=
+                 old_library=
+                 func_source "$lib"
+                 for l in $old_library $library_names; do
+                   ll="$l"
+                 done
+                 if test "X$ll" = "X$old_library" ; then # only static version available
+                   found=no
+                   func_dirname "$lib" "" "."
+                   ladir="$func_dirname_result"
+                   lib=$ladir/$old_library
+                   if test "$linkmode,$pass" = "prog,link"; then
+                     compile_deplibs="$deplib $compile_deplibs"
+                     finalize_deplibs="$deplib $finalize_deplibs"
+                   else
+                     deplibs="$deplib $deplibs"
+                     test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+                   fi
+                   continue
+                 fi
+               fi
+               ;;
+             *) ;;
+             esac
+           fi
+         fi
+         ;; # -l
+       *.ltframework)
+         if test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$deplib $compile_deplibs"
+           finalize_deplibs="$deplib $finalize_deplibs"
+         else
+           deplibs="$deplib $deplibs"
+           if test "$linkmode" = lib ; then
+               case "$new_inherited_linker_flags " in
+                   *" $deplib "*) ;;
+                   * ) func_append new_inherited_linker_flags " $deplib" ;;
+               esac
+           fi
+         fi
+         continue
+         ;;
+       -L*)
+         case $linkmode in
+         lib)
+           deplibs="$deplib $deplibs"
+           test "$pass" = conv && continue
+           newdependency_libs="$deplib $newdependency_libs"
+           func_stripname '-L' '' "$deplib"
+           func_resolve_sysroot "$func_stripname_result"
+           func_append newlib_search_path " $func_resolve_sysroot_result"
+           ;;
+         prog)
+           if test "$pass" = conv; then
+             deplibs="$deplib $deplibs"
+             continue
+           fi
+           if test "$pass" = scan; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           func_stripname '-L' '' "$deplib"
+           func_resolve_sysroot "$func_stripname_result"
+           func_append newlib_search_path " $func_resolve_sysroot_result"
+           ;;
+         *)
+           func_warning "\`-L' is ignored for archives/objects"
+           ;;
+         esac # linkmode
+         continue
+         ;; # -L
+       -R*)
+         if test "$pass" = link; then
+           func_stripname '-R' '' "$deplib"
+           func_resolve_sysroot "$func_stripname_result"
+           dir=$func_resolve_sysroot_result
+           # Make sure the xrpath contains only unique directories.
+           case "$xrpath " in
+           *" $dir "*) ;;
+           *) func_append xrpath " $dir" ;;
+           esac
+         fi
+         deplibs="$deplib $deplibs"
+         continue
+         ;;
+       *.la)
+         func_resolve_sysroot "$deplib"
+         lib=$func_resolve_sysroot_result
+         ;;
+       *.$libext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+           continue
+         fi
+         case $linkmode in
+         lib)
+           # Linking convenience modules into shared libraries is allowed,
+           # but linking other static libraries is non-portable.
+           case " $dlpreconveniencelibs " in
+           *" $deplib "*) ;;
+           *)
+             valid_a_lib=no
+             case $deplibs_check_method in
+               match_pattern*)
+                 set dummy $deplibs_check_method; shift
+                 match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+                 if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+                   | $EGREP "$match_pattern_regex" > /dev/null; then
+                   valid_a_lib=yes
+                 fi
+               ;;
+               pass_all)
+                 valid_a_lib=yes
+               ;;
+             esac
+             if test "$valid_a_lib" != yes; then
+               echo
+               $ECHO "*** Warning: Trying to link with static lib archive $deplib."
+               echo "*** I have the capability to make that library automatically link in when"
+               echo "*** you link to this library.  But I can only do this if you have a"
+               echo "*** shared version of the library, which you do not appear to have"
+               echo "*** because the file extensions .$libext of this argument makes me believe"
+               echo "*** that it is just a static archive that I should not use here."
+             else
+               echo
+               $ECHO "*** Warning: Linking the shared library $output against the"
+               $ECHO "*** static library $deplib is not portable!"
+               deplibs="$deplib $deplibs"
+             fi
+             ;;
+           esac
+           continue
+           ;;
+         prog)
+           if test "$pass" != link; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           continue
+           ;;
+         esac # linkmode
+         ;; # *.$libext
+       *.lo | *.$objext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+         elif test "$linkmode" = prog; then
+           if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+             # If there is no dlopen support or we're linking statically,
+             # we need to preload.
+             func_append newdlprefiles " $deplib"
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             func_append newdlfiles " $deplib"
+           fi
+         fi
+         continue
+         ;;
+       %DEPLIBS%)
+         alldeplibs=yes
+         continue
+         ;;
+       esac # case $deplib
+
+       if test "$found" = yes || test -f "$lib"; then :
+       else
+         func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+       fi
+
+       # Check to see that this really is a libtool archive.
+       func_lalib_unsafe_p "$lib" \
+         || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+       func_dirname "$lib" "" "."
+       ladir="$func_dirname_result"
+
+       dlname=
+       dlopen=
+       dlpreopen=
+       libdir=
+       library_names=
+       old_library=
+       inherited_linker_flags=
+       # If the library was installed with an old release of libtool,
+       # it will not redefine variables installed, or shouldnotlink
+       installed=yes
+       shouldnotlink=no
+       avoidtemprpath=
+
+
+       # Read the .la file
+       func_source "$lib"
+
+       # Convert "-framework foo" to "foo.ltframework"
+       if test -n "$inherited_linker_flags"; then
+         tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+         for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+           case " $new_inherited_linker_flags " in
+             *" $tmp_inherited_linker_flag "*) ;;
+             *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
+           esac
+         done
+       fi
+       dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+       if test "$linkmode,$pass" = "lib,link" ||
+          test "$linkmode,$pass" = "prog,scan" ||
+          { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+         test -n "$dlopen" && func_append dlfiles " $dlopen"
+         test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
+       fi
+
+       if test "$pass" = conv; then
+         # Only check for convenience libraries
+         deplibs="$lib $deplibs"
+         if test -z "$libdir"; then
+           if test -z "$old_library"; then
+             func_fatal_error "cannot find name of link library for \`$lib'"
+           fi
+           # It is a libtool convenience library, so add in its objects.
+           func_append convenience " $ladir/$objdir/$old_library"
+           func_append old_convenience " $ladir/$objdir/$old_library"
+           tmp_libs=
+           for deplib in $dependency_libs; do
+             deplibs="$deplib $deplibs"
+             if $opt_preserve_dup_deps ; then
+               case "$tmp_libs " in
+               *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+               esac
+             fi
+             func_append tmp_libs " $deplib"
+           done
+         elif test "$linkmode" != prog && test "$linkmode" != lib; then
+           func_fatal_error "\`$lib' is not a convenience library"
+         fi
+         continue
+       fi # $pass = conv
+
+
+       # Get the name of the library we link against.
+       linklib=
+       if test -n "$old_library" &&
+          { test "$prefer_static_libs" = yes ||
+            test "$prefer_static_libs,$installed" = "built,no"; }; then
+         linklib=$old_library
+       else
+         for l in $old_library $library_names; do
+           linklib="$l"
+         done
+       fi
+       if test -z "$linklib"; then
+         func_fatal_error "cannot find name of link library for \`$lib'"
+       fi
+
+       # This library was specified with -dlopen.
+       if test "$pass" = dlopen; then
+         if test -z "$libdir"; then
+           func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+         fi
+         if test -z "$dlname" ||
+            test "$dlopen_support" != yes ||
+            test "$build_libtool_libs" = no; then
+           # If there is no dlname, no dlopen support or we're linking
+           # statically, we need to preload.  We also need to preload any
+           # dependent libraries so libltdl's deplib preloader doesn't
+           # bomb out in the load deplibs phase.
+           func_append dlprefiles " $lib $dependency_libs"
+         else
+           func_append newdlfiles " $lib"
+         fi
+         continue
+       fi # $pass = dlopen
+
+       # We need an absolute path.
+       case $ladir in
+       [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+       *)
+         abs_ladir=`cd "$ladir" && pwd`
+         if test -z "$abs_ladir"; then
+           func_warning "cannot determine absolute directory name of \`$ladir'"
+           func_warning "passing it literally to the linker, although it might fail"
+           abs_ladir="$ladir"
+         fi
+         ;;
+       esac
+       func_basename "$lib"
+       laname="$func_basename_result"
+
+       # Find the relevant object directory and library name.
+       if test "X$installed" = Xyes; then
+         if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           func_warning "library \`$lib' was moved."
+           dir="$ladir"
+           absdir="$abs_ladir"
+           libdir="$abs_ladir"
+         else
+           dir="$lt_sysroot$libdir"
+           absdir="$lt_sysroot$libdir"
+         fi
+         test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+       else
+         if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           dir="$ladir"
+           absdir="$abs_ladir"
+           # Remove this search path later
+           func_append notinst_path " $abs_ladir"
+         else
+           dir="$ladir/$objdir"
+           absdir="$abs_ladir/$objdir"
+           # Remove this search path later
+           func_append notinst_path " $abs_ladir"
+         fi
+       fi # $installed = yes
+       func_stripname 'lib' '.la' "$laname"
+       name=$func_stripname_result
+
+       # This library was specified with -dlpreopen.
+       if test "$pass" = dlpreopen; then
+         if test -z "$libdir" && test "$linkmode" = prog; then
+           func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+         fi
+         case "$host" in
+           # special handling for platforms with PE-DLLs.
+           *cygwin* | *mingw* | *cegcc* )
+             # Linker will automatically link against shared library if both
+             # static and shared are present.  Therefore, ensure we extract
+             # symbols from the import library if a shared library is present
+             # (otherwise, the dlopen module name will be incorrect).  We do
+             # this by putting the import library name into $newdlprefiles.
+             # We recover the dlopen module name by 'saving' the la file
+             # name in a special purpose variable, and (later) extracting the
+             # dlname from the la file.
+             if test -n "$dlname"; then
+               func_tr_sh "$dir/$linklib"
+               eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+               func_append newdlprefiles " $dir/$linklib"
+             else
+               func_append newdlprefiles " $dir/$old_library"
+               # Keep a list of preopened convenience libraries to check
+               # that they are being used correctly in the link pass.
+               test -z "$libdir" && \
+                 func_append dlpreconveniencelibs " $dir/$old_library"
+             fi
+           ;;
+           * )
+             # Prefer using a static library (so that no silly _DYNAMIC symbols
+             # are required to link).
+             if test -n "$old_library"; then
+               func_append newdlprefiles " $dir/$old_library"
+               # Keep a list of preopened convenience libraries to check
+               # that they are being used correctly in the link pass.
+               test -z "$libdir" && \
+                 func_append dlpreconveniencelibs " $dir/$old_library"
+             # Otherwise, use the dlname, so that lt_dlopen finds it.
+             elif test -n "$dlname"; then
+               func_append newdlprefiles " $dir/$dlname"
+             else
+               func_append newdlprefiles " $dir/$linklib"
+             fi
+           ;;
+         esac
+       fi # $pass = dlpreopen
+
+       if test -z "$libdir"; then
+         # Link the convenience library
+         if test "$linkmode" = lib; then
+           deplibs="$dir/$old_library $deplibs"
+         elif test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$dir/$old_library $compile_deplibs"
+           finalize_deplibs="$dir/$old_library $finalize_deplibs"
+         else
+           deplibs="$lib $deplibs" # used for prog,scan pass
+         fi
+         continue
+       fi
+
+
+       if test "$linkmode" = prog && test "$pass" != link; then
+         func_append newlib_search_path " $ladir"
+         deplibs="$lib $deplibs"
+
+         linkalldeplibs=no
+         if test "$link_all_deplibs" != no || test -z "$library_names" ||
+            test "$build_libtool_libs" = no; then
+           linkalldeplibs=yes
+         fi
+
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           case $deplib in
+           -L*) func_stripname '-L' '' "$deplib"
+                func_resolve_sysroot "$func_stripname_result"
+                func_append newlib_search_path " $func_resolve_sysroot_result"
+                ;;
+           esac
+           # Need to link against all dependency_libs?
+           if test "$linkalldeplibs" = yes; then
+             deplibs="$deplib $deplibs"
+           else
+             # Need to hardcode shared library paths
+             # or/and link against static libraries
+             newdependency_libs="$deplib $newdependency_libs"
+           fi
+           if $opt_preserve_dup_deps ; then
+             case "$tmp_libs " in
+             *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+             esac
+           fi
+           func_append tmp_libs " $deplib"
+         done # for deplib
+         continue
+       fi # $linkmode = prog...
+
+       if test "$linkmode,$pass" = "prog,link"; then
+         if test -n "$library_names" &&
+            { { test "$prefer_static_libs" = no ||
+                test "$prefer_static_libs,$installed" = "built,yes"; } ||
+              test -z "$old_library"; }; then
+           # We need to hardcode the library path
+           if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+             # Make sure the rpath contains only unique directories.
+             case "$temp_rpath:" in
+             *"$absdir:"*) ;;
+             *) func_append temp_rpath "$absdir:" ;;
+             esac
+           fi
+
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) func_append compile_rpath " $absdir" ;;
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) func_append finalize_rpath " $libdir" ;;
+             esac
+             ;;
+           esac
+         fi # $linkmode,$pass = prog,link...
+
+         if test "$alldeplibs" = yes &&
+            { test "$deplibs_check_method" = pass_all ||
+              { test "$build_libtool_libs" = yes &&
+                test -n "$library_names"; }; }; then
+           # We only need to search for static libraries
+           continue
+         fi
+       fi
+
+       link_static=no # Whether the deplib will be linked statically
+       use_static_libs=$prefer_static_libs
+       if test "$use_static_libs" = built && test "$installed" = yes; then
+         use_static_libs=no
+       fi
+       if test -n "$library_names" &&
+          { test "$use_static_libs" = no || test -z "$old_library"; }; then
+         case $host in
+         *cygwin* | *mingw* | *cegcc*)
+             # No point in relinking DLLs because paths are not encoded
+             func_append notinst_deplibs " $lib"
+             need_relink=no
+           ;;
+         *)
+           if test "$installed" = no; then
+             func_append notinst_deplibs " $lib"
+             need_relink=yes
+           fi
+           ;;
+         esac
+         # This is a shared library
+
+         # Warn about portability, can't link against -module's on some
+         # systems (darwin).  Don't bleat about dlopened modules though!
+         dlopenmodule=""
+         for dlpremoduletest in $dlprefiles; do
+           if test "X$dlpremoduletest" = "X$lib"; then
+             dlopenmodule="$dlpremoduletest"
+             break
+           fi
+         done
+         if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+           echo
+           if test "$linkmode" = prog; then
+             $ECHO "*** Warning: Linking the executable $output against the loadable module"
+           else
+             $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+           fi
+           $ECHO "*** $linklib is not portable!"
+         fi
+         if test "$linkmode" = lib &&
+            test "$hardcode_into_libs" = yes; then
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) func_append compile_rpath " $absdir" ;;
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) func_append finalize_rpath " $libdir" ;;
+             esac
+             ;;
+           esac
+         fi
+
+         if test -n "$old_archive_from_expsyms_cmds"; then
+           # figure out the soname
+           set dummy $library_names
+           shift
+           realname="$1"
+           shift
+           libname=`eval "\\$ECHO \"$libname_spec\""`
+           # use dlname if we got it. it's perfectly good, no?
+           if test -n "$dlname"; then
+             soname="$dlname"
+           elif test -n "$soname_spec"; then
+             # bleh windows
+             case $host in
+             *cygwin* | mingw* | *cegcc*)
+               func_arith $current - $age
+               major=$func_arith_result
+               versuffix="-$major"
+               ;;
+             esac
+             eval soname=\"$soname_spec\"
+           else
+             soname="$realname"
+           fi
+
+           # Make a new name for the extract_expsyms_cmds to use
+           soroot="$soname"
+           func_basename "$soroot"
+           soname="$func_basename_result"
+           func_stripname 'lib' '.dll' "$soname"
+           newlib=libimp-$func_stripname_result.a
+
+           # If the library has no export list, then create one now
+           if test -f "$output_objdir/$soname-def"; then :
+           else
+             func_verbose "extracting exported symbol list from \`$soname'"
+             func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+           fi
+
+           # Create $newlib
+           if test -f "$output_objdir/$newlib"; then :; else
+             func_verbose "generating import library for \`$soname'"
+             func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+           fi
+           # make sure the library variables are pointing to the new library
+           dir=$output_objdir
+           linklib=$newlib
+         fi # test -n "$old_archive_from_expsyms_cmds"
+
+         if test "$linkmode" = prog || test "$opt_mode" != relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           lib_linked=yes
+           case $hardcode_action in
+           immediate | unsupported)
+             if test "$hardcode_direct" = no; then
+               add="$dir/$linklib"
+               case $host in
+                 *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+                 *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+                 *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+                   *-*-unixware7*) add_dir="-L$dir" ;;
+                 *-*-darwin* )
+                   # if the lib is a (non-dlopened) module then we can not
+                   # link against it, someone is ignoring the earlier warnings
+                   if /usr/bin/file -L $add 2> /dev/null |
+                        $GREP ": [^:]* bundle" >/dev/null ; then
+                     if test "X$dlopenmodule" != "X$lib"; then
+                       $ECHO "*** Warning: lib $linklib is a module, not a shared library"
+                       if test -z "$old_library" ; then
+                         echo
+                         echo "*** And there doesn't seem to be a static archive available"
+                         echo "*** The link will probably fail, sorry"
+                       else
+                         add="$dir/$old_library"
+                       fi
+                     elif test -n "$old_library"; then
+                       add="$dir/$old_library"
+                     fi
+                   fi
+               esac
+             elif test "$hardcode_minus_L" = no; then
+               case $host in
+               *-*-sunos*) add_shlibpath="$dir" ;;
+               esac
+               add_dir="-L$dir"
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = no; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           relink)
+             if test "$hardcode_direct" = yes &&
+                test "$hardcode_direct_absolute" = no; then
+               add="$dir/$linklib"
+             elif test "$hardcode_minus_L" = yes; then
+               add_dir="-L$absdir"
+               # Try looking first in the location we're being installed to.
+               if test -n "$inst_prefix_dir"; then
+                 case $libdir in
+                   [\\/]*)
+                     func_append add_dir " -L$inst_prefix_dir$libdir"
+                     ;;
+                 esac
+               fi
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = yes; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           *) lib_linked=no ;;
+           esac
+
+           if test "$lib_linked" != yes; then
+             func_fatal_configuration "unsupported hardcode properties"
+           fi
+
+           if test -n "$add_shlibpath"; then
+             case :$compile_shlibpath: in
+             *":$add_shlibpath:"*) ;;
+             *) func_append compile_shlibpath "$add_shlibpath:" ;;
+             esac
+           fi
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+             test -n "$add" && compile_deplibs="$add $compile_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+             if test "$hardcode_direct" != yes &&
+                test "$hardcode_minus_L" != yes &&
+                test "$hardcode_shlibpath_var" = yes; then
+               case :$finalize_shlibpath: in
+               *":$libdir:"*) ;;
+               *) func_append finalize_shlibpath "$libdir:" ;;
+               esac
+             fi
+           fi
+         fi
+
+         if test "$linkmode" = prog || test "$opt_mode" = relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           # Finalize command for both is simple: just hardcode it.
+           if test "$hardcode_direct" = yes &&
+              test "$hardcode_direct_absolute" = no; then
+             add="$libdir/$linklib"
+           elif test "$hardcode_minus_L" = yes; then
+             add_dir="-L$libdir"
+             add="-l$name"
+           elif test "$hardcode_shlibpath_var" = yes; then
+             case :$finalize_shlibpath: in
+             *":$libdir:"*) ;;
+             *) func_append finalize_shlibpath "$libdir:" ;;
+             esac
+             add="-l$name"
+           elif test "$hardcode_automatic" = yes; then
+             if test -n "$inst_prefix_dir" &&
+                test -f "$inst_prefix_dir$libdir/$linklib" ; then
+               add="$inst_prefix_dir$libdir/$linklib"
+             else
+               add="$libdir/$linklib"
+             fi
+           else
+             # We cannot seem to hardcode it, guess we'll fake it.
+             add_dir="-L$libdir"
+             # Try looking first in the location we're being installed to.
+             if test -n "$inst_prefix_dir"; then
+               case $libdir in
+                 [\\/]*)
+                   func_append add_dir " -L$inst_prefix_dir$libdir"
+                   ;;
+               esac
+             fi
+             add="-l$name"
+           fi
+
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+             test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+           fi
+         fi
+       elif test "$linkmode" = prog; then
+         # Here we assume that one of hardcode_direct or hardcode_minus_L
+         # is not unsupported.  This is valid on all known static and
+         # shared platforms.
+         if test "$hardcode_direct" != unsupported; then
+           test -n "$old_library" && linklib="$old_library"
+           compile_deplibs="$dir/$linklib $compile_deplibs"
+           finalize_deplibs="$dir/$linklib $finalize_deplibs"
+         else
+           compile_deplibs="-l$name -L$dir $compile_deplibs"
+           finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+         fi
+       elif test "$build_libtool_libs" = yes; then
+         # Not a shared library
+         if test "$deplibs_check_method" != pass_all; then
+           # We're trying link a shared library against a static one
+           # but the system doesn't support it.
+
+           # Just print a warning and add the library to dependency_libs so
+           # that the program can be linked against the static library.
+           echo
+           $ECHO "*** Warning: This system can not link to static lib archive $lib."
+           echo "*** I have the capability to make that library automatically link in when"
+           echo "*** you link to this library.  But I can only do this if you have a"
+           echo "*** shared version of the library, which you do not appear to have."
+           if test "$module" = yes; then
+             echo "*** But as you try to build a module library, libtool will still create "
+             echo "*** a static module, that should work as long as the dlopening application"
+             echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+             if test -z "$global_symbol_pipe"; then
+               echo
+               echo "*** However, this would only work if libtool was able to extract symbol"
+               echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+               echo "*** not find such a program.  So, this module is probably useless."
+               echo "*** \`nm' from GNU binutils and a full rebuild may help."
+             fi
+             if test "$build_old_libs" = no; then
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         else
+           deplibs="$dir/$old_library $deplibs"
+           link_static=yes
+         fi
+       fi # link shared/static library?
+
+       if test "$linkmode" = lib; then
+         if test -n "$dependency_libs" &&
+            { test "$hardcode_into_libs" != yes ||
+              test "$build_old_libs" = yes ||
+              test "$link_static" = yes; }; then
+           # Extract -R from dependency_libs
+           temp_deplibs=
+           for libdir in $dependency_libs; do
+             case $libdir in
+             -R*) func_stripname '-R' '' "$libdir"
+                  temp_xrpath=$func_stripname_result
+                  case " $xrpath " in
+                  *" $temp_xrpath "*) ;;
+                  *) func_append xrpath " $temp_xrpath";;
+                  esac;;
+             *) func_append temp_deplibs " $libdir";;
+             esac
+           done
+           dependency_libs="$temp_deplibs"
+         fi
+
+         func_append newlib_search_path " $absdir"
+         # Link against this library
+         test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+         # ... and its dependency_libs
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           newdependency_libs="$deplib $newdependency_libs"
+           case $deplib in
+              -L*) func_stripname '-L' '' "$deplib"
+                   func_resolve_sysroot "$func_stripname_result";;
+              *) func_resolve_sysroot "$deplib" ;;
+            esac
+           if $opt_preserve_dup_deps ; then
+             case "$tmp_libs " in
+             *" $func_resolve_sysroot_result "*)
+                func_append specialdeplibs " $func_resolve_sysroot_result" ;;
+             esac
+           fi
+           func_append tmp_libs " $func_resolve_sysroot_result"
+         done
+
+         if test "$link_all_deplibs" != no; then
+           # Add the search paths of all dependency libraries
+           for deplib in $dependency_libs; do
+             path=
+             case $deplib in
+             -L*) path="$deplib" ;;
+             *.la)
+               func_resolve_sysroot "$deplib"
+               deplib=$func_resolve_sysroot_result
+               func_dirname "$deplib" "" "."
+               dir=$func_dirname_result
+               # We need an absolute path.
+               case $dir in
+               [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+               *)
+                 absdir=`cd "$dir" && pwd`
+                 if test -z "$absdir"; then
+                   func_warning "cannot determine absolute directory name of \`$dir'"
+                   absdir="$dir"
+                 fi
+                 ;;
+               esac
+               if $GREP "^installed=no" $deplib > /dev/null; then
+               case $host in
+               *-*-darwin*)
+                 depdepl=
+                 eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+                 if test -n "$deplibrary_names" ; then
+                   for tmp in $deplibrary_names ; do
+                     depdepl=$tmp
+                   done
+                   if test -f "$absdir/$objdir/$depdepl" ; then
+                     depdepl="$absdir/$objdir/$depdepl"
+                     darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+                     func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+                     func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}"
+                     path=
+                   fi
+                 fi
+                 ;;
+               *)
+                 path="-L$absdir/$objdir"
+                 ;;
+               esac
+               else
+                 eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+                 test -z "$libdir" && \
+                   func_fatal_error "\`$deplib' is not a valid libtool archive"
+                 test "$absdir" != "$libdir" && \
+                   func_warning "\`$deplib' seems to be moved"
+
+                 path="-L$absdir"
+               fi
+               ;;
+             esac
+             case " $deplibs " in
+             *" $path "*) ;;
+             *) deplibs="$path $deplibs" ;;
+             esac
+           done
+         fi # link_all_deplibs != no
+       fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+       if test "$linkmode" = "prog"; then
+         compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+         finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+       else
+         compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+       fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+       # Link the dlpreopened libraries before other libraries
+       for deplib in $save_deplibs; do
+         deplibs="$deplib $deplibs"
+       done
+      fi
+      if test "$pass" != dlopen; then
+       if test "$pass" != conv; then
+         # Make sure lib_search_path contains only unique directories.
+         lib_search_path=
+         for dir in $newlib_search_path; do
+           case "$lib_search_path " in
+           *" $dir "*) ;;
+           *) func_append lib_search_path " $dir" ;;
+           esac
+         done
+         newlib_search_path=
+       fi
+
+       if test "$linkmode,$pass" != "prog,link"; then
+         vars="deplibs"
+       else
+         vars="compile_deplibs finalize_deplibs"
+       fi
+       for var in $vars dependency_libs; do
+         # Add libraries to $var in reverse order
+         eval tmp_libs=\"\$$var\"
+         new_libs=
+         for deplib in $tmp_libs; do
+           # FIXME: Pedantically, this is the right thing to do, so
+           #        that some nasty dependency loop isn't accidentally
+           #        broken:
+           #new_libs="$deplib $new_libs"
+           # Pragmatically, this seems to cause very few problems in
+           # practice:
+           case $deplib in
+           -L*) new_libs="$deplib $new_libs" ;;
+           -R*) ;;
+           *)
+             # And here is the reason: when a library appears more
+             # than once as an explicit dependence of a library, or
+             # is implicitly linked in more than once by the
+             # compiler, it is considered special, and multiple
+             # occurrences thereof are not removed.  Compare this
+             # with having the same library being listed as a
+             # dependency of multiple other libraries: in this case,
+             # we know (pedantically, we assume) the library does not
+             # need to be listed more than once, so we keep only the
+             # last copy.  This is not always right, but it is rare
+             # enough that we require users that really mean to play
+             # such unportable linking tricks to link the library
+             # using -Wl,-lname, so that libtool does not consider it
+             # for duplicate removal.
+             case " $specialdeplibs " in
+             *" $deplib "*) new_libs="$deplib $new_libs" ;;
+             *)
+               case " $new_libs " in
+               *" $deplib "*) ;;
+               *) new_libs="$deplib $new_libs" ;;
+               esac
+               ;;
+             esac
+             ;;
+           esac
+         done
+         tmp_libs=
+         for deplib in $new_libs; do
+           case $deplib in
+           -L*)
+             case " $tmp_libs " in
+             *" $deplib "*) ;;
+             *) func_append tmp_libs " $deplib" ;;
+             esac
+             ;;
+           *) func_append tmp_libs " $deplib" ;;
+           esac
+         done
+         eval $var=\"$tmp_libs\"
+       done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+       case " $predeps $postdeps $compiler_lib_search_path " in
+       *" $i "*)
+         i=""
+         ;;
+       esac
+       if test -n "$i" ; then
+         func_append tmp_libs " $i"
+       fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+       func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+       func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+       func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+       func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+       func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+       func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      func_append objs "$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+       func_stripname 'lib' '.la' "$outputname"
+       name=$func_stripname_result
+       eval shared_ext=\"$shrext_cmds\"
+       eval libname=\"$libname_spec\"
+       ;;
+      *)
+       test "$module" = no && \
+         func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+       if test "$need_lib_prefix" != no; then
+         # Add the "lib" prefix for modules if required
+         func_stripname '' '.la' "$outputname"
+         name=$func_stripname_result
+         eval shared_ext=\"$shrext_cmds\"
+         eval libname=\"$libname_spec\"
+       else
+         func_stripname '' '.la' "$outputname"
+         libname=$func_stripname_result
+       fi
+       ;;
+      esac
+
+      if test -n "$objs"; then
+       if test "$deplibs_check_method" != pass_all; then
+         func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+       else
+         echo
+         $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+         $ECHO "*** objects $objs is not portable!"
+         func_append libobjs " $objs"
+       fi
+      fi
+
+      test "$dlself" != no && \
+       func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+       func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+       if test "$build_libtool_libs" = yes; then
+         # Building a libtool convenience library.
+         # Some compilers have problems with a `.al' extension so
+         # convenience libraries should have the same extension an
+         # archive normally would.
+         oldlibs="$output_objdir/$libname.$libext $oldlibs"
+         build_libtool_libs=convenience
+         build_old_libs=yes
+       fi
+
+       test -n "$vinfo" && \
+         func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+       test -n "$release" && \
+         func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+       # Parse the version information argument.
+       save_ifs="$IFS"; IFS=':'
+       set dummy $vinfo 0 0 0
+       shift
+       IFS="$save_ifs"
+
+       test -n "$7" && \
+         func_fatal_help "too many parameters to \`-version-info'"
+
+       # convert absolute version numbers to libtool ages
+       # this retains compatibility with .la files and attempts
+       # to make the code below a bit more comprehensible
+
+       case $vinfo_number in
+       yes)
+         number_major="$1"
+         number_minor="$2"
+         number_revision="$3"
+         #
+         # There are really only two kinds -- those that
+         # use the current revision as the major version
+         # and those that subtract age and use age as
+         # a minor version.  But, then there is irix
+         # which has an extra 1 added just for fun
+         #
+         case $version_type in
+         # correct linux to gnu/linux during the next big refactor
+         darwin|linux|osf|windows|none)
+           func_arith $number_major + $number_minor
+           current=$func_arith_result
+           age="$number_minor"
+           revision="$number_revision"
+           ;;
+         freebsd-aout|freebsd-elf|qnx|sunos)
+           current="$number_major"
+           revision="$number_minor"
+           age="0"
+           ;;
+         irix|nonstopux)
+           func_arith $number_major + $number_minor
+           current=$func_arith_result
+           age="$number_minor"
+           revision="$number_minor"
+           lt_irix_increment=no
+           ;;
+         *)
+           func_fatal_configuration "$modename: unknown library version type \`$version_type'"
+           ;;
+         esac
+         ;;
+       no)
+         current="$1"
+         revision="$2"
+         age="$3"
+         ;;
+       esac
+
+       # Check that each of the things are valid numbers.
+       case $current in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         func_error "CURRENT \`$current' must be a nonnegative integer"
+         func_fatal_error "\`$vinfo' is not valid version information"
+         ;;
+       esac
+
+       case $revision in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         func_error "REVISION \`$revision' must be a nonnegative integer"
+         func_fatal_error "\`$vinfo' is not valid version information"
+         ;;
+       esac
+
+       case $age in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         func_error "AGE \`$age' must be a nonnegative integer"
+         func_fatal_error "\`$vinfo' is not valid version information"
+         ;;
+       esac
+
+       if test "$age" -gt "$current"; then
+         func_error "AGE \`$age' is greater than the current interface number \`$current'"
+         func_fatal_error "\`$vinfo' is not valid version information"
+       fi
+
+       # Calculate the version variables.
+       major=
+       versuffix=
+       verstring=
+       case $version_type in
+       none) ;;
+
+       darwin)
+         # Like Linux, but with the current version available in
+         # verstring for coding it into the library header
+         func_arith $current - $age
+         major=.$func_arith_result
+         versuffix="$major.$age.$revision"
+         # Darwin ld doesn't like 0 for these options...
+         func_arith $current + 1
+         minor_current=$func_arith_result
+         xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+         verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+         ;;
+
+       freebsd-aout)
+         major=".$current"
+         versuffix=".$current.$revision";
+         ;;
+
+       freebsd-elf)
+         major=".$current"
+         versuffix=".$current"
+         ;;
+
+       irix | nonstopux)
+         if test "X$lt_irix_increment" = "Xno"; then
+           func_arith $current - $age
+         else
+           func_arith $current - $age + 1
+         fi
+         major=$func_arith_result
+
+         case $version_type in
+           nonstopux) verstring_prefix=nonstopux ;;
+           *)         verstring_prefix=sgi ;;
+         esac
+         verstring="$verstring_prefix$major.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$revision
+         while test "$loop" -ne 0; do
+           func_arith $revision - $loop
+           iface=$func_arith_result
+           func_arith $loop - 1
+           loop=$func_arith_result
+           verstring="$verstring_prefix$major.$iface:$verstring"
+         done
+
+         # Before this point, $major must not contain `.'.
+         major=.$major
+         versuffix="$major.$revision"
+         ;;
+
+       linux) # correct to gnu/linux during the next big refactor
+         func_arith $current - $age
+         major=.$func_arith_result
+         versuffix="$major.$age.$revision"
+         ;;
+
+       osf)
+         func_arith $current - $age
+         major=.$func_arith_result
+         versuffix=".$current.$age.$revision"
+         verstring="$current.$age.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$age
+         while test "$loop" -ne 0; do
+           func_arith $current - $loop
+           iface=$func_arith_result
+           func_arith $loop - 1
+           loop=$func_arith_result
+           verstring="$verstring:${iface}.0"
+         done
+
+         # Make executables depend on our current version.
+         func_append verstring ":${current}.0"
+         ;;
+
+       qnx)
+         major=".$current"
+         versuffix=".$current"
+         ;;
+
+       sunos)
+         major=".$current"
+         versuffix=".$current.$revision"
+         ;;
+
+       windows)
+         # Use '-' rather than '.', since we only want one
+         # extension on DOS 8.3 filesystems.
+         func_arith $current - $age
+         major=$func_arith_result
+         versuffix="-$major"
+         ;;
+
+       *)
+         func_fatal_configuration "unknown library version type \`$version_type'"
+         ;;
+       esac
+
+       # Clear the version info if we defaulted, and they specified a release.
+       if test -z "$vinfo" && test -n "$release"; then
+         major=
+         case $version_type in
+         darwin)
+           # we can't check for "0.0" in archive_cmds due to quoting
+           # problems, so we reset it completely
+           verstring=
+           ;;
+         *)
+           verstring="0.0"
+           ;;
+         esac
+         if test "$need_version" = no; then
+           versuffix=
+         else
+           versuffix=".0.0"
+         fi
+       fi
+
+       # Remove version info from name if versioning should be avoided
+       if test "$avoid_version" = yes && test "$need_version" = no; then
+         major=
+         versuffix=
+         verstring=""
+       fi
+
+       # Check to see if the archive will have undefined symbols.
+       if test "$allow_undefined" = yes; then
+         if test "$allow_undefined_flag" = unsupported; then
+           func_warning "undefined symbols not allowed in $host shared libraries"
+           build_libtool_libs=no
+           build_old_libs=yes
+         fi
+       else
+         # Don't allow undefined symbols.
+         allow_undefined_flag="$no_undefined_flag"
+       fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      func_append libobjs " $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$opt_mode" != relink; then
+       # Remove our outputs, but don't remove object files since they
+       # may have been created when compiling PIC objects.
+       removelist=
+       tempremovelist=`$ECHO "$output_objdir/*"`
+       for p in $tempremovelist; do
+         case $p in
+           *.$objext | *.gcno)
+              ;;
+           $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+              if test "X$precious_files_regex" != "X"; then
+                if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+                then
+                  continue
+                fi
+              fi
+              func_append removelist " $p"
+              ;;
+           *) ;;
+         esac
+       done
+       test -n "$removelist" && \
+         func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+       func_append oldlibs " $output_objdir/$libname.$libext"
+
+       # Transform .lo files to .o files.
+       oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #        lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+      #        deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+      #        dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       temp_xrpath=
+       for libdir in $xrpath; do
+         func_replace_sysroot "$libdir"
+         func_append temp_xrpath " -R$func_replace_sysroot_result"
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) func_append finalize_rpath " $libdir" ;;
+         esac
+       done
+       if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+         dependency_libs="$temp_xrpath $dependency_libs"
+       fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+       case " $dlprefiles $dlfiles " in
+       *" $lib "*) ;;
+       *) func_append dlfiles " $lib" ;;
+       esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+       case "$dlprefiles " in
+       *" $lib "*) ;;
+       *) func_append dlprefiles " $lib" ;;
+       esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+       if test -n "$rpath"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+           # these systems don't actually have a c library (as such)!
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C library is in the System framework
+           func_append deplibs " System.ltframework"
+           ;;
+         *-*-netbsd*)
+           # Don't link with libc until the a.out ld.so is fixed.
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           ;;
+         *)
+           # Add libc to deplibs on all other systems if necessary.
+           if test "$build_libtool_need_lc" = "yes"; then
+             func_append deplibs " -lc"
+           fi
+           ;;
+         esac
+       fi
+
+       # Transform deplibs into only deplibs that can be linked in shared.
+       name_save=$name
+       libname_save=$libname
+       release_save=$release
+       versuffix_save=$versuffix
+       major_save=$major
+       # I'm not sure if I'm treating the release correctly.  I think
+       # release should show up in the -l (ie -lgmp5) so we don't want to
+       # add it in twice.  Is that correct?
+       release=""
+       versuffix=""
+       major=""
+       newdeplibs=
+       droppeddeps=no
+       case $deplibs_check_method in
+       pass_all)
+         # Don't check for shared/static.  Everything works.
+         # This might be a little naive.  We might want to check
+         # whether the library exists or not.  But this is on
+         # osf3 & osf4 and I'm not really sure... Just
+         # implementing what was already the behavior.
+         newdeplibs=$deplibs
+         ;;
+       test_compile)
+         # This code stresses the "libraries are programs" paradigm to its
+         # limits. Maybe even breaks it.  We compile a program, linking it
+         # against the deplibs as a proxy for the library.  Then we can check
+         # whether they linked in statically or dynamically with ldd.
+         $opt_dry_run || $RM conftest.c
+         cat > conftest.c <<EOF
+         int main() { return 0; }
+EOF
+         $opt_dry_run || $RM conftest
+         if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                 case " $predeps $postdeps " in
+                 *" $i "*)
+                   func_append newdeplibs " $i"
+                   i=""
+                   ;;
+                 esac
+               fi
+               if test -n "$i" ; then
+                 libname=`eval "\\$ECHO \"$libname_spec\""`
+                 deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                 set dummy $deplib_matches; shift
+                 deplib_match=$1
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   func_append newdeplibs " $i"
+                 else
+                   droppeddeps=yes
+                   echo
+                   $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                   echo "*** I have the capability to make that library automatically link in when"
+                   echo "*** you link to this library.  But I can only do this if you have a"
+                   echo "*** shared version of the library, which I believe you do not have"
+                   echo "*** because a test_compile did reveal that the linker did not use it for"
+                   echo "*** its dynamic dependency list that programs get resolved with at runtime."
+                 fi
+               fi
+               ;;
+             *)
+               func_append newdeplibs " $i"
+               ;;
+             esac
+           done
+         else
+           # Error occurred in the first compile.  Let's try to salvage
+           # the situation: Compile a separate program for each library.
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               $opt_dry_run || $RM conftest
+               if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+                 ldd_output=`ldd conftest`
+                 if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                   case " $predeps $postdeps " in
+                   *" $i "*)
+                     func_append newdeplibs " $i"
+                     i=""
+                     ;;
+                   esac
+                 fi
+                 if test -n "$i" ; then
+                   libname=`eval "\\$ECHO \"$libname_spec\""`
+                   deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                   set dummy $deplib_matches; shift
+                   deplib_match=$1
+                   if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                     func_append newdeplibs " $i"
+                   else
+                     droppeddeps=yes
+                     echo
+                     $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                     echo "*** I have the capability to make that library automatically link in when"
+                     echo "*** you link to this library.  But I can only do this if you have a"
+                     echo "*** shared version of the library, which you do not appear to have"
+                     echo "*** because a test_compile did reveal that the linker did not use this one"
+                     echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+                   fi
+                 fi
+               else
+                 droppeddeps=yes
+                 echo
+                 $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+                 echo "*** make it link in!  You will probably need to install it or some"
+                 echo "*** library that it depends on before this library will be fully"
+                 echo "*** functional.  Installing it before continuing would be even better."
+               fi
+               ;;
+             *)
+               func_append newdeplibs " $i"
+               ;;
+             esac
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method; shift
+         file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+         for a_deplib in $deplibs; do
+           case $a_deplib in
+           -l*)
+             func_stripname -l '' "$a_deplib"
+             name=$func_stripname_result
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 func_append newdeplibs " $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval "\\$ECHO \"$libname_spec\""`
+               if test -n "$file_magic_glob"; then
+                 libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
+               else
+                 libnameglob=$libname
+               fi
+               test "$want_nocaseglob" = yes && nocaseglob=`shopt -p nocaseglob`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 if test "$want_nocaseglob" = yes; then
+                   shopt -s nocaseglob
+                   potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+                   $nocaseglob
+                 else
+                   potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+                 fi
+                 for potent_lib in $potential_libs; do
+                     # Follow soft links.
+                     if ls -lLd "$potent_lib" 2>/dev/null |
+                        $GREP " -> " >/dev/null; then
+                       continue
+                     fi
+                     # The statement above tries to avoid entering an
+                     # endless loop below, in case of cyclic links.
+                     # We might still enter an endless loop, since a link
+                     # loop can be closed while we follow links,
+                     # but so what?
+                     potlib="$potent_lib"
+                     while test -h "$potlib" 2>/dev/null; do
+                       potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+                       case $potliblink in
+                       [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+                       *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";;
+                       esac
+                     done
+                     if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+                        $SED -e 10q |
+                        $EGREP "$file_magic_regex" > /dev/null; then
+                       func_append newdeplibs " $a_deplib"
+                       a_deplib=""
+                       break 2
+                     fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               echo
+               $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+               echo "*** I have the capability to make that library automatically link in when"
+               echo "*** you link to this library.  But I can only do this if you have a"
+               echo "*** shared version of the library, which you do not appear to have"
+               echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+               else
+                 $ECHO "*** with $libname and none of the candidates passed a file format test"
+                 $ECHO "*** using a file magic. Last file checked: $potlib"
+               fi
+             fi
+             ;;
+           *)
+             # Add a -L argument.
+             func_append newdeplibs " $a_deplib"
+             ;;
+           esac
+         done # Gone through all deplibs.
+         ;;
+       match_pattern*)
+         set dummy $deplibs_check_method; shift
+         match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+         for a_deplib in $deplibs; do
+           case $a_deplib in
+           -l*)
+             func_stripname -l '' "$a_deplib"
+             name=$func_stripname_result
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 func_append newdeplibs " $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval "\\$ECHO \"$libname_spec\""`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                 for potent_lib in $potential_libs; do
+                   potlib="$potent_lib" # see symlink-check above in file_magic test
+                   if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+                      $EGREP "$match_pattern_regex" > /dev/null; then
+                     func_append newdeplibs " $a_deplib"
+                     a_deplib=""
+                     break 2
+                   fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               echo
+               $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+               echo "*** I have the capability to make that library automatically link in when"
+               echo "*** you link to this library.  But I can only do this if you have a"
+               echo "*** shared version of the library, which you do not appear to have"
+               echo "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+               else
+                 $ECHO "*** with $libname and none of the candidates passed a file format test"
+                 $ECHO "*** using a regex pattern. Last file checked: $potlib"
+               fi
+             fi
+             ;;
+           *)
+             # Add a -L argument.
+             func_append newdeplibs " $a_deplib"
+             ;;
+           esac
+         done # Gone through all deplibs.
+         ;;
+       none | unknown | *)
+         newdeplibs=""
+         tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+         if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+           for i in $predeps $postdeps ; do
+             # can't use Xsed below, because $i might contain '/'
+             tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"`
+           done
+         fi
+         case $tmp_deplibs in
+         *[!\  \ ]*)
+           echo
+           if test "X$deplibs_check_method" = "Xnone"; then
+             echo "*** Warning: inter-library dependencies are not supported in this platform."
+           else
+             echo "*** Warning: inter-library dependencies are not known to be supported."
+           fi
+           echo "*** All declared inter-library dependencies are being dropped."
+           droppeddeps=yes
+           ;;
+         esac
+         ;;
+       esac
+       versuffix=$versuffix_save
+       major=$major_save
+       release=$release_save
+       libname=$libname_save
+       name=$name_save
+
+       case $host in
+       *-*-rhapsody* | *-*-darwin1.[012])
+         # On Rhapsody replace the C library with the System framework
+         newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+         ;;
+       esac
+
+       if test "$droppeddeps" = yes; then
+         if test "$module" = yes; then
+           echo
+           echo "*** Warning: libtool could not satisfy all declared inter-library"
+           $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+           echo "*** a static module, that should work as long as the dlopening"
+           echo "*** application is linked with the -dlopen flag."
+           if test -z "$global_symbol_pipe"; then
+             echo
+             echo "*** However, this would only work if libtool was able to extract symbol"
+             echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+             echo "*** not find such a program.  So, this module is probably useless."
+             echo "*** \`nm' from GNU binutils and a full rebuild may help."
+           fi
+           if test "$build_old_libs" = no; then
+             oldlibs="$output_objdir/$libname.$libext"
+             build_libtool_libs=module
+             build_old_libs=yes
+           else
+             build_libtool_libs=no
+           fi
+         else
+           echo "*** The inter-library dependencies that have been dropped here will be"
+           echo "*** automatically added whenever a program is linked with this library"
+           echo "*** or is declared to -dlopen it."
+
+           if test "$allow_undefined" = no; then
+             echo
+             echo "*** Since this library must not contain undefined symbols,"
+             echo "*** because either the platform does not support them or"
+             echo "*** it was explicitly requested with -no-undefined,"
+             echo "*** libtool will only create a static version of it."
+             if test "$build_old_libs" = no; then
+               oldlibs="$output_objdir/$libname.$libext"
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         fi
+       fi
+       # Done checking deplibs!
+       deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+       *-*-darwin*)
+         newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+         new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+         deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+         ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $deplibs " in
+         *" -L$path/$objdir "*)
+           func_append new_libs " -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) func_append new_libs " $deplib" ;;
+         esac
+         ;;
+       *) func_append new_libs " $deplib" ;;
+       esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+       # Remove ${wl} instances when linking with ld.
+       # FIXME: should test the right _cmds variable.
+       case $archive_cmds in
+         *\$LD\ *) wl= ;;
+        esac
+       if test "$hardcode_into_libs" = yes; then
+         # Hardcode the library paths
+         hardcode_libdirs=
+         dep_rpath=
+         rpath="$finalize_rpath"
+         test "$opt_mode" != relink && rpath="$compile_rpath$rpath"
+         for libdir in $rpath; do
+           if test -n "$hardcode_libdir_flag_spec"; then
+             if test -n "$hardcode_libdir_separator"; then
+               func_replace_sysroot "$libdir"
+               libdir=$func_replace_sysroot_result
+               if test -z "$hardcode_libdirs"; then
+                 hardcode_libdirs="$libdir"
+               else
+                 # Just accumulate the unique libdirs.
+                 case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+                 *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+                   ;;
+                 *)
+                   func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+                   ;;
+                 esac
+               fi
+             else
+               eval flag=\"$hardcode_libdir_flag_spec\"
+               func_append dep_rpath " $flag"
+             fi
+           elif test -n "$runpath_var"; then
+             case "$perm_rpath " in
+             *" $libdir "*) ;;
+             *) func_append perm_rpath " $libdir" ;;
+             esac
+           fi
+         done
+         # Substitute the hardcoded libdirs into the rpath.
+         if test -n "$hardcode_libdir_separator" &&
+            test -n "$hardcode_libdirs"; then
+           libdir="$hardcode_libdirs"
+           eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+         fi
+         if test -n "$runpath_var" && test -n "$perm_rpath"; then
+           # We should set the runpath_var.
+           rpath=
+           for dir in $perm_rpath; do
+             func_append rpath "$dir:"
+           done
+           eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+         fi
+         test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+       fi
+
+       shlibpath="$finalize_shlibpath"
+       test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+       if test -n "$shlibpath"; then
+         eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+       fi
+
+       # Get the real and link names of the library.
+       eval shared_ext=\"$shrext_cmds\"
+       eval library_names=\"$library_names_spec\"
+       set dummy $library_names
+       shift
+       realname="$1"
+       shift
+
+       if test -n "$soname_spec"; then
+         eval soname=\"$soname_spec\"
+       else
+         soname="$realname"
+       fi
+       if test -z "$dlname"; then
+         dlname=$soname
+       fi
+
+       lib="$output_objdir/$realname"
+       linknames=
+       for link
+       do
+         func_append linknames " $link"
+       done
+
+       # Use standard objects if they are pic
+       test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+       test "X$libobjs" = "X " && libobjs=
+
+       delfiles=
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+         export_symbols="$output_objdir/$libname.uexp"
+         func_append delfiles " $export_symbols"
+       fi
+
+       orig_export_symbols=
+       case $host_os in
+       cygwin* | mingw* | cegcc*)
+         if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+           # exporting using user supplied symfile
+           if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+             # and it's NOT already a .def file. Must figure out
+             # which of the given symbols are data symbols and tag
+             # them as such. So, trigger use of export_symbols_cmds.
+             # export_symbols gets reassigned inside the "prepare
+             # the list of exported symbols" if statement, so the
+             # include_expsyms logic still works.
+             orig_export_symbols="$export_symbols"
+             export_symbols=
+             always_export_symbols=yes
+           fi
+         fi
+         ;;
+       esac
+
+       # Prepare the list of exported symbols
+       if test -z "$export_symbols"; then
+         if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+           func_verbose "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $opt_dry_run || $RM $export_symbols
+           cmds=$export_symbols_cmds
+           save_ifs="$IFS"; IFS='~'
+           for cmd1 in $cmds; do
+             IFS="$save_ifs"
+             # Take the normal branch if the nm_file_list_spec branch
+             # doesn't work or if tool conversion is not needed.
+             case $nm_file_list_spec~$to_tool_file_cmd in
+               *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+                 try_normal_branch=yes
+                 eval cmd=\"$cmd1\"
+                 func_len " $cmd"
+                 len=$func_len_result
+                 ;;
+               *)
+                 try_normal_branch=no
+                 ;;
+             esac
+             if test "$try_normal_branch" = yes \
+                && { test "$len" -lt "$max_cmd_len" \
+                     || test "$max_cmd_len" -le -1; }
+             then
+               func_show_eval "$cmd" 'exit $?'
+               skipped_export=false
+             elif test -n "$nm_file_list_spec"; then
+               func_basename "$output"
+               output_la=$func_basename_result
+               save_libobjs=$libobjs
+               save_output=$output
+               output=${output_objdir}/${output_la}.nm
+               func_to_tool_file "$output"
+               libobjs=$nm_file_list_spec$func_to_tool_file_result
+               func_append delfiles " $output"
+               func_verbose "creating $NM input file list: $output"
+               for obj in $save_libobjs; do
+                 func_to_tool_file "$obj"
+                 $ECHO "$func_to_tool_file_result"
+               done > "$output"
+               eval cmd=\"$cmd1\"
+               func_show_eval "$cmd" 'exit $?'
+               output=$save_output
+               libobjs=$save_libobjs
+               skipped_export=false
+             else
+               # The command line is too long to execute in one step.
+               func_verbose "using reloadable object file for export list..."
+               skipped_export=:
+               # Break out early, otherwise skipped_export may be
+               # set to false by a later but shorter cmd.
+               break
+             fi
+           done
+           IFS="$save_ifs"
+           if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+             func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+       fi
+
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         tmp_export_symbols="$export_symbols"
+         test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+         $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+       fi
+
+       if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+         # The given exports_symbols file has to be filtered, so filter it.
+         func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+         # FIXME: $output_objdir/$libname.filter potentially contains lots of
+         # 's' commands which not all seds can handle. GNU sed should be fine
+         # though. Also, the filter scales superlinearly with the number of
+         # global variables. join(1) would be nice here, but unfortunately
+         # isn't a blessed tool.
+         $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+         func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+         export_symbols=$output_objdir/$libname.def
+         $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+       fi
+
+       tmp_deplibs=
+       for test_deplib in $deplibs; do
+         case " $convenience " in
+         *" $test_deplib "*) ;;
+         *)
+           func_append tmp_deplibs " $test_deplib"
+           ;;
+         esac
+       done
+       deplibs="$tmp_deplibs"
+
+       if test -n "$convenience"; then
+         if test -n "$whole_archive_flag_spec" &&
+           test "$compiler_needs_object" = yes &&
+           test -z "$libobjs"; then
+           # extract the archives, so we have objects to list.
+           # TODO: could optimize this to just extract one archive.
+           whole_archive_flag_spec=
+         fi
+         if test -n "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+           test "X$libobjs" = "X " && libobjs=
+         else
+           gentop="$output_objdir/${outputname}x"
+           func_append generated " $gentop"
+
+           func_extract_archives $gentop $convenience
+           func_append libobjs " $func_extract_archives_result"
+           test "X$libobjs" = "X " && libobjs=
+         fi
+       fi
+
+       if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+         eval flag=\"$thread_safe_flag_spec\"
+         func_append linker_flags " $flag"
+       fi
+
+       # Make a backup of the uninstalled library when relinking
+       if test "$opt_mode" = relink; then
+         $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+       fi
+
+       # Do each of the archive commands.
+       if test "$module" = yes && test -n "$module_cmds" ; then
+         if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+           eval test_cmds=\"$module_expsym_cmds\"
+           cmds=$module_expsym_cmds
+         else
+           eval test_cmds=\"$module_cmds\"
+           cmds=$module_cmds
+         fi
+       else
+         if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+           eval test_cmds=\"$archive_expsym_cmds\"
+           cmds=$archive_expsym_cmds
+         else
+           eval test_cmds=\"$archive_cmds\"
+           cmds=$archive_cmds
+         fi
+       fi
+
+       if test "X$skipped_export" != "X:" &&
+          func_len " $test_cmds" &&
+          len=$func_len_result &&
+          test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         :
+       else
+         # The command line is too long to link in one step, link piecewise
+         # or, if using GNU ld and skipped_export is not :, use a linker
+         # script.
+
+         # Save the value of $output and $libobjs because we want to
+         # use them later.  If we have whole_archive_flag_spec, we
+         # want to use save_libobjs as it was before
+         # whole_archive_flag_spec was expanded, because we can't
+         # assume the linker understands whole_archive_flag_spec.
+         # This may have to be revisited, in case too many
+         # convenience libraries get linked in and end up exceeding
+         # the spec.
+         if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+         fi
+         save_output=$output
+         func_basename "$output"
+         output_la=$func_basename_result
+
+         # Clear the reloadable object creation command queue and
+         # initialize k to one.
+         test_cmds=
+         concat_cmds=
+         objlist=
+         last_robj=
+         k=1
+
+         if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+           output=${output_objdir}/${output_la}.lnkscript
+           func_verbose "creating GNU ld script: $output"
+           echo 'INPUT (' > $output
+           for obj in $save_libobjs
+           do
+             func_to_tool_file "$obj"
+             $ECHO "$func_to_tool_file_result" >> $output
+           done
+           echo ')' >> $output
+           func_append delfiles " $output"
+           func_to_tool_file "$output"
+           output=$func_to_tool_file_result
+         elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+           output=${output_objdir}/${output_la}.lnk
+           func_verbose "creating linker input file list: $output"
+           : > $output
+           set x $save_libobjs
+           shift
+           firstobj=
+           if test "$compiler_needs_object" = yes; then
+             firstobj="$1 "
+             shift
+           fi
+           for obj
+           do
+             func_to_tool_file "$obj"
+             $ECHO "$func_to_tool_file_result" >> $output
+           done
+           func_append delfiles " $output"
+           func_to_tool_file "$output"
+           output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
+         else
+           if test -n "$save_libobjs"; then
+             func_verbose "creating reloadable object files..."
+             output=$output_objdir/$output_la-${k}.$objext
+             eval test_cmds=\"$reload_cmds\"
+             func_len " $test_cmds"
+             len0=$func_len_result
+             len=$len0
+
+             # Loop over the list of objects to be linked.
+             for obj in $save_libobjs
+             do
+               func_len " $obj"
+               func_arith $len + $func_len_result
+               len=$func_arith_result
+               if test "X$objlist" = X ||
+                  test "$len" -lt "$max_cmd_len"; then
+                 func_append objlist " $obj"
+               else
+                 # The command $test_cmds is almost too long, add a
+                 # command to the queue.
+                 if test "$k" -eq 1 ; then
+                   # The first file doesn't have a previous command to add.
+                   reload_objs=$objlist
+                   eval concat_cmds=\"$reload_cmds\"
+                 else
+                   # All subsequent reloadable object files will link in
+                   # the last one created.
+                   reload_objs="$objlist $last_robj"
+                   eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
+                 fi
+                 last_robj=$output_objdir/$output_la-${k}.$objext
+                 func_arith $k + 1
+                 k=$func_arith_result
+                 output=$output_objdir/$output_la-${k}.$objext
+                 objlist=" $obj"
+                 func_len " $last_robj"
+                 func_arith $len0 + $func_len_result
+                 len=$func_arith_result
+               fi
+             done
+             # Handle the remaining objects by creating one last
+             # reloadable object file.  All subsequent reloadable object
+             # files will link in the last one created.
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             reload_objs="$objlist $last_robj"
+             eval concat_cmds=\"\${concat_cmds}$reload_cmds\"
+             if test -n "$last_robj"; then
+               eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+             fi
+             func_append delfiles " $output"
+
+           else
+             output=
+           fi
+
+           if ${skipped_export-false}; then
+             func_verbose "generating symbol list for \`$libname.la'"
+             export_symbols="$output_objdir/$libname.exp"
+             $opt_dry_run || $RM $export_symbols
+             libobjs=$output
+             # Append the command to create the export file.
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+             if test -n "$last_robj"; then
+               eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+             fi
+           fi
+
+           test -n "$save_libobjs" &&
+             func_verbose "creating a temporary reloadable object file: $output"
+
+           # Loop through the commands generated above and execute them.
+           save_ifs="$IFS"; IFS='~'
+           for cmd in $concat_cmds; do
+             IFS="$save_ifs"
+             $opt_silent || {
+                 func_quote_for_expand "$cmd"
+                 eval "func_echo $func_quote_for_expand_result"
+             }
+             $opt_dry_run || eval "$cmd" || {
+               lt_exit=$?
+
+               # Restore the uninstalled library and exit
+               if test "$opt_mode" = relink; then
+                 ( cd "$output_objdir" && \
+                   $RM "${realname}T" && \
+                   $MV "${realname}U" "$realname" )
+               fi
+
+               exit $lt_exit
+             }
+           done
+           IFS="$save_ifs"
+
+           if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+             func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+
+          if ${skipped_export-false}; then
+           if test -n "$export_symbols" && test -n "$include_expsyms"; then
+             tmp_export_symbols="$export_symbols"
+             test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+             $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+           fi
+
+           if test -n "$orig_export_symbols"; then
+             # The given exports_symbols file has to be filtered, so filter it.
+             func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+             # FIXME: $output_objdir/$libname.filter potentially contains lots of
+             # 's' commands which not all seds can handle. GNU sed should be fine
+             # though. Also, the filter scales superlinearly with the number of
+             # global variables. join(1) would be nice here, but unfortunately
+             # isn't a blessed tool.
+             $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+             func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+             export_symbols=$output_objdir/$libname.def
+             $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+           fi
+         fi
+
+         libobjs=$output
+         # Restore the value of output.
+         output=$save_output
+
+         if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+           test "X$libobjs" = "X " && libobjs=
+         fi
+         # Expand the library linking commands again to reset the
+         # value of $libobjs for piecewise linking.
+
+         # Do each of the archive commands.
+         if test "$module" = yes && test -n "$module_cmds" ; then
+           if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+             cmds=$module_expsym_cmds
+           else
+             cmds=$module_cmds
+           fi
+         else
+           if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+             cmds=$archive_expsym_cmds
+           else
+             cmds=$archive_cmds
+           fi
+         fi
+       fi
+
+       if test -n "$delfiles"; then
+         # Append the command to remove temporary files to $cmds.
+         eval cmds=\"\$cmds~\$RM $delfiles\"
+       fi
+
+       # Add any objects from preloaded convenience libraries
+       if test -n "$dlprefiles"; then
+         gentop="$output_objdir/${outputname}x"
+         func_append generated " $gentop"
+
+         func_extract_archives $gentop $dlprefiles
+         func_append libobjs " $func_extract_archives_result"
+         test "X$libobjs" = "X " && libobjs=
+       fi
+
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         eval cmd=\"$cmd\"
+         $opt_silent || {
+           func_quote_for_expand "$cmd"
+           eval "func_echo $func_quote_for_expand_result"
+         }
+         $opt_dry_run || eval "$cmd" || {
+           lt_exit=$?
+
+           # Restore the uninstalled library and exit
+           if test "$opt_mode" = relink; then
+             ( cd "$output_objdir" && \
+               $RM "${realname}T" && \
+               $MV "${realname}U" "$realname" )
+           fi
+
+           exit $lt_exit
+         }
+       done
+       IFS="$save_ifs"
+
+       # Restore the uninstalled library and exit
+       if test "$opt_mode" = relink; then
+         $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+         if test -n "$convenience"; then
+           if test -z "$whole_archive_flag_spec"; then
+             func_show_eval '${RM}r "$gentop"'
+           fi
+         fi
+
+         exit $EXIT_SUCCESS
+       fi
+
+       # Create links to the real library.
+       for linkname in $linknames; do
+         if test "$realname" != "$linkname"; then
+           func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+         fi
+       done
+
+       # If -module or -export-dynamic was specified, set the dlname.
+       if test "$module" = yes || test "$export_dynamic" = yes; then
+         # On all known operating systems, these are identical.
+         dlname="$soname"
+       fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+       func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+       func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+       func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+       func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+       func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+       test -n "$objs$old_deplibs" && \
+         func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+       libobj=$output
+       func_lo2o "$libobj"
+       obj=$func_lo2o_result
+       ;;
+      *)
+       libobj=
+       obj="$output"
+       ;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+       if test -n "$whole_archive_flag_spec"; then
+         eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+         reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+       else
+         gentop="$output_objdir/${obj}x"
+         func_append generated " $gentop"
+
+         func_extract_archives $gentop $convenience
+         reload_conv_objs="$reload_objs $func_extract_archives_result"
+       fi
+      fi
+
+      # If we're not building shared, we need to use non_pic_objs
+      test "$build_libtool_libs" != yes && libobjs="$non_pic_objects"
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+       if test -n "$gentop"; then
+         func_show_eval '${RM}r "$gentop"'
+       fi
+
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+       if test -n "$gentop"; then
+         func_show_eval '${RM}r "$gentop"'
+       fi
+
+       # Create an invalid libtool object if no PIC, so that we don't
+       # accidentally link it into a program.
+       # $show "echo timestamp > $libobj"
+       # $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+       exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+       # Only do commands if we really have different PIC objects.
+       reload_objs="$libobjs $reload_conv_objs"
+       output="$libobj"
+       func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+       func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+       *cygwin*) func_stripname '' '.exe' "$output"
+                 output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+       func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+       func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+       && test "$dlopen_self" = unknown \
+       && test "$dlopen_self_static" = unknown && \
+         func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+       # On Rhapsody replace the C library is the System framework
+       compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+       finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+       ;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+       # Don't allow lazy linking, it breaks C++ global constructors
+       # But is supposedly fixed on 10.4 or later (yay!).
+       if test "$tagname" = CXX ; then
+         case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+           10.[0123])
+             func_append compile_command " ${wl}-bind_at_load"
+             func_append finalize_command " ${wl}-bind_at_load"
+           ;;
+         esac
+       fi
+       # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+       compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+       finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+       ;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $compile_deplibs " in
+         *" -L$path/$objdir "*)
+           func_append new_libs " -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $compile_deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) func_append new_libs " $deplib" ;;
+         esac
+         ;;
+       *) func_append new_libs " $deplib" ;;
+       esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      func_append compile_command " $compile_deplibs"
+      func_append finalize_command " $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       for libdir in $rpath $xrpath; do
+         # This is the magic to use -rpath.
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) func_append finalize_rpath " $libdir" ;;
+         esac
+       done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           func_append rpath " $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$perm_rpath " in
+         *" $libdir "*) ;;
+         *) func_append perm_rpath " $libdir" ;;
+         esac
+       fi
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+         testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$libdir:"*) ;;
+         ::) dllsearchpath=$libdir;;
+         *) func_append dllsearchpath ":$libdir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         ::) dllsearchpath=$testbindir;;
+         *) func_append dllsearchpath ":$testbindir";;
+         esac
+         ;;
+       esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           func_append rpath " $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$finalize_perm_rpath " in
+         *" $libdir "*) ;;
+         *) func_append finalize_perm_rpath " $libdir" ;;
+         esac
+       fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+       # Transform all the library objects into standard objects.
+       compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+       finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+       func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cegcc* | *mingw32ce*)
+        # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+       # Replace the output file specification.
+       compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+       link_command="$compile_command$compile_rpath"
+
+       # We have no uninstalled library dependencies, so finalize right now.
+       exit_status=0
+       func_show_eval "$link_command" 'exit_status=$?'
+
+       if test -n "$postlink_cmds"; then
+         func_to_tool_file "$output"
+         postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+         func_execute_cmds "$postlink_cmds" 'exit $?'
+       fi
+
+       # Delete the generated files.
+       if test -f "$output_objdir/${outputname}S.${objext}"; then
+         func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+       fi
+
+       exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+       compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+       finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+       if test -n "$perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $perm_rpath; do
+           func_append rpath "$dir:"
+         done
+         compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+       if test -n "$finalize_perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $finalize_perm_rpath; do
+           func_append rpath "$dir:"
+         done
+         finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+      fi
+
+      if test "$no_install" = yes; then
+       # We don't need to create a wrapper script.
+       link_command="$compile_var$compile_command$compile_rpath"
+       # Replace the output file specification.
+       link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+       # Delete the old output file.
+       $opt_dry_run || $RM $output
+       # Link the executable and exit
+       func_show_eval "$link_command" 'exit $?'
+
+       if test -n "$postlink_cmds"; then
+         func_to_tool_file "$output"
+         postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+         func_execute_cmds "$postlink_cmds" 'exit $?'
+       fi
+
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+       # Fast installation is not supported
+       link_command="$compile_var$compile_command$compile_rpath"
+       relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+       func_warning "this platform does not like uninstalled shared libraries"
+       func_warning "\`$output' will be relinked during installation"
+      else
+       if test "$fast_install" != no; then
+         link_command="$finalize_var$compile_command$finalize_rpath"
+         if test "$fast_install" = yes; then
+           relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+         else
+           # fast_install is set to needless
+           relink_command=
+         fi
+       else
+         link_command="$compile_var$compile_command$compile_rpath"
+         relink_command="$finalize_var$finalize_command$finalize_rpath"
+       fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      if test -n "$postlink_cmds"; then
+       func_to_tool_file "$output_objdir/$outputname"
+       postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+       func_execute_cmds "$postlink_cmds" 'exit $?'
+      fi
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+       # Preserve any variables that may affect compiler behavior
+       for var in $variables_saved_for_relink; do
+         if eval test -z \"\${$var+set}\"; then
+           relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+         elif eval var_value=\$$var; test -z "$var_value"; then
+           relink_command="$var=; export $var; $relink_command"
+         else
+           func_quote_for_eval "$var_value"
+           relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+         fi
+       done
+       relink_command="(cd `pwd`; $relink_command)"
+       relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+       # win32 will think the script is a binary if it has
+       # a .exe suffix, so we strip it off here.
+       case $output in
+         *.exe) func_stripname '' '.exe' "$output"
+                output=$func_stripname_result ;;
+       esac
+       # test for cygwin because mv fails w/o .exe extensions
+       case $host in
+         *cygwin*)
+           exeext=.exe
+           func_stripname '' '.exe' "$outputname"
+           outputname=$func_stripname_result ;;
+         *) exeext= ;;
+       esac
+       case $host in
+         *cygwin* | *mingw* )
+           func_dirname_and_basename "$output" "" "."
+           output_name=$func_basename_result
+           output_path=$func_dirname_result
+           cwrappersource="$output_path/$objdir/lt-$output_name.c"
+           cwrapper="$output_path/$output_name.exe"
+           $RM $cwrappersource $cwrapper
+           trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+           func_emit_cwrapperexe_src > $cwrappersource
+
+           # The wrapper executable is built using the $host compiler,
+           # because it contains $host paths and files. If cross-
+           # compiling, it, like the target executable, must be
+           # executed on the $host or under an emulation environment.
+           $opt_dry_run || {
+             $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+             $STRIP $cwrapper
+           }
+
+           # Now, create the wrapper script for func_source use:
+           func_ltwrapper_scriptname $cwrapper
+           $RM $func_ltwrapper_scriptname_result
+           trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+           $opt_dry_run || {
+             # note: this script will not be executed, so do not chmod.
+             if test "x$build" = "x$host" ; then
+               $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+             else
+               func_emit_wrapper no > $func_ltwrapper_scriptname_result
+             fi
+           }
+         ;;
+         * )
+           $RM $output
+           trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+           func_emit_wrapper no > $output
+           chmod +x $output
+         ;;
+       esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+       oldobjs="$libobjs_save $symfileobj"
+       addlibs="$convenience"
+       build_libtool_libs=no
+      else
+       if test "$build_libtool_libs" = module; then
+         oldobjs="$libobjs_save"
+         build_libtool_libs=no
+       else
+         oldobjs="$old_deplibs $non_pic_objects"
+         if test "$preload" = yes && test -f "$symfileobj"; then
+           func_append oldobjs " $symfileobj"
+         fi
+       fi
+       addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+       gentop="$output_objdir/${outputname}x"
+       func_append generated " $gentop"
+
+       func_extract_archives $gentop $addlibs
+       func_append oldobjs " $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+       cmds=$old_archive_from_new_cmds
+      else
+
+       # Add any objects from preloaded convenience libraries
+       if test -n "$dlprefiles"; then
+         gentop="$output_objdir/${outputname}x"
+         func_append generated " $gentop"
+
+         func_extract_archives $gentop $dlprefiles
+         func_append oldobjs " $func_extract_archives_result"
+       fi
+
+       # POSIX demands no paths to be encoded in archives.  We have
+       # to avoid creating archives with duplicate basenames if we
+       # might have to extract them afterwards, e.g., when creating a
+       # static archive out of a convenience library, or when linking
+       # the entirety of a libtool archive into another (currently
+       # not supported by libtool).
+       if (for obj in $oldobjs
+           do
+             func_basename "$obj"
+             $ECHO "$func_basename_result"
+           done | sort | sort -uc >/dev/null 2>&1); then
+         :
+       else
+         echo "copying selected object files to avoid basename conflicts..."
+         gentop="$output_objdir/${outputname}x"
+         func_append generated " $gentop"
+         func_mkdir_p "$gentop"
+         save_oldobjs=$oldobjs
+         oldobjs=
+         counter=1
+         for obj in $save_oldobjs
+         do
+           func_basename "$obj"
+           objbase="$func_basename_result"
+           case " $oldobjs " in
+           " ") oldobjs=$obj ;;
+           *[\ /]"$objbase "*)
+             while :; do
+               # Make sure we don't pick an alternate name that also
+               # overlaps.
+               newobj=lt$counter-$objbase
+               func_arith $counter + 1
+               counter=$func_arith_result
+               case " $oldobjs " in
+               *[\ /]"$newobj "*) ;;
+               *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+               esac
+             done
+             func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+             func_append oldobjs " $gentop/$newobj"
+             ;;
+           *) func_append oldobjs " $obj" ;;
+           esac
+         done
+       fi
+       func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+       tool_oldlib=$func_to_tool_file_result
+       eval cmds=\"$old_archive_cmds\"
+
+       func_len " $cmds"
+       len=$func_len_result
+       if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         cmds=$old_archive_cmds
+       elif test -n "$archiver_list_spec"; then
+         func_verbose "using command file archive linking..."
+         for obj in $oldobjs
+         do
+           func_to_tool_file "$obj"
+           $ECHO "$func_to_tool_file_result"
+         done > $output_objdir/$libname.libcmd
+         func_to_tool_file "$output_objdir/$libname.libcmd"
+         oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+         cmds=$old_archive_cmds
+       else
+         # the command line is too long to link in one step, link in parts
+         func_verbose "using piecewise archive linking..."
+         save_RANLIB=$RANLIB
+         RANLIB=:
+         objlist=
+         concat_cmds=
+         save_oldobjs=$oldobjs
+         oldobjs=
+         # Is there a better way of finding the last object in the list?
+         for obj in $save_oldobjs
+         do
+           last_oldobj=$obj
+         done
+         eval test_cmds=\"$old_archive_cmds\"
+         func_len " $test_cmds"
+         len0=$func_len_result
+         len=$len0
+         for obj in $save_oldobjs
+         do
+           func_len " $obj"
+           func_arith $len + $func_len_result
+           len=$func_arith_result
+           func_append objlist " $obj"
+           if test "$len" -lt "$max_cmd_len"; then
+             :
+           else
+             # the above command should be used before it gets too long
+             oldobjs=$objlist
+             if test "$obj" = "$last_oldobj" ; then
+               RANLIB=$save_RANLIB
+             fi
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+             objlist=
+             len=$len0
+           fi
+         done
+         RANLIB=$save_RANLIB
+         oldobjs=$objlist
+         if test "X$oldobjs" = "X" ; then
+           eval cmds=\"\$concat_cmds\"
+         else
+           eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+         fi
+       fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+       if eval test -z \"\${$var+set}\"; then
+         relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+       elif eval var_value=\$$var; test -z "$var_value"; then
+         relink_command="$var=; export $var; $relink_command"
+       else
+         func_quote_for_eval "$var_value"
+         relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+       fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+       relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+       for installed in no yes; do
+         if test "$installed" = yes; then
+           if test -z "$install_libdir"; then
+             break
+           fi
+           output="$output_objdir/$outputname"i
+           # Replace all uninstalled libtool libraries with the installed ones
+           newdependency_libs=
+           for deplib in $dependency_libs; do
+             case $deplib in
+             *.la)
+               func_basename "$deplib"
+               name="$func_basename_result"
+               func_resolve_sysroot "$deplib"
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
+               test -z "$libdir" && \
+                 func_fatal_error "\`$deplib' is not a valid libtool archive"
+               func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
+               ;;
+             -L*)
+               func_stripname -L '' "$deplib"
+               func_replace_sysroot "$func_stripname_result"
+               func_append newdependency_libs " -L$func_replace_sysroot_result"
+               ;;
+             -R*)
+               func_stripname -R '' "$deplib"
+               func_replace_sysroot "$func_stripname_result"
+               func_append newdependency_libs " -R$func_replace_sysroot_result"
+               ;;
+             *) func_append newdependency_libs " $deplib" ;;
+             esac
+           done
+           dependency_libs="$newdependency_libs"
+           newdlfiles=
+
+           for lib in $dlfiles; do
+             case $lib in
+             *.la)
+               func_basename "$lib"
+               name="$func_basename_result"
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+               test -z "$libdir" && \
+                 func_fatal_error "\`$lib' is not a valid libtool archive"
+               func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
+               ;;
+             *) func_append newdlfiles " $lib" ;;
+             esac
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             case $lib in
+             *.la)
+               # Only pass preopened files to the pseudo-archive (for
+               # eventual linking with the app. that links it) if we
+               # didn't already link the preopened objects directly into
+               # the library:
+               func_basename "$lib"
+               name="$func_basename_result"
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+               test -z "$libdir" && \
+                 func_fatal_error "\`$lib' is not a valid libtool archive"
+               func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
+               ;;
+             esac
+           done
+           dlprefiles="$newdlprefiles"
+         else
+           newdlfiles=
+           for lib in $dlfiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             func_append newdlfiles " $abs"
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             func_append newdlprefiles " $abs"
+           done
+           dlprefiles="$newdlprefiles"
+         fi
+         $RM $output
+         # place dlname in correct position for cygwin
+         # In fact, it would be nice if we could use this code for all target
+         # systems that can't hard-code library paths into their executables
+         # and that have no shared library path variable independent of PATH,
+         # but it turns out we can't easily determine that from inspecting
+         # libtool variables, so we have to hard-code the OSs to which it
+         # applies here; at the moment, that means platforms that use the PE
+         # object format with DLL files.  See the long comment at the top of
+         # tests/bindir.at for full details.
+         tdlname=$dlname
+         case $host,$output,$installed,$module,$dlname in
+           *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+             # If a -bindir argument was supplied, place the dll there.
+             if test "x$bindir" != x ;
+             then
+               func_relative_path "$install_libdir" "$bindir"
+               tdlname=$func_relative_path_result$dlname
+             else
+               # Otherwise fall back on heuristic.
+               tdlname=../bin/$dlname
+             fi
+             ;;
+         esac
+         $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+         if test "$installed" = no && test "$need_relink" = yes; then
+           $ECHO >> $output "\
+relink_command=\"$relink_command\""
+         fi
+       done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$opt_mode" = link || test "$opt_mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) func_append RM " $arg"; rmforce=yes ;;
+      -*) func_append RM " $arg" ;;
+      *) func_append files " $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+       odir="$objdir"
+      else
+       odir="$dir/$objdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$opt_mode" = uninstall && odir="$dir"
+
+      # Remember odir for removal later, being careful to avoid duplicates
+      if test "$opt_mode" = clean; then
+       case " $rmdirs " in
+         *" $odir "*) ;;
+         *) func_append rmdirs " $odir" ;;
+       esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+        { test -h "$file"; } >/dev/null 2>&1 ||
+        test -f "$file"; then
+       :
+      elif test -d "$file"; then
+       exit_status=1
+       continue
+      elif test "$rmforce" = yes; then
+       continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+       # Possibly a libtool archive, so verify it.
+       if func_lalib_p "$file"; then
+         func_source $dir/$name
+
+         # Delete the libtool libraries and symlinks.
+         for n in $library_names; do
+           func_append rmfiles " $odir/$n"
+         done
+         test -n "$old_library" && func_append rmfiles " $odir/$old_library"
+
+         case "$opt_mode" in
+         clean)
+           case " $library_names " in
+           *" $dlname "*) ;;
+           *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
+           esac
+           test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
+           ;;
+         uninstall)
+           if test -n "$library_names"; then
+             # Do each command in the postuninstall commands.
+             func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+           fi
+
+           if test -n "$old_library"; then
+             # Do each command in the old_postuninstall commands.
+             func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+           fi
+           # FIXME: should reinstall the best remaining shared library.
+           ;;
+         esac
+       fi
+       ;;
+
+      *.lo)
+       # Possibly a libtool object, so verify it.
+       if func_lalib_p "$file"; then
+
+         # Read the .lo file
+         func_source $dir/$name
+
+         # Add PIC object to the list of files to remove.
+         if test -n "$pic_object" &&
+            test "$pic_object" != none; then
+           func_append rmfiles " $dir/$pic_object"
+         fi
+
+         # Add non-PIC object to the list of files to remove.
+         if test -n "$non_pic_object" &&
+            test "$non_pic_object" != none; then
+           func_append rmfiles " $dir/$non_pic_object"
+         fi
+       fi
+       ;;
+
+      *)
+       if test "$opt_mode" = clean ; then
+         noexename=$name
+         case $file in
+         *.exe)
+           func_stripname '' '.exe' "$file"
+           file=$func_stripname_result
+           func_stripname '' '.exe' "$name"
+           noexename=$func_stripname_result
+           # $file with .exe has already been added to rmfiles,
+           # add $file without .exe
+           func_append rmfiles " $file"
+           ;;
+         esac
+         # Do a test to see if this is a libtool program.
+         if func_ltwrapper_p "$file"; then
+           if func_ltwrapper_executable_p "$file"; then
+             func_ltwrapper_scriptname "$file"
+             relink_command=
+             func_source $func_ltwrapper_scriptname_result
+             func_append rmfiles " $func_ltwrapper_scriptname_result"
+           else
+             relink_command=
+             func_source $dir/$noexename
+           fi
+
+           # note $name still contains .exe if it was in $file originally
+           # as does the version of $file that was added into $rmfiles
+           func_append rmfiles " $odir/$name $odir/${name}S.${objext}"
+           if test "$fast_install" = yes && test -n "$relink_command"; then
+             func_append rmfiles " $odir/lt-$name"
+           fi
+           if test "X$noexename" != "X$name" ; then
+             func_append rmfiles " $odir/lt-${noexename}.c"
+           fi
+         fi
+       fi
+       ;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+       func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$opt_mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$opt_mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/libltdl/config/missing b/libltdl/config/missing
new file mode 100755 (executable)
index 0000000..db98974
--- /dev/null
@@ -0,0 +1,215 @@
+#! /bin/sh
+# Common wrapper for a few potentially missing GNU programs.
+
+scriptversion=2013-10-28.13; # UTC
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try '$0 --help' for more information"
+  exit 1
+fi
+
+case $1 in
+
+  --is-lightweight)
+    # Used by our autoconf macros to check whether the available missing
+    # script is modern enough.
+    exit 0
+    ;;
+
+  --run)
+    # Back-compat with the calling convention used by older automake.
+    shift
+    ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
+  bison     yacc      flex         lex       help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: unknown '$1' option"
+    echo 1>&2 "Try '$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch.  This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+  msg="probably too old"
+elif test $st -eq 127; then
+  # Program was missing.
+  msg="missing on your system"
+else
+  # Program was found and executed, but failed.  Give up.
+  exit $st
+fi
+
+perl_URL=http://www.perl.org/
+flex_URL=http://flex.sourceforge.net/
+gnu_software_URL=http://www.gnu.org/software
+
+program_details ()
+{
+  case $1 in
+    aclocal|automake)
+      echo "The '$1' program is part of the GNU Automake package:"
+      echo "<$gnu_software_URL/automake>"
+      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/autoconf>"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+    autoconf|autom4te|autoheader)
+      echo "The '$1' program is part of the GNU Autoconf package:"
+      echo "<$gnu_software_URL/autoconf/>"
+      echo "It also requires GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+  esac
+}
+
+give_advice ()
+{
+  # Normalize program name to check for.
+  normalized_program=`echo "$1" | sed '
+    s/^gnu-//; t
+    s/^gnu//; t
+    s/^g//; t'`
+
+  printf '%s\n' "'$1' is $msg."
+
+  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+  case $normalized_program in
+    autoconf*)
+      echo "You should only need it if you modified 'configure.ac',"
+      echo "or m4 files included by it."
+      program_details 'autoconf'
+      ;;
+    autoheader*)
+      echo "You should only need it if you modified 'acconfig.h' or"
+      echo "$configure_deps."
+      program_details 'autoheader'
+      ;;
+    automake*)
+      echo "You should only need it if you modified 'Makefile.am' or"
+      echo "$configure_deps."
+      program_details 'automake'
+      ;;
+    aclocal*)
+      echo "You should only need it if you modified 'acinclude.m4' or"
+      echo "$configure_deps."
+      program_details 'aclocal'
+      ;;
+   autom4te*)
+      echo "You might have modified some maintainer files that require"
+      echo "the 'autom4te' program to be rebuilt."
+      program_details 'autom4te'
+      ;;
+    bison*|yacc*)
+      echo "You should only need it if you modified a '.y' file."
+      echo "You may want to install the GNU Bison package:"
+      echo "<$gnu_software_URL/bison/>"
+      ;;
+    lex*|flex*)
+      echo "You should only need it if you modified a '.l' file."
+      echo "You may want to install the Fast Lexical Analyzer package:"
+      echo "<$flex_URL>"
+      ;;
+    help2man*)
+      echo "You should only need it if you modified a dependency" \
+           "of a man page."
+      echo "You may want to install the GNU Help2man package:"
+      echo "<$gnu_software_URL/help2man/>"
+    ;;
+    makeinfo*)
+      echo "You should only need it if you modified a '.texi' file, or"
+      echo "any other file indirectly affecting the aspect of the manual."
+      echo "You might want to install the Texinfo package:"
+      echo "<$gnu_software_URL/texinfo/>"
+      echo "The spurious makeinfo call might also be the consequence of"
+      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+      echo "want to install GNU make:"
+      echo "<$gnu_software_URL/make/>"
+      ;;
+    *)
+      echo "You might have modified some files without having the proper"
+      echo "tools for further handling them.  Check the 'README' file, it"
+      echo "often tells you about the needed prerequisites for installing"
+      echo "this package.  You may also peek at any GNU archive site, in"
+      echo "case some other package contains this missing '$1' program."
+      ;;
+  esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+                       -e '2,$s/^/         /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libltdl/config/test-driver b/libltdl/config/test-driver
new file mode 100755 (executable)
index 0000000..d306056
--- /dev/null
@@ -0,0 +1,139 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2013-07-13.22; # UTC
+
+# Copyright (C) 2011-2013 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+              [--expect-failure={yes|no}] [--color-tests={yes|no}]
+              [--enable-hard-errors={yes|no}] [--]
+              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+   *) break;;
+  esac
+  shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+  usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+  usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='\e[0;31m' # Red.
+  grn='\e[0;32m' # Green.
+  lgn='\e[1;32m' # Light green.
+  blu='\e[1;34m' # Blue.
+  mgn='\e[0;35m' # Magenta.
+  std='\e[m'     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  estatus=1
+fi
+
+case $estatus:$expect_failure in
+  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libltdl/config/ylwrap b/libltdl/config/ylwrap
new file mode 100755 (executable)
index 0000000..9253635
--- /dev/null
@@ -0,0 +1,226 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+
+scriptversion=2011-08-25.18; # UTC
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
+# 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case "$1" in
+  '')
+    echo "$0: No files given.  Try \`$0 --help' for more information." 1>&2
+    exit 1
+    ;;
+  --basedir)
+    basedir=$2
+    shift 2
+    ;;
+  -h|--h*)
+    cat <<\EOF
+Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+
+Wrapper for lex/yacc invocations, renaming files as desired.
+
+  INPUT is the input file
+  OUTPUT is one file PROG generates
+  DESIRED is the file we actually want instead of OUTPUT
+  PROGRAM is program to run
+  ARGS are passed to PROG
+
+Any number of OUTPUT,DESIRED pairs may be used.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v|--v*)
+    echo "ylwrap $scriptversion"
+    exit $?
+    ;;
+esac
+
+
+# The input.
+input="$1"
+shift
+case "$input" in
+  [\\/]* | ?:[\\/]*)
+    # Absolute path; do nothing.
+    ;;
+  *)
+    # Relative path.  Make it absolute.
+    input="`pwd`/$input"
+    ;;
+esac
+
+pairlist=
+while test "$#" -ne 0; do
+  if test "$1" = "--"; then
+    shift
+    break
+  fi
+  pairlist="$pairlist $1"
+  shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+  [\\/]* | ?:[\\/]*) ;;
+  *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines.  But that might take us over the 14-char limit.
+dirname=ylwrap$$
+do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret'
+trap "ret=129; $do_exit" 1
+trap "ret=130; $do_exit" 2
+trap "ret=141; $do_exit" 13
+trap "ret=143; $do_exit" 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+case $# in
+  0) "$prog" "$input" ;;
+  *) "$prog" "$@" "$input" ;;
+esac
+ret=$?
+
+if test $ret -eq 0; then
+  set X $pairlist
+  shift
+  first=yes
+  # Since DOS filename conventions don't allow two dots,
+  # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+  # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+  y_tab_nodot="no"
+  if test -f y_tab.c || test -f y_tab.h; then
+    y_tab_nodot="yes"
+  fi
+
+  # The directory holding the input.
+  input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+  # Quote $INPUT_DIR so we can use it in a regexp.
+  # FIXME: really we should care about more than `.' and `\'.
+  input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
+
+  while test "$#" -ne 0; do
+    from="$1"
+    # Handle y_tab.c and y_tab.h output by DOS
+    if test $y_tab_nodot = "yes"; then
+      if test $from = "y.tab.c"; then
+        from="y_tab.c"
+      else
+        if test $from = "y.tab.h"; then
+          from="y_tab.h"
+        fi
+      fi
+    fi
+    if test -f "$from"; then
+      # If $2 is an absolute path name, then just use that,
+      # otherwise prepend `../'.
+      case "$2" in
+        [\\/]* | ?:[\\/]*) target="$2";;
+        *) target="../$2";;
+      esac
+
+      # We do not want to overwrite a header file if it hasn't
+      # changed.  This avoid useless recompilations.  However the
+      # parser itself (the first file) should always be updated,
+      # because it is the destination of the .y.c rule in the
+      # Makefile.  Divert the output of all other files to a temporary
+      # file so we can compare them to existing versions.
+      if test $first = no; then
+        realtarget="$target"
+        target="tmp-`echo $target | sed s/.*[\\/]//g`"
+      fi
+      # Edit out `#line' or `#' directives.
+      #
+      # We don't want the resulting debug information to point at
+      # an absolute srcdir; it is better for it to just mention the
+      # .y file with no path.
+      #
+      # We want to use the real output file name, not yy.lex.c for
+      # instance.
+      #
+      # We want the include guards to be adjusted too.
+      FROM=`echo "$from" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+      TARGET=`echo "$2" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+
+      sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
+          -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
+
+      # Check whether header files must be updated.
+      if test $first = no; then
+        if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
+          echo "$2" is unchanged
+          rm -f "$target"
+        else
+          echo updating "$2"
+          mv -f "$target" "$realtarget"
+        fi
+      fi
+    else
+      # A missing file is only an error for the first file.  This
+      # is a blatant hack to let us support using "yacc -d".  If -d
+      # is not specified, we don't want an error when the header
+      # file is "missing".
+      if test $first = yes; then
+        ret=1
+      fi
+    fi
+    shift
+    shift
+    first=no
+  done
+else
+  ret=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libltdl/configure b/libltdl/configure
new file mode 100755 (executable)
index 0000000..5a23ad3
--- /dev/null
@@ -0,0 +1,15076 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for libltdl 2.4.2.
+#
+# Report bugs to <bug-libtool@gnu.org>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+  test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+      || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+        /*)
+          for as_base in sh bash ksh sh5; do
+            # Try only shells that exist, to save several forks.
+            as_shell=$as_dir/$as_base
+            if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+                   { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+                  if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+          done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+             { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org and
+$0: bug-libtool@gnu.org about your system, including any
+$0: error possibly output before this message. Then install
+$0: a modern shell, or manually run the script under such a
+$0: shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='libltdl'
+PACKAGE_TARNAME='libltdl'
+PACKAGE_VERSION='2.4.2'
+PACKAGE_STRING='libltdl 2.4.2'
+PACKAGE_BUGREPORT='bug-libtool@gnu.org'
+PACKAGE_URL=''
+
+ac_unique_file="ltdl.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LTDLOPEN
+LT_CONFIG_H
+CONVENIENCE_LTDL_FALSE
+CONVENIENCE_LTDL_TRUE
+INSTALL_LTDL_FALSE
+INSTALL_LTDL_TRUE
+ARGZ_H
+LIBOBJS
+sys_symbol_underscore
+LIBADD_DL
+LT_DLPREOPEN
+LIBADD_DLD_LINK
+LIBADD_SHL_LOAD
+LIBADD_DLOPEN
+LT_DLLOADERS
+CPP
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+RANLIB
+ac_ct_AR
+AR
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+OBJDUMP
+DLLTOOL
+AS
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+enable_dependency_tracking
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+enable_ltdl_install
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_myself" : 'X\(//\)[^/]' \| \
+        X"$as_myself" : 'X\(//\)$' \| \
+        X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures libltdl 2.4.2 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/libltdl]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of libltdl 2.4.2:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
+  --enable-shared[=PKGS]  build shared libraries [default=yes]
+  --enable-static[=PKGS]  build static libraries [default=yes]
+  --enable-fast-install[=PKGS]
+                          optimize for fast installation [default=yes]
+  --enable-dependency-tracking
+                          do not reject slow dependency extractors
+  --disable-dependency-tracking
+                          speeds up one-time build
+  --disable-libtool-lock  avoid locking (might break parallel builds)
+  --enable-ltdl-install   install libltdl
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-pic[=PKGS]       try to use only PIC/non-PIC objects [default=use
+                          both]
+  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
+  --with-sysroot=DIR Search for dependent libraries within DIR
+                        (or the compiler's sysroot if not specified).
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <bug-libtool@gnu.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+libltdl configure 2.4.2
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+        return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+           return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libltdl $as_me 2.4.2, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       $as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       # differences in whitespace do not lead to failure.
+       ac_old_val_w=`echo x $ac_old_val`
+       ac_new_val_w=`echo x $ac_new_val`
+       if test "$ac_old_val_w" != "$ac_new_val_w"; then
+         { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+         ac_cache_corrupted=:
+       else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+         eval $ac_var=\$ac_old_val
+       fi
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+       { $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_config_headers="$ac_config_headers config.h:config-h.in"
+
+
+ac_aux_dir=
+for ac_dir in config "$srcdir"/config; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+
+
+
+
+
+
+ # I am me!
+
+
+## ------------------------ ##
+## Automake Initialisation. ##
+## ------------------------ ##
+
+am__api_version='1.14'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           rm -rf conftest.one conftest.two conftest.dir
+           echo one > conftest.one
+           echo two > conftest.two
+           mkdir conftest.dir
+           if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+             test -s conftest.one && test -s conftest.two &&
+             test -s conftest.dir/conftest.one &&
+             test -s conftest.dir/conftest.two
+           then
+             ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+             break 3
+           fi
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \    ]*)
+    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$*" = "X"; then
+       # -L didn't work.
+       set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$*" != "X $srcdir/configure conftest.file" \
+       && test "$*" != "X conftest.file $srcdir/configure"; then
+
+       # If neither matched, then we have a broken ls.  This can happen
+       # if, for instance, CONFIG_SHELL is bash and it inherits a
+       # broken ls alias from the environment.  This has actually
+       # happened.  Such a system could not be considered "sane".
+       as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment" "$LINENO" 5
+     fi
+     if test "$2" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if ${ac_cv_path_mkdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+        for ac_exec_ext in '' $ac_executable_extensions; do
+          as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+          case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+            'mkdir (GNU coreutils) '* | \
+            'mkdir (coreutils) '* | \
+            'mkdir (fileutils) '4.1*)
+              ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+              break 3;;
+          esac
+        done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+       @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libltdl'
+ VERSION='2.4.2'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <http://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
+
+
+## ------------------------------- ##
+## Libtool specific configuration. ##
+## ------------------------------- ##
+pkgdatadir='${datadir}'"/${PACKAGE}"
+
+
+## ----------------------- ##
+## Libtool initialisation. ##
+## ----------------------- ##
+case `pwd` in
+  *\ * | *\    *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.2'
+macro_revision='1.3337'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO ""
+}
+
+case "$ECHO" in
+  printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+  print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+  *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from 'make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if ${ac_cv_path_FGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+   then ac_cv_path_FGREP="$GREP -F"
+   else
+     if test -z "$FGREP"; then
+  ac_path_FGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in fgrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+  # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'FGREP' >> "conftest.nl"
+    "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_FGREP="$ac_path_FGREP"
+      ac_path_FGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_FGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_FGREP"; then
+    as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_FGREP=$FGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+  with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [\\/]* | ?:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if ${lt_cv_path_NM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in dumpbin "link -dump"
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DUMPBIN"; then
+  ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$DUMPBIN" && break
+  done
+fi
+if test -z "$DUMPBIN"; then
+  ac_ct_DUMPBIN=$DUMPBIN
+  for ac_prog in dumpbin "link -dump"
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DUMPBIN"; then
+  ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_DUMPBIN" && break
+done
+
+  if test "x$ac_ct_DUMPBIN" = x; then
+    DUMPBIN=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DUMPBIN=$ac_ct_DUMPBIN
+  fi
+fi
+
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if ${lt_cv_nm_interface+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&5
+  (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+  cat conftest.out >&5
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if ${lt_cv_sys_max_cmd_len+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+    i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[         ]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \
+                = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,b/c, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+$as_echo_n "checking how to convert $build file names to $host format... " >&6; }
+if ${lt_cv_to_host_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+$as_echo "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
+if ${lt_cv_to_tool_file_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+$as_echo "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if ${lt_cv_ld_reload_flag+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test "$GCC" != yes; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if ${lt_cv_deplibs_check_method+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[45]*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[3-9]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DLLTOOL=$ac_ct_DLLTOOL
+  fi
+else
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+$as_echo_n "checking how to associate runtime and link libraries... " >&6; }
+if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+  ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in ar
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$AR" && break
+  done
+fi
+if test -z "$AR"; then
+  ac_ct_AR=$AR
+  for ac_prog in ar
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AR"; then
+  ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AR="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_AR" && break
+done
+
+  if test "x$ac_ct_AR" = x; then
+    AR="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AR=$ac_ct_AR
+  fi
+fi
+
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+$as_echo_n "checking for archiver @FILE support... " >&6; }
+if ${lt_cv_ar_at_file+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ar_at_file=no
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+      { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+      if test "$ac_status" -eq 0; then
+       # Ensure the archiver fails upon bogus file names.
+       rm -f conftest.$ac_objext libconftest.a
+       { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+  (eval $lt_ar_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+       if test "$ac_status" -ne 0; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+$as_echo "$lt_cv_ar_at_file" >&6; }
+
+if test "x$lt_cv_ar_at_file" = xno; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_RANLIB" = x; then
+    RANLIB=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    RANLIB=$ac_ct_RANLIB
+  fi
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if ${lt_cv_sys_global_symbol_pipe+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[BCDT]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[ABCDGISTW]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[ABCDEGRST]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[BCDEGRST]'
+  ;;
+osf*)
+  symcode='[BCDEGQRST]'
+  ;;
+solaris*)
+  symcode='[BDRT]'
+  ;;
+sco3.2v5*)
+  symcode='[DT]'
+  ;;
+sysv4.2uw2*)
+  symcode='[DT]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[ABDT]'
+  ;;
+sysv4)
+  symcode='[DFNSTU]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK '"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[     ]\($symcode$symcode*\)[         ][      ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+       if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+         cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+         cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_globsym_save_LIBS=$LIBS
+         lt_globsym_save_CFLAGS=$CFLAGS
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS=$lt_globsym_save_LIBS
+         CFLAGS=$lt_globsym_save_CFLAGS
+       else
+         echo "cannot find nm_test_func in $nlist" >&5
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&5
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "$progname: failed program was:" >&5
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+$as_echo_n "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+  withval=$with_sysroot;
+else
+  with_sysroot=no
+fi
+
+
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+   if test "$GCC" = yes; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5
+$as_echo "${with_sysroot}" >&6; }
+   as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+   ;;
+esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+$as_echo "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+  enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+       HPUX_IA64_MODE="32"
+       ;;
+      *ELF-64*)
+       HPUX_IA64_MODE="64"
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -melf32bsmip"
+         ;;
+       *N32*)
+         LD="${LD-ld} -melf32bmipn32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -melf64bmip"
+       ;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -32"
+         ;;
+       *N32*)
+         LD="${LD-ld} -n32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -64"
+         ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_i386_fbsd"
+           ;;
+         x86_64-*linux*)
+           case `/usr/bin/file conftest.o` in
+             *x86-64*)
+               LD="${LD-ld} -m elf32_x86_64"
+               ;;
+             *)
+               LD="${LD-ld} -m elf_i386"
+               ;;
+           esac
+           ;;
+         powerpc64le-*)
+           LD="${LD-ld} -m elf32lppclinux"
+           ;;
+         powerpc64-*)
+           LD="${LD-ld} -m elf32ppclinux"
+           ;;
+         s390x-*linux*)
+           LD="${LD-ld} -m elf_s390"
+           ;;
+         sparc64-*linux*)
+           LD="${LD-ld} -m elf32_sparc"
+           ;;
+       esac
+       ;;
+      *64-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_x86_64_fbsd"
+           ;;
+         x86_64-*linux*)
+           LD="${LD-ld} -m elf_x86_64"
+           ;;
+         powerpcle-*)
+           LD="${LD-ld} -m elf64lppc"
+           ;;
+         powerpc-*)
+           LD="${LD-ld} -m elf64ppc"
+           ;;
+         s390*-*linux*|s390*-*tpf*)
+           LD="${LD-ld} -m elf64_s390"
+           ;;
+         sparc*-*linux*)
+           LD="${LD-ld} -m elf64_sparc"
+           ;;
+       esac
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if ${lt_cv_cc_needs_belf+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+     cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_cc_needs_belf=yes
+else
+  lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+     ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD="${LD-ld}_sol2"
+        fi
+        ;;
+      *)
+       if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+         LD="${LD-ld} -64"
+       fi
+       ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$MANIFEST_TOOL"; then
+  ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+$as_echo "$MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+  ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+  # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_MANIFEST_TOOL"; then
+  ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+$as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_MANIFEST_TOOL" = x; then
+    MANIFEST_TOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+  fi
+else
+  MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if ${lt_cv_path_mainfest_tool+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&5
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+$as_echo "$lt_cv_path_mainfest_tool" >&6; }
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+  MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+  case $host_os in
+    rhapsody* | darwin*)
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DSYMUTIL"; then
+  ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+  ac_ct_DSYMUTIL=$DSYMUTIL
+  # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DSYMUTIL"; then
+  ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DSYMUTIL" = x; then
+    DSYMUTIL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DSYMUTIL=$ac_ct_DSYMUTIL
+  fi
+else
+  DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$NMEDIT"; then
+  ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+  ac_ct_NMEDIT=$NMEDIT
+  # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_NMEDIT"; then
+  ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_NMEDIT="nmedit"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_NMEDIT" = x; then
+    NMEDIT=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    NMEDIT=$ac_ct_NMEDIT
+  fi
+else
+  NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LIPO"; then
+  ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+  ac_ct_LIPO=$LIPO
+  # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_LIPO"; then
+  ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_LIPO="lipo"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_LIPO" = x; then
+    LIPO=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    LIPO=$ac_ct_LIPO
+  fi
+else
+  LIPO="$ac_cv_prog_LIPO"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL"; then
+  ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+  ac_ct_OTOOL=$OTOOL
+  # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL"; then
+  ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL="otool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL" = x; then
+    OTOOL=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL=$ac_ct_OTOOL
+  fi
+else
+  OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+    if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OTOOL64"; then
+  ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+  ac_ct_OTOOL64=$OTOOL64
+  # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OTOOL64"; then
+  ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OTOOL64="otool64"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OTOOL64" = x; then
+    OTOOL64=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OTOOL64=$ac_ct_OTOOL64
+  fi
+else
+  OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if ${lt_cv_apple_cc_single_mod+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+       # By default we will add the -single_module flag. You can override
+       # by either setting the environment variable LT_MULTI_MODULE
+       # non-empty at configure time, or by adding -multi_module to the
+       # link flags.
+       rm -rf libconftest.dylib*
+       echo "int foo(void){return 1;}" > conftest.c
+       echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+       $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+         -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+       # If there is a non-empty error log, and "single_module"
+       # appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+         cat conftest.err >&5
+       # Otherwise, if the output was created with a 0 exit code from
+       # the compiler, it worked.
+       elif test -f libconftest.dylib && test $_lt_result -eq 0; then
+         lt_cv_apple_cc_single_mod=yes
+       else
+         cat conftest.err >&5
+       fi
+       rm -rf libconftest.dylib*
+       rm -f conftest.*
+      fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if ${lt_cv_ld_exported_symbols_list+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_ld_exported_symbols_list=yes
+else
+  lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+       LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if ${lt_cv_ld_force_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+      echo "$AR cru libconftest.a conftest.o" >&5
+      $AR cru libconftest.a conftest.o 2>&5
+      echo "$RANLIB libconftest.a" >&5
+      $RANLIB libconftest.a 2>&5
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+       cat conftest.err >&5
+      elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then
+       lt_cv_ld_force_load=yes
+      else
+       cat conftest.err >&5
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+    case $host_os in
+    rhapsody* | darwin1.[012])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+       10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+       10.[012]*)
+         _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+       10.*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in dlfcn.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+# Set options
+enable_dlopen=yes
+enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AS"; then
+  ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AS="${ac_tool_prefix}as"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AS=$ac_cv_prog_AS
+if test -n "$AS"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5
+$as_echo "$AS" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AS"; then
+  ac_ct_AS=$AS
+  # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AS+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_AS"; then
+  ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_AS="as"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AS=$ac_cv_prog_ac_ct_AS
+if test -n "$ac_ct_AS"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5
+$as_echo "$ac_ct_AS" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_AS" = x; then
+    AS="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    AS=$ac_ct_AS
+  fi
+else
+  AS="$ac_cv_prog_AS"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$DLLTOOL"; then
+  ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+  ac_ct_DLLTOOL=$DLLTOOL
+  # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_DLLTOOL"; then
+  ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_DLLTOOL" = x; then
+    DLLTOOL="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    DLLTOOL=$ac_ct_DLLTOOL
+  fi
+else
+  DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$OBJDUMP"; then
+  ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+  ac_ct_OBJDUMP=$OBJDUMP
+  # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_OBJDUMP"; then
+  ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJDUMP="objdump"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_OBJDUMP" = x; then
+    OBJDUMP="false"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    OBJDUMP=$ac_ct_OBJDUMP
+  fi
+else
+  OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+  ;;
+esac
+
+test -z "$AS" && AS=as
+
+
+
+
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+            # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+  enableval=$enable_shared; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+  # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+  withval=$with_pic; lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for lt_pkg in $withval; do
+       IFS="$lt_save_ifs"
+       if test "X$lt_pkg" = "X$lt_p"; then
+         pic_mode=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+  # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+  enableval=$enable_fast_install; p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac
+else
+  enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if ${lt_cv_objdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+  case $cc_temp in
+    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/${ac_tool_prefix}file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $MAGIC_CMD in
+[\\/*] |  ?:[\\/]*)
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/file; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/file"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  else
+    MAGIC_CMD=:
+  fi
+fi
+
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+  *)
+    lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+  esac
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_rtti_exceptions=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="-fno-rtti -fno-exceptions"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_rtti_exceptions=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+    lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+    :
+fi
+
+fi
+
+
+
+
+
+
+  lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+  if test "$GCC" = yes; then
+    lt_prog_compiler_wl='-Wl,'
+    lt_prog_compiler_static='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            lt_prog_compiler_pic='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      lt_prog_compiler_pic='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      lt_prog_compiler_static=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='-fPIC'
+       ;;
+      esac
+      ;;
+
+    interix[3-9]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      lt_prog_compiler_can_build_shared=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       lt_prog_compiler_pic=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      lt_prog_compiler_pic='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      lt_prog_compiler_wl='-Xlinker '
+      if test -n "$lt_prog_compiler_pic"; then
+        lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      lt_prog_compiler_wl='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       lt_prog_compiler_static='-Bstatic'
+      else
+       lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      lt_prog_compiler_pic='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       lt_prog_compiler_pic='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      lt_prog_compiler_static='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      lt_prog_compiler_wl='-Wl,'
+      # PIC (with -KPIC) is the default.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-KPIC'
+       lt_prog_compiler_static='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-fPIC'
+       lt_prog_compiler_static='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='--shared'
+       lt_prog_compiler_static='--static'
+       ;;
+      nagfor*)
+       # NAG Fortran compiler
+       lt_prog_compiler_wl='-Wl,-Wl,,'
+       lt_prog_compiler_pic='-PIC'
+       lt_prog_compiler_static='-Bstatic'
+       ;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-fpic'
+       lt_prog_compiler_static='-Bstatic'
+        ;;
+      ccc*)
+        lt_prog_compiler_wl='-Wl,'
+        # All Alpha code is PIC.
+        lt_prog_compiler_static='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+       # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+       lt_prog_compiler_wl='-Wl,'
+       lt_prog_compiler_pic='-qpic'
+       lt_prog_compiler_static='-qstaticlink'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl=''
+         ;;
+       *Sun\ F* | *Sun*Fortran*)
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl='-Qoption ld '
+         ;;
+       *Sun\ C*)
+         # Sun C 5.9
+         lt_prog_compiler_pic='-KPIC'
+         lt_prog_compiler_static='-Bstatic'
+         lt_prog_compiler_wl='-Wl,'
+         ;;
+        *Intel*\ [CF]*Compiler*)
+         lt_prog_compiler_wl='-Wl,'
+         lt_prog_compiler_pic='-fPIC'
+         lt_prog_compiler_static='-static'
+         ;;
+       *Portland\ Group*)
+         lt_prog_compiler_wl='-Wl,'
+         lt_prog_compiler_pic='-fpic'
+         lt_prog_compiler_static='-Bstatic'
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    newsos6)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      lt_prog_compiler_pic='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      lt_prog_compiler_wl='-Wl,'
+      # All OSF/1 code is PIC.
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    rdos*)
+      lt_prog_compiler_static='-non_shared'
+      ;;
+
+    solaris*)
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+       lt_prog_compiler_wl='-Qoption ld ';;
+      *)
+       lt_prog_compiler_wl='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      lt_prog_compiler_wl='-Qoption ld '
+      lt_prog_compiler_pic='-PIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       lt_prog_compiler_pic='-Kconform_pic'
+       lt_prog_compiler_static='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_pic='-KPIC'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    unicos*)
+      lt_prog_compiler_wl='-Wl,'
+      lt_prog_compiler_can_build_shared=no
+      ;;
+
+    uts4*)
+      lt_prog_compiler_pic='-pic'
+      lt_prog_compiler_static='-Bstatic'
+      ;;
+
+    *)
+      lt_prog_compiler_can_build_shared=no
+      ;;
+    esac
+  fi
+
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    lt_prog_compiler_pic=
+    ;;
+  *)
+    lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+    ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+$as_echo "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_pic_works=no
+   ac_outfile=conftest.$ac_objext
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_pic_works=yes
+     fi
+   fi
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+    case $lt_prog_compiler_pic in
+     "" | " "*) ;;
+     *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+     esac
+else
+    lt_prog_compiler_pic=
+     lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_static_works=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler_static_works=yes
+       fi
+     else
+       lt_cv_prog_compiler_static_works=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+    :
+else
+    lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler_c_o=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&5
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       lt_cv_prog_compiler_c_o=yes
+     fi
+   fi
+   chmod u+w . 2>&5
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+  if test "$hard_links" = no; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+  runpath_var=
+  allow_undefined_flag=
+  always_export_symbols=no
+  archive_cmds=
+  archive_expsym_cmds=
+  compiler_needs_object=no
+  enable_shared_with_static_runtimes=no
+  export_dynamic_flag_spec=
+  export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  hardcode_automatic=no
+  hardcode_direct=no
+  hardcode_direct_absolute=no
+  hardcode_libdir_flag_spec=
+  hardcode_libdir_separator=
+  hardcode_minus_L=no
+  hardcode_shlibpath_var=unsupported
+  inherit_rpath=no
+  link_all_deplibs=unknown
+  module_cmds=
+  module_expsym_cmds=
+  old_archive_from_new_cmds=
+  old_archive_from_expsyms_cmds=
+  thread_safe_flag_spec=
+  whole_archive_flag_spec=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  include_expsyms=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    link_all_deplibs=no
+    ;;
+  esac
+
+  ld_shlibs=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+       # The AIX port of GNU ld has always aspired to compatibility
+       # with the native linker.  However, as the warning in the GNU ld
+       # block says, versions before 2.19.5* couldn't really create working
+       # shared libraries, regardless of the interface used.
+       case `$LD -v 2>&1` in
+         *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+         *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+         *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+         *)
+           lt_use_gnu_ld_interface=yes
+           ;;
+       esac
+       ;;
+      *)
+       lt_use_gnu_ld_interface=yes
+       ;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+    export_dynamic_flag_spec='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      whole_archive_flag_spec=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[3-9]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       allow_undefined_flag=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+      # as there is no search path for DLLs.
+      hardcode_libdir_flag_spec='-L$libdir'
+      export_dynamic_flag_spec='${wl}--export-all-symbols'
+      allow_undefined_flag=unsupported
+      always_export_symbols=no
+      enable_shared_with_static_runtimes=yes
+      export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+      exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    haiku*)
+      archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      link_all_deplibs=yes
+      ;;
+
+    interix[3-9]*)
+      hardcode_direct=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+      export_dynamic_flag_spec='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+       case $cc_basename in
+         diet\ *) tmp_diet=yes;;       # linux-dietlibc with static linking (!diet-dyn)
+       esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+        && test "$tmp_diet" = no
+      then
+       tmp_addflag=' $pic_flag'
+       tmp_sharedflag='-shared'
+       case $cc_basename,$host_cpu in
+        pgcc*)                         # Portland Group C compiler
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95* | pgfortran*)
+                                       # Portland Group f77 and f90 compilers
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)        # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       lf95*)                          # Lahey Fortran 8.1
+         whole_archive_flag_spec=
+         tmp_sharedflag='--shared' ;;
+       xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+         tmp_sharedflag='-qmkshrobj'
+         tmp_addflag= ;;
+       nvcc*)  # Cuda Compiler Driver 2.2
+         whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         compiler_needs_object=yes
+         ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         compiler_needs_object=yes
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       esac
+       archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+           cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+           echo "local: *; };" >> $output_objdir/$libname.ver~
+           $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+       case $cc_basename in
+       xlf* | bgf* | bgxlf* | mpixlf*)
+         # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+         whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+         hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+         archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+         if test "x$supports_anon_versioning" = xyes; then
+           archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+             cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+             echo "local: *; };" >> $output_objdir/$libname.ver~
+             $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+         fi
+         ;;
+       esac
+      else
+        ld_shlibs=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+       ld_shlibs=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         # For security reasons, it is highly recommended that you always
+         # use absolute paths for naming shared libraries, and exclude the
+         # DT_RUNPATH tag from executables and libraries.  But doing so
+         # requires that you compile everything twice, which is a pain.
+         if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+           hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+           archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         else
+           ld_shlibs=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+    esac
+
+    if test "$ld_shlibs" = no; then
+      runpath_var=
+      hardcode_libdir_flag_spec=
+      export_dynamic_flag_spec=
+      whole_archive_flag_spec=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      allow_undefined_flag=unsupported
+      always_export_symbols=yes
+      archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      hardcode_minus_L=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       hardcode_direct=unsupported
+      fi
+      ;;
+
+    aix[4-9]*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       # Also, AIX nm treats weak defined symbols like other global
+       # defined symbols, whereas GNU nm marks them as "W".
+       if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+         export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       else
+         export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      archive_cmds=''
+      hardcode_direct=yes
+      hardcode_direct_absolute=yes
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      file_list_spec='${wl}-f,'
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+          strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         hardcode_direct=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         hardcode_minus_L=yes
+         hardcode_libdir_flag_spec='-L$libdir'
+         hardcode_libdir_separator=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+       link_all_deplibs=no
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      export_dynamic_flag_spec='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      always_export_symbols=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       allow_undefined_flag='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+         /^0/ {
+             s/^0  *\([^ ]*\) *$/\1/
+             p
+         }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+        archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+       if test "$host_cpu" = ia64; then
+         hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+         allow_undefined_flag="-z nodefs"
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  if ${lt_cv_aix_libpath_+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+  lt_aix_libpath_sed='
+      /Import File Strings/,/^$/ {
+         /^0/ {
+             s/^0  *\([^ ]*\) *$/\1/
+             p
+         }
+      }'
+  lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+  if test -z "$lt_cv_aix_libpath_"; then
+    lt_cv_aix_libpath_="/usr/lib:/lib"
+  fi
+
+fi
+
+  aix_libpath=$lt_cv_aix_libpath_
+fi
+
+        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         no_undefined_flag=' ${wl}-bernotok'
+         allow_undefined_flag=' ${wl}-berok'
+         if test "$with_gnu_ld" = yes; then
+           # We only use this code for GNU lds that support --whole-archive.
+           whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+         else
+           # Exported symbols can be pulled into shared objects from archives
+           whole_archive_flag_spec='$convenience'
+         fi
+         archive_cmds_need_lc=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            archive_expsym_cmds=''
+        ;;
+      m68k)
+            archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            hardcode_libdir_flag_spec='-L$libdir'
+            hardcode_minus_L=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[45]*)
+      export_dynamic_flag_spec=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl*)
+       # Native MSVC
+       hardcode_libdir_flag_spec=' '
+       allow_undefined_flag=unsupported
+       always_export_symbols=yes
+       file_list_spec='@'
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+       archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+           sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+         else
+           sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+         fi~
+         $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+         linknames='
+       # The linker will not automatically build a static lib if we build a DLL.
+       # _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+       enable_shared_with_static_runtimes=yes
+       exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+       export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+       # Don't use ranlib
+       old_postinstall_cmds='chmod 644 $oldlib'
+       postlink_cmds='lt_outputfile="@OUTPUT@"~
+         lt_tool_outputfile="@TOOL_OUTPUT@"~
+         case $lt_outputfile in
+           *.exe|*.EXE) ;;
+           *)
+             lt_outputfile="$lt_outputfile.exe"
+             lt_tool_outputfile="$lt_tool_outputfile.exe"
+             ;;
+         esac~
+         if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+           $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+           $RM "$lt_outputfile.manifest";
+         fi'
+       ;;
+      *)
+       # Assume MSVC wrapper
+       hardcode_libdir_flag_spec=' '
+       allow_undefined_flag=unsupported
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+       # The linker will automatically build a .lib file if we build a DLL.
+       old_archive_from_new_cmds='true'
+       # FIXME: Should let the user specify the lib program.
+       old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+       enable_shared_with_static_runtimes=yes
+       ;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+
+
+  archive_cmds_need_lc=no
+  hardcode_direct=no
+  hardcode_automatic=yes
+  hardcode_shlibpath_var=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    whole_archive_flag_spec='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+  else
+    whole_archive_flag_spec=''
+  fi
+  link_all_deplibs=yes
+  allow_undefined_flag="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+  else
+  ld_shlibs=no
+  fi
+
+      ;;
+
+    dgux*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_direct=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      hardcode_minus_L=yes
+      export_dynamic_flag_spec='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+       hardcode_direct=yes
+       hardcode_direct_absolute=yes
+       export_dynamic_flag_spec='${wl}-E'
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       hardcode_minus_L=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+
+         # Older versions of the 11.00 compiler do not understand -b yet
+         # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+         { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if ${lt_cv_prog_compiler__b+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_prog_compiler__b=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS -b"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&5
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         lt_cv_prog_compiler__b=yes
+       fi
+     else
+       lt_cv_prog_compiler__b=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+    archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+    archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+       hardcode_libdir_separator=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         hardcode_direct=no
+         hardcode_shlibpath_var=no
+         ;;
+       *)
+         hardcode_direct=yes
+         hardcode_direct_absolute=yes
+         export_dynamic_flag_spec='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         hardcode_minus_L=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       # Try to use the -exported_symbol ld option, if it does not
+       # work, assume that -exports_file does not work either and
+       # implicitly export all symbols.
+       # This should be the same for all languages, so no per-tag cache variable.
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if ${lt_cv_irix_exported_symbol+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  save_LDFLAGS="$LDFLAGS"
+          LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+          cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  lt_cv_irix_exported_symbol=yes
+else
+  lt_cv_irix_exported_symbol=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+           LDFLAGS="$save_LDFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+$as_echo "$lt_cv_irix_exported_symbol" >&6; }
+       if test "$lt_cv_irix_exported_symbol" = yes; then
+          archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+       fi
+      else
+       archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      inherit_rpath=yes
+      link_all_deplibs=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_direct=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    newsos6)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_direct=yes
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      hardcode_shlibpath_var=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       hardcode_direct=yes
+       hardcode_shlibpath_var=no
+       hardcode_direct_absolute=yes
+       if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+         export_dynamic_flag_spec='${wl}-E'
+       else
+         case $host_os in
+          openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+            archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            hardcode_libdir_flag_spec='-R$libdir'
+            ;;
+          *)
+            archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+            ;;
+         esac
+       fi
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    os2*)
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_minus_L=yes
+      allow_undefined_flag=unsupported
+      archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      hardcode_libdir_separator=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+      else
+       allow_undefined_flag=' -expect_unresolved \*'
+       archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+       $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       hardcode_libdir_flag_spec='-rpath $libdir'
+      fi
+      archive_cmds_need_lc='no'
+      hardcode_libdir_separator=:
+      ;;
+
+    solaris*)
+      no_undefined_flag=' -z defs'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+       case `$CC -V 2>&1` in
+       *"Compilers 5.0"*)
+         wlarc=''
+         archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+         ;;
+       *)
+         wlarc='${wl}'
+         archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+         archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+         ;;
+       esac
+      fi
+      hardcode_libdir_flag_spec='-R$libdir'
+      hardcode_shlibpath_var=no
+      case $host_os in
+      solaris2.[0-5] | solaris2.[0-5].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      link_all_deplibs=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_direct=yes
+      hardcode_minus_L=yes
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         reload_cmds='$CC -r -o $output$reload_objs'
+         hardcode_direct=no
+        ;;
+       motorola)
+         archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      hardcode_shlibpath_var=no
+      ;;
+
+    sysv4.3*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_shlibpath_var=no
+      export_dynamic_flag_spec='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       hardcode_shlibpath_var=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       ld_shlibs=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+      no_undefined_flag='${wl}-z,text'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      no_undefined_flag='${wl}-z,text'
+      allow_undefined_flag='${wl}-z,nodefs'
+      archive_cmds_need_lc=no
+      hardcode_shlibpath_var=no
+      hardcode_libdir_flag_spec='${wl}-R,$libdir'
+      hardcode_libdir_separator=':'
+      link_all_deplibs=yes
+      export_dynamic_flag_spec='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      hardcode_libdir_flag_spec='-L$libdir'
+      hardcode_shlibpath_var=no
+      ;;
+
+    *)
+      ld_shlibs=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+       export_dynamic_flag_spec='${wl}-Blargedynsym'
+       ;;
+      esac
+    fi
+  fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+  # Assume -lc should be added
+  archive_cmds_need_lc=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $archive_cmds in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  $RM conftest*
+       echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+       if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } 2>conftest.err; then
+         soname=conftest
+         lib=conftest
+         libobjs=conftest.$ac_objext
+         deplibs=
+         wl=$lt_prog_compiler_wl
+         pic_flag=$lt_prog_compiler_pic
+         compiler_flags=-v
+         linker_flags=-v
+         verstring=
+         output_objdir=.
+         libname=conftest
+         lt_save_allow_undefined_flag=$allow_undefined_flag
+         allow_undefined_flag=
+         if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+  (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+         then
+           lt_cv_archive_cmds_need_lc=no
+         else
+           lt_cv_archive_cmds_need_lc=yes
+         fi
+         allow_undefined_flag=$lt_save_allow_undefined_flag
+       else
+         cat conftest.err 1>&5
+       fi
+       $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+      archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[lt_foo]++; }
+  if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[4-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[01] | aix4.[01].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[45]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[23].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+  freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[3-9]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux # correct to gnu/linux during the next big refactor
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+        LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  if  ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+  lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+
+fi
+
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[      ]*hwcap[        ]/d;s/[:,      ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[89] | openbsd2.[89].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+   test -n "$runpath_var" ||
+   test "X$hardcode_automatic" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$hardcode_direct" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+     test "$hardcode_minus_L" != no; then
+    # Linking always hardcodes the temporary library directory.
+    hardcode_action=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    hardcode_action=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+   test "$inherit_rpath" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+
+
+
+
+
+
+  if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+
+fi
+
+    ;;
+
+  *)
+    ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+  lt_cv_dlopen="shl_load"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+  ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen=yes
+else
+  ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self_static+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+         if test "$cross_compiling" = yes; then :
+  lt_cv_dlopen_self_static=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+      x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+    esac
+  else :
+    # compilation failed
+    lt_cv_dlopen_self_static=no
+  fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    else
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    fi
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    ;;
+  esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+  # Report which library types will actually be built
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[4-9]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+        ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which extension is used for runtime loadable modules" >&5
+$as_echo_n "checking which extension is used for runtime loadable modules... " >&6; }
+if ${libltdl_cv_shlibext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+module=yes
+eval libltdl_cv_shlibext=$shrext_cmds
+module=no
+eval libltdl_cv_shrext=$shrext_cmds
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_shlibext" >&5
+$as_echo "$libltdl_cv_shlibext" >&6; }
+if test -n "$libltdl_cv_shlibext"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LT_MODULE_EXT "$libltdl_cv_shlibext"
+_ACEOF
+
+fi
+if test "$libltdl_cv_shrext" != "$libltdl_cv_shlibext"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LT_SHARED_EXT "$libltdl_cv_shrext"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which variable specifies run-time module search path" >&5
+$as_echo_n "checking which variable specifies run-time module search path... " >&6; }
+if ${lt_cv_module_path_var+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_module_path_var="$shlibpath_var"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_module_path_var" >&5
+$as_echo "$lt_cv_module_path_var" >&6; }
+if test -n "$lt_cv_module_path_var"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LT_MODULE_PATH_VAR "$lt_cv_module_path_var"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the default library search path" >&5
+$as_echo_n "checking for the default library search path... " >&6; }
+if ${lt_cv_sys_dlsearch_path+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sys_dlsearch_path="$sys_lib_dlsearch_path_spec"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_dlsearch_path" >&5
+$as_echo "$lt_cv_sys_dlsearch_path" >&6; }
+if test -n "$lt_cv_sys_dlsearch_path"; then
+  sys_dlsearch_path=
+  for dir in $lt_cv_sys_dlsearch_path; do
+    if test -z "$sys_dlsearch_path"; then
+      sys_dlsearch_path="$dir"
+    else
+      sys_dlsearch_path="$sys_dlsearch_path$PATH_SEPARATOR$dir"
+    fi
+  done
+
+cat >>confdefs.h <<_ACEOF
+#define LT_DLSEARCH_PATH "$sys_dlsearch_path"
+_ACEOF
+
+fi
+
+
+LT_DLLOADERS=
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+LIBADD_DLOPEN=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_dlopen+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+  ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+$as_echo "#define HAVE_LIBDL 1" >>confdefs.h
+
+       if test "$ac_cv_search_dlopen" != "none required" ; then
+         LIBADD_DLOPEN="-ldl"
+       fi
+       libltdl_cv_lib_dl_dlopen="yes"
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if HAVE_DLFCN_H
+#  include <dlfcn.h>
+#endif
+
+int
+main ()
+{
+dlopen(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+$as_echo "#define HAVE_LIBDL 1" >>confdefs.h
+
+           libltdl_cv_func_dlopen="yes"
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_svld_dlopen=yes
+else
+  ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+
+$as_echo "#define HAVE_LIBDL 1" >>confdefs.h
+
+               LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes"
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"
+fi
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes
+then
+  lt_save_LIBS="$LIBS"
+  LIBS="$LIBS $LIBADD_DLOPEN"
+  for ac_func in dlerror
+do :
+  ac_fn_c_check_func "$LINENO" "dlerror" "ac_cv_func_dlerror"
+if test "x$ac_cv_func_dlerror" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DLERROR 1
+_ACEOF
+
+fi
+done
+
+  LIBS="$lt_save_LIBS"
+fi
+
+
+LIBADD_SHL_LOAD=
+ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+
+$as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h
+
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_shl_load=yes
+else
+  ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+
+$as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h
+
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"
+           LIBADD_SHL_LOAD="-ldld"
+fi
+
+fi
+
+
+
+case $host_os in
+darwin[1567].*)
+# We only want this for pre-Mac OS X 10.4.
+  ac_fn_c_check_func "$LINENO" "_dyld_func_lookup" "ac_cv_func__dyld_func_lookup"
+if test "x$ac_cv_func__dyld_func_lookup" = xyes; then :
+
+$as_echo "#define HAVE_DYLD 1" >>confdefs.h
+
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dyld.la"
+fi
+
+  ;;
+beos*)
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}load_add_on.la"
+  ;;
+cygwin* | mingw* | os2* | pw32*)
+  ac_fn_c_check_decl "$LINENO" "cygwin_conv_path" "ac_cv_have_decl_cygwin_conv_path" "#include <sys/cygwin.h>
+"
+if test "x$ac_cv_have_decl_cygwin_conv_path" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_CYGWIN_CONV_PATH $ac_have_decl
+_ACEOF
+
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}loadlibrary.la"
+  ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dld_dld_link=yes
+else
+  ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+
+$as_echo "#define HAVE_DLD 1" >>confdefs.h
+
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dld_link.la"
+fi
+
+
+
+
+LT_DLPREOPEN=
+if test -n "$LT_DLLOADERS"
+then
+  for lt_loader in $LT_DLLOADERS; do
+    LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen $lt_loader "
+  done
+
+$as_echo "#define HAVE_LIBDLLOADER 1" >>confdefs.h
+
+fi
+
+
+LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD"
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ prefix in compiled symbols" >&5
+$as_echo_n "checking for _ prefix in compiled symbols... " >&6; }
+if ${lt_cv_sys_symbol_underscore+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  lt_cv_sys_symbol_underscore=no
+  cat > conftest.$ac_ext <<_LT_EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\""; } >&5
+  (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s "$ac_nlist"; then
+      # See whether the symbols have a leading underscore.
+      if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+        lt_cv_sys_symbol_underscore=yes
+      else
+        if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+         :
+        else
+         echo "configure: cannot find nm_test_func in $ac_nlist" >&5
+        fi
+      fi
+    else
+      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5
+    fi
+  else
+    echo "configure: failed program was:" >&5
+    cat conftest.c >&5
+  fi
+  rm -rf conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_symbol_underscore" >&5
+$as_echo "$lt_cv_sys_symbol_underscore" >&6; }
+  sys_symbol_underscore=$lt_cv_sys_symbol_underscore
+
+
+if test x"$lt_cv_sys_symbol_underscore" = xyes; then
+  if test x"$libltdl_cv_func_dlopen" = xyes ||
+     test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have to add an underscore for dlsym" >&5
+$as_echo_n "checking whether we have to add an underscore for dlsym... " >&6; }
+if ${libltdl_cv_need_uscore+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  libltdl_cv_need_uscore=unknown
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $LIBADD_DLOPEN"
+         if test "$cross_compiling" = yes; then :
+  libltdl_cv_need_uscore=cross
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}
+_LT_EOF
+  if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&5 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;;
+      x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;;
+      x$lt_dlunknown|x*)  ;;
+    esac
+  else :
+    # compilation failed
+
+  fi
+fi
+rm -fr conftest*
+
+         LIBS="$save_LIBS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_need_uscore" >&5
+$as_echo "$libltdl_cv_need_uscore" >&6; }
+  fi
+fi
+
+if test x"$libltdl_cv_need_uscore" = xyes; then
+
+$as_echo "#define NEED_USCORE 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether deplibs are loaded by dlopen" >&5
+$as_echo_n "checking whether deplibs are loaded by dlopen... " >&6; }
+if ${lt_cv_sys_dlopen_deplibs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # PORTME does your system automatically load deplibs for dlopen?
+  # or its logical equivalent (e.g. shl_load for HP-UX < 11)
+  # For now, we just catch OSes we know something about -- in the
+  # future, we'll try test this programmatically.
+  lt_cv_sys_dlopen_deplibs=unknown
+  case $host_os in
+  aix3*|aix4.1.*|aix4.2.*)
+    # Unknown whether this is true for these versions of AIX, but
+    # we want this `case' here to explicitly catch those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  aix[4-9]*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  amigaos*)
+    case $host_cpu in
+    powerpc)
+      lt_cv_sys_dlopen_deplibs=no
+      ;;
+    esac
+    ;;
+  darwin*)
+    # Assuming the user has installed a libdl from somewhere, this is true
+    # If you are looking for one http://www.opendarwin.org/projects/dlcompat
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  freebsd* | dragonfly*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  gnu* | linux* | k*bsd*-gnu | kopensolaris*-gnu)
+    # GNU and its variants, using gnu ld.so (Glibc)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  hpux10*|hpux11*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  interix*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  irix[12345]*|irix6.[01]*)
+    # Catch all versions of IRIX before 6.2, and indicate that we don't
+    # know how it worked for any of those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  irix*)
+    # The case above catches anything before 6.2, and it's known that
+    # at 6.2 and later dlopen does load deplibs.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  openbsd*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  osf[1234]*)
+    # dlopen did load deplibs (at least at 4.x), but until the 5.x series,
+    # it did *not* use an RPATH in a shared library to find objects the
+    # library depends on, so we explicitly say `no'.
+    lt_cv_sys_dlopen_deplibs=no
+    ;;
+  osf5.0|osf5.0a|osf5.1)
+    # dlopen *does* load deplibs and with the right loader patch applied
+    # it even uses RPATH in a shared library to search for shared objects
+    # that the library depends on, but there's no easy way to know if that
+    # patch is installed.  Since this is the case, all we can really
+    # say is unknown -- it depends on the patch being installed.  If
+    # it is, this changes to `yes'.  Without it, it would be `no'.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  osf*)
+    # the two cases above should catch all versions of osf <= 5.1.  Read
+    # the comments above for what we know about them.
+    # At > 5.1, deplibs are loaded *and* any RPATH in a shared library
+    # is used to find them so we can finally say `yes'.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  qnx*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  solaris*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_dlopen_deplibs" >&5
+$as_echo "$lt_cv_sys_dlopen_deplibs" >&6; }
+if test "$lt_cv_sys_dlopen_deplibs" != yes; then
+
+$as_echo "#define LTDL_DLOPEN_DEPLIBS 1" >>confdefs.h
+
+fi
+
+:
+
+for ac_header in argz.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "argz.h" "ac_cv_header_argz_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_argz_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ARGZ_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_fn_c_check_type "$LINENO" "error_t" "ac_cv_type_error_t" "#if defined(HAVE_ARGZ_H)
+#  include <argz.h>
+#endif
+"
+if test "x$ac_cv_type_error_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ERROR_T 1
+_ACEOF
+
+
+else
+
+$as_echo "#define error_t int" >>confdefs.h
+
+
+$as_echo "#define __error_t_defined 1" >>confdefs.h
+
+fi
+
+
+ARGZ_H=
+for ac_func in argz_add argz_append argz_count argz_create_sep argz_insert \
+       argz_next argz_stringify
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  ARGZ_H=argz.h; case " $LIBOBJS " in
+  *" argz.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS argz.$ac_objext"
+ ;;
+esac
+
+fi
+done
+
+
+if test -z "$ARGZ_H"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if argz actually works" >&5
+$as_echo_n "checking if argz actually works... " >&6; }
+if ${lt_cv_sys_argz_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $host_os in #(
+        *cygwin*)
+          lt_cv_sys_argz_works=no
+          if test "$cross_compiling" != no; then
+            lt_cv_sys_argz_works="guessing no"
+          else
+            lt_sed_extract_leading_digits='s/^\([0-9\.]*\).*/\1/'
+            save_IFS=$IFS
+            IFS=-.
+            set x `uname -r | sed -e "$lt_sed_extract_leading_digits"`
+            IFS=$save_IFS
+            lt_os_major=${2-0}
+            lt_os_minor=${3-0}
+            lt_os_micro=${4-0}
+            if test "$lt_os_major" -gt 1 \
+               || { test "$lt_os_major" -eq 1 \
+                 && { test "$lt_os_minor" -gt 5 \
+                   || { test "$lt_os_minor" -eq 5 \
+                     && test "$lt_os_micro" -gt 24; }; }; }; then
+              lt_cv_sys_argz_works=yes
+            fi
+          fi
+          ;; #(
+        *) lt_cv_sys_argz_works=yes ;;
+        esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_argz_works" >&5
+$as_echo "$lt_cv_sys_argz_works" >&6; }
+     if test "$lt_cv_sys_argz_works" = yes; then :
+
+$as_echo "#define HAVE_WORKING_ARGZ 1" >>confdefs.h
+
+else
+  ARGZ_H=argz.h
+        case " $LIBOBJS " in
+  *" argz.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS argz.$ac_objext"
+ ;;
+esac
+
+fi
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libtool supports -dlopen/-dlpreopen" >&5
+$as_echo_n "checking whether libtool supports -dlopen/-dlpreopen... " >&6; }
+if ${libltdl_cv_preloaded_symbols+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$lt_cv_sys_global_symbol_pipe"; then
+    libltdl_cv_preloaded_symbols=yes
+  else
+    libltdl_cv_preloaded_symbols=no
+  fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_preloaded_symbols" >&5
+$as_echo "$libltdl_cv_preloaded_symbols" >&6; }
+if test x"$libltdl_cv_preloaded_symbols" = xyes; then
+
+$as_echo "#define HAVE_PRELOADED_SYMBOLS 1" >>confdefs.h
+
+fi
+
+
+
+# Check whether --enable-ltdl-install was given.
+if test "${enable_ltdl_install+set}" = set; then :
+  enableval=$enable_ltdl_install;
+fi
+
+
+case ,${enable_ltdl_install},${enable_ltdl_convenience} in
+  *yes*) ;;
+  *) enable_ltdl_convenience=yes ;;
+esac
+
+ if test x"${enable_ltdl_install-no}" != xno; then
+  INSTALL_LTDL_TRUE=
+  INSTALL_LTDL_FALSE='#'
+else
+  INSTALL_LTDL_TRUE='#'
+  INSTALL_LTDL_FALSE=
+fi
+
+  if test x"${enable_ltdl_convenience-no}" != xno; then
+  CONVENIENCE_LTDL_TRUE=
+  CONVENIENCE_LTDL_FALSE='#'
+else
+  CONVENIENCE_LTDL_TRUE='#'
+  CONVENIENCE_LTDL_FALSE=
+fi
+
+
+
+
+
+
+# In order that ltdl.c can compile, find out the first AC_CONFIG_HEADERS
+# the user used.  This is so that ltdl.h can pick up the parent projects
+# config.h file, The first file in AC_CONFIG_HEADERS must contain the
+# definitions required by ltdl.c.
+# FIXME: Remove use of undocumented AC_LIST_HEADERS (2.59 compatibility).
+
+
+
+for ac_header in unistd.h dl.h sys/dl.h dld.h mach-o/dyld.h dirent.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in closedir opendir readdir
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case " $LIBOBJS " in
+  *" lt__dirent.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS lt__dirent.$ac_objext"
+ ;;
+esac
+
+fi
+done
+
+for ac_func in strlcat strlcpy
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  case " $LIBOBJS " in
+  *" lt__strl.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS lt__strl.$ac_objext"
+ ;;
+esac
+
+fi
+done
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_LIBEXT "$libext"
+_ACEOF
+
+
+name=
+eval "lt_libprefix=\"$libname_spec\""
+
+cat >>confdefs.h <<_ACEOF
+#define LT_LIBPREFIX "$lt_libprefix"
+_ACEOF
+
+
+name=ltdl
+eval "LTDLOPEN=\"$libname_spec\""
+
+
+
+
+## -------- ##
+## Outputs. ##
+## -------- ##
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+       cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+         mv -f confcache "$cache_file"$$ &&
+         mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+         mv -f confcache "$cache_file" ;;
+       esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${INSTALL_LTDL_TRUE}" && test -z "${INSTALL_LTDL_FALSE}"; then
+  as_fn_error $? "conditional \"INSTALL_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${CONVENIENCE_LTDL_TRUE}" && test -z "${CONVENIENCE_LTDL_FALSE}"; then
+  as_fn_error $? "conditional \"CONVENIENCE_LTDL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+LT_CONFIG_H=config.h
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='        ';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by libltdl $as_me 2.4.2, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-libtool@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+libltdl config.status 2.4.2
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in AS \
+DLLTOOL \
+OBJDUMP \
+SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+sharedlib_from_linklib_cmd \
+AR \
+AR_FLAGS \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+nm_file_list_spec \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+sys_lib_dlsearch_path_spec; do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[\\\\\\\`\\"\\\$]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+xsi_shell='$xsi_shell'
+lt_shell_append='$lt_shell_append'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config-h.in" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = "\a"
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=[    ]*/{
+h
+s///
+s/^/:/
+s/[     ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[  ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[    ]*#[    ]*define[       ][      ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+         $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+       `' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+       || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$_am_arg" : 'X\(//\)[^/]' \| \
+        X"$_am_arg" : 'X\(//\)$' \| \
+        X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named 'Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$mf" : 'X\(//\)[^/]' \| \
+        X"$mf" : 'X\(//\)$' \| \
+        X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running 'make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "$am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$file" : 'X\(//\)[^/]' \| \
+        X"$file" : 'X\(//\)$' \| \
+        X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      as_dir=$dirpart/$fdir; as_fn_mkdir_p
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+    "libtool":C)
+
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=""
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Assembler program.
+AS=$lt_AS
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Object dumper program.
+OBJDUMP=$lt_OBJDUMP
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive.
+AR_FLAGS=$lt_AR_FLAGS
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and in which our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+  if test x"$xsi_shell" = xyes; then
+  sed -e '/^func_dirname ()$/,/^} # func_dirname /c\
+func_dirname ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_basename ()$/,/^} # func_basename /c\
+func_basename ()\
+{\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\
+func_dirname_and_basename ()\
+{\
+\    case ${1} in\
+\      */*) func_dirname_result="${1%/*}${2}" ;;\
+\      *  ) func_dirname_result="${3}" ;;\
+\    esac\
+\    func_basename_result="${1##*/}"\
+} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_stripname ()$/,/^} # func_stripname /c\
+func_stripname ()\
+{\
+\    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\
+\    # positional parameters, so assign one to ordinary parameter first.\
+\    func_stripname_result=${3}\
+\    func_stripname_result=${func_stripname_result#"${1}"}\
+\    func_stripname_result=${func_stripname_result%"${2}"}\
+} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\
+func_split_long_opt ()\
+{\
+\    func_split_long_opt_name=${1%%=*}\
+\    func_split_long_opt_arg=${1#*=}\
+} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\
+func_split_short_opt ()\
+{\
+\    func_split_short_opt_arg=${1#??}\
+\    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\
+} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\
+func_lo2o ()\
+{\
+\    case ${1} in\
+\      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\
+\      *)    func_lo2o_result=${1} ;;\
+\    esac\
+} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_xform ()$/,/^} # func_xform /c\
+func_xform ()\
+{\
+    func_xform_result=${1%.*}.lo\
+} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_arith ()$/,/^} # func_arith /c\
+func_arith ()\
+{\
+    func_arith_result=$(( $* ))\
+} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_len ()$/,/^} # func_len /c\
+func_len ()\
+{\
+    func_len_result=${#1}\
+} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+fi
+
+if test x"$lt_shell_append" = xyes; then
+  sed -e '/^func_append ()$/,/^} # func_append /c\
+func_append ()\
+{\
+    eval "${1}+=\\${2}"\
+} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\
+func_append_quoted ()\
+{\
+\    func_quote_for_eval "${2}"\
+\    eval "${1}+=\\\\ \\$func_quote_for_eval_result"\
+} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5
+$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;}
+fi
+
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/libltdl/configure.ac b/libltdl/configure.ac
new file mode 100644 (file)
index 0000000..b6e9ea9
--- /dev/null
@@ -0,0 +1,75 @@
+# Process this file with autoconf to create configure. -*- autoconf -*-
+#
+#    Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+#    Written by Gary V. Vaughan, 2004
+#
+#    NOTE: The canonical source of this file is maintained with the
+#    GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+#
+# GNU Libltdl is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# As a special exception to the GNU Lesser General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libltdl 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU LesserGeneral Public
+# License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+# copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+####
+
+# This configure.ac is not used at all by the libtool bootstrap, but
+# is copied to the ltdl subdirectory if you libtoolize --ltdl your own
+# project.  Adding LT_WITH_LTDL to your project configure.ac will then
+# configure this directory if your user doesn't want to use the installed
+# libltdl.
+
+AC_PREREQ(2.59)dnl We use AS_HELP_STRING
+
+
+## ------------------------ ##
+## Autoconf initialisation. ##
+## ------------------------ ##
+AC_INIT([libltdl], [2.4.2], [bug-libtool@gnu.org])
+AC_CONFIG_HEADERS([config.h:config-h.in])
+AC_CONFIG_SRCDIR([ltdl.c])
+AC_CONFIG_AUX_DIR([config])
+AC_CONFIG_MACRO_DIR([m4])
+LT_CONFIG_LTDL_DIR([.]) # I am me!
+
+
+## ------------------------ ##
+## Automake Initialisation. ##
+## ------------------------ ##
+
+AM_INIT_AUTOMAKE([gnu])
+
+
+## ------------------------------- ##
+## Libtool specific configuration. ##
+## ------------------------------- ##
+pkgdatadir='${datadir}'"/${PACKAGE}"
+
+
+## ----------------------- ##
+## Libtool initialisation. ##
+## ----------------------- ##
+LT_INIT([dlopen win32-dll])
+_LTDL_SETUP
+
+
+## -------- ##
+## Outputs. ##
+## -------- ##
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/libltdl/libltdl/lt__alloc.h b/libltdl/libltdl/lt__alloc.h
new file mode 100644 (file)
index 0000000..1ceddf0
--- /dev/null
@@ -0,0 +1,58 @@
+/* lt__alloc.h -- internal memory management interface
+
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#if !defined(LT__ALLOC_H)
+#define LT__ALLOC_H 1
+
+#include "lt_system.h"
+
+LT_BEGIN_C_DECLS
+
+#define MALLOC(tp, n)          (tp*) lt__malloc((n) * sizeof(tp))
+#define REALLOC(tp, mem, n)    (tp*) lt__realloc((mem), (n) * sizeof(tp))
+#define FREE(mem)                                      LT_STMT_START { \
+       if (mem) { free ((void *)mem); mem = NULL; }    } LT_STMT_END
+#define MEMREASSIGN(p, q)                              LT_STMT_START { \
+       if ((p) != (q)) { if (p) free (p); (p) = (q); (q) = 0; }        \
+                                                               } LT_STMT_END
+
+/* If set, this function is called when memory allocation has failed.  */
+LT_SCOPE void (*lt__alloc_die) (void);
+
+LT_SCOPE void *lt__malloc (size_t n);
+LT_SCOPE void *lt__zalloc (size_t n);
+LT_SCOPE void *lt__realloc (void *mem, size_t n);
+LT_SCOPE void *lt__memdup (void const *mem, size_t n);
+
+LT_SCOPE char *lt__strdup (const char *string);
+
+LT_END_C_DECLS
+
+#endif /*!defined(LT__ALLOC_H)*/
diff --git a/libltdl/libltdl/lt__dirent.h b/libltdl/libltdl/lt__dirent.h
new file mode 100644 (file)
index 0000000..4f24f82
--- /dev/null
@@ -0,0 +1,87 @@
+/* lt__dirent.h -- internal directory entry scanning interface
+
+   Copyright (C) 2001, 2004, 2006 Free Software Foundation, Inc.
+   Written by Bob Friesenhahn, 2001
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#if !defined(LT__DIRENT_H)
+#define LT__DIRENT_H 1
+
+#if defined(LT_CONFIG_H)
+#  include LT_CONFIG_H
+#else
+#  include <config.h>
+#endif
+
+#include "lt_system.h"
+
+#ifdef HAVE_DIRENT_H
+/* We have a fully operational dirent subsystem.  */
+#  include <dirent.h>
+#  define D_NAMLEN(dirent) (strlen((dirent)->d_name))
+
+#elif defined __WINDOWS__
+/* Use some wrapper code to emulate dirent on windows..  */
+#  define WINDOWS_DIRENT_EMULATION 1
+
+#  include <windows.h>
+
+#  define D_NAMLEN(dirent)     (strlen((dirent)->d_name))
+#  define dirent               lt__dirent
+#  define DIR                  lt__DIR
+#  define opendir              lt__opendir
+#  define readdir              lt__readdir
+#  define closedir             lt__closedir
+
+LT_BEGIN_C_DECLS
+
+struct dirent
+{
+  char d_name[LT_FILENAME_MAX];
+  int  d_namlen;
+};
+
+typedef struct
+{
+  HANDLE hSearch;
+  WIN32_FIND_DATA Win32FindData;
+  BOOL firsttime;
+  struct dirent file_info;
+} DIR;
+
+
+LT_SCOPE DIR *         opendir         (const char *path);
+LT_SCOPE struct dirent *readdir                (DIR *entry);
+LT_SCOPE void          closedir        (DIR *entry);
+
+LT_END_C_DECLS
+
+#else /* !defined(__WINDOWS__)*/
+ERROR - cannot find dirent
+#endif /*!defined(__WINDOWS__)*/
+
+#endif /*!defined(LT__DIRENT_H)*/
diff --git a/libltdl/libltdl/lt__glibc.h b/libltdl/libltdl/lt__glibc.h
new file mode 100644 (file)
index 0000000..f284773
--- /dev/null
@@ -0,0 +1,83 @@
+/* lt__glibc.h -- support for non glibc environments
+
+   Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#if !defined(LT__GLIBC_H)
+#define LT__GLIBC_H 1
+
+#if defined(LT_CONFIG_H)
+#  include LT_CONFIG_H
+#else
+#  include <config.h>
+#endif
+
+#if !defined(HAVE_ARGZ_H) || !defined(HAVE_WORKING_ARGZ)
+/* Redefine any glibc symbols we reimplement to import the
+   implementations into our lt__ namespace so we don't ever
+   clash with the system library if our clients use argz_*
+   from there in addition to libltdl.  */
+#  undef  argz_append
+#  define argz_append          lt__argz_append
+#  undef  argz_create_sep
+#  define argz_create_sep      lt__argz_create_sep
+#  undef  argz_insert
+#  define argz_insert          lt__argz_insert
+#  undef  argz_next
+#  define argz_next            lt__argz_next
+#  undef  argz_stringify
+#  define argz_stringify       lt__argz_stringify
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <argz.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+# define slist_concat  lt__slist_concat
+# define slist_cons    lt__slist_cons
+# define slist_delete  lt__slist_delete
+# define slist_remove  lt__slist_remove
+# define slist_reverse lt__slist_reverse
+# define slist_sort    lt__slist_sort
+# define slist_tail    lt__slist_tail
+# define slist_nth     lt__slist_nth
+# define slist_find    lt__slist_find
+# define slist_length  lt__slist_length
+# define slist_foreach lt__slist_foreach
+# define slist_box     lt__slist_box
+# define slist_unbox   lt__slist_unbox
+
+#include <slist.h>
+
+#endif /*!defined(LT__GLIBC_H)*/
diff --git a/libltdl/libltdl/lt__private.h b/libltdl/libltdl/lt__private.h
new file mode 100644 (file)
index 0000000..f4c4a3d
--- /dev/null
@@ -0,0 +1,149 @@
+/* lt__private.h -- internal apis for libltdl
+
+   Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy con be downloaded from http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#if !defined(LT__PRIVATE_H)
+#define LT__PRIVATE_H 1
+
+#if defined(LT_CONFIG_H)
+#  include LT_CONFIG_H
+#else
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#if defined(HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+/* Import internal interfaces...  */
+#include "lt__alloc.h"
+#include "lt__dirent.h"
+#include "lt__strl.h"
+#include "lt__glibc.h"
+
+/* ...and all exported interfaces.  */
+#include "ltdl.h"
+
+#if defined(WITH_DMALLOC)
+#  include <dmalloc.h>
+#endif
+
+/* DLL building support on win32 hosts;  mostly to workaround their
+   ridiculous implementation of data symbol exporting. */
+#ifndef LT_GLOBAL_DATA
+# if defined(__WINDOWS__) || defined(__CYGWIN__)
+#  if defined(DLL_EXPORT)      /* defined by libtool (if required) */
+#   define LT_GLOBAL_DATA      __declspec(dllexport)
+#  endif
+# endif
+# ifndef LT_GLOBAL_DATA
+#  define LT_GLOBAL_DATA       /* static linking or !__WINDOWS__ */
+# endif
+#endif
+
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
+#  define __attribute__(x)
+# endif
+#endif
+
+#ifndef LT__UNUSED
+# define LT__UNUSED __attribute__ ((__unused__))
+#endif
+
+
+LT_BEGIN_C_DECLS
+
+#if !defined(errno)
+extern int errno;
+#endif
+
+LT_SCOPE void  lt__alloc_die_callback (void);
+
+
+/* For readability:  */
+#define strneq(s1, s2) (strcmp((s1), (s2)) != 0)
+#define streq(s1, s2)  (!strcmp((s1), (s2)))
+
+
+
+/* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
+
+/* This type is used for the array of interface data sets in each handler. */
+typedef struct {
+  lt_dlinterface_id    key;
+  void *               data;
+} lt_interface_data;
+
+struct lt__handle {
+  lt_dlhandle          next;
+  const lt_dlvtable *  vtable;         /* dlopening interface */
+  lt_dlinfo            info;           /* user visible fields */
+  int                  depcount;       /* number of dependencies */
+  lt_dlhandle *                deplibs;        /* dependencies */
+  lt_module            module;         /* system module handle */
+  void *               system;         /* system specific data */
+  lt_interface_data *  interface_data; /* per caller associated data */
+  int                  flags;          /* various boolean stats */
+};
+
+struct lt__advise {
+  unsigned int try_ext:1;      /* try system library extensions.  */
+  unsigned int is_resident:1;  /* module can't be unloaded. */
+  unsigned int is_symglobal:1; /* module symbols can satisfy
+                                  subsequently loaded modules.  */
+  unsigned int is_symlocal:1;  /* module symbols are only available
+                                  locally. */
+  unsigned int try_preload_only:1;/* only preloaded modules will be tried. */
+};
+
+/* --- ERROR HANDLING --- */
+
+/* Extract the diagnostic strings from the error table macro in the same
+   order as the enumerated indices in lt_error.h. */
+
+#define LT__STRERROR(name)     lt__error_string(LT_CONC(LT_ERROR_,name))
+
+#define LT__GETERROR(lvalue)         (lvalue) = lt__get_last_error()
+#define LT__SETERRORSTR(errormsg)     lt__set_last_error(errormsg)
+#define LT__SETERROR(errorcode)              LT__SETERRORSTR(LT__STRERROR(errorcode))
+
+LT_SCOPE const char *lt__error_string  (int errorcode);
+LT_SCOPE const char *lt__get_last_error        (void);
+LT_SCOPE const char *lt__set_last_error        (const char *errormsg);
+
+LT_END_C_DECLS
+
+#endif /*!defined(LT__PRIVATE_H)*/
diff --git a/libltdl/libltdl/lt__strl.h b/libltdl/libltdl/lt__strl.h
new file mode 100644 (file)
index 0000000..5799dc8
--- /dev/null
@@ -0,0 +1,53 @@
+/* lt__strl.h -- size-bounded string copying and concatenation
+
+   Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+   Written by Bob Friesenhahn, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#if !defined(LT__STRL_H)
+#define LT__STRL_H 1
+
+#if defined(LT_CONFIG_H)
+#  include LT_CONFIG_H
+#else
+#  include <config.h>
+#endif
+
+#include <string.h>
+#include "lt_system.h"
+
+#if !defined(HAVE_STRLCAT)
+#  define strlcat(dst,src,dstsize) lt_strlcat(dst,src,dstsize)
+LT_SCOPE size_t lt_strlcat(char *dst, const char *src, const size_t dstsize);
+#endif /* !defined(HAVE_STRLCAT) */
+
+#if !defined(HAVE_STRLCPY)
+#  define strlcpy(dst,src,dstsize) lt_strlcpy(dst,src,dstsize)
+LT_SCOPE size_t lt_strlcpy(char *dst, const char *src, const size_t dstsize);
+#endif /* !defined(HAVE_STRLCPY) */
+
+#endif /*!defined(LT__STRL_H)*/
diff --git a/libltdl/libltdl/lt_dlloader.h b/libltdl/libltdl/lt_dlloader.h
new file mode 100644 (file)
index 0000000..589fd0d
--- /dev/null
@@ -0,0 +1,90 @@
+/* lt_dlloader.h -- dynamic library loader interface
+
+   Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#if !defined(LT_DLLOADER_H)
+#define LT_DLLOADER_H 1
+
+#include <libltdl/lt_system.h>
+
+LT_BEGIN_C_DECLS
+
+typedef        void *  lt_dlloader;
+typedef void * lt_module;
+typedef void * lt_user_data;
+typedef struct lt__advise *    lt_dladvise;
+
+/* Function pointer types for module loader vtable entries:  */
+typedef lt_module   lt_module_open     (lt_user_data data,
+                                        const char *filename,
+                                        lt_dladvise advise);
+typedef int        lt_module_close     (lt_user_data data,
+                                        lt_module module);
+typedef void *     lt_find_sym         (lt_user_data data, lt_module module,
+                                        const char *symbolname);
+typedef int        lt_dlloader_init    (lt_user_data data);
+typedef int        lt_dlloader_exit    (lt_user_data data);
+
+/* Default priority is LT_DLLOADER_PREPEND if none is explicitly given.  */
+typedef enum {
+  LT_DLLOADER_PREPEND = 0, LT_DLLOADER_APPEND
+} lt_dlloader_priority;
+
+/* This structure defines a module loader, as populated by the get_vtable
+   entry point of each loader.  */
+typedef struct {
+  const char *         name;
+  const char *         sym_prefix;
+  lt_module_open *     module_open;
+  lt_module_close *    module_close;
+  lt_find_sym *                find_sym;
+  lt_dlloader_init *   dlloader_init;
+  lt_dlloader_exit *   dlloader_exit;
+  lt_user_data         dlloader_data;
+  lt_dlloader_priority priority;
+} lt_dlvtable;
+
+LT_SCOPE int           lt_dlloader_add    (const lt_dlvtable *vtable);
+LT_SCOPE lt_dlloader   lt_dlloader_next   (const lt_dlloader loader);
+
+LT_SCOPE lt_dlvtable * lt_dlloader_remove      (const char *name);
+LT_SCOPE const lt_dlvtable *lt_dlloader_find   (const char *name);
+LT_SCOPE const lt_dlvtable *lt_dlloader_get    (lt_dlloader loader);
+
+
+/* Type of a function to get a loader's vtable:  */
+typedef  const lt_dlvtable *lt_get_vtable      (lt_user_data data);
+
+#ifdef LT_DEBUG_LOADERS
+LT_SCOPE void          lt_dlloader_dump        (void);
+#endif
+
+LT_END_C_DECLS
+
+#endif /*!defined(LT_DLLOADER_H)*/
diff --git a/libltdl/libltdl/lt_error.h b/libltdl/libltdl/lt_error.h
new file mode 100644 (file)
index 0000000..e789b3a
--- /dev/null
@@ -0,0 +1,85 @@
+/* lt_error.h -- error propogation interface
+
+   Copyright (C) 1999, 2000, 2001, 2004, 2007 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1999
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* Only include this header file once. */
+#if !defined(LT_ERROR_H)
+#define LT_ERROR_H 1
+
+#include <libltdl/lt_system.h>
+
+LT_BEGIN_C_DECLS
+
+/* Defining error strings alongside their symbolic names in a macro in
+   this way allows us to expand the macro in different contexts with
+   confidence that the enumeration of symbolic names will map correctly
+   onto the table of error strings.  \0 is appended to the strings to
+   expilicitely initialize the string terminator. */
+#define lt_dlerror_table                                               \
+    LT_ERROR(UNKNOWN,              "unknown error\0")                  \
+    LT_ERROR(DLOPEN_NOT_SUPPORTED,  "dlopen support not available\0")  \
+    LT_ERROR(INVALID_LOADER,       "invalid loader\0")                 \
+    LT_ERROR(INIT_LOADER,          "loader initialization failed\0")   \
+    LT_ERROR(REMOVE_LOADER,        "loader removal failed\0")          \
+    LT_ERROR(FILE_NOT_FOUND,       "file not found\0")                 \
+    LT_ERROR(DEPLIB_NOT_FOUND,     "dependency library not found\0")   \
+    LT_ERROR(NO_SYMBOLS,           "no symbols defined\0")             \
+    LT_ERROR(CANNOT_OPEN,          "can't open the module\0")          \
+    LT_ERROR(CANNOT_CLOSE,         "can't close the module\0")         \
+    LT_ERROR(SYMBOL_NOT_FOUND,     "symbol not found\0")               \
+    LT_ERROR(NO_MEMORY,                    "not enough memory\0")              \
+    LT_ERROR(INVALID_HANDLE,       "invalid module handle\0")          \
+    LT_ERROR(BUFFER_OVERFLOW,      "internal buffer overflow\0")       \
+    LT_ERROR(INVALID_ERRORCODE,            "invalid errorcode\0")              \
+    LT_ERROR(SHUTDOWN,             "library already shutdown\0")       \
+    LT_ERROR(CLOSE_RESIDENT_MODULE, "can't close resident module\0")   \
+    LT_ERROR(INVALID_MUTEX_ARGS,    "internal error (code withdrawn)\0")\
+    LT_ERROR(INVALID_POSITION,     "invalid search path insert position\0")\
+    LT_ERROR(CONFLICTING_FLAGS,            "symbol visibility can be global or local\0")
+
+/* Enumerate the symbolic error names. */
+enum {
+#define LT_ERROR(name, diagnostic)     LT_CONC(LT_ERROR_, name),
+       lt_dlerror_table
+#undef LT_ERROR
+
+       LT_ERROR_MAX
+};
+
+/* Should be max of the error string lengths above (plus one for C++) */
+#define LT_ERROR_LEN_MAX (41)
+
+/* These functions are only useful from inside custom module loaders. */
+LT_SCOPE int   lt_dladderror   (const char *diagnostic);
+LT_SCOPE int   lt_dlseterror   (int errorcode);
+
+
+LT_END_C_DECLS
+
+#endif /*!defined(LT_ERROR_H)*/
diff --git a/libltdl/libltdl/lt_system.h b/libltdl/libltdl/lt_system.h
new file mode 100644 (file)
index 0000000..f1545ce
--- /dev/null
@@ -0,0 +1,166 @@
+/* lt_system.h -- system portability abstraction layer
+
+   Copyright (C) 2004, 2007, 2010 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#if !defined(LT_SYSTEM_H)
+#define LT_SYSTEM_H 1
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+/* Some systems do not define EXIT_*, even with STDC_HEADERS.  */
+#if !defined(EXIT_SUCCESS)
+# define EXIT_SUCCESS 0
+#endif
+#if !defined(EXIT_FAILURE)
+# define EXIT_FAILURE 1
+#endif
+
+/* Just pick a big number... */
+#define LT_FILENAME_MAX 2048
+
+
+/* Saves on those hard to debug '\0' typos....  */
+#define LT_EOS_CHAR    '\0'
+
+/* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations,
+   so that C++ compilers don't mangle their names.  Use LTDL_END_C_DECLS at
+   the end of C declarations. */
+#if defined(__cplusplus)
+# define LT_BEGIN_C_DECLS      extern "C" {
+# define LT_END_C_DECLS                }
+#else
+# define LT_BEGIN_C_DECLS      /* empty */
+# define LT_END_C_DECLS                /* empty */
+#endif
+
+/* LT_STMT_START/END are used to create macros which expand to a
+   a single compound statement in a portable way.  */
+#if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
+#  define LT_STMT_START        (void)(
+#  define LT_STMT_END          )
+#else
+#  if (defined (sun) || defined (__sun__))
+#    define LT_STMT_START      if (1)
+#    define LT_STMT_END        else (void)0
+#  else
+#    define LT_STMT_START      do
+#    define LT_STMT_END        while (0)
+#  endif
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+/* Canonicalise Windows and Cygwin recognition macros.
+   To match the values set by recent Cygwin compilers, make sure that if
+   __CYGWIN__ is defined (after canonicalisation), __WINDOWS__ is NOT!  */
+#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
+# define __CYGWIN__ __CYGWIN32__
+#endif
+#if defined(__CYGWIN__)
+# if defined(__WINDOWS__)
+#   undef __WINDOWS__
+# endif
+#elif defined(_WIN32)
+# define __WINDOWS__ _WIN32
+#elif defined(WIN32)
+# define __WINDOWS__ WIN32
+#endif
+#if defined(__CYGWIN__) && defined(__WINDOWS__)
+# undef __WINDOWS__
+#endif
+
+
+/* DLL building support on win32 hosts;  mostly to workaround their
+   ridiculous implementation of data symbol exporting. */
+#if !defined(LT_SCOPE)
+#  if defined(__WINDOWS__) || defined(__CYGWIN__)
+#    if defined(DLL_EXPORT)            /* defined by libtool (if required) */
+#      define LT_SCOPE extern __declspec(dllexport)
+#    endif
+#    if defined(LIBLTDL_DLL_IMPORT)    /* define if linking with this dll */
+       /* note: cygwin/mingw compilers can rely instead on auto-import */
+#      define LT_SCOPE extern __declspec(dllimport)
+#    endif
+#  endif
+#  if !defined(LT_SCOPE)               /* static linking or !__WINDOWS__ */
+#    define LT_SCOPE   extern
+#  endif
+#endif
+
+#if defined(__WINDOWS__)
+/* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory
+   separator when it is set. */
+# define LT_DIRSEP_CHAR                '\\'
+# define LT_PATHSEP_CHAR       ';'
+#else
+# define LT_PATHSEP_CHAR       ':'
+#endif
+
+#if defined(_MSC_VER) /* Visual Studio */
+#  define R_OK 4
+#endif
+
+/* fopen() mode flags for reading a text file */
+#undef LT_READTEXT_MODE
+#if defined(__WINDOWS__) || defined(__CYGWIN__)
+#  define LT_READTEXT_MODE "rt"
+#else
+#  define LT_READTEXT_MODE "r"
+#endif
+
+/* The extra indirection to the LT__STR and LT__CONC macros is required so
+   that if the arguments to LT_STR() (or LT_CONC()) are themselves macros,
+   they will be expanded before being quoted.   */
+#ifndef LT_STR
+#  define LT__STR(arg)         #arg
+#  define LT_STR(arg)          LT__STR(arg)
+#endif
+
+#ifndef LT_CONC
+#  define LT__CONC(a, b)       a##b
+#  define LT_CONC(a, b)                LT__CONC(a, b)
+#endif
+#ifndef LT_CONC3
+#  define LT__CONC3(a, b, c)   a##b##c
+#  define LT_CONC3(a, b, c)    LT__CONC3(a, b, c)
+#endif
+
+#endif /*!defined(LT_SYSTEM_H)*/
diff --git a/libltdl/libltdl/slist.h b/libltdl/libltdl/slist.h
new file mode 100644 (file)
index 0000000..4d56509
--- /dev/null
@@ -0,0 +1,96 @@
+/* slist.h -- generalised singly linked lists
+
+   Copyright (C) 2000, 2004, 2009 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2000
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* A generalised list.  This is deliberately transparent so that you
+   can make the NEXT field of all your chained data structures first,
+   and then cast them to `(SList *)' so that they can be manipulated
+   by this API.
+
+   Alternatively, you can generate raw SList elements using slist_new(),
+   and put the element data in the USERDATA field.  Either way you
+   get to manage the memory involved by yourself.
+*/
+
+#if !defined(SLIST_H)
+#define SLIST_H 1
+
+#if defined(LTDL)
+#  include <libltdl/lt__glibc.h>
+#  include <libltdl/lt_system.h>
+#else
+#  define LT_SCOPE
+#endif
+
+#include <stddef.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef struct slist {
+  struct slist *next;          /* chain forward pointer*/
+  const void *userdata;                /* for boxed `SList' item */
+} SList;
+
+typedef void * SListCallback   (SList *item, void *userdata);
+typedef int    SListCompare    (const SList *item1, const SList *item2,
+                                void *userdata);
+
+LT_SCOPE SList *slist_concat   (SList *head, SList *tail);
+LT_SCOPE SList *slist_cons     (SList *item, SList *slist);
+
+LT_SCOPE SList *slist_delete   (SList *slist, void (*delete_fct) (void *item));
+LT_SCOPE SList *slist_remove   (SList **phead, SListCallback *find,
+                                void *matchdata);
+LT_SCOPE SList *slist_reverse  (SList *slist);
+LT_SCOPE SList *slist_sort     (SList *slist, SListCompare *compare,
+                                void *userdata);
+
+LT_SCOPE SList *slist_tail     (SList *slist);
+LT_SCOPE SList *slist_nth      (SList *slist, size_t n);
+LT_SCOPE void *        slist_find      (SList *slist, SListCallback *find,
+                                void *matchdata);
+LT_SCOPE size_t slist_length   (SList *slist);
+
+LT_SCOPE void *        slist_foreach   (SList *slist, SListCallback *foreach,
+                                void *userdata);
+
+LT_SCOPE SList *slist_box      (const void *userdata);
+LT_SCOPE void *        slist_unbox     (SList *item);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if !defined(LTDL)
+#  undef LT_SCOPE
+#endif
+
+#endif /*!defined(SLIST_H)*/
diff --git a/libltdl/loaders/dld_link.c b/libltdl/loaders/dld_link.c
new file mode 100644 (file)
index 0000000..7e882c9
--- /dev/null
@@ -0,0 +1,158 @@
+/* loader-dld_link.c -- dynamic linking with dld
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2006,
+                 2007, 2008 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+/* Use the preprocessor to rename non-static symbols to avoid namespace
+   collisions when the loader code is statically linked into libltdl.
+   Use the "<module_name>_LTX_" prefix so that the symbol addresses can
+   be fetched from the preloaded symbol list by lt_dlsym():  */
+#define get_vtable     dld_link_LTX_get_vtable
+
+LT_BEGIN_C_DECLS
+LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
+LT_END_C_DECLS
+
+
+/* Boilerplate code to set up the vtable for hooking this loader into
+   libltdl's loader list:  */
+static int      vl_exit  (lt_user_data loader_data);
+static lt_module vm_open  (lt_user_data loader_data, const char *filename,
+                           lt_dladvise advise);
+static int      vm_close (lt_user_data loader_data, lt_module module);
+static void *   vm_sym   (lt_user_data loader_data, lt_module module,
+                         const char *symbolname);
+
+static lt_dlvtable *vtable = 0;
+
+/* Return the vtable for this loader, only the name and sym_prefix
+   attributes (plus the virtual function implementations, obviously)
+   change between loaders.  */
+lt_dlvtable *
+get_vtable (lt_user_data loader_data)
+{
+  if (!vtable)
+    {
+      vtable = lt__zalloc (sizeof *vtable);
+    }
+
+  if (vtable && !vtable->name)
+    {
+      vtable->name             = "lt_dld_link";
+      vtable->module_open      = vm_open;
+      vtable->module_close     = vm_close;
+      vtable->find_sym         = vm_sym;
+      vtable->dlloader_exit    = vl_exit;
+      vtable->dlloader_data    = loader_data;
+      vtable->priority         = LT_DLLOADER_APPEND;
+    }
+
+  if (vtable && (vtable->dlloader_data != loader_data))
+    {
+      LT__SETERROR (INIT_LOADER);
+      return 0;
+    }
+
+  return vtable;
+}
+
+
+
+/* --- IMPLEMENTATION --- */
+
+
+#if defined(HAVE_DLD_H)
+#  include <dld.h>
+#endif
+
+/* A function called through the vtable when this loader is no
+   longer needed by the application.  */
+static int
+vl_exit (lt_user_data LT__UNUSED loader_data)
+{
+  vtable = NULL;
+  return 0;
+}
+
+/* A function called through the vtable to open a module with this
+   loader.  Returns an opaque representation of the newly opened
+   module for processing with this loader's other vtable functions.  */
+static lt_module
+vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
+         lt_dladvise LT__UNUSED advise)
+{
+  lt_module module = lt__strdup (filename);
+
+  if (dld_link (filename) != 0)
+    {
+      LT__SETERROR (CANNOT_OPEN);
+      FREE (module);
+    }
+
+  return module;
+}
+
+/* A function called through the vtable when a particular module
+   should be unloaded.  */
+static int
+vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
+{
+  int errors = 0;
+
+  if (dld_unlink_by_file ((char*)(module), 1) != 0)
+    {
+      LT__SETERROR (CANNOT_CLOSE);
+      ++errors;
+    }
+  else
+    {
+      FREE (module);
+    }
+
+  return errors;
+}
+
+/* A function called through the vtable to get the address of
+   a symbol loaded from a particular module.  */
+static void *
+vm_sym (lt_user_data LT__UNUSED loader_data, lt_module LT__UNUSED module,
+       const char *name)
+{
+  void *address = dld_get_func (name);
+
+  if (!address)
+    {
+      LT__SETERROR (SYMBOL_NOT_FOUND);
+    }
+
+  return address;
+}
diff --git a/libltdl/loaders/dlopen.c b/libltdl/loaders/dlopen.c
new file mode 100644 (file)
index 0000000..1d052b4
--- /dev/null
@@ -0,0 +1,235 @@
+/* loader-dlopen.c --  dynamic linking with dlopen/dlsym
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2006,
+                 2007, 2008 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+/* Use the preprocessor to rename non-static symbols to avoid namespace
+   collisions when the loader code is statically linked into libltdl.
+   Use the "<module_name>_LTX_" prefix so that the symbol addresses can
+   be fetched from the preloaded symbol list by lt_dlsym():  */
+#define get_vtable     dlopen_LTX_get_vtable
+
+LT_BEGIN_C_DECLS
+LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
+LT_END_C_DECLS
+
+
+/* Boilerplate code to set up the vtable for hooking this loader into
+   libltdl's loader list:  */
+static int      vl_exit  (lt_user_data loader_data);
+static lt_module vm_open  (lt_user_data loader_data, const char *filename,
+                           lt_dladvise advise);
+static int      vm_close (lt_user_data loader_data, lt_module module);
+static void *   vm_sym   (lt_user_data loader_data, lt_module module,
+                         const char *symbolname);
+
+static lt_dlvtable *vtable = 0;
+
+/* Return the vtable for this loader, only the name and sym_prefix
+   attributes (plus the virtual function implementations, obviously)
+   change between loaders.  */
+lt_dlvtable *
+get_vtable (lt_user_data loader_data)
+{
+  if (!vtable)
+    {
+      vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
+    }
+
+  if (vtable && !vtable->name)
+    {
+      vtable->name             = "lt_dlopen";
+#if defined(DLSYM_USCORE)
+      vtable->sym_prefix       = "_";
+#endif
+      vtable->module_open      = vm_open;
+      vtable->module_close     = vm_close;
+      vtable->find_sym         = vm_sym;
+      vtable->dlloader_exit    = vl_exit;
+      vtable->dlloader_data    = loader_data;
+      vtable->priority         = LT_DLLOADER_PREPEND;
+    }
+
+  if (vtable && (vtable->dlloader_data != loader_data))
+    {
+      LT__SETERROR (INIT_LOADER);
+      return 0;
+    }
+
+  return vtable;
+}
+
+
+
+/* --- IMPLEMENTATION --- */
+
+
+#if defined(HAVE_DLFCN_H)
+#  include <dlfcn.h>
+#endif
+
+#if defined(HAVE_SYS_DL_H)
+#  include <sys/dl.h>
+#endif
+
+
+/* We may have to define LT_LAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#if !defined(LT_LAZY_OR_NOW)
+#  if defined(RTLD_LAZY)
+#    define LT_LAZY_OR_NOW     RTLD_LAZY
+#  else
+#    if defined(DL_LAZY)
+#      define LT_LAZY_OR_NOW   DL_LAZY
+#    endif
+#  endif /* !RTLD_LAZY */
+#endif
+#if !defined(LT_LAZY_OR_NOW)
+#  if defined(RTLD_NOW)
+#    define LT_LAZY_OR_NOW     RTLD_NOW
+#  else
+#    if defined(DL_NOW)
+#      define LT_LAZY_OR_NOW   DL_NOW
+#    endif
+#  endif /* !RTLD_NOW */
+#endif
+#if !defined(LT_LAZY_OR_NOW)
+#  define LT_LAZY_OR_NOW       0
+#endif /* !LT_LAZY_OR_NOW */
+
+/* We only support local and global symbols from modules for loaders
+   that provide such a thing, otherwise the system default is used.  */
+#if !defined(RTLD_GLOBAL)
+#  if defined(DL_GLOBAL)
+#    define RTLD_GLOBAL                DL_GLOBAL
+#  endif
+#endif /* !RTLD_GLOBAL */
+#if !defined(RTLD_LOCAL)
+#  if defined(DL_LOCAL)
+#    define RTLD_LOCAL         DL_LOCAL
+#  endif
+#endif /* !RTLD_LOCAL */
+
+#if defined(HAVE_DLERROR)
+#  define DLERROR(arg) dlerror ()
+#else
+#  define DLERROR(arg) LT__STRERROR (arg)
+#endif
+
+#define DL__SETERROR(errorcode) \
+       LT__SETERRORSTR (DLERROR (errorcode))
+
+
+/* A function called through the vtable when this loader is no
+   longer needed by the application.  */
+static int
+vl_exit (lt_user_data LT__UNUSED loader_data)
+{
+  vtable = NULL;
+  return 0;
+}
+
+
+/* A function called through the vtable to open a module with this
+   loader.  Returns an opaque representation of the newly opened
+   module for processing with this loader's other vtable functions.  */
+static lt_module
+vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
+         lt_dladvise advise)
+{
+  int          module_flags = LT_LAZY_OR_NOW;
+  lt_module    module;
+
+  if (advise)
+    {
+#ifdef RTLD_GLOBAL
+      /* If there is some means of asking for global symbol resolution,
+         do so.  */
+      if (advise->is_symglobal)
+        module_flags |= RTLD_GLOBAL;
+#else
+      /* Otherwise, reset that bit so the caller can tell it wasn't
+         acted on.  */
+      advise->is_symglobal = 0;
+#endif
+
+/* And similarly for local only symbol resolution.  */
+#ifdef RTLD_LOCAL
+      if (advise->is_symlocal)
+        module_flags |= RTLD_LOCAL;
+#else
+      advise->is_symlocal = 0;
+#endif
+    }
+
+  module = dlopen (filename, module_flags);
+
+  if (!module)
+    {
+      DL__SETERROR (CANNOT_OPEN);
+    }
+
+  return module;
+}
+
+
+/* A function called through the vtable when a particular module
+   should be unloaded.  */
+static int
+vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
+{
+  int errors = 0;
+
+  if (dlclose (module) != 0)
+    {
+      DL__SETERROR (CANNOT_CLOSE);
+      ++errors;
+    }
+
+  return errors;
+}
+
+
+/* A function called through the vtable to get the address of
+   a symbol loaded from a particular module.  */
+static void *
+vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
+{
+  void *address = dlsym (module, name);
+
+  if (!address)
+    {
+      DL__SETERROR (SYMBOL_NOT_FOUND);
+    }
+
+  return address;
+}
diff --git a/libltdl/loaders/dyld.c b/libltdl/loaders/dyld.c
new file mode 100644 (file)
index 0000000..b139d6c
--- /dev/null
@@ -0,0 +1,511 @@
+/* loader-dyld.c -- dynamic linking on darwin and OS X
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2006,
+                 2007, 2008 Free Software Foundation, Inc.
+   Written by Peter O'Gorman, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+/* Use the preprocessor to rename non-static symbols to avoid namespace
+   collisions when the loader code is statically linked into libltdl.
+   Use the "<module_name>_LTX_" prefix so that the symbol addresses can
+   be fetched from the preloaded symbol list by lt_dlsym():  */
+#define get_vtable     dyld_LTX_get_vtable
+
+LT_BEGIN_C_DECLS
+LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
+LT_END_C_DECLS
+
+
+/* Boilerplate code to set up the vtable for hooking this loader into
+   libltdl's loader list:  */
+static int      vl_init  (lt_user_data loader_data);
+static int      vl_exit  (lt_user_data loader_data);
+static lt_module vm_open  (lt_user_data loader_data, const char *filename,
+                           lt_dladvise advise);
+static int      vm_close (lt_user_data loader_data, lt_module module);
+static void *   vm_sym   (lt_user_data loader_data, lt_module module,
+                         const char *symbolname);
+
+static lt_dlvtable *vtable = 0;
+
+/* Return the vtable for this loader, only the name and sym_prefix
+   attributes (plus the virtual function implementations, obviously)
+   change between loaders.  */
+lt_dlvtable *
+get_vtable (lt_user_data loader_data)
+{
+  if (!vtable)
+    {
+      vtable = lt__zalloc (sizeof *vtable);
+    }
+
+  if (vtable && !vtable->name)
+    {
+      vtable->name             = "lt_dyld";
+      vtable->sym_prefix       = "_";
+      vtable->dlloader_init    = vl_init;
+      vtable->module_open      = vm_open;
+      vtable->module_close     = vm_close;
+      vtable->find_sym         = vm_sym;
+      vtable->dlloader_exit    = vl_exit;
+      vtable->dlloader_data    = loader_data;
+      vtable->priority         = LT_DLLOADER_APPEND;
+    }
+
+  if (vtable && (vtable->dlloader_data != loader_data))
+    {
+      LT__SETERROR (INIT_LOADER);
+      return 0;
+    }
+
+  return vtable;
+}
+
+
+
+/* --- IMPLEMENTATION --- */
+
+
+#if defined(HAVE_MACH_O_DYLD_H)
+#  if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
+  /* Is this correct? Does it still function properly? */
+#    define __private_extern__ extern
+#  endif
+#  include <mach-o/dyld.h>
+#endif
+
+#include <mach-o/getsect.h>
+
+/* We have to put some stuff here that isn't in older dyld.h files */
+#if !defined(ENUM_DYLD_BOOL)
+# define ENUM_DYLD_BOOL
+# undef FALSE
+# undef TRUE
+ enum DYLD_BOOL {
+    FALSE,
+    TRUE
+ };
+#endif
+#if !defined(LC_REQ_DYLD)
+# define LC_REQ_DYLD 0x80000000
+#endif
+#if !defined(LC_LOAD_WEAK_DYLIB)
+# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
+#endif
+
+#if !defined(NSADDIMAGE_OPTION_NONE)
+#  define NSADDIMAGE_OPTION_NONE                          0x0
+#endif
+#if !defined(NSADDIMAGE_OPTION_RETURN_ON_ERROR)
+#  define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
+#endif
+#if !defined(NSADDIMAGE_OPTION_WITH_SEARCHING)
+#  define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
+#endif
+#if !defined(NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED)
+#  define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
+#endif
+#if !defined(NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME)
+#  define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
+#endif
+
+#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_BIND)
+#  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND               0x0
+#endif
+#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW)
+#  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW           0x1
+#endif
+#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY)
+#  define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY         0x2
+#endif
+#if !defined(NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR)
+#  define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR    0x4
+#endif
+
+#define LT__SYMLOOKUP_OPTS     (NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW \
+                               | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR)
+
+#if defined(__BIG_ENDIAN__)
+#  define LT__MAGIC    MH_MAGIC
+#else
+#  define LT__MAGIC    MH_CIGAM
+#endif
+
+#define DYLD__SETMYERROR(errmsg)    LT__SETERRORSTR (dylderror (errmsg))
+#define DYLD__SETERROR(errcode)            DYLD__SETMYERROR (LT__STRERROR (errcode))
+
+typedef struct mach_header mach_header;
+typedef struct dylib_command dylib_command;
+
+static const char *dylderror (const char *errmsg);
+static const mach_header *lt__nsmodule_get_header (NSModule module);
+static const char *lt__header_get_instnam (const mach_header *mh);
+static const mach_header *lt__match_loadedlib (const char *name);
+static NSSymbol lt__linkedlib_symbol (const char *symname, const mach_header *mh);
+
+static const mach_header *(*lt__addimage)      (const char *image_name,
+                                                unsigned long options) = 0;
+static NSSymbol        (*lt__image_symbol)             (const mach_header *image,
+                                                const char *symbolName,
+                                                unsigned long options) = 0;
+static enum DYLD_BOOL (*lt__image_symbol_p)    (const mach_header *image,
+                                                const char *symbolName) = 0;
+static enum DYLD_BOOL (*lt__module_export)     (NSModule module) = 0;
+
+static int dyld_cannot_close                             = 0;
+
+
+/* A function called through the vtable when this loader is no
+   longer needed by the application.  */
+static int
+vl_exit (lt_user_data LT__UNUSED loader_data)
+{
+  vtable = NULL;
+  return 0;
+}
+
+/* A function called through the vtable to initialise this loader.  */
+static int
+vl_init (lt_user_data loader_data)
+{
+  int errors = 0;
+
+  if (! dyld_cannot_close)
+    {
+      if (!_dyld_present ())
+       {
+         ++errors;
+       }
+      else
+       {
+         (void) _dyld_func_lookup ("__dyld_NSAddImage",
+                                   (unsigned long*) &lt__addimage);
+         (void) _dyld_func_lookup ("__dyld_NSLookupSymbolInImage",
+                                   (unsigned long*)&lt__image_symbol);
+         (void) _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage",
+                                   (unsigned long*) &lt__image_symbol_p);
+         (void) _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic",
+                                   (unsigned long*) &lt__module_export);
+         dyld_cannot_close = lt_dladderror ("can't close a dylib");
+       }
+    }
+
+  return errors;
+}
+
+
+/* A function called through the vtable to open a module with this
+   loader.  Returns an opaque representation of the newly opened
+   module for processing with this loader's other vtable functions.  */
+static lt_module
+vm_open (lt_user_data loader_data, const char *filename,
+         lt_dladvise LT__UNUSED advise)
+{
+  lt_module module = 0;
+  NSObjectFileImage ofi = 0;
+
+  if (!filename)
+    {
+      return (lt_module) -1;
+    }
+
+  switch (NSCreateObjectFileImageFromFile (filename, &ofi))
+    {
+    case NSObjectFileImageSuccess:
+      module = NSLinkModule (ofi, filename, NSLINKMODULE_OPTION_RETURN_ON_ERROR
+                                           | NSLINKMODULE_OPTION_PRIVATE
+                                           | NSLINKMODULE_OPTION_BINDNOW);
+      NSDestroyObjectFileImage (ofi);
+
+      if (module)
+       {
+         lt__module_export (module);
+       }
+      break;
+
+    case NSObjectFileImageInappropriateFile:
+      if (lt__image_symbol_p && lt__image_symbol)
+       {
+         module = (lt_module) lt__addimage(filename,
+                                           NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+       }
+      break;
+
+    case NSObjectFileImageFailure:
+    case NSObjectFileImageArch:
+    case NSObjectFileImageFormat:
+    case NSObjectFileImageAccess:
+      /*NOWORK*/
+      break;
+    }
+
+  if (!module)
+    {
+      DYLD__SETERROR (CANNOT_OPEN);
+    }
+
+  return module;
+}
+
+
+/* A function called through the vtable when a particular module
+   should be unloaded.  */
+static int
+vm_close (lt_user_data loader_data, lt_module module)
+{
+  int errors = 0;
+
+  if (module != (lt_module) -1)
+    {
+      const mach_header *mh = (const mach_header *) module;
+      int flags = 0;
+      if (mh->magic == LT__MAGIC)
+       {
+         lt_dlseterror (dyld_cannot_close);
+         ++errors;
+       }
+      else
+       {
+         /* Currently, if a module contains c++ static destructors and it
+            is unloaded, we get a segfault in atexit(), due to compiler and
+            dynamic loader differences of opinion, this works around that.  */
+         if ((const struct section *) NULL !=
+             getsectbynamefromheader (lt__nsmodule_get_header (module),
+                                      "__DATA", "__mod_term_func"))
+           {
+             flags |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
+           }
+#if defined(__ppc__)
+         flags |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
+#endif
+         if (!NSUnLinkModule (module, flags))
+           {
+             DYLD__SETERROR (CANNOT_CLOSE);
+             ++errors;
+           }
+       }
+    }
+
+  return errors;
+}
+
+/* A function called through the vtable to get the address of
+   a symbol loaded from a particular module.  */
+static void *
+vm_sym (lt_user_data loader_data, lt_module module, const char *name)
+{
+  NSSymbol *nssym = 0;
+  const mach_header *mh = (const mach_header *) module;
+  char saveError[256] = "Symbol not found";
+
+  if (module == (lt_module) -1)
+    {
+      void *address, *unused;
+      _dyld_lookup_and_bind (name, (unsigned long*) &address, &unused);
+      return address;
+    }
+
+  if (mh->magic == LT__MAGIC)
+    {
+      if (lt__image_symbol_p && lt__image_symbol)
+       {
+         if (lt__image_symbol_p (mh, name))
+           {
+             nssym = lt__image_symbol (mh, name, LT__SYMLOOKUP_OPTS);
+           }
+       }
+
+    }
+  else
+    {
+      nssym = NSLookupSymbolInModule (module, name);
+    }
+
+  if (!nssym)
+    {
+      strncpy (saveError, dylderror (LT__STRERROR (SYMBOL_NOT_FOUND)), 255);
+      saveError[255] = 0;
+      if (!mh)
+       {
+         mh = (mach_header *)lt__nsmodule_get_header (module);
+       }
+      nssym = lt__linkedlib_symbol (name, mh);
+    }
+
+  if (!nssym)
+    {
+      LT__SETERRORSTR (saveError);
+    }
+
+  return nssym ? NSAddressOfSymbol (nssym) : 0;
+}
+
+
+
+
+/* --- HELPER FUNCTIONS --- */
+
+
+/* Return the dyld error string, or the passed in error string if none. */
+static const char *
+dylderror (const char *errmsg)
+{
+  NSLinkEditErrors ler;
+  int lerno;
+  const char *file;
+  const char *errstr;
+
+  NSLinkEditError (&ler, &lerno, &file, &errstr);
+
+  if (! (errstr && *errstr))
+    {
+      errstr = errmsg;
+    }
+
+  return errstr;
+}
+
+/* There should probably be an apple dyld api for this. */
+static const mach_header *
+lt__nsmodule_get_header (NSModule module)
+{
+  int i = _dyld_image_count();
+  const char *modname = NSNameOfModule (module);
+  const mach_header *mh = 0;
+
+  if (!modname)
+    return NULL;
+
+  while (i > 0)
+    {
+      --i;
+      if (strneq (_dyld_get_image_name (i), modname))
+       {
+         mh = _dyld_get_image_header (i);
+         break;
+       }
+    }
+
+  return mh;
+}
+
+/* NSAddImage is also used to get the loaded image, but it only works if
+   the lib is installed, for uninstalled libs we need to check the
+   install_names against each other.  Note that this is still broken if
+   DYLD_IMAGE_SUFFIX is set and a different lib was loaded as a result.  */
+static const char *
+lt__header_get_instnam (const mach_header *mh)
+{
+  unsigned long offset = sizeof(mach_header);
+  const char* result   = 0;
+  int j;
+
+  for (j = 0; j < mh->ncmds; j++)
+    {
+      struct load_command *lc;
+
+      lc = (struct load_command*) (((unsigned long) mh) + offset);
+      if (LC_ID_DYLIB == lc->cmd)
+       {
+         result=(char*)(((dylib_command*) lc)->dylib.name.offset +
+                        (unsigned long) lc);
+       }
+      offset += lc->cmdsize;
+    }
+
+  return result;
+}
+
+static const mach_header *
+lt__match_loadedlib (const char *name)
+{
+  const mach_header *mh        = 0;
+  int i = _dyld_image_count();
+
+  while (i > 0)
+    {
+      const char *id;
+
+      --i;
+      id = lt__header_get_instnam (_dyld_get_image_header (i));
+      if (id && strneq (id, name))
+       {
+         mh = _dyld_get_image_header (i);
+         break;
+       }
+    }
+
+  return mh;
+}
+
+/* Safe to assume our mh is good. */
+static NSSymbol
+lt__linkedlib_symbol (const char *symname, const mach_header *mh)
+{
+  NSSymbol symbol = 0;
+
+  if (lt__image_symbol && NSIsSymbolNameDefined (symname))
+    {
+      unsigned long offset = sizeof(mach_header);
+      struct load_command *lc;
+      int j;
+
+      for (j = 0; j < mh->ncmds; j++)
+       {
+         lc = (struct load_command*) (((unsigned long) mh) + offset);
+         if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
+           {
+             unsigned long base = ((dylib_command *) lc)->dylib.name.offset;
+             char *name = (char *) (base + (unsigned long) lc);
+             const mach_header *mh1 = lt__match_loadedlib (name);
+
+             if (!mh1)
+               {
+                 /* Maybe NSAddImage can find it */
+                 mh1 = lt__addimage (name,
+                                     NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
+                                     | NSADDIMAGE_OPTION_WITH_SEARCHING
+                                     | NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+               }
+
+             if (mh1)
+               {
+                 symbol = lt__image_symbol (mh1, symname, LT__SYMLOOKUP_OPTS);
+                 if (symbol)
+                   break;
+               }
+           }
+
+         offset += lc->cmdsize;
+       }
+    }
+
+  return symbol;
+}
diff --git a/libltdl/loaders/load_add_on.c b/libltdl/loaders/load_add_on.c
new file mode 100644 (file)
index 0000000..379f9ba
--- /dev/null
@@ -0,0 +1,167 @@
+/* loader-load_add_on.c --  dynamic linking for BeOS
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2006,
+                 2007, 2008 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+/* Use the preprocessor to rename non-static symbols to avoid namespace
+   collisions when the loader code is statically linked into libltdl.
+   Use the "<module_name>_LTX_" prefix so that the symbol addresses can
+   be fetched from the preloaded symbol list by lt_dlsym():  */
+#define get_vtable     load_add_on_LTX_get_vtable
+
+LT_BEGIN_C_DECLS
+LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
+LT_END_C_DECLS
+
+
+/* Boilerplate code to set up the vtable for hooking this loader into
+   libltdl's loader list:  */
+static int      vl_exit  (lt_user_data loader_data);
+static lt_module vm_open  (lt_user_data loader_data, const char *filename,
+                           lt_dladvise advise);
+static int      vm_close (lt_user_data loader_data, lt_module module);
+static void *   vm_sym   (lt_user_data loader_data, lt_module module,
+                         const char *symbolname);
+
+static lt_dlvtable *vtable = 0;
+
+/* Return the vtable for this loader, only the name and sym_prefix
+   attributes (plus the virtual function implementations, obviously)
+   change between loaders.  */
+lt_dlvtable *
+get_vtable (lt_user_data loader_data)
+{
+  if (!vtable)
+    {
+      vtable = lt__zalloc (sizeof *vtable);
+    }
+
+  if (vtable && !vtable->name)
+    {
+      vtable->name             = "lt_load_add_on";
+      vtable->module_open      = vm_open;
+      vtable->module_close     = vm_close;
+      vtable->find_sym         = vm_sym;
+      vtable->dlloader_exit    = vl_exit;
+      vtable->dlloader_data    = loader_data;
+      vtable->priority         = LT_DLLOADER_APPEND;
+    }
+
+  if (vtable && (vtable->dlloader_data != loader_data))
+    {
+      LT__SETERROR (INIT_LOADER);
+      return 0;
+    }
+
+  return vtable;
+}
+
+
+
+/* --- IMPLEMENTATION --- */
+
+
+#include <kernel/image.h>
+
+/* A function called through the vtable when this loader is no
+   longer needed by the application.  */
+static int
+vl_exit (lt_user_data LT__UNUSED loader_data)
+{
+  vtable = NULL;
+  return 0;
+}
+
+/* A function called through the vtable to open a module with this
+   loader.  Returns an opaque representation of the newly opened
+   module for processing with this loader's other vtable functions.  */
+static lt_module
+vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
+         lt_dladvise LT__UNUSED advise)
+{
+  image_id image = 0;
+
+  if (filename)
+    {
+      image = load_add_on (filename);
+    }
+  else
+    {
+      image_info info;
+      int32 cookie = 0;
+      if (get_next_image_info (0, &cookie, &info) == B_OK)
+       image = load_add_on (info.name);
+    }
+
+  if (image <= 0)
+    {
+      LT__SETERROR (CANNOT_OPEN);
+      image = 0;
+    }
+
+  return (lt_module) image;
+}
+
+
+/* A function called through the vtable when a particular module
+   should be unloaded.  */
+static int
+vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
+{
+  int errors = 0;
+
+  if (unload_add_on ((image_id) module) != B_OK)
+    {
+      LT__SETERROR (CANNOT_CLOSE);
+      ++errors;
+    }
+
+  return errors;
+}
+
+
+/* A function called through the vtable to get the address of
+   a symbol loaded from a particular module.  */
+static void *
+vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
+{
+  void *address = 0;
+  image_id image = (image_id) module;
+
+  if (get_image_symbol (image, name, B_SYMBOL_TYPE_ANY, address) != B_OK)
+    {
+      LT__SETERROR (SYMBOL_NOT_FOUND);
+      address = 0;
+    }
+
+  return address;
+}
diff --git a/libltdl/loaders/loadlibrary.c b/libltdl/loaders/loadlibrary.c
new file mode 100644 (file)
index 0000000..179c009
--- /dev/null
@@ -0,0 +1,369 @@
+/* loader-loadlibrary.c --  dynamic linking for Win32
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
+                 2007, 2008, 2010 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+#if defined(__CYGWIN__)
+# include <sys/cygwin.h>
+#endif
+
+/* Use the preprocessor to rename non-static symbols to avoid namespace
+   collisions when the loader code is statically linked into libltdl.
+   Use the "<module_name>_LTX_" prefix so that the symbol addresses can
+   be fetched from the preloaded symbol list by lt_dlsym():  */
+#define get_vtable     loadlibrary_LTX_get_vtable
+
+LT_BEGIN_C_DECLS
+LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
+LT_END_C_DECLS
+
+
+/* Boilerplate code to set up the vtable for hooking this loader into
+   libltdl's loader list:  */
+static int      vl_exit  (lt_user_data loader_data);
+static lt_module vm_open  (lt_user_data loader_data, const char *filename,
+                           lt_dladvise advise);
+static int      vm_close (lt_user_data loader_data, lt_module module);
+static void *   vm_sym   (lt_user_data loader_data, lt_module module,
+                         const char *symbolname);
+
+static lt_dlinterface_id iface_id = 0;
+static lt_dlvtable *vtable = 0;
+
+/* Return the vtable for this loader, only the name and sym_prefix
+   attributes (plus the virtual function implementations, obviously)
+   change between loaders.  */
+lt_dlvtable *
+get_vtable (lt_user_data loader_data)
+{
+  if (!vtable)
+    {
+      vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
+      iface_id = lt_dlinterface_register ("ltdl loadlibrary", NULL);
+    }
+
+  if (vtable && !vtable->name)
+    {
+      vtable->name             = "lt_loadlibrary";
+      vtable->module_open      = vm_open;
+      vtable->module_close     = vm_close;
+      vtable->find_sym         = vm_sym;
+      vtable->dlloader_exit    = vl_exit;
+      vtable->dlloader_data    = loader_data;
+      vtable->priority         = LT_DLLOADER_APPEND;
+    }
+
+  if (vtable && (vtable->dlloader_data != loader_data))
+    {
+      LT__SETERROR (INIT_LOADER);
+      return 0;
+    }
+
+  return vtable;
+}
+
+
+
+/* --- IMPLEMENTATION --- */
+
+
+#include <windows.h>
+
+#define LOCALFREE(mem)                                      LT_STMT_START { \
+       if (mem) { LocalFree ((void *)mem); mem = NULL; }    } LT_STMT_END
+#define LOADLIB__SETERROR(errmsg) LT__SETERRORSTR (loadlibraryerror (errmsg))
+#define LOADLIB_SETERROR(errcode) LOADLIB__SETERROR (LT__STRERROR (errcode))
+
+static const char *loadlibraryerror (const char *default_errmsg);
+static DWORD WINAPI wrap_getthreaderrormode (void);
+static DWORD WINAPI fallback_getthreaderrormode (void);
+static BOOL WINAPI wrap_setthreaderrormode (DWORD mode, DWORD *oldmode);
+static BOOL WINAPI fallback_setthreaderrormode (DWORD mode, DWORD *oldmode);
+
+typedef DWORD (WINAPI getthreaderrormode_type) (void);
+typedef BOOL (WINAPI setthreaderrormode_type) (DWORD, DWORD *);
+
+static getthreaderrormode_type *getthreaderrormode = wrap_getthreaderrormode;
+static setthreaderrormode_type *setthreaderrormode = wrap_setthreaderrormode;
+static char *error_message = 0;
+
+
+/* A function called through the vtable when this loader is no
+   longer needed by the application.  */
+static int
+vl_exit (lt_user_data LT__UNUSED loader_data)
+{
+  vtable = NULL;
+  LOCALFREE (error_message);
+  return 0;
+}
+
+/* A function called through the vtable to open a module with this
+   loader.  Returns an opaque representation of the newly opened
+   module for processing with this loader's other vtable functions.  */
+static lt_module
+vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
+         lt_dladvise LT__UNUSED advise)
+{
+  lt_module    module     = 0;
+  char         *ext;
+  char         wpath[MAX_PATH];
+  size_t       len;
+
+  if (!filename)
+    {
+      /* Get the name of main module */
+      *wpath = 0;
+      GetModuleFileName (NULL, wpath, sizeof (wpath));
+      filename = wpath;
+    }
+  else
+    {
+      len = LT_STRLEN (filename);
+
+      if (len >= MAX_PATH)
+        {
+         LT__SETERROR (CANNOT_OPEN);
+         return 0;
+       }
+
+#if HAVE_DECL_CYGWIN_CONV_PATH
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, filename, wpath, MAX_PATH))
+       {
+         LT__SETERROR (CANNOT_OPEN);
+         return 0;
+       }
+      len = 0;
+#elif defined(__CYGWIN__)
+      cygwin_conv_to_full_win32_path (filename, wpath);
+      len = 0;
+#else
+      strcpy(wpath, filename);
+#endif
+
+      ext = strrchr (wpath, '.');
+      if (!ext)
+       {
+         /* Append a `.' to stop Windows from adding an
+            implicit `.dll' extension. */
+         if (!len)
+           len = strlen (wpath);
+
+         if (len + 1 >= MAX_PATH)
+           {
+             LT__SETERROR (CANNOT_OPEN);
+             return 0;
+           }
+
+         wpath[len] = '.';
+         wpath[len+1] = '\0';
+       }
+    }
+
+  {
+    /* Silence dialog from LoadLibrary on some failures. */
+    DWORD errormode = getthreaderrormode ();
+    DWORD last_error;
+
+    setthreaderrormode (errormode | SEM_FAILCRITICALERRORS, NULL);
+
+    module = LoadLibrary (wpath);
+
+    /* Restore the error mode. */
+    last_error = GetLastError ();
+    setthreaderrormode (errormode, NULL);
+    SetLastError (last_error);
+  }
+
+  /* libltdl expects this function to fail if it is unable
+     to physically load the library.  Sadly, LoadLibrary
+     will search the loaded libraries for a match and return
+     one of them if the path search load fails.
+
+     We check whether LoadLibrary is returning a handle to
+     an already loaded module, and simulate failure if we
+     find one. */
+  {
+    lt_dlhandle cur = 0;
+
+    while ((cur = lt_dlhandle_iterate (iface_id, cur)))
+      {
+        if (!cur->module)
+          {
+            cur = 0;
+            break;
+          }
+
+        if (cur->module == module)
+          {
+            break;
+          }
+      }
+
+    if (!module)
+      LOADLIB_SETERROR (CANNOT_OPEN);
+    else if (cur)
+      {
+        LT__SETERROR (CANNOT_OPEN);
+        module = 0;
+      }
+  }
+
+  return module;
+}
+
+
+/* A function called through the vtable when a particular module
+   should be unloaded.  */
+static int
+vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
+{
+  int errors = 0;
+
+  if (FreeLibrary ((HMODULE) module) == 0)
+    {
+      LOADLIB_SETERROR (CANNOT_CLOSE);
+      ++errors;
+    }
+
+  return errors;
+}
+
+
+/* A function called through the vtable to get the address of
+   a symbol loaded from a particular module.  */
+static void *
+vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
+{
+  void *address = (void *) GetProcAddress ((HMODULE) module, name);
+
+  if (!address)
+    {
+      LOADLIB_SETERROR (SYMBOL_NOT_FOUND);
+    }
+
+  return address;
+}
+
+
+
+/* --- HELPER FUNCTIONS --- */
+
+
+/* Return the windows error message, or the passed in error message on
+   failure. */
+static const char *
+loadlibraryerror (const char *default_errmsg)
+{
+  size_t len;
+  LOCALFREE (error_message);
+
+  FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM |
+                  FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL,
+                  GetLastError (),
+                  0,
+                  (char *) &error_message,
+                  0, NULL);
+
+  /* Remove trailing CRNL */
+  len = LT_STRLEN (error_message);
+  if (len && error_message[len - 1] == '\n')
+    error_message[--len] = LT_EOS_CHAR;
+  if (len && error_message[len - 1] == '\r')
+    error_message[--len] = LT_EOS_CHAR;
+
+  return len ? error_message : default_errmsg;
+}
+
+/* A function called through the getthreaderrormode variable which checks
+   if the system supports GetThreadErrorMode (or GetErrorMode) and arranges
+   for it or a fallback implementation to be called directly in the future.
+   The selected version is then called. */
+static DWORD WINAPI
+wrap_getthreaderrormode (void)
+{
+  HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
+  getthreaderrormode
+    = (getthreaderrormode_type *) GetProcAddress (kernel32,
+                                                 "GetThreadErrorMode");
+  if (!getthreaderrormode)
+    getthreaderrormode
+      = (getthreaderrormode_type *) GetProcAddress (kernel32,
+                                                   "GetErrorMode");
+  if (!getthreaderrormode)
+    getthreaderrormode = fallback_getthreaderrormode;
+  return getthreaderrormode ();
+}
+
+/* A function called through the getthreaderrormode variable for cases
+   where the system does not support GetThreadErrorMode or GetErrorMode */
+static DWORD WINAPI
+fallback_getthreaderrormode (void)
+{
+  /* Prior to Windows Vista, the only way to get the current error
+     mode was to set a new one. In our case, we are setting a new
+     error mode right after "getting" it while ignoring the error
+     mode in effect when setting the new error mode, so that's
+     fairly ok. */
+  return (DWORD) SetErrorMode (SEM_FAILCRITICALERRORS);
+}
+
+/* A function called through the setthreaderrormode variable which checks
+   if the system supports SetThreadErrorMode and arranges for it or a
+   fallback implementation to be called directly in the future.
+   The selected version is then called. */
+static BOOL WINAPI
+wrap_setthreaderrormode (DWORD mode, DWORD *oldmode)
+{
+  HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
+  setthreaderrormode
+    = (setthreaderrormode_type *) GetProcAddress (kernel32,
+                                                 "SetThreadErrorMode");
+  if (!setthreaderrormode)
+    setthreaderrormode = fallback_setthreaderrormode;
+  return setthreaderrormode (mode, oldmode);
+}
+
+/* A function called through the setthreaderrormode variable for cases
+   where the system does not support SetThreadErrorMode. */
+static BOOL WINAPI
+fallback_setthreaderrormode (DWORD mode, DWORD *oldmode)
+{
+  /* Prior to Windows 7, there was no way to set the thread local error
+     mode, so set the process global error mode instead. */
+  DWORD old = (DWORD) SetErrorMode (mode);
+  if (oldmode)
+    *oldmode = old;
+  return TRUE;
+}
diff --git a/libltdl/loaders/preopen.c b/libltdl/loaders/preopen.c
new file mode 100644 (file)
index 0000000..7149287
--- /dev/null
@@ -0,0 +1,375 @@
+/* loader-preopen.c -- emulate dynamic linking using preloaded_symbols
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2006,
+                 2007, 2008 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+/* Use the preprocessor to rename non-static symbols to avoid namespace
+   collisions when the loader code is statically linked into libltdl.
+   Use the "<module_name>_LTX_" prefix so that the symbol addresses can
+   be fetched from the preloaded symbol list by lt_dlsym():  */
+#define get_vtable     preopen_LTX_get_vtable
+
+LT_BEGIN_C_DECLS
+LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
+LT_END_C_DECLS
+
+
+/* Boilerplate code to set up the vtable for hooking this loader into
+   libltdl's loader list:  */
+static int      vl_init  (lt_user_data loader_data);
+static int      vl_exit  (lt_user_data loader_data);
+static lt_module vm_open  (lt_user_data loader_data, const char *filename,
+                           lt_dladvise advise);
+static int      vm_close (lt_user_data loader_data, lt_module module);
+static void *   vm_sym   (lt_user_data loader_data, lt_module module,
+                         const char *symbolname);
+
+static lt_dlvtable *vtable = 0;
+
+/* Return the vtable for this loader, only the name and sym_prefix
+   attributes (plus the virtual function implementations, obviously)
+   change between loaders.  */
+lt_dlvtable *
+get_vtable (lt_user_data loader_data)
+{
+  if (!vtable)
+    {
+      vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
+    }
+
+  if (vtable && !vtable->name)
+    {
+      vtable->name             = "lt_preopen";
+      vtable->sym_prefix       = 0;
+      vtable->module_open      = vm_open;
+      vtable->module_close     = vm_close;
+      vtable->find_sym         = vm_sym;
+      vtable->dlloader_init    = vl_init;
+      vtable->dlloader_exit    = vl_exit;
+      vtable->dlloader_data    = loader_data;
+      vtable->priority         = LT_DLLOADER_PREPEND;
+    }
+
+  if (vtable && (vtable->dlloader_data != loader_data))
+    {
+      LT__SETERROR (INIT_LOADER);
+      return 0;
+    }
+
+  return vtable;
+}
+
+
+
+/* --- IMPLEMENTATION --- */
+
+
+/* Wrapper type to chain together symbol lists of various origins.  */
+typedef struct symlist_chain
+{
+  struct symlist_chain *next;
+  const lt_dlsymlist   *symlist;
+} symlist_chain;
+
+
+static int add_symlist   (const lt_dlsymlist *symlist);
+static int free_symlists (void);
+
+/* The start of the symbol lists chain.  */
+static symlist_chain          *preloaded_symlists              = 0;
+
+/* A symbol list preloaded before lt_init() was called.  */
+static const   lt_dlsymlist   *default_preloaded_symbols       = 0;
+
+
+/* A function called through the vtable to initialise this loader.  */
+static int
+vl_init (lt_user_data LT__UNUSED loader_data)
+{
+  int errors = 0;
+
+  preloaded_symlists = 0;
+  if (default_preloaded_symbols)
+    {
+      errors = lt_dlpreload (default_preloaded_symbols);
+    }
+
+  return errors;
+}
+
+
+/* A function called through the vtable when this loader is no
+   longer needed by the application.  */
+static int
+vl_exit (lt_user_data LT__UNUSED loader_data)
+{
+  vtable = NULL;
+  free_symlists ();
+  return 0;
+}
+
+
+/* A function called through the vtable to open a module with this
+   loader.  Returns an opaque representation of the newly opened
+   module for processing with this loader's other vtable functions.  */
+static lt_module
+vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
+         lt_dladvise LT__UNUSED advise)
+{
+  symlist_chain *lists;
+  lt_module     module = 0;
+
+  if (!preloaded_symlists)
+    {
+      LT__SETERROR (NO_SYMBOLS);
+      goto done;
+    }
+
+  /* Can't use NULL as the reflective symbol header, as NULL is
+     used to mark the end of the entire symbol list.  Self-dlpreopened
+     symbols follow this magic number, chosen to be an unlikely
+     clash with a real module name.  */
+  if (!filename)
+    {
+      filename = "@PROGRAM@";
+    }
+
+  for (lists = preloaded_symlists; lists; lists = lists->next)
+    {
+      const lt_dlsymlist *symbol;
+      for (symbol= lists->symlist; symbol->name; ++symbol)
+       {
+         if (!symbol->address && streq (symbol->name, filename))
+           {
+             /* If the next symbol's name and address is 0, it means
+                the module just contains the originator and no symbols.
+                In this case we pretend that we never saw the module and
+                hope that some other loader will be able to load the module
+                and have access to its symbols */
+             const lt_dlsymlist *next_symbol = symbol +1;
+             if (next_symbol->address && next_symbol->name)
+               {
+                 module = (lt_module) lists->symlist;
+                 goto done;
+               }
+           }
+       }
+    }
+
+  LT__SETERROR (FILE_NOT_FOUND);
+
+ done:
+  return module;
+}
+
+
+/* A function called through the vtable when a particular module
+   should be unloaded.  */
+static int
+vm_close (lt_user_data LT__UNUSED loader_data, lt_module LT__UNUSED module)
+{
+  /* Just to silence gcc -Wall */
+  module = 0;
+  return 0;
+}
+
+
+/* A function called through the vtable to get the address of
+   a symbol loaded from a particular module.  */
+static void *
+vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
+{
+  lt_dlsymlist        *symbol = (lt_dlsymlist*) module;
+
+  symbol +=2;                  /* Skip header (originator then libname). */
+
+  while (symbol->name)
+    {
+      if (streq (symbol->name, name))
+       {
+         return symbol->address;
+       }
+
+    ++symbol;
+  }
+
+  LT__SETERROR (SYMBOL_NOT_FOUND);
+
+  return 0;
+}
+
+
+
+/* --- HELPER FUNCTIONS --- */
+
+
+/* The symbol lists themselves are not allocated from the heap, but
+   we can unhook them and free up the chain of links between them.  */
+static int
+free_symlists (void)
+{
+  symlist_chain *lists;
+
+  lists = preloaded_symlists;
+  while (lists)
+    {
+      symlist_chain *next = lists->next;
+      FREE (lists);
+      lists = next;
+    }
+  preloaded_symlists = 0;
+
+  return 0;
+}
+
+/* Add a new symbol list to the global chain.  */
+static int
+add_symlist (const lt_dlsymlist *symlist)
+{
+  symlist_chain *lists;
+  int           errors   = 0;
+
+  /* Search for duplicate entries:  */
+  for (lists = preloaded_symlists;
+       lists && lists->symlist != symlist; lists = lists->next)
+    /*NOWORK*/;
+
+  /* Don't add the same list twice:  */
+  if (!lists)
+    {
+      symlist_chain *tmp = (symlist_chain *) lt__zalloc (sizeof *tmp);
+
+      if (tmp)
+       {
+         tmp->symlist = symlist;
+         tmp->next = preloaded_symlists;
+         preloaded_symlists = tmp;
+       }
+      else
+       {
+         ++errors;
+       }
+    }
+
+  return errors;
+}
+
+
+
+/* --- PRELOADING API CALL IMPLEMENTATIONS --- */
+
+
+/* Save a default symbol list for later.  */
+int
+lt_dlpreload_default (const lt_dlsymlist *preloaded)
+{
+  default_preloaded_symbols = preloaded;
+  return 0;
+}
+
+
+/* Add a symbol list to the global chain, or with a NULL argument,
+   revert to just the default list.  */
+int
+lt_dlpreload (const lt_dlsymlist *preloaded)
+{
+  int errors = 0;
+
+  if (preloaded)
+    {
+      errors = add_symlist (preloaded);
+    }
+  else
+    {
+      free_symlists();
+
+      if (default_preloaded_symbols)
+       {
+         errors = lt_dlpreload (default_preloaded_symbols);
+       }
+    }
+
+  return errors;
+}
+
+
+/* Open all the preloaded modules from the named originator, executing
+   a callback for each one.  If ORIGINATOR is NULL, then call FUNC for
+   each preloaded module from the program itself.  */
+int
+lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
+{
+  symlist_chain *list;
+  int           errors = 0;
+  int           found  = 0;
+
+  /* For each symlist in the chain...  */
+  for (list = preloaded_symlists; list; list = list->next)
+    {
+      /* ...that was preloaded by the requesting ORIGINATOR... */
+      if ((originator && streq (list->symlist->name, originator))
+          || (!originator && streq (list->symlist->name, "@PROGRAM@")))
+       {
+         const lt_dlsymlist *symbol;
+         unsigned int idx = 0;
+
+         ++found;
+
+         /* ...load the symbols per source compilation unit:
+            (we preincrement the index to skip over the originator entry)  */
+         while ((symbol = &list->symlist[++idx])->name != 0)
+           {
+             if ((symbol->address == 0)
+                 && (strneq (symbol->name, "@PROGRAM@")))
+               {
+                 lt_dlhandle handle = lt_dlopen (symbol->name);
+                 if (handle == 0)
+                   {
+                     ++errors;
+                   }
+                 else
+                   {
+                     errors += (*func) (handle);
+                   }
+               }
+           }
+       }
+    }
+
+  if (!found)
+    {
+      LT__SETERROR(CANNOT_OPEN);
+      ++errors;
+    }
+
+  return errors;
+}
diff --git a/libltdl/loaders/shl_load.c b/libltdl/loaders/shl_load.c
new file mode 100644 (file)
index 0000000..5a09d87
--- /dev/null
@@ -0,0 +1,222 @@
+/* loader-shl_load.c --  dynamic linking with shl_load (HP-UX)
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2006,
+                 2007, 2008 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+/* Use the preprocessor to rename non-static symbols to avoid namespace
+   collisions when the loader code is statically linked into libltdl.
+   Use the "<module_name>_LTX_" prefix so that the symbol addresses can
+   be fetched from the preloaded symbol list by lt_dlsym():  */
+#define get_vtable     shl_load_LTX_get_vtable
+
+LT_BEGIN_C_DECLS
+LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
+LT_END_C_DECLS
+
+
+/* Boilerplate code to set up the vtable for hooking this loader into
+   libltdl's loader list:  */
+static int      vl_exit  (lt_user_data loader_data);
+static lt_module vm_open  (lt_user_data loader_data, const char *filename,
+                           lt_dladvise advise);
+static int      vm_close (lt_user_data loader_data, lt_module module);
+static void *   vm_sym   (lt_user_data loader_data, lt_module module,
+                         const char *symbolname);
+
+static lt_dlvtable *vtable = 0;
+
+/* Return the vtable for this loader, only the name and sym_prefix
+   attributes (plus the virtual function implementations, obviously)
+   change between loaders.  */
+lt_dlvtable *
+get_vtable (lt_user_data loader_data)
+{
+  if (!vtable)
+    {
+      vtable = lt__zalloc (sizeof *vtable);
+    }
+
+  if (vtable && !vtable->name)
+    {
+      vtable->name             = "lt_shl_load";
+      vtable->module_open      = vm_open;
+      vtable->module_close     = vm_close;
+      vtable->find_sym         = vm_sym;
+      vtable->dlloader_exit    = vl_exit;
+      vtable->dlloader_data    = loader_data;
+      vtable->priority         = LT_DLLOADER_APPEND;
+    }
+
+  if (vtable && (vtable->dlloader_data != loader_data))
+    {
+      LT__SETERROR (INIT_LOADER);
+      return 0;
+    }
+
+  return vtable;
+}
+
+
+
+/* --- IMPLEMENTATION --- */
+
+
+#if defined(HAVE_DL_H)
+#  include <dl.h>
+#endif
+
+/* some flags are missing on some systems, so we provide
+ * harmless defaults.
+ *
+ * Mandatory:
+ * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
+ * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
+ *
+ * Optionally:
+ * BIND_FIRST     - Place the library at the head of the symbol search
+ *                  order.
+ * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
+ *                  unsatisfied symbols as fatal.  This flag allows
+ *                  binding of unsatisfied code symbols to be deferred
+ *                  until use.
+ *                  [Perl: For certain libraries, like DCE, deferred
+ *                  binding often causes run time problems. Adding
+ *                  BIND_NONFATAL to BIND_IMMEDIATE still allows
+ *                  unresolved references in situations like this.]
+ * BIND_NOSTART           - Do not call the initializer for the shared library
+ *                  when the library is loaded, nor on a future call to
+ *                  shl_unload().
+ * BIND_VERBOSE           - Print verbose messages concerning possible
+ *                  unsatisfied symbols.
+ *
+ * hp9000s700/hp9000s800:
+ * BIND_RESTRICTED - Restrict symbols visible by the library to those
+ *                  present at library load time.
+ * DYNAMIC_PATH           - Allow the loader to dynamically search for the
+ *                  library specified by the path argument.
+ */
+
+#if !defined(DYNAMIC_PATH)
+#  define DYNAMIC_PATH         0
+#endif
+#if !defined(BIND_RESTRICTED)
+#  define BIND_RESTRICTED      0
+#endif
+
+#define        LT_BIND_FLAGS   (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
+
+
+/* A function called through the vtable when this loader is no
+   longer needed by the application.  */
+static int
+vl_exit (lt_user_data LT__UNUSED loader_data)
+{
+  vtable = NULL;
+  return 0;
+}
+
+/* A function called through the vtable to open a module with this
+   loader.  Returns an opaque representation of the newly opened
+   module for processing with this loader's other vtable functions.  */
+static lt_module
+vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
+         lt_dladvise LT__UNUSED advise)
+{
+  static shl_t self = (shl_t) 0;
+  lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
+
+  /* Since searching for a symbol against a NULL module handle will also
+     look in everything else that was already loaded and exported with
+     the -E compiler flag, we always cache a handle saved before any
+     modules are loaded.  */
+  if (!self)
+    {
+      void *address;
+      shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
+    }
+
+  if (!filename)
+    {
+      module = self;
+    }
+  else
+    {
+      module = shl_load (filename, LT_BIND_FLAGS, 0L);
+
+      if (!module)
+       {
+         LT__SETERROR (CANNOT_OPEN);
+       }
+    }
+
+  return module;
+}
+
+/* A function called through the vtable when a particular module
+   should be unloaded.  */
+static int
+vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
+{
+  int errors = 0;
+
+  if (module && (shl_unload ((shl_t) (module)) != 0))
+    {
+      LT__SETERROR (CANNOT_CLOSE);
+      ++errors;
+    }
+
+  return errors;
+}
+
+
+/* A function called through the vtable to get the address of
+   a symbol loaded from a particular module.  */
+static void *
+vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
+{
+  void *address = 0;
+
+  /* sys_shl_open should never return a NULL module handle */
+  if (module == (lt_module) 0)
+  {
+    LT__SETERROR (INVALID_HANDLE);
+  }
+  else if (!shl_findsym((shl_t*) &module, name, TYPE_UNDEFINED, &address))
+    {
+      if (!address)
+       {
+         LT__SETERROR (SYMBOL_NOT_FOUND);
+       }
+    }
+
+  return address;
+}
diff --git a/libltdl/lt__alloc.c b/libltdl/lt__alloc.c
new file mode 100644 (file)
index 0000000..d39e17e
--- /dev/null
@@ -0,0 +1,95 @@
+/* lt__alloc.c -- internal memory management interface
+
+   Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+
+#include <stdio.h>
+
+#include "lt__alloc.h"
+
+static void alloc_die_default (void);
+
+void (*lt__alloc_die) (void) = alloc_die_default;
+
+/* Unless overridden, exit on memory failure.  */
+static void
+alloc_die_default (void)
+{
+  fprintf (stderr, "Out of memory.\n");
+  exit (EXIT_FAILURE);
+}
+
+void *
+lt__malloc (size_t n)
+{
+  void *mem;
+
+  if (! (mem = malloc (n)))
+    (*lt__alloc_die) ();
+
+  return mem;
+}
+
+void *
+lt__zalloc (size_t n)
+{
+  void *mem;
+
+  if ((mem = lt__malloc (n)))
+    memset (mem, 0, n);
+
+  return mem;
+}
+
+void *
+lt__realloc (void *mem, size_t n)
+{
+  if (! (mem = realloc (mem, n)))
+    (*lt__alloc_die) ();
+
+  return mem;
+}
+
+void *
+lt__memdup (void const *mem, size_t n)
+{
+  void *newmem;
+
+  if ((newmem = lt__malloc (n)))
+    return memcpy (newmem, mem, n);
+
+  return 0;
+}
+
+char *
+lt__strdup (const char *string)
+{
+  return (char *) lt__memdup (string, strlen (string) +1);
+}
diff --git a/libltdl/lt__dirent.c b/libltdl/lt__dirent.c
new file mode 100644 (file)
index 0000000..30dc072
--- /dev/null
@@ -0,0 +1,107 @@
+/* lt__dirent.c -- internal directory entry scanning interface
+
+   Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+   Written by Bob Friesenhahn, 2001
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+
+#include <assert.h>
+#include <stddef.h>
+
+#include "lt__dirent.h"
+
+#if defined(__WINDOWS__)
+
+void
+closedir (DIR *entry)
+{
+  assert (entry != (DIR *) NULL);
+  FindClose (entry->hSearch);
+  free ((void *) entry);
+}
+
+
+DIR *
+opendir (const char *path)
+{
+  char file_spec[LT_FILENAME_MAX];
+  DIR *entry;
+
+  assert (path != (char *) 0);
+  if (lt_strlcpy (file_spec, path, sizeof file_spec) >= sizeof file_spec
+      || lt_strlcat (file_spec, "\\", sizeof file_spec) >= sizeof file_spec)
+    return (DIR *) 0;
+  entry = (DIR *) malloc (sizeof(DIR));
+  if (entry != (DIR *) 0)
+    {
+      entry->firsttime = TRUE;
+      entry->hSearch = FindFirstFile (file_spec, &entry->Win32FindData);
+
+      if (entry->hSearch == INVALID_HANDLE_VALUE)
+       {
+         if (lt_strlcat (file_spec, "\\*.*", sizeof file_spec) < sizeof file_spec)
+           {
+             entry->hSearch = FindFirstFile (file_spec, &entry->Win32FindData);
+           }
+
+         if (entry->hSearch == INVALID_HANDLE_VALUE)
+           {
+             entry = (free (entry), (DIR *) 0);
+           }
+       }
+    }
+
+  return entry;
+}
+
+
+struct dirent *
+readdir (DIR *entry)
+{
+  int status;
+
+  if (entry == (DIR *) 0)
+    return (struct dirent *) 0;
+
+  if (!entry->firsttime)
+    {
+      status = FindNextFile (entry->hSearch, &entry->Win32FindData);
+      if (status == 0)
+        return (struct dirent *) 0;
+    }
+
+  entry->firsttime = FALSE;
+  if (lt_strlcpy (entry->file_info.d_name, entry->Win32FindData.cFileName,
+       sizeof entry->file_info.d_name) >= sizeof entry->file_info.d_name)
+    return (struct dirent *) 0;
+  entry->file_info.d_namlen = strlen (entry->file_info.d_name);
+
+  return &entry->file_info;
+}
+
+#endif /*defined(__WINDOWS__)*/
diff --git a/libltdl/lt__strl.c b/libltdl/lt__strl.c
new file mode 100644 (file)
index 0000000..c2cee58
--- /dev/null
@@ -0,0 +1,127 @@
+/* lt__strl.c -- size-bounded string copying and concatenation
+
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Written by Bob Friesenhahn, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <assert.h>
+#include <string.h>
+
+#include "lt__strl.h"
+
+/*
+ lt_strlcat appends the NULL-terminated string src to the end of dst.
+ It will append at most dstsize - strlen(dst) - 1 bytes,
+ NULL-terminating the result. The total length of the string which
+ would have been created given sufficient buffer size (may be longer
+ than dstsize) is returned.  This function substitutes for strlcat()
+ which is available under NetBSD, FreeBSD and Solaris 9.
+
+ Buffer overflow can be checked as follows:
+
+   if (lt_strlcat(dst, src, dstsize) >= dstsize)
+     return -1;
+*/
+#if !defined(HAVE_STRLCAT)
+size_t
+lt_strlcat(char *dst, const char *src, const size_t dstsize)
+{
+  size_t length;
+  char *p;
+  const char *q;
+
+  assert(dst != NULL);
+  assert(src != (const char *) NULL);
+  assert(dstsize >= 1);
+
+  length=strlen(dst);
+
+  /*
+    Copy remaining characters from src while constraining length to
+    size - 1.
+  */
+  for ( p = dst + length, q = src;
+        (*q != 0) && (length < dstsize - 1) ;
+        length++, p++, q++ )
+    *p = *q;
+
+  dst[length]='\0';
+
+  /*
+    Add remaining length of src to length.
+  */
+  while (*q++)
+    length++;
+
+  return length;
+}
+#endif /* !defined(HAVE_STRLCAT) */
+
+/*
+  lt_strlcpy copies up to dstsize - 1 characters from the NULL-terminated
+  string src to dst, NULL-terminating the result. The total length of
+  the string which would have been created given sufficient buffer
+  size (may be longer than dstsize) is returned. This function
+  substitutes for strlcpy() which is available under OpenBSD, FreeBSD
+  and Solaris 9.
+
+  Buffer overflow can be checked as  follows:
+
+    if (lt_strlcpy(dst, src, dstsize) >= dstsize)
+      return -1;
+*/
+#if !defined(HAVE_STRLCPY)
+size_t
+lt_strlcpy(char *dst, const char *src, const size_t dstsize)
+{
+  size_t length=0;
+  char *p;
+  const char *q;
+
+  assert(dst != NULL);
+  assert(src != (const char *) NULL);
+  assert(dstsize >= 1);
+
+  /*
+    Copy src to dst within bounds of size-1.
+  */
+  for ( p=dst, q=src, length=0 ;
+        (*q != 0) && (length < dstsize-1) ;
+        length++, p++, q++ )
+    *p = *q;
+
+  dst[length]='\0';
+
+  /*
+    Add remaining length of src to length.
+  */
+  while (*q++)
+    length++;
+
+  return length;
+}
+#endif /* !defined(HAVE_STRLCPY) */
diff --git a/libltdl/lt_dlloader.c b/libltdl/lt_dlloader.c
new file mode 100644 (file)
index 0000000..2c99a22
--- /dev/null
@@ -0,0 +1,210 @@
+/* lt_dlloader.c -- dynamic library loader interface
+
+   Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2004
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_dlloader.h"
+
+#define RETURN_SUCCESS 0
+#define RETURN_FAILURE 1
+
+static void *  loader_callback (SList *item, void *userdata);
+
+/* A list of all the dlloaders we know about, each stored as a boxed
+   SList item:  */
+static SList    *loaders               = 0;
+
+
+/* Return NULL, unless the loader in this ITEM has a matching name,
+   in which case we return the matching item so that its address is
+   passed back out (for possible freeing) by slist_remove.  */
+static void *
+loader_callback (SList *item, void *userdata)
+{
+  const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
+  const char *     name    = (const char *) userdata;
+
+  assert (vtable);
+
+  return streq (vtable->name, name) ? (void *) item : NULL;
+}
+
+
+/* Hook VTABLE into our global LOADERS list according to its own
+   PRIORITY field value.  */
+int
+lt_dlloader_add (const lt_dlvtable *vtable)
+{
+  SList *item;
+
+  if ((vtable == 0)    /* diagnose invalid vtable fields */
+      || (vtable->module_open == 0)
+      || (vtable->module_close == 0)
+      || (vtable->find_sym == 0)
+      || ((vtable->priority != LT_DLLOADER_PREPEND) &&
+         (vtable->priority != LT_DLLOADER_APPEND)))
+    {
+      LT__SETERROR (INVALID_LOADER);
+      return RETURN_FAILURE;
+    }
+
+  item = slist_box (vtable);
+  if (!item)
+    {
+      (*lt__alloc_die) ();
+
+      /* Let the caller know something went wrong if lt__alloc_die
+        doesn't abort.  */
+      return RETURN_FAILURE;
+    }
+
+  if (vtable->priority == LT_DLLOADER_PREPEND)
+    {
+      loaders = slist_cons (item, loaders);
+    }
+  else
+    {
+      assert (vtable->priority == LT_DLLOADER_APPEND);
+      loaders = slist_concat (loaders, item);
+    }
+
+  return RETURN_SUCCESS;
+}
+
+#ifdef LT_DEBUG_LOADERS
+static void *
+loader_dump_callback (SList *item, void *userdata)
+{
+  const lt_dlvtable *vtable = (const lt_dlvtable *) item->userdata;
+  fprintf (stderr, ", %s", (vtable && vtable->name) ? vtable->name : "(null)");
+  return 0;
+}
+
+void
+lt_dlloader_dump (void)
+{
+  fprintf (stderr, "loaders: ");
+  if (!loaders)
+    {
+      fprintf (stderr, "(empty)");
+    }
+  else
+    {
+      const lt_dlvtable *head = (const lt_dlvtable *) loaders->userdata;
+      fprintf (stderr, "%s", (head && head->name) ? head->name : "(null)");
+      if (slist_tail (loaders))
+       slist_foreach (slist_tail (loaders), loader_dump_callback, NULL);
+    }
+  fprintf (stderr, "\n");
+}
+#endif
+
+/* An iterator for the global loader list: if LOADER is NULL, then
+   return the first element, otherwise the following element.  */
+lt_dlloader
+lt_dlloader_next (lt_dlloader loader)
+{
+  SList *item = (SList *) loader;
+  return (lt_dlloader) (item ? item->next : loaders);
+}
+
+
+/* Non-destructive unboxing of a loader.  */
+const lt_dlvtable *
+lt_dlloader_get        (lt_dlloader loader)
+{
+  return (const lt_dlvtable *) (loader ? ((SList *) loader)->userdata : NULL);
+}
+
+
+/* Return the contents of the first item in the global loader list
+   with a matching NAME after removing it from that list.  If there
+   was no match, return NULL; if there is an error, return NULL and
+   set an error for lt_dlerror; do not set an error if only resident
+   modules need this loader; in either case, the loader list is not
+   changed if NULL is returned.  */
+lt_dlvtable *
+lt_dlloader_remove (const char *name)
+{
+  const lt_dlvtable *  vtable  = lt_dlloader_find (name);
+  static const char    id_string[] = "lt_dlloader_remove";
+  lt_dlinterface_id    iface;
+  lt_dlhandle          handle = 0;
+  int                  in_use = 0;
+  int                  in_use_by_resident = 0;
+
+  if (!vtable)
+    {
+      LT__SETERROR (INVALID_LOADER);
+      return 0;
+    }
+
+  /* Fail if there are any open modules which use this loader.  */
+  iface = lt_dlinterface_register (id_string, NULL);
+  while ((handle = lt_dlhandle_iterate (iface, handle)))
+    {
+      lt_dlhandle cur = handle;
+      if (cur->vtable == vtable)
+       {
+         in_use = 1;
+         if (lt_dlisresident (handle))
+           in_use_by_resident = 1;
+       }
+    }
+  lt_dlinterface_free (iface);
+  if (in_use)
+    {
+      if (!in_use_by_resident)
+       LT__SETERROR (REMOVE_LOADER);
+      return 0;
+    }
+
+  /* Call the loader finalisation function.  */
+  if (vtable && vtable->dlloader_exit)
+    {
+      if ((*vtable->dlloader_exit) (vtable->dlloader_data) != 0)
+       {
+         /* If there is an exit function, and it returns non-zero
+            then it must set an error, and we will not remove it
+            from the list.  */
+         return 0;
+       }
+    }
+
+  /* If we got this far, remove the loader from our global list.  */
+  return (lt_dlvtable *)
+      slist_unbox ((SList *) slist_remove (&loaders, loader_callback, (void *) name));
+}
+
+
+const lt_dlvtable *
+lt_dlloader_find (const char *name)
+{
+  return lt_dlloader_get (slist_find (loaders, loader_callback, (void *) name));
+}
diff --git a/libltdl/lt_error.c b/libltdl/lt_error.c
new file mode 100644 (file)
index 0000000..d7af36d
--- /dev/null
@@ -0,0 +1,110 @@
+/* lt_error.c -- error propogation interface
+
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1999
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_error.h"
+
+static const char      *last_error     = 0;
+static const char      error_strings[LT_ERROR_MAX][LT_ERROR_LEN_MAX + 1] =
+  {
+#define LT_ERROR(name, diagnostic)     diagnostic,
+    lt_dlerror_table
+#undef LT_ERROR
+  };
+
+static const char    **user_error_strings      = 0;
+static int             errorcount              = LT_ERROR_MAX;
+
+int
+lt_dladderror (const char *diagnostic)
+{
+  int          errindex = 0;
+  int          result   = -1;
+  const char  **temp     = (const char **) 0;
+
+  assert (diagnostic);
+
+  errindex = errorcount - LT_ERROR_MAX;
+  temp = REALLOC (const char *, user_error_strings, 1 + errindex);
+  if (temp)
+    {
+      user_error_strings               = temp;
+      user_error_strings[errindex]     = diagnostic;
+      result                           = errorcount++;
+    }
+
+  return result;
+}
+
+int
+lt_dlseterror (int errindex)
+{
+  int          errors   = 0;
+
+  if (errindex >= errorcount || errindex < 0)
+    {
+      /* Ack!  Error setting the error message! */
+      LT__SETERROR (INVALID_ERRORCODE);
+      ++errors;
+    }
+  else if (errindex < LT_ERROR_MAX)
+    {
+      /* No error setting the error message! */
+      LT__SETERRORSTR (error_strings[errindex]);
+    }
+  else
+    {
+      /* No error setting the error message! */
+      LT__SETERRORSTR (user_error_strings[errindex - LT_ERROR_MAX]);
+    }
+
+  return errors;
+}
+
+const char *
+lt__error_string (int errorcode)
+{
+  assert (errorcode >= 0);
+  assert (errorcode < LT_ERROR_MAX);
+
+  return error_strings[errorcode];
+}
+
+const char *
+lt__get_last_error (void)
+{
+  return last_error;
+}
+
+const char *
+lt__set_last_error (const char *errormsg)
+{
+  return last_error = errormsg;
+}
diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c
new file mode 100644 (file)
index 0000000..01853e0
--- /dev/null
@@ -0,0 +1,2464 @@
+/* ltdl.c -- system independent dlopen wrapper
+
+   Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
+                2007, 2008, 2011 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "lt__private.h"
+#include "lt_system.h"
+#include "lt_dlloader.h"
+
+
+/* --- MANIFEST CONSTANTS --- */
+
+
+/* Standard libltdl search path environment variable name  */
+#undef  LTDL_SEARCHPATH_VAR
+#define LTDL_SEARCHPATH_VAR    "LTDL_LIBRARY_PATH"
+
+/* Standard libtool archive file extension.  */
+#undef  LT_ARCHIVE_EXT
+#define LT_ARCHIVE_EXT ".la"
+
+/* max. filename length */
+#if !defined(LT_FILENAME_MAX)
+#  define LT_FILENAME_MAX      1024
+#endif
+
+#if !defined(LT_LIBEXT)
+#  define LT_LIBEXT "a"
+#endif
+
+#if !defined(LT_LIBPREFIX)
+#  define LT_LIBPREFIX "lib"
+#endif
+
+/* This is the maximum symbol size that won't require malloc/free */
+#undef LT_SYMBOL_LENGTH
+#define LT_SYMBOL_LENGTH       128
+
+/* This accounts for the _LTX_ separator */
+#undef LT_SYMBOL_OVERHEAD
+#define LT_SYMBOL_OVERHEAD     5
+
+/* Various boolean flags can be stored in the flags field of an
+   lt_dlhandle... */
+#define LT_DLIS_RESIDENT(handle)  ((handle)->info.is_resident)
+#define LT_DLIS_SYMGLOBAL(handle) ((handle)->info.is_symglobal)
+#define LT_DLIS_SYMLOCAL(handle)  ((handle)->info.is_symlocal)
+
+
+static const char      objdir[]                = LT_OBJDIR;
+static const char      archive_ext[]           = LT_ARCHIVE_EXT;
+static  const char     libext[]                = LT_LIBEXT;
+static  const char     libprefix[]             = LT_LIBPREFIX;
+#if defined(LT_MODULE_EXT)
+static const char      shlib_ext[]             = LT_MODULE_EXT;
+#endif
+/* If the loadable module suffix is not the same as the linkable
+ * shared library suffix, this will be defined. */
+#if defined(LT_SHARED_EXT)
+static const char      shared_ext[]            = LT_SHARED_EXT;
+#endif
+#if defined(LT_DLSEARCH_PATH)
+static const char      sys_dlsearch_path[]     = LT_DLSEARCH_PATH;
+#endif
+
+
+
+\f
+/* --- DYNAMIC MODULE LOADING --- */
+
+
+/* The type of a function used at each iteration of  foreach_dirinpath().  */
+typedef int    foreach_callback_func (char *filename, void *data1,
+                                      void *data2);
+/* foreachfile_callback itself calls a function of this type: */
+typedef int    file_worker_func      (const char *filename, void *data);
+
+
+static int     foreach_dirinpath     (const char *search_path,
+                                      const char *base_name,
+                                      foreach_callback_func *func,
+                                      void *data1, void *data2);
+static int     find_file_callback    (char *filename, void *data1,
+                                      void *data2);
+static int     find_handle_callback  (char *filename, void *data,
+                                      void *ignored);
+static int     foreachfile_callback  (char *filename, void *data1,
+                                      void *data2);
+
+
+static int     canonicalize_path     (const char *path, char **pcanonical);
+static int     argzize_path          (const char *path,
+                                      char **pargz, size_t *pargz_len);
+static FILE   *find_file             (const char *search_path,
+                                      const char *base_name, char **pdir);
+static lt_dlhandle *find_handle      (const char *search_path,
+                                      const char *base_name,
+                                      lt_dlhandle *handle,
+                                      lt_dladvise advise);
+static int     find_module           (lt_dlhandle *handle, const char *dir,
+                                      const char *libdir, const char *dlname,
+                                      const char *old_name, int installed,
+                                      lt_dladvise advise);
+static  int     has_library_ext       (const char *filename);
+static int     load_deplibs          (lt_dlhandle handle,  char *deplibs);
+static int     trim                  (char **dest, const char *str);
+static int     try_dlopen            (lt_dlhandle *handle,
+                                      const char *filename, const char *ext,
+                                      lt_dladvise advise);
+static int     tryall_dlopen         (lt_dlhandle *handle,
+                                      const char *filename,
+                                      lt_dladvise padvise,
+                                      const lt_dlvtable *vtable);
+static int     unload_deplibs        (lt_dlhandle handle);
+static int     lt_argz_insert        (char **pargz, size_t *pargz_len,
+                                      char *before, const char *entry);
+static int     lt_argz_insertinorder (char **pargz, size_t *pargz_len,
+                                      const char *entry);
+static int     lt_argz_insertdir     (char **pargz, size_t *pargz_len,
+                                      const char *dirnam, struct dirent *dp);
+static int     lt_dlpath_insertdir   (char **ppath, char *before,
+                                      const char *dir);
+static int     list_files_by_dir     (const char *dirnam,
+                                      char **pargz, size_t *pargz_len);
+static int     file_not_found        (void);
+
+#ifdef HAVE_LIBDLLOADER
+static int     loader_init_callback  (lt_dlhandle handle);
+#endif /* HAVE_LIBDLLOADER */
+
+static int     loader_init           (lt_get_vtable *vtable_func,
+                                      lt_user_data data);
+
+static char           *user_search_path= 0;
+static lt_dlhandle     handles = 0;
+static int             initialized     = 0;
+
+/* Our memory failure callback sets the error message to be passed back
+   up to the client, so we must be careful to return from mallocation
+   callers if allocation fails (as this callback returns!!).  */
+void
+lt__alloc_die_callback (void)
+{
+  LT__SETERROR (NO_MEMORY);
+}
+
+#ifdef HAVE_LIBDLLOADER
+/* This function is called to initialise each preloaded module loader,
+   and hook it into the list of loaders to be used when attempting to
+   dlopen an application module.  */
+static int
+loader_init_callback (lt_dlhandle handle)
+{
+  lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");
+  return loader_init (vtable_func, 0);
+}
+#endif /* HAVE_LIBDLLOADER */
+
+static int
+loader_init (lt_get_vtable *vtable_func, lt_user_data data)
+{
+  const lt_dlvtable *vtable = 0;
+  int errors = 0;
+
+  if (vtable_func)
+    {
+      vtable = (*vtable_func) (data);
+    }
+
+  /* lt_dlloader_add will LT__SETERROR if it fails.  */
+  errors += lt_dlloader_add (vtable);
+
+  assert (errors || vtable);
+
+  if ((!errors) && vtable->dlloader_init)
+    {
+      if ((*vtable->dlloader_init) (vtable->dlloader_data))
+       {
+         LT__SETERROR (INIT_LOADER);
+         ++errors;
+       }
+    }
+
+  return errors;
+}
+
+/* Bootstrap the loader loading with the preopening loader.  */
+#define get_vtable             preopen_LTX_get_vtable
+#define preloaded_symbols      LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)
+
+LT_BEGIN_C_DECLS
+LT_SCOPE const lt_dlvtable *   get_vtable (lt_user_data data);
+LT_END_C_DECLS
+#ifdef HAVE_LIBDLLOADER
+extern LT_DLSYM_CONST lt_dlsymlist preloaded_symbols[];
+#endif
+
+/* Initialize libltdl. */
+int
+lt_dlinit (void)
+{
+  int  errors  = 0;
+
+  /* Initialize only at first call. */
+  if (++initialized == 1)
+    {
+      lt__alloc_die    = lt__alloc_die_callback;
+      handles          = 0;
+      user_search_path = 0; /* empty search path */
+
+      /* First set up the statically loaded preload module loader, so
+        we can use it to preopen the other loaders we linked in at
+        compile time.  */
+      errors += loader_init (get_vtable, 0);
+
+      /* Now open all the preloaded module loaders, so the application
+        can use _them_ to lt_dlopen its own modules.  */
+#ifdef HAVE_LIBDLLOADER
+      if (!errors)
+       {
+         errors += lt_dlpreload (preloaded_symbols);
+       }
+
+      if (!errors)
+       {
+         errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
+       }
+#endif /* HAVE_LIBDLLOADER */
+    }
+
+#ifdef LT_DEBUG_LOADERS
+  lt_dlloader_dump();
+#endif
+
+  return errors;
+}
+
+int
+lt_dlexit (void)
+{
+  /* shut down libltdl */
+  lt_dlloader *loader   = 0;
+  lt_dlhandle  handle   = handles;
+  int         errors   = 0;
+
+  if (!initialized)
+    {
+      LT__SETERROR (SHUTDOWN);
+      ++errors;
+      goto done;
+    }
+
+  /* shut down only at last call. */
+  if (--initialized == 0)
+    {
+      int      level;
+
+      while (handles && LT_DLIS_RESIDENT (handles))
+       {
+         handles = handles->next;
+       }
+
+      /* close all modules */
+      for (level = 1; handle; ++level)
+       {
+         lt_dlhandle cur = handles;
+         int saw_nonresident = 0;
+
+         while (cur)
+           {
+             lt_dlhandle tmp = cur;
+             cur = cur->next;
+             if (!LT_DLIS_RESIDENT (tmp))
+               {
+                 saw_nonresident = 1;
+                 if (tmp->info.ref_count <= level)
+                   {
+                     if (lt_dlclose (tmp))
+                       {
+                         ++errors;
+                       }
+                     /* Make sure that the handle pointed to by 'cur' still exists.
+                        lt_dlclose recursively closes dependent libraries which removes
+                        them from the linked list.  One of these might be the one
+                        pointed to by 'cur'.  */
+                     if (cur)
+                       {
+                         for (tmp = handles; tmp; tmp = tmp->next)
+                           if (tmp == cur)
+                             break;
+                         if (! tmp)
+                           cur = handles;
+                       }
+                   }
+               }
+           }
+         /* done if only resident modules are left */
+         if (!saw_nonresident)
+           break;
+       }
+
+      /* When removing loaders, we can only find out failure by testing
+        the error string, so avoid a spurious one from an earlier
+        failed command. */
+      if (!errors)
+       LT__SETERRORSTR (0);
+
+      /* close all loaders */
+      for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
+       {
+         lt_dlloader *next   = (lt_dlloader *) lt_dlloader_next (loader);
+         lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);
+
+         if ((vtable = lt_dlloader_remove ((char *) vtable->name)))
+           {
+             FREE (vtable);
+           }
+         else
+           {
+             /* ignore errors due to resident modules */
+             const char *err;
+             LT__GETERROR (err);
+             if (err)
+               ++errors;
+           }
+
+         loader = next;
+       }
+
+      FREE(user_search_path);
+    }
+
+ done:
+  return errors;
+}
+
+
+/* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.
+   If the library is not successfully loaded, return non-zero.  Otherwise,
+   the dlhandle is stored at the address given in PHANDLE.  */
+static int
+tryall_dlopen (lt_dlhandle *phandle, const char *filename,
+              lt_dladvise advise, const lt_dlvtable *vtable)
+{
+  lt_dlhandle  handle          = handles;
+  const char * saved_error     = 0;
+  int          errors          = 0;
+
+#ifdef LT_DEBUG_LOADERS
+  fprintf (stderr, "tryall_dlopen (%s, %s)\n",
+          filename ? filename : "(null)",
+          vtable ? vtable->name : "(ALL)");
+#endif
+
+  LT__GETERROR (saved_error);
+
+  /* check whether the module was already opened */
+  for (;handle; handle = handle->next)
+    {
+      if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
+         || (handle->info.filename && filename
+             && streq (handle->info.filename, filename)))
+       {
+         break;
+       }
+    }
+
+  if (handle)
+    {
+      ++handle->info.ref_count;
+      *phandle = handle;
+      goto done;
+    }
+
+  handle = *phandle;
+  if (filename)
+    {
+      /* Comment out the check of file permissions using access.
+        This call seems to always return -1 with error EACCES.
+      */
+      /* We need to catch missing file errors early so that
+        file_not_found() can detect what happened.
+      if (access (filename, R_OK) != 0)
+       {
+         LT__SETERROR (FILE_NOT_FOUND);
+         ++errors;
+         goto done;
+       } */
+
+      handle->info.filename = lt__strdup (filename);
+      if (!handle->info.filename)
+       {
+         ++errors;
+         goto done;
+       }
+    }
+  else
+    {
+      handle->info.filename = 0;
+    }
+
+  {
+    lt_dlloader loader = lt_dlloader_next (0);
+    const lt_dlvtable *loader_vtable;
+
+    do
+      {
+       if (vtable)
+         loader_vtable = vtable;
+       else
+         loader_vtable = lt_dlloader_get (loader);
+
+#ifdef LT_DEBUG_LOADERS
+       fprintf (stderr, "Calling %s->module_open (%s)\n",
+                (loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",
+                filename ? filename : "(null)");
+#endif
+       handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,
+                                                       filename, advise);
+#ifdef LT_DEBUG_LOADERS
+       fprintf (stderr, "  Result: %s\n",
+                handle->module ? "Success" : "Failed");
+#endif
+
+       if (handle->module != 0)
+         {
+           if (advise)
+             {
+               handle->info.is_resident  = advise->is_resident;
+               handle->info.is_symglobal = advise->is_symglobal;
+               handle->info.is_symlocal  = advise->is_symlocal;
+             }
+           break;
+         }
+      }
+    while (!vtable && (loader = lt_dlloader_next (loader)));
+
+    /* If VTABLE was given but couldn't open the module, or VTABLE wasn't
+       given but we exhausted all loaders without opening the module, bail
+       out!  */
+    if ((vtable && !handle->module)
+       || (!vtable && !loader))
+      {
+       FREE (handle->info.filename);
+       ++errors;
+       goto done;
+      }
+
+    handle->vtable = loader_vtable;
+  }
+
+  LT__SETERRORSTR (saved_error);
+
+ done:
+  return errors;
+}
+
+
+static int
+tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
+                     const char *dirname, const char *dlname,
+                     lt_dladvise advise)
+{
+  int      error       = 0;
+  char     *filename   = 0;
+  size_t   filename_len        = 0;
+  size_t   dirname_len = LT_STRLEN (dirname);
+
+  assert (handle);
+  assert (dirname);
+  assert (dlname);
+#if defined(LT_DIRSEP_CHAR)
+  /* Only canonicalized names (i.e. with DIRSEP chars already converted)
+     should make it into this function:  */
+  assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
+#endif
+
+  if (dirname_len > 0)
+    if (dirname[dirname_len -1] == '/')
+      --dirname_len;
+  filename_len = dirname_len + 1 + LT_STRLEN (dlname);
+
+  /* Allocate memory, and combine DIRNAME and MODULENAME into it.
+     The PREFIX (if any) is handled below.  */
+  filename  = MALLOC (char, filename_len + 1);
+  if (!filename)
+    return 1;
+
+  sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
+
+  /* Now that we have combined DIRNAME and MODULENAME, if there is
+     also a PREFIX to contend with, simply recurse with the arguments
+     shuffled.  Otherwise, attempt to open FILENAME as a module.  */
+  if (prefix)
+    {
+      error += tryall_dlopen_module (handle, (const char *) 0,
+                                    prefix, filename, advise);
+    }
+  else if (tryall_dlopen (handle, filename, advise, 0) != 0)
+    {
+      ++error;
+    }
+
+  FREE (filename);
+  return error;
+}
+
+static int
+find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
+            const char *dlname,  const char *old_name, int installed,
+            lt_dladvise advise)
+{
+  /* Try to open the old library first; if it was dlpreopened,
+     we want the preopened version of it, even if a dlopenable
+     module is available.  */
+  if (old_name && tryall_dlopen (handle, old_name,
+                         advise, lt_dlloader_find ("lt_preopen") ) == 0)
+    {
+      return 0;
+    }
+
+  /* Try to open the dynamic library.  */
+  if (dlname)
+    {
+      /* try to open the installed module */
+      if (installed && libdir)
+       {
+         if (tryall_dlopen_module (handle, (const char *) 0,
+                                   libdir, dlname, advise) == 0)
+           return 0;
+       }
+
+      /* try to open the not-installed module */
+      if (!installed)
+       {
+         if (tryall_dlopen_module (handle, dir, objdir,
+                                   dlname, advise) == 0)
+           return 0;
+       }
+
+      /* maybe it was moved to another directory */
+      {
+         if (dir && (tryall_dlopen_module (handle, (const char *) 0,
+                                           dir, dlname, advise) == 0))
+           return 0;
+      }
+    }
+
+  return 1;
+}
+
+
+static int
+canonicalize_path (const char *path, char **pcanonical)
+{
+  char *canonical = 0;
+
+  assert (path && *path);
+  assert (pcanonical);
+
+  canonical = MALLOC (char, 1+ LT_STRLEN (path));
+  if (!canonical)
+    return 1;
+
+  {
+    size_t dest = 0;
+    size_t src;
+    for (src = 0; path[src] != LT_EOS_CHAR; ++src)
+      {
+       /* Path separators are not copied to the beginning or end of
+          the destination, or if another separator would follow
+          immediately.  */
+       if (path[src] == LT_PATHSEP_CHAR)
+         {
+           if ((dest == 0)
+               || (path[1+ src] == LT_PATHSEP_CHAR)
+               || (path[1+ src] == LT_EOS_CHAR))
+             continue;
+         }
+
+       /* Anything other than a directory separator is copied verbatim.  */
+       if ((path[src] != '/')
+#if defined(LT_DIRSEP_CHAR)
+           && (path[src] != LT_DIRSEP_CHAR)
+#endif
+           )
+         {
+           canonical[dest++] = path[src];
+         }
+       /* Directory separators are converted and copied only if they are
+          not at the end of a path -- i.e. before a path separator or
+          NULL terminator.  */
+       else if ((path[1+ src] != LT_PATHSEP_CHAR)
+                && (path[1+ src] != LT_EOS_CHAR)
+#if defined(LT_DIRSEP_CHAR)
+                && (path[1+ src] != LT_DIRSEP_CHAR)
+#endif
+                && (path[1+ src] != '/'))
+         {
+           canonical[dest++] = '/';
+         }
+      }
+
+    /* Add an end-of-string marker at the end.  */
+    canonical[dest] = LT_EOS_CHAR;
+  }
+
+  /* Assign new value.  */
+  *pcanonical = canonical;
+
+  return 0;
+}
+
+static int
+argzize_path (const char *path, char **pargz, size_t *pargz_len)
+{
+  error_t error;
+
+  assert (path);
+  assert (pargz);
+  assert (pargz_len);
+
+  if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
+    {
+      switch (error)
+       {
+       case ENOMEM:
+         LT__SETERROR (NO_MEMORY);
+         break;
+       default:
+         LT__SETERROR (UNKNOWN);
+         break;
+       }
+
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
+   of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
+   non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
+   it is appended to each SEARCH_PATH element before FUNC is called.  */
+static int
+foreach_dirinpath (const char *search_path, const char *base_name,
+                  foreach_callback_func *func, void *data1, void *data2)
+{
+  int   result         = 0;
+  size_t filenamesize  = 0;
+  size_t lenbase       = LT_STRLEN (base_name);
+  size_t argz_len      = 0;
+  char *argz           = 0;
+  char *filename       = 0;
+  char *canonical      = 0;
+
+  if (!search_path || !*search_path)
+    {
+      LT__SETERROR (FILE_NOT_FOUND);
+      goto cleanup;
+    }
+
+  if (canonicalize_path (search_path, &canonical) != 0)
+    goto cleanup;
+
+  if (argzize_path (canonical, &argz, &argz_len) != 0)
+    goto cleanup;
+
+  {
+    char *dir_name = 0;
+    while ((dir_name = argz_next (argz, argz_len, dir_name)))
+      {
+       size_t lendir = LT_STRLEN (dir_name);
+
+       if (1+ lendir + lenbase >= filenamesize)
+       {
+         FREE (filename);
+         filenamesize  = 1+ lendir + 1+ lenbase; /* "/d" + '/' + "f" + '\0' */
+         filename      = MALLOC (char, filenamesize);
+         if (!filename)
+           goto cleanup;
+       }
+
+       assert (filenamesize > lendir);
+       strcpy (filename, dir_name);
+
+       if (base_name && *base_name)
+         {
+           if (filename[lendir -1] != '/')
+             filename[lendir++] = '/';
+           strcpy (filename +lendir, base_name);
+         }
+
+       if ((result = (*func) (filename, data1, data2)))
+         {
+           break;
+         }
+      }
+  }
+
+ cleanup:
+  FREE (argz);
+  FREE (canonical);
+  FREE (filename);
+
+  return result;
+}
+
+/* If FILEPATH can be opened, store the name of the directory component
+   in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
+   DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
+static int
+find_file_callback (char *filename, void *data1, void *data2)
+{
+  char      **pdir     = (char **) data1;
+  FILE      **pfile    = (FILE **) data2;
+  int       is_done    = 0;
+
+  assert (filename && *filename);
+  assert (pdir);
+  assert (pfile);
+
+  if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
+    {
+      char *dirend = strrchr (filename, '/');
+
+      if (dirend > filename)
+       *dirend   = LT_EOS_CHAR;
+
+      FREE (*pdir);
+      *pdir   = lt__strdup (filename);
+      is_done = (*pdir == 0) ? -1 : 1;
+    }
+
+  return is_done;
+}
+
+static FILE *
+find_file (const char *search_path, const char *base_name, char **pdir)
+{
+  FILE *file = 0;
+
+  foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
+
+  return file;
+}
+
+static int
+find_handle_callback (char *filename, void *data, void *data2)
+{
+  lt_dlhandle  *phandle                = (lt_dlhandle *) data;
+  int          notfound        = access (filename, R_OK);
+  lt_dladvise   advise         = (lt_dladvise) data2;
+
+  /* Bail out if file cannot be read...  */
+  if (notfound)
+    return 0;
+
+  /* Try to dlopen the file, but do not continue searching in any
+     case.  */
+  if (tryall_dlopen (phandle, filename, advise, 0) != 0)
+    *phandle = 0;
+
+  return 1;
+}
+
+/* If HANDLE was found return it, otherwise return 0.  If HANDLE was
+   found but could not be opened, *HANDLE will be set to 0.  */
+static lt_dlhandle *
+find_handle (const char *search_path, const char *base_name,
+            lt_dlhandle *phandle, lt_dladvise advise)
+{
+  if (!search_path)
+    return 0;
+
+  if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
+                         phandle, advise))
+    return 0;
+
+  return phandle;
+}
+
+#if !defined(LTDL_DLOPEN_DEPLIBS)
+static int
+load_deplibs (lt_dlhandle handle, char * LT__UNUSED deplibs)
+{
+  handle->depcount = 0;
+  return 0;
+}
+
+#else /* defined(LTDL_DLOPEN_DEPLIBS) */
+static int
+load_deplibs (lt_dlhandle handle, char *deplibs)
+{
+  char *p, *save_search_path = 0;
+  int   depcount = 0;
+  int  i;
+  char **names = 0;
+  int  errors = 0;
+
+  handle->depcount = 0;
+
+  if (!deplibs)
+    {
+      return errors;
+    }
+  ++errors;
+
+  if (user_search_path)
+    {
+      save_search_path = lt__strdup (user_search_path);
+      if (!save_search_path)
+       goto cleanup;
+    }
+
+  /* extract search paths and count deplibs */
+  p = deplibs;
+  while (*p)
+    {
+      if (!isspace ((unsigned char) *p))
+       {
+         char *end = p+1;
+         while (*end && !isspace((unsigned char) *end))
+           {
+             ++end;
+           }
+
+         if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
+           {
+             char save = *end;
+             *end = 0; /* set a temporary string terminator */
+             if (lt_dladdsearchdir(p+2))
+               {
+                 goto cleanup;
+               }
+             *end = save;
+           }
+         else
+           {
+             ++depcount;
+           }
+
+         p = end;
+       }
+      else
+       {
+         ++p;
+       }
+    }
+
+
+  if (!depcount)
+    {
+      errors = 0;
+      goto cleanup;
+    }
+
+  names = MALLOC (char *, depcount);
+  if (!names)
+    goto cleanup;
+
+  /* now only extract the actual deplibs */
+  depcount = 0;
+  p = deplibs;
+  while (*p)
+    {
+      if (isspace ((unsigned char) *p))
+       {
+         ++p;
+       }
+      else
+       {
+         char *end = p+1;
+         while (*end && !isspace ((unsigned char) *end))
+           {
+             ++end;
+           }
+
+         if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
+           {
+             char *name;
+             char save = *end;
+             *end = 0; /* set a temporary string terminator */
+             if (strncmp(p, "-l", 2) == 0)
+               {
+                 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
+                 name = MALLOC (char, 1+ name_len);
+                 if (name)
+                   sprintf (name, "lib%s", p+2);
+               }
+             else
+               name = lt__strdup(p);
+
+             if (!name)
+               goto cleanup_names;
+
+             names[depcount++] = name;
+             *end = save;
+           }
+         p = end;
+       }
+    }
+
+  /* load the deplibs (in reverse order)
+     At this stage, don't worry if the deplibs do not load correctly,
+     they may already be statically linked into the loading application
+     for instance.  There will be a more enlightening error message
+     later on if the loaded module cannot resolve all of its symbols.  */
+  if (depcount)
+    {
+      lt_dlhandle cur = handle;
+      int      j = 0;
+
+      cur->deplibs = MALLOC (lt_dlhandle, depcount);
+      if (!cur->deplibs)
+       goto cleanup_names;
+
+      for (i = 0; i < depcount; ++i)
+       {
+         cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
+         if (cur->deplibs[j])
+           {
+             ++j;
+           }
+       }
+
+      cur->depcount    = j;    /* Number of successfully loaded deplibs */
+      errors           = 0;
+    }
+
+ cleanup_names:
+  for (i = 0; i < depcount; ++i)
+    {
+      FREE (names[i]);
+    }
+
+ cleanup:
+  FREE (names);
+  /* restore the old search path */
+  if (save_search_path) {
+    MEMREASSIGN (user_search_path, save_search_path);
+  }
+
+  return errors;
+}
+#endif /* defined(LTDL_DLOPEN_DEPLIBS) */
+
+static int
+unload_deplibs (lt_dlhandle handle)
+{
+  int i;
+  int errors = 0;
+  lt_dlhandle cur = handle;
+
+  if (cur->depcount)
+    {
+      for (i = 0; i < cur->depcount; ++i)
+       {
+         if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
+           {
+             errors += lt_dlclose (cur->deplibs[i]);
+           }
+       }
+      FREE (cur->deplibs);
+    }
+
+  return errors;
+}
+
+static int
+trim (char **dest, const char *str)
+{
+  /* remove the leading and trailing "'" from str
+     and store the result in dest */
+  const char *end   = strrchr (str, '\'');
+  size_t len       = LT_STRLEN (str);
+  char *tmp;
+
+  FREE (*dest);
+
+  if (!end || end == str)
+    return 1;
+
+  if (len > 3 && str[0] == '\'')
+    {
+      tmp = MALLOC (char, end - str);
+      if (!tmp)
+       return 1;
+
+      memcpy(tmp, &str[1], (end - str) - 1);
+      tmp[(end - str) - 1] = LT_EOS_CHAR;
+      *dest = tmp;
+    }
+  else
+    {
+      *dest = 0;
+    }
+
+  return 0;
+}
+
+/* Read the .la file FILE. */
+static int
+parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
+    char **old_name, int *installed)
+{
+  int          errors = 0;
+  size_t       line_len = LT_FILENAME_MAX;
+  char *       line = MALLOC (char, line_len);
+
+  if (!line)
+    {
+      LT__SETERROR (FILE_NOT_FOUND);
+      return 1;
+    }
+
+  while (!feof (file))
+    {
+      line[line_len-2] = '\0';
+      if (!fgets (line, (int) line_len, file))
+       {
+         break;
+       }
+
+      /* Handle the case where we occasionally need to read a line
+        that is longer than the initial buffer size.
+        Behave even if the file contains NUL bytes due to corruption. */
+      while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
+       {
+         line = REALLOC (char, line, line_len *2);
+         if (!line)
+           {
+             ++errors;
+             goto cleanup;
+           }
+         line[line_len * 2 - 2] = '\0';
+         if (!fgets (&line[line_len -1], (int) line_len +1, file))
+           {
+             break;
+           }
+         line_len *= 2;
+       }
+
+      if (line[0] == '\n' || line[0] == '#')
+       {
+         continue;
+       }
+
+#undef  STR_DLNAME
+#define STR_DLNAME     "dlname="
+      if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
+       {
+         errors += trim (dlname, &line[sizeof (STR_DLNAME) - 1]);
+       }
+
+#undef  STR_OLD_LIBRARY
+#define STR_OLD_LIBRARY        "old_library="
+      else if (strncmp (line, STR_OLD_LIBRARY,
+           sizeof (STR_OLD_LIBRARY) - 1) == 0)
+       {
+         errors += trim (old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
+       }
+
+      /* Windows native tools do not understand the POSIX paths we store
+        in libdir. */
+#undef  STR_LIBDIR
+#define STR_LIBDIR     "libdir="
+      else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
+       {
+         errors += trim (libdir, &line[sizeof(STR_LIBDIR) - 1]);
+#ifdef __WINDOWS__
+         /* Disallow following unix-style paths on MinGW.  */
+         if (*libdir && (**libdir == '/' || **libdir == '\\'))
+           **libdir = '\0';
+#endif
+       }
+
+#undef  STR_DL_DEPLIBS
+#define STR_DL_DEPLIBS "dependency_libs="
+      else if (strncmp (line, STR_DL_DEPLIBS,
+           sizeof (STR_DL_DEPLIBS) - 1) == 0)
+       {
+         errors += trim (deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
+       }
+      else if (streq (line, "installed=yes\n"))
+       {
+         *installed = 1;
+       }
+      else if (streq (line, "installed=no\n"))
+       {
+         *installed = 0;
+       }
+
+#undef  STR_LIBRARY_NAMES
+#define STR_LIBRARY_NAMES "library_names="
+      else if (!*dlname && strncmp (line, STR_LIBRARY_NAMES,
+           sizeof (STR_LIBRARY_NAMES) - 1) == 0)
+       {
+         char *last_libname;
+         errors += trim (dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
+         if (!errors
+             && *dlname
+             && (last_libname = strrchr (*dlname, ' ')) != 0)
+           {
+             last_libname = lt__strdup (last_libname + 1);
+             if (!last_libname)
+               {
+                 ++errors;
+                 goto cleanup;
+               }
+             MEMREASSIGN (*dlname, last_libname);
+           }
+       }
+
+      if (errors)
+       break;
+    }
+cleanup:
+  FREE (line);
+  return errors;
+}
+
+
+/* Try to open FILENAME as a module. */
+static int
+try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
+           lt_dladvise advise)
+{
+  const char * saved_error     = 0;
+  char *       archive_name    = 0;
+  char *       canonical       = 0;
+  char *       base_name       = 0;
+  char *       dir             = 0;
+  char *       name            = 0;
+  char *        attempt                = 0;
+  int          errors          = 0;
+  lt_dlhandle  newhandle;
+
+  assert (phandle);
+  assert (*phandle == 0);
+
+#ifdef LT_DEBUG_LOADERS
+  fprintf (stderr, "try_dlopen (%s, %s)\n",
+          filename ? filename : "(null)",
+          ext ? ext : "(null)");
+#endif
+
+  LT__GETERROR (saved_error);
+
+  /* dlopen self? */
+  if (!filename)
+    {
+      *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
+      if (*phandle == 0)
+       return 1;
+
+      newhandle        = *phandle;
+
+      /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
+      newhandle->info.is_resident = 1;
+
+      if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
+       {
+         FREE (*phandle);
+         return 1;
+       }
+
+      goto register_handle;
+    }
+
+  assert (filename && *filename);
+
+  if (ext)
+    {
+      attempt = MALLOC (char, LT_STRLEN (filename) + LT_STRLEN (ext) + 1);
+      if (!attempt)
+       return 1;
+
+      sprintf(attempt, "%s%s", filename, ext);
+    }
+  else
+    {
+      attempt = lt__strdup (filename);
+      if (!attempt)
+       return 1;
+    }
+
+  /* Doing this immediately allows internal functions to safely
+     assume only canonicalized paths are passed.  */
+  if (canonicalize_path (attempt, &canonical) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  /* If the canonical module name is a path (relative or absolute)
+     then split it into a directory part and a name part.  */
+  base_name = strrchr (canonical, '/');
+  if (base_name)
+    {
+      size_t dirlen = (1+ base_name) - canonical;
+
+      dir = MALLOC (char, 1+ dirlen);
+      if (!dir)
+       {
+         ++errors;
+         goto cleanup;
+       }
+
+      strncpy (dir, canonical, dirlen);
+      dir[dirlen] = LT_EOS_CHAR;
+
+      ++base_name;
+    }
+  else
+    MEMREASSIGN (base_name, canonical);
+
+  assert (base_name && *base_name);
+
+  ext = strrchr (base_name, '.');
+  if (!ext)
+    {
+      ext = base_name + LT_STRLEN (base_name);
+    }
+
+  /* extract the module name from the file name */
+  name = MALLOC (char, ext - base_name + 1);
+  if (!name)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  /* canonicalize the module name */
+  {
+    int i;
+    for (i = 0; i < ext - base_name; ++i)
+      {
+       if (isalnum ((unsigned char)(base_name[i])))
+         {
+           name[i] = base_name[i];
+         }
+       else
+         {
+           name[i] = '_';
+         }
+      }
+    name[ext - base_name] = LT_EOS_CHAR;
+  }
+
+  /* Before trawling through the filesystem in search of a module,
+     check whether we are opening a preloaded module.  */
+  if (!dir)
+    {
+      const lt_dlvtable *vtable        = lt_dlloader_find ("lt_preopen");
+
+      if (vtable)
+       {
+         /* libprefix + name + "." + libext + NULL */
+         archive_name = MALLOC (char, strlen (libprefix) + LT_STRLEN (name) + strlen (libext) + 2);
+         *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
+
+         if ((*phandle == NULL) || (archive_name == NULL))
+           {
+             ++errors;
+             goto cleanup;
+           }
+         newhandle = *phandle;
+
+         /* Preloaded modules are always named according to their old
+            archive name.  */
+         if (strncmp(name, "lib", 3) == 0)
+           {
+             sprintf (archive_name, "%s%s.%s", libprefix, name + 3, libext);
+           }
+         else
+           {
+             sprintf (archive_name, "%s.%s", name, libext);
+           }
+
+         if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
+           {
+             goto register_handle;
+           }
+
+         /* If we're still here, there was no matching preloaded module,
+            so put things back as we found them, and continue searching.  */
+         FREE (*phandle);
+         newhandle = NULL;
+       }
+    }
+
+  /* If we are allowing only preloaded modules, and we didn't find
+     anything yet, give up on the search here.  */
+  if (advise && advise->try_preload_only)
+    {
+      goto cleanup;
+    }
+
+  /* Check whether we are opening a libtool module (.la extension).  */
+  if (ext && streq (ext, archive_ext))
+    {
+      /* this seems to be a libtool module */
+      FILE *   file     = 0;
+      char *   dlname   = 0;
+      char *   old_name = 0;
+      char *   libdir   = 0;
+      char *   deplibs  = 0;
+
+      /* if we can't find the installed flag, it is probably an
+        installed libtool archive, produced with an old version
+        of libtool */
+      int      installed = 1;
+
+      /* Now try to open the .la file.  If there is no directory name
+        component, try to find it first in user_search_path and then other
+        prescribed paths.  Otherwise (or in any case if the module was not
+        yet found) try opening just the module name as passed.  */
+      if (!dir)
+       {
+         const char *search_path = user_search_path;
+
+         if (search_path)
+           file = find_file (user_search_path, base_name, &dir);
+
+         if (!file)
+           {
+             search_path = getenv (LTDL_SEARCHPATH_VAR);
+             if (search_path)
+               file = find_file (search_path, base_name, &dir);
+           }
+
+#if defined(LT_MODULE_PATH_VAR)
+         if (!file)
+           {
+             search_path = getenv (LT_MODULE_PATH_VAR);
+             if (search_path)
+               file = find_file (search_path, base_name, &dir);
+           }
+#endif
+#if defined(LT_DLSEARCH_PATH)
+         if (!file && *sys_dlsearch_path)
+           {
+             file = find_file (sys_dlsearch_path, base_name, &dir);
+           }
+#endif
+       }
+      else
+       {
+         file = fopen (attempt, LT_READTEXT_MODE);
+       }
+
+      /* If we didn't find the file by now, it really isn't there.  Set
+        the status flag, and bail out.  */
+      if (!file)
+       {
+         LT__SETERROR (FILE_NOT_FOUND);
+         ++errors;
+         goto cleanup;
+       }
+
+      /* read the .la file */
+      if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
+           &old_name, &installed) != 0)
+       ++errors;
+
+      fclose (file);
+
+      /* allocate the handle */
+      *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
+      if (*phandle == 0)
+       ++errors;
+
+      if (errors)
+       {
+         FREE (dlname);
+         FREE (old_name);
+         FREE (libdir);
+         FREE (deplibs);
+         FREE (*phandle);
+         goto cleanup;
+       }
+
+      assert (*phandle);
+
+      if (load_deplibs (*phandle, deplibs) == 0)
+       {
+         newhandle = *phandle;
+         /* find_module may replace newhandle */
+         if (find_module (&newhandle, dir, libdir, dlname, old_name,
+                          installed, advise))
+           {
+             unload_deplibs (*phandle);
+             ++errors;
+           }
+       }
+      else
+       {
+         ++errors;
+       }
+
+      FREE (dlname);
+      FREE (old_name);
+      FREE (libdir);
+      FREE (deplibs);
+
+      if (errors)
+       {
+         FREE (*phandle);
+         goto cleanup;
+       }
+
+      if (*phandle != newhandle)
+       {
+         unload_deplibs (*phandle);
+       }
+    }
+  else
+    {
+      /* not a libtool module */
+      *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
+      if (*phandle == 0)
+       {
+         ++errors;
+         goto cleanup;
+       }
+
+      newhandle = *phandle;
+
+      /* If the module has no directory name component, try to find it
+        first in user_search_path and then other prescribed paths.
+        Otherwise (or in any case if the module was not yet found) try
+        opening just the module name as passed.  */
+      if ((dir || (!find_handle (user_search_path, base_name,
+                                &newhandle, advise)
+                  && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
+                                   &newhandle, advise)
+#if defined(LT_MODULE_PATH_VAR)
+                  && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
+                                   &newhandle, advise)
+#endif
+#if defined(LT_DLSEARCH_PATH)
+                  && !find_handle (sys_dlsearch_path, base_name,
+                                   &newhandle, advise)
+#endif
+                  )))
+       {
+         if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
+           {
+             newhandle = NULL;
+           }
+       }
+
+      if (!newhandle)
+       {
+         FREE (*phandle);
+         ++errors;
+         goto cleanup;
+       }
+    }
+
+ register_handle:
+  MEMREASSIGN (*phandle, newhandle);
+
+  if ((*phandle)->info.ref_count == 0)
+    {
+      (*phandle)->info.ref_count       = 1;
+      MEMREASSIGN ((*phandle)->info.name, name);
+
+      (*phandle)->next = handles;
+      handles          = *phandle;
+    }
+
+  LT__SETERRORSTR (saved_error);
+
+ cleanup:
+  FREE (dir);
+  FREE (attempt);
+  FREE (name);
+  if (!canonical)              /* was MEMREASSIGNed */
+    FREE (base_name);
+  FREE (canonical);
+  FREE (archive_name);
+
+  return errors;
+}
+
+
+/* If the last error message stored was `FILE_NOT_FOUND', then return
+   non-zero.  */
+static int
+file_not_found (void)
+{
+  const char *error = 0;
+
+  LT__GETERROR (error);
+  if (error == LT__STRERROR (FILE_NOT_FOUND))
+    return 1;
+
+  return 0;
+}
+
+
+/* Unless FILENAME already bears a suitable library extension, then
+   return 0.  */
+static int
+has_library_ext (const char *filename)
+{
+  const char * ext     = 0;
+
+  assert (filename);
+
+  ext = strrchr (filename, '.');
+
+  if (ext && ((streq (ext, archive_ext))
+#if defined(LT_MODULE_EXT)
+            || (streq (ext, shlib_ext))
+#endif
+#if defined(LT_SHARED_EXT)
+            || (streq (ext, shared_ext))
+#endif
+    ))
+    {
+      return 1;
+    }
+
+  return 0;
+}
+
+
+/* Initialise and configure a user lt_dladvise opaque object.  */
+
+int
+lt_dladvise_init (lt_dladvise *padvise)
+{
+  lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
+  *padvise = advise;
+  return (advise ? 0 : 1);
+}
+
+int
+lt_dladvise_destroy (lt_dladvise *padvise)
+{
+  if (padvise)
+    FREE(*padvise);
+  return 0;
+}
+
+int
+lt_dladvise_ext (lt_dladvise *padvise)
+{
+  assert (padvise && *padvise);
+  (*padvise)->try_ext = 1;
+  return 0;
+}
+
+int
+lt_dladvise_resident (lt_dladvise *padvise)
+{
+  assert (padvise && *padvise);
+  (*padvise)->is_resident = 1;
+  return 0;
+}
+
+int
+lt_dladvise_local (lt_dladvise *padvise)
+{
+  assert (padvise && *padvise);
+  (*padvise)->is_symlocal = 1;
+  return 0;
+}
+
+int
+lt_dladvise_global (lt_dladvise *padvise)
+{
+  assert (padvise && *padvise);
+  (*padvise)->is_symglobal = 1;
+  return 0;
+}
+
+int
+lt_dladvise_preload (lt_dladvise *padvise)
+{
+  assert (padvise && *padvise);
+  (*padvise)->try_preload_only = 1;
+  return 0;
+}
+
+/* Libtool-1.5.x interface for loading a new module named FILENAME.  */
+lt_dlhandle
+lt_dlopen (const char *filename)
+{
+  return lt_dlopenadvise (filename, NULL);
+}
+
+
+/* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to
+   open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
+   and if a file is still not found try again with MODULE_EXT appended
+   instead.  */
+lt_dlhandle
+lt_dlopenext (const char *filename)
+{
+  lt_dlhandle  handle  = 0;
+  lt_dladvise  advise;
+
+  if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
+    handle = lt_dlopenadvise (filename, advise);
+
+  lt_dladvise_destroy (&advise);
+  return handle;
+}
+
+
+lt_dlhandle
+lt_dlopenadvise (const char *filename, lt_dladvise advise)
+{
+  lt_dlhandle  handle  = 0;
+  int          errors  = 0;
+  const char * saved_error     = 0;
+
+  LT__GETERROR (saved_error);
+
+  /* Can't have symbols hidden and visible at the same time!  */
+  if (advise && advise->is_symlocal && advise->is_symglobal)
+    {
+      LT__SETERROR (CONFLICTING_FLAGS);
+      return 0;
+    }
+
+  if (!filename
+      || !advise
+      || !advise->try_ext
+      || has_library_ext (filename))
+    {
+      /* Just incase we missed a code path in try_dlopen() that reports
+        an error, but forgot to reset handle... */
+      if (try_dlopen (&handle, filename, NULL, advise) != 0)
+       return 0;
+
+      return handle;
+    }
+  else if (filename && *filename)
+    {
+
+      /* First try appending ARCHIVE_EXT.  */
+      errors += try_dlopen (&handle, filename, archive_ext, advise);
+
+      /* If we found FILENAME, stop searching -- whether we were able to
+        load the file as a module or not.  If the file exists but loading
+        failed, it is better to return an error message here than to
+        report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
+        in the module search path.  */
+      if (handle || ((errors > 0) && !file_not_found ()))
+       return handle;
+
+#if defined(LT_MODULE_EXT)
+      /* Try appending SHLIB_EXT.   */
+      LT__SETERRORSTR (saved_error);
+      errors = try_dlopen (&handle, filename, shlib_ext, advise);
+
+      /* As before, if the file was found but loading failed, return now
+        with the current error message.  */
+      if (handle || ((errors > 0) && !file_not_found ()))
+       return handle;
+#endif
+
+#if defined(LT_SHARED_EXT)
+      /* Try appending SHARED_EXT.   */
+      LT__SETERRORSTR (saved_error);
+      errors = try_dlopen (&handle, filename, shared_ext, advise);
+
+      /* As before, if the file was found but loading failed, return now
+        with the current error message.  */
+      if (handle || ((errors > 0) && !file_not_found ()))
+       return handle;
+#endif
+    }
+
+  /* Still here?  Then we really did fail to locate any of the file
+     names we tried.  */
+  LT__SETERROR (FILE_NOT_FOUND);
+  return 0;
+}
+
+
+static int
+lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
+               const char *entry)
+{
+  error_t error;
+
+  /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
+     pargz_len, NULL, entry) failed with EINVAL.  */
+  if (before)
+    error = argz_insert (pargz, pargz_len, before, entry);
+  else
+    error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
+
+  if (error)
+    {
+      switch (error)
+       {
+       case ENOMEM:
+         LT__SETERROR (NO_MEMORY);
+         break;
+       default:
+         LT__SETERROR (UNKNOWN);
+         break;
+       }
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
+{
+  char *before = 0;
+
+  assert (pargz);
+  assert (pargz_len);
+  assert (entry && *entry);
+
+  if (*pargz)
+    while ((before = argz_next (*pargz, *pargz_len, before)))
+      {
+       int cmp = strcmp (entry, before);
+
+       if (cmp < 0)  break;
+       if (cmp == 0) return 0; /* No duplicates! */
+      }
+
+  return lt_argz_insert (pargz, pargz_len, before, entry);
+}
+
+static int
+lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
+                  struct dirent *dp)
+{
+  char   *buf      = 0;
+  size_t buf_len    = 0;
+  char   *end      = 0;
+  size_t end_offset = 0;
+  size_t dir_len    = 0;
+  int    errors            = 0;
+
+  assert (pargz);
+  assert (pargz_len);
+  assert (dp);
+
+  dir_len = LT_STRLEN (dirnam);
+  end     = dp->d_name + D_NAMLEN(dp);
+
+  /* Ignore version numbers.  */
+  {
+    char *p;
+    for (p = end; p -1 > dp->d_name; --p)
+      if (strchr (".0123456789", p[-1]) == 0)
+       break;
+
+    if (*p == '.')
+      end = p;
+  }
+
+  /* Ignore filename extension.  */
+  {
+    char *p;
+    for (p = end -1; p > dp->d_name; --p)
+      if (*p == '.')
+       {
+         end = p;
+         break;
+       }
+  }
+
+  /* Prepend the directory name.  */
+  end_offset   = end - dp->d_name;
+  buf_len      = dir_len + 1+ end_offset;
+  buf          = MALLOC (char, 1+ buf_len);
+  if (!buf)
+    return ++errors;
+
+  assert (buf);
+
+  strcpy  (buf, dirnam);
+  strcat  (buf, "/");
+  strncat (buf, dp->d_name, end_offset);
+  buf[buf_len] = LT_EOS_CHAR;
+
+  /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
+  if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
+    ++errors;
+
+  FREE (buf);
+
+  return errors;
+}
+
+static int
+list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
+{
+  DIR  *dirp     = 0;
+  int    errors          = 0;
+
+  assert (dirnam && *dirnam);
+  assert (pargz);
+  assert (pargz_len);
+  assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
+
+  dirp = opendir (dirnam);
+  if (dirp)
+    {
+      struct dirent *dp        = 0;
+
+      while ((dp = readdir (dirp)))
+       if (dp->d_name[0] != '.')
+         if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
+           {
+             ++errors;
+             break;
+           }
+
+      closedir (dirp);
+    }
+  else
+    ++errors;
+
+  return errors;
+}
+
+
+/* If there are any files in DIRNAME, call the function passed in
+   DATA1 (with the name of each file and DATA2 as arguments).  */
+static int
+foreachfile_callback (char *dirname, void *data1, void *data2)
+{
+  file_worker_func *func = *(file_worker_func **) data1;
+
+  int    is_done  = 0;
+  char   *argz     = 0;
+  size_t  argz_len = 0;
+
+  if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
+    goto cleanup;
+  if (!argz)
+    goto cleanup;
+
+  {
+    char *filename = 0;
+    while ((filename = argz_next (argz, argz_len, filename)))
+      if ((is_done = (*func) (filename, data2)))
+       break;
+  }
+
+ cleanup:
+  FREE (argz);
+
+  return is_done;
+}
+
+
+/* Call FUNC for each unique extensionless file in SEARCH_PATH, along
+   with DATA.  The filenames passed to FUNC would be suitable for
+   passing to lt_dlopenext.  The extensions are stripped so that
+   individual modules do not generate several entries (e.g. libfoo.la,
+   libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
+   then the same directories that lt_dlopen would search are examined.  */
+int
+lt_dlforeachfile (const char *search_path,
+                 int (*func) (const char *filename, void *data),
+                 void *data)
+{
+  int is_done = 0;
+  file_worker_func **fpptr = &func;
+
+  if (search_path)
+    {
+      /* If a specific path was passed, search only the directories
+        listed in it.  */
+      is_done = foreach_dirinpath (search_path, 0,
+                                  foreachfile_callback, fpptr, data);
+    }
+  else
+    {
+      /* Otherwise search the default paths.  */
+      is_done = foreach_dirinpath (user_search_path, 0,
+                                  foreachfile_callback, fpptr, data);
+      if (!is_done)
+       {
+         is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
+                                      foreachfile_callback, fpptr, data);
+       }
+
+#if defined(LT_MODULE_PATH_VAR)
+      if (!is_done)
+       {
+         is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
+                                      foreachfile_callback, fpptr, data);
+       }
+#endif
+#if defined(LT_DLSEARCH_PATH)
+      if (!is_done && *sys_dlsearch_path)
+       {
+         is_done = foreach_dirinpath (sys_dlsearch_path, 0,
+                                      foreachfile_callback, fpptr, data);
+       }
+#endif
+    }
+
+  return is_done;
+}
+
+int
+lt_dlclose (lt_dlhandle handle)
+{
+  lt_dlhandle cur, last;
+  int errors = 0;
+
+  /* check whether the handle is valid */
+  last = cur = handles;
+  while (cur && handle != cur)
+    {
+      last = cur;
+      cur = cur->next;
+    }
+
+  if (!cur)
+    {
+      LT__SETERROR (INVALID_HANDLE);
+      ++errors;
+      goto done;
+    }
+
+  cur = handle;
+  cur->info.ref_count--;
+
+  /* Note that even with resident modules, we must track the ref_count
+     correctly incase the user decides to reset the residency flag
+     later (even though the API makes no provision for that at the
+     moment).  */
+  if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
+    {
+      lt_user_data data = cur->vtable->dlloader_data;
+
+      if (cur != handles)
+       {
+         last->next = cur->next;
+       }
+      else
+       {
+         handles = cur->next;
+       }
+
+      errors += cur->vtable->module_close (data, cur->module);
+      errors += unload_deplibs (handle);
+
+      /* It is up to the callers to free the data itself.  */
+      FREE (cur->interface_data);
+
+      FREE (cur->info.filename);
+      FREE (cur->info.name);
+      FREE (cur);
+
+      goto done;
+    }
+
+  if (LT_DLIS_RESIDENT (handle))
+    {
+      LT__SETERROR (CLOSE_RESIDENT_MODULE);
+      ++errors;
+    }
+
+ done:
+  return errors;
+}
+
+void *
+lt_dlsym (lt_dlhandle place, const char *symbol)
+{
+  size_t lensym;
+  char lsym[LT_SYMBOL_LENGTH];
+  char *sym;
+  void *address;
+  lt_user_data data;
+  lt_dlhandle handle;
+
+  if (!place)
+    {
+      LT__SETERROR (INVALID_HANDLE);
+      return 0;
+    }
+
+  handle = place;
+
+  if (!symbol)
+    {
+      LT__SETERROR (SYMBOL_NOT_FOUND);
+      return 0;
+    }
+
+  lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
+                                       + LT_STRLEN (handle->info.name);
+
+  if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
+    {
+      sym = lsym;
+    }
+  else
+    {
+      sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
+      if (!sym)
+       {
+         LT__SETERROR (BUFFER_OVERFLOW);
+         return 0;
+       }
+    }
+
+  data = handle->vtable->dlloader_data;
+  if (handle->info.name)
+    {
+      const char *saved_error;
+
+      LT__GETERROR (saved_error);
+
+      /* this is a libtool module */
+      if (handle->vtable->sym_prefix)
+       {
+         strcpy(sym, handle->vtable->sym_prefix);
+         strcat(sym, handle->info.name);
+       }
+      else
+       {
+         strcpy(sym, handle->info.name);
+       }
+
+      strcat(sym, "_LTX_");
+      strcat(sym, symbol);
+
+      /* try "modulename_LTX_symbol" */
+      address = handle->vtable->find_sym (data, handle->module, sym);
+      if (address)
+       {
+         if (sym != lsym)
+           {
+             FREE (sym);
+           }
+         return address;
+       }
+      LT__SETERRORSTR (saved_error);
+    }
+
+  /* otherwise try "symbol" */
+  if (handle->vtable->sym_prefix)
+    {
+      strcpy(sym, handle->vtable->sym_prefix);
+      strcat(sym, symbol);
+    }
+  else
+    {
+      strcpy(sym, symbol);
+    }
+
+  address = handle->vtable->find_sym (data, handle->module, sym);
+  if (sym != lsym)
+    {
+      FREE (sym);
+    }
+
+  return address;
+}
+
+const char *
+lt_dlerror (void)
+{
+  const char *error;
+
+  LT__GETERROR (error);
+  LT__SETERRORSTR (0);
+
+  return error;
+}
+
+static int
+lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
+{
+  int    errors                = 0;
+  char  *canonical     = 0;
+  char  *argz          = 0;
+  size_t argz_len      = 0;
+
+  assert (ppath);
+  assert (dir && *dir);
+
+  if (canonicalize_path (dir, &canonical) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  assert (canonical && *canonical);
+
+  /* If *PPATH is empty, set it to DIR.  */
+  if (*ppath == 0)
+    {
+      assert (!before);                /* BEFORE cannot be set without PPATH.  */
+      assert (dir);            /* Without DIR, don't call this function!  */
+
+      *ppath = lt__strdup (dir);
+      if (*ppath == 0)
+       ++errors;
+
+      goto cleanup;
+    }
+
+  assert (ppath && *ppath);
+
+  if (argzize_path (*ppath, &argz, &argz_len) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
+     if *PPATH is already canonicalized, and hence does not change length
+     with respect to ARGZ.  We canonicalize each entry as it is added to
+     the search path, and don't call this function with (uncanonicalized)
+     user paths, so this is a fair assumption.  */
+  if (before)
+    {
+      assert (*ppath <= before);
+      assert ((int) (before - *ppath) <= (int) strlen (*ppath));
+
+      before = before - *ppath + argz;
+    }
+
+  if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
+    {
+      ++errors;
+      goto cleanup;
+    }
+
+  argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
+  MEMREASSIGN(*ppath, argz);
+
+ cleanup:
+  FREE (argz);
+  FREE (canonical);
+
+  return errors;
+}
+
+int
+lt_dladdsearchdir (const char *search_dir)
+{
+  int errors = 0;
+
+  if (search_dir && *search_dir)
+    {
+      if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
+       ++errors;
+    }
+
+  return errors;
+}
+
+int
+lt_dlinsertsearchdir (const char *before, const char *search_dir)
+{
+  int errors = 0;
+
+  if (before)
+    {
+      if ((before < user_search_path)
+         || (before >= user_search_path + LT_STRLEN (user_search_path)))
+       {
+         LT__SETERROR (INVALID_POSITION);
+         return 1;
+       }
+    }
+
+  if (search_dir && *search_dir)
+    {
+      if (lt_dlpath_insertdir (&user_search_path,
+                              (char *) before, search_dir) != 0)
+       {
+         ++errors;
+       }
+    }
+
+  return errors;
+}
+
+int
+lt_dlsetsearchpath (const char *search_path)
+{
+  int   errors     = 0;
+
+  FREE (user_search_path);
+
+  if (!search_path || !LT_STRLEN (search_path))
+    {
+      return errors;
+    }
+
+  if (canonicalize_path (search_path, &user_search_path) != 0)
+    ++errors;
+
+  return errors;
+}
+
+const char *
+lt_dlgetsearchpath (void)
+{
+  const char *saved_path;
+
+  saved_path = user_search_path;
+
+  return saved_path;
+}
+
+int
+lt_dlmakeresident (lt_dlhandle handle)
+{
+  int errors = 0;
+
+  if (!handle)
+    {
+      LT__SETERROR (INVALID_HANDLE);
+      ++errors;
+    }
+  else
+    {
+      handle->info.is_resident = 1;
+    }
+
+  return errors;
+}
+
+int
+lt_dlisresident        (lt_dlhandle handle)
+{
+  if (!handle)
+    {
+      LT__SETERROR (INVALID_HANDLE);
+      return -1;
+    }
+
+  return LT_DLIS_RESIDENT (handle);
+}
+
+
+
+/* --- MODULE INFORMATION --- */
+
+typedef struct {
+  const char *id_string;
+  lt_dlhandle_interface *iface;
+} lt__interface_id;
+
+lt_dlinterface_id
+lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
+{
+  lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
+
+  /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
+     can then be detected with lt_dlerror() if we return 0.  */
+  if (interface_id)
+    {
+      interface_id->id_string = lt__strdup (id_string);
+      if (!interface_id->id_string)
+       FREE (interface_id);
+      else
+       interface_id->iface = iface;
+    }
+
+  return (lt_dlinterface_id) interface_id;
+}
+
+void lt_dlinterface_free (lt_dlinterface_id key)
+{
+  lt__interface_id *interface_id = (lt__interface_id *)key;
+  FREE (interface_id->id_string);
+  FREE (interface_id);
+}
+
+void *
+lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
+{
+  int n_elements = 0;
+  void *stale = (void *) 0;
+  lt_dlhandle cur = handle;
+  int i;
+
+  if (cur->interface_data)
+    while (cur->interface_data[n_elements].key)
+      ++n_elements;
+
+  for (i = 0; i < n_elements; ++i)
+    {
+      if (cur->interface_data[i].key == key)
+       {
+         stale = cur->interface_data[i].data;
+         break;
+       }
+    }
+
+  /* Ensure that there is enough room in this handle's interface_data
+     array to accept a new element (and an empty end marker).  */
+  if (i == n_elements)
+    {
+      lt_interface_data *temp
+       = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
+
+      if (!temp)
+       {
+         stale = 0;
+         goto done;
+       }
+
+      cur->interface_data = temp;
+
+      /* We only need this if we needed to allocate a new interface_data.  */
+      cur->interface_data[i].key       = key;
+      cur->interface_data[1+ i].key    = 0;
+    }
+
+  cur->interface_data[i].data = data;
+
+ done:
+  return stale;
+}
+
+void *
+lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
+{
+  void *result = (void *) 0;
+  lt_dlhandle cur = handle;
+
+  /* Locate the index of the element with a matching KEY.  */
+  if (cur->interface_data)
+    {
+      int i;
+      for (i = 0; cur->interface_data[i].key; ++i)
+       {
+         if (cur->interface_data[i].key == key)
+           {
+             result = cur->interface_data[i].data;
+             break;
+           }
+       }
+    }
+
+  return result;
+}
+
+const lt_dlinfo *
+lt_dlgetinfo (lt_dlhandle handle)
+{
+  if (!handle)
+    {
+      LT__SETERROR (INVALID_HANDLE);
+      return 0;
+    }
+
+  return &(handle->info);
+}
+
+
+lt_dlhandle
+lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
+{
+  lt_dlhandle handle = place;
+  lt__interface_id *iterator = (lt__interface_id *) iface;
+
+  assert (iface); /* iface is a required argument */
+
+  if (!handle)
+    handle = handles;
+  else
+    handle = handle->next;
+
+  /* advance while the interface check fails */
+  while (handle && iterator->iface
+        && ((*iterator->iface) (handle, iterator->id_string) != 0))
+    {
+      handle = handle->next;
+    }
+
+  return handle;
+}
+
+
+lt_dlhandle
+lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
+{
+  lt_dlhandle handle = 0;
+
+  assert (iface); /* iface is a required argument */
+
+  while ((handle = lt_dlhandle_iterate (iface, handle)))
+    {
+      lt_dlhandle cur = handle;
+      if (cur && cur->info.name && streq (cur->info.name, module_name))
+       break;
+    }
+
+  return handle;
+}
+
+
+int
+lt_dlhandle_map (lt_dlinterface_id iface,
+                int (*func) (lt_dlhandle handle, void *data), void *data)
+{
+  lt__interface_id *iterator = (lt__interface_id *) iface;
+  lt_dlhandle cur = handles;
+
+  assert (iface); /* iface is a required argument */
+
+  while (cur)
+    {
+      int errorcode = 0;
+
+      /* advance while the interface check fails */
+      while (cur && iterator->iface
+            && ((*iterator->iface) (cur, iterator->id_string) != 0))
+       {
+         cur = cur->next;
+       }
+
+      if ((errorcode = (*func) (cur, data)) != 0)
+       return errorcode;
+    }
+
+  return 0;
+}
diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h
new file mode 100644 (file)
index 0000000..749a54d
--- /dev/null
@@ -0,0 +1,163 @@
+/* ltdl.h -- generic dlopen functions
+
+   Copyright (C) 1998-2000, 2004, 2005,
+                 2007, 2008 Free Software Foundation, Inc.
+   Written by Thomas Tanner, 1998
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* Only include this header file once. */
+#if !defined(LTDL_H)
+#define LTDL_H 1
+
+#include <libltdl/lt_system.h>
+#include <libltdl/lt_error.h>
+#include <libltdl/lt_dlloader.h>
+
+LT_BEGIN_C_DECLS
+
+
+/* LT_STRLEN can be used safely on NULL pointers.  */
+#define LT_STRLEN(s)   (((s) && (s)[0]) ? strlen (s) : 0)
+
+\f
+/* --- DYNAMIC MODULE LOADING API --- */
+
+
+typedef        struct lt__handle *lt_dlhandle; /* A loaded module.  */
+
+/* Initialisation and finalisation functions for libltdl. */
+LT_SCOPE int       lt_dlinit           (void);
+LT_SCOPE int       lt_dlexit           (void);
+
+/* Module search path manipulation.  */
+LT_SCOPE int       lt_dladdsearchdir    (const char *search_dir);
+LT_SCOPE int       lt_dlinsertsearchdir (const char *before,
+                                                 const char *search_dir);
+LT_SCOPE int       lt_dlsetsearchpath   (const char *search_path);
+LT_SCOPE const char *lt_dlgetsearchpath         (void);
+LT_SCOPE int       lt_dlforeachfile     (
+                       const char *search_path,
+                       int (*func) (const char *filename, void *data),
+                       void *data);
+
+/* User module loading advisors.  */
+LT_SCOPE int       lt_dladvise_init     (lt_dladvise *advise);
+LT_SCOPE int       lt_dladvise_destroy  (lt_dladvise *advise);
+LT_SCOPE int       lt_dladvise_ext      (lt_dladvise *advise);
+LT_SCOPE int       lt_dladvise_resident (lt_dladvise *advise);
+LT_SCOPE int       lt_dladvise_local    (lt_dladvise *advise);
+LT_SCOPE int       lt_dladvise_global   (lt_dladvise *advise);
+LT_SCOPE int       lt_dladvise_preload  (lt_dladvise *advise);
+
+/* Portable libltdl versions of the system dlopen() API. */
+LT_SCOPE lt_dlhandle lt_dlopen         (const char *filename);
+LT_SCOPE lt_dlhandle lt_dlopenext      (const char *filename);
+LT_SCOPE lt_dlhandle lt_dlopenadvise   (const char *filename,
+                                        lt_dladvise advise);
+LT_SCOPE void *            lt_dlsym            (lt_dlhandle handle, const char *name);
+LT_SCOPE const char *lt_dlerror                (void);
+LT_SCOPE int       lt_dlclose          (lt_dlhandle handle);
+
+
+
+/* --- PRELOADED MODULE SUPPORT --- */
+
+
+/* A preopened symbol. Arrays of this type comprise the exported
+   symbols for a dlpreopened module. */
+typedef struct {
+  const char *name;
+  void       *address;
+} lt_dlsymlist;
+
+typedef int lt_dlpreload_callback_func (lt_dlhandle handle);
+
+LT_SCOPE int   lt_dlpreload         (const lt_dlsymlist *preloaded);
+LT_SCOPE int   lt_dlpreload_default (const lt_dlsymlist *preloaded);
+LT_SCOPE int   lt_dlpreload_open    (const char *originator,
+                                     lt_dlpreload_callback_func *func);
+
+#define lt_preloaded_symbols   lt__PROGRAM__LTX_preloaded_symbols
+/* Ensure C linkage.  */
+extern LT_DLSYM_CONST lt_dlsymlist lt__PROGRAM__LTX_preloaded_symbols[];
+
+#define LTDL_SET_PRELOADED_SYMBOLS() \
+       lt_dlpreload_default(lt_preloaded_symbols)
+
+
+
+\f
+/* --- MODULE INFORMATION --- */
+
+
+/* Associating user data with loaded modules. */
+typedef void * lt_dlinterface_id;
+typedef int lt_dlhandle_interface (lt_dlhandle handle, const char *id_string);
+
+LT_SCOPE lt_dlinterface_id lt_dlinterface_register (const char *id_string,
+                                         lt_dlhandle_interface *iface);
+LT_SCOPE void  lt_dlinterface_free (lt_dlinterface_id key);
+LT_SCOPE void *        lt_dlcaller_set_data  (lt_dlinterface_id key,
+                                         lt_dlhandle handle, void *data);
+LT_SCOPE void *        lt_dlcaller_get_data  (lt_dlinterface_id key,
+                                         lt_dlhandle handle);
+
+
+/* Read only information pertaining to a loaded module. */
+typedef        struct {
+  char *       filename;       /* file name */
+  char *       name;           /* module name */
+  int          ref_count;      /* number of times lt_dlopened minus
+                                  number of times lt_dlclosed. */
+  unsigned int is_resident:1;  /* module can't be unloaded. */
+  unsigned int is_symglobal:1; /* module symbols can satisfy
+                                  subsequently loaded modules.  */
+  unsigned int is_symlocal:1;  /* module symbols are only available
+                                  locally. */
+} lt_dlinfo;
+
+LT_SCOPE const lt_dlinfo *lt_dlgetinfo     (lt_dlhandle handle);
+
+LT_SCOPE lt_dlhandle   lt_dlhandle_iterate (lt_dlinterface_id iface,
+                                            lt_dlhandle place);
+LT_SCOPE lt_dlhandle   lt_dlhandle_fetch   (lt_dlinterface_id iface,
+                                            const char *module_name);
+LT_SCOPE int           lt_dlhandle_map     (lt_dlinterface_id iface,
+                               int (*func) (lt_dlhandle handle, void *data),
+                               void *data);
+
+
+
+/* Deprecated module residency management API. */
+LT_SCOPE int       lt_dlmakeresident   (lt_dlhandle handle);
+LT_SCOPE int       lt_dlisresident     (lt_dlhandle handle);
+
+#define lt_ptr void *
+
+LT_END_C_DECLS
+
+#endif /*!defined(LTDL_H)*/
diff --git a/libltdl/m4/argz.m4 b/libltdl/m4/argz.m4
new file mode 100644 (file)
index 0000000..d1f4ec5
--- /dev/null
@@ -0,0 +1,79 @@
+# Portability macros for glibc argz.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+#   Written by Gary V. Vaughan <gary@gnu.org>
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 argz.m4
+
+AC_DEFUN([gl_FUNC_ARGZ],
+[gl_PREREQ_ARGZ
+
+AC_CHECK_HEADERS([argz.h], [], [], [AC_INCLUDES_DEFAULT])
+
+AC_CHECK_TYPES([error_t],
+  [],
+  [AC_DEFINE([error_t], [int],
+   [Define to a type to use for `error_t' if it is not otherwise available.])
+   AC_DEFINE([__error_t_defined], [1], [Define so that glibc/gnulib argp.h
+    does not typedef error_t.])],
+  [#if defined(HAVE_ARGZ_H)
+#  include <argz.h>
+#endif])
+
+ARGZ_H=
+AC_CHECK_FUNCS([argz_add argz_append argz_count argz_create_sep argz_insert \
+       argz_next argz_stringify], [], [ARGZ_H=argz.h; AC_LIBOBJ([argz])])
+
+dnl if have system argz functions, allow forced use of
+dnl libltdl-supplied implementation (and default to do so
+dnl on "known bad" systems). Could use a runtime check, but
+dnl (a) detecting malloc issues is notoriously unreliable
+dnl (b) only known system that declares argz functions,
+dnl     provides them, yet they are broken, is cygwin
+dnl     releases prior to 16-Mar-2007 (1.5.24 and earlier)
+dnl So, it's more straightforward simply to special case
+dnl this for known bad systems.
+AS_IF([test -z "$ARGZ_H"],
+    [AC_CACHE_CHECK(
+        [if argz actually works],
+        [lt_cv_sys_argz_works],
+        [[case $host_os in #(
+        *cygwin*)
+          lt_cv_sys_argz_works=no
+          if test "$cross_compiling" != no; then
+            lt_cv_sys_argz_works="guessing no"
+          else
+            lt_sed_extract_leading_digits='s/^\([0-9\.]*\).*/\1/'
+            save_IFS=$IFS
+            IFS=-.
+            set x `uname -r | sed -e "$lt_sed_extract_leading_digits"`
+            IFS=$save_IFS
+            lt_os_major=${2-0}
+            lt_os_minor=${3-0}
+            lt_os_micro=${4-0}
+            if test "$lt_os_major" -gt 1 \
+               || { test "$lt_os_major" -eq 1 \
+                 && { test "$lt_os_minor" -gt 5 \
+                   || { test "$lt_os_minor" -eq 5 \
+                     && test "$lt_os_micro" -gt 24; }; }; }; then
+              lt_cv_sys_argz_works=yes
+            fi
+          fi
+          ;; #(
+        *) lt_cv_sys_argz_works=yes ;;
+        esac]])
+     AS_IF([test "$lt_cv_sys_argz_works" = yes],
+        [AC_DEFINE([HAVE_WORKING_ARGZ], 1,
+                   [This value is set to 1 to indicate that the system argz facility works])],
+        [ARGZ_H=argz.h
+        AC_LIBOBJ([argz])])])
+
+AC_SUBST([ARGZ_H])
+])
+
+# Prerequisites of lib/argz.c.
+AC_DEFUN([gl_PREREQ_ARGZ], [:])
diff --git a/libltdl/m4/libtool.m4 b/libltdl/m4/libtool.m4
new file mode 100644 (file)
index 0000000..d7c043f
--- /dev/null
@@ -0,0 +1,7997 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+#   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+#                 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+#                 Foundation, Inc.
+#   Written by Gordon Matzigkeit, 1996
+#
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 57 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+       [m4_default([$3],
+                  [m4_fatal([Libtool version $1 or higher is required],
+                            63)])],
+       [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+  *\ * | *\    *)
+    AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename.  Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+  case $cc_temp in
+    compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+    distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+    \-*) ;;
+    *) break;;
+  esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+   setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    _LT_PATH_MAGIC
+  fi
+  ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool.  Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+          [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+                     [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+              [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME.  Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+    [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+       [m4_ifval([$1], [$1], [$2])])
+    lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+    m4_ifval([$4],
+       [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+    lt_dict_add_subkey([lt_decl_dict], [$2],
+       [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+  [0], [m4_fatal([$0: too few arguments: $#])],
+  [1], [m4_fatal([$0: too few arguments: $#: $1])],
+  [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+  [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+  [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+    m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+    m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+     m4_if([$2], [],
+          m4_quote(lt_decl_varnames),
+       m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+                       lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'.  VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly.  In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+#    <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+    [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+#    # Some comment about what VAR is for.
+#    visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+                                          [description])))[]dnl
+m4_pushdef([_libtool_name],
+    m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+    [0], [_libtool_name=[$]$1],
+    [1], [_libtool_name=$lt_[]$1],
+    [2], [_libtool_name=$lt_[]$1],
+    [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script.  Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+    m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+    [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS.  Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'.  Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+       dnl If the libtool generation code has been placed in $CONFIG_LT,
+       dnl instead of duplicating it all over again into config.status,
+       dnl then we will have config.status run $CONFIG_LT later, so it
+       dnl needs to know what name is stored there:
+        [AC_CONFIG_COMMANDS([libtool],
+            [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+    dnl If the libtool generation code is destined for config.status,
+    dnl expand the accumulated commands and init code now:
+    [AC_CONFIG_COMMANDS([libtool],
+        [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+  eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+    case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+    *[[\\\\\\\`\\"\\\$]]*)
+      eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+      ;;
+    *)
+      eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+      ;;
+    esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable.  If COMMENT is supplied, it is inserted after the
+# `#!' sequence but before initialization text begins.  After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script.  The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test $lt_write_fail = 0 && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+  echo
+  AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+  -h, --help      print this help, then exit
+  -V, --version   print version number, then exit
+  -q, --quiet     do not print progress messages
+  -d, --debug     don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+  case $[1] in
+    --version | --v* | -V )
+      echo "$lt_cl_version"; exit 0 ;;
+    --help | --h* | -h )
+      echo "$lt_cl_help"; exit 0 ;;
+    --debug | --d* | -d )
+      debug=: ;;
+    --quiet | --q* | --silent | --s* | -q )
+      lt_cl_silent=: ;;
+
+    -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+    *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+  esac
+  shift
+done
+
+if $lt_cl_silent; then
+  exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure.  Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test "$silent" = yes &&
+  lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars.  Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+  m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+  m4_if(_LT_TAG, [C], [
+    # See if we are running on zsh, and set the options which allow our
+    # commands through without removal of \ escapes.
+    if test -n "${ZSH_VERSION+set}" ; then
+      setopt NO_GLOB_SUBST
+    fi
+
+    cfgfile="${ofile}T"
+    trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+    $RM "$cfgfile"
+
+    cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+  case $host_os in
+  aix3*)
+    cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+_LT_EOF
+    ;;
+  esac
+
+  _LT_PROG_LTMAIN
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" \
+     || (rm -f "$cfgfile"; exit 1)
+
+  _LT_PROG_REPLACE_SHELLFNS
+
+   mv -f "$cfgfile" "$ofile" ||
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+    PACKAGE='$PACKAGE'
+    VERSION='$VERSION'
+    TIMESTAMP='$TIMESTAMP'
+    RM='$RM'
+    ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+#    autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+  [C],                 [_LT_LANG(C)],
+  [C++],               [_LT_LANG(CXX)],
+  [Go],                        [_LT_LANG(GO)],
+  [Java],              [_LT_LANG(GCJ)],
+  [Fortran 77],                [_LT_LANG(F77)],
+  [Fortran],           [_LT_LANG(FC)],
+  [Windows Resource],  [_LT_LANG(RC)],
+  [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+    [_LT_LANG($1)],
+    [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+  [LT_SUPPORTED_TAG([$1])dnl
+  m4_append([_LT_TAGS], [$1 ])dnl
+  m4_define([_LT_LANG_]$1[_enabled], [])dnl
+  _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_GO.  When it is available in    #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC],     [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+  fi
+fi
+if test -z "$GOC"; then
+  AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+  [LT_LANG(CXX)],
+  [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+  [LT_LANG(F77)],
+  [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+  [LT_LANG(FC)],
+  [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+  [LT_LANG(GCJ)],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+    [LT_LANG(GCJ)],
+    [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+      [LT_LANG(GCJ)],
+      [m4_ifdef([AC_PROG_GCJ],
+       [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([A][M_PROG_GCJ],
+       [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+       m4_ifdef([LT_PROG_GCJ],
+       [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+  [LT_LANG(GO)],
+  [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+  [LT_LANG(RC)],
+  [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+  case $host_os in
+    rhapsody* | darwin*)
+    AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+    AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+    AC_CHECK_TOOL([LIPO], [lipo], [:])
+    AC_CHECK_TOOL([OTOOL], [otool], [:])
+    AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+    _LT_DECL([], [DSYMUTIL], [1],
+      [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+    _LT_DECL([], [NMEDIT], [1],
+      [Tool to change global to local symbols on Mac OS X])
+    _LT_DECL([], [LIPO], [1],
+      [Tool to manipulate fat objects and archives on Mac OS X])
+    _LT_DECL([], [OTOOL], [1],
+      [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+    _LT_DECL([], [OTOOL64], [1],
+      [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+    AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+      [lt_cv_apple_cc_single_mod=no
+      if test -z "${LT_MULTI_MODULE}"; then
+       # By default we will add the -single_module flag. You can override
+       # by either setting the environment variable LT_MULTI_MODULE
+       # non-empty at configure time, or by adding -multi_module to the
+       # link flags.
+       rm -rf libconftest.dylib*
+       echo "int foo(void){return 1;}" > conftest.c
+       echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+       $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+         -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+        _lt_result=$?
+       # If there is a non-empty error log, and "single_module"
+       # appears in it, assume the flag caused a linker warning
+        if test -s conftest.err && $GREP single_module conftest.err; then
+         cat conftest.err >&AS_MESSAGE_LOG_FD
+       # Otherwise, if the output was created with a 0 exit code from
+       # the compiler, it worked.
+       elif test -f libconftest.dylib && test $_lt_result -eq 0; then
+         lt_cv_apple_cc_single_mod=yes
+       else
+         cat conftest.err >&AS_MESSAGE_LOG_FD
+       fi
+       rm -rf libconftest.dylib*
+       rm -f conftest.*
+      fi])
+
+    AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+      [lt_cv_ld_exported_symbols_list],
+      [lt_cv_ld_exported_symbols_list=no
+      save_LDFLAGS=$LDFLAGS
+      echo "_main" > conftest.sym
+      LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+       [lt_cv_ld_exported_symbols_list=yes],
+       [lt_cv_ld_exported_symbols_list=no])
+       LDFLAGS="$save_LDFLAGS"
+    ])
+
+    AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+      [lt_cv_ld_force_load=no
+      cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+      echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+      $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+      echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+      $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+      cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+      echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+      $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+      _lt_result=$?
+      if test -s conftest.err && $GREP force_load conftest.err; then
+       cat conftest.err >&AS_MESSAGE_LOG_FD
+      elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then
+       lt_cv_ld_force_load=yes
+      else
+       cat conftest.err >&AS_MESSAGE_LOG_FD
+      fi
+        rm -f conftest.err libconftest.a conftest conftest.c
+        rm -rf conftest.dSYM
+    ])
+    case $host_os in
+    rhapsody* | darwin1.[[012]])
+      _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+    darwin1.*)
+      _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+    darwin*) # darwin 5.x on
+      # if running on 10.5 or later, the deployment target defaults
+      # to the OS version, if on x86, and 10.4, the deployment
+      # target defaults to 10.4. Don't you love it?
+      case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+       10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+       10.[[012]]*)
+         _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+       10.*)
+         _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+      esac
+    ;;
+  esac
+    if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+      _lt_dar_single_mod='$single_module'
+    fi
+    if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+      _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+    else
+      _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+      _lt_dsymutil='~$DSYMUTIL $lib || :'
+    else
+      _lt_dsymutil=
+    fi
+    ;;
+  esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+  m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_automatic, $1)=yes
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  if test "$lt_cv_ld_force_load" = "yes"; then
+    _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+    m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+                  [FC],  [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+  else
+    _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+  fi
+  _LT_TAGVAR(link_all_deplibs, $1)=yes
+  _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+  case $cc_basename in
+     ifort*) _lt_dar_can_shared=yes ;;
+     *) _lt_dar_can_shared=$GCC ;;
+  esac
+  if test "$_lt_dar_can_shared" = "yes"; then
+    output_verbose_link_cmd=func_echo_all
+    _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+    _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+    _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+    _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+    m4_if([$1], [CXX],
+[   if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+      _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+      _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+    fi
+],[])
+  else
+  _LT_TAGVAR(ld_shlibs, $1)=no
+  fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test "${lt_cv_aix_libpath+set}" = set; then
+  aix_libpath=$lt_cv_aix_libpath
+else
+  AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+  [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+  lt_aix_libpath_sed='[
+      /Import File Strings/,/^$/ {
+         /^0/ {
+             s/^0  *\([^ ]*\) *$/\1/
+             p
+         }
+      }]'
+  _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  # Check for a 64-bit object if we didn't find anything.
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+  fi],[])
+  if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+    _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib"
+  fi
+  ])
+  aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script which will find a shell with a builtin
+# printf (which we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+   test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+  ECHO='printf %s\n'
+else
+  # Use this function as a fallback that always works.
+  func_fallback_echo ()
+  {
+    eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+  }
+  ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+    $ECHO "$*" 
+}
+
+case "$ECHO" in
+  printf*) AC_MSG_RESULT([printf]) ;;
+  print*) AC_MSG_RESULT([print -r]) ;;
+  *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+  test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+    ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+    ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+    PATH=/empty FPATH=/empty; export PATH FPATH
+    test "X`printf %s $ECHO`" = "X$ECHO" \
+      || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[  --with-sysroot[=DIR] Search for dependent libraries within DIR
+                        (or the compiler's sysroot if not specified).],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted.  We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+   if test "$GCC" = yes; then
+     lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+   fi
+   ;; #(
+ /*)
+   lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+   ;; #(
+ no|'')
+   ;; #(
+ *)
+   AC_MSG_RESULT([${with_sysroot}])
+   AC_MSG_ERROR([The sysroot must be an absolute path.])
+   ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and in which our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+  [AS_HELP_STRING([--disable-libtool-lock],
+    [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+      *ELF-32*)
+       HPUX_IA64_MODE="32"
+       ;;
+      *ELF-64*)
+       HPUX_IA64_MODE="64"
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    if test "$lt_cv_prog_gnu_ld" = yes; then
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -melf32bsmip"
+         ;;
+       *N32*)
+         LD="${LD-ld} -melf32bmipn32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -melf64bmip"
+       ;;
+      esac
+    else
+      case `/usr/bin/file conftest.$ac_objext` in
+       *32-bit*)
+         LD="${LD-ld} -32"
+         ;;
+       *N32*)
+         LD="${LD-ld} -n32"
+         ;;
+       *64-bit*)
+         LD="${LD-ld} -64"
+         ;;
+      esac
+    fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+      *32-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_i386_fbsd"
+           ;;
+         x86_64-*linux*)
+           case `/usr/bin/file conftest.o` in
+             *x86-64*)
+               LD="${LD-ld} -m elf32_x86_64"
+               ;;
+             *)
+               LD="${LD-ld} -m elf_i386"
+               ;;
+           esac
+           ;;
+         powerpc64le-*)
+           LD="${LD-ld} -m elf32lppclinux"
+           ;;
+         powerpc64-*)
+           LD="${LD-ld} -m elf32ppclinux"
+           ;;
+         s390x-*linux*)
+           LD="${LD-ld} -m elf_s390"
+           ;;
+         sparc64-*linux*)
+           LD="${LD-ld} -m elf32_sparc"
+           ;;
+       esac
+       ;;
+      *64-bit*)
+       case $host in
+         x86_64-*kfreebsd*-gnu)
+           LD="${LD-ld} -m elf_x86_64_fbsd"
+           ;;
+         x86_64-*linux*)
+           LD="${LD-ld} -m elf_x86_64"
+           ;;
+         powerpcle-*)
+           LD="${LD-ld} -m elf64lppc"
+           ;;
+         powerpc-*)
+           LD="${LD-ld} -m elf64ppc"
+           ;;
+         s390*-*linux*|s390*-*tpf*)
+           LD="${LD-ld} -m elf64_s390"
+           ;;
+         sparc*-*linux*)
+           LD="${LD-ld} -m elf64_sparc"
+           ;;
+       esac
+       ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+*-*solaris*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.o` in
+    *64-bit*)
+      case $lt_cv_prog_gnu_ld in
+      yes*)
+        case $host in
+        i?86-*-solaris*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        sparc*-*-solaris*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+        esac
+        # GNU ld 2.21 introduced _sol2 emulations.  Use them if available.
+        if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+          LD="${LD-ld}_sol2"
+        fi
+        ;;
+      *)
+       if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+         LD="${LD-ld} -64"
+       fi
+       ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+  [lt_cv_ar_at_file=no
+   AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+     [echo conftest.$ac_objext > conftest.lst
+      lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+      AC_TRY_EVAL([lt_ar_try])
+      if test "$ac_status" -eq 0; then
+       # Ensure the archiver fails upon bogus file names.
+       rm -f conftest.$ac_objext libconftest.a
+       AC_TRY_EVAL([lt_ar_try])
+       if test "$ac_status" -ne 0; then
+          lt_cv_ar_at_file=@
+        fi
+      fi
+      rm -f conftest.* libconftest.a
+     ])
+  ])
+
+if test "x$lt_cv_ar_at_file" = xno; then
+  archiver_list_spec=
+else
+  archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+  [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+    [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+    ;;
+  *)
+    old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+  darwin*)
+    lock_old_archive_extraction=yes ;;
+  *)
+    lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+    [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+    [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#              [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings other than the usual output.
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+     $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+     if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+       $2=yes
+     fi
+   fi
+   $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$5], , :, [$5])
+else
+    m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                  [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   echo "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The linker can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+       $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+       $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+       if diff conftest.exp conftest.er2 >/dev/null; then
+         $2=yes
+       fi
+     else
+       $2=yes
+     fi
+   fi
+   $RM -r conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    m4_if([$4], , :, [$4])
+else
+    m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  teststring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw* | cegcc*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  mint*)
+    # On MiNT this can take a long time and run out of memory.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+    # This has been around since 386BSD, at least.  Likely further.
+    if test -x /sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+    elif test -x /usr/sbin/sysctl; then
+      lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+    else
+      lt_cv_sys_max_cmd_len=65536      # usable default for all BSDs
+    fi
+    # And add a safety zone
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    ;;
+
+  interix*)
+    # We know the value 262144 and hardcode it with a safety zone (like BSD)
+    lt_cv_sys_max_cmd_len=196608
+    ;;
+
+  os2*)
+    # The test takes a long time on OS/2.
+    lt_cv_sys_max_cmd_len=8192
+    ;;
+
+  osf*)
+    # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+    # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+    # nice to cause kernel panics so lets avoid the loop below.
+    # First set a reasonable default.
+    lt_cv_sys_max_cmd_len=16384
+    #
+    if test -x /sbin/sysconfig; then
+      case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+        *1*) lt_cv_sys_max_cmd_len=-1 ;;
+      esac
+    fi
+    ;;
+  sco3.2v5*)
+    lt_cv_sys_max_cmd_len=102400
+    ;;
+  sysv5* | sco5v6* | sysv4.2uw2*)
+    kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+    if test -n "$kargmax"; then
+      lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[        ]]//'`
+    else
+      lt_cv_sys_max_cmd_len=32768
+    fi
+    ;;
+  *)
+    lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+    if test -n "$lt_cv_sys_max_cmd_len" && \
+       test undefined != "$lt_cv_sys_max_cmd_len"; then
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+    else
+      # Make teststring a little bigger before we do anything with it.
+      # a 1K string should be a reasonable start.
+      for i in 1 2 3 4 5 6 7 8 ; do
+        teststring=$teststring$teststring
+      done
+      SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+      # If test is not a shell built-in, we'll probably end up computing a
+      # maximum length that is only half of the actual maximum length, but
+      # we can't tell.
+      while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \
+                = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+             test $i != 17 # 1/2 MB should be enough
+      do
+        i=`expr $i + 1`
+        teststring=$teststring$teststring
+      done
+      # Only check the string length outside the loop.
+      lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+      teststring=
+      # Add a significant safety factor because C++ compilers can tack on
+      # massive amounts of additional arguments before passing them to the
+      # linker.  It appears as though 1/2 is a usable value.
+      lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    fi
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+    [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                      ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+   correspondingly for the symbols needed.  */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else
+        {
+         if (dlsym( self,"_fnord"))  status = $lt_dlneed_uscore;
+          else puts (dlerror ());
+       }
+      /* dlclose (self); */
+    }
+  else
+    puts (dlerror ());
+
+  return status;
+}]
+_LT_EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_dlunknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32* | cegcc*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+    ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+    ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+    ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+         [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+           [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+       [AC_CHECK_FUNC([dlopen],
+             [lt_cv_dlopen="dlopen"],
+         [AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+           [AC_CHECK_LIB([svld], [dlopen],
+                 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+             [AC_CHECK_LIB([dld], [dld_link],
+                   [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+             ])
+           ])
+         ])
+       ])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+         lt_cv_dlopen_self, [dnl
+         _LT_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+           lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+         lt_cv_dlopen_self_static, [dnl
+         _LT_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+           lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+        [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+        [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+        [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $RM -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+     $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+     if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+       _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w . 2>&AS_MESSAGE_LOG_FD
+   $RM conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+   $RM out/* && rmdir out
+   cd ..
+   $RM -r conftest
+   $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+       [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $RM conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+         [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+  [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+   test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+   test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+  # We can hardcode non-existent directories.
+  if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+   test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+    [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+  darwin*)
+    if test -n "$STRIP" ; then
+      striplib="$STRIP -x"
+      old_striplib="$STRIP -S"
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+       [], [
+if test "$GCC" = yes; then
+  case $host_os in
+    darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+    *) lt_awk_arg="/^libraries:/" ;;
+  esac
+  case $host_os in
+    mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;;
+    *) lt_sed_strip_eq="s,=/,/,g" ;;
+  esac
+  lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+  case $lt_search_path_spec in
+  *\;*)
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+    ;;
+  *)
+    lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+    ;;
+  esac
+  # Ok, now we have the path, separated by spaces, we can step through it
+  # and add multilib dir if necessary.
+  lt_tmp_lt_search_path_spec=
+  lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+  for lt_sys_path in $lt_search_path_spec; do
+    if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+      lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+    else
+      test -d "$lt_sys_path" && \
+       lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+    fi
+  done
+  lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+  lt_foo="";
+  lt_count=0;
+  for (lt_i = NF; lt_i > 0; lt_i--) {
+    if ($lt_i != "" && $lt_i != ".") {
+      if ($lt_i == "..") {
+        lt_count++;
+      } else {
+        if (lt_count == 0) {
+          lt_foo="/" $lt_i lt_foo;
+        } else {
+          lt_count--;
+        }
+      }
+    }
+  }
+  if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+  if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+  # AWK program above erroneously prepends '/' to C:/dos/paths
+  # for these hosts.
+  case $host_os in
+    mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+      $SED 's,/\([[A-Za-z]]:\),\1,g'` ;;
+  esac
+  sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix[[4-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  case $host_cpu in
+  powerpc)
+    # Since July 2007 AmigaOS4 officially supports .so libraries.
+    # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    ;;
+  m68k)
+    library_names_spec='$libname.ixlibrary $libname.a'
+    # Create ${libname}_ixlibrary.a entries in /sys/libs.
+    finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+    ;;
+  esac
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi[[45]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+  version_type=windows
+  shrext_cmds=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$cc_basename in
+  yes,*)
+    # gcc
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname~
+      chmod a+x \$dldir/$dlname~
+      if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+        eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+      fi'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+m4_if([$1], [],[
+      sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+      ;;
+    mingw* | cegcc*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    dynamic_linker='Win32 ld.exe'
+    ;;
+
+  *,cl*)
+    # Native MSVC
+    libname_spec='$name'
+    soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+    library_names_spec='${libname}.dll.lib'
+
+    case $build_os in
+    mingw*)
+      sys_lib_search_path_spec=
+      lt_save_ifs=$IFS
+      IFS=';'
+      for lt_path in $LIB
+      do
+        IFS=$lt_save_ifs
+        # Let DOS variable expansion print the short 8.3 style file name.
+        lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+        sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+      done
+      IFS=$lt_save_ifs
+      # Convert to MSYS style.
+      sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+      ;;
+    cygwin*)
+      # Convert to unix form, then to dos form, then back to unix form
+      # but this time dos style (no spaces!) so that the unix form looks
+      # like /cygdrive/c/PROGRA~1:/cygdr...
+      sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+      sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+      sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      ;;
+    *)
+      sys_lib_search_path_spec="$LIB"
+      if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH.
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      # FIXME: find the short name or the path components, as spaces are
+      # common. (e.g. "Program Files" -> "PROGRA~1")
+      ;;
+    esac
+
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $RM \$dlpath'
+    shlibpath_overrides_runpath=yes
+    dynamic_linker='Win32 link.exe'
+    ;;
+
+  *)
+    # Assume MSVC wrapper
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    dynamic_linker='Win32 ld.exe'
+    ;;
+  esac
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+  sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd* | dragonfly*)
+  # DragonFly does not have aout.  When/if they implement a new
+  # versioning mechanism, adjust this.
+  if test -x /usr/bin/objformat; then
+    objformat=`/usr/bin/objformat`
+  else
+    case $host_os in
+    freebsd[[23]].*) objformat=aout ;;
+    *) objformat=elf ;;
+    esac
+  fi
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2.*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+  freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  *) # from 4.6 on, and DragonFly
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+haiku*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  dynamic_linker="$host_os runtime_loader"
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case $host_cpu in
+  ia64*)
+    shrext_cmds='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  hppa*64*)
+    shrext_cmds='.sl'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+  *)
+    shrext_cmds='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+  postinstall_cmds='chmod 555 $lib'
+  # or fails outright, so override atomically:
+  install_override_mode=555
+  ;;
+
+interix[[3-9]]*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux # correct to gnu/linux during the next big refactor
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+
+  # Some binutils ld are patched to set DT_RUNPATH
+  AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+    [lt_cv_shlibpath_overrides_runpath=no
+    save_LDFLAGS=$LDFLAGS
+    save_libdir=$libdir
+    eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+        LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+    AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+      [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+        [lt_cv_shlibpath_overrides_runpath=yes])])
+    LDFLAGS=$save_LDFLAGS
+    libdir=$save_libdir
+    ])
+  shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[  ]*hwcap[        ]/d;s/[:,      ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+netbsdelf*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='NetBSD ld.elf_so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+*nto* | *qnx*)
+  version_type=qnx
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='ldqnx.so'
+  ;;
+
+openbsd*)
+  version_type=sunos
+  sys_lib_dlsearch_path_spec="/usr/lib"
+  need_lib_prefix=no
+  # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+  case $host_os in
+    openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+    *)                         need_version=no  ;;
+  esac
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext_cmds=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+rdos*)
+  dynamic_linker=no
+  ;;
+
+solaris*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.3*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux # correct to gnu/linux during the next big refactor
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  version_type=freebsd-elf
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  if test "$with_gnu_ld" = yes; then
+    sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+  else
+    sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+    case $host_os in
+      sco3.2v5*)
+        sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+       ;;
+    esac
+  fi
+  sys_lib_dlsearch_path_spec='/usr/lib'
+  ;;
+
+tpf*)
+  # TPF is a cross-target only.  Preferred cross-host = GNU/Linux.
+  version_type=linux # correct to gnu/linux during the next big refactor
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  ;;
+
+uts4*)
+  version_type=linux # correct to gnu/linux during the next big refactor
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+  sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+  sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+    [Variables whose values should be saved in libtool wrapper scripts and
+    restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+    [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0],  [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+    [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+    [[List of archive names.  First name is the real one, the rest are links.
+    The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+    [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+    [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+    [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+    [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+    [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+    [[As "finish_cmds", except a single script fragment to be evaled but
+    not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+    [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+    [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+    [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="m4_if([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+        [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+    [AS_HELP_STRING([--with-gnu-ld],
+       [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+      while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some variants of GNU ld only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    if test "$GCC" != yes; then
+      reload_cmds=false
+    fi
+    ;;
+  darwin*)
+    if test "$GCC" = yes; then
+      reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+    else
+      reload_cmds='$LD$reload_flag -o $output$reload_objs'
+    fi
+    ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi[[45]]*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # func_win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='func_win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # func_win32_libid shell function, so use a weaker test based on 'objdump',
+  # unless we find 'file', for example because we are cross-compiling.
+  # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+  if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+    lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+    lt_cv_file_magic_cmd='func_win32_libid'
+  else
+    # Keep this pattern in sync with the one in func_win32_libid.
+    lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+    lt_cv_file_magic_cmd='$OBJDUMP -f'
+  fi
+  ;;
+
+cegcc*)
+  # use the weaker test based on 'objdump'. See mingw*.
+  lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | dragonfly*)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+haiku*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case $host_cpu in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+interix[[3-9]]*)
+  # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+  lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd* | netbsdelf*-gnu)
+  if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+*nto* | *qnx*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+openbsd*)
+  if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+rdos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.3*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  pc)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+tpf*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+  case $host_os in
+  mingw* | pw32*)
+    if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+      want_nocaseglob=yes
+    else
+      file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+    fi
+    ;;
+  esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+    [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+    [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+    [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+    [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_nm_to_check="${ac_tool_prefix}nm"
+  if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+    lt_nm_to_check="$lt_nm_to_check nm"
+  fi
+  for lt_tmp_nm in $lt_nm_to_check; do
+    lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+    for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+      IFS="$lt_save_ifs"
+      test -z "$ac_dir" && ac_dir=.
+      tmp_nm="$ac_dir/$lt_tmp_nm"
+      if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+       # Check to see if the nm accepts a BSD-compat flag.
+       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+       #   nm: unknown option "B" ignored
+       # Tru64's nm complains that /dev/null is an invalid object file
+       case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+       */dev/null* | *'Invalid file or object type'*)
+         lt_cv_path_NM="$tmp_nm -B"
+         break
+         ;;
+       *)
+         case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+         */dev/null*)
+           lt_cv_path_NM="$tmp_nm -p"
+           break
+           ;;
+         *)
+           lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+           continue # so that we can try to find one that supports BSD flags
+           ;;
+         esac
+         ;;
+       esac
+      fi
+    done
+    IFS="$lt_save_ifs"
+  done
+  : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+  NM="$lt_cv_path_NM"
+else
+  # Didn't find any BSD compatible name lister, look for dumpbin.
+  if test -n "$DUMPBIN"; then :
+    # Let the user override the test.
+  else
+    AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+    case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+    *COFF*)
+      DUMPBIN="$DUMPBIN -symbols"
+      ;;
+    *)
+      DUMPBIN=:
+      ;;
+    esac
+  fi
+  AC_SUBST([DUMPBIN])
+  if test "$DUMPBIN" != ":"; then
+    NM="$DUMPBIN"
+  fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+  [lt_cv_nm_interface="BSD nm"
+  echo "int some_variable = 0;" > conftest.$ac_ext
+  (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$ac_compile" 2>conftest.err)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+  (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+  cat conftest.out >&AS_MESSAGE_LOG_FD
+  if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+    lt_cv_nm_interface="MS dumpbin"
+  fi
+  rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+#  -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+  # two different shell functions defined in ltmain.sh
+  # decide which to use based on capabilities of $DLLTOOL
+  case `$DLLTOOL --help 2>&1` in
+  *--identify-strict*)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+    ;;
+  *)
+    lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+    ;;
+  esac
+  ;;
+*)
+  # fallback: assume linklib IS sharedlib
+  lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+  ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+    [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+  [lt_cv_path_mainfest_tool=no
+  echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+  $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+  cat conftest.err >&AS_MESSAGE_LOG_FD
+  if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+    lt_cv_path_mainfest_tool=yes
+  fi
+  rm -f conftest*])
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+  MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  case $cc_basename in
+  nvcc*)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+  esac
+
+  _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+       [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32* | cegcc*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*)
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris*)
+  symcode='[[BDRT]]'
+  ;;
+sco3.2v5*)
+  symcode='[[DT]]'
+  ;;
+sysv4.2uw2*)
+  symcode='[[DT]]'
+  ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+  symcode='[[ABDT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/  {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/  {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+  symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+  # Write the raw and C identifiers.
+  if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+    # Fake it for dumpbin and say T for any non-static function
+    # and D for any global variable.
+    # Also find C++ and __fastcall symbols from MSVC++,
+    # which start with @ or ?.
+    lt_cv_sys_global_symbol_pipe="$AWK ['"\
+"     {last_section=section; section=\$ 3};"\
+"     /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+"     /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+"     \$ 0!~/External *\|/{next};"\
+"     / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+"     {if(hide[section]) next};"\
+"     {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+"     {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+"     s[1]~/^[@?]/{print s[1], s[1]; next};"\
+"     s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+"     ' prfx=^$ac_symprfx]"
+  else
+    lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[    ]]\($symcode$symcode*\)[[       ]][[    ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+  fi
+  lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+       if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests.  */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+   relocations are performed -- see ld's documentation on pseudo-relocs.  */
+# define LT@&t@_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data.  */
+# define LT@&t@_DLSYM_CONST
+#else
+# define LT@&t@_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+         cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols.  */
+LT@&t@_DLSYM_CONST struct {
+  const char *name;
+  void       *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+  { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+         cat <<\_LT_EOF >> conftest.$ac_ext
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_globsym_save_LIBS=$LIBS
+         lt_globsym_save_CFLAGS=$CFLAGS
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+         if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS=$lt_globsym_save_LIBS
+         CFLAGS=$lt_globsym_save_CFLAGS
+       else
+         echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -rf conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+  nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+  nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+    [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+    [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+    [lt_cv_sys_global_symbol_to_c_name_address], [1],
+    [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+    [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+    [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([], [nm_file_list_spec], [1],
+    [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | cygwin* | os2* | pw32* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+    *qnx* | *nto*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix[[4-9]]*)
+       # All AIX code is PIC.
+       if test "$host_cpu" = ia64; then
+         # AIX 5 now supports IA64 processor
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       else
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68*)
+         # Green Hills C++ Compiler
+         # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+      mingw* | cygwin* | os2* | pw32* | cegcc*)
+       # This hack is so that the source file can tell whether it is being
+       # built for inclusion in a dll (and should export symbols for example).
+       m4_if([$1], [GCJ], [],
+         [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++*)
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         ghcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | dragonfly*)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           if test "$host_cpu" != ia64; then
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+           fi
+           ;;
+         aCC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+           case $host_cpu in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      interix*)
+       # This is c89, which is MS Visual C++ (no shared libs)
+       # Anyone wants to do a port?
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+       case $cc_basename in
+         KCC*)
+           # KAI C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           ;;
+         ecpc* )
+           # old Intel C++ for x86_64 which still supported -KPIC.
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         icpc* )
+           # Intel C++, used to be incompatible with GCC.
+           # ICC 10 doesn't accept -KPIC any more.
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         pgCC* | pgcpp*)
+           # Portland Group C++ compiler
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         cxx*)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+           # IBM XL 8.0, 9.0 on PPC and BlueGene
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+             _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+             _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx*)
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd* | netbsdelf*-gnu)
+       ;;
+      *qnx* | *nto*)
+        # QNX uses GNU C++, but need to define -shared option too, otherwise
+        # it will coredump.
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+        ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           ;;
+         RCC*)
+           # Rational C++ 2.4.1
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         cxx*)
+           # Digital/Compaq C++
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC* | sunCC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+           ;;
+         gcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC*)
+           # Sun C++ 4.x
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         lcc*)
+           # Lucid
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+       case $cc_basename in
+         CC*)
+           _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC*)
+           # NonStop-UX NCC 3.20
+           _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      vxworks*)
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+       ;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+        ;;
+      m68k)
+            # FIXME: we need at least 68020 code to build shared libraries, but
+            # adding the `-m68020' flag to GCC prevents building anything better,
+            # like `-m68040'.
+            _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+        ;;
+      esac
+      ;;
+
+    beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      # Although the cygwin gcc ignores -fPIC, still need this for old-style
+      # (--disable-auto-import) libraries
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    haiku*)
+      # PIC is the default for Haiku.
+      # The "-static" flag exists, but is broken.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)=
+      ;;
+
+    hpux*)
+      # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+      # PA HP-UX.  On IA64 HP-UX, PIC is the default but the pic flag
+      # sets the default TLS model and affects inlining.
+      case $host_cpu in
+      hppa*64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+
+    interix[[3-9]]*)
+      # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+      # Instead, we relocate shared libraries at runtime.
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+
+    case $cc_basename in
+    nvcc*) # Cuda Compiler Driver 2.2
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+      if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+        _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+      fi
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | cygwin* | pw32* | os2* | cegcc*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      m4_if([$1], [GCJ], [],
+       [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case $host_cpu in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+      case $cc_basename in
+      # old Intel for x86_64 which still supported -KPIC.
+      ecc*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # icc used to be incompatible with GCC.
+      # ICC 10 doesn't accept -KPIC any more.
+      icc* | ifort*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      # Lahey Fortran 8.1.
+      lf95*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+       ;;
+      nagfor*)
+       # NAG Fortran compiler
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       ;;
+      pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+        # Portland Group compilers (*not* the Pentium gcc compiler,
+       # which looks to be a dead project)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+        ;;
+      ccc*)
+        _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      xl* | bgxl* | bgf* | mpixl*)
+       # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+       ;;
+      *)
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+         # Sun Fortran 8.3 passes all unrecognized flags to the linker
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+         ;;
+       *Sun\ F* | *Sun*Fortran*)
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+         ;;
+       *Sun\ C*)
+         # Sun C 5.9
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         ;;
+        *Intel*\ [[CF]]*Compiler*)
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+         ;;
+       *Portland\ Group*)
+         _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+         _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+         _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+         ;;
+       esac
+       ;;
+      esac
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *nto* | *qnx*)
+      # QNX uses GNU C++, but need to define -shared option too, otherwise
+      # it will coredump.
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    rdos*)
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      case $cc_basename in
+      f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+      *)
+       _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+       _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    unicos*)
+      _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+case $host_os in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+  [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+    [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+    [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+       [Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+       [How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+  _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+  $lt_tmp_static_flag,
+  [],
+  [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+       [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  case $host_os in
+  aix[[4-9]]*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    # Also, AIX nm treats weak defined symbols like other global defined
+    # symbols, whereas GNU nm marks them as "W".
+    if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+    ;;
+  cygwin* | mingw* | cegcc*)
+    case $cc_basename in
+    cl*)
+      _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+      ;;
+    *)
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+      ;;
+    esac
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    _LT_TAGVAR(link_all_deplibs, $1)=no
+    ;;
+  *)
+    _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+    ;;
+  esac
+], [
+  runpath_var=
+  _LT_TAGVAR(allow_undefined_flag, $1)=
+  _LT_TAGVAR(always_export_symbols, $1)=no
+  _LT_TAGVAR(archive_cmds, $1)=
+  _LT_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_TAGVAR(compiler_needs_object, $1)=no
+  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  _LT_TAGVAR(hardcode_automatic, $1)=no
+  _LT_TAGVAR(hardcode_direct, $1)=no
+  _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+  _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_TAGVAR(inherit_rpath, $1)=no
+  _LT_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_TAGVAR(module_cmds, $1)=
+  _LT_TAGVAR(module_expsym_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+  _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_TAGVAR(whole_archive_flag_spec, $1)=
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32* | cegcc*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  interix*)
+    # we just hope/assume this is gcc and not c89 (= MSVC++)
+    with_gnu_ld=yes
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  linux* | k*bsd*-gnu | gnu*)
+    _LT_TAGVAR(link_all_deplibs, $1)=no
+    ;;
+  esac
+
+  _LT_TAGVAR(ld_shlibs, $1)=yes
+
+  # On some targets, GNU ld is compatible enough with the native linker
+  # that we're better off using the native interface for both.
+  lt_use_gnu_ld_interface=no
+  if test "$with_gnu_ld" = yes; then
+    case $host_os in
+      aix*)
+       # The AIX port of GNU ld has always aspired to compatibility
+       # with the native linker.  However, as the warning in the GNU ld
+       # block says, versions before 2.19.5* couldn't really create working
+       # shared libraries, regardless of the interface used.
+       case `$LD -v 2>&1` in
+         *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+         *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+         *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+         *)
+           lt_use_gnu_ld_interface=yes
+           ;;
+       esac
+       ;;
+      *)
+       lt_use_gnu_ld_interface=yes
+       ;;
+    esac
+  fi
+
+  if test "$lt_use_gnu_ld_interface" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # Set some defaults for GNU ld with shared library support. These
+    # are reset later if shared libraries are not supported. Putting them
+    # here allows them to be overridden if necessary.
+    runpath_var=LD_RUN_PATH
+    _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+      _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+    supports_anon_versioning=no
+    case `$LD -v 2>&1` in
+      *GNU\ gold*) supports_anon_versioning=yes ;;
+      *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+      *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+      *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+      *\ 2.11.*) ;; # other 2.11 versions
+      *) supports_anon_versioning=yes ;;
+    esac
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix[[3-9]]*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=no
+      _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+      _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+      if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    haiku*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    interix[[3-9]]*)
+      _LT_TAGVAR(hardcode_direct, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+      # Instead, shared libraries are loaded at an image base (0x10000000 by
+      # default) and relocated if they conflict, which is a slow very memory
+      # consuming and fragmenting process.  To avoid this, we pick a random,
+      # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+      # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+      ;;
+
+    gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+      tmp_diet=no
+      if test "$host_os" = linux-dietlibc; then
+       case $cc_basename in
+         diet\ *) tmp_diet=yes;;       # linux-dietlibc with static linking (!diet-dyn)
+       esac
+      fi
+      if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+        && test "$tmp_diet" = no
+      then
+       tmp_addflag=' $pic_flag'
+       tmp_sharedflag='-shared'
+       case $cc_basename,$host_cpu in
+        pgcc*)                         # Portland Group C compiler
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag'
+         ;;
+       pgf77* | pgf90* | pgf95* | pgfortran*)
+                                       # Portland Group f77 and f90 compilers
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         tmp_addflag=' $pic_flag -Mnomain' ;;
+       ecc*,ia64* | icc*,ia64*)        # Intel C compiler on ia64
+         tmp_addflag=' -i_dynamic' ;;
+       efc*,ia64* | ifort*,ia64*)      # Intel Fortran compiler on ia64
+         tmp_addflag=' -i_dynamic -nofor_main' ;;
+       ifc* | ifort*)                  # Intel Fortran compiler
+         tmp_addflag=' -nofor_main' ;;
+       lf95*)                          # Lahey Fortran 8.1
+         _LT_TAGVAR(whole_archive_flag_spec, $1)=
+         tmp_sharedflag='--shared' ;;
+       xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+         tmp_sharedflag='-qmkshrobj'
+         tmp_addflag= ;;
+       nvcc*)  # Cuda Compiler Driver 2.2
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         _LT_TAGVAR(compiler_needs_object, $1)=yes
+         ;;
+       esac
+       case `$CC -V 2>&1 | sed 5q` in
+       *Sun\ C*)                       # Sun C 5.9
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+         _LT_TAGVAR(compiler_needs_object, $1)=yes
+         tmp_sharedflag='-G' ;;
+       *Sun\ F*)                       # Sun Fortran 8.3
+         tmp_sharedflag='-G' ;;
+       esac
+       _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+        if test "x$supports_anon_versioning" = xyes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+           cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+           echo "local: *; };" >> $output_objdir/$libname.ver~
+           $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+        fi
+
+       case $cc_basename in
+       xlf* | bgf* | bgxlf* | mpixlf*)
+         # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+         if test "x$supports_anon_versioning" = xyes; then
+           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+             cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+             echo "local: *; };" >> $output_objdir/$libname.ver~
+             $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+         fi
+         ;;
+       esac
+      else
+        _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris*)
+      if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+      elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+      case `$LD -v 2>&1` in
+        *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+       ;;
+       *)
+         # For security reasons, it is highly recommended that you always
+         # use absolute paths for naming shared libraries, and exclude the
+         # DT_RUNPATH tag from executables and libraries.  But doing so
+         # requires that you compile everything twice, which is a pain.
+         if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+         else
+           _LT_TAGVAR(ld_shlibs, $1)=no
+         fi
+       ;;
+      esac
+      ;;
+
+    sunos4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+      runpath_var=
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+      _LT_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       _LT_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix[[4-9]]*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       # Also, AIX nm treats weak defined symbols like other global
+       # defined symbols, whereas GNU nm marks them as "W".
+       if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+         _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       else
+         _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+         ;;
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_TAGVAR(archive_cmds, $1)=''
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[[012]]|aix4.[[012]].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+          strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         :
+         else
+         # We have old collect2
+         _LT_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+         ;;
+       esac
+       shared_flag='-shared'
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag="$shared_flag "'${wl}-G'
+       fi
+       _LT_TAGVAR(link_all_deplibs, $1)=no
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+         fi
+       fi
+      fi
+
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX([$1])
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+      else
+       if test "$host_cpu" = ia64; then
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+         _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+         _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an
+        # empty executable.
+        _LT_SYS_MODULE_PATH_AIX([$1])
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+         _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+         if test "$with_gnu_ld" = yes; then
+           # We only use this code for GNU lds that support --whole-archive.
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+         else
+           # Exported symbols can be pulled into shared objects from archives
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+         fi
+         _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+         # This is similar to how AIX traditionally builds its shared libraries.
+         _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      case $host_cpu in
+      powerpc)
+            # see comment about AmigaOS4 .so support
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+            _LT_TAGVAR(archive_expsym_cmds, $1)=''
+        ;;
+      m68k)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes
+        ;;
+      esac
+      ;;
+
+    bsdi[[45]]*)
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32* | cegcc*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      case $cc_basename in
+      cl*)
+       # Native MSVC
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       _LT_TAGVAR(always_export_symbols, $1)=yes
+       _LT_TAGVAR(file_list_spec, $1)='@'
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+       _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+           sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+         else
+           sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+         fi~
+         $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+         linknames='
+       # The linker will not automatically build a static lib if we build a DLL.
+       # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+       _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+       # Don't use ranlib
+       _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+       _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+         lt_tool_outputfile="@TOOL_OUTPUT@"~
+         case $lt_outputfile in
+           *.exe|*.EXE) ;;
+           *)
+             lt_outputfile="$lt_outputfile.exe"
+             lt_tool_outputfile="$lt_tool_outputfile.exe"
+             ;;
+         esac~
+         if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+           $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+           $RM "$lt_outputfile.manifest";
+         fi'
+       ;;
+      *)
+       # Assume MSVC wrapper
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+       _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Tell ltmain to make .lib files, not .a files.
+       libext=lib
+       # Tell ltmain to make .dll files, not .so files.
+       shrext_cmds=".dll"
+       # FIXME: Setting linknames here is a bad hack.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+       # The linker will automatically build a .lib file if we build a DLL.
+       _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+       # FIXME: Should let the user specify the lib program.
+       _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+       _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+       ;;
+      esac
+      ;;
+
+    darwin* | rhapsody*)
+      _LT_DARWIN_LINKER_FEATURES($1)
+      ;;
+
+    dgux*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2.*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | dragonfly*)
+      _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+       _LT_TAGVAR(hardcode_direct, $1)=yes
+       _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       # hardcode_minus_L: Not really in the search PATH,
+       # but as the default location of the library.
+       _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      fi
+      ;;
+
+    hpux11*)
+      if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+       case $host_cpu in
+       hppa*64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case $host_cpu in
+       hppa*64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       ia64*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+       m4_if($1, [], [
+         # Older versions of the 11.00 compiler do not understand -b yet
+         # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+         _LT_LINKER_OPTION([if $CC understands -b],
+           _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+           [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+           [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+         [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       case $host_cpu in
+       hppa*64*|ia64*)
+         _LT_TAGVAR(hardcode_direct, $1)=no
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+         ;;
+       *)
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         _LT_TAGVAR(hardcode_minus_L, $1)=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       # Try to use the -exported_symbol ld option, if it does not
+       # work, assume that -exports_file does not work either and
+       # implicitly export all symbols.
+       # This should be the same for all languages, so no per-tag cache variable.
+       AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+         [lt_cv_irix_exported_symbol],
+         [save_LDFLAGS="$LDFLAGS"
+          LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+          AC_LINK_IFELSE(
+            [AC_LANG_SOURCE(
+               [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+                             [C++], [[int foo (void) { return 0; }]],
+                             [Fortran 77], [[
+      subroutine foo
+      end]],
+                             [Fortran], [[
+      subroutine foo
+      end]])])],
+             [lt_cv_irix_exported_symbol=yes],
+             [lt_cv_irix_exported_symbol=no])
+           LDFLAGS="$save_LDFLAGS"])
+       if test "$lt_cv_irix_exported_symbol" = yes; then
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+       fi
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(inherit_rpath, $1)=yes
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd* | netbsdelf*-gnu)
+      if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *nto* | *qnx*)
+      ;;
+
+    openbsd*)
+      if test -f /usr/libexec/ld.so; then
+       _LT_TAGVAR(hardcode_direct, $1)=yes
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+       if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       else
+         case $host_os in
+          openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+            _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+            ;;
+          *)
+            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+            _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+            ;;
+         esac
+       fi
+      else
+       _LT_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    os2*)
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+       _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+       $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    solaris*)
+      _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+      if test "$GCC" = yes; then
+       wlarc='${wl}'
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+      else
+       case `$CC -V 2>&1` in
+       *"Compilers 5.0"*)
+         wlarc=''
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+         ;;
+       *)
+         wlarc='${wl}'
+         _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+         $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+         ;;
+       esac
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *)
+       # The compiler driver will combine and reorder linker options,
+       # but understands `-z linker_flag'.  GCC discards it without `$wl',
+       # but is careful enough not to reorder.
+       # Supported since Solaris 2.6 (maybe 2.5.1?)
+       if test "$GCC" = yes; then
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+       else
+         _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+       fi
+       ;;
+      esac
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_direct, $1)=yes
+      _LT_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+         _LT_TAGVAR(hardcode_direct, $1)=no
+        ;;
+       motorola)
+         _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       _LT_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    sysv5* | sco3.2v5* | sco5v6*)
+      # Note: We can NOT use -z defs as we might desire, because we do not
+      # link with -lc, and that would cause any symbols used from libc to
+      # always be unresolved, which means just about no library would
+      # ever link correctly.  If we're not using GNU ld we use -z text
+      # though, which does catch some bad symbols but isn't as heavy-handed
+      # as -z defs.
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+      _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_TAGVAR(link_all_deplibs, $1)=yes
+      _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var='LD_RUN_PATH'
+
+      if test "$GCC" = yes; then
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      ;;
+
+    uts4*)
+      _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+
+    if test x$host_vendor = xsni; then
+      case $host in
+      sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+       ;;
+      esac
+    fi
+  fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+    [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+       [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+       [$RM conftest*
+       echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+       if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+         soname=conftest
+         lib=conftest
+         libobjs=conftest.$ac_objext
+         deplibs=
+         wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+         pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+         compiler_flags=-v
+         linker_flags=-v
+         verstring=
+         output_objdir=.
+         libname=conftest
+         lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+         _LT_TAGVAR(allow_undefined_flag, $1)=
+         if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+         then
+           lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+         else
+           lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+         fi
+         _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+       else
+         cat conftest.err 1>&5
+       fi
+       $RM conftest*
+       ])
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+      ;;
+    esac
+  fi
+  ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+    [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+    [enable_shared_with_static_runtimes], [0],
+    [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+    [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+    [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+    [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+    [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+    [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+    [Commands used to build a loadable module if different from building
+    a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+    [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+    [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+    [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+    [Flag to hardcode $libdir into a binary during linking.
+    This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+    [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+    [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+    DIR into the resulting binary and the resulting library dependency is
+    "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+    library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+    [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+    [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+    into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+    [Set to "yes" if building a shared library automatically hardcodes DIR
+    into the library and all subsequent libraries and executables linked
+    against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+    [Set to yes if linker adds runtime paths of dependent libraries
+    to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+    [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+    [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+    [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+    [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+    [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+    [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+    [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+    [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl    [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_SYS_DYNAMIC_LINKER($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+  LT_SYS_DLOPEN_SELF
+  _LT_CMD_STRIPLIB
+
+  # Report which library types will actually be built
+  AC_MSG_CHECKING([if libtool supports shared libraries])
+  AC_MSG_RESULT([$can_build_shared])
+
+  AC_MSG_CHECKING([whether to build shared libraries])
+  test "$can_build_shared" = "no" && enable_shared=no
+
+  # On AIX, shared libraries and static libraries use the same namespace, and
+  # are all built from PIC.
+  case $host_os in
+  aix3*)
+    test "$enable_shared" = yes && enable_static=no
+    if test -n "$RANLIB"; then
+      archive_cmds="$archive_cmds~\$RANLIB \$lib"
+      postinstall_cmds='$RANLIB $lib'
+    fi
+    ;;
+
+  aix[[4-9]]*)
+    if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+      test "$enable_shared" = yes && enable_static=no
+    fi
+    ;;
+  esac
+  AC_MSG_RESULT([$enable_shared])
+
+  AC_MSG_CHECKING([whether to build static libraries])
+  # Make sure either enable_shared or enable_static is yes.
+  test "$enable_shared" = yes || enable_static=yes
+  AC_MSG_RESULT([$enable_static])
+
+  _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined.  These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+    ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+    (test "X$CXX" != "Xg++"))) ; then
+  AC_PROG_CXXCPP
+else
+  _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="int some_variable = 0;"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC=$CC
+  lt_save_CFLAGS=$CFLAGS
+  lt_save_LD=$LD
+  lt_save_GCC=$GCC
+  GCC=$GXX
+  lt_save_with_gnu_ld=$with_gnu_ld
+  lt_save_path_LD=$lt_cv_path_LD
+  if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+    lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+  else
+    $as_unset lt_cv_prog_gnu_ld
+  fi
+  if test -n "${lt_cv_path_LDCXX+set}"; then
+    lt_cv_path_LD=$lt_cv_path_LDCXX
+  else
+    $as_unset lt_cv_path_LD
+  fi
+  test -z "${LDCXX+set}" || LD=$LDCXX
+  CC=${CXX-"c++"}
+  CFLAGS=$CXXFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    # We don't want -fno-exception when compiling C++ code, so set the
+    # no_builtin_flag separately
+    if test "$GXX" = yes; then
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+    else
+      _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+    fi
+
+    if test "$GXX" = yes; then
+      # Set up default GNU C++ configuration
+
+      LT_PATH_LD
+
+      # Check if GNU C++ uses GNU ld as the underlying linker, since the
+      # archiving commands below assume that GNU ld is being used.
+      if test "$with_gnu_ld" = yes; then
+        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+        # If archive_cmds runs LD, not CC, wlarc should be empty
+        # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+        #     investigate it a little bit more. (MM)
+        wlarc='${wl}'
+
+        # ancient GNU ld didn't support --whole-archive et. al.
+        if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+         $GREP 'no-whole-archive' > /dev/null; then
+          _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+        else
+          _LT_TAGVAR(whole_archive_flag_spec, $1)=
+        fi
+      else
+        with_gnu_ld=no
+        wlarc=
+
+        # A generic and very simple default shared library creation
+        # command for GNU C++ for the case where it uses the native
+        # linker, instead of GNU ld.  If possible, this setting should
+        # overridden to take advantage of the native linker features on
+        # the platform it is being used on.
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+      fi
+
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+    else
+      GXX=no
+      with_gnu_ld=no
+      wlarc=
+    fi
+
+    # PORTME: fill in a description of your system's C++ link characteristics
+    AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+    _LT_TAGVAR(ld_shlibs, $1)=yes
+    case $host_os in
+      aix3*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+      aix[[4-9]]*)
+        if test "$host_cpu" = ia64; then
+          # On IA64, the linker does run time linking by default, so we don't
+          # have to do anything special.
+          aix_use_runtimelinking=no
+          exp_sym_flag='-Bexport'
+          no_entry_flag=""
+        else
+          aix_use_runtimelinking=no
+
+          # Test if we are trying to use run time linking or normal
+          # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+          # need to do runtime linking.
+          case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+           for ld_flag in $LDFLAGS; do
+             case $ld_flag in
+             *-brtl*)
+               aix_use_runtimelinking=yes
+               break
+               ;;
+             esac
+           done
+           ;;
+          esac
+
+          exp_sym_flag='-bexport'
+          no_entry_flag='-bnoentry'
+        fi
+
+        # When large executables or shared objects are built, AIX ld can
+        # have problems creating the table of contents.  If linking a library
+        # or program results in "error TOC overflow" add -mminimal-toc to
+        # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+        # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+        _LT_TAGVAR(archive_cmds, $1)=''
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+        if test "$GXX" = yes; then
+          case $host_os in aix4.[[012]]|aix4.[[012]].*)
+          # We only want to do this on AIX 4.2 and lower, the check
+          # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" &&
+            strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+         then
+           # We have reworked collect2
+           :
+         else
+           # We have old collect2
+           _LT_TAGVAR(hardcode_direct, $1)=unsupported
+           # It fails to find uninstalled libraries when the uninstalled
+           # path is not listed in the libpath.  Setting hardcode_minus_L
+           # to unsupported forces relinking
+           _LT_TAGVAR(hardcode_minus_L, $1)=yes
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+          esac
+          shared_flag='-shared'
+         if test "$aix_use_runtimelinking" = yes; then
+           shared_flag="$shared_flag "'${wl}-G'
+         fi
+        else
+          # not using gcc
+          if test "$host_cpu" = ia64; then
+         # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+         # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+          else
+           if test "$aix_use_runtimelinking" = yes; then
+             shared_flag='${wl}-G'
+           else
+             shared_flag='${wl}-bM:SRE'
+           fi
+          fi
+        fi
+
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+        # It seems that -bexpall does not export symbols beginning with
+        # underscore (_), so it is better to generate a list of symbols to
+       # export.
+        _LT_TAGVAR(always_export_symbols, $1)=yes
+        if test "$aix_use_runtimelinking" = yes; then
+          # Warning - without using the other runtime loading flags (-brtl),
+          # -berok will link without error, but may produce a broken library.
+          _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+          # Determine the default libpath from the value encoded in an empty
+          # executable.
+          _LT_SYS_MODULE_PATH_AIX([$1])
+          _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+          _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+        else
+          if test "$host_cpu" = ia64; then
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+           _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+           _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+          else
+           # Determine the default libpath from the value encoded in an
+           # empty executable.
+           _LT_SYS_MODULE_PATH_AIX([$1])
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+           # Warning - without using the other run time loading flags,
+           # -berok will link without error, but may produce a broken library.
+           _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+           _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+           if test "$with_gnu_ld" = yes; then
+             # We only use this code for GNU lds that support --whole-archive.
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+           else
+             # Exported symbols can be pulled into shared objects from archives
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+           fi
+           _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+           # This is similar to how AIX traditionally builds its shared
+           # libraries.
+           _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+          fi
+        fi
+        ;;
+
+      beos*)
+       if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+         # support --undefined.  This deserves some investigation.  FIXME
+         _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       else
+         _LT_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+
+      chorus*)
+        case $cc_basename in
+          *)
+         # FIXME: insert proper C++ library support
+         _LT_TAGVAR(ld_shlibs, $1)=no
+         ;;
+        esac
+        ;;
+
+      cygwin* | mingw* | pw32* | cegcc*)
+       case $GXX,$cc_basename in
+       ,cl* | no,cl*)
+         # Native MSVC
+         # hardcode_libdir_flag_spec is actually meaningless, as there is
+         # no search path for DLLs.
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         _LT_TAGVAR(always_export_symbols, $1)=yes
+         _LT_TAGVAR(file_list_spec, $1)='@'
+         # Tell ltmain to make .lib files, not .a files.
+         libext=lib
+         # Tell ltmain to make .dll files, not .so files.
+         shrext_cmds=".dll"
+         # FIXME: Setting linknames here is a bad hack.
+         _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+         _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+             $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+           else
+             $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+           fi~
+           $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+           linknames='
+         # The linker will not automatically build a static lib if we build a DLL.
+         # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+         _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+         # Don't use ranlib
+         _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+         _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+           lt_tool_outputfile="@TOOL_OUTPUT@"~
+           case $lt_outputfile in
+             *.exe|*.EXE) ;;
+             *)
+               lt_outputfile="$lt_outputfile.exe"
+               lt_tool_outputfile="$lt_tool_outputfile.exe"
+               ;;
+           esac~
+           func_to_tool_file "$lt_outputfile"~
+           if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+             $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+             $RM "$lt_outputfile.manifest";
+           fi'
+         ;;
+       *)
+         # g++
+         # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+         # as there is no search path for DLLs.
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+         _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+         _LT_TAGVAR(always_export_symbols, $1)=no
+         _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+         if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+           # If the export-symbols file already is a .def file (1st line
+           # is EXPORTS), use it as is; otherwise, prepend...
+           _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+             cp $export_symbols $output_objdir/$soname.def;
+           else
+             echo EXPORTS > $output_objdir/$soname.def;
+             cat $export_symbols >> $output_objdir/$soname.def;
+           fi~
+           $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+         else
+           _LT_TAGVAR(ld_shlibs, $1)=no
+         fi
+         ;;
+       esac
+       ;;
+      darwin* | rhapsody*)
+        _LT_DARWIN_LINKER_FEATURES($1)
+       ;;
+
+      dgux*)
+        case $cc_basename in
+          ec++*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          ghcx*)
+           # Green Hills C++ Compiler
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      freebsd2.*)
+        # C++ shared libraries reported to be fairly broken before
+       # switch to ELF
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      freebsd-elf*)
+        _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+        ;;
+
+      freebsd* | dragonfly*)
+        # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+        # conventions
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+        ;;
+
+      haiku*)
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+        _LT_TAGVAR(link_all_deplibs, $1)=yes
+        ;;
+
+      hpux9*)
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        _LT_TAGVAR(hardcode_direct, $1)=yes
+        _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                            # but as the default
+                                            # location of the library.
+
+        case $cc_basename in
+          CC*)
+            # FIXME: insert proper C++ library support
+            _LT_TAGVAR(ld_shlibs, $1)=no
+            ;;
+          aCC*)
+            _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            # Commands to make compiler produce verbose output that lists
+            # what "hidden" libraries, object files and flags are used when
+            # linking a shared library.
+            #
+            # There doesn't appear to be a way to prevent this compiler from
+            # explicitly linking system object files so we need to strip them
+            # from the output so that they don't get included in the library
+            # dependencies.
+            output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+            ;;
+          *)
+            if test "$GXX" = yes; then
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+            else
+              # FIXME: insert proper C++ library support
+              _LT_TAGVAR(ld_shlibs, $1)=no
+            fi
+            ;;
+        esac
+        ;;
+
+      hpux10*|hpux11*)
+        if test $with_gnu_ld = no; then
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+         _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+          case $host_cpu in
+            hppa*64*|ia64*)
+              ;;
+            *)
+             _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+              ;;
+          esac
+        fi
+        case $host_cpu in
+          hppa*64*|ia64*)
+            _LT_TAGVAR(hardcode_direct, $1)=no
+            _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+            ;;
+          *)
+            _LT_TAGVAR(hardcode_direct, $1)=yes
+            _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+            _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                                # but as the default
+                                                # location of the library.
+            ;;
+        esac
+
+        case $cc_basename in
+          CC*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          aCC*)
+           case $host_cpu in
+             hppa*64*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+             ia64*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+             *)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+               ;;
+           esac
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+           ;;
+          *)
+           if test "$GXX" = yes; then
+             if test $with_gnu_ld = no; then
+               case $host_cpu in
+                 hppa*64*)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+                 ia64*)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+                 *)
+                   _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+                   ;;
+               esac
+             fi
+           else
+             # FIXME: insert proper C++ library support
+             _LT_TAGVAR(ld_shlibs, $1)=no
+           fi
+           ;;
+        esac
+        ;;
+
+      interix[[3-9]]*)
+       _LT_TAGVAR(hardcode_direct, $1)=no
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+       # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+       # Instead, shared libraries are loaded at an image base (0x10000000 by
+       # default) and relocated if they conflict, which is a slow very memory
+       # consuming and fragmenting process.  To avoid this, we pick a random,
+       # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+       # time.  Moving up from 0x10000000 also allows more sbrk(2) space.
+       _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+       _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+       ;;
+      irix5* | irix6*)
+        case $cc_basename in
+          CC*)
+           # SGI C++
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+
+           # Archives containing C++ object files must be created using
+           # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+           # necessary to make sure instantiated templates are included
+           # in the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+           ;;
+          *)
+           if test "$GXX" = yes; then
+             if test "$with_gnu_ld" = no; then
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+             else
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
+             fi
+           fi
+           _LT_TAGVAR(link_all_deplibs, $1)=yes
+           ;;
+        esac
+        _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+        _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+        _LT_TAGVAR(inherit_rpath, $1)=yes
+        ;;
+
+      linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+        case $cc_basename in
+          KCC*)
+           # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+           # KCC will only create a shared library if the output file
+           # ends with ".so" (or ".sl" for HP-UX), so rename the library
+           # to its proper name (with version) after linking.
+           _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+           # Archives containing C++ object files must be created using
+           # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+           ;;
+         icpc* | ecpc* )
+           # Intel C++
+           with_gnu_ld=yes
+           # version 8.0 and above of icpc choke on multiply defined symbols
+           # if we add $predep_objects and $postdep_objects, however 7.1 and
+           # earlier do not add the objects themselves.
+           case `$CC -V 2>&1` in
+             *"Version 7."*)
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+               ;;
+             *)  # Version 8.0 or newer
+               tmp_idyn=
+               case $host_cpu in
+                 ia64*) tmp_idyn=' -i_dynamic';;
+               esac
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+               ;;
+           esac
+           _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+           ;;
+          pgCC* | pgcpp*)
+            # Portland Group C++ compiler
+           case `$CC -V` in
+           *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+             _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+               compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+             _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+               $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+               $RANLIB $oldlib'
+             _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+               $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+               rm -rf $tpldir~
+               $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+               $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+             ;;
+           *) # Version 6 and above use weak symbols
+             _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+             ;;
+           esac
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test  -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+            ;;
+         cxx*)
+           # Compaq C++
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+           runpath_var=LD_RUN_PATH
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+           ;;
+         xl* | mpixl* | bgxl*)
+           # IBM XL 8.0 on PPC, with GNU ld
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+           if test "x$supports_anon_versioning" = xyes; then
+             _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+               cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+               echo "local: *; };" >> $output_objdir/$libname.ver~
+               $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+           fi
+           ;;
+         *)
+           case `$CC -V 2>&1 | sed 5q` in
+           *Sun\ C*)
+             # Sun C++ 5.9
+             _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+             _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+             _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+             _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+             # Not sure whether something based on
+             # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+             # would be better.
+             output_verbose_link_cmd='func_echo_all'
+
+             # Archives containing C++ object files must be created using
+             # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+             # necessary to make sure instantiated templates are included
+             # in the archive.
+             _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+             ;;
+           esac
+           ;;
+       esac
+       ;;
+
+      lynxos*)
+        # FIXME: insert proper C++ library support
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      m88k*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      mvs*)
+        case $cc_basename in
+          cxx*)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+         *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+       esac
+       ;;
+
+      netbsd*)
+        if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+         _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+         wlarc=
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       fi
+       # Workaround some broken pre-1.5 toolchains
+       output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+       ;;
+
+      *nto* | *qnx*)
+        _LT_TAGVAR(ld_shlibs, $1)=yes
+       ;;
+
+      openbsd2*)
+        # C++ shared libraries are fairly broken
+       _LT_TAGVAR(ld_shlibs, $1)=no
+       ;;
+
+      openbsd*)
+       if test -f /usr/libexec/ld.so; then
+         _LT_TAGVAR(hardcode_direct, $1)=yes
+         _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+         _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+         if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+           _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+           _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+         fi
+         output_verbose_link_cmd=func_echo_all
+       else
+         _LT_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+
+      osf3* | osf4* | osf5*)
+        case $cc_basename in
+          KCC*)
+           # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+           # KCC will only create a shared library if the output file
+           # ends with ".so" (or ".sl" for HP-UX), so rename the library
+           # to its proper name (with version) after linking.
+           _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Archives containing C++ object files must be created using
+           # the KAI C++ compiler.
+           case $host in
+             osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+             *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+           esac
+           ;;
+          RCC*)
+           # Rational C++ 2.4.1
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          cxx*)
+           case $host in
+             osf3*)
+               _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+               _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+               ;;
+             *)
+               _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+                 echo "-hidden">> $lib.exp~
+                 $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp  `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
+                 $RM $lib.exp'
+               _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+               ;;
+           esac
+
+           _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           #
+           # There doesn't appear to be a way to prevent this compiler from
+           # explicitly linking system object files so we need to strip them
+           # from the output so that they don't get included in the library
+           # dependencies.
+           output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+           ;;
+         *)
+           if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+             _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+             case $host in
+               osf3*)
+                 _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+                 ;;
+               *)
+                 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+                 ;;
+             esac
+
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+             _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+             # Commands to make compiler produce verbose output that lists
+             # what "hidden" libraries, object files and flags are used when
+             # linking a shared library.
+             output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+           else
+             # FIXME: insert proper C++ library support
+             _LT_TAGVAR(ld_shlibs, $1)=no
+           fi
+           ;;
+        esac
+        ;;
+
+      psos*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      sunos4*)
+        case $cc_basename in
+          CC*)
+           # Sun C++ 4.x
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          lcc*)
+           # Lucid
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      solaris*)
+        case $cc_basename in
+          CC* | sunCC*)
+           # Sun C++ 4.2, 5.x and Centerline C++
+            _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+           _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+           _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag}  -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+             $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+           _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+           _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+           case $host_os in
+             solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+             *)
+               # The compiler driver will combine and reorder linker options,
+               # but understands `-z linker_flag'.
+               # Supported since Solaris 2.6 (maybe 2.5.1?)
+               _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+               ;;
+           esac
+           _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+           output_verbose_link_cmd='func_echo_all'
+
+           # Archives containing C++ object files must be created using
+           # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+           # necessary to make sure instantiated templates are included
+           # in the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+           ;;
+          gcx*)
+           # Green Hills C++ Compiler
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+           # The C++ compiler must be used to create the archive.
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+           ;;
+          *)
+           # GNU C++ compiler with Solaris linker
+           if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+             _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+             if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+               _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                 $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+               # Commands to make compiler produce verbose output that lists
+               # what "hidden" libraries, object files and flags are used when
+               # linking a shared library.
+               output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+             else
+               # g++ 2.7 appears to require `-G' NOT `-shared' on this
+               # platform.
+               _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+               _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+                 $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+               # Commands to make compiler produce verbose output that lists
+               # what "hidden" libraries, object files and flags are used when
+               # linking a shared library.
+               output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+             fi
+
+             _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+             case $host_os in
+               solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+               *)
+                 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+                 ;;
+             esac
+           fi
+           ;;
+        esac
+        ;;
+
+    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+      _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+      _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+      _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+
+      case $cc_basename in
+        CC*)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+      esac
+      ;;
+
+      sysv5* | sco3.2v5* | sco5v6*)
+       # Note: We can NOT use -z defs as we might desire, because we do not
+       # link with -lc, and that would cause any symbols used from libc to
+       # always be unresolved, which means just about no library would
+       # ever link correctly.  If we're not using GNU ld we use -z text
+       # though, which does catch some bad symbols but isn't as heavy-handed
+       # as -z defs.
+       _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+       _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+       _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+       _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+       _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+       _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+       _LT_TAGVAR(link_all_deplibs, $1)=yes
+       _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+       runpath_var='LD_RUN_PATH'
+
+       case $cc_basename in
+          CC*)
+           _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+             '"$_LT_TAGVAR(old_archive_cmds, $1)"
+           _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+             '"$_LT_TAGVAR(reload_cmds, $1)"
+           ;;
+         *)
+           _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+           ;;
+       esac
+      ;;
+
+      tandem*)
+        case $cc_basename in
+          NCC*)
+           # NonStop-UX NCC 3.20
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+          *)
+           # FIXME: insert proper C++ library support
+           _LT_TAGVAR(ld_shlibs, $1)=no
+           ;;
+        esac
+        ;;
+
+      vxworks*)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+
+      *)
+        # FIXME: insert proper C++ library support
+        _LT_TAGVAR(ld_shlibs, $1)=no
+        ;;
+    esac
+
+    AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+    test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+    _LT_TAGVAR(GCC, $1)="$GXX"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+  LDCXX=$LD
+  LD=$lt_save_LD
+  GCC=$lt_save_GCC
+  with_gnu_ld=$lt_save_with_gnu_ld
+  lt_cv_path_LDCXX=$lt_cv_path_LD
+  lt_cv_path_LD=$lt_save_path_LD
+  lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+  lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+  case ${2} in
+  .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+  *)  func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+  esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+      subroutine foo
+      implicit none
+      integer a
+      a=0
+      return
+      end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  for p in `eval "$output_verbose_link_cmd"`; do
+    case ${prev}${p} in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" ||
+          test $p = "-R"; then
+        prev=$p
+        continue
+       fi
+
+       # Expand the sysroot to ease extracting the directories later.
+       if test -z "$prev"; then
+         case $p in
+         -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+         -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+         -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+         esac
+       fi
+       case $p in
+       =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+       esac
+       if test "$pre_test_object_deps_done" = no; then
+        case ${prev} in
+        -L | -R)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+            _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+          else
+            _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+          _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+        else
+          _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+        fi
+       fi
+       prev=
+       ;;
+
+    *.lto.$objext) ;; # Ignore GCC LTO objects
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+          _LT_TAGVAR(predep_objects, $1)="$p"
+        else
+          _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+        fi
+       else
+        if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+          _LT_TAGVAR(postdep_objects, $1)="$p"
+        else
+          _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+  # Interix 3.5 installs completely hosed .la files for C++, so rather than
+  # hack all around it, let's just trust "g++" to DTRT.
+  _LT_TAGVAR(predep_objects,$1)=
+  _LT_TAGVAR(postdep_objects,$1)=
+  _LT_TAGVAR(postdeps,$1)=
+  ;;
+
+linux*)
+  case `$CC -V 2>&1 | sed 5q` in
+  *Sun\ C*)
+    # Sun C++ 5.9
+
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+
+solaris*)
+  case $cc_basename in
+  CC* | sunCC*)
+    # The more standards-conforming stlport4 library is
+    # incompatible with the Cstd library. Avoid specifying
+    # it if it's in CXXFLAGS. Ignore libCrun as
+    # -library=stlport4 depends on it.
+    case " $CXX $CXXFLAGS " in
+    *" -library=stlport4 "*)
+      solaris_use_stlport4=yes
+      ;;
+    esac
+
+    # Adding this requires a known-good setup of shared libraries for
+    # Sun compiler versions before 5.6, else PIC objects from an old
+    # archive will be linked into the output, leading to subtle bugs.
+    if test "$solaris_use_stlport4" != yes; then
+      _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+    fi
+    ;;
+  esac
+  ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+    [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+    [Dependencies to place before and after the objects being linked to
+    create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+    [The library search path used internally by the compiler when linking
+    a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test "X$F77" = "Xno"; then
+  _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${F77-"f77"}
+  CFLAGS=$FFLAGS
+  compiler=$CC
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+  GCC=$G77
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+       if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+         test "$enable_shared" = yes && enable_static=no
+       fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$G77"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC="$lt_save_CC"
+  CFLAGS="$lt_save_CFLAGS"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test "X$FC" = "Xno"; then
+  _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working.  Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+  # Code to be used in simple compile tests
+  lt_simple_compile_test_code="\
+      subroutine t
+      return
+      end
+"
+
+  # Code to be used in simple link tests
+  lt_simple_link_test_code="\
+      program t
+      end
+"
+
+  # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+  _LT_TAG_COMPILER
+
+  # save warnings/boilerplate of simple test code
+  _LT_COMPILER_BOILERPLATE
+  _LT_LINKER_BOILERPLATE
+
+  # Allow CC to be a program name with arguments.
+  lt_save_CC="$CC"
+  lt_save_GCC=$GCC
+  lt_save_CFLAGS=$CFLAGS
+  CC=${FC-"f95"}
+  CFLAGS=$FCFLAGS
+  compiler=$CC
+  GCC=$ac_cv_fc_compiler_gnu
+
+  _LT_TAGVAR(compiler, $1)=$CC
+  _LT_CC_BASENAME([$compiler])
+
+  if test -n "$compiler"; then
+    AC_MSG_CHECKING([if libtool supports shared libraries])
+    AC_MSG_RESULT([$can_build_shared])
+
+    AC_MSG_CHECKING([whether to build shared libraries])
+    test "$can_build_shared" = "no" && enable_shared=no
+
+    # On AIX, shared libraries and static libraries use the same namespace, and
+    # are all built from PIC.
+    case $host_os in
+      aix3*)
+        test "$enable_shared" = yes && enable_static=no
+        if test -n "$RANLIB"; then
+          archive_cmds="$archive_cmds~\$RANLIB \$lib"
+          postinstall_cmds='$RANLIB $lib'
+        fi
+        ;;
+      aix[[4-9]]*)
+       if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+         test "$enable_shared" = yes && enable_static=no
+       fi
+        ;;
+    esac
+    AC_MSG_RESULT([$enable_shared])
+
+    AC_MSG_CHECKING([whether to build static libraries])
+    # Make sure either enable_shared or enable_static is yes.
+    test "$enable_shared" = yes || enable_static=yes
+    AC_MSG_RESULT([$enable_static])
+
+    _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+    _LT_TAGVAR(LD, $1)="$LD"
+
+    ## CAVEAT EMPTOR:
+    ## There is no encapsulation within the following macros, do not change
+    ## the running order or otherwise move them around unless you know exactly
+    ## what you are doing...
+    _LT_SYS_HIDDEN_LIBDEPS($1)
+    _LT_COMPILER_PIC($1)
+    _LT_COMPILER_C_O($1)
+    _LT_COMPILER_FILE_LOCKS($1)
+    _LT_LINKER_SHLIBS($1)
+    _LT_SYS_DYNAMIC_LINKER($1)
+    _LT_LINKER_HARDCODE_LIBPATH($1)
+
+    _LT_CONFIG($1)
+  fi # test -n "$compiler"
+
+  GCC=$lt_save_GCC
+  CC=$lt_save_CC
+  CFLAGS=$lt_save_CFLAGS
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+  _LT_COMPILER_NO_RTTI($1)
+  _LT_COMPILER_PIC($1)
+  _LT_COMPILER_C_O($1)
+  _LT_COMPILER_FILE_LOCKS($1)
+  _LT_LINKER_SHLIBS($1)
+  _LT_LINKER_HARDCODE_LIBPATH($1)
+
+  _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined.  These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+  :
+  _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+  [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+    [AC_CHECK_TOOL(GCJ, gcj,)
+      test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+      AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+    [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && continue
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+  test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+      = c,a/b,b/c, \
+    && eval 'test $(( 1 + 1 )) -eq 2 \
+    && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+  && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+    >/dev/null 2>&1 \
+  && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  lt_unset=unset
+else
+  lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  lt_SP2NL='tr \040 \012'
+  lt_NL2SP='tr \015\012 \040\040'
+  ;;
+ *) # EBCDIC based system
+  lt_SP2NL='tr \100 \n'
+  lt_NL2SP='tr \r\n \100\100'
+  ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY)
+# ------------------------------------------------------
+# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and
+# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY.
+m4_defun([_LT_PROG_FUNCTION_REPLACE],
+[dnl {
+sed -e '/^$1 ()$/,/^} # $1 /c\
+$1 ()\
+{\
+m4_bpatsubsts([$2], [$], [\\], [^\([    ]\)], [\\\1])
+} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \
+  && mv -f "$cfgfile.tmp" "$cfgfile" \
+    || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+])
+
+
+# _LT_PROG_REPLACE_SHELLFNS
+# -------------------------
+# Replace existing portable implementations of several shell functions with
+# equivalent extended shell implementations where those features are available..
+m4_defun([_LT_PROG_REPLACE_SHELLFNS],
+[if test x"$xsi_shell" = xyes; then
+  _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac])
+
+  _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl
+    func_basename_result="${1##*/}"])
+
+  _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl
+    case ${1} in
+      */*) func_dirname_result="${1%/*}${2}" ;;
+      *  ) func_dirname_result="${3}" ;;
+    esac
+    func_basename_result="${1##*/}"])
+
+  _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl
+    # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+    # positional parameters, so assign one to ordinary parameter first.
+    func_stripname_result=${3}
+    func_stripname_result=${func_stripname_result#"${1}"}
+    func_stripname_result=${func_stripname_result%"${2}"}])
+
+  _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl
+    func_split_long_opt_name=${1%%=*}
+    func_split_long_opt_arg=${1#*=}])
+
+  _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl
+    func_split_short_opt_arg=${1#??}
+    func_split_short_opt_name=${1%"$func_split_short_opt_arg"}])
+
+  _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl
+    case ${1} in
+      *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+      *)    func_lo2o_result=${1} ;;
+    esac])
+
+  _LT_PROG_FUNCTION_REPLACE([func_xform], [    func_xform_result=${1%.*}.lo])
+
+  _LT_PROG_FUNCTION_REPLACE([func_arith], [    func_arith_result=$(( $[*] ))])
+
+  _LT_PROG_FUNCTION_REPLACE([func_len], [    func_len_result=${#1}])
+fi
+
+if test x"$lt_shell_append" = xyes; then
+  _LT_PROG_FUNCTION_REPLACE([func_append], [    eval "${1}+=\\${2}"])
+
+  _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl
+    func_quote_for_eval "${2}"
+dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \
+    eval "${1}+=\\\\ \\$func_quote_for_eval_result"])
+
+  # Save a `func_append' function call where possible by direct use of '+='
+  sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+else
+  # Save a `func_append' function call even when '+=' is not available
+  sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+    && mv -f "$cfgfile.tmp" "$cfgfile" \
+      || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+  test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+  AC_MSG_WARN([Unable to substitute extended shell functions in $ofile])
+fi
+])
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine which file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path).  These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+        ;;
+    esac
+    ;;
+  *-*-cygwin* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+        ;;
+      *-*-cygwin* )
+        lt_cv_to_host_file_cmd=func_convert_file_noop
+        ;;
+      * ) # otherwise, assume *nix
+        lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+        ;;
+    esac
+    ;;
+  * ) # unhandled hosts (and "normal" native builds)
+    lt_cv_to_host_file_cmd=func_convert_file_noop
+    ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+         [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+  *-*-mingw* )
+    case $build in
+      *-*-mingw* ) # actually msys
+        lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+        ;;
+    esac
+    ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+         [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
diff --git a/libltdl/m4/ltdl.m4 b/libltdl/m4/ltdl.m4
new file mode 100644 (file)
index 0000000..1ef84a5
--- /dev/null
@@ -0,0 +1,817 @@
+# ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*-
+#
+#   Copyright (C) 1999-2006, 2007, 2008, 2011 Free Software Foundation, Inc.
+#   Written by Thomas Tanner, 1999
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 18 LTDL_INIT
+
+# LT_CONFIG_LTDL_DIR(DIRECTORY, [LTDL-MODE])
+# ------------------------------------------
+# DIRECTORY contains the libltdl sources.  It is okay to call this
+# function multiple times, as long as the same DIRECTORY is always given.
+AC_DEFUN([LT_CONFIG_LTDL_DIR],
+[AC_BEFORE([$0], [LTDL_INIT])
+_$0($*)
+])# LT_CONFIG_LTDL_DIR
+
+# We break this out into a separate macro, so that we can call it safely
+# internally without being caught accidentally by the sed scan in libtoolize.
+m4_defun([_LT_CONFIG_LTDL_DIR],
+[dnl remove trailing slashes
+m4_pushdef([_ARG_DIR], m4_bpatsubst([$1], [/*$]))
+m4_case(_LTDL_DIR,
+       [], [dnl only set lt_ltdl_dir if _ARG_DIR is not simply `.'
+            m4_if(_ARG_DIR, [.],
+                    [],
+                [m4_define([_LTDL_DIR], _ARG_DIR)
+                 _LT_SHELL_INIT([lt_ltdl_dir=']_ARG_DIR['])])],
+    [m4_if(_ARG_DIR, _LTDL_DIR,
+           [],
+       [m4_fatal([multiple libltdl directories: `]_LTDL_DIR[', `]_ARG_DIR['])])])
+m4_popdef([_ARG_DIR])
+])# _LT_CONFIG_LTDL_DIR
+
+# Initialise:
+m4_define([_LTDL_DIR], [])
+
+
+# _LT_BUILD_PREFIX
+# ----------------
+# If Autoconf is new enough, expand to `${top_build_prefix}', otherwise
+# to `${top_builddir}/'.
+m4_define([_LT_BUILD_PREFIX],
+[m4_ifdef([AC_AUTOCONF_VERSION],
+   [m4_if(m4_version_compare(m4_defn([AC_AUTOCONF_VERSION]), [2.62]),
+         [-1], [m4_ifdef([_AC_HAVE_TOP_BUILD_PREFIX],
+                         [${top_build_prefix}],
+                         [${top_builddir}/])],
+         [${top_build_prefix}])],
+   [${top_builddir}/])[]dnl
+])
+
+
+# LTDL_CONVENIENCE
+# ----------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called here.  LIBLTDL will be prefixed with
+# '${top_build_prefix}' if available, otherwise with '${top_builddir}/',
+# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
+# quotes!).  If your package is not flat and you're not using automake,
+# define top_build_prefix, top_builddir, and top_srcdir appropriately
+# in your Makefiles.
+AC_DEFUN([LTDL_CONVENIENCE],
+[AC_BEFORE([$0], [LTDL_INIT])dnl
+dnl Although the argument is deprecated and no longer documented,
+dnl LTDL_CONVENIENCE used to take a DIRECTORY orgument, if we have one
+dnl here make sure it is the same as any other declaration of libltdl's
+dnl location!  This also ensures lt_ltdl_dir is set when configure.ac is
+dnl not yet using an explicit LT_CONFIG_LTDL_DIR.
+m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl
+_$0()
+])# LTDL_CONVENIENCE
+
+# AC_LIBLTDL_CONVENIENCE accepted a directory argument in older libtools,
+# now we have LT_CONFIG_LTDL_DIR:
+AU_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])])
+_LTDL_CONVENIENCE])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [])
+
+
+# _LTDL_CONVENIENCE
+# -----------------
+# Code shared by LTDL_CONVENIENCE and LTDL_INIT([convenience]).
+m4_defun([_LTDL_CONVENIENCE],
+[case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+esac
+LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdlc.la"
+LTDLDEPS=$LIBLTDL
+LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}"
+
+AC_SUBST([LIBLTDL])
+AC_SUBST([LTDLDEPS])
+AC_SUBST([LTDLINCL])
+
+# For backwards non-gettext consistent compatibility...
+INCLTDL="$LTDLINCL"
+AC_SUBST([INCLTDL])
+])# _LTDL_CONVENIENCE
+
+
+# LTDL_INSTALLABLE
+# ----------------
+# sets LIBLTDL to the link flags for the libltdl installable library
+# and LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments.  Note that
+# AC_CONFIG_SUBDIRS is not called from here.  If an installed libltdl
+# is not found, LIBLTDL will be prefixed with '${top_build_prefix}' if
+# available, otherwise with '${top_builddir}/', and LTDLINCL will be
+# prefixed with '${top_srcdir}/' (note the single quotes!).  If your
+# package is not flat and you're not using automake, define top_build_prefix,
+# top_builddir, and top_srcdir appropriately in your Makefiles.
+# In the future, this macro may have to be called after LT_INIT.
+AC_DEFUN([LTDL_INSTALLABLE],
+[AC_BEFORE([$0], [LTDL_INIT])dnl
+dnl Although the argument is deprecated and no longer documented,
+dnl LTDL_INSTALLABLE used to take a DIRECTORY orgument, if we have one
+dnl here make sure it is the same as any other declaration of libltdl's
+dnl location!  This also ensures lt_ltdl_dir is set when configure.ac is
+dnl not yet using an explicit LT_CONFIG_LTDL_DIR.
+m4_ifval([$1], [_LT_CONFIG_LTDL_DIR([$1])])dnl
+_$0()
+])# LTDL_INSTALLABLE
+
+# AC_LIBLTDL_INSTALLABLE accepted a directory argument in older libtools,
+# now we have LT_CONFIG_LTDL_DIR:
+AU_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[_LT_CONFIG_LTDL_DIR([m4_default([$1], [libltdl])])
+_LTDL_INSTALLABLE])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [])
+
+
+# _LTDL_INSTALLABLE
+# -----------------
+# Code shared by LTDL_INSTALLABLE and LTDL_INIT([installable]).
+m4_defun([_LTDL_INSTALLABLE],
+[if test -f $prefix/lib/libltdl.la; then
+  lt_save_LDFLAGS="$LDFLAGS"
+  LDFLAGS="-L$prefix/lib $LDFLAGS"
+  AC_CHECK_LIB([ltdl], [lt_dlinit], [lt_lib_ltdl=yes])
+  LDFLAGS="$lt_save_LDFLAGS"
+  if test x"${lt_lib_ltdl-no}" = xyes; then
+    if test x"$enable_ltdl_install" != xyes; then
+      # Don't overwrite $prefix/lib/libltdl.la without --enable-ltdl-install
+      AC_MSG_WARN([not overwriting libltdl at $prefix, force with `--enable-ltdl-install'])
+      enable_ltdl_install=no
+    fi
+  elif test x"$enable_ltdl_install" = xno; then
+    AC_MSG_WARN([libltdl not installed, but installation disabled])
+  fi
+fi
+
+# If configure.ac declared an installable ltdl, and the user didn't override
+# with --disable-ltdl-install, we will install the shipped libltdl.
+case $enable_ltdl_install in
+  no) ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+      LIBLTDL="-lltdl"
+      LTDLDEPS=
+      LTDLINCL=
+      ;;
+  *)  enable_ltdl_install=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-install"
+      LIBLTDL='_LT_BUILD_PREFIX'"${lt_ltdl_dir+$lt_ltdl_dir/}libltdl.la"
+      LTDLDEPS=$LIBLTDL
+      LTDLINCL='-I${top_srcdir}'"${lt_ltdl_dir+/$lt_ltdl_dir}"
+      ;;
+esac
+
+AC_SUBST([LIBLTDL])
+AC_SUBST([LTDLDEPS])
+AC_SUBST([LTDLINCL])
+
+# For backwards non-gettext consistent compatibility...
+INCLTDL="$LTDLINCL"
+AC_SUBST([INCLTDL])
+])# LTDL_INSTALLABLE
+
+
+# _LTDL_MODE_DISPATCH
+# -------------------
+m4_define([_LTDL_MODE_DISPATCH],
+[dnl If _LTDL_DIR is `.', then we are configuring libltdl itself:
+m4_if(_LTDL_DIR, [],
+       [],
+    dnl if _LTDL_MODE was not set already, the default value is `subproject':
+    [m4_case(m4_default(_LTDL_MODE, [subproject]),
+         [subproject], [AC_CONFIG_SUBDIRS(_LTDL_DIR)
+                         _LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"])],
+         [nonrecursive], [_LT_SHELL_INIT([lt_dlopen_dir="$lt_ltdl_dir"; lt_libobj_prefix="$lt_ltdl_dir/"])],
+         [recursive], [],
+       [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])])dnl
+dnl Be careful not to expand twice:
+m4_define([$0], [])
+])# _LTDL_MODE_DISPATCH
+
+
+# _LT_LIBOBJ(MODULE_NAME)
+# -----------------------
+# Like AC_LIBOBJ, except that MODULE_NAME goes into _LT_LIBOBJS instead
+# of into LIBOBJS.
+AC_DEFUN([_LT_LIBOBJ], [
+  m4_pattern_allow([^_LT_LIBOBJS$])
+  _LT_LIBOBJS="$_LT_LIBOBJS $1.$ac_objext"
+])# _LT_LIBOBJS
+
+
+# LTDL_INIT([OPTIONS])
+# --------------------
+# Clients of libltdl can use this macro to allow the installer to
+# choose between a shipped copy of the ltdl sources or a preinstalled
+# version of the library.  If the shipped ltdl sources are not in a
+# subdirectory named libltdl, the directory name must be given by
+# LT_CONFIG_LTDL_DIR.
+AC_DEFUN([LTDL_INIT],
+[dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+dnl We need to keep our own list of libobjs separate from our parent project,
+dnl and the easiest way to do that is redefine the AC_LIBOBJs macro while
+dnl we look for our own LIBOBJs.
+m4_pushdef([AC_LIBOBJ], m4_defn([_LT_LIBOBJ]))
+m4_pushdef([AC_LIBSOURCES])
+
+dnl If not otherwise defined, default to the 1.5.x compatible subproject mode:
+m4_if(_LTDL_MODE, [],
+        [m4_define([_LTDL_MODE], m4_default([$2], [subproject]))
+        m4_if([-1], [m4_bregexp(_LTDL_MODE, [\(subproject\|\(non\)?recursive\)])],
+                [m4_fatal([unknown libltdl mode: ]_LTDL_MODE)])])
+
+AC_ARG_WITH([included_ltdl],
+    [AS_HELP_STRING([--with-included-ltdl],
+                    [use the GNU ltdl sources included here])])
+
+if test "x$with_included_ltdl" != xyes; then
+  # We are not being forced to use the included libltdl sources, so
+  # decide whether there is a useful installed version we can use.
+  AC_CHECK_HEADER([ltdl.h],
+      [AC_CHECK_DECL([lt_dlinterface_register],
+          [AC_CHECK_LIB([ltdl], [lt_dladvise_preload],
+              [with_included_ltdl=no],
+              [with_included_ltdl=yes])],
+          [with_included_ltdl=yes],
+          [AC_INCLUDES_DEFAULT
+           #include <ltdl.h>])],
+      [with_included_ltdl=yes],
+      [AC_INCLUDES_DEFAULT]
+  )
+fi
+
+dnl If neither LT_CONFIG_LTDL_DIR, LTDL_CONVENIENCE nor LTDL_INSTALLABLE
+dnl was called yet, then for old times' sake, we assume libltdl is in an
+dnl eponymous directory:
+AC_PROVIDE_IFELSE([LT_CONFIG_LTDL_DIR], [], [_LT_CONFIG_LTDL_DIR([libltdl])])
+
+AC_ARG_WITH([ltdl_include],
+    [AS_HELP_STRING([--with-ltdl-include=DIR],
+                    [use the ltdl headers installed in DIR])])
+
+if test -n "$with_ltdl_include"; then
+  if test -f "$with_ltdl_include/ltdl.h"; then :
+  else
+    AC_MSG_ERROR([invalid ltdl include directory: `$with_ltdl_include'])
+  fi
+else
+  with_ltdl_include=no
+fi
+
+AC_ARG_WITH([ltdl_lib],
+    [AS_HELP_STRING([--with-ltdl-lib=DIR],
+                    [use the libltdl.la installed in DIR])])
+
+if test -n "$with_ltdl_lib"; then
+  if test -f "$with_ltdl_lib/libltdl.la"; then :
+  else
+    AC_MSG_ERROR([invalid ltdl library directory: `$with_ltdl_lib'])
+  fi
+else
+  with_ltdl_lib=no
+fi
+
+case ,$with_included_ltdl,$with_ltdl_include,$with_ltdl_lib, in
+  ,yes,no,no,)
+       m4_case(m4_default(_LTDL_TYPE, [convenience]),
+           [convenience], [_LTDL_CONVENIENCE],
+           [installable], [_LTDL_INSTALLABLE],
+         [m4_fatal([unknown libltdl build type: ]_LTDL_TYPE)])
+       ;;
+  ,no,no,no,)
+       # If the included ltdl is not to be used, then use the
+       # preinstalled libltdl we found.
+       AC_DEFINE([HAVE_LTDL], [1],
+         [Define this if a modern libltdl is already installed])
+       LIBLTDL=-lltdl
+       LTDLDEPS=
+       LTDLINCL=
+       ;;
+  ,no*,no,*)
+       AC_MSG_ERROR([`--with-ltdl-include' and `--with-ltdl-lib' options must be used together])
+       ;;
+  *)   with_included_ltdl=no
+       LIBLTDL="-L$with_ltdl_lib -lltdl"
+       LTDLDEPS=
+       LTDLINCL="-I$with_ltdl_include"
+       ;;
+esac
+INCLTDL="$LTDLINCL"
+
+# Report our decision...
+AC_MSG_CHECKING([where to find libltdl headers])
+AC_MSG_RESULT([$LTDLINCL])
+AC_MSG_CHECKING([where to find libltdl library])
+AC_MSG_RESULT([$LIBLTDL])
+
+_LTDL_SETUP
+
+dnl restore autoconf definition.
+m4_popdef([AC_LIBOBJ])
+m4_popdef([AC_LIBSOURCES])
+
+AC_CONFIG_COMMANDS_PRE([
+    _ltdl_libobjs=
+    _ltdl_ltlibobjs=
+    if test -n "$_LT_LIBOBJS"; then
+      # Remove the extension.
+      _lt_sed_drop_objext='s/\.o$//;s/\.obj$//'
+      for i in `for i in $_LT_LIBOBJS; do echo "$i"; done | sed "$_lt_sed_drop_objext" | sort -u`; do
+        _ltdl_libobjs="$_ltdl_libobjs $lt_libobj_prefix$i.$ac_objext"
+        _ltdl_ltlibobjs="$_ltdl_ltlibobjs $lt_libobj_prefix$i.lo"
+      done
+    fi
+    AC_SUBST([ltdl_LIBOBJS], [$_ltdl_libobjs])
+    AC_SUBST([ltdl_LTLIBOBJS], [$_ltdl_ltlibobjs])
+])
+
+# Only expand once:
+m4_define([LTDL_INIT])
+])# LTDL_INIT
+
+# Old names:
+AU_DEFUN([AC_LIB_LTDL], [LTDL_INIT($@)])
+AU_DEFUN([AC_WITH_LTDL], [LTDL_INIT($@)])
+AU_DEFUN([LT_WITH_LTDL], [LTDL_INIT($@)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIB_LTDL], [])
+dnl AC_DEFUN([AC_WITH_LTDL], [])
+dnl AC_DEFUN([LT_WITH_LTDL], [])
+
+
+# _LTDL_SETUP
+# -----------
+# Perform all the checks necessary for compilation of the ltdl objects
+#  -- including compiler checks and header checks.  This is a public
+# interface  mainly for the benefit of libltdl's own configure.ac, most
+# other users should call LTDL_INIT instead.
+AC_DEFUN([_LTDL_SETUP],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_SYS_MODULE_EXT])dnl
+AC_REQUIRE([LT_SYS_MODULE_PATH])dnl
+AC_REQUIRE([LT_SYS_DLSEARCH_PATH])dnl
+AC_REQUIRE([LT_LIB_DLLOAD])dnl
+AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl
+AC_REQUIRE([LT_FUNC_DLSYM_USCORE])dnl
+AC_REQUIRE([LT_SYS_DLOPEN_DEPLIBS])dnl
+AC_REQUIRE([gl_FUNC_ARGZ])dnl
+
+m4_require([_LT_CHECK_OBJDIR])dnl
+m4_require([_LT_HEADER_DLFCN])dnl
+m4_require([_LT_CHECK_DLPREOPEN])dnl
+m4_require([_LT_DECL_SED])dnl
+
+dnl Don't require this, or it will be expanded earlier than the code
+dnl that sets the variables it relies on:
+_LT_ENABLE_INSTALL
+
+dnl _LTDL_MODE specific code must be called at least once:
+_LTDL_MODE_DISPATCH
+
+# In order that ltdl.c can compile, find out the first AC_CONFIG_HEADERS
+# the user used.  This is so that ltdl.h can pick up the parent projects
+# config.h file, The first file in AC_CONFIG_HEADERS must contain the
+# definitions required by ltdl.c.
+# FIXME: Remove use of undocumented AC_LIST_HEADERS (2.59 compatibility).
+AC_CONFIG_COMMANDS_PRE([dnl
+m4_pattern_allow([^LT_CONFIG_H$])dnl
+m4_ifset([AH_HEADER],
+    [LT_CONFIG_H=AH_HEADER],
+    [m4_ifset([AC_LIST_HEADERS],
+           [LT_CONFIG_H=`echo "AC_LIST_HEADERS" | $SED 's,^[[      ]]*,,;s,[[ :]].*$,,'`],
+       [])])])
+AC_SUBST([LT_CONFIG_H])
+
+AC_CHECK_HEADERS([unistd.h dl.h sys/dl.h dld.h mach-o/dyld.h dirent.h],
+       [], [], [AC_INCLUDES_DEFAULT])
+
+AC_CHECK_FUNCS([closedir opendir readdir], [], [AC_LIBOBJ([lt__dirent])])
+AC_CHECK_FUNCS([strlcat strlcpy], [], [AC_LIBOBJ([lt__strl])])
+
+m4_pattern_allow([LT_LIBEXT])dnl
+AC_DEFINE_UNQUOTED([LT_LIBEXT],["$libext"],[The archive extension])
+
+name=
+eval "lt_libprefix=\"$libname_spec\""
+m4_pattern_allow([LT_LIBPREFIX])dnl
+AC_DEFINE_UNQUOTED([LT_LIBPREFIX],["$lt_libprefix"],[The archive prefix])
+
+name=ltdl
+eval "LTDLOPEN=\"$libname_spec\""
+AC_SUBST([LTDLOPEN])
+])# _LTDL_SETUP
+
+
+# _LT_ENABLE_INSTALL
+# ------------------
+m4_define([_LT_ENABLE_INSTALL],
+[AC_ARG_ENABLE([ltdl-install],
+    [AS_HELP_STRING([--enable-ltdl-install], [install libltdl])])
+
+case ,${enable_ltdl_install},${enable_ltdl_convenience} in
+  *yes*) ;;
+  *) enable_ltdl_convenience=yes ;;
+esac
+
+m4_ifdef([AM_CONDITIONAL],
+[AM_CONDITIONAL(INSTALL_LTDL, test x"${enable_ltdl_install-no}" != xno)
+ AM_CONDITIONAL(CONVENIENCE_LTDL, test x"${enable_ltdl_convenience-no}" != xno)])
+])# _LT_ENABLE_INSTALL
+
+
+# LT_SYS_DLOPEN_DEPLIBS
+# ---------------------
+AC_DEFUN([LT_SYS_DLOPEN_DEPLIBS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_CACHE_CHECK([whether deplibs are loaded by dlopen],
+  [lt_cv_sys_dlopen_deplibs],
+  [# PORTME does your system automatically load deplibs for dlopen?
+  # or its logical equivalent (e.g. shl_load for HP-UX < 11)
+  # For now, we just catch OSes we know something about -- in the
+  # future, we'll try test this programmatically.
+  lt_cv_sys_dlopen_deplibs=unknown
+  case $host_os in
+  aix3*|aix4.1.*|aix4.2.*)
+    # Unknown whether this is true for these versions of AIX, but
+    # we want this `case' here to explicitly catch those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  aix[[4-9]]*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  amigaos*)
+    case $host_cpu in
+    powerpc)
+      lt_cv_sys_dlopen_deplibs=no
+      ;;
+    esac
+    ;;
+  darwin*)
+    # Assuming the user has installed a libdl from somewhere, this is true
+    # If you are looking for one http://www.opendarwin.org/projects/dlcompat
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  freebsd* | dragonfly*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  gnu* | linux* | k*bsd*-gnu | kopensolaris*-gnu)
+    # GNU and its variants, using gnu ld.so (Glibc)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  hpux10*|hpux11*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  interix*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  irix[[12345]]*|irix6.[[01]]*)
+    # Catch all versions of IRIX before 6.2, and indicate that we don't
+    # know how it worked for any of those versions.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  irix*)
+    # The case above catches anything before 6.2, and it's known that
+    # at 6.2 and later dlopen does load deplibs.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  netbsd* | netbsdelf*-gnu)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  openbsd*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  osf[[1234]]*)
+    # dlopen did load deplibs (at least at 4.x), but until the 5.x series,
+    # it did *not* use an RPATH in a shared library to find objects the
+    # library depends on, so we explicitly say `no'.
+    lt_cv_sys_dlopen_deplibs=no
+    ;;
+  osf5.0|osf5.0a|osf5.1)
+    # dlopen *does* load deplibs and with the right loader patch applied
+    # it even uses RPATH in a shared library to search for shared objects
+    # that the library depends on, but there's no easy way to know if that
+    # patch is installed.  Since this is the case, all we can really
+    # say is unknown -- it depends on the patch being installed.  If
+    # it is, this changes to `yes'.  Without it, it would be `no'.
+    lt_cv_sys_dlopen_deplibs=unknown
+    ;;
+  osf*)
+    # the two cases above should catch all versions of osf <= 5.1.  Read
+    # the comments above for what we know about them.
+    # At > 5.1, deplibs are loaded *and* any RPATH in a shared library
+    # is used to find them so we can finally say `yes'.
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  qnx*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  solaris*)
+    lt_cv_sys_dlopen_deplibs=yes
+    ;;
+  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+    libltdl_cv_sys_dlopen_deplibs=yes
+    ;;
+  esac
+  ])
+if test "$lt_cv_sys_dlopen_deplibs" != yes; then
+ AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1],
+    [Define if the OS needs help to load dependent libraries for dlopen().])
+fi
+])# LT_SYS_DLOPEN_DEPLIBS
+
+# Old name:
+AU_ALIAS([AC_LTDL_SYS_DLOPEN_DEPLIBS], [LT_SYS_DLOPEN_DEPLIBS])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], [])
+
+
+# LT_SYS_MODULE_EXT
+# -----------------
+AC_DEFUN([LT_SYS_MODULE_EXT],
+[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl
+AC_CACHE_CHECK([which extension is used for runtime loadable modules],
+  [libltdl_cv_shlibext],
+[
+module=yes
+eval libltdl_cv_shlibext=$shrext_cmds
+module=no
+eval libltdl_cv_shrext=$shrext_cmds
+  ])
+if test -n "$libltdl_cv_shlibext"; then
+  m4_pattern_allow([LT_MODULE_EXT])dnl
+  AC_DEFINE_UNQUOTED([LT_MODULE_EXT], ["$libltdl_cv_shlibext"],
+    [Define to the extension used for runtime loadable modules, say, ".so".])
+fi
+if test "$libltdl_cv_shrext" != "$libltdl_cv_shlibext"; then
+  m4_pattern_allow([LT_SHARED_EXT])dnl
+  AC_DEFINE_UNQUOTED([LT_SHARED_EXT], ["$libltdl_cv_shrext"],
+    [Define to the shared library suffix, say, ".dylib".])
+fi
+])# LT_SYS_MODULE_EXT
+
+# Old name:
+AU_ALIAS([AC_LTDL_SHLIBEXT], [LT_SYS_MODULE_EXT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SHLIBEXT], [])
+
+
+# LT_SYS_MODULE_PATH
+# ------------------
+AC_DEFUN([LT_SYS_MODULE_PATH],
+[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl
+AC_CACHE_CHECK([which variable specifies run-time module search path],
+  [lt_cv_module_path_var], [lt_cv_module_path_var="$shlibpath_var"])
+if test -n "$lt_cv_module_path_var"; then
+  m4_pattern_allow([LT_MODULE_PATH_VAR])dnl
+  AC_DEFINE_UNQUOTED([LT_MODULE_PATH_VAR], ["$lt_cv_module_path_var"],
+    [Define to the name of the environment variable that determines the run-time module search path.])
+fi
+])# LT_SYS_MODULE_PATH
+
+# Old name:
+AU_ALIAS([AC_LTDL_SHLIBPATH], [LT_SYS_MODULE_PATH])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SHLIBPATH], [])
+
+
+# LT_SYS_DLSEARCH_PATH
+# --------------------
+AC_DEFUN([LT_SYS_DLSEARCH_PATH],
+[m4_require([_LT_SYS_DYNAMIC_LINKER])dnl
+AC_CACHE_CHECK([for the default library search path],
+  [lt_cv_sys_dlsearch_path],
+  [lt_cv_sys_dlsearch_path="$sys_lib_dlsearch_path_spec"])
+if test -n "$lt_cv_sys_dlsearch_path"; then
+  sys_dlsearch_path=
+  for dir in $lt_cv_sys_dlsearch_path; do
+    if test -z "$sys_dlsearch_path"; then
+      sys_dlsearch_path="$dir"
+    else
+      sys_dlsearch_path="$sys_dlsearch_path$PATH_SEPARATOR$dir"
+    fi
+  done
+  m4_pattern_allow([LT_DLSEARCH_PATH])dnl
+  AC_DEFINE_UNQUOTED([LT_DLSEARCH_PATH], ["$sys_dlsearch_path"],
+    [Define to the system default library search path.])
+fi
+])# LT_SYS_DLSEARCH_PATH
+
+# Old name:
+AU_ALIAS([AC_LTDL_SYSSEARCHPATH], [LT_SYS_DLSEARCH_PATH])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SYSSEARCHPATH], [])
+
+
+# _LT_CHECK_DLPREOPEN
+# -------------------
+m4_defun([_LT_CHECK_DLPREOPEN],
+[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen],
+  [libltdl_cv_preloaded_symbols],
+  [if test -n "$lt_cv_sys_global_symbol_pipe"; then
+    libltdl_cv_preloaded_symbols=yes
+  else
+    libltdl_cv_preloaded_symbols=no
+  fi
+  ])
+if test x"$libltdl_cv_preloaded_symbols" = xyes; then
+  AC_DEFINE([HAVE_PRELOADED_SYMBOLS], [1],
+    [Define if libtool can extract symbol lists from object files.])
+fi
+])# _LT_CHECK_DLPREOPEN
+
+
+# LT_LIB_DLLOAD
+# -------------
+AC_DEFUN([LT_LIB_DLLOAD],
+[m4_pattern_allow([^LT_DLLOADERS$])
+LT_DLLOADERS=
+AC_SUBST([LT_DLLOADERS])
+
+AC_LANG_PUSH([C])
+
+LIBADD_DLOPEN=
+AC_SEARCH_LIBS([dlopen], [dl],
+       [AC_DEFINE([HAVE_LIBDL], [1],
+                  [Define if you have the libdl library or equivalent.])
+       if test "$ac_cv_search_dlopen" != "none required" ; then
+         LIBADD_DLOPEN="-ldl"
+       fi
+       libltdl_cv_lib_dl_dlopen="yes"
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"],
+    [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_DLFCN_H
+#  include <dlfcn.h>
+#endif
+    ]], [[dlopen(0, 0);]])],
+           [AC_DEFINE([HAVE_LIBDL], [1],
+                      [Define if you have the libdl library or equivalent.])
+           libltdl_cv_func_dlopen="yes"
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"],
+       [AC_CHECK_LIB([svld], [dlopen],
+               [AC_DEFINE([HAVE_LIBDL], [1],
+                        [Define if you have the libdl library or equivalent.])
+               LIBADD_DLOPEN="-lsvld" libltdl_cv_func_dlopen="yes"
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dlopen.la"])])])
+if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes
+then
+  lt_save_LIBS="$LIBS"
+  LIBS="$LIBS $LIBADD_DLOPEN"
+  AC_CHECK_FUNCS([dlerror])
+  LIBS="$lt_save_LIBS"
+fi
+AC_SUBST([LIBADD_DLOPEN])
+
+LIBADD_SHL_LOAD=
+AC_CHECK_FUNC([shl_load],
+       [AC_DEFINE([HAVE_SHL_LOAD], [1],
+                  [Define if you have the shl_load function.])
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"],
+    [AC_CHECK_LIB([dld], [shl_load],
+           [AC_DEFINE([HAVE_SHL_LOAD], [1],
+                      [Define if you have the shl_load function.])
+           LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}shl_load.la"
+           LIBADD_SHL_LOAD="-ldld"])])
+AC_SUBST([LIBADD_SHL_LOAD])
+
+case $host_os in
+darwin[[1567]].*)
+# We only want this for pre-Mac OS X 10.4.
+  AC_CHECK_FUNC([_dyld_func_lookup],
+       [AC_DEFINE([HAVE_DYLD], [1],
+                  [Define if you have the _dyld_func_lookup function.])
+       LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dyld.la"])
+  ;;
+beos*)
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}load_add_on.la"
+  ;;
+cygwin* | mingw* | os2* | pw32*)
+  AC_CHECK_DECLS([cygwin_conv_path], [], [], [[#include <sys/cygwin.h>]])
+  LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}loadlibrary.la"
+  ;;
+esac
+
+AC_CHECK_LIB([dld], [dld_link],
+       [AC_DEFINE([HAVE_DLD], [1],
+                  [Define if you have the GNU dld library.])
+               LT_DLLOADERS="$LT_DLLOADERS ${lt_dlopen_dir+$lt_dlopen_dir/}dld_link.la"])
+AC_SUBST([LIBADD_DLD_LINK])
+
+m4_pattern_allow([^LT_DLPREOPEN$])
+LT_DLPREOPEN=
+if test -n "$LT_DLLOADERS"
+then
+  for lt_loader in $LT_DLLOADERS; do
+    LT_DLPREOPEN="$LT_DLPREOPEN-dlpreopen $lt_loader "
+  done
+  AC_DEFINE([HAVE_LIBDLLOADER], [1],
+            [Define if libdlloader will be built on this platform])
+fi
+AC_SUBST([LT_DLPREOPEN])
+
+dnl This isn't used anymore, but set it for backwards compatibility
+LIBADD_DL="$LIBADD_DLOPEN $LIBADD_SHL_LOAD"
+AC_SUBST([LIBADD_DL])
+
+AC_LANG_POP
+])# LT_LIB_DLLOAD
+
+# Old name:
+AU_ALIAS([AC_LTDL_DLLIB], [LT_LIB_DLLOAD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_DLLIB], [])
+
+
+# LT_SYS_SYMBOL_USCORE
+# --------------------
+# does the compiler prefix global symbols with an underscore?
+AC_DEFUN([LT_SYS_SYMBOL_USCORE],
+[m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+AC_CACHE_CHECK([for _ prefix in compiled symbols],
+  [lt_cv_sys_symbol_underscore],
+  [lt_cv_sys_symbol_underscore=no
+  cat > conftest.$ac_ext <<_LT_EOF
+void nm_test_func(){}
+int main(){nm_test_func;return 0;}
+_LT_EOF
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    ac_nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) && test -s "$ac_nlist"; then
+      # See whether the symbols have a leading underscore.
+      if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then
+        lt_cv_sys_symbol_underscore=yes
+      else
+        if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then
+         :
+        else
+         echo "configure: cannot find nm_test_func in $ac_nlist" >&AS_MESSAGE_LOG_FD
+        fi
+      fi
+    else
+      echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.c >&AS_MESSAGE_LOG_FD
+  fi
+  rm -rf conftest*
+  ])
+  sys_symbol_underscore=$lt_cv_sys_symbol_underscore
+  AC_SUBST([sys_symbol_underscore])
+])# LT_SYS_SYMBOL_USCORE
+
+# Old name:
+AU_ALIAS([AC_LTDL_SYMBOL_USCORE], [LT_SYS_SYMBOL_USCORE])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_SYMBOL_USCORE], [])
+
+
+# LT_FUNC_DLSYM_USCORE
+# --------------------
+AC_DEFUN([LT_FUNC_DLSYM_USCORE],
+[AC_REQUIRE([LT_SYS_SYMBOL_USCORE])dnl
+if test x"$lt_cv_sys_symbol_underscore" = xyes; then
+  if test x"$libltdl_cv_func_dlopen" = xyes ||
+     test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then
+       AC_CACHE_CHECK([whether we have to add an underscore for dlsym],
+         [libltdl_cv_need_uscore],
+         [libltdl_cv_need_uscore=unknown
+          save_LIBS="$LIBS"
+          LIBS="$LIBS $LIBADD_DLOPEN"
+         _LT_TRY_DLOPEN_SELF(
+           [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes],
+           [],                          [libltdl_cv_need_uscore=cross])
+         LIBS="$save_LIBS"
+       ])
+  fi
+fi
+
+if test x"$libltdl_cv_need_uscore" = xyes; then
+  AC_DEFINE([NEED_USCORE], [1],
+    [Define if dlsym() requires a leading underscore in symbol names.])
+fi
+])# LT_FUNC_DLSYM_USCORE
+
+# Old name:
+AU_ALIAS([AC_LTDL_DLSYM_USCORE], [LT_FUNC_DLSYM_USCORE])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LTDL_DLSYM_USCORE], [])
diff --git a/libltdl/m4/ltoptions.m4 b/libltdl/m4/ltoptions.m4
new file mode 100644 (file)
index 0000000..5d9acd8
--- /dev/null
@@ -0,0 +1,384 @@
+# Helper functions for option handling.                    -*- Autoconf -*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
+#   Inc.
+#   Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 7 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it.  Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+        _LT_MANGLE_DEFUN([$1], [$2]),
+    [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+           [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+                     [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME.  If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+    [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+  dnl
+  dnl Simply set some default values (i.e off) if boolean options were not
+  dnl specified:
+  _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+  ])
+  _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+  ])
+  dnl
+  dnl If no reference was made to various pairs of opposing options, then
+  dnl we run the default mode handler for the pair.  For example, if neither
+  dnl `shared' nor `disable-shared' was passed, we enable building of shared
+  dnl archives by default:
+  _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+  _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+  _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+                  [_LT_ENABLE_FAST_INSTALL])
+  ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS],      [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+    [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+       [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+    _LT_DECL([build_libtool_libs], [enable_shared], [0],
+       [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+    [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+       [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+    _LT_DECL([build_old_libs], [enable_static], [0],
+       [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+    [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+        [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+    [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+       [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [lt_p=${PACKAGE-default}
+    case $withval in
+    yes|no) pic_mode=$withval ;;
+    *)
+      pic_mode=default
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for lt_pkg in $withval; do
+       IFS="$lt_save_ifs"
+       if test "X$lt_pkg" = "X$lt_p"; then
+         pic_mode=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+                [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+                [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+                [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+                [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+                [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/libltdl/m4/ltsugar.m4 b/libltdl/m4/ltsugar.m4
new file mode 100644 (file)
index 0000000..9000a05
--- /dev/null
@@ -0,0 +1,123 @@
+# ltsugar.m4 -- libtool m4 base layer.                         -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+       [$#], [2], [[$2]],
+       [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+       [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+       [$#], 1, [],
+       [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+          m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn.  Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+       [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+            [m4_foreach([_Lt_suffix],
+               ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+       [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+         [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+                [lt_append([$1], [$2], [$3])$4],
+                [$5])],
+         [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+       m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+    m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+       [$5],
+    [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+  [lt_join(m4_quote(m4_default([$4], [[, ]])),
+           lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+                     [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/libltdl/m4/ltversion.m4 b/libltdl/m4/ltversion.m4
new file mode 100644 (file)
index 0000000..07a8602
--- /dev/null
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers                      -*- Autoconf -*-
+#
+#   Copyright (C) 2004 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 3337 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.2])
+m4_define([LT_PACKAGE_REVISION], [1.3337])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.2'
+macro_revision='1.3337'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/libltdl/m4/lt~obsolete.m4 b/libltdl/m4/lt~obsolete.m4
new file mode 100644 (file)
index 0000000..c573da9
--- /dev/null
@@ -0,0 +1,98 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
+#
+#   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+#   Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick.  It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else.  This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION],  [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP],             [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH],        [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT],         [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX],    [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN],           [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR],             [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL],    [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN],           [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER],       [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK],               [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE],        [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF],    [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O],    [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR],         [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR],            [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP],  [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC],             [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU],            [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG],    [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD],   [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP],          [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED],            [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME],           [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE],  [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE],    [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL],          [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP],          [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN],                [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER],     [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG],          [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL],   [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX],           [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77],           [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ],           [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG],  [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG],      [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG],    [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG],    [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG],        [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG],    [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG],     [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG],         [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C],       [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS],        [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP],                [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS],        [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH],   [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77],              [AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC],               [AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX],              [AC_DEFUN([_LT_PROG_CXX])])
diff --git a/libltdl/slist.c b/libltdl/slist.c
new file mode 100644 (file)
index 0000000..25906a4
--- /dev/null
@@ -0,0 +1,379 @@
+/* slist.c -- generalised singly linked lists
+
+   Copyright (C) 2000, 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Written by Gary V. Vaughan, 2000
+
+   NOTE: The canonical source of this file is maintained with the
+   GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
+
+GNU Libltdl is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+As a special exception to the GNU Lesser General Public License,
+if you distribute this file as part of a program or library that
+is built using GNU Libtool, you may include this file under the
+same distribution terms that you use for the rest of that program.
+
+GNU Libltdl 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
+copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
+or obtained by writing to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <assert.h>
+
+#include "slist.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+static SList * slist_sort_merge    (SList *left, SList *right,
+                                    SListCompare *compare, void *userdata);
+
+
+/* Call DELETE repeatedly on each element of HEAD.
+
+   CAVEAT: If you call this when HEAD is the start of a list of boxed
+           items, you must remember that each item passed back to your
+          DELETE function will be a boxed item that must be slist_unbox()ed
+          before operating on its contents.
+
+   e.g. void boxed_delete (void *item) { item_free (slist_unbox (item)); }
+        ...
+         slist = slist_delete (slist, boxed_delete);
+       ...
+*/
+SList *
+slist_delete (SList *head, void (*delete_fct) (void *item))
+{
+  assert (delete_fct);
+
+  while (head)
+    {
+      SList *next = head->next;
+      (*delete_fct) (head);
+      head = next;
+    }
+
+  return 0;
+}
+
+/* Call FIND repeatedly with MATCHDATA and each item of *PHEAD, until
+   FIND returns non-NULL, or the list is exhausted.  If a match is found
+   the matching item is destructively removed from *PHEAD, and the value
+   returned by the matching call to FIND is returned.
+
+   CAVEAT: To avoid memory leaks, unless you already have the address of
+           the stale item, you should probably return that from FIND if
+          it makes a successful match.  Don't forget to slist_unbox()
+          every item in a boxed list before operating on its contents.   */
+SList *
+slist_remove (SList **phead, SListCallback *find, void *matchdata)
+{
+  SList *stale = 0;
+  void *result = 0;
+
+  assert (find);
+
+  if (!phead || !*phead)
+    return 0;
+
+  /* Does the head of the passed list match? */
+  result = (*find) (*phead, matchdata);
+  if (result)
+    {
+      stale = *phead;
+      *phead = stale->next;
+    }
+  /* what about the rest of the elements? */
+  else
+    {
+      SList *head;
+      for (head = *phead; head->next; head = head->next)
+       {
+         result = (*find) (head->next, matchdata);
+         if (result)
+           {
+             stale             = head->next;
+             head->next        = stale->next;
+             break;
+           }
+       }
+    }
+
+  return (SList *) result;
+}
+
+/* Call FIND repeatedly with each element of SLIST and MATCHDATA, until
+   FIND returns non-NULL, or the list is exhausted.  If a match is found
+   the value returned by the matching call to FIND is returned. */
+void *
+slist_find (SList *slist, SListCallback *find, void *matchdata)
+{
+  void *result = 0;
+
+  assert (find);
+
+  for (; slist; slist = slist->next)
+    {
+      result = (*find) (slist, matchdata);
+      if (result)
+       break;
+    }
+
+  return result;
+}
+
+/* Return a single list, composed by destructively concatenating the
+   items in HEAD and TAIL.  The values of HEAD and TAIL are undefined
+   after calling this function.
+
+   CAVEAT: Don't mix boxed and unboxed items in a single list.
+
+   e.g.  slist1 = slist_concat (slist1, slist2);  */
+SList *
+slist_concat (SList *head, SList *tail)
+{
+  SList *last;
+
+  if (!head)
+    {
+      return tail;
+    }
+
+  last = head;
+  while (last->next)
+    last = last->next;
+
+  last->next = tail;
+
+  return head;
+}
+
+/* Return a single list, composed by destructively appending all of
+   the items in SLIST to ITEM.  The values of ITEM and SLIST are undefined
+   after calling this function.
+
+   CAVEAT:  Don't mix boxed and unboxed items in a single list.
+
+   e.g.  slist1 = slist_cons (slist_box (data), slist1);  */
+SList *
+slist_cons (SList *item, SList *slist)
+{
+  if (!item)
+    {
+      return slist;
+    }
+
+  assert (!item->next);
+
+  item->next = slist;
+  return item;
+}
+
+/* Return a list starting at the second item of SLIST.  */
+SList *
+slist_tail (SList *slist)
+{
+  return slist ? slist->next : NULL;
+}
+
+/* Return a list starting at the Nth item of SLIST.  If SLIST is less
+   than N items long, NULL is returned.  Just to be confusing, list items
+   are counted from 1, to get the 2nd element of slist:
+
+   e.g. shared_list = slist_nth (slist, 2);  */
+SList *
+slist_nth (SList *slist, size_t n)
+{
+  for (;n > 1 && slist; n--)
+    slist = slist->next;
+
+  return slist;
+}
+
+/* Return the number of items in SLIST.  We start counting from 1, so
+   the length of a list with no items is 0, and so on.  */
+size_t
+slist_length (SList *slist)
+{
+  size_t n;
+
+  for (n = 0; slist; ++n)
+    slist = slist->next;
+
+  return n;
+}
+
+/* Destructively reverse the order of items in SLIST.  The value of SLIST
+   is undefined after calling this function.
+
+  CAVEAT: You must store the result of this function, or you might not
+          be able to get all the items except the first one back again.
+
+  e.g.    slist = slist_reverse (slist);  */
+SList *
+slist_reverse (SList *slist)
+{
+  SList *result = 0;
+  SList *next;
+
+  while (slist)
+    {
+      next             = slist->next;
+      slist->next      = result;
+      result           = slist;
+      slist            = next;
+    }
+
+  return result;
+}
+
+/* Call FOREACH once for each item in SLIST, passing both the item and
+   USERDATA on each call. */
+void *
+slist_foreach (SList *slist, SListCallback *foreach, void *userdata)
+{
+  void *result = 0;
+
+  assert (foreach);
+
+  while (slist)
+    {
+      SList *next = slist->next;
+      result = (*foreach) (slist, userdata);
+
+      if (result)
+       break;
+
+      slist = next;
+    }
+
+  return result;
+}
+
+/* Destructively merge the items of two ordered lists LEFT and RIGHT,
+   returning a single sorted list containing the items of both --  Part of
+   the quicksort algorithm.  The values of LEFT and RIGHT are undefined
+   after calling this function.
+
+   At each iteration, add another item to the merged list by taking the
+   lowest valued item from the head of either LEFT or RIGHT, determined
+   by passing those items and USERDATA to COMPARE.  COMPARE should return
+   less than 0 if the head of LEFT has the lower value, greater than 0 if
+   the head of RIGHT has the lower value, otherwise 0.  */
+static SList *
+slist_sort_merge (SList *left, SList *right, SListCompare *compare,
+                 void *userdata)
+{
+  SList merged, *insert;
+
+  insert = &merged;
+
+  while (left && right)
+    {
+      if ((*compare) (left, right, userdata) <= 0)
+       {
+         insert = insert->next = left;
+         left = left->next;
+       }
+      else
+       {
+         insert = insert->next = right;
+         right = right->next;
+       }
+    }
+
+  insert->next = left ? left : right;
+
+  return merged.next;
+}
+
+/* Perform a destructive quicksort on the items in SLIST, by repeatedly
+   calling COMPARE with a pair of items from SLIST along with USERDATA
+   at every iteration.  COMPARE is a function as defined above for
+   slist_sort_merge().  The value of SLIST is undefined after calling
+   this function.
+
+   e.g.  slist = slist_sort (slist, compare, 0);  */
+SList *
+slist_sort (SList *slist, SListCompare *compare, void *userdata)
+{
+  SList *left, *right;
+
+  if (!slist)
+    return slist;
+
+  /* Be sure that LEFT and RIGHT never contain the same item.  */
+  left = slist;
+  right = slist->next;
+
+  if (!right)
+    return left;
+
+  /* Skip two items with RIGHT and one with SLIST, until RIGHT falls off
+     the end.  SLIST must be about half way along.  */
+  while (right && (right = right->next))
+    {
+      if (!right || !(right = right->next))
+       break;
+      slist = slist->next;
+    }
+  right = slist->next;
+  slist->next = 0;
+
+  /* Sort LEFT and RIGHT, then merge the two.  */
+  return slist_sort_merge (slist_sort (left, compare, userdata),
+                          slist_sort (right, compare, userdata),
+                          compare, userdata);
+}
+
+
+/* Aside from using the functions above to manage chained structures of
+   any type that has a NEXT pointer as its first field, SLISTs can
+   be comprised of boxed items.  The boxes are chained together in
+   that case, so there is no need for a NEXT field in the item proper.
+   Some care must be taken to slist_box and slist_unbox each item in
+   a boxed list at the appropriate points to avoid leaking the memory
+   used for the boxes.  It us usually a very bad idea to mix boxed and
+   non-boxed items in a single list.  */
+
+/* Return a `boxed' freshly mallocated 1 element list containing
+   USERDATA.  */
+SList *
+slist_box (const void *userdata)
+{
+  SList *item = (SList *) malloc (sizeof *item);
+
+  if (item)
+    {
+      item->next     = 0;
+      item->userdata = userdata;
+    }
+
+  return item;
+}
+
+/* Return the contents of a `boxed' ITEM, recycling the box itself.  */
+void *
+slist_unbox (SList *item)
+{
+  void *userdata = 0;
+
+  if (item)
+    {
+      /* Strip the const, because responsibility for this memory
+        passes to the caller on return.  */
+      userdata = (void *) item->userdata;
+      free (item);
+    }
+
+  return userdata;
+}
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100755 (executable)
index 0000000..7ed280b
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,8413 @@
+# Generated from ltmain.m4sh.
+
+# ltmain.sh (GNU libtool) 2.2.6b
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions.  There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Usage: $progname [OPTION]... [MODE-ARG]...
+#
+# Provide generalized library-building support services.
+#
+#     --config             show all configuration variables
+#     --debug              enable verbose shell tracing
+# -n, --dry-run            display commands without modifying any files
+#     --features           display basic configuration information and exit
+#     --mode=MODE          use operation mode MODE
+#     --preserve-dup-deps  don't remove duplicate dependency libraries
+#     --quiet, --silent    don't print informational messages
+#     --tag=TAG            use configuration variables from tag TAG
+# -v, --verbose            print informational messages (default)
+#     --version            print version information
+# -h, --help               print short or long help message
+#
+# MODE must be one of the following:
+#
+#       clean              remove files from the build directory
+#       compile            compile a source file into a libtool object
+#       execute            automatically set library path, then run a program
+#       finish             complete the installation of libtool libraries
+#       install            install libraries or executables
+#       link               create a library or an executable
+#       uninstall          remove libraries from an installed directory
+#
+# MODE-ARGS vary depending on the MODE.
+# Try `$progname --help --mode=MODE' for a more detailed description of MODE.
+#
+# When reporting a bug, please describe a test case to reproduce it and
+# include the following information:
+#
+#       host-triplet:  $host
+#       shell:         $SHELL
+#       compiler:              $LTCC
+#       compiler flags:                $LTCFLAGS
+#       linker:                $LD (gnu? $with_gnu_ld)
+#       $progname:             (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu1
+#       automake:              $automake_version
+#       autoconf:              $autoconf_version
+#
+# Report bugs to <bug-libtool@gnu.org>.
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION="2.2.6b Debian-2.2.6b-2ubuntu1"
+TIMESTAMP=""
+package_revision=1.3017
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# NLS nuisances: We save the old values to restore during execute mode.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+lt_user_locale=
+lt_safe_locale=
+for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+          save_$lt_var=\$$lt_var
+          $lt_var=C
+         export $lt_var
+         lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\"
+         lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\"
+       fi"
+done
+
+$lt_unset CDPATH
+
+
+
+
+
+: ${CP="cp -f"}
+: ${ECHO="echo"}
+: ${EGREP="/bin/grep -E"}
+: ${FGREP="/bin/grep -F"}
+: ${GREP="/bin/grep"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SED="/bin/sed"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+: ${Xsed="$SED -e 1s/^X//"}
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63  # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77     # $? = 77 is used to indicate a skipped test to automake.
+
+exit_status=$EXIT_SUCCESS
+
+# Make sure IFS has a sensible default
+lt_nl='
+'
+IFS="  $lt_nl"
+
+dirname="s,/[^/]*$,,"
+basename="s,^.*/,,"
+
+# func_dirname_and_basename file append nondir_replacement
+# perform func_basename and func_dirname in a single function
+# call:
+#   dirname:  Compute the dirname of FILE.  If nonempty,
+#             add APPEND to the result, otherwise set result
+#             to NONDIR_REPLACEMENT.
+#             value returned in "$func_dirname_result"
+#   basename: Compute filename of FILE.
+#             value retuned in "$func_basename_result"
+# Implementation must be kept synchronized with func_dirname
+# and func_basename. For efficiency, we do not delegate to
+# those functions but instead duplicate the functionality here.
+func_dirname_and_basename ()
+{
+  # Extract subdirectory from the argument.
+  func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
+  if test "X$func_dirname_result" = "X${1}"; then
+    func_dirname_result="${3}"
+  else
+    func_dirname_result="$func_dirname_result${2}"
+  fi
+  func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
+}
+
+# Generated shell functions inserted here.
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+# In the unlikely event $progname began with a '-', it would play havoc with
+# func_echo (imagine progname=-n), so we prepend ./ in that case:
+func_dirname_and_basename "$progpath"
+progname=$func_basename_result
+case $progname in
+  -*) progname=./$progname ;;
+esac
+
+# Make sure we have an absolute path for reexecution:
+case $progpath in
+  [\\/]*|[A-Za-z]:\\*) ;;
+  *[\\/]*)
+     progdir=$func_dirname_result
+     progdir=`cd "$progdir" && pwd`
+     progpath="$progdir/$progname"
+     ;;
+  *)
+     save_IFS="$IFS"
+     IFS=:
+     for progdir in $PATH; do
+       IFS="$save_IFS"
+       test -x "$progdir/$progname" && break
+     done
+     IFS="$save_IFS"
+     test -n "$progdir" || progdir=`pwd`
+     progpath="$progdir/$progname"
+     ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([`"$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Re-`\' parameter expansions in output of double_quote_subst that were
+# `\'-ed in input to the same.  If an odd number of `\' preceded a '$'
+# in input to double_quote_subst, that '$' was protected from expansion.
+# Since each input `\' is now two `\'s, look for any number of runs of
+# four `\'s followed by two `\'s and then a '$'.  `\' that '$'.
+bs='\\'
+bs2='\\\\'
+bs4='\\\\\\\\'
+dollar='\$'
+sed_double_backslash="\
+  s/$bs4/&\\
+/g
+  s/^$bs2$dollar/$bs&/
+  s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g
+  s/\n//g"
+
+# Standard options:
+opt_dry_run=false
+opt_help=false
+opt_quiet=false
+opt_verbose=false
+opt_warning=:
+
+# func_echo arg...
+# Echo program name prefixed message, along with the current mode
+# name if it has been set yet.
+func_echo ()
+{
+    $ECHO "$progname${mode+: }$mode: $*"
+}
+
+# func_verbose arg...
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+    $opt_verbose && func_echo ${1+"$@"}
+
+    # A bug in bash halts the script if the last line of a function
+    # fails when set -e is in force, so we need another command to
+    # work around that:
+    :
+}
+
+# func_error arg...
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+    $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2
+}
+
+# func_warning arg...
+# Echo program name prefixed warning message to standard error.
+func_warning ()
+{
+    $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2
+
+    # bash bug again:
+    :
+}
+
+# func_fatal_error arg...
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+    func_error ${1+"$@"}
+    exit $EXIT_FAILURE
+}
+
+# func_fatal_help arg...
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+    func_error ${1+"$@"}
+    func_fatal_error "$help"
+}
+help="Try \`$progname --help' for more information."  ## default
+
+
+# func_grep expression filename
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+    $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_mkdir_p directory-path
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+    my_directory_path="$1"
+    my_dir_list=
+
+    if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then
+
+      # Protect directory names starting with `-'
+      case $my_directory_path in
+        -*) my_directory_path="./$my_directory_path" ;;
+      esac
+
+      # While some portion of DIR does not yet exist...
+      while test ! -d "$my_directory_path"; do
+        # ...make a list in topmost first order.  Use a colon delimited
+       # list incase some portion of path contains whitespace.
+        my_dir_list="$my_directory_path:$my_dir_list"
+
+        # If the last portion added has no slash in it, the list is done
+        case $my_directory_path in */*) ;; *) break ;; esac
+
+        # ...otherwise throw away the child directory and loop
+        my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"`
+      done
+      my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'`
+
+      save_mkdir_p_IFS="$IFS"; IFS=':'
+      for my_dir in $my_dir_list; do
+       IFS="$save_mkdir_p_IFS"
+        # mkdir can fail with a `File exist' error if two processes
+        # try to create one of the directories concurrently.  Don't
+        # stop in that case!
+        $MKDIR "$my_dir" 2>/dev/null || :
+      done
+      IFS="$save_mkdir_p_IFS"
+
+      # Bail out if we (or some other process) failed to create a directory.
+      test -d "$my_directory_path" || \
+        func_fatal_error "Failed to create \`$1'"
+    fi
+}
+
+
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$opt_dry_run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+        # Failing that, at least try and use $RANDOM to avoid a race
+        my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+        save_mktempdir_umask=`umask`
+        umask 0077
+        $MKDIR "$my_tmpdir"
+        umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || \
+        func_fatal_error "cannot create temporary directory \`$my_tmpdir'"
+    fi
+
+    $ECHO "X$my_tmpdir" | $Xsed
+}
+
+
+# func_quote_for_eval arg
+# Aesthetically quote ARG to be evaled later.
+# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT
+# is double-quoted, suitable for a subsequent eval, whereas
+# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters
+# which are still active within double quotes backslashified.
+func_quote_for_eval ()
+{
+    case $1 in
+      *[\\\`\"\$]*)
+       func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;;
+      *)
+        func_quote_for_eval_unquoted_result="$1" ;;
+    esac
+
+    case $func_quote_for_eval_unquoted_result in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting, command substitution and and variable
+      # expansion for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+        func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\""
+        ;;
+      *)
+        func_quote_for_eval_result="$func_quote_for_eval_unquoted_result"
+    esac
+}
+
+
+# func_quote_for_expand arg
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+    case $1 in
+      *[\\\`\"]*)
+       my_arg=`$ECHO "X$1" | $Xsed \
+           -e "$double_quote_subst" -e "$sed_double_backslash"` ;;
+      *)
+        my_arg="$1" ;;
+    esac
+
+    case $my_arg in
+      # Double-quote args containing shell metacharacters to delay
+      # word splitting and command substitution for a subsequent eval.
+      # Many Bourne shells cannot handle close brackets correctly
+      # in scan sets, so we specify it separately.
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+        my_arg="\"$my_arg\""
+        ;;
+    esac
+
+    func_quote_for_expand_result="$my_arg"
+}
+
+
+# func_show_eval cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$my_cmd"
+      my_status=$?
+      if test "$my_status" -eq 0; then :; else
+       eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+# func_show_eval_locale cmd [fail_exp]
+# Unless opt_silent is true, then output CMD.  Then, if opt_dryrun is
+# not true, evaluate CMD.  If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.  Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+    my_cmd="$1"
+    my_fail_exp="${2-:}"
+
+    ${opt_silent-false} || {
+      func_quote_for_expand "$my_cmd"
+      eval "func_echo $func_quote_for_expand_result"
+    }
+
+    if ${opt_dry_run-false}; then :; else
+      eval "$lt_user_locale
+           $my_cmd"
+      my_status=$?
+      eval "$lt_safe_locale"
+      if test "$my_status" -eq 0; then :; else
+       eval "(exit $my_status); $my_fail_exp"
+      fi
+    fi
+}
+
+
+
+
+
+# func_version
+# Echo version message to standard output and exit.
+func_version ()
+{
+    $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / {
+        s/^# //
+       s/^# *$//
+        s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/
+        p
+     }' < "$progpath"
+     exit $?
+}
+
+# func_usage
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+    $SED -n '/^# Usage:/,/# -h/ {
+        s/^# //
+       s/^# *$//
+       s/\$progname/'$progname'/
+       p
+    }' < "$progpath"
+    $ECHO
+    $ECHO "run \`$progname --help | more' for full usage"
+    exit $?
+}
+
+# func_help
+# Echo long help message to standard output and exit.
+func_help ()
+{
+    $SED -n '/^# Usage:/,/# Report bugs to/ {
+        s/^# //
+       s/^# *$//
+       s*\$progname*'$progname'*
+       s*\$host*'"$host"'*
+       s*\$SHELL*'"$SHELL"'*
+       s*\$LTCC*'"$LTCC"'*
+       s*\$LTCFLAGS*'"$LTCFLAGS"'*
+       s*\$LD*'"$LD"'*
+       s/\$with_gnu_ld/'"$with_gnu_ld"'/
+       s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/
+       s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/
+       p
+     }' < "$progpath"
+    exit $?
+}
+
+# func_missing_arg argname
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+    func_error "missing argument for $1"
+    exit_cmd=exit
+}
+
+exit_cmd=:
+
+
+
+
+
+# Check that we have a working $ECHO.
+if test "X$1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X$1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
+  # Yippee, $ECHO works!
+  :
+else
+  # Restart under the correct shell, and then maybe $ECHO will work.
+  exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+$*
+EOF
+  exit $EXIT_SUCCESS
+fi
+
+magic="%%%MAGIC variable%%%"
+magic_exe="%%%MAGIC EXE variable%%%"
+
+# Global variables.
+# $mode is unset
+nonopt=
+execute_dlfiles=
+preserve_args=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
+
+opt_dry_run=false
+opt_duplicate_deps=false
+opt_silent=false
+opt_debug=:
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end.  This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+# func_fatal_configuration arg...
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+    func_error ${1+"$@"}
+    func_error "See the $PACKAGE documentation for more information."
+    func_fatal_error "Fatal configuration error."
+}
+
+
+# func_config
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+    re_begincf='^# ### BEGIN LIBTOOL'
+    re_endcf='^# ### END LIBTOOL'
+
+    # Default configuration.
+    $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+    # Now print the configurations for the tags.
+    for tagname in $taglist; do
+      $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+    done
+
+    exit $?
+}
+
+# func_features
+# Display the features supported by this script.
+func_features ()
+{
+    $ECHO "host: $host"
+    if test "$build_libtool_libs" = yes; then
+      $ECHO "enable shared libraries"
+    else
+      $ECHO "disable shared libraries"
+    fi
+    if test "$build_old_libs" = yes; then
+      $ECHO "enable static libraries"
+    else
+      $ECHO "disable static libraries"
+    fi
+
+    exit $?
+}
+
+# func_enable_tag tagname
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag.  We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+  # Global variable:
+  tagname="$1"
+
+  re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+  re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+  sed_extractcf="/$re_begincf/,/$re_endcf/p"
+
+  # Validate tagname.
+  case $tagname in
+    *[!-_A-Za-z0-9,/]*)
+      func_fatal_error "invalid tag name: $tagname"
+      ;;
+  esac
+
+  # Don't test for the "default" C tag, as we know it's
+  # there but not specially marked.
+  case $tagname in
+    CC) ;;
+    *)
+      if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+       taglist="$taglist $tagname"
+
+       # Evaluate the configuration.  Be careful to quote the path
+       # and the sed script, to avoid splitting on whitespace, but
+       # also don't use non-portable quotes within backquotes within
+       # quotes we have to do it in 2 steps:
+       extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+       eval "$extractedcf"
+      else
+       func_error "ignoring unknown tag $tagname"
+      fi
+      ;;
+  esac
+}
+
+# Parse options once, thoroughly.  This comes as soon as possible in
+# the script to make things like `libtool --version' happen quickly.
+{
+
+  # Shorthand for --mode=foo, only valid as the first argument
+  case $1 in
+  clean|clea|cle|cl)
+    shift; set dummy --mode clean ${1+"$@"}; shift
+    ;;
+  compile|compil|compi|comp|com|co|c)
+    shift; set dummy --mode compile ${1+"$@"}; shift
+    ;;
+  execute|execut|execu|exec|exe|ex|e)
+    shift; set dummy --mode execute ${1+"$@"}; shift
+    ;;
+  finish|finis|fini|fin|fi|f)
+    shift; set dummy --mode finish ${1+"$@"}; shift
+    ;;
+  install|instal|insta|inst|ins|in|i)
+    shift; set dummy --mode install ${1+"$@"}; shift
+    ;;
+  link|lin|li|l)
+    shift; set dummy --mode link ${1+"$@"}; shift
+    ;;
+  uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+    shift; set dummy --mode uninstall ${1+"$@"}; shift
+    ;;
+  esac
+
+  # Parse non-mode specific arguments:
+  while test "$#" -gt 0; do
+    opt="$1"
+    shift
+
+    case $opt in
+      --config)                func_config                                     ;;
+
+      --debug)         preserve_args="$preserve_args $opt"
+                       func_echo "enabling shell trace mode"
+                       opt_debug='set -x'
+                       $opt_debug
+                       ;;
+
+      -dlopen)         test "$#" -eq 0 && func_missing_arg "$opt" && break
+                       execute_dlfiles="$execute_dlfiles $1"
+                       shift
+                       ;;
+
+      --dry-run | -n)  opt_dry_run=:                                   ;;
+      --features)       func_features                                  ;;
+      --finish)                mode="finish"                                   ;;
+
+      --mode)          test "$#" -eq 0 && func_missing_arg "$opt" && break
+                       case $1 in
+                         # Valid mode arguments:
+                         clean)        ;;
+                         compile)      ;;
+                         execute)      ;;
+                         finish)       ;;
+                         install)      ;;
+                         link)         ;;
+                         relink)       ;;
+                         uninstall)    ;;
+
+                         # Catch anything else as an error
+                         *) func_error "invalid argument for $opt"
+                            exit_cmd=exit
+                            break
+                            ;;
+                       esac
+
+                       mode="$1"
+                       shift
+                       ;;
+
+      --preserve-dup-deps)
+                       opt_duplicate_deps=:                            ;;
+
+      --quiet|--silent)        preserve_args="$preserve_args $opt"
+                       opt_silent=:
+                       ;;
+
+      --verbose| -v)   preserve_args="$preserve_args $opt"
+                       opt_silent=false
+                       ;;
+
+      --tag)           test "$#" -eq 0 && func_missing_arg "$opt" && break
+                       preserve_args="$preserve_args $opt $1"
+                       func_enable_tag "$1"    # tagname is set here
+                       shift
+                       ;;
+
+      # Separate optargs to long options:
+      -dlopen=*|--mode=*|--tag=*)
+                       func_opt_split "$opt"
+                       set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"}
+                       shift
+                       ;;
+
+      -\?|-h)          func_usage                                      ;;
+      --help)          opt_help=:                                      ;;
+      --version)       func_version                                    ;;
+
+      -*)              func_fatal_help "unrecognized option \`$opt'"   ;;
+
+      *)               nonopt="$opt"
+                       break
+                       ;;
+    esac
+  done
+
+
+  case $host in
+    *cygwin* | *mingw* | *pw32* | *cegcc*)
+      # don't eliminate duplications in $postdeps and $predeps
+      opt_duplicate_compiler_generated_deps=:
+      ;;
+    *)
+      opt_duplicate_compiler_generated_deps=$opt_duplicate_deps
+      ;;
+  esac
+
+  # Having warned about all mis-specified options, bail out if
+  # anything was wrong.
+  $exit_cmd $EXIT_FAILURE
+}
+
+# func_check_version_match
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+  if test "$package_revision" != "$macro_revision"; then
+    if test "$VERSION" != "$macro_version"; then
+      if test -z "$macro_version"; then
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      else
+        cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+      fi
+    else
+      cat >&2 <<_LT_EOF
+$progname: Version mismatch error.  This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+    fi
+
+    exit $EXIT_MISMATCH
+  fi
+}
+
+
+## ----------- ##
+##    Main.    ##
+## ----------- ##
+
+$opt_help || {
+  # Sanity checks first:
+  func_check_version_match
+
+  if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+    func_fatal_configuration "not configured to build any kind of library"
+  fi
+
+  test -z "$mode" && func_fatal_error "error: you must specify a MODE."
+
+
+  # Darwin sucks
+  eval std_shrext=\"$shrext_cmds\"
+
+
+  # Only execute mode is allowed to have -dlopen flags.
+  if test -n "$execute_dlfiles" && test "$mode" != execute; then
+    func_error "unrecognized option \`-dlopen'"
+    $ECHO "$help" 1>&2
+    exit $EXIT_FAILURE
+  fi
+
+  # Change the help message to a mode-specific one.
+  generic_help="$help"
+  help="Try \`$progname --help --mode=$mode' for more information."
+}
+
+
+# func_lalib_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+    test -f "$1" &&
+      $SED -e 4q "$1" 2>/dev/null \
+        | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool `.la' library or `.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs.  To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway.  Works if `file' does not exist.
+func_lalib_unsafe_p ()
+{
+    lalib_p=no
+    if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+       for lalib_p_l in 1 2 3 4
+       do
+           read lalib_p_line
+           case "$lalib_p_line" in
+               \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+           esac
+       done
+       exec 0<&5 5<&-
+    fi
+    test "$lalib_p" = yes
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+    func_lalib_p "$1"
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+    func_ltwrapper_exec_suffix=
+    case $1 in
+    *.exe) ;;
+    *) func_ltwrapper_exec_suffix=.exe ;;
+    esac
+    $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+    func_ltwrapper_scriptname_result=""
+    if func_ltwrapper_executable_p "$1"; then
+       func_dirname_and_basename "$1" "" "."
+       func_stripname '' '.exe' "$func_basename_result"
+       func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper"
+    fi
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+    func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+    $opt_debug
+    save_ifs=$IFS; IFS='~'
+    for cmd in $1; do
+      IFS=$save_ifs
+      eval cmd=\"$cmd\"
+      func_show_eval "$cmd" "${2-:}"
+    done
+    IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)!  Also, sourcing
+# `FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+    $opt_debug
+    case $1 in
+    */* | *\\*)        . "$1" ;;
+    *)         . "./$1" ;;
+    esac
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+    $opt_debug
+    if test -n "$available_tags" && test -z "$tagname"; then
+      CC_quoted=
+      for arg in $CC; do
+        func_quote_for_eval "$arg"
+       CC_quoted="$CC_quoted $func_quote_for_eval_result"
+      done
+      case $@ in
+      # Blanks in the command may have been stripped by the calling shell,
+      # but not from the CC environment variable when configure was run.
+      " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;;
+      # Blanks at the start of $base_compile will cause this to fail
+      # if we don't check for them as well.
+      *)
+       for z in $available_tags; do
+         if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+           # Evaluate the configuration.
+           eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+           CC_quoted=
+           for arg in $CC; do
+             # Double-quote args containing other shell metacharacters.
+             func_quote_for_eval "$arg"
+             CC_quoted="$CC_quoted $func_quote_for_eval_result"
+           done
+           case "$@ " in
+             " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*)
+             # The compiler in the base compile command matches
+             # the one in the tagged configuration.
+             # Assume this is the tagged configuration we want.
+             tagname=$z
+             break
+             ;;
+           esac
+         fi
+       done
+       # If $tagname still isn't set, then no tagged configuration
+       # was found and let the user know that the "--tag" command
+       # line option must be used.
+       if test -z "$tagname"; then
+         func_echo "unable to infer tagged configuration"
+         func_fatal_error "specify a tag with \`--tag'"
+#      else
+#        func_verbose "using $tagname tagged configuration"
+       fi
+       ;;
+      esac
+    fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+    write_libobj=${1}
+    if test "$build_libtool_libs" = yes; then
+      write_lobj=\'${2}\'
+    else
+      write_lobj=none
+    fi
+
+    if test "$build_old_libs" = yes; then
+      write_oldobj=\'${3}\'
+    else
+      write_oldobj=none
+    fi
+
+    $opt_dry_run || {
+      cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+      $MV "${write_libobj}T" "${write_libobj}"
+    }
+}
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+    $opt_debug
+    # Get the compilation command and the source file.
+    base_compile=
+    srcfile="$nonopt"  #  always keep a non-empty value in "srcfile"
+    suppress_opt=yes
+    suppress_output=
+    arg_mode=normal
+    libobj=
+    later=
+    pie_flag=
+
+    for arg
+    do
+      case $arg_mode in
+      arg  )
+       # do not "continue".  Instead, add this to base_compile
+       lastarg="$arg"
+       arg_mode=normal
+       ;;
+
+      target )
+       libobj="$arg"
+       arg_mode=normal
+       continue
+       ;;
+
+      normal )
+       # Accept any command-line options.
+       case $arg in
+       -o)
+         test -n "$libobj" && \
+           func_fatal_error "you cannot specify \`-o' more than once"
+         arg_mode=target
+         continue
+         ;;
+
+       -pie | -fpie | -fPIE)
+          pie_flag="$pie_flag $arg"
+         continue
+         ;;
+
+       -shared | -static | -prefer-pic | -prefer-non-pic)
+         later="$later $arg"
+         continue
+         ;;
+
+       -no-suppress)
+         suppress_opt=no
+         continue
+         ;;
+
+       -Xcompiler)
+         arg_mode=arg  #  the next one goes into the "base_compile" arg list
+         continue      #  The current "srcfile" will either be retained or
+         ;;            #  replaced later.  I would guess that would be a bug.
+
+       -Wc,*)
+         func_stripname '-Wc,' '' "$arg"
+         args=$func_stripname_result
+         lastarg=
+         save_ifs="$IFS"; IFS=','
+         for arg in $args; do
+           IFS="$save_ifs"
+           func_quote_for_eval "$arg"
+           lastarg="$lastarg $func_quote_for_eval_result"
+         done
+         IFS="$save_ifs"
+         func_stripname ' ' '' "$lastarg"
+         lastarg=$func_stripname_result
+
+         # Add the arguments to base_compile.
+         base_compile="$base_compile $lastarg"
+         continue
+         ;;
+
+       *)
+         # Accept the current argument as the source file.
+         # The previous "srcfile" becomes the current argument.
+         #
+         lastarg="$srcfile"
+         srcfile="$arg"
+         ;;
+       esac  #  case $arg
+       ;;
+      esac    #  case $arg_mode
+
+      # Aesthetically quote the previous argument.
+      func_quote_for_eval "$lastarg"
+      base_compile="$base_compile $func_quote_for_eval_result"
+    done # for arg
+
+    case $arg_mode in
+    arg)
+      func_fatal_error "you must specify an argument for -Xcompile"
+      ;;
+    target)
+      func_fatal_error "you must specify a target with \`-o'"
+      ;;
+    *)
+      # Get the name of the library object.
+      test -z "$libobj" && {
+       func_basename "$srcfile"
+       libobj="$func_basename_result"
+      }
+      ;;
+    esac
+
+    # Recognize several different file suffixes.
+    # If the user specifies -o file.o, it is replaced with file.lo
+    case $libobj in
+    *.[cCFSifmso] | \
+    *.ada | *.adb | *.ads | *.asm | \
+    *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+    *.[fF][09]? | *.for | *.java | *.obj | *.sx)
+      func_xform "$libobj"
+      libobj=$func_xform_result
+      ;;
+    esac
+
+    case $libobj in
+    *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+    *)
+      func_fatal_error "cannot determine name of library object from \`$libobj'"
+      ;;
+    esac
+
+    func_infer_tag $base_compile
+
+    for arg in $later; do
+      case $arg in
+      -shared)
+       test "$build_libtool_libs" != yes && \
+         func_fatal_configuration "can not build a shared library"
+       build_old_libs=no
+       continue
+       ;;
+
+      -static)
+       build_libtool_libs=no
+       build_old_libs=yes
+       continue
+       ;;
+
+      -prefer-pic)
+       pic_mode=yes
+       continue
+       ;;
+
+      -prefer-non-pic)
+       pic_mode=no
+       continue
+       ;;
+      esac
+    done
+
+    func_quote_for_eval "$libobj"
+    test "X$libobj" != "X$func_quote_for_eval_result" \
+      && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"'   &()|`$[]' \
+      && func_warning "libobj name \`$libobj' may not contain shell special characters."
+    func_dirname_and_basename "$obj" "/" ""
+    objname="$func_basename_result"
+    xdir="$func_dirname_result"
+    lobj=${xdir}$objdir/$objname
+
+    test -z "$base_compile" && \
+      func_fatal_help "you must specify a compilation command"
+
+    # Delete any leftover library objects.
+    if test "$build_old_libs" = yes; then
+      removelist="$obj $lobj $libobj ${libobj}T"
+    else
+      removelist="$lobj $libobj ${libobj}T"
+    fi
+
+    # On Cygwin there's no "real" PIC flag so we must build both object types
+    case $host_os in
+    cygwin* | mingw* | pw32* | os2* | cegcc*)
+      pic_mode=default
+      ;;
+    esac
+    if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+      # non-PIC code in shared libraries is not supported
+      pic_mode=default
+    fi
+
+    # Calculate the filename of the output object if compiler does
+    # not support -o with -c
+    if test "$compiler_c_o" = no; then
+      output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+      lockfile="$output_obj.lock"
+    else
+      output_obj=
+      need_locks=no
+      lockfile=
+    fi
+
+    # Lock this critical section if it is needed
+    # We use this script file to make the link, it avoids creating a new file
+    if test "$need_locks" = yes; then
+      until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+       func_echo "Waiting for $lockfile to be removed"
+       sleep 2
+      done
+    elif test "$need_locks" = warn; then
+      if test -f "$lockfile"; then
+       $ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $opt_dry_run || $RM $removelist
+       exit $EXIT_FAILURE
+      fi
+      removelist="$removelist $output_obj"
+      $ECHO "$srcfile" > "$lockfile"
+    fi
+
+    $opt_dry_run || $RM $removelist
+    removelist="$removelist $lockfile"
+    trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+    if test -n "$fix_srcfile_path"; then
+      eval srcfile=\"$fix_srcfile_path\"
+    fi
+    func_quote_for_eval "$srcfile"
+    qsrcfile=$func_quote_for_eval_result
+
+    # Only build a PIC object if we are building libtool libraries.
+    if test "$build_libtool_libs" = yes; then
+      # Without this assignment, base_compile gets emptied.
+      fbsd_hideous_sh_bug=$base_compile
+
+      if test "$pic_mode" != no; then
+       command="$base_compile $qsrcfile $pic_flag"
+      else
+       # Don't build PIC code
+       command="$base_compile $qsrcfile"
+      fi
+
+      func_mkdir_p "$xdir$objdir"
+
+      if test -z "$output_obj"; then
+       # Place PIC objects in $objdir
+       command="$command -o $lobj"
+      fi
+
+      func_show_eval_locale "$command" \
+          'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $opt_dry_run || $RM $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed, then go on to compile the next one
+      if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+       func_show_eval '$MV "$output_obj" "$lobj"' \
+         'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+
+      # Allow error messages only from the first compilation.
+      if test "$suppress_opt" = yes; then
+       suppress_output=' >/dev/null 2>&1'
+      fi
+    fi
+
+    # Only build a position-dependent object if we build old libraries.
+    if test "$build_old_libs" = yes; then
+      if test "$pic_mode" != yes; then
+       # Don't build PIC code
+       command="$base_compile $qsrcfile$pie_flag"
+      else
+       command="$base_compile $qsrcfile $pic_flag"
+      fi
+      if test "$compiler_c_o" = yes; then
+       command="$command -o $obj"
+      fi
+
+      # Suppress compiler output if we already did a PIC compilation.
+      command="$command$suppress_output"
+      func_show_eval_locale "$command" \
+        '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+      if test "$need_locks" = warn &&
+        test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+       $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together.  If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+       $opt_dry_run || $RM $removelist
+       exit $EXIT_FAILURE
+      fi
+
+      # Just move the object if needed
+      if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+       func_show_eval '$MV "$output_obj" "$obj"' \
+         'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+      fi
+    fi
+
+    $opt_dry_run || {
+      func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+      # Unlock the critical section if it was locked
+      if test "$need_locks" != no; then
+       removelist=$lockfile
+        $RM "$lockfile"
+      fi
+    }
+
+    exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+test "$mode" = compile && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+    # We need to display help for each of the modes.
+    case $mode in
+      "")
+        # Generic help is extracted from the usage comments
+        # at the start of this file.
+        func_help
+        ;;
+
+      clean)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      compile)
+      $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+  -o OUTPUT-FILE    set the output file name to OUTPUT-FILE
+  -no-suppress      do not suppress compiler output for multiple passes
+  -prefer-pic       try to building PIC objects only
+  -prefer-non-pic   try to building non-PIC objects only
+  -shared           do not build a \`.o' file suitable for static linking
+  -static           only build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+        ;;
+
+      execute)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+  -dlopen FILE      add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+        ;;
+
+      finish)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges.  Use
+the \`--dry-run' option if you just want to see what would be executed."
+        ;;
+
+      install)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command.  The first component should be
+either the \`install' or \`cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+  -inst-prefix PREFIX-DIR  Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+        ;;
+
+      link)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+  -all-static       do not do any dynamic linking at all
+  -avoid-version    do not add a version suffix if possible
+  -dlopen FILE      \`-dlpreopen' FILE if it cannot be dlopened at runtime
+  -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
+  -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+  -export-symbols SYMFILE
+                    try to export only the symbols listed in SYMFILE
+  -export-symbols-regex REGEX
+                    try to export only the symbols matching REGEX
+  -LLIBDIR          search LIBDIR for required installed libraries
+  -lNAME            OUTPUT-FILE requires the installed library libNAME
+  -module           build a library that can dlopened
+  -no-fast-install  disable the fast-install mode
+  -no-install       link a not-installable executable
+  -no-undefined     declare that a library does not refer to external symbols
+  -o OUTPUT-FILE    create OUTPUT-FILE from the specified objects
+  -objectlist FILE  Use a list of object files found in FILE to specify objects
+  -precious-files-regex REGEX
+                    don't remove output files matching REGEX
+  -release RELEASE  specify package release information
+  -rpath LIBDIR     the created library will eventually be installed in LIBDIR
+  -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
+  -shared           only do dynamic linking of libtool libraries
+  -shrext SUFFIX    override the standard shared library file extension
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
+  -version-info CURRENT[:REVISION[:AGE]]
+                    specify library version info [each variable defaults to 0]
+  -weak LIBNAME     declare that the target provides the LIBNAME interface
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename.  Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+        ;;
+
+      uninstall)
+        $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm').  RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+        ;;
+
+      *)
+        func_fatal_help "invalid operation mode \`$mode'"
+        ;;
+    esac
+
+    $ECHO
+    $ECHO "Try \`$progname --help' for more information about other modes."
+
+    exit $?
+}
+
+  # Now that we've collected a possible --mode arg, show help if necessary
+  $opt_help && func_mode_help
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+    $opt_debug
+    # The first argument is the command name.
+    cmd="$nonopt"
+    test -z "$cmd" && \
+      func_fatal_help "you must specify a COMMAND"
+
+    # Handle -dlopen flags immediately.
+    for file in $execute_dlfiles; do
+      test -f "$file" \
+       || func_fatal_help "\`$file' is not a file"
+
+      dir=
+      case $file in
+      *.la)
+       # Check to see that this really is a libtool archive.
+       func_lalib_unsafe_p "$file" \
+         || func_fatal_help "\`$lib' is not a valid libtool archive"
+
+       # Read the libtool library.
+       dlname=
+       library_names=
+       func_source "$file"
+
+       # Skip this library if it cannot be dlopened.
+       if test -z "$dlname"; then
+         # Warn if it was a shared library.
+         test -n "$library_names" && \
+           func_warning "\`$file' was not linked with \`-export-dynamic'"
+         continue
+       fi
+
+       func_dirname "$file" "" "."
+       dir="$func_dirname_result"
+
+       if test -f "$dir/$objdir/$dlname"; then
+         dir="$dir/$objdir"
+       else
+         if test ! -f "$dir/$dlname"; then
+           func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'"
+         fi
+       fi
+       ;;
+
+      *.lo)
+       # Just add the directory containing the .lo file.
+       func_dirname "$file" "" "."
+       dir="$func_dirname_result"
+       ;;
+
+      *)
+       func_warning "\`-dlopen' is ignored for non-libtool libraries and objects"
+       continue
+       ;;
+      esac
+
+      # Get the absolute pathname.
+      absdir=`cd "$dir" && pwd`
+      test -n "$absdir" && dir="$absdir"
+
+      # Now add the directory to shlibpath_var.
+      if eval "test -z \"\$$shlibpath_var\""; then
+       eval "$shlibpath_var=\"\$dir\""
+      else
+       eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+      fi
+    done
+
+    # This variable tells wrapper scripts just to set shlibpath_var
+    # rather than running their programs.
+    libtool_execute_magic="$magic"
+
+    # Check if any of the arguments is a wrapper script.
+    args=
+    for file
+    do
+      case $file in
+      -*) ;;
+      *)
+       # Do a test to see if this is really a libtool program.
+       if func_ltwrapper_script_p "$file"; then
+         func_source "$file"
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       elif func_ltwrapper_executable_p "$file"; then
+         func_ltwrapper_scriptname "$file"
+         func_source "$func_ltwrapper_scriptname_result"
+         # Transform arg to wrapped name.
+         file="$progdir/$program"
+       fi
+       ;;
+      esac
+      # Quote arguments (to preserve shell metacharacters).
+      func_quote_for_eval "$file"
+      args="$args $func_quote_for_eval_result"
+    done
+
+    if test "X$opt_dry_run" = Xfalse; then
+      if test -n "$shlibpath_var"; then
+       # Export the shlibpath_var.
+       eval "export $shlibpath_var"
+      fi
+
+      # Restore saved environment variables
+      for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+       eval "if test \"\${save_$lt_var+set}\" = set; then
+                $lt_var=\$save_$lt_var; export $lt_var
+             else
+               $lt_unset $lt_var
+             fi"
+      done
+
+      # Now prepare to actually exec the command.
+      exec_cmd="\$cmd$args"
+    else
+      # Display what would be done.
+      if test -n "$shlibpath_var"; then
+       eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+       $ECHO "export $shlibpath_var"
+      fi
+      $ECHO "$cmd$args"
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = execute && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+    $opt_debug
+    libdirs="$nonopt"
+    admincmds=
+
+    if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+      for dir
+      do
+       libdirs="$libdirs $dir"
+      done
+
+      for libdir in $libdirs; do
+       if test -n "$finish_cmds"; then
+         # Do each command in the finish commands.
+         func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+       fi
+       if test -n "$finish_eval"; then
+         # Do the single finish_eval.
+         eval cmds=\"$finish_eval\"
+         $opt_dry_run || eval "$cmds" || admincmds="$admincmds
+       $cmds"
+       fi
+      done
+    fi
+
+    # Exit here if they wanted silent mode.
+    $opt_silent && exit $EXIT_SUCCESS
+
+    $ECHO "X----------------------------------------------------------------------" | $Xsed
+    $ECHO "Libraries have been installed in:"
+    for libdir in $libdirs; do
+      $ECHO "   $libdir"
+    done
+    $ECHO
+    $ECHO "If you ever happen to want to link against installed libraries"
+    $ECHO "in a given directory, LIBDIR, you must either use libtool, and"
+    $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'"
+    $ECHO "flag during linking and do at least one of the following:"
+    if test -n "$shlibpath_var"; then
+      $ECHO "   - add LIBDIR to the \`$shlibpath_var' environment variable"
+      $ECHO "     during execution"
+    fi
+    if test -n "$runpath_var"; then
+      $ECHO "   - add LIBDIR to the \`$runpath_var' environment variable"
+      $ECHO "     during linking"
+    fi
+    if test -n "$hardcode_libdir_flag_spec"; then
+      libdir=LIBDIR
+      eval flag=\"$hardcode_libdir_flag_spec\"
+
+      $ECHO "   - use the \`$flag' linker flag"
+    fi
+    if test -n "$admincmds"; then
+      $ECHO "   - have your system administrator run these commands:$admincmds"
+    fi
+    if test -f /etc/ld.so.conf; then
+      $ECHO "   - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+    fi
+    $ECHO
+
+    $ECHO "See any operating system documentation about shared libraries for"
+    case $host in
+      solaris2.[6789]|solaris2.1[0-9])
+        $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+       $ECHO "pages."
+       ;;
+      *)
+        $ECHO "more information, such as the ld(1) and ld.so(8) manual pages."
+        ;;
+    esac
+    $ECHO "X----------------------------------------------------------------------" | $Xsed
+    exit $EXIT_SUCCESS
+}
+
+test "$mode" = finish && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+    $opt_debug
+    # There may be an optional sh(1) argument at the beginning of
+    # install_prog (especially on Windows NT).
+    if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+       # Allow the use of GNU shtool's install command.
+       $ECHO "X$nonopt" | $GREP shtool >/dev/null; then
+      # Aesthetically quote it.
+      func_quote_for_eval "$nonopt"
+      install_prog="$func_quote_for_eval_result "
+      arg=$1
+      shift
+    else
+      install_prog=
+      arg=$nonopt
+    fi
+
+    # The real first argument should be the name of the installation program.
+    # Aesthetically quote it.
+    func_quote_for_eval "$arg"
+    install_prog="$install_prog$func_quote_for_eval_result"
+
+    # We need to accept at least all the BSD install flags.
+    dest=
+    files=
+    opts=
+    prev=
+    install_type=
+    isdir=no
+    stripme=
+    for arg
+    do
+      if test -n "$dest"; then
+       files="$files $dest"
+       dest=$arg
+       continue
+      fi
+
+      case $arg in
+      -d) isdir=yes ;;
+      -f)
+       case " $install_prog " in
+       *[\\\ /]cp\ *) ;;
+       *) prev=$arg ;;
+       esac
+       ;;
+      -g | -m | -o)
+       prev=$arg
+       ;;
+      -s)
+       stripme=" -s"
+       continue
+       ;;
+      -*)
+       ;;
+      *)
+       # If the previous option needed an argument, then skip it.
+       if test -n "$prev"; then
+         prev=
+       else
+         dest=$arg
+         continue
+       fi
+       ;;
+      esac
+
+      # Aesthetically quote the argument.
+      func_quote_for_eval "$arg"
+      install_prog="$install_prog $func_quote_for_eval_result"
+    done
+
+    test -z "$install_prog" && \
+      func_fatal_help "you must specify an install program"
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prev' option requires an argument"
+
+    if test -z "$files"; then
+      if test -z "$dest"; then
+       func_fatal_help "no file or destination specified"
+      else
+       func_fatal_help "you must specify a destination"
+      fi
+    fi
+
+    # Strip any trailing slash from the destination.
+    func_stripname '' '/' "$dest"
+    dest=$func_stripname_result
+
+    # Check to see that the destination is a directory.
+    test -d "$dest" && isdir=yes
+    if test "$isdir" = yes; then
+      destdir="$dest"
+      destname=
+    else
+      func_dirname_and_basename "$dest" "" "."
+      destdir="$func_dirname_result"
+      destname="$func_basename_result"
+
+      # Not a directory, so check to see that there is only one file specified.
+      set dummy $files; shift
+      test "$#" -gt 1 && \
+       func_fatal_help "\`$dest' is not a directory"
+    fi
+    case $destdir in
+    [\\/]* | [A-Za-z]:[\\/]*) ;;
+    *)
+      for file in $files; do
+       case $file in
+       *.lo) ;;
+       *)
+         func_fatal_help "\`$destdir' must be an absolute directory name"
+         ;;
+       esac
+      done
+      ;;
+    esac
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    staticlibs=
+    future_libdirs=
+    current_libdirs=
+    for file in $files; do
+
+      # Do each installation.
+      case $file in
+      *.$libext)
+       # Do the static libraries later.
+       staticlibs="$staticlibs $file"
+       ;;
+
+      *.la)
+       # Check to see that this really is a libtool archive.
+       func_lalib_unsafe_p "$file" \
+         || func_fatal_help "\`$file' is not a valid libtool archive"
+
+       library_names=
+       old_library=
+       relink_command=
+       func_source "$file"
+
+       # Add the libdir to current_libdirs if it is the destination.
+       if test "X$destdir" = "X$libdir"; then
+         case "$current_libdirs " in
+         *" $libdir "*) ;;
+         *) current_libdirs="$current_libdirs $libdir" ;;
+         esac
+       else
+         # Note the libdir as a future libdir.
+         case "$future_libdirs " in
+         *" $libdir "*) ;;
+         *) future_libdirs="$future_libdirs $libdir" ;;
+         esac
+       fi
+
+       func_dirname "$file" "/" ""
+       dir="$func_dirname_result"
+       dir="$dir$objdir"
+
+       if test -n "$relink_command"; then
+         # Determine the prefix the user has applied to our future dir.
+         inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"`
+
+         # Don't allow the user to place us outside of our expected
+         # location b/c this prevents finding dependent libraries that
+         # are installed to the same prefix.
+         # At present, this check doesn't affect windows .dll's that
+         # are installed into $libdir/../bin (currently, that works fine)
+         # but it's something to keep an eye on.
+         test "$inst_prefix_dir" = "$destdir" && \
+           func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir"
+
+         if test -n "$inst_prefix_dir"; then
+           # Stick the inst_prefix_dir data into the link command.
+           relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+         else
+           relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"`
+         fi
+
+         func_warning "relinking \`$file'"
+         func_show_eval "$relink_command" \
+           'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"'
+       fi
+
+       # See the names of the shared library.
+       set dummy $library_names; shift
+       if test -n "$1"; then
+         realname="$1"
+         shift
+
+         srcname="$realname"
+         test -n "$relink_command" && srcname="$realname"T
+
+         # Install the shared library and build the symlinks.
+         func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \
+             'exit $?'
+         tstripme="$stripme"
+         case $host_os in
+         cygwin* | mingw* | pw32* | cegcc*)
+           case $realname in
+           *.dll.a)
+             tstripme=""
+             ;;
+           esac
+           ;;
+         esac
+         if test -n "$tstripme" && test -n "$striplib"; then
+           func_show_eval "$striplib $destdir/$realname" 'exit $?'
+         fi
+
+         if test "$#" -gt 0; then
+           # Delete the old symlinks, and create new ones.
+           # Try `ln -sf' first, because the `ln' binary might depend on
+           # the symlink we replace!  Solaris /bin/ln does not understand -f,
+           # so we also need to try rm && ln -s.
+           for linkname
+           do
+             test "$linkname" != "$realname" \
+               && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+           done
+         fi
+
+         # Do each command in the postinstall commands.
+         lib="$destdir/$realname"
+         func_execute_cmds "$postinstall_cmds" 'exit $?'
+       fi
+
+       # Install the pseudo-library for information purposes.
+       func_basename "$file"
+       name="$func_basename_result"
+       instname="$dir/$name"i
+       func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+       # Maybe install the static library, too.
+       test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+       ;;
+
+      *.lo)
+       # Install (i.e. copy) a libtool object.
+
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         func_basename "$file"
+         destfile="$func_basename_result"
+         destfile="$destdir/$destfile"
+       fi
+
+       # Deduce the name of the destination old-style object file.
+       case $destfile in
+       *.lo)
+         func_lo2o "$destfile"
+         staticdest=$func_lo2o_result
+         ;;
+       *.$objext)
+         staticdest="$destfile"
+         destfile=
+         ;;
+       *)
+         func_fatal_help "cannot copy a libtool object to \`$destfile'"
+         ;;
+       esac
+
+       # Install the libtool object if requested.
+       test -n "$destfile" && \
+         func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+       # Install the old object if enabled.
+       if test "$build_old_libs" = yes; then
+         # Deduce the name of the old-style object file.
+         func_lo2o "$file"
+         staticobj=$func_lo2o_result
+         func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+       fi
+       exit $EXIT_SUCCESS
+       ;;
+
+      *)
+       # Figure out destination file name, if it wasn't already specified.
+       if test -n "$destname"; then
+         destfile="$destdir/$destname"
+       else
+         func_basename "$file"
+         destfile="$func_basename_result"
+         destfile="$destdir/$destfile"
+       fi
+
+       # If the file is missing, and there is a .exe on the end, strip it
+       # because it is most likely a libtool script we actually want to
+       # install
+       stripped_ext=""
+       case $file in
+         *.exe)
+           if test ! -f "$file"; then
+             func_stripname '' '.exe' "$file"
+             file=$func_stripname_result
+             stripped_ext=".exe"
+           fi
+           ;;
+       esac
+
+       # Do a test to see if this is really a libtool program.
+       case $host in
+       *cygwin* | *mingw*)
+           if func_ltwrapper_executable_p "$file"; then
+             func_ltwrapper_scriptname "$file"
+             wrapper=$func_ltwrapper_scriptname_result
+           else
+             func_stripname '' '.exe' "$file"
+             wrapper=$func_stripname_result
+           fi
+           ;;
+       *)
+           wrapper=$file
+           ;;
+       esac
+       if func_ltwrapper_script_p "$wrapper"; then
+         notinst_deplibs=
+         relink_command=
+
+         func_source "$wrapper"
+
+         # Check the variables that should have been set.
+         test -z "$generated_by_libtool_version" && \
+           func_fatal_error "invalid libtool wrapper script \`$wrapper'"
+
+         finalize=yes
+         for lib in $notinst_deplibs; do
+           # Check to see that each library is installed.
+           libdir=
+           if test -f "$lib"; then
+             func_source "$lib"
+           fi
+           libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+           if test -n "$libdir" && test ! -f "$libfile"; then
+             func_warning "\`$lib' has not been installed in \`$libdir'"
+             finalize=no
+           fi
+         done
+
+         relink_command=
+         func_source "$wrapper"
+
+         outputname=
+         if test "$fast_install" = no && test -n "$relink_command"; then
+           $opt_dry_run || {
+             if test "$finalize" = yes; then
+               tmpdir=`func_mktempdir`
+               func_basename "$file$stripped_ext"
+               file="$func_basename_result"
+               outputname="$tmpdir/$file"
+               # Replace the output file specification.
+               relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+               $opt_silent || {
+                 func_quote_for_expand "$relink_command"
+                 eval "func_echo $func_quote_for_expand_result"
+               }
+               if eval "$relink_command"; then :
+                 else
+                 func_error "error: relink \`$file' with the above command before installing it"
+                 $opt_dry_run || ${RM}r "$tmpdir"
+                 continue
+               fi
+               file="$outputname"
+             else
+               func_warning "cannot relink \`$file'"
+             fi
+           }
+         else
+           # Install the binary that we compiled earlier.
+           file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+         fi
+       fi
+
+       # remove .exe since cygwin /usr/bin/install will append another
+       # one anyway
+       case $install_prog,$host in
+       */usr/bin/install*,*cygwin*)
+         case $file:$destfile in
+         *.exe:*.exe)
+           # this is ok
+           ;;
+         *.exe:*)
+           destfile=$destfile.exe
+           ;;
+         *:*.exe)
+           func_stripname '' '.exe' "$destfile"
+           destfile=$func_stripname_result
+           ;;
+         esac
+         ;;
+       esac
+       func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+       $opt_dry_run || if test -n "$outputname"; then
+         ${RM}r "$tmpdir"
+       fi
+       ;;
+      esac
+    done
+
+    for file in $staticlibs; do
+      func_basename "$file"
+      name="$func_basename_result"
+
+      # Set up the ranlib parameters.
+      oldlib="$destdir/$name"
+
+      func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+      if test -n "$stripme" && test -n "$old_striplib"; then
+       func_show_eval "$old_striplib $oldlib" 'exit $?'
+      fi
+
+      # Do each command in the postinstall commands.
+      func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+    done
+
+    test -n "$future_libdirs" && \
+      func_warning "remember to run \`$progname --finish$future_libdirs'"
+
+    if test -n "$current_libdirs"; then
+      # Maybe just do a dry run.
+      $opt_dry_run && current_libdirs=" -n$current_libdirs"
+      exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+    else
+      exit $EXIT_SUCCESS
+    fi
+}
+
+test "$mode" = install && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+    $opt_debug
+    my_outputname="$1"
+    my_originator="$2"
+    my_pic_p="${3-no}"
+    my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'`
+    my_dlsyms=
+
+    if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+      if test -n "$NM" && test -n "$global_symbol_pipe"; then
+       my_dlsyms="${my_outputname}S.c"
+      else
+       func_error "not configured to extract global symbols from dlpreopened files"
+      fi
+    fi
+
+    if test -n "$my_dlsyms"; then
+      case $my_dlsyms in
+      "") ;;
+      *.c)
+       # Discover the nlist of each of the dlfiles.
+       nlist="$output_objdir/${my_outputname}.nm"
+
+       func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+       # Parse the name list into a source file.
+       func_verbose "creating $output_objdir/$my_dlsyms"
+
+       $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* External symbol declarations for the compiler. */\
+"
+
+       if test "$dlself" = yes; then
+         func_verbose "generating symbol list for \`$output'"
+
+         $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+         # Add our own program objects to the symbol list.
+         progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+         for progfile in $progfiles; do
+           func_verbose "extracting global C symbols from \`$progfile'"
+           $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'"
+         done
+
+         if test -n "$exclude_expsyms"; then
+           $opt_dry_run || {
+             eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+             eval '$MV "$nlist"T "$nlist"'
+           }
+         fi
+
+         if test -n "$export_symbols_regex"; then
+           $opt_dry_run || {
+             eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+             eval '$MV "$nlist"T "$nlist"'
+           }
+         fi
+
+         # Prepare the list of exported symbols
+         if test -z "$export_symbols"; then
+           export_symbols="$output_objdir/$outputname.exp"
+           $opt_dry_run || {
+             $RM $export_symbols
+             eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+             case $host in
+             *cygwin* | *mingw* | *cegcc* )
+                eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+               ;;
+             esac
+           }
+         else
+           $opt_dry_run || {
+             eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+             eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+             eval '$MV "$nlist"T "$nlist"'
+             case $host in
+               *cygwin | *mingw* | *cegcc* )
+                 eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+                 eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+                 ;;
+             esac
+           }
+         fi
+       fi
+
+       for dlprefile in $dlprefiles; do
+         func_verbose "extracting global C symbols from \`$dlprefile'"
+         func_basename "$dlprefile"
+         name="$func_basename_result"
+         $opt_dry_run || {
+           eval '$ECHO ": $name " >> "$nlist"'
+           eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+         }
+       done
+
+       $opt_dry_run || {
+         # Make sure we have at least an empty file.
+         test -f "$nlist" || : > "$nlist"
+
+         if test -n "$exclude_expsyms"; then
+           $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+           $MV "$nlist"T "$nlist"
+         fi
+
+         # Try sorting and uniquifying the output.
+         if $GREP -v "^: " < "$nlist" |
+             if sort -k 3 </dev/null >/dev/null 2>&1; then
+               sort -k 3
+             else
+               sort +2
+             fi |
+             uniq > "$nlist"S; then
+           :
+         else
+           $GREP -v "^: " < "$nlist" > "$nlist"S
+         fi
+
+         if test -f "$nlist"S; then
+           eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+         else
+           $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms"
+         fi
+
+         $ECHO >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols.  */
+typedef struct {
+  const char *name;
+  void *address;
+} lt_dlsymlist;
+"
+         case $host in
+         *cygwin* | *mingw* | *cegcc* )
+           $ECHO >> "$output_objdir/$my_dlsyms" "\
+/* DATA imports from DLLs on WIN32 con't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs.  */"
+           lt_dlsym_const= ;;
+         *osf5*)
+           echo >> "$output_objdir/$my_dlsyms" "\
+/* This system does not cope well with relocations in const data */"
+           lt_dlsym_const= ;;
+         *)
+           lt_dlsym_const=const ;;
+         esac
+
+         $ECHO >> "$output_objdir/$my_dlsyms" "\
+extern $lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];
+$lt_dlsym_const lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{\
+  { \"$my_originator\", (void *) 0 },"
+
+         case $need_lib_prefix in
+         no)
+           eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+           ;;
+         *)
+           eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+           ;;
+         esac
+         $ECHO >> "$output_objdir/$my_dlsyms" "\
+  {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+  return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+       } # !$opt_dry_run
+
+       pic_flag_for_symtable=
+       case "$compile_command " in
+       *" -static "*) ;;
+       *)
+         case $host in
+         # compiling the symbol table file with pic_flag works around
+         # a FreeBSD bug that causes programs to crash when -lm is
+         # linked before any other PIC object.  But we must not use
+         # pic_flag when linking with -static.  The problem exists in
+         # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+         *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+           pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+         *-*-hpux*)
+           pic_flag_for_symtable=" $pic_flag"  ;;
+         *)
+           if test "X$my_pic_p" != Xno; then
+             pic_flag_for_symtable=" $pic_flag"
+           fi
+           ;;
+         esac
+         ;;
+       esac
+       symtab_cflags=
+       for arg in $LTCFLAGS; do
+         case $arg in
+         -pie | -fpie | -fPIE) ;;
+         *) symtab_cflags="$symtab_cflags $arg" ;;
+         esac
+       done
+
+       # Now compile the dynamic symbol file.
+       func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+       # Clean up the generated files.
+       func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"'
+
+       # Transform the symbol file into the correct name.
+       symfileobj="$output_objdir/${my_outputname}S.$objext"
+       case $host in
+       *cygwin* | *mingw* | *cegcc* )
+         if test -f "$output_objdir/$my_outputname.def"; then
+           compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+           finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+         else
+           compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+           finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+         fi
+         ;;
+       *)
+         compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+         finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"`
+         ;;
+       esac
+       ;;
+      *)
+       func_fatal_error "unknown suffix for \`$my_dlsyms'"
+       ;;
+      esac
+    else
+      # We keep going just in case the user didn't refer to
+      # lt_preloaded_symbols.  The linker will fail if global_symbol_pipe
+      # really was required.
+
+      # Nullify the symbol file.
+      compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+      finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+    fi
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid ()
+{
+  $opt_debug
+  win32_libid_type="unknown"
+  win32_fileres=`file -L $1 2>/dev/null`
+  case $win32_fileres in
+  *ar\ archive\ import\ library*) # definitely import
+    win32_libid_type="x86 archive import"
+    ;;
+  *ar\ archive*) # could be an import, or static
+    if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+       $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+      win32_nmres=`eval $NM -f posix -A $1 |
+       $SED -n -e '
+           1,100{
+               / I /{
+                   s,.*,import,
+                   p
+                   q
+               }
+           }'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
+    fi
+    ;;
+  *DLL*)
+    win32_libid_type="x86 DLL"
+    ;;
+  *executable*) # but shell scripts are "executable" too...
+    case $win32_fileres in
+    *MS\ Windows\ PE\ Intel*)
+      win32_libid_type="x86 DLL"
+      ;;
+    esac
+    ;;
+  esac
+  $ECHO "$win32_libid_type"
+}
+
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    $opt_debug
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+    func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?'
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+    fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    $opt_debug
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+       [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+       *) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      func_basename "$my_xlib"
+      my_xlib="$func_basename_result"
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+       *" $my_xlib_u "*)
+         func_arith $extracted_serial + 1
+         extracted_serial=$func_arith_result
+         my_xlib_u=lt$extracted_serial-$my_xlib ;;
+       *) break ;;
+       esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      func_mkdir_p "$my_xdir"
+
+      case $host in
+      *-darwin*)
+       func_verbose "Extracting $my_xabs"
+       # Do not bother doing anything if just a dry run
+       $opt_dry_run || {
+         darwin_orig_dir=`pwd`
+         cd $my_xdir || exit $?
+         darwin_archive=$my_xabs
+         darwin_curdir=`pwd`
+         darwin_base_archive=`basename "$darwin_archive"`
+         darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+         if test -n "$darwin_arches"; then
+           darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+           darwin_arch=
+           func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+           for darwin_arch in  $darwin_arches ; do
+             func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+             cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+             cd "$darwin_curdir"
+             $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+           done # $darwin_arches
+            ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+           darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u`
+           darwin_file=
+           darwin_files=
+           for darwin_file in $darwin_filelist; do
+             darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+             $LIPO -create -output "$darwin_file" $darwin_files
+           done # $darwin_filelist
+           $RM -rf unfat-$$
+           cd "$darwin_orig_dir"
+         else
+           cd $darwin_orig_dir
+           func_extract_an_archive "$my_xdir" "$my_xabs"
+         fi # $darwin_arches
+       } # !$opt_dry_run
+       ;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+       ;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+
+    func_extract_archives_result="$my_oldobjs"
+}
+
+
+
+# func_emit_wrapper_part1 [arg=no]
+#
+# Emit the first part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part1 ()
+{
+       func_emit_wrapper_part1_arg1=no
+       if test -n "$1" ; then
+         func_emit_wrapper_part1_arg1=$1
+       fi
+
+       $ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+  # install mode needs the following variables:
+  generated_by_libtool_version='$macro_version'
+  notinst_deplibs='$notinst_deplibs'
+else
+  # When we are sourced in execute mode, \$file and \$ECHO are already set.
+  if test \"\$libtool_execute_magic\" != \"$magic\"; then
+    ECHO=\"$qecho\"
+    file=\"\$0\"
+    # Make sure echo works.
+    if test \"X\$1\" = X--no-reexec; then
+      # Discard the --no-reexec flag, and continue.
+      shift
+    elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then
+      # Yippee, \$ECHO works!
+      :
+    else
+      # Restart under the correct shell, and then maybe \$ECHO will work.
+      exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+    fi
+  fi\
+"
+       $ECHO "\
+
+  # Find the directory that this script lives in.
+  thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+  test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+  # Follow symbolic links until we get to the real thisdir.
+  file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+  while test -n \"\$file\"; do
+    destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+    # If there was a directory component, then change thisdir.
+    if test \"x\$destdir\" != \"x\$file\"; then
+      case \"\$destdir\" in
+      [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+      *) thisdir=\"\$thisdir/\$destdir\" ;;
+      esac
+    fi
+
+    file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+    file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+  done
+"
+}
+# end: func_emit_wrapper_part1
+
+# func_emit_wrapper_part2 [arg=no]
+#
+# Emit the second part of a libtool wrapper script on stdout.
+# For more information, see the description associated with
+# func_emit_wrapper(), below.
+func_emit_wrapper_part2 ()
+{
+       func_emit_wrapper_part2_arg1=no
+       if test -n "$1" ; then
+         func_emit_wrapper_part2_arg1=$1
+       fi
+
+       $ECHO "\
+
+  # Usually 'no', except on cygwin/mingw when embedded into
+  # the cwrapper.
+  WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1
+  if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+    # special case for '.'
+    if test \"\$thisdir\" = \".\"; then
+      thisdir=\`pwd\`
+    fi
+    # remove .libs from thisdir
+    case \"\$thisdir\" in
+    *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;;
+    $objdir )   thisdir=. ;;
+    esac
+  fi
+
+  # Try to get the absolute directory name.
+  absdir=\`cd \"\$thisdir\" && pwd\`
+  test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+       if test "$fast_install" = yes; then
+         $ECHO "\
+  program=lt-'$outputname'$exeext
+  progdir=\"\$thisdir/$objdir\"
+
+  if test ! -f \"\$progdir/\$program\" ||
+     { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+       test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+    file=\"\$\$-\$program\"
+
+    if test ! -d \"\$progdir\"; then
+      $MKDIR \"\$progdir\"
+    else
+      $RM \"\$progdir/\$file\"
+    fi"
+
+         $ECHO "\
+
+    # relink executable if necessary
+    if test -n \"\$relink_command\"; then
+      if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+      else
+       $ECHO \"\$relink_command_output\" >&2
+       $RM \"\$progdir/\$file\"
+       exit 1
+      fi
+    fi
+
+    $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+    { $RM \"\$progdir/\$program\";
+      $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+    $RM \"\$progdir/\$file\"
+  fi"
+       else
+         $ECHO "\
+  program='$outputname'
+  progdir=\"\$thisdir/$objdir\"
+"
+       fi
+
+       $ECHO "\
+
+  if test -f \"\$progdir/\$program\"; then"
+
+       # Export our shlibpath_var if we have one.
+       if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+         $ECHO "\
+    # Add our own library path to $shlibpath_var
+    $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+    # Some systems cannot cope with colon-terminated $shlibpath_var
+    # The second colon is a workaround for a bug in BeOS R4 sed
+    $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+    export $shlibpath_var
+"
+       fi
+
+       # fixup the dll searchpath if we need to.
+       if test -n "$dllsearchpath"; then
+         $ECHO "\
+    # Add the dll search path components to the executable PATH
+    PATH=$dllsearchpath:\$PATH
+"
+       fi
+
+       $ECHO "\
+    if test \"\$libtool_execute_magic\" != \"$magic\"; then
+      # Run the actual program with our arguments.
+"
+       case $host in
+       # Backslashes separate directories on plain windows
+       *-*-mingw | *-*-os2* | *-cegcc*)
+         $ECHO "\
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+         ;;
+
+       *)
+         $ECHO "\
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+         ;;
+       esac
+       $ECHO "\
+      \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+      exit 1
+    fi
+  else
+    # The program doesn't exist.
+    \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
+    \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+    $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+    exit 1
+  fi
+fi\
+"
+}
+# end: func_emit_wrapper_part2
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable.  Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take.  If 'yes', then the emitted script
+# will assume that the directory in which it is stored is
+# the $objdir directory.  This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+       func_emit_wrapper_arg1=no
+       if test -n "$1" ; then
+         func_emit_wrapper_arg1=$1
+       fi
+
+       # split this up so that func_emit_cwrapperexe_src
+       # can call each part independently.
+       func_emit_wrapper_part1 "${func_emit_wrapper_arg1}"
+       func_emit_wrapper_part2 "${func_emit_wrapper_arg1}"
+}
+
+
+# func_to_host_path arg
+#
+# Convert paths to host format when used with build tools.
+# Intended for use with "native" mingw (where libtool itself
+# is running under the msys shell), or in the following cross-
+# build environments:
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+# where wine is equipped with the `winepath' executable.
+# In the native mingw case, the (msys) shell automatically
+# converts paths for any non-msys applications it launches,
+# but that facility isn't available from inside the cwrapper.
+# Similar accommodations are necessary for $host mingw and
+# $build cygwin.  Calling this function does no harm for other
+# $host/$build combinations not listed above.
+#
+# ARG is the path (on $build) that should be converted to
+# the proper representation for $host. The result is stored
+# in $func_to_host_path_result.
+func_to_host_path ()
+{
+  func_to_host_path_result="$1"
+  if test -n "$1" ; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        case $build in
+          *mingw* ) # actually, msys
+            # awkward: cmd appends spaces to result
+            lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+            func_to_host_path_tmp1=`( cmd //c echo "$1" |\
+              $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+            func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_path_tmp1=`cygpath -w "$1"`
+            func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # Unfortunately, winepath does not exit with a non-zero
+            # error code, so we are forced to check the contents of
+            # stdout. On the other hand, if the command is not
+            # found, the shell will set an exit code of 127 and print
+            # *an error message* to stdout. So we must check for both
+            # error code of zero AND non-empty stdout, which explains
+            # the odd construction:
+            func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null`
+            if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then
+              func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\
+                $SED -e "$lt_sed_naive_backslashify"`
+            else
+              # Allow warning below.
+              func_to_host_path_result=""
+            fi
+            ;;
+        esac
+        if test -z "$func_to_host_path_result" ; then
+          func_error "Could not determine host path corresponding to"
+          func_error "  '$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback:
+          func_to_host_path_result="$1"
+        fi
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_path
+
+# func_to_host_pathlist arg
+#
+# Convert pathlists to host format when used with build tools.
+# See func_to_host_path(), above. This function supports the
+# following $build/$host combinations (but does no harm for
+# combinations not listed here):
+#    $build          $host
+#    mingw (msys)    mingw  [e.g. native]
+#    cygwin          mingw
+#    *nix + wine     mingw
+#
+# Path separators are also converted from $build format to
+# $host format. If ARG begins or ends with a path separator
+# character, it is preserved (but converted to $host format)
+# on output.
+#
+# ARG is a pathlist (on $build) that should be converted to
+# the proper representation on $host. The result is stored
+# in $func_to_host_pathlist_result.
+func_to_host_pathlist ()
+{
+  func_to_host_pathlist_result="$1"
+  if test -n "$1" ; then
+    case $host in
+      *mingw* )
+        lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+        # Remove leading and trailing path separator characters from
+        # ARG. msys behavior is inconsistent here, cygpath turns them
+        # into '.;' and ';.', and winepath ignores them completely.
+        func_to_host_pathlist_tmp2="$1"
+        # Once set for this call, this variable should not be
+        # reassigned. It is used in tha fallback case.
+        func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\
+          $SED -e 's|^:*||' -e 's|:*$||'`
+        case $build in
+          *mingw* ) # Actually, msys.
+            # Awkward: cmd appends spaces to result.
+            lt_sed_strip_trailing_spaces="s/[ ]*\$//"
+            func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\
+              $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""`
+            func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          *cygwin* )
+            func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"`
+            func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\
+              $SED -e "$lt_sed_naive_backslashify"`
+            ;;
+          * )
+            # unfortunately, winepath doesn't convert pathlists
+            func_to_host_pathlist_result=""
+            func_to_host_pathlist_oldIFS=$IFS
+            IFS=:
+            for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do
+              IFS=$func_to_host_pathlist_oldIFS
+              if test -n "$func_to_host_pathlist_f" ; then
+                func_to_host_path "$func_to_host_pathlist_f"
+                if test -n "$func_to_host_path_result" ; then
+                  if test -z "$func_to_host_pathlist_result" ; then
+                    func_to_host_pathlist_result="$func_to_host_path_result"
+                  else
+                    func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result"
+                  fi
+                fi
+              fi
+              IFS=:
+            done
+            IFS=$func_to_host_pathlist_oldIFS
+            ;;
+        esac
+        if test -z "$func_to_host_pathlist_result" ; then
+          func_error "Could not determine the host path(s) corresponding to"
+          func_error "  '$1'"
+          func_error "Continuing, but uninstalled executables may not work."
+          # Fallback. This may break if $1 contains DOS-style drive
+          # specifications. The fix is not to complicate the expression
+          # below, but for the user to provide a working wine installation
+          # with winepath so that path translation in the cross-to-mingw
+          # case works properly.
+          lt_replace_pathsep_nix_to_dos="s|:|;|g"
+          func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\
+            $SED -e "$lt_replace_pathsep_nix_to_dos"`
+        fi
+        # Now, add the leading and trailing path separators back
+        case "$1" in
+          :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result"
+            ;;
+        esac
+        case "$1" in
+          *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;"
+            ;;
+        esac
+        ;;
+    esac
+  fi
+}
+# end: func_to_host_pathlist
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+       cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+   Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+
+   The $output program cannot be directly executed until all the libtool
+   libraries that it depends on are installed.
+
+   This wrapper executable should never be moved out of the build directory.
+   If it is, it will not operate correctly.
+
+   Currently, it simply execs the wrapper *script* "$SHELL $output",
+   but could eventually absorb all of the scripts functionality and
+   exec $objdir/$outputname directly.
+*/
+EOF
+           cat <<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+# define setmode _setmode
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+#  include <io.h>
+#  define HAVE_SETENV
+#  ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+#  endif
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+#ifdef _MSC_VER
+# define S_IXUSR _S_IEXEC
+# define stat _stat
+# ifndef _INTPTR_T_DEFINED
+#  define intptr_t int
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+  defined (__OS2__)
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+       (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifdef __CYGWIN__
+# define FOPEN_WB "wb"
+#endif
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+  if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+#undef LTWRAPPER_DEBUGPRINTF
+#if defined DEBUGWRAPPER
+# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args
+static void
+ltwrapper_debugprintf (const char *fmt, ...)
+{
+    va_list args;
+    va_start (args, fmt);
+    (void) vfprintf (stderr, fmt, args);
+    va_end (args);
+}
+#else
+# define LTWRAPPER_DEBUGPRINTF(args)
+#endif
+
+const char *program_name = NULL;
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_opt_process_env_set (const char *arg);
+void lt_opt_process_env_prepend (const char *arg);
+void lt_opt_process_env_append (const char *arg);
+int lt_split_name_value (const char *arg, char** name, char** value);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+
+static const char *script_text_part1 =
+EOF
+
+           func_emit_wrapper_part1 yes |
+               $SED -e 's/\([\\"]\)/\\\1/g' \
+                    -e 's/^/  "/' -e 's/$/\\n"/'
+           echo ";"
+           cat <<EOF
+
+static const char *script_text_part2 =
+EOF
+           func_emit_wrapper_part2 yes |
+               $SED -e 's/\([\\"]\)/\\\1/g' \
+                    -e 's/^/  "/' -e 's/$/\\n"/'
+           echo ";"
+
+           cat <<EOF
+const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+           if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+              func_to_host_pathlist "$temp_rpath"
+             cat <<EOF
+const char * LIB_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+           else
+             cat <<"EOF"
+const char * LIB_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test -n "$dllsearchpath"; then
+              func_to_host_pathlist "$dllsearchpath:"
+             cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE   = "$func_to_host_pathlist_result";
+EOF
+           else
+             cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE   = "";
+EOF
+           fi
+
+           if test "$fast_install" = yes; then
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+           else
+             cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+           fi
+
+
+           cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX         "--lt-"
+#define LTWRAPPER_OPTION_PREFIX_LENGTH  5
+
+static const size_t opt_prefix_len         = LTWRAPPER_OPTION_PREFIX_LENGTH;
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+
+static const char *dumpscript_opt       = LTWRAPPER_OPTION_PREFIX "dump-script";
+
+static const size_t env_set_opt_len     = LTWRAPPER_OPTION_PREFIX_LENGTH + 7;
+static const char *env_set_opt          = LTWRAPPER_OPTION_PREFIX "env-set";
+  /* argument is putenv-style "foo=bar", value of foo is set to bar */
+
+static const size_t env_prepend_opt_len = LTWRAPPER_OPTION_PREFIX_LENGTH + 11;
+static const char *env_prepend_opt      = LTWRAPPER_OPTION_PREFIX "env-prepend";
+  /* argument is putenv-style "foo=bar", new value of foo is bar${foo} */
+
+static const size_t env_append_opt_len  = LTWRAPPER_OPTION_PREFIX_LENGTH + 10;
+static const char *env_append_opt       = LTWRAPPER_OPTION_PREFIX "env-append";
+  /* argument is putenv-style "foo=bar", new value of foo is ${foo}bar */
+
+int
+main (int argc, char *argv[])
+{
+  char **newargz;
+  int  newargc;
+  char *tmp_pathspec;
+  char *actual_cwrapper_path;
+  char *actual_cwrapper_name;
+  char *target_name;
+  char *lt_argv_zero;
+  intptr_t rval = 127;
+
+  int i;
+
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) argv[0]      : %s\n", argv[0]));
+  LTWRAPPER_DEBUGPRINTF (("(main) program_name : %s\n", program_name));
+
+  /* very simple arg parsing; don't want to rely on getopt */
+  for (i = 1; i < argc; i++)
+    {
+      if (strcmp (argv[i], dumpscript_opt) == 0)
+       {
+EOF
+           case "$host" in
+             *mingw* | *cygwin* )
+               # make stdout use "unix" line endings
+               echo "          setmode(1,_O_BINARY);"
+               ;;
+             esac
+
+           cat <<"EOF"
+         printf ("%s", script_text_part1);
+         printf ("%s", script_text_part2);
+         return 0;
+       }
+    }
+
+  newargz = XMALLOC (char *, argc + 1);
+  tmp_pathspec = find_executable (argv[0]);
+  if (tmp_pathspec == NULL)
+    lt_fatal ("Couldn't find %s", argv[0]);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (before symlink chase) at : %s\n",
+                         tmp_pathspec));
+
+  actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+  LTWRAPPER_DEBUGPRINTF (("(main) found exe (after symlink chase) at : %s\n",
+                         actual_cwrapper_path));
+  XFREE (tmp_pathspec);
+
+  actual_cwrapper_name = xstrdup( base_name (actual_cwrapper_path));
+  strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+  /* wrapper name transforms */
+  strendzap (actual_cwrapper_name, ".exe");
+  tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+  XFREE (actual_cwrapper_name);
+  actual_cwrapper_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  /* target_name transforms -- use actual target program name; might have lt- prefix */
+  target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+  strendzap (target_name, ".exe");
+  tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+  XFREE (target_name);
+  target_name = tmp_pathspec;
+  tmp_pathspec = 0;
+
+  LTWRAPPER_DEBUGPRINTF (("(main) libtool target name: %s\n",
+                         target_name));
+EOF
+
+           cat <<EOF
+  newargz[0] =
+    XMALLOC (char, (strlen (actual_cwrapper_path) +
+                   strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+  strcpy (newargz[0], actual_cwrapper_path);
+  strcat (newargz[0], "$objdir");
+  strcat (newargz[0], "/");
+EOF
+
+           cat <<"EOF"
+  /* stop here, and copy so we don't have to do this twice */
+  tmp_pathspec = xstrdup (newargz[0]);
+
+  /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+  strcat (newargz[0], actual_cwrapper_name);
+
+  /* DO want the lt- prefix here if it exists, so use target_name */
+  lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+  XFREE (tmp_pathspec);
+  tmp_pathspec = NULL;
+EOF
+
+           case $host_os in
+             mingw*)
+           cat <<"EOF"
+  {
+    char* p;
+    while ((p = strchr (newargz[0], '\\')) != NULL)
+      {
+       *p = '/';
+      }
+    while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+      {
+       *p = '/';
+      }
+  }
+EOF
+           ;;
+           esac
+
+           cat <<"EOF"
+  XFREE (target_name);
+  XFREE (actual_cwrapper_path);
+  XFREE (actual_cwrapper_name);
+
+  lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+  lt_setenv ("DUALCASE", "1");  /* for MSK sh */
+  lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+  lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+
+  newargc=0;
+  for (i = 1; i < argc; i++)
+    {
+      if (strncmp (argv[i], env_set_opt, env_set_opt_len) == 0)
+        {
+          if (argv[i][env_set_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_set_opt_len + 1;
+              lt_opt_process_env_set (p);
+            }
+          else if (argv[i][env_set_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_set (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_set_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_prepend_opt, env_prepend_opt_len) == 0)
+        {
+          if (argv[i][env_prepend_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_prepend_opt_len + 1;
+              lt_opt_process_env_prepend (p);
+            }
+          else if (argv[i][env_prepend_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_prepend (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_prepend_opt);
+          continue;
+        }
+      if (strncmp (argv[i], env_append_opt, env_append_opt_len) == 0)
+        {
+          if (argv[i][env_append_opt_len] == '=')
+            {
+              const char *p = argv[i] + env_append_opt_len + 1;
+              lt_opt_process_env_append (p);
+            }
+          else if (argv[i][env_append_opt_len] == '\0' && i + 1 < argc)
+            {
+              lt_opt_process_env_append (argv[++i]); /* don't copy */
+            }
+          else
+            lt_fatal ("%s missing required argument", env_append_opt);
+          continue;
+        }
+      if (strncmp (argv[i], ltwrapper_option_prefix, opt_prefix_len) == 0)
+        {
+          /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+             namespace, but it is not one of the ones we know about and
+             have already dealt with, above (inluding dump-script), then
+             report an error. Otherwise, targets might begin to believe
+             they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+             namespace. The first time any user complains about this, we'll
+             need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+             or a configure.ac-settable value.
+           */
+          lt_fatal ("Unrecognized option in %s namespace: '%s'",
+                    ltwrapper_option_prefix, argv[i]);
+        }
+      /* otherwise ... */
+      newargz[++newargc] = xstrdup (argv[i]);
+    }
+  newargz[++newargc] = NULL;
+
+  LTWRAPPER_DEBUGPRINTF     (("(main) lt_argv_zero : %s\n", (lt_argv_zero ? lt_argv_zero : "<NULL>")));
+  for (i = 0; i < newargc; i++)
+    {
+      LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d]   : %s\n", i, (newargz[i] ? newargz[i] : "<NULL>")));
+    }
+
+EOF
+
+           case $host_os in
+             mingw*)
+               cat <<"EOF"
+  /* execv doesn't actually work on mingw as expected on unix */
+  rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+  if (rval == -1)
+    {
+      /* failed to start process */
+      LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno));
+      return 127;
+    }
+  return rval;
+EOF
+               ;;
+             *)
+               cat <<"EOF"
+  execv (lt_argv_zero, newargz);
+  return rval; /* =127, but avoids unused variable warning */
+EOF
+               ;;
+           esac
+
+           cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+  void *p = (void *) malloc (num);
+  if (!p)
+    lt_fatal ("Memory exhausted");
+
+  return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+  return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+                         string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+  const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  /* Skip over the disk name in MSDOS pathnames. */
+  if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+    name += 2;
+#endif
+
+  for (base = name; *name; name++)
+    if (IS_DIR_SEPARATOR (*name))
+      base = name + 1;
+  return base;
+}
+
+int
+check_executable (const char *path)
+{
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(check_executable)  : %s\n",
+                         path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0)
+      && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+    return 1;
+  else
+    return 0;
+}
+
+int
+make_executable (const char *path)
+{
+  int rval = 0;
+  struct stat st;
+
+  LTWRAPPER_DEBUGPRINTF (("(make_executable)   : %s\n",
+                         path ? (*path ? path : "EMPTY!") : "NULL!"));
+  if ((!path) || (!*path))
+    return 0;
+
+  if (stat (path, &st) >= 0)
+    {
+      rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+    }
+  return rval;
+}
+
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise
+   Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+  int has_slash = 0;
+  const char *p;
+  const char *p_next;
+  /* static buffer for getcwd */
+  char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char *concat_name;
+
+  LTWRAPPER_DEBUGPRINTF (("(find_executable)   : %s\n",
+                         wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"));
+
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
+
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable (concat_name))
+       return concat_name;
+      XFREE (concat_name);
+    }
+  else
+    {
+#endif
+      if (IS_DIR_SEPARATOR (wrapper[0]))
+       {
+         concat_name = xstrdup (wrapper);
+         if (check_executable (concat_name))
+           return concat_name;
+         XFREE (concat_name);
+       }
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+    }
+#endif
+
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+      {
+       has_slash = 1;
+       break;
+      }
+  if (!has_slash)
+    {
+      /* no slashes; search PATH */
+      const char *path = getenv ("PATH");
+      if (path != NULL)
+       {
+         for (p = path; *p; p = p_next)
+           {
+             const char *q;
+             size_t p_len;
+             for (q = p; *q; q++)
+               if (IS_PATH_SEPARATOR (*q))
+                 break;
+             p_len = q - p;
+             p_next = (*q == '\0' ? q : q + 1);
+             if (p_len == 0)
+               {
+                 /* empty path: current directory */
+                 if (getcwd (tmp, LT_PATHMAX) == NULL)
+                   lt_fatal ("getcwd failed");
+                 tmp_len = strlen (tmp);
+                 concat_name =
+                   XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+                 memcpy (concat_name, tmp, tmp_len);
+                 concat_name[tmp_len] = '/';
+                 strcpy (concat_name + tmp_len + 1, wrapper);
+               }
+             else
+               {
+                 concat_name =
+                   XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+                 memcpy (concat_name, p, p_len);
+                 concat_name[p_len] = '/';
+                 strcpy (concat_name + p_len + 1, wrapper);
+               }
+             if (check_executable (concat_name))
+               return concat_name;
+             XFREE (concat_name);
+           }
+       }
+      /* not found in PATH; assume curdir */
+    }
+  /* Relative path | not found in path: prepend cwd */
+  if (getcwd (tmp, LT_PATHMAX) == NULL)
+    lt_fatal ("getcwd failed");
+  tmp_len = strlen (tmp);
+  concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable (concat_name))
+    return concat_name;
+  XFREE (concat_name);
+  return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+  return xstrdup (pathspec);
+#else
+  char buf[LT_PATHMAX];
+  struct stat s;
+  char *tmp_pathspec = xstrdup (pathspec);
+  char *p;
+  int has_symlinks = 0;
+  while (strlen (tmp_pathspec) && !has_symlinks)
+    {
+      LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n",
+                             tmp_pathspec));
+      if (lstat (tmp_pathspec, &s) == 0)
+       {
+         if (S_ISLNK (s.st_mode) != 0)
+           {
+             has_symlinks = 1;
+             break;
+           }
+
+         /* search backwards for last DIR_SEPARATOR */
+         p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+         while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+           p--;
+         if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+           {
+             /* no more DIR_SEPARATORS left */
+             break;
+           }
+         *p = '\0';
+       }
+      else
+       {
+         char *errstr = strerror (errno);
+         lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr);
+       }
+    }
+  XFREE (tmp_pathspec);
+
+  if (!has_symlinks)
+    {
+      return xstrdup (pathspec);
+    }
+
+  tmp_pathspec = realpath (pathspec, buf);
+  if (tmp_pathspec == 0)
+    {
+      lt_fatal ("Could not follow symlinks for %s", pathspec);
+    }
+  return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+  size_t len, patlen;
+
+  assert (str != NULL);
+  assert (pat != NULL);
+
+  len = strlen (str);
+  patlen = strlen (pat);
+
+  if (patlen <= len)
+    {
+      str += len - patlen;
+      if (strcmp (str, pat) == 0)
+       *str = '\0';
+    }
+  return str;
+}
+
+static void
+lt_error_core (int exit_status, const char *mode,
+              const char *message, va_list ap)
+{
+  fprintf (stderr, "%s: %s: ", program_name, mode);
+  vfprintf (stderr, message, ap);
+  fprintf (stderr, ".\n");
+
+  if (exit_status >= 0)
+    exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+  va_list ap;
+  va_start (ap, message);
+  lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+  va_end (ap);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+  {
+#ifdef HAVE_SETENV
+    /* always make a copy, for consistency with !HAVE_SETENV */
+    char *str = xstrdup (value);
+    setenv (name, str, 1);
+#else
+    int len = strlen (name) + 1 + strlen (value) + 1;
+    char *str = XMALLOC (char, len);
+    sprintf (str, "%s=%s", name, value);
+    if (putenv (str) != EXIT_SUCCESS)
+      {
+        XFREE (str);
+      }
+#endif
+  }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+  char *new_value;
+  if (orig_value && *orig_value)
+    {
+      int orig_value_len = strlen (orig_value);
+      int add_len = strlen (add);
+      new_value = XMALLOC (char, add_len + orig_value_len + 1);
+      if (to_end)
+        {
+          strcpy (new_value, orig_value);
+          strcpy (new_value + orig_value_len, add);
+        }
+      else
+        {
+          strcpy (new_value, add);
+          strcpy (new_value + add_len, orig_value);
+        }
+    }
+  else
+    {
+      new_value = xstrdup (add);
+    }
+  return new_value;
+}
+
+int
+lt_split_name_value (const char *arg, char** name, char** value)
+{
+  const char *p;
+  int len;
+  if (!arg || !*arg)
+    return 1;
+
+  p = strchr (arg, (int)'=');
+
+  if (!p)
+    return 1;
+
+  *value = xstrdup (++p);
+
+  len = strlen (arg) - strlen (*value);
+  *name = XMALLOC (char, len);
+  strncpy (*name, arg, len-1);
+  (*name)[len - 1] = '\0';
+
+  return 0;
+}
+
+void
+lt_opt_process_env_set (const char *arg)
+{
+  char *name = NULL;
+  char *value = NULL;
+
+  if (lt_split_name_value (arg, &name, &value) != 0)
+    {
+      XFREE (name);
+      XFREE (value);
+      lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg);
+    }
+
+  lt_setenv (name, value);
+  XFREE (name);
+  XFREE (value);
+}
+
+void
+lt_opt_process_env_prepend (const char *arg)
+{
+  char *name = NULL;
+  char *value = NULL;
+  char *new_value = NULL;
+
+  if (lt_split_name_value (arg, &name, &value) != 0)
+    {
+      XFREE (name);
+      XFREE (value);
+      lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg);
+    }
+
+  new_value = lt_extend_str (getenv (name), value, 0);
+  lt_setenv (name, new_value);
+  XFREE (new_value);
+  XFREE (name);
+  XFREE (value);
+}
+
+void
+lt_opt_process_env_append (const char *arg)
+{
+  char *name = NULL;
+  char *value = NULL;
+  char *new_value = NULL;
+
+  if (lt_split_name_value (arg, &name, &value) != 0)
+    {
+      XFREE (name);
+      XFREE (value);
+      lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg);
+    }
+
+  new_value = lt_extend_str (getenv (name), value, 1);
+  lt_setenv (name, new_value);
+  XFREE (new_value);
+  XFREE (name);
+  XFREE (value);
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      /* some systems can't cope with a ':'-terminated path #' */
+      int len = strlen (new_value);
+      while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+        {
+          new_value[len-1] = '\0';
+        }
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+  LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+                          (name ? name : "<NULL>"),
+                          (value ? value : "<NULL>")));
+
+  if (name && *name && value && *value)
+    {
+      char *new_value = lt_extend_str (getenv (name), value, 0);
+      lt_setenv (name, new_value);
+      XFREE (new_value);
+    }
+}
+
+
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_mode_link arg...
+func_mode_link ()
+{
+    $opt_debug
+    case $host in
+    *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+      # It is impossible to link a dll without this setting, and
+      # we shouldn't force the makefile maintainer to figure out
+      # which system we are compiling for in order to pass an extra
+      # flag for every libtool invocation.
+      # allow_undefined=no
+
+      # FIXME: Unfortunately, there are problems with the above when trying
+      # to make a dll which has undefined symbols, in which case not
+      # even a static library is built.  For now, we need to specify
+      # -no-undefined on the libtool link line when we can be certain
+      # that all symbols are satisfied, otherwise we get a static library.
+      allow_undefined=yes
+      ;;
+    *)
+      allow_undefined=yes
+      ;;
+    esac
+    libtool_args=$nonopt
+    base_compile="$nonopt $@"
+    compile_command=$nonopt
+    finalize_command=$nonopt
+
+    compile_rpath=
+    finalize_rpath=
+    compile_shlibpath=
+    finalize_shlibpath=
+    convenience=
+    old_convenience=
+    deplibs=
+    old_deplibs=
+    compiler_flags=
+    linker_flags=
+    dllsearchpath=
+    lib_search_path=`pwd`
+    inst_prefix_dir=
+    new_inherited_linker_flags=
+
+    avoid_version=no
+    dlfiles=
+    dlprefiles=
+    dlself=no
+    export_dynamic=no
+    export_symbols=
+    export_symbols_regex=
+    generated=
+    libobjs=
+    ltlibs=
+    module=no
+    no_install=no
+    objs=
+    non_pic_objects=
+    precious_files_regex=
+    prefer_static_libs=no
+    preload=no
+    prev=
+    prevarg=
+    release=
+    rpath=
+    xrpath=
+    perm_rpath=
+    temp_rpath=
+    thread_safe=no
+    vinfo=
+    vinfo_number=no
+    weak_libs=
+    single_module="${wl}-single_module"
+    func_infer_tag $base_compile
+
+    # We need to know -static, to get the right output filenames.
+    for arg
+    do
+      case $arg in
+      -shared)
+       test "$build_libtool_libs" != yes && \
+         func_fatal_configuration "can not build a shared library"
+       build_old_libs=no
+       break
+       ;;
+      -all-static | -static | -static-libtool-libs)
+       case $arg in
+       -all-static)
+         if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+           func_warning "complete static linking is impossible in this configuration"
+         fi
+         if test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       -static)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=built
+         ;;
+       -static-libtool-libs)
+         if test -z "$pic_flag" && test -n "$link_static_flag"; then
+           dlopen_self=$dlopen_self_static
+         fi
+         prefer_static_libs=yes
+         ;;
+       esac
+       build_libtool_libs=no
+       build_old_libs=yes
+       break
+       ;;
+      esac
+    done
+
+    # See if our shared archives depend on static archives.
+    test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+    # Go through the arguments, transforming them on the way.
+    while test "$#" -gt 0; do
+      arg="$1"
+      shift
+      func_quote_for_eval "$arg"
+      qarg=$func_quote_for_eval_unquoted_result
+      func_append libtool_args " $func_quote_for_eval_result"
+
+      # If the previous option needs an argument, assign it.
+      if test -n "$prev"; then
+       case $prev in
+       output)
+         func_append compile_command " @OUTPUT@"
+         func_append finalize_command " @OUTPUT@"
+         ;;
+       esac
+
+       case $prev in
+       dlfiles|dlprefiles)
+         if test "$preload" = no; then
+           # Add the symbol object into the linking commands.
+           func_append compile_command " @SYMFILE@"
+           func_append finalize_command " @SYMFILE@"
+           preload=yes
+         fi
+         case $arg in
+         *.la | *.lo) ;;  # We handle these cases below.
+         force)
+           if test "$dlself" = no; then
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         self)
+           if test "$prev" = dlprefiles; then
+             dlself=yes
+           elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+             dlself=yes
+           else
+             dlself=needless
+             export_dynamic=yes
+           fi
+           prev=
+           continue
+           ;;
+         *)
+           if test "$prev" = dlfiles; then
+             dlfiles="$dlfiles $arg"
+           else
+             dlprefiles="$dlprefiles $arg"
+           fi
+           prev=
+           continue
+           ;;
+         esac
+         ;;
+       expsyms)
+         export_symbols="$arg"
+         test -f "$arg" \
+           || func_fatal_error "symbol file \`$arg' does not exist"
+         prev=
+         continue
+         ;;
+       expsyms_regex)
+         export_symbols_regex="$arg"
+         prev=
+         continue
+         ;;
+       framework)
+         case $host in
+           *-*-darwin*)
+             case "$deplibs " in
+               *" $qarg.ltframework "*) ;;
+               *) deplibs="$deplibs $qarg.ltframework" # this is fixed later
+                  ;;
+             esac
+             ;;
+         esac
+         prev=
+         continue
+         ;;
+       inst_prefix)
+         inst_prefix_dir="$arg"
+         prev=
+         continue
+         ;;
+       objectlist)
+         if test -f "$arg"; then
+           save_arg=$arg
+           moreargs=
+           for fil in `cat "$save_arg"`
+           do
+#            moreargs="$moreargs $fil"
+             arg=$fil
+             # A libtool-controlled object.
+
+             # Check to see that this really is a libtool object.
+             if func_lalib_unsafe_p "$arg"; then
+               pic_object=
+               non_pic_object=
+
+               # Read the .lo file
+               func_source "$arg"
+
+               if test -z "$pic_object" ||
+                  test -z "$non_pic_object" ||
+                  test "$pic_object" = none &&
+                  test "$non_pic_object" = none; then
+                 func_fatal_error "cannot find name of object for \`$arg'"
+               fi
+
+               # Extract subdirectory from the argument.
+               func_dirname "$arg" "/" ""
+               xdir="$func_dirname_result"
+
+               if test "$pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 pic_object="$xdir$pic_object"
+
+                 if test "$prev" = dlfiles; then
+                   if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+                     dlfiles="$dlfiles $pic_object"
+                     prev=
+                     continue
+                   else
+                     # If libtool objects are unsupported, then we need to preload.
+                     prev=dlprefiles
+                   fi
+                 fi
+
+                 # CHECK ME:  I think I busted this.  -Ossama
+                 if test "$prev" = dlprefiles; then
+                   # Preload the old-style object.
+                   dlprefiles="$dlprefiles $pic_object"
+                   prev=
+                 fi
+
+                 # A PIC object.
+                 func_append libobjs " $pic_object"
+                 arg="$pic_object"
+               fi
+
+               # Non-PIC object.
+               if test "$non_pic_object" != none; then
+                 # Prepend the subdirectory the object is found in.
+                 non_pic_object="$xdir$non_pic_object"
+
+                 # A standard non-PIC object
+                 func_append non_pic_objects " $non_pic_object"
+                 if test -z "$pic_object" || test "$pic_object" = none ; then
+                   arg="$non_pic_object"
+                 fi
+               else
+                 # If the PIC object exists, use it instead.
+                 # $xdir was prepended to $pic_object above.
+                 non_pic_object="$pic_object"
+                 func_append non_pic_objects " $non_pic_object"
+               fi
+             else
+               # Only an error if not doing a dry-run.
+               if $opt_dry_run; then
+                 # Extract subdirectory from the argument.
+                 func_dirname "$arg" "/" ""
+                 xdir="$func_dirname_result"
+
+                 func_lo2o "$arg"
+                 pic_object=$xdir$objdir/$func_lo2o_result
+                 non_pic_object=$xdir$func_lo2o_result
+                 func_append libobjs " $pic_object"
+                 func_append non_pic_objects " $non_pic_object"
+               else
+                 func_fatal_error "\`$arg' is not a valid libtool object"
+               fi
+             fi
+           done
+         else
+           func_fatal_error "link input file \`$arg' does not exist"
+         fi
+         arg=$save_arg
+         prev=
+         continue
+         ;;
+       precious_regex)
+         precious_files_regex="$arg"
+         prev=
+         continue
+         ;;
+       release)
+         release="-$arg"
+         prev=
+         continue
+         ;;
+       rpath | xrpath)
+         # We need an absolute path.
+         case $arg in
+         [\\/]* | [A-Za-z]:[\\/]*) ;;
+         *)
+           func_fatal_error "only absolute run-paths are allowed"
+           ;;
+         esac
+         if test "$prev" = rpath; then
+           case "$rpath " in
+           *" $arg "*) ;;
+           *) rpath="$rpath $arg" ;;
+           esac
+         else
+           case "$xrpath " in
+           *" $arg "*) ;;
+           *) xrpath="$xrpath $arg" ;;
+           esac
+         fi
+         prev=
+         continue
+         ;;
+       shrext)
+         shrext_cmds="$arg"
+         prev=
+         continue
+         ;;
+       weak)
+         weak_libs="$weak_libs $arg"
+         prev=
+         continue
+         ;;
+       xcclinker)
+         linker_flags="$linker_flags $qarg"
+         compiler_flags="$compiler_flags $qarg"
+         prev=
+         func_append compile_command " $qarg"
+         func_append finalize_command " $qarg"
+         continue
+         ;;
+       xcompiler)
+         compiler_flags="$compiler_flags $qarg"
+         prev=
+         func_append compile_command " $qarg"
+         func_append finalize_command " $qarg"
+         continue
+         ;;
+       xlinker)
+         linker_flags="$linker_flags $qarg"
+         compiler_flags="$compiler_flags $wl$qarg"
+         prev=
+         func_append compile_command " $wl$qarg"
+         func_append finalize_command " $wl$qarg"
+         continue
+         ;;
+       *)
+         eval "$prev=\"\$arg\""
+         prev=
+         continue
+         ;;
+       esac
+      fi # test -n "$prev"
+
+      prevarg="$arg"
+
+      case $arg in
+      -all-static)
+       if test -n "$link_static_flag"; then
+         # See comment for -static flag below, for more details.
+         func_append compile_command " $link_static_flag"
+         func_append finalize_command " $link_static_flag"
+       fi
+       continue
+       ;;
+
+      -allow-undefined)
+       # FIXME: remove this flag sometime in the future.
+       func_fatal_error "\`-allow-undefined' must not be used because it is the default"
+       ;;
+
+      -avoid-version)
+       avoid_version=yes
+       continue
+       ;;
+
+      -dlopen)
+       prev=dlfiles
+       continue
+       ;;
+
+      -dlpreopen)
+       prev=dlprefiles
+       continue
+       ;;
+
+      -export-dynamic)
+       export_dynamic=yes
+       continue
+       ;;
+
+      -export-symbols | -export-symbols-regex)
+       if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+         func_fatal_error "more than one -exported-symbols argument is not allowed"
+       fi
+       if test "X$arg" = "X-export-symbols"; then
+         prev=expsyms
+       else
+         prev=expsyms_regex
+       fi
+       continue
+       ;;
+
+      -framework)
+       prev=framework
+       continue
+       ;;
+
+      -inst-prefix-dir)
+       prev=inst_prefix
+       continue
+       ;;
+
+      # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+      # so, if we see these flags be careful not to treat them like -L
+      -L[A-Z][A-Z]*:*)
+       case $with_gcc/$host in
+       no/*-*-irix* | /*-*-irix*)
+         func_append compile_command " $arg"
+         func_append finalize_command " $arg"
+         ;;
+       esac
+       continue
+       ;;
+
+      -L*)
+       func_stripname '-L' '' "$arg"
+       dir=$func_stripname_result
+       if test -z "$dir"; then
+         if test "$#" -gt 0; then
+           func_fatal_error "require no space between \`-L' and \`$1'"
+         else
+           func_fatal_error "need path for \`-L' option"
+         fi
+       fi
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         absdir=`cd "$dir" && pwd`
+         test -z "$absdir" && \
+           func_fatal_error "cannot determine absolute directory name of \`$dir'"
+         dir="$absdir"
+         ;;
+       esac
+       case "$deplibs " in
+       *" -L$dir "*) ;;
+       *)
+         deplibs="$deplibs -L$dir"
+         lib_search_path="$lib_search_path $dir"
+         ;;
+       esac
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+         testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$dir:"*) ;;
+         ::) dllsearchpath=$dir;;
+         *) dllsearchpath="$dllsearchpath:$dir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         ::) dllsearchpath=$testbindir;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
+         ;;
+       esac
+       continue
+       ;;
+
+      -l*)
+       if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*)
+           # These systems don't actually have a C or math library (as such)
+           continue
+           ;;
+         *-*-os2*)
+           # These systems don't actually have a C library (as such)
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C and math libraries are in the System framework
+           deplibs="$deplibs System.ltframework"
+           continue
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           test "X$arg" = "X-lc" && continue
+           ;;
+         esac
+       elif test "X$arg" = "X-lc_r"; then
+        case $host in
+        *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+          # Do not include libc_r directly, use -pthread flag.
+          continue
+          ;;
+        esac
+       fi
+       deplibs="$deplibs $arg"
+       continue
+       ;;
+
+      -module)
+       module=yes
+       continue
+       ;;
+
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      # Darwin uses the -arch flag to determine output architecture.
+      -model|-arch|-isysroot)
+       compiler_flags="$compiler_flags $arg"
+       func_append compile_command " $arg"
+       func_append finalize_command " $arg"
+       prev=xcompiler
+       continue
+       ;;
+
+      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+       compiler_flags="$compiler_flags $arg"
+       func_append compile_command " $arg"
+       func_append finalize_command " $arg"
+       case "$new_inherited_linker_flags " in
+           *" $arg "*) ;;
+           * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;;
+       esac
+       continue
+       ;;
+
+      -multi_module)
+       single_module="${wl}-multi_module"
+       continue
+       ;;
+
+      -no-fast-install)
+       fast_install=no
+       continue
+       ;;
+
+      -no-install)
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+         # The PATH hackery in wrapper scripts is required on Windows
+         # and Darwin in order for the loader to find any dlls it needs.
+         func_warning "\`-no-install' is ignored for $host"
+         func_warning "assuming \`-no-fast-install' instead"
+         fast_install=no
+         ;;
+       *) no_install=yes ;;
+       esac
+       continue
+       ;;
+
+      -no-undefined)
+       allow_undefined=no
+       continue
+       ;;
+
+      -objectlist)
+       prev=objectlist
+       continue
+       ;;
+
+      -o) prev=output ;;
+
+      -precious-files-regex)
+       prev=precious_regex
+       continue
+       ;;
+
+      -release)
+       prev=release
+       continue
+       ;;
+
+      -rpath)
+       prev=rpath
+       continue
+       ;;
+
+      -R)
+       prev=xrpath
+       continue
+       ;;
+
+      -R*)
+       func_stripname '-R' '' "$arg"
+       dir=$func_stripname_result
+       # We need an absolute path.
+       case $dir in
+       [\\/]* | [A-Za-z]:[\\/]*) ;;
+       *)
+         func_fatal_error "only absolute run-paths are allowed"
+         ;;
+       esac
+       case "$xrpath " in
+       *" $dir "*) ;;
+       *) xrpath="$xrpath $dir" ;;
+       esac
+       continue
+       ;;
+
+      -shared)
+       # The effects of -shared are defined in a previous loop.
+       continue
+       ;;
+
+      -shrext)
+       prev=shrext
+       continue
+       ;;
+
+      -static | -static-libtool-libs)
+       # The effects of -static are defined in a previous loop.
+       # We used to do the same as -all-static on platforms that
+       # didn't have a PIC flag, but the assumption that the effects
+       # would be equivalent was wrong.  It would break on at least
+       # Digital Unix and AIX.
+       continue
+       ;;
+
+      -thread-safe)
+       thread_safe=yes
+       continue
+       ;;
+
+      -version-info)
+       prev=vinfo
+       continue
+       ;;
+
+      -version-number)
+       prev=vinfo
+       vinfo_number=yes
+       continue
+       ;;
+
+      -weak)
+        prev=weak
+       continue
+       ;;
+
+      -Wc,*)
+       func_stripname '-Wc,' '' "$arg"
+       args=$func_stripname_result
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+         arg="$arg $wl$func_quote_for_eval_result"
+         compiler_flags="$compiler_flags $func_quote_for_eval_result"
+       done
+       IFS="$save_ifs"
+       func_stripname ' ' '' "$arg"
+       arg=$func_stripname_result
+       ;;
+
+      -Wl,*)
+       func_stripname '-Wl,' '' "$arg"
+       args=$func_stripname_result
+       arg=
+       save_ifs="$IFS"; IFS=','
+       for flag in $args; do
+         IFS="$save_ifs"
+          func_quote_for_eval "$flag"
+         arg="$arg $wl$func_quote_for_eval_result"
+         compiler_flags="$compiler_flags $wl$func_quote_for_eval_result"
+         linker_flags="$linker_flags $func_quote_for_eval_result"
+       done
+       IFS="$save_ifs"
+       func_stripname ' ' '' "$arg"
+       arg=$func_stripname_result
+       ;;
+
+      -Xcompiler)
+       prev=xcompiler
+       continue
+       ;;
+
+      -Xlinker)
+       prev=xlinker
+       continue
+       ;;
+
+      -XCClinker)
+       prev=xcclinker
+       continue
+       ;;
+
+      # -msg_* for osf cc
+      -msg_*)
+       func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+       ;;
+
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -F/path gives path to uninstalled frameworks, gcc on darwin
+      # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC
+      # @file GCC response files
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+      -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*)
+        func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+        func_append compile_command " $arg"
+        func_append finalize_command " $arg"
+        compiler_flags="$compiler_flags $arg"
+        continue
+        ;;
+
+      # Some other compiler flag.
+      -* | +*)
+        func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+       ;;
+
+      *.$objext)
+       # A standard object.
+       objs="$objs $arg"
+       ;;
+
+      *.lo)
+       # A libtool-controlled object.
+
+       # Check to see that this really is a libtool object.
+       if func_lalib_unsafe_p "$arg"; then
+         pic_object=
+         non_pic_object=
+
+         # Read the .lo file
+         func_source "$arg"
+
+         if test -z "$pic_object" ||
+            test -z "$non_pic_object" ||
+            test "$pic_object" = none &&
+            test "$non_pic_object" = none; then
+           func_fatal_error "cannot find name of object for \`$arg'"
+         fi
+
+         # Extract subdirectory from the argument.
+         func_dirname "$arg" "/" ""
+         xdir="$func_dirname_result"
+
+         if test "$pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           pic_object="$xdir$pic_object"
+
+           if test "$prev" = dlfiles; then
+             if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+               dlfiles="$dlfiles $pic_object"
+               prev=
+               continue
+             else
+               # If libtool objects are unsupported, then we need to preload.
+               prev=dlprefiles
+             fi
+           fi
+
+           # CHECK ME:  I think I busted this.  -Ossama
+           if test "$prev" = dlprefiles; then
+             # Preload the old-style object.
+             dlprefiles="$dlprefiles $pic_object"
+             prev=
+           fi
+
+           # A PIC object.
+           func_append libobjs " $pic_object"
+           arg="$pic_object"
+         fi
+
+         # Non-PIC object.
+         if test "$non_pic_object" != none; then
+           # Prepend the subdirectory the object is found in.
+           non_pic_object="$xdir$non_pic_object"
+
+           # A standard non-PIC object
+           func_append non_pic_objects " $non_pic_object"
+           if test -z "$pic_object" || test "$pic_object" = none ; then
+             arg="$non_pic_object"
+           fi
+         else
+           # If the PIC object exists, use it instead.
+           # $xdir was prepended to $pic_object above.
+           non_pic_object="$pic_object"
+           func_append non_pic_objects " $non_pic_object"
+         fi
+       else
+         # Only an error if not doing a dry-run.
+         if $opt_dry_run; then
+           # Extract subdirectory from the argument.
+           func_dirname "$arg" "/" ""
+           xdir="$func_dirname_result"
+
+           func_lo2o "$arg"
+           pic_object=$xdir$objdir/$func_lo2o_result
+           non_pic_object=$xdir$func_lo2o_result
+           func_append libobjs " $pic_object"
+           func_append non_pic_objects " $non_pic_object"
+         else
+           func_fatal_error "\`$arg' is not a valid libtool object"
+         fi
+       fi
+       ;;
+
+      *.$libext)
+       # An archive.
+       deplibs="$deplibs $arg"
+       old_deplibs="$old_deplibs $arg"
+       continue
+       ;;
+
+      *.la)
+       # A libtool-controlled library.
+
+       if test "$prev" = dlfiles; then
+         # This library was specified with -dlopen.
+         dlfiles="$dlfiles $arg"
+         prev=
+       elif test "$prev" = dlprefiles; then
+         # The library was specified with -dlpreopen.
+         dlprefiles="$dlprefiles $arg"
+         prev=
+       else
+         deplibs="$deplibs $arg"
+       fi
+       continue
+       ;;
+
+      # Some other compiler argument.
+      *)
+       # Unknown arguments in both finalize_command and compile_command need
+       # to be aesthetically quoted because they are evaled later.
+       func_quote_for_eval "$arg"
+       arg="$func_quote_for_eval_result"
+       ;;
+      esac # arg
+
+      # Now actually substitute the argument into the commands.
+      if test -n "$arg"; then
+       func_append compile_command " $arg"
+       func_append finalize_command " $arg"
+      fi
+    done # argument parsing loop
+
+    test -n "$prev" && \
+      func_fatal_help "the \`$prevarg' option requires an argument"
+
+    if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+      eval arg=\"$export_dynamic_flag_spec\"
+      func_append compile_command " $arg"
+      func_append finalize_command " $arg"
+    fi
+
+    oldlibs=
+    # calculate the name of the file, without its directory
+    func_basename "$output"
+    outputname="$func_basename_result"
+    libobjs_save="$libobjs"
+
+    if test -n "$shlibpath_var"; then
+      # get the directories listed in $shlibpath_var
+      eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+    else
+      shlib_search_path=
+    fi
+    eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+    eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+    func_dirname "$output" "/" ""
+    output_objdir="$func_dirname_result$objdir"
+    # Create the object directory.
+    func_mkdir_p "$output_objdir"
+
+    # Determine the type of output
+    case $output in
+    "")
+      func_fatal_help "you must specify an output file"
+      ;;
+    *.$libext) linkmode=oldlib ;;
+    *.lo | *.$objext) linkmode=obj ;;
+    *.la) linkmode=lib ;;
+    *) linkmode=prog ;; # Anything else should be a program.
+    esac
+
+    specialdeplibs=
+
+    libs=
+    # Find all interdependent deplibs by searching for libraries
+    # that are linked more than once (e.g. -la -lb -la)
+    for deplib in $deplibs; do
+      if $opt_duplicate_deps ; then
+       case "$libs " in
+       *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+       esac
+      fi
+      libs="$libs $deplib"
+    done
+
+    if test "$linkmode" = lib; then
+      libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+      # Compute libraries that are listed more than once in $predeps
+      # $postdeps and mark them as special (i.e., whose duplicates are
+      # not to be eliminated).
+      pre_post_deps=
+      if $opt_duplicate_compiler_generated_deps; then
+       for pre_post_dep in $predeps $postdeps; do
+         case "$pre_post_deps " in
+         *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+         esac
+         pre_post_deps="$pre_post_deps $pre_post_dep"
+       done
+      fi
+      pre_post_deps=
+    fi
+
+    deplibs=
+    newdependency_libs=
+    newlib_search_path=
+    need_relink=no # whether we're linking any uninstalled libtool libraries
+    notinst_deplibs= # not-installed libtool libraries
+    notinst_path= # paths that contain not-installed libtool libraries
+
+    case $linkmode in
+    lib)
+       passes="conv dlpreopen link"
+       for file in $dlfiles $dlprefiles; do
+         case $file in
+         *.la) ;;
+         *)
+           func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file"
+           ;;
+         esac
+       done
+       ;;
+    prog)
+       compile_deplibs=
+       finalize_deplibs=
+       alldeplibs=no
+       newdlfiles=
+       newdlprefiles=
+       passes="conv scan dlopen dlpreopen link"
+       ;;
+    *)  passes="conv"
+       ;;
+    esac
+
+    for pass in $passes; do
+      # The preopen pass in lib mode reverses $deplibs; put it back here
+      # so that -L comes before libs that need it for instance...
+      if test "$linkmode,$pass" = "lib,link"; then
+       ## FIXME: Find the place where the list is rebuilt in the wrong
+       ##        order, and fix it there properly
+        tmp_deplibs=
+       for deplib in $deplibs; do
+         tmp_deplibs="$deplib $tmp_deplibs"
+       done
+       deplibs="$tmp_deplibs"
+      fi
+
+      if test "$linkmode,$pass" = "lib,link" ||
+        test "$linkmode,$pass" = "prog,scan"; then
+       libs="$deplibs"
+       deplibs=
+      fi
+      if test "$linkmode" = prog; then
+       case $pass in
+       dlopen) libs="$dlfiles" ;;
+       dlpreopen) libs="$dlprefiles" ;;
+       link)
+         libs="$deplibs %DEPLIBS%"
+         test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+         ;;
+       esac
+      fi
+      if test "$linkmode,$pass" = "lib,dlpreopen"; then
+       # Collect and forward deplibs of preopened libtool libs
+       for lib in $dlprefiles; do
+         # Ignore non-libtool-libs
+         dependency_libs=
+         case $lib in
+         *.la) func_source "$lib" ;;
+         esac
+
+         # Collect preopened libtool deplibs, except any this library
+         # has declared as weak libs
+         for deplib in $dependency_libs; do
+            deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"`
+           case " $weak_libs " in
+           *" $deplib_base "*) ;;
+           *) deplibs="$deplibs $deplib" ;;
+           esac
+         done
+       done
+       libs="$dlprefiles"
+      fi
+      if test "$pass" = dlopen; then
+       # Collect dlpreopened libraries
+       save_deplibs="$deplibs"
+       deplibs=
+      fi
+
+      for deplib in $libs; do
+       lib=
+       found=no
+       case $deplib in
+       -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads)
+         if test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$deplib $compile_deplibs"
+           finalize_deplibs="$deplib $finalize_deplibs"
+         else
+           compiler_flags="$compiler_flags $deplib"
+           if test "$linkmode" = lib ; then
+               case "$new_inherited_linker_flags " in
+                   *" $deplib "*) ;;
+                   * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+               esac
+           fi
+         fi
+         continue
+         ;;
+       -l*)
+         if test "$linkmode" != lib && test "$linkmode" != prog; then
+           func_warning "\`-l' is ignored for archives/objects"
+           continue
+         fi
+         func_stripname '-l' '' "$deplib"
+         name=$func_stripname_result
+         if test "$linkmode" = lib; then
+           searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+         else
+           searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+         fi
+         for searchdir in $searchdirs; do
+           for search_ext in .la $std_shrext .so .a; do
+             # Search the libtool library
+             lib="$searchdir/lib${name}${search_ext}"
+             if test -f "$lib"; then
+               if test "$search_ext" = ".la"; then
+                 found=yes
+               else
+                 found=no
+               fi
+               break 2
+             fi
+           done
+         done
+         if test "$found" != yes; then
+           # deplib doesn't seem to be a libtool library
+           if test "$linkmode,$pass" = "prog,link"; then
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             deplibs="$deplib $deplibs"
+             test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+           fi
+           continue
+         else # deplib is a libtool library
+           # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+           # We need to do some special things here, and not later.
+           if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+             case " $predeps $postdeps " in
+             *" $deplib "*)
+               if func_lalib_p "$lib"; then
+                 library_names=
+                 old_library=
+                 func_source "$lib"
+                 for l in $old_library $library_names; do
+                   ll="$l"
+                 done
+                 if test "X$ll" = "X$old_library" ; then # only static version available
+                   found=no
+                   func_dirname "$lib" "" "."
+                   ladir="$func_dirname_result"
+                   lib=$ladir/$old_library
+                   if test "$linkmode,$pass" = "prog,link"; then
+                     compile_deplibs="$deplib $compile_deplibs"
+                     finalize_deplibs="$deplib $finalize_deplibs"
+                   else
+                     deplibs="$deplib $deplibs"
+                     test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+                   fi
+                   continue
+                 fi
+               fi
+               ;;
+             *) ;;
+             esac
+           fi
+         fi
+         ;; # -l
+       *.ltframework)
+         if test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$deplib $compile_deplibs"
+           finalize_deplibs="$deplib $finalize_deplibs"
+         else
+           deplibs="$deplib $deplibs"
+           if test "$linkmode" = lib ; then
+               case "$new_inherited_linker_flags " in
+                   *" $deplib "*) ;;
+                   * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;;
+               esac
+           fi
+         fi
+         continue
+         ;;
+       -L*)
+         case $linkmode in
+         lib)
+           deplibs="$deplib $deplibs"
+           test "$pass" = conv && continue
+           newdependency_libs="$deplib $newdependency_libs"
+           func_stripname '-L' '' "$deplib"
+           newlib_search_path="$newlib_search_path $func_stripname_result"
+           ;;
+         prog)
+           if test "$pass" = conv; then
+             deplibs="$deplib $deplibs"
+             continue
+           fi
+           if test "$pass" = scan; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           func_stripname '-L' '' "$deplib"
+           newlib_search_path="$newlib_search_path $func_stripname_result"
+           ;;
+         *)
+           func_warning "\`-L' is ignored for archives/objects"
+           ;;
+         esac # linkmode
+         continue
+         ;; # -L
+       -R*)
+         if test "$pass" = link; then
+           func_stripname '-R' '' "$deplib"
+           dir=$func_stripname_result
+           # Make sure the xrpath contains only unique directories.
+           case "$xrpath " in
+           *" $dir "*) ;;
+           *) xrpath="$xrpath $dir" ;;
+           esac
+         fi
+         deplibs="$deplib $deplibs"
+         continue
+         ;;
+       *.la) lib="$deplib" ;;
+       *.$libext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+           continue
+         fi
+         case $linkmode in
+         lib)
+           # Linking convenience modules into shared libraries is allowed,
+           # but linking other static libraries is non-portable.
+           case " $dlpreconveniencelibs " in
+           *" $deplib "*) ;;
+           *)
+             valid_a_lib=no
+             case $deplibs_check_method in
+               match_pattern*)
+                 set dummy $deplibs_check_method; shift
+                 match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+                 if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \
+                   | $EGREP "$match_pattern_regex" > /dev/null; then
+                   valid_a_lib=yes
+                 fi
+               ;;
+               pass_all)
+                 valid_a_lib=yes
+               ;;
+             esac
+             if test "$valid_a_lib" != yes; then
+               $ECHO
+               $ECHO "*** Warning: Trying to link with static lib archive $deplib."
+               $ECHO "*** I have the capability to make that library automatically link in when"
+               $ECHO "*** you link to this library.  But I can only do this if you have a"
+               $ECHO "*** shared version of the library, which you do not appear to have"
+               $ECHO "*** because the file extensions .$libext of this argument makes me believe"
+               $ECHO "*** that it is just a static archive that I should not use here."
+             else
+               $ECHO
+               $ECHO "*** Warning: Linking the shared library $output against the"
+               $ECHO "*** static library $deplib is not portable!"
+               deplibs="$deplib $deplibs"
+             fi
+             ;;
+           esac
+           continue
+           ;;
+         prog)
+           if test "$pass" != link; then
+             deplibs="$deplib $deplibs"
+           else
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           fi
+           continue
+           ;;
+         esac # linkmode
+         ;; # *.$libext
+       *.lo | *.$objext)
+         if test "$pass" = conv; then
+           deplibs="$deplib $deplibs"
+         elif test "$linkmode" = prog; then
+           if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+             # If there is no dlopen support or we're linking statically,
+             # we need to preload.
+             newdlprefiles="$newdlprefiles $deplib"
+             compile_deplibs="$deplib $compile_deplibs"
+             finalize_deplibs="$deplib $finalize_deplibs"
+           else
+             newdlfiles="$newdlfiles $deplib"
+           fi
+         fi
+         continue
+         ;;
+       %DEPLIBS%)
+         alldeplibs=yes
+         continue
+         ;;
+       esac # case $deplib
+
+       if test "$found" = yes || test -f "$lib"; then :
+       else
+         func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'"
+       fi
+
+       # Check to see that this really is a libtool archive.
+       func_lalib_unsafe_p "$lib" \
+         || func_fatal_error "\`$lib' is not a valid libtool archive"
+
+       func_dirname "$lib" "" "."
+       ladir="$func_dirname_result"
+
+       dlname=
+       dlopen=
+       dlpreopen=
+       libdir=
+       library_names=
+       old_library=
+       inherited_linker_flags=
+       # If the library was installed with an old release of libtool,
+       # it will not redefine variables installed, or shouldnotlink
+       installed=yes
+       shouldnotlink=no
+       avoidtemprpath=
+
+
+       # Read the .la file
+       func_source "$lib"
+
+       # Convert "-framework foo" to "foo.ltframework"
+       if test -n "$inherited_linker_flags"; then
+         tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'`
+         for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+           case " $new_inherited_linker_flags " in
+             *" $tmp_inherited_linker_flag "*) ;;
+             *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";;
+           esac
+         done
+       fi
+       dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+       if test "$linkmode,$pass" = "lib,link" ||
+          test "$linkmode,$pass" = "prog,scan" ||
+          { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+         test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+         test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+       fi
+
+       if test "$pass" = conv; then
+         # Only check for convenience libraries
+         deplibs="$lib $deplibs"
+         if test -z "$libdir"; then
+           if test -z "$old_library"; then
+             func_fatal_error "cannot find name of link library for \`$lib'"
+           fi
+           # It is a libtool convenience library, so add in its objects.
+           convenience="$convenience $ladir/$objdir/$old_library"
+           old_convenience="$old_convenience $ladir/$objdir/$old_library"
+           tmp_libs=
+           for deplib in $dependency_libs; do
+             deplibs="$deplib $deplibs"
+             if $opt_duplicate_deps ; then
+               case "$tmp_libs " in
+               *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+               esac
+             fi
+             tmp_libs="$tmp_libs $deplib"
+           done
+         elif test "$linkmode" != prog && test "$linkmode" != lib; then
+           func_fatal_error "\`$lib' is not a convenience library"
+         fi
+         continue
+       fi # $pass = conv
+
+
+       # Get the name of the library we link against.
+       linklib=
+       for l in $old_library $library_names; do
+         linklib="$l"
+       done
+       if test -z "$linklib"; then
+         func_fatal_error "cannot find name of link library for \`$lib'"
+       fi
+
+       # This library was specified with -dlopen.
+       if test "$pass" = dlopen; then
+         if test -z "$libdir"; then
+           func_fatal_error "cannot -dlopen a convenience library: \`$lib'"
+         fi
+         if test -z "$dlname" ||
+            test "$dlopen_support" != yes ||
+            test "$build_libtool_libs" = no; then
+           # If there is no dlname, no dlopen support or we're linking
+           # statically, we need to preload.  We also need to preload any
+           # dependent libraries so libltdl's deplib preloader doesn't
+           # bomb out in the load deplibs phase.
+           dlprefiles="$dlprefiles $lib $dependency_libs"
+         else
+           newdlfiles="$newdlfiles $lib"
+         fi
+         continue
+       fi # $pass = dlopen
+
+       # We need an absolute path.
+       case $ladir in
+       [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+       *)
+         abs_ladir=`cd "$ladir" && pwd`
+         if test -z "$abs_ladir"; then
+           func_warning "cannot determine absolute directory name of \`$ladir'"
+           func_warning "passing it literally to the linker, although it might fail"
+           abs_ladir="$ladir"
+         fi
+         ;;
+       esac
+       func_basename "$lib"
+       laname="$func_basename_result"
+
+       # Find the relevant object directory and library name.
+       if test "X$installed" = Xyes; then
+         if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           func_warning "library \`$lib' was moved."
+           dir="$ladir"
+           absdir="$abs_ladir"
+           libdir="$abs_ladir"
+         else
+           dir="$libdir"
+           absdir="$libdir"
+         fi
+         test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
+       else
+         if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           dir="$ladir"
+           absdir="$abs_ladir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         else
+           dir="$ladir/$objdir"
+           absdir="$abs_ladir/$objdir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         fi
+       fi # $installed = yes
+       func_stripname 'lib' '.la' "$laname"
+       name=$func_stripname_result
+
+       # This library was specified with -dlpreopen.
+       if test "$pass" = dlpreopen; then
+         if test -z "$libdir" && test "$linkmode" = prog; then
+           func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'"
+         fi
+         # Prefer using a static library (so that no silly _DYNAMIC symbols
+         # are required to link).
+         if test -n "$old_library"; then
+           newdlprefiles="$newdlprefiles $dir/$old_library"
+           # Keep a list of preopened convenience libraries to check
+           # that they are being used correctly in the link pass.
+           test -z "$libdir" && \
+               dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library"
+         # Otherwise, use the dlname, so that lt_dlopen finds it.
+         elif test -n "$dlname"; then
+           newdlprefiles="$newdlprefiles $dir/$dlname"
+         else
+           newdlprefiles="$newdlprefiles $dir/$linklib"
+         fi
+       fi # $pass = dlpreopen
+
+       if test -z "$libdir"; then
+         # Link the convenience library
+         if test "$linkmode" = lib; then
+           deplibs="$dir/$old_library $deplibs"
+         elif test "$linkmode,$pass" = "prog,link"; then
+           compile_deplibs="$dir/$old_library $compile_deplibs"
+           finalize_deplibs="$dir/$old_library $finalize_deplibs"
+         else
+           deplibs="$lib $deplibs" # used for prog,scan pass
+         fi
+         continue
+       fi
+
+
+       if test "$linkmode" = prog && test "$pass" != link; then
+         newlib_search_path="$newlib_search_path $ladir"
+         deplibs="$lib $deplibs"
+
+         linkalldeplibs=no
+         if test "$link_all_deplibs" != no || test -z "$library_names" ||
+            test "$build_libtool_libs" = no; then
+           linkalldeplibs=yes
+         fi
+
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           case $deplib in
+           -L*) func_stripname '-L' '' "$deplib"
+                newlib_search_path="$newlib_search_path $func_stripname_result"
+                ;;
+           esac
+           # Need to link against all dependency_libs?
+           if test "$linkalldeplibs" = yes; then
+             deplibs="$deplib $deplibs"
+           else
+             # Need to hardcode shared library paths
+             # or/and link against static libraries
+             newdependency_libs="$deplib $newdependency_libs"
+           fi
+           if $opt_duplicate_deps ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done # for deplib
+         continue
+       fi # $linkmode = prog...
+
+       if test "$linkmode,$pass" = "prog,link"; then
+         if test -n "$library_names" &&
+            { { test "$prefer_static_libs" = no ||
+                test "$prefer_static_libs,$installed" = "built,yes"; } ||
+              test -z "$old_library"; }; then
+           # We need to hardcode the library path
+           if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
+             # Make sure the rpath contains only unique directories.
+             case "$temp_rpath:" in
+             *"$absdir:"*) ;;
+             *) temp_rpath="$temp_rpath$absdir:" ;;
+             esac
+           fi
+
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) compile_rpath="$compile_rpath $absdir"
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) finalize_rpath="$finalize_rpath $libdir"
+             esac
+             ;;
+           esac
+         fi # $linkmode,$pass = prog,link...
+
+         if test "$alldeplibs" = yes &&
+            { test "$deplibs_check_method" = pass_all ||
+              { test "$build_libtool_libs" = yes &&
+                test -n "$library_names"; }; }; then
+           # We only need to search for static libraries
+           continue
+         fi
+       fi
+
+       link_static=no # Whether the deplib will be linked statically
+       use_static_libs=$prefer_static_libs
+       if test "$use_static_libs" = built && test "$installed" = yes; then
+         use_static_libs=no
+       fi
+       if test -n "$library_names" &&
+          { test "$use_static_libs" = no || test -z "$old_library"; }; then
+         case $host in
+         *cygwin* | *mingw* | *cegcc*)
+             # No point in relinking DLLs because paths are not encoded
+             notinst_deplibs="$notinst_deplibs $lib"
+             need_relink=no
+           ;;
+         *)
+           if test "$installed" = no; then
+             notinst_deplibs="$notinst_deplibs $lib"
+             need_relink=yes
+           fi
+           ;;
+         esac
+         # This is a shared library
+
+         # Warn about portability, can't link against -module's on some
+         # systems (darwin).  Don't bleat about dlopened modules though!
+         dlopenmodule=""
+         for dlpremoduletest in $dlprefiles; do
+           if test "X$dlpremoduletest" = "X$lib"; then
+             dlopenmodule="$dlpremoduletest"
+             break
+           fi
+         done
+         if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then
+           $ECHO
+           if test "$linkmode" = prog; then
+             $ECHO "*** Warning: Linking the executable $output against the loadable module"
+           else
+             $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+           fi
+           $ECHO "*** $linklib is not portable!"
+         fi
+         if test "$linkmode" = lib &&
+            test "$hardcode_into_libs" = yes; then
+           # Hardcode the library path.
+           # Skip directories that are in the system default run-time
+           # search path.
+           case " $sys_lib_dlsearch_path " in
+           *" $absdir "*) ;;
+           *)
+             case "$compile_rpath " in
+             *" $absdir "*) ;;
+             *) compile_rpath="$compile_rpath $absdir"
+             esac
+             ;;
+           esac
+           case " $sys_lib_dlsearch_path " in
+           *" $libdir "*) ;;
+           *)
+             case "$finalize_rpath " in
+             *" $libdir "*) ;;
+             *) finalize_rpath="$finalize_rpath $libdir"
+             esac
+             ;;
+           esac
+         fi
+
+         if test -n "$old_archive_from_expsyms_cmds"; then
+           # figure out the soname
+           set dummy $library_names
+           shift
+           realname="$1"
+           shift
+           libname=`eval "\\$ECHO \"$libname_spec\""`
+           # use dlname if we got it. it's perfectly good, no?
+           if test -n "$dlname"; then
+             soname="$dlname"
+           elif test -n "$soname_spec"; then
+             # bleh windows
+             case $host in
+             *cygwin* | mingw* | *cegcc*)
+               func_arith $current - $age
+               major=$func_arith_result
+               versuffix="-$major"
+               ;;
+             esac
+             eval soname=\"$soname_spec\"
+           else
+             soname="$realname"
+           fi
+
+           # Make a new name for the extract_expsyms_cmds to use
+           soroot="$soname"
+           func_basename "$soroot"
+           soname="$func_basename_result"
+           func_stripname 'lib' '.dll' "$soname"
+           newlib=libimp-$func_stripname_result.a
+
+           # If the library has no export list, then create one now
+           if test -f "$output_objdir/$soname-def"; then :
+           else
+             func_verbose "extracting exported symbol list from \`$soname'"
+             func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+           fi
+
+           # Create $newlib
+           if test -f "$output_objdir/$newlib"; then :; else
+             func_verbose "generating import library for \`$soname'"
+             func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+           fi
+           # make sure the library variables are pointing to the new library
+           dir=$output_objdir
+           linklib=$newlib
+         fi # test -n "$old_archive_from_expsyms_cmds"
+
+         if test "$linkmode" = prog || test "$mode" != relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           lib_linked=yes
+           case $hardcode_action in
+           immediate | unsupported)
+             if test "$hardcode_direct" = no; then
+               add="$dir/$linklib"
+               case $host in
+                 *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+                 *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+                 *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+                   *-*-unixware7*) add_dir="-L$dir" ;;
+                 *-*-darwin* )
+                   # if the lib is a (non-dlopened) module then we can not
+                   # link against it, someone is ignoring the earlier warnings
+                   if /usr/bin/file -L $add 2> /dev/null |
+                        $GREP ": [^:]* bundle" >/dev/null ; then
+                     if test "X$dlopenmodule" != "X$lib"; then
+                       $ECHO "*** Warning: lib $linklib is a module, not a shared library"
+                       if test -z "$old_library" ; then
+                         $ECHO
+                         $ECHO "*** And there doesn't seem to be a static archive available"
+                         $ECHO "*** The link will probably fail, sorry"
+                       else
+                         add="$dir/$old_library"
+                       fi
+                     elif test -n "$old_library"; then
+                       add="$dir/$old_library"
+                     fi
+                   fi
+               esac
+             elif test "$hardcode_minus_L" = no; then
+               case $host in
+               *-*-sunos*) add_shlibpath="$dir" ;;
+               esac
+               add_dir="-L$dir"
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = no; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           relink)
+             if test "$hardcode_direct" = yes &&
+                test "$hardcode_direct_absolute" = no; then
+               add="$dir/$linklib"
+             elif test "$hardcode_minus_L" = yes; then
+               add_dir="-L$dir"
+               # Try looking first in the location we're being installed to.
+               if test -n "$inst_prefix_dir"; then
+                 case $libdir in
+                   [\\/]*)
+                     add_dir="$add_dir -L$inst_prefix_dir$libdir"
+                     ;;
+                 esac
+               fi
+               add="-l$name"
+             elif test "$hardcode_shlibpath_var" = yes; then
+               add_shlibpath="$dir"
+               add="-l$name"
+             else
+               lib_linked=no
+             fi
+             ;;
+           *) lib_linked=no ;;
+           esac
+
+           if test "$lib_linked" != yes; then
+             func_fatal_configuration "unsupported hardcode properties"
+           fi
+
+           if test -n "$add_shlibpath"; then
+             case :$compile_shlibpath: in
+             *":$add_shlibpath:"*) ;;
+             *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+             esac
+           fi
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+             test -n "$add" && compile_deplibs="$add $compile_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+             if test "$hardcode_direct" != yes &&
+                test "$hardcode_minus_L" != yes &&
+                test "$hardcode_shlibpath_var" = yes; then
+               case :$finalize_shlibpath: in
+               *":$libdir:"*) ;;
+               *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+               esac
+             fi
+           fi
+         fi
+
+         if test "$linkmode" = prog || test "$mode" = relink; then
+           add_shlibpath=
+           add_dir=
+           add=
+           # Finalize command for both is simple: just hardcode it.
+           if test "$hardcode_direct" = yes &&
+              test "$hardcode_direct_absolute" = no; then
+             add="$libdir/$linklib"
+           elif test "$hardcode_minus_L" = yes; then
+             add_dir="-L$libdir"
+             add="-l$name"
+           elif test "$hardcode_shlibpath_var" = yes; then
+             case :$finalize_shlibpath: in
+             *":$libdir:"*) ;;
+             *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+             esac
+             add="-l$name"
+           elif test "$hardcode_automatic" = yes; then
+             if test -n "$inst_prefix_dir" &&
+                test -f "$inst_prefix_dir$libdir/$linklib" ; then
+               add="$inst_prefix_dir$libdir/$linklib"
+             else
+               add="$libdir/$linklib"
+             fi
+           else
+             # We cannot seem to hardcode it, guess we'll fake it.
+             add_dir="-L$libdir"
+             # Try looking first in the location we're being installed to.
+             if test -n "$inst_prefix_dir"; then
+               case $libdir in
+                 [\\/]*)
+                   add_dir="$add_dir -L$inst_prefix_dir$libdir"
+                   ;;
+               esac
+             fi
+             add="-l$name"
+           fi
+
+           if test "$linkmode" = prog; then
+             test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+             test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+           else
+             test -n "$add_dir" && deplibs="$add_dir $deplibs"
+             test -n "$add" && deplibs="$add $deplibs"
+           fi
+         fi
+       elif test "$linkmode" = prog; then
+         # Here we assume that one of hardcode_direct or hardcode_minus_L
+         # is not unsupported.  This is valid on all known static and
+         # shared platforms.
+         if test "$hardcode_direct" != unsupported; then
+           test -n "$old_library" && linklib="$old_library"
+           compile_deplibs="$dir/$linklib $compile_deplibs"
+           finalize_deplibs="$dir/$linklib $finalize_deplibs"
+         else
+           compile_deplibs="-l$name -L$dir $compile_deplibs"
+           finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+         fi
+       elif test "$build_libtool_libs" = yes; then
+         # Not a shared library
+         if test "$deplibs_check_method" != pass_all; then
+           # We're trying link a shared library against a static one
+           # but the system doesn't support it.
+
+           # Just print a warning and add the library to dependency_libs so
+           # that the program can be linked against the static library.
+           $ECHO
+           $ECHO "*** Warning: This system can not link to static lib archive $lib."
+           $ECHO "*** I have the capability to make that library automatically link in when"
+           $ECHO "*** you link to this library.  But I can only do this if you have a"
+           $ECHO "*** shared version of the library, which you do not appear to have."
+           if test "$module" = yes; then
+             $ECHO "*** But as you try to build a module library, libtool will still create "
+             $ECHO "*** a static module, that should work as long as the dlopening application"
+             $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime."
+             if test -z "$global_symbol_pipe"; then
+               $ECHO
+               $ECHO "*** However, this would only work if libtool was able to extract symbol"
+               $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+               $ECHO "*** not find such a program.  So, this module is probably useless."
+               $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+             fi
+             if test "$build_old_libs" = no; then
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         else
+           deplibs="$dir/$old_library $deplibs"
+           link_static=yes
+         fi
+       fi # link shared/static library?
+
+       if test "$linkmode" = lib; then
+         if test -n "$dependency_libs" &&
+            { test "$hardcode_into_libs" != yes ||
+              test "$build_old_libs" = yes ||
+              test "$link_static" = yes; }; then
+           # Extract -R from dependency_libs
+           temp_deplibs=
+           for libdir in $dependency_libs; do
+             case $libdir in
+             -R*) func_stripname '-R' '' "$libdir"
+                  temp_xrpath=$func_stripname_result
+                  case " $xrpath " in
+                  *" $temp_xrpath "*) ;;
+                  *) xrpath="$xrpath $temp_xrpath";;
+                  esac;;
+             *) temp_deplibs="$temp_deplibs $libdir";;
+             esac
+           done
+           dependency_libs="$temp_deplibs"
+         fi
+
+         newlib_search_path="$newlib_search_path $absdir"
+         # Link against this library
+         test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+         # ... and its dependency_libs
+         tmp_libs=
+         for deplib in $dependency_libs; do
+           newdependency_libs="$deplib $newdependency_libs"
+           if $opt_duplicate_deps ; then
+             case "$tmp_libs " in
+             *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+             esac
+           fi
+           tmp_libs="$tmp_libs $deplib"
+         done
+
+         if test "$link_all_deplibs" != no; then
+           # Add the search paths of all dependency libraries
+           for deplib in $dependency_libs; do
+             path=
+             case $deplib in
+             -L*) path="$deplib" ;;
+             *.la)
+               func_dirname "$deplib" "" "."
+               dir="$func_dirname_result"
+               # We need an absolute path.
+               case $dir in
+               [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+               *)
+                 absdir=`cd "$dir" && pwd`
+                 if test -z "$absdir"; then
+                   func_warning "cannot determine absolute directory name of \`$dir'"
+                   absdir="$dir"
+                 fi
+                 ;;
+               esac
+               if $GREP "^installed=no" $deplib > /dev/null; then
+               case $host in
+               *-*-darwin*)
+                 depdepl=
+                 eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+                 if test -n "$deplibrary_names" ; then
+                   for tmp in $deplibrary_names ; do
+                     depdepl=$tmp
+                   done
+                   if test -f "$absdir/$objdir/$depdepl" ; then
+                     depdepl="$absdir/$objdir/$depdepl"
+                     darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+                      if test -z "$darwin_install_name"; then
+                          darwin_install_name=`${OTOOL64} -L $depdepl  | awk '{if (NR == 2) {print $1;exit}}'`
+                      fi
+                     compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}"
+                     linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}"
+                     path=
+                   fi
+                 fi
+                 ;;
+               *)
+                 path="-L$absdir/$objdir"
+                 ;;
+               esac
+               else
+                 eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+                 test -z "$libdir" && \
+                   func_fatal_error "\`$deplib' is not a valid libtool archive"
+                 test "$absdir" != "$libdir" && \
+                   func_warning "\`$deplib' seems to be moved"
+
+                 path="-L$absdir"
+               fi
+               ;;
+             esac
+             case " $deplibs " in
+             *" $path "*) ;;
+             *) deplibs="$path $deplibs" ;;
+             esac
+           done
+         fi # link_all_deplibs != no
+       fi # linkmode = lib
+      done # for deplib in $libs
+      if test "$pass" = link; then
+       if test "$linkmode" = "prog"; then
+         compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+         finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+       else
+         compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+       fi
+      fi
+      dependency_libs="$newdependency_libs"
+      if test "$pass" = dlpreopen; then
+       # Link the dlpreopened libraries before other libraries
+       for deplib in $save_deplibs; do
+         deplibs="$deplib $deplibs"
+       done
+      fi
+      if test "$pass" != dlopen; then
+       if test "$pass" != conv; then
+         # Make sure lib_search_path contains only unique directories.
+         lib_search_path=
+         for dir in $newlib_search_path; do
+           case "$lib_search_path " in
+           *" $dir "*) ;;
+           *) lib_search_path="$lib_search_path $dir" ;;
+           esac
+         done
+         newlib_search_path=
+       fi
+
+       if test "$linkmode,$pass" != "prog,link"; then
+         vars="deplibs"
+       else
+         vars="compile_deplibs finalize_deplibs"
+       fi
+       for var in $vars dependency_libs; do
+         # Add libraries to $var in reverse order
+         eval tmp_libs=\"\$$var\"
+         new_libs=
+         for deplib in $tmp_libs; do
+           # FIXME: Pedantically, this is the right thing to do, so
+           #        that some nasty dependency loop isn't accidentally
+           #        broken:
+           #new_libs="$deplib $new_libs"
+           # Pragmatically, this seems to cause very few problems in
+           # practice:
+           case $deplib in
+           -L*) new_libs="$deplib $new_libs" ;;
+           -R*) ;;
+           *)
+             # And here is the reason: when a library appears more
+             # than once as an explicit dependence of a library, or
+             # is implicitly linked in more than once by the
+             # compiler, it is considered special, and multiple
+             # occurrences thereof are not removed.  Compare this
+             # with having the same library being listed as a
+             # dependency of multiple other libraries: in this case,
+             # we know (pedantically, we assume) the library does not
+             # need to be listed more than once, so we keep only the
+             # last copy.  This is not always right, but it is rare
+             # enough that we require users that really mean to play
+             # such unportable linking tricks to link the library
+             # using -Wl,-lname, so that libtool does not consider it
+             # for duplicate removal.
+             case " $specialdeplibs " in
+             *" $deplib "*) new_libs="$deplib $new_libs" ;;
+             *)
+               case " $new_libs " in
+               *" $deplib "*) ;;
+               *) new_libs="$deplib $new_libs" ;;
+               esac
+               ;;
+             esac
+             ;;
+           esac
+         done
+         tmp_libs=
+         for deplib in $new_libs; do
+           case $deplib in
+           -L*)
+             case " $tmp_libs " in
+             *" $deplib "*) ;;
+             *) tmp_libs="$tmp_libs $deplib" ;;
+             esac
+             ;;
+           *) tmp_libs="$tmp_libs $deplib" ;;
+           esac
+         done
+         eval $var=\"$tmp_libs\"
+       done # for var
+      fi
+      # Last step: remove runtime libs from dependency_libs
+      # (they stay in deplibs)
+      tmp_libs=
+      for i in $dependency_libs ; do
+       case " $predeps $postdeps $compiler_lib_search_path " in
+       *" $i "*)
+         i=""
+         ;;
+       esac
+       if test -n "$i" ; then
+         tmp_libs="$tmp_libs $i"
+       fi
+      done
+      dependency_libs=$tmp_libs
+    done # for pass
+    if test "$linkmode" = prog; then
+      dlfiles="$newdlfiles"
+    fi
+    if test "$linkmode" = prog || test "$linkmode" = lib; then
+      dlprefiles="$newdlprefiles"
+    fi
+
+    case $linkmode in
+    oldlib)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       func_warning "\`-dlopen' is ignored for archives"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+       func_warning "\`-l' and \`-L' are ignored for archives" ;;
+      esac
+
+      test -n "$rpath" && \
+       func_warning "\`-rpath' is ignored for archives"
+
+      test -n "$xrpath" && \
+       func_warning "\`-R' is ignored for archives"
+
+      test -n "$vinfo" && \
+       func_warning "\`-version-info/-version-number' is ignored for archives"
+
+      test -n "$release" && \
+       func_warning "\`-release' is ignored for archives"
+
+      test -n "$export_symbols$export_symbols_regex" && \
+       func_warning "\`-export-symbols' is ignored for archives"
+
+      # Now set the variables for building old libraries.
+      build_libtool_libs=no
+      oldlibs="$output"
+      objs="$objs$old_deplibs"
+      ;;
+
+    lib)
+      # Make sure we only generate libraries of the form `libNAME.la'.
+      case $outputname in
+      lib*)
+       func_stripname 'lib' '.la' "$outputname"
+       name=$func_stripname_result
+       eval shared_ext=\"$shrext_cmds\"
+       eval libname=\"$libname_spec\"
+       ;;
+      *)
+       test "$module" = no && \
+         func_fatal_help "libtool library \`$output' must begin with \`lib'"
+
+       if test "$need_lib_prefix" != no; then
+         # Add the "lib" prefix for modules if required
+         func_stripname '' '.la' "$outputname"
+         name=$func_stripname_result
+         eval shared_ext=\"$shrext_cmds\"
+         eval libname=\"$libname_spec\"
+       else
+         func_stripname '' '.la' "$outputname"
+         libname=$func_stripname_result
+       fi
+       ;;
+      esac
+
+      if test -n "$objs"; then
+       if test "$deplibs_check_method" != pass_all; then
+         func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs"
+       else
+         $ECHO
+         $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+         $ECHO "*** objects $objs is not portable!"
+         libobjs="$libobjs $objs"
+       fi
+      fi
+
+      test "$dlself" != no && \
+       func_warning "\`-dlopen self' is ignored for libtool libraries"
+
+      set dummy $rpath
+      shift
+      test "$#" -gt 1 && \
+       func_warning "ignoring multiple \`-rpath's for a libtool library"
+
+      install_libdir="$1"
+
+      oldlibs=
+      if test -z "$rpath"; then
+       if test "$build_libtool_libs" = yes; then
+         # Building a libtool convenience library.
+         # Some compilers have problems with a `.al' extension so
+         # convenience libraries should have the same extension an
+         # archive normally would.
+         oldlibs="$output_objdir/$libname.$libext $oldlibs"
+         build_libtool_libs=convenience
+         build_old_libs=yes
+       fi
+
+       test -n "$vinfo" && \
+         func_warning "\`-version-info/-version-number' is ignored for convenience libraries"
+
+       test -n "$release" && \
+         func_warning "\`-release' is ignored for convenience libraries"
+      else
+
+       # Parse the version information argument.
+       save_ifs="$IFS"; IFS=':'
+       set dummy $vinfo 0 0 0
+       shift
+       IFS="$save_ifs"
+
+       test -n "$7" && \
+         func_fatal_help "too many parameters to \`-version-info'"
+
+       # convert absolute version numbers to libtool ages
+       # this retains compatibility with .la files and attempts
+       # to make the code below a bit more comprehensible
+
+       case $vinfo_number in
+       yes)
+         number_major="$1"
+         number_minor="$2"
+         number_revision="$3"
+         #
+         # There are really only two kinds -- those that
+         # use the current revision as the major version
+         # and those that subtract age and use age as
+         # a minor version.  But, then there is irix
+         # which has an extra 1 added just for fun
+         #
+         case $version_type in
+         darwin|linux|osf|windows|none)
+           func_arith $number_major + $number_minor
+           current=$func_arith_result
+           age="$number_minor"
+           revision="$number_revision"
+           ;;
+         freebsd-aout|freebsd-elf|sunos)
+           current="$number_major"
+           revision="$number_minor"
+           age="0"
+           ;;
+         irix|nonstopux)
+           func_arith $number_major + $number_minor
+           current=$func_arith_result
+           age="$number_minor"
+           revision="$number_minor"
+           lt_irix_increment=no
+           ;;
+         *)
+           func_fatal_configuration "$modename: unknown library version type \`$version_type'"
+           ;;
+         esac
+         ;;
+       no)
+         current="$1"
+         revision="$2"
+         age="$3"
+         ;;
+       esac
+
+       # Check that each of the things are valid numbers.
+       case $current in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         func_error "CURRENT \`$current' must be a nonnegative integer"
+         func_fatal_error "\`$vinfo' is not valid version information"
+         ;;
+       esac
+
+       case $revision in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         func_error "REVISION \`$revision' must be a nonnegative integer"
+         func_fatal_error "\`$vinfo' is not valid version information"
+         ;;
+       esac
+
+       case $age in
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+       *)
+         func_error "AGE \`$age' must be a nonnegative integer"
+         func_fatal_error "\`$vinfo' is not valid version information"
+         ;;
+       esac
+
+       if test "$age" -gt "$current"; then
+         func_error "AGE \`$age' is greater than the current interface number \`$current'"
+         func_fatal_error "\`$vinfo' is not valid version information"
+       fi
+
+       # Calculate the version variables.
+       major=
+       versuffix=
+       verstring=
+       case $version_type in
+       none) ;;
+
+       darwin)
+         # Like Linux, but with the current version available in
+         # verstring for coding it into the library header
+         func_arith $current - $age
+         major=.$func_arith_result
+         versuffix="$major.$age.$revision"
+         # Darwin ld doesn't like 0 for these options...
+         func_arith $current + 1
+         minor_current=$func_arith_result
+         xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+         verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+         ;;
+
+       freebsd-aout)
+         major=".$current"
+         versuffix=".$current.$revision";
+         ;;
+
+       freebsd-elf)
+         major=".$current"
+         versuffix=".$current"
+         ;;
+
+       irix | nonstopux)
+         if test "X$lt_irix_increment" = "Xno"; then
+           func_arith $current - $age
+         else
+           func_arith $current - $age + 1
+         fi
+         major=$func_arith_result
+
+         case $version_type in
+           nonstopux) verstring_prefix=nonstopux ;;
+           *)         verstring_prefix=sgi ;;
+         esac
+         verstring="$verstring_prefix$major.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$revision
+         while test "$loop" -ne 0; do
+           func_arith $revision - $loop
+           iface=$func_arith_result
+           func_arith $loop - 1
+           loop=$func_arith_result
+           verstring="$verstring_prefix$major.$iface:$verstring"
+         done
+
+         # Before this point, $major must not contain `.'.
+         major=.$major
+         versuffix="$major.$revision"
+         ;;
+
+       linux)
+         func_arith $current - $age
+         major=.$func_arith_result
+         versuffix="$major.$age.$revision"
+         ;;
+
+       osf)
+         func_arith $current - $age
+         major=.$func_arith_result
+         versuffix=".$current.$age.$revision"
+         verstring="$current.$age.$revision"
+
+         # Add in all the interfaces that we are compatible with.
+         loop=$age
+         while test "$loop" -ne 0; do
+           func_arith $current - $loop
+           iface=$func_arith_result
+           func_arith $loop - 1
+           loop=$func_arith_result
+           verstring="$verstring:${iface}.0"
+         done
+
+         # Make executables depend on our current version.
+         verstring="$verstring:${current}.0"
+         ;;
+
+       qnx)
+         major=".$current"
+         versuffix=".$current"
+         ;;
+
+       sunos)
+         major=".$current"
+         versuffix=".$current.$revision"
+         ;;
+
+       windows)
+         # Use '-' rather than '.', since we only want one
+         # extension on DOS 8.3 filesystems.
+         func_arith $current - $age
+         major=$func_arith_result
+         versuffix="-$major"
+         ;;
+
+       *)
+         func_fatal_configuration "unknown library version type \`$version_type'"
+         ;;
+       esac
+
+       # Clear the version info if we defaulted, and they specified a release.
+       if test -z "$vinfo" && test -n "$release"; then
+         major=
+         case $version_type in
+         darwin)
+           # we can't check for "0.0" in archive_cmds due to quoting
+           # problems, so we reset it completely
+           verstring=
+           ;;
+         *)
+           verstring="0.0"
+           ;;
+         esac
+         if test "$need_version" = no; then
+           versuffix=
+         else
+           versuffix=".0.0"
+         fi
+       fi
+
+       # Remove version info from name if versioning should be avoided
+       if test "$avoid_version" = yes && test "$need_version" = no; then
+         major=
+         versuffix=
+         verstring=""
+       fi
+
+       # Check to see if the archive will have undefined symbols.
+       if test "$allow_undefined" = yes; then
+         if test "$allow_undefined_flag" = unsupported; then
+           func_warning "undefined symbols not allowed in $host shared libraries"
+           build_libtool_libs=no
+           build_old_libs=yes
+         fi
+       else
+         # Don't allow undefined symbols.
+         allow_undefined_flag="$no_undefined_flag"
+       fi
+
+      fi
+
+      func_generate_dlsyms "$libname" "$libname" "yes"
+      libobjs="$libobjs $symfileobj"
+      test "X$libobjs" = "X " && libobjs=
+
+      if test "$mode" != relink; then
+       # Remove our outputs, but don't remove object files since they
+       # may have been created when compiling PIC objects.
+       removelist=
+       tempremovelist=`$ECHO "$output_objdir/*"`
+       for p in $tempremovelist; do
+         case $p in
+           *.$objext | *.gcno)
+              ;;
+           $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+              if test "X$precious_files_regex" != "X"; then
+                if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+                then
+                  continue
+                fi
+              fi
+              removelist="$removelist $p"
+              ;;
+           *) ;;
+         esac
+       done
+       test -n "$removelist" && \
+         func_show_eval "${RM}r \$removelist"
+      fi
+
+      # Now set the variables for building old libraries.
+      if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+       oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+       # Transform .lo files to .o files.
+       oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+      fi
+
+      # Eliminate all temporary directories.
+      #for path in $notinst_path; do
+      #        lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"`
+      #        deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"`
+      #        dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"`
+      #done
+
+      if test -n "$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       temp_xrpath=
+       for libdir in $xrpath; do
+         temp_xrpath="$temp_xrpath -R$libdir"
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+       if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+         dependency_libs="$temp_xrpath $dependency_libs"
+       fi
+      fi
+
+      # Make sure dlfiles contains only unique files that won't be dlpreopened
+      old_dlfiles="$dlfiles"
+      dlfiles=
+      for lib in $old_dlfiles; do
+       case " $dlprefiles $dlfiles " in
+       *" $lib "*) ;;
+       *) dlfiles="$dlfiles $lib" ;;
+       esac
+      done
+
+      # Make sure dlprefiles contains only unique files
+      old_dlprefiles="$dlprefiles"
+      dlprefiles=
+      for lib in $old_dlprefiles; do
+       case "$dlprefiles " in
+       *" $lib "*) ;;
+       *) dlprefiles="$dlprefiles $lib" ;;
+       esac
+      done
+
+      if test "$build_libtool_libs" = yes; then
+       if test -n "$rpath"; then
+         case $host in
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*)
+           # these systems don't actually have a c library (as such)!
+           ;;
+         *-*-rhapsody* | *-*-darwin1.[012])
+           # Rhapsody C library is in the System framework
+           deplibs="$deplibs System.ltframework"
+           ;;
+         *-*-netbsd*)
+           # Don't link with libc until the a.out ld.so is fixed.
+           ;;
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+           # Do not include libc due to us having libc/libc_r.
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           ;;
+         *)
+           # Add libc to deplibs on all other systems if necessary.
+           if test "$build_libtool_need_lc" = "yes"; then
+             deplibs="$deplibs -lc"
+           fi
+           ;;
+         esac
+       fi
+
+       # Transform deplibs into only deplibs that can be linked in shared.
+       name_save=$name
+       libname_save=$libname
+       release_save=$release
+       versuffix_save=$versuffix
+       major_save=$major
+       # I'm not sure if I'm treating the release correctly.  I think
+       # release should show up in the -l (ie -lgmp5) so we don't want to
+       # add it in twice.  Is that correct?
+       release=""
+       versuffix=""
+       major=""
+       newdeplibs=
+       droppeddeps=no
+       case $deplibs_check_method in
+       pass_all)
+         # Don't check for shared/static.  Everything works.
+         # This might be a little naive.  We might want to check
+         # whether the library exists or not.  But this is on
+         # osf3 & osf4 and I'm not really sure... Just
+         # implementing what was already the behavior.
+         newdeplibs=$deplibs
+         ;;
+       test_compile)
+         # This code stresses the "libraries are programs" paradigm to its
+         # limits. Maybe even breaks it.  We compile a program, linking it
+         # against the deplibs as a proxy for the library.  Then we can check
+         # whether they linked in statically or dynamically with ldd.
+         $opt_dry_run || $RM conftest.c
+         cat > conftest.c <<EOF
+         int main() { return 0; }
+EOF
+         $opt_dry_run || $RM conftest
+         if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+           ldd_output=`ldd conftest`
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                 case " $predeps $postdeps " in
+                 *" $i "*)
+                   newdeplibs="$newdeplibs $i"
+                   i=""
+                   ;;
+                 esac
+               fi
+               if test -n "$i" ; then
+                 libname=`eval "\\$ECHO \"$libname_spec\""`
+                 deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                 set dummy $deplib_matches; shift
+                 deplib_match=$1
+                 if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                   newdeplibs="$newdeplibs $i"
+                 else
+                   droppeddeps=yes
+                   $ECHO
+                   $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                   $ECHO "*** I have the capability to make that library automatically link in when"
+                   $ECHO "*** you link to this library.  But I can only do this if you have a"
+                   $ECHO "*** shared version of the library, which I believe you do not have"
+                   $ECHO "*** because a test_compile did reveal that the linker did not use it for"
+                   $ECHO "*** its dynamic dependency list that programs get resolved with at runtime."
+                 fi
+               fi
+               ;;
+             *)
+               newdeplibs="$newdeplibs $i"
+               ;;
+             esac
+           done
+         else
+           # Error occurred in the first compile.  Let's try to salvage
+           # the situation: Compile a separate program for each library.
+           for i in $deplibs; do
+             case $i in
+             -l*)
+               func_stripname -l '' "$i"
+               name=$func_stripname_result
+               $opt_dry_run || $RM conftest
+               if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+                 ldd_output=`ldd conftest`
+                 if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+                   case " $predeps $postdeps " in
+                   *" $i "*)
+                     newdeplibs="$newdeplibs $i"
+                     i=""
+                     ;;
+                   esac
+                 fi
+                 if test -n "$i" ; then
+                   libname=`eval "\\$ECHO \"$libname_spec\""`
+                   deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+                   set dummy $deplib_matches; shift
+                   deplib_match=$1
+                   if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+                     newdeplibs="$newdeplibs $i"
+                   else
+                     droppeddeps=yes
+                     $ECHO
+                     $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+                     $ECHO "*** I have the capability to make that library automatically link in when"
+                     $ECHO "*** you link to this library.  But I can only do this if you have a"
+                     $ECHO "*** shared version of the library, which you do not appear to have"
+                     $ECHO "*** because a test_compile did reveal that the linker did not use this one"
+                     $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime."
+                   fi
+                 fi
+               else
+                 droppeddeps=yes
+                 $ECHO
+                 $ECHO "*** Warning!  Library $i is needed by this library but I was not able to"
+                 $ECHO "*** make it link in!  You will probably need to install it or some"
+                 $ECHO "*** library that it depends on before this library will be fully"
+                 $ECHO "*** functional.  Installing it before continuing would be even better."
+               fi
+               ;;
+             *)
+               newdeplibs="$newdeplibs $i"
+               ;;
+             esac
+           done
+         fi
+         ;;
+       file_magic*)
+         set dummy $deplibs_check_method; shift
+         file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+         for a_deplib in $deplibs; do
+           case $a_deplib in
+           -l*)
+             func_stripname -l '' "$a_deplib"
+             name=$func_stripname_result
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 newdeplibs="$newdeplibs $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval "\\$ECHO \"$libname_spec\""`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                 for potent_lib in $potential_libs; do
+                     # Follow soft links.
+                     if ls -lLd "$potent_lib" 2>/dev/null |
+                        $GREP " -> " >/dev/null; then
+                       continue
+                     fi
+                     # The statement above tries to avoid entering an
+                     # endless loop below, in case of cyclic links.
+                     # We might still enter an endless loop, since a link
+                     # loop can be closed while we follow links,
+                     # but so what?
+                     potlib="$potent_lib"
+                     while test -h "$potlib" 2>/dev/null; do
+                       potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+                       case $potliblink in
+                       [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+                       *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+                       esac
+                     done
+                     if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+                        $SED -e 10q |
+                        $EGREP "$file_magic_regex" > /dev/null; then
+                       newdeplibs="$newdeplibs $a_deplib"
+                       a_deplib=""
+                       break 2
+                     fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               $ECHO
+               $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+               $ECHO "*** I have the capability to make that library automatically link in when"
+               $ECHO "*** you link to this library.  But I can only do this if you have a"
+               $ECHO "*** shared version of the library, which you do not appear to have"
+               $ECHO "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+               else
+                 $ECHO "*** with $libname and none of the candidates passed a file format test"
+                 $ECHO "*** using a file magic. Last file checked: $potlib"
+               fi
+             fi
+             ;;
+           *)
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+             ;;
+           esac
+         done # Gone through all deplibs.
+         ;;
+       match_pattern*)
+         set dummy $deplibs_check_method; shift
+         match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+         for a_deplib in $deplibs; do
+           case $a_deplib in
+           -l*)
+             func_stripname -l '' "$a_deplib"
+             name=$func_stripname_result
+             if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+               case " $predeps $postdeps " in
+               *" $a_deplib "*)
+                 newdeplibs="$newdeplibs $a_deplib"
+                 a_deplib=""
+                 ;;
+               esac
+             fi
+             if test -n "$a_deplib" ; then
+               libname=`eval "\\$ECHO \"$libname_spec\""`
+               for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+                 potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+                 for potent_lib in $potential_libs; do
+                   potlib="$potent_lib" # see symlink-check above in file_magic test
+                   if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \
+                      $EGREP "$match_pattern_regex" > /dev/null; then
+                     newdeplibs="$newdeplibs $a_deplib"
+                     a_deplib=""
+                     break 2
+                   fi
+                 done
+               done
+             fi
+             if test -n "$a_deplib" ; then
+               droppeddeps=yes
+               $ECHO
+               $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+               $ECHO "*** I have the capability to make that library automatically link in when"
+               $ECHO "*** you link to this library.  But I can only do this if you have a"
+               $ECHO "*** shared version of the library, which you do not appear to have"
+               $ECHO "*** because I did check the linker path looking for a file starting"
+               if test -z "$potlib" ; then
+                 $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+               else
+                 $ECHO "*** with $libname and none of the candidates passed a file format test"
+                 $ECHO "*** using a regex pattern. Last file checked: $potlib"
+               fi
+             fi
+             ;;
+           *)
+             # Add a -L argument.
+             newdeplibs="$newdeplibs $a_deplib"
+             ;;
+           esac
+         done # Gone through all deplibs.
+         ;;
+       none | unknown | *)
+         newdeplibs=""
+         tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \
+             -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'`
+         if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+           for i in $predeps $postdeps ; do
+             # can't use Xsed below, because $i might contain '/'
+             tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"`
+           done
+         fi
+         if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[      ]//g' |
+            $GREP . >/dev/null; then
+           $ECHO
+           if test "X$deplibs_check_method" = "Xnone"; then
+             $ECHO "*** Warning: inter-library dependencies are not supported in this platform."
+           else
+             $ECHO "*** Warning: inter-library dependencies are not known to be supported."
+           fi
+           $ECHO "*** All declared inter-library dependencies are being dropped."
+           droppeddeps=yes
+         fi
+         ;;
+       esac
+       versuffix=$versuffix_save
+       major=$major_save
+       release=$release_save
+       libname=$libname_save
+       name=$name_save
+
+       case $host in
+       *-*-rhapsody* | *-*-darwin1.[012])
+         # On Rhapsody replace the C library with the System framework
+         newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+         ;;
+       esac
+
+       if test "$droppeddeps" = yes; then
+         if test "$module" = yes; then
+           $ECHO
+           $ECHO "*** Warning: libtool could not satisfy all declared inter-library"
+           $ECHO "*** dependencies of module $libname.  Therefore, libtool will create"
+           $ECHO "*** a static module, that should work as long as the dlopening"
+           $ECHO "*** application is linked with the -dlopen flag."
+           if test -z "$global_symbol_pipe"; then
+             $ECHO
+             $ECHO "*** However, this would only work if libtool was able to extract symbol"
+             $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could"
+             $ECHO "*** not find such a program.  So, this module is probably useless."
+             $ECHO "*** \`nm' from GNU binutils and a full rebuild may help."
+           fi
+           if test "$build_old_libs" = no; then
+             oldlibs="$output_objdir/$libname.$libext"
+             build_libtool_libs=module
+             build_old_libs=yes
+           else
+             build_libtool_libs=no
+           fi
+         else
+           $ECHO "*** The inter-library dependencies that have been dropped here will be"
+           $ECHO "*** automatically added whenever a program is linked with this library"
+           $ECHO "*** or is declared to -dlopen it."
+
+           if test "$allow_undefined" = no; then
+             $ECHO
+             $ECHO "*** Since this library must not contain undefined symbols,"
+             $ECHO "*** because either the platform does not support them or"
+             $ECHO "*** it was explicitly requested with -no-undefined,"
+             $ECHO "*** libtool will only create a static version of it."
+             if test "$build_old_libs" = no; then
+               oldlibs="$output_objdir/$libname.$libext"
+               build_libtool_libs=module
+               build_old_libs=yes
+             else
+               build_libtool_libs=no
+             fi
+           fi
+         fi
+       fi
+       # Done checking deplibs!
+       deplibs=$newdeplibs
+      fi
+      # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+      case $host in
+       *-*-darwin*)
+         newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+         new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+         deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+         ;;
+      esac
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      deplibs="$new_libs"
+
+      # All the library-specific variables (install_libdir is set above).
+      library_names=
+      old_library=
+      dlname=
+
+      # Test again, we may have decided not to build it any more
+      if test "$build_libtool_libs" = yes; then
+       if test "$hardcode_into_libs" = yes; then
+         # Hardcode the library paths
+         hardcode_libdirs=
+         dep_rpath=
+         rpath="$finalize_rpath"
+         test "$mode" != relink && rpath="$compile_rpath$rpath"
+         for libdir in $rpath; do
+           if test -n "$hardcode_libdir_flag_spec"; then
+             if test -n "$hardcode_libdir_separator"; then
+               if test -z "$hardcode_libdirs"; then
+                 hardcode_libdirs="$libdir"
+               else
+                 # Just accumulate the unique libdirs.
+                 case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+                 *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+                   ;;
+                 *)
+                   hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+                   ;;
+                 esac
+               fi
+             else
+               eval flag=\"$hardcode_libdir_flag_spec\"
+               dep_rpath="$dep_rpath $flag"
+             fi
+           elif test -n "$runpath_var"; then
+             case "$perm_rpath " in
+             *" $libdir "*) ;;
+             *) perm_rpath="$perm_rpath $libdir" ;;
+             esac
+           fi
+         done
+         # Substitute the hardcoded libdirs into the rpath.
+         if test -n "$hardcode_libdir_separator" &&
+            test -n "$hardcode_libdirs"; then
+           libdir="$hardcode_libdirs"
+           if test -n "$hardcode_libdir_flag_spec_ld"; then
+             eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+           else
+             eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+           fi
+         fi
+         if test -n "$runpath_var" && test -n "$perm_rpath"; then
+           # We should set the runpath_var.
+           rpath=
+           for dir in $perm_rpath; do
+             rpath="$rpath$dir:"
+           done
+           eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+         fi
+         test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+       fi
+
+       shlibpath="$finalize_shlibpath"
+       test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+       if test -n "$shlibpath"; then
+         eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+       fi
+
+       # Get the real and link names of the library.
+       eval shared_ext=\"$shrext_cmds\"
+       eval library_names=\"$library_names_spec\"
+       set dummy $library_names
+       shift
+       realname="$1"
+       shift
+
+       if test -n "$soname_spec"; then
+         eval soname=\"$soname_spec\"
+       else
+         soname="$realname"
+       fi
+       if test -z "$dlname"; then
+         dlname=$soname
+       fi
+
+       lib="$output_objdir/$realname"
+       linknames=
+       for link
+       do
+         linknames="$linknames $link"
+       done
+
+       # Use standard objects if they are pic
+       test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+       test "X$libobjs" = "X " && libobjs=
+
+       delfiles=
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+         export_symbols="$output_objdir/$libname.uexp"
+         delfiles="$delfiles $export_symbols"
+       fi
+
+       orig_export_symbols=
+       case $host_os in
+       cygwin* | mingw* | cegcc*)
+         if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+           # exporting using user supplied symfile
+           if test "x`$SED 1q $export_symbols`" != xEXPORTS; then
+             # and it's NOT already a .def file. Must figure out
+             # which of the given symbols are data symbols and tag
+             # them as such. So, trigger use of export_symbols_cmds.
+             # export_symbols gets reassigned inside the "prepare
+             # the list of exported symbols" if statement, so the
+             # include_expsyms logic still works.
+             orig_export_symbols="$export_symbols"
+             export_symbols=
+             always_export_symbols=yes
+           fi
+         fi
+         ;;
+       esac
+
+       # Prepare the list of exported symbols
+       if test -z "$export_symbols"; then
+         if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+           func_verbose "generating symbol list for \`$libname.la'"
+           export_symbols="$output_objdir/$libname.exp"
+           $opt_dry_run || $RM $export_symbols
+           cmds=$export_symbols_cmds
+           save_ifs="$IFS"; IFS='~'
+           for cmd in $cmds; do
+             IFS="$save_ifs"
+             eval cmd=\"$cmd\"
+             func_len " $cmd"
+             len=$func_len_result
+             if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+               func_show_eval "$cmd" 'exit $?'
+               skipped_export=false
+             else
+               # The command line is too long to execute in one step.
+               func_verbose "using reloadable object file for export list..."
+               skipped_export=:
+               # Break out early, otherwise skipped_export may be
+               # set to false by a later but shorter cmd.
+               break
+             fi
+           done
+           IFS="$save_ifs"
+           if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then
+             func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+       fi
+
+       if test -n "$export_symbols" && test -n "$include_expsyms"; then
+         tmp_export_symbols="$export_symbols"
+         test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+         $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+       fi
+
+       if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then
+         # The given exports_symbols file has to be filtered, so filter it.
+         func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+         # FIXME: $output_objdir/$libname.filter potentially contains lots of
+         # 's' commands which not all seds can handle. GNU sed should be fine
+         # though. Also, the filter scales superlinearly with the number of
+         # global variables. join(1) would be nice here, but unfortunately
+         # isn't a blessed tool.
+         $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+         delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+         export_symbols=$output_objdir/$libname.def
+         $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+       fi
+
+       tmp_deplibs=
+       for test_deplib in $deplibs; do
+         case " $convenience " in
+         *" $test_deplib "*) ;;
+         *)
+           tmp_deplibs="$tmp_deplibs $test_deplib"
+           ;;
+         esac
+       done
+       deplibs="$tmp_deplibs"
+
+       if test -n "$convenience"; then
+         if test -n "$whole_archive_flag_spec" &&
+           test "$compiler_needs_object" = yes &&
+           test -z "$libobjs"; then
+           # extract the archives, so we have objects to list.
+           # TODO: could optimize this to just extract one archive.
+           whole_archive_flag_spec=
+         fi
+         if test -n "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+           test "X$libobjs" = "X " && libobjs=
+         else
+           gentop="$output_objdir/${outputname}x"
+           generated="$generated $gentop"
+
+           func_extract_archives $gentop $convenience
+           libobjs="$libobjs $func_extract_archives_result"
+           test "X$libobjs" = "X " && libobjs=
+         fi
+       fi
+
+       if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+         eval flag=\"$thread_safe_flag_spec\"
+         linker_flags="$linker_flags $flag"
+       fi
+
+       # Make a backup of the uninstalled library when relinking
+       if test "$mode" = relink; then
+         $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+       fi
+
+       # Do each of the archive commands.
+       if test "$module" = yes && test -n "$module_cmds" ; then
+         if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+           eval test_cmds=\"$module_expsym_cmds\"
+           cmds=$module_expsym_cmds
+         else
+           eval test_cmds=\"$module_cmds\"
+           cmds=$module_cmds
+         fi
+       else
+         if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+           eval test_cmds=\"$archive_expsym_cmds\"
+           cmds=$archive_expsym_cmds
+         else
+           eval test_cmds=\"$archive_cmds\"
+           cmds=$archive_cmds
+         fi
+       fi
+
+       if test "X$skipped_export" != "X:" &&
+          func_len " $test_cmds" &&
+          len=$func_len_result &&
+          test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         :
+       else
+         # The command line is too long to link in one step, link piecewise
+         # or, if using GNU ld and skipped_export is not :, use a linker
+         # script.
+
+         # Save the value of $output and $libobjs because we want to
+         # use them later.  If we have whole_archive_flag_spec, we
+         # want to use save_libobjs as it was before
+         # whole_archive_flag_spec was expanded, because we can't
+         # assume the linker understands whole_archive_flag_spec.
+         # This may have to be revisited, in case too many
+         # convenience libraries get linked in and end up exceeding
+         # the spec.
+         if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+           save_libobjs=$libobjs
+         fi
+         save_output=$output
+         output_la=`$ECHO "X$output" | $Xsed -e "$basename"`
+
+         # Clear the reloadable object creation command queue and
+         # initialize k to one.
+         test_cmds=
+         concat_cmds=
+         objlist=
+         last_robj=
+         k=1
+
+         if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then
+           output=${output_objdir}/${output_la}.lnkscript
+           func_verbose "creating GNU ld script: $output"
+           $ECHO 'INPUT (' > $output
+           for obj in $save_libobjs
+           do
+             $ECHO "$obj" >> $output
+           done
+           $ECHO ')' >> $output
+           delfiles="$delfiles $output"
+         elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then
+           output=${output_objdir}/${output_la}.lnk
+           func_verbose "creating linker input file list: $output"
+           : > $output
+           set x $save_libobjs
+           shift
+           firstobj=
+           if test "$compiler_needs_object" = yes; then
+             firstobj="$1 "
+             shift
+           fi
+           for obj
+           do
+             $ECHO "$obj" >> $output
+           done
+           delfiles="$delfiles $output"
+           output=$firstobj\"$file_list_spec$output\"
+         else
+           if test -n "$save_libobjs"; then
+             func_verbose "creating reloadable object files..."
+             output=$output_objdir/$output_la-${k}.$objext
+             eval test_cmds=\"$reload_cmds\"
+             func_len " $test_cmds"
+             len0=$func_len_result
+             len=$len0
+
+             # Loop over the list of objects to be linked.
+             for obj in $save_libobjs
+             do
+               func_len " $obj"
+               func_arith $len + $func_len_result
+               len=$func_arith_result
+               if test "X$objlist" = X ||
+                  test "$len" -lt "$max_cmd_len"; then
+                 func_append objlist " $obj"
+               else
+                 # The command $test_cmds is almost too long, add a
+                 # command to the queue.
+                 if test "$k" -eq 1 ; then
+                   # The first file doesn't have a previous command to add.
+                   eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+                 else
+                   # All subsequent reloadable object files will link in
+                   # the last one created.
+                   eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\"
+                 fi
+                 last_robj=$output_objdir/$output_la-${k}.$objext
+                 func_arith $k + 1
+                 k=$func_arith_result
+                 output=$output_objdir/$output_la-${k}.$objext
+                 objlist=$obj
+                 func_len " $last_robj"
+                 func_arith $len0 + $func_len_result
+                 len=$func_arith_result
+               fi
+             done
+             # Handle the remaining objects by creating one last
+             # reloadable object file.  All subsequent reloadable object
+             # files will link in the last one created.
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+             if test -n "$last_robj"; then
+               eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\"
+             fi
+             delfiles="$delfiles $output"
+
+           else
+             output=
+           fi
+
+           if ${skipped_export-false}; then
+             func_verbose "generating symbol list for \`$libname.la'"
+             export_symbols="$output_objdir/$libname.exp"
+             $opt_dry_run || $RM $export_symbols
+             libobjs=$output
+             # Append the command to create the export file.
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+             if test -n "$last_robj"; then
+               eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+             fi
+           fi
+
+           test -n "$save_libobjs" &&
+             func_verbose "creating a temporary reloadable object file: $output"
+
+           # Loop through the commands generated above and execute them.
+           save_ifs="$IFS"; IFS='~'
+           for cmd in $concat_cmds; do
+             IFS="$save_ifs"
+             $opt_silent || {
+                 func_quote_for_expand "$cmd"
+                 eval "func_echo $func_quote_for_expand_result"
+             }
+             $opt_dry_run || eval "$cmd" || {
+               lt_exit=$?
+
+               # Restore the uninstalled library and exit
+               if test "$mode" = relink; then
+                 ( cd "$output_objdir" && \
+                   $RM "${realname}T" && \
+                   $MV "${realname}U" "$realname" )
+               fi
+
+               exit $lt_exit
+             }
+           done
+           IFS="$save_ifs"
+
+           if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+             func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+             func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+           fi
+         fi
+
+          if ${skipped_export-false}; then
+           if test -n "$export_symbols" && test -n "$include_expsyms"; then
+             tmp_export_symbols="$export_symbols"
+             test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols"
+             $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"'
+           fi
+
+           if test -n "$orig_export_symbols"; then
+             # The given exports_symbols file has to be filtered, so filter it.
+             func_verbose "filter symbol list for \`$libname.la' to tag DATA exports"
+             # FIXME: $output_objdir/$libname.filter potentially contains lots of
+             # 's' commands which not all seds can handle. GNU sed should be fine
+             # though. Also, the filter scales superlinearly with the number of
+             # global variables. join(1) would be nice here, but unfortunately
+             # isn't a blessed tool.
+             $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+             delfiles="$delfiles $export_symbols $output_objdir/$libname.filter"
+             export_symbols=$output_objdir/$libname.def
+             $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+           fi
+         fi
+
+         libobjs=$output
+         # Restore the value of output.
+         output=$save_output
+
+         if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+           eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+           test "X$libobjs" = "X " && libobjs=
+         fi
+         # Expand the library linking commands again to reset the
+         # value of $libobjs for piecewise linking.
+
+         # Do each of the archive commands.
+         if test "$module" = yes && test -n "$module_cmds" ; then
+           if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+             cmds=$module_expsym_cmds
+           else
+             cmds=$module_cmds
+           fi
+         else
+           if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+             cmds=$archive_expsym_cmds
+           else
+             cmds=$archive_cmds
+           fi
+         fi
+       fi
+
+       if test -n "$delfiles"; then
+         # Append the command to remove temporary files to $cmds.
+         eval cmds=\"\$cmds~\$RM $delfiles\"
+       fi
+
+       # Add any objects from preloaded convenience libraries
+       if test -n "$dlprefiles"; then
+         gentop="$output_objdir/${outputname}x"
+         generated="$generated $gentop"
+
+         func_extract_archives $gentop $dlprefiles
+         libobjs="$libobjs $func_extract_archives_result"
+         test "X$libobjs" = "X " && libobjs=
+       fi
+
+       save_ifs="$IFS"; IFS='~'
+       for cmd in $cmds; do
+         IFS="$save_ifs"
+         eval cmd=\"$cmd\"
+         $opt_silent || {
+           func_quote_for_expand "$cmd"
+           eval "func_echo $func_quote_for_expand_result"
+         }
+         $opt_dry_run || eval "$cmd" || {
+           lt_exit=$?
+
+           # Restore the uninstalled library and exit
+           if test "$mode" = relink; then
+             ( cd "$output_objdir" && \
+               $RM "${realname}T" && \
+               $MV "${realname}U" "$realname" )
+           fi
+
+           exit $lt_exit
+         }
+       done
+       IFS="$save_ifs"
+
+       # Restore the uninstalled library and exit
+       if test "$mode" = relink; then
+         $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+         if test -n "$convenience"; then
+           if test -z "$whole_archive_flag_spec"; then
+             func_show_eval '${RM}r "$gentop"'
+           fi
+         fi
+
+         exit $EXIT_SUCCESS
+       fi
+
+       # Create links to the real library.
+       for linkname in $linknames; do
+         if test "$realname" != "$linkname"; then
+           func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+         fi
+       done
+
+       # If -module or -export-dynamic was specified, set the dlname.
+       if test "$module" = yes || test "$export_dynamic" = yes; then
+         # On all known operating systems, these are identical.
+         dlname="$soname"
+       fi
+      fi
+      ;;
+
+    obj)
+      if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+       func_warning "\`-dlopen' is ignored for objects"
+      fi
+
+      case " $deplibs" in
+      *\ -l* | *\ -L*)
+       func_warning "\`-l' and \`-L' are ignored for objects" ;;
+      esac
+
+      test -n "$rpath" && \
+       func_warning "\`-rpath' is ignored for objects"
+
+      test -n "$xrpath" && \
+       func_warning "\`-R' is ignored for objects"
+
+      test -n "$vinfo" && \
+       func_warning "\`-version-info' is ignored for objects"
+
+      test -n "$release" && \
+       func_warning "\`-release' is ignored for objects"
+
+      case $output in
+      *.lo)
+       test -n "$objs$old_deplibs" && \
+         func_fatal_error "cannot build library object \`$output' from non-libtool objects"
+
+       libobj=$output
+       func_lo2o "$libobj"
+       obj=$func_lo2o_result
+       ;;
+      *)
+       libobj=
+       obj="$output"
+       ;;
+      esac
+
+      # Delete the old objects.
+      $opt_dry_run || $RM $obj $libobj
+
+      # Objects from convenience libraries.  This assumes
+      # single-version convenience libraries.  Whenever we create
+      # different ones for PIC/non-PIC, this we'll have to duplicate
+      # the extraction.
+      reload_conv_objs=
+      gentop=
+      # reload_cmds runs $LD directly, so let us get rid of
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
+      wl=
+
+      if test -n "$convenience"; then
+       if test -n "$whole_archive_flag_spec"; then
+         eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+         reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
+       else
+         gentop="$output_objdir/${obj}x"
+         generated="$generated $gentop"
+
+         func_extract_archives $gentop $convenience
+         reload_conv_objs="$reload_objs $func_extract_archives_result"
+       fi
+      fi
+
+      # Create the old-style object.
+      reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+      output="$obj"
+      func_execute_cmds "$reload_cmds" 'exit $?'
+
+      # Exit if we aren't doing a library object file.
+      if test -z "$libobj"; then
+       if test -n "$gentop"; then
+         func_show_eval '${RM}r "$gentop"'
+       fi
+
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$build_libtool_libs" != yes; then
+       if test -n "$gentop"; then
+         func_show_eval '${RM}r "$gentop"'
+       fi
+
+       # Create an invalid libtool object if no PIC, so that we don't
+       # accidentally link it into a program.
+       # $show "echo timestamp > $libobj"
+       # $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+       exit $EXIT_SUCCESS
+      fi
+
+      if test -n "$pic_flag" || test "$pic_mode" != default; then
+       # Only do commands if we really have different PIC objects.
+       reload_objs="$libobjs $reload_conv_objs"
+       output="$libobj"
+       func_execute_cmds "$reload_cmds" 'exit $?'
+      fi
+
+      if test -n "$gentop"; then
+       func_show_eval '${RM}r "$gentop"'
+      fi
+
+      exit $EXIT_SUCCESS
+      ;;
+
+    prog)
+      case $host in
+       *cygwin*) func_stripname '' '.exe' "$output"
+                 output=$func_stripname_result.exe;;
+      esac
+      test -n "$vinfo" && \
+       func_warning "\`-version-info' is ignored for programs"
+
+      test -n "$release" && \
+       func_warning "\`-release' is ignored for programs"
+
+      test "$preload" = yes \
+        && test "$dlopen_support" = unknown \
+       && test "$dlopen_self" = unknown \
+       && test "$dlopen_self_static" = unknown && \
+         func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+      case $host in
+      *-*-rhapsody* | *-*-darwin1.[012])
+       # On Rhapsody replace the C library is the System framework
+       compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+       finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'`
+       ;;
+      esac
+
+      case $host in
+      *-*-darwin*)
+       # Don't allow lazy linking, it breaks C++ global constructors
+       # But is supposedly fixed on 10.4 or later (yay!).
+       if test "$tagname" = CXX ; then
+         case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+           10.[0123])
+             compile_command="$compile_command ${wl}-bind_at_load"
+             finalize_command="$finalize_command ${wl}-bind_at_load"
+           ;;
+         esac
+       fi
+       # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+       compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+       finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'`
+       ;;
+      esac
+
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $compile_deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $compile_deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      compile_deplibs="$new_libs"
+
+
+      compile_command="$compile_command $compile_deplibs"
+      finalize_command="$finalize_command $finalize_deplibs"
+
+      if test -n "$rpath$xrpath"; then
+       # If the user specified any rpath flags, then add them.
+       for libdir in $rpath $xrpath; do
+         # This is the magic to use -rpath.
+         case "$finalize_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_rpath="$finalize_rpath $libdir" ;;
+         esac
+       done
+      fi
+
+      # Now hardcode the library paths
+      rpath=
+      hardcode_libdirs=
+      for libdir in $compile_rpath $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$perm_rpath " in
+         *" $libdir "*) ;;
+         *) perm_rpath="$perm_rpath $libdir" ;;
+         esac
+       fi
+       case $host in
+       *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+         testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'`
+         case :$dllsearchpath: in
+         *":$libdir:"*) ;;
+         ::) dllsearchpath=$libdir;;
+         *) dllsearchpath="$dllsearchpath:$libdir";;
+         esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         ::) dllsearchpath=$testbindir;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
+         ;;
+       esac
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      compile_rpath="$rpath"
+
+      rpath=
+      hardcode_libdirs=
+      for libdir in $finalize_rpath; do
+       if test -n "$hardcode_libdir_flag_spec"; then
+         if test -n "$hardcode_libdir_separator"; then
+           if test -z "$hardcode_libdirs"; then
+             hardcode_libdirs="$libdir"
+           else
+             # Just accumulate the unique libdirs.
+             case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+             *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+               ;;
+             *)
+               hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+               ;;
+             esac
+           fi
+         else
+           eval flag=\"$hardcode_libdir_flag_spec\"
+           rpath="$rpath $flag"
+         fi
+       elif test -n "$runpath_var"; then
+         case "$finalize_perm_rpath " in
+         *" $libdir "*) ;;
+         *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+         esac
+       fi
+      done
+      # Substitute the hardcoded libdirs into the rpath.
+      if test -n "$hardcode_libdir_separator" &&
+        test -n "$hardcode_libdirs"; then
+       libdir="$hardcode_libdirs"
+       eval rpath=\" $hardcode_libdir_flag_spec\"
+      fi
+      finalize_rpath="$rpath"
+
+      if test -n "$libobjs" && test "$build_old_libs" = yes; then
+       # Transform all the library objects into standard objects.
+       compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+       finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+      fi
+
+      func_generate_dlsyms "$outputname" "@PROGRAM@" "no"
+
+      # template prelinking step
+      if test -n "$prelink_cmds"; then
+       func_execute_cmds "$prelink_cmds" 'exit $?'
+      fi
+
+      wrappers_required=yes
+      case $host in
+      *cygwin* | *mingw* )
+        if test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      *cegcc)
+        # Disable wrappers for cegcc, we are cross compiling anyway.
+        wrappers_required=no
+        ;;
+      *)
+        if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+          wrappers_required=no
+        fi
+        ;;
+      esac
+      if test "$wrappers_required" = no; then
+       # Replace the output file specification.
+       compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       link_command="$compile_command$compile_rpath"
+
+       # We have no uninstalled library dependencies, so finalize right now.
+       exit_status=0
+       func_show_eval "$link_command" 'exit_status=$?'
+
+       # Delete the generated files.
+       if test -f "$output_objdir/${outputname}S.${objext}"; then
+         func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"'
+       fi
+
+       exit $exit_status
+      fi
+
+      if test -n "$compile_shlibpath$finalize_shlibpath"; then
+       compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+      fi
+      if test -n "$finalize_shlibpath"; then
+       finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+      fi
+
+      compile_var=
+      finalize_var=
+      if test -n "$runpath_var"; then
+       if test -n "$perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+       if test -n "$finalize_perm_rpath"; then
+         # We should set the runpath_var.
+         rpath=
+         for dir in $finalize_perm_rpath; do
+           rpath="$rpath$dir:"
+         done
+         finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+       fi
+      fi
+
+      if test "$no_install" = yes; then
+       # We don't need to create a wrapper script.
+       link_command="$compile_var$compile_command$compile_rpath"
+       # Replace the output file specification.
+       link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       # Delete the old output file.
+       $opt_dry_run || $RM $output
+       # Link the executable and exit
+       func_show_eval "$link_command" 'exit $?'
+       exit $EXIT_SUCCESS
+      fi
+
+      if test "$hardcode_action" = relink; then
+       # Fast installation is not supported
+       link_command="$compile_var$compile_command$compile_rpath"
+       relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+       func_warning "this platform does not like uninstalled shared libraries"
+       func_warning "\`$output' will be relinked during installation"
+      else
+       if test "$fast_install" != no; then
+         link_command="$finalize_var$compile_command$finalize_rpath"
+         if test "$fast_install" = yes; then
+           relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+         else
+           # fast_install is set to needless
+           relink_command=
+         fi
+       else
+         link_command="$compile_var$compile_command$compile_rpath"
+         relink_command="$finalize_var$finalize_command$finalize_rpath"
+       fi
+      fi
+
+      # Replace the output file specification.
+      link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+      # Delete the old output files.
+      $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+      func_show_eval "$link_command" 'exit $?'
+
+      # Now create the wrapper script.
+      func_verbose "creating $output"
+
+      # Quote the relink command for shipping.
+      if test -n "$relink_command"; then
+       # Preserve any variables that may affect compiler behavior
+       for var in $variables_saved_for_relink; do
+         if eval test -z \"\${$var+set}\"; then
+           relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+         elif eval var_value=\$$var; test -z "$var_value"; then
+           relink_command="$var=; export $var; $relink_command"
+         else
+           func_quote_for_eval "$var_value"
+           relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+         fi
+       done
+       relink_command="(cd `pwd`; $relink_command)"
+       relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Quote $ECHO for shipping.
+      if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then
+       case $progpath in
+       [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+       *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+       esac
+       qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"`
+      else
+       qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"`
+      fi
+
+      # Only actually do things if not in dry run mode.
+      $opt_dry_run || {
+       # win32 will think the script is a binary if it has
+       # a .exe suffix, so we strip it off here.
+       case $output in
+         *.exe) func_stripname '' '.exe' "$output"
+                output=$func_stripname_result ;;
+       esac
+       # test for cygwin because mv fails w/o .exe extensions
+       case $host in
+         *cygwin*)
+           exeext=.exe
+           func_stripname '' '.exe' "$outputname"
+           outputname=$func_stripname_result ;;
+         *) exeext= ;;
+       esac
+       case $host in
+         *cygwin* | *mingw* )
+           func_dirname_and_basename "$output" "" "."
+           output_name=$func_basename_result
+           output_path=$func_dirname_result
+           cwrappersource="$output_path/$objdir/lt-$output_name.c"
+           cwrapper="$output_path/$output_name.exe"
+           $RM $cwrappersource $cwrapper
+           trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+           func_emit_cwrapperexe_src > $cwrappersource
+
+           # The wrapper executable is built using the $host compiler,
+           # because it contains $host paths and files. If cross-
+           # compiling, it, like the target executable, must be
+           # executed on the $host or under an emulation environment.
+           $opt_dry_run || {
+             $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+             $STRIP $cwrapper
+           }
+
+           # Now, create the wrapper script for func_source use:
+           func_ltwrapper_scriptname $cwrapper
+           $RM $func_ltwrapper_scriptname_result
+           trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+           $opt_dry_run || {
+             # note: this script will not be executed, so do not chmod.
+             if test "x$build" = "x$host" ; then
+               $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+             else
+               func_emit_wrapper no > $func_ltwrapper_scriptname_result
+             fi
+           }
+         ;;
+         * )
+           $RM $output
+           trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+           func_emit_wrapper no > $output
+           chmod +x $output
+         ;;
+       esac
+      }
+      exit $EXIT_SUCCESS
+      ;;
+    esac
+
+    # See if we need to build an old-fashioned archive.
+    for oldlib in $oldlibs; do
+
+      if test "$build_libtool_libs" = convenience; then
+       oldobjs="$libobjs_save $symfileobj"
+       addlibs="$convenience"
+       build_libtool_libs=no
+      else
+       if test "$build_libtool_libs" = module; then
+         oldobjs="$libobjs_save"
+         build_libtool_libs=no
+       else
+         oldobjs="$old_deplibs $non_pic_objects"
+         if test "$preload" = yes && test -f "$symfileobj"; then
+           oldobjs="$oldobjs $symfileobj"
+         fi
+       fi
+       addlibs="$old_convenience"
+      fi
+
+      if test -n "$addlibs"; then
+       gentop="$output_objdir/${outputname}x"
+       generated="$generated $gentop"
+
+       func_extract_archives $gentop $addlibs
+       oldobjs="$oldobjs $func_extract_archives_result"
+      fi
+
+      # Do each command in the archive commands.
+      if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+       cmds=$old_archive_from_new_cmds
+      else
+
+       # Add any objects from preloaded convenience libraries
+       if test -n "$dlprefiles"; then
+         gentop="$output_objdir/${outputname}x"
+         generated="$generated $gentop"
+
+         func_extract_archives $gentop $dlprefiles
+         oldobjs="$oldobjs $func_extract_archives_result"
+       fi
+
+       # POSIX demands no paths to be encoded in archives.  We have
+       # to avoid creating archives with duplicate basenames if we
+       # might have to extract them afterwards, e.g., when creating a
+       # static archive out of a convenience library, or when linking
+       # the entirety of a libtool archive into another (currently
+       # not supported by libtool).
+       if (for obj in $oldobjs
+           do
+             func_basename "$obj"
+             $ECHO "$func_basename_result"
+           done | sort | sort -uc >/dev/null 2>&1); then
+         :
+       else
+         $ECHO "copying selected object files to avoid basename conflicts..."
+         gentop="$output_objdir/${outputname}x"
+         generated="$generated $gentop"
+         func_mkdir_p "$gentop"
+         save_oldobjs=$oldobjs
+         oldobjs=
+         counter=1
+         for obj in $save_oldobjs
+         do
+           func_basename "$obj"
+           objbase="$func_basename_result"
+           case " $oldobjs " in
+           " ") oldobjs=$obj ;;
+           *[\ /]"$objbase "*)
+             while :; do
+               # Make sure we don't pick an alternate name that also
+               # overlaps.
+               newobj=lt$counter-$objbase
+               func_arith $counter + 1
+               counter=$func_arith_result
+               case " $oldobjs " in
+               *[\ /]"$newobj "*) ;;
+               *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+               esac
+             done
+             func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+             oldobjs="$oldobjs $gentop/$newobj"
+             ;;
+           *) oldobjs="$oldobjs $obj" ;;
+           esac
+         done
+       fi
+       eval cmds=\"$old_archive_cmds\"
+
+       func_len " $cmds"
+       len=$func_len_result
+       if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+         cmds=$old_archive_cmds
+       else
+         # the command line is too long to link in one step, link in parts
+         func_verbose "using piecewise archive linking..."
+         save_RANLIB=$RANLIB
+         RANLIB=:
+         objlist=
+         concat_cmds=
+         save_oldobjs=$oldobjs
+         oldobjs=
+         # Is there a better way of finding the last object in the list?
+         for obj in $save_oldobjs
+         do
+           last_oldobj=$obj
+         done
+         eval test_cmds=\"$old_archive_cmds\"
+         func_len " $test_cmds"
+         len0=$func_len_result
+         len=$len0
+         for obj in $save_oldobjs
+         do
+           func_len " $obj"
+           func_arith $len + $func_len_result
+           len=$func_arith_result
+           func_append objlist " $obj"
+           if test "$len" -lt "$max_cmd_len"; then
+             :
+           else
+             # the above command should be used before it gets too long
+             oldobjs=$objlist
+             if test "$obj" = "$last_oldobj" ; then
+               RANLIB=$save_RANLIB
+             fi
+             test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+             eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+             objlist=
+             len=$len0
+           fi
+         done
+         RANLIB=$save_RANLIB
+         oldobjs=$objlist
+         if test "X$oldobjs" = "X" ; then
+           eval cmds=\"\$concat_cmds\"
+         else
+           eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+         fi
+       fi
+      fi
+      func_execute_cmds "$cmds" 'exit $?'
+    done
+
+    test -n "$generated" && \
+      func_show_eval "${RM}r$generated"
+
+    # Now create the libtool archive.
+    case $output in
+    *.la)
+      old_library=
+      test "$build_old_libs" = yes && old_library="$libname.$libext"
+      func_verbose "creating $output"
+
+      # Preserve any variables that may affect compiler behavior
+      for var in $variables_saved_for_relink; do
+       if eval test -z \"\${$var+set}\"; then
+         relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+       elif eval var_value=\$$var; test -z "$var_value"; then
+         relink_command="$var=; export $var; $relink_command"
+       else
+         func_quote_for_eval "$var_value"
+         relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+       fi
+      done
+      # Quote the link command for shipping.
+      relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+      relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      if test "$hardcode_automatic" = yes ; then
+       relink_command=
+      fi
+
+      # Only create the output if not a dry run.
+      $opt_dry_run || {
+       for installed in no yes; do
+         if test "$installed" = yes; then
+           if test -z "$install_libdir"; then
+             break
+           fi
+           output="$output_objdir/$outputname"i
+           # Replace all uninstalled libtool libraries with the installed ones
+           newdependency_libs=
+           for deplib in $dependency_libs; do
+             case $deplib in
+             *.la)
+               func_basename "$deplib"
+               name="$func_basename_result"
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+               test -z "$libdir" && \
+                 func_fatal_error "\`$deplib' is not a valid libtool archive"
+               newdependency_libs="$newdependency_libs $libdir/$name"
+               ;;
+             *) newdependency_libs="$newdependency_libs $deplib" ;;
+             esac
+           done
+           dependency_libs="$newdependency_libs"
+           newdlfiles=
+
+           for lib in $dlfiles; do
+             case $lib in
+             *.la)
+               func_basename "$lib"
+               name="$func_basename_result"
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+               test -z "$libdir" && \
+                 func_fatal_error "\`$lib' is not a valid libtool archive"
+               newdlfiles="$newdlfiles $libdir/$name"
+               ;;
+             *) newdlfiles="$newdlfiles $lib" ;;
+             esac
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             case $lib in
+             *.la)
+               # Only pass preopened files to the pseudo-archive (for
+               # eventual linking with the app. that links it) if we
+               # didn't already link the preopened objects directly into
+               # the library:
+               func_basename "$lib"
+               name="$func_basename_result"
+               eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+               test -z "$libdir" && \
+                 func_fatal_error "\`$lib' is not a valid libtool archive"
+               newdlprefiles="$newdlprefiles $libdir/$name"
+               ;;
+             esac
+           done
+           dlprefiles="$newdlprefiles"
+         else
+           newdlfiles=
+           for lib in $dlfiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             newdlfiles="$newdlfiles $abs"
+           done
+           dlfiles="$newdlfiles"
+           newdlprefiles=
+           for lib in $dlprefiles; do
+             case $lib in
+               [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+               *) abs=`pwd`"/$lib" ;;
+             esac
+             newdlprefiles="$newdlprefiles $abs"
+           done
+           dlprefiles="$newdlprefiles"
+         fi
+         $RM $output
+         # place dlname in correct position for cygwin
+         tdlname=$dlname
+         case $host,$output,$installed,$module,$dlname in
+           *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+         esac
+         $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that can not go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+         if test "$installed" = no && test "$need_relink" = yes; then
+           $ECHO >> $output "\
+relink_command=\"$relink_command\""
+         fi
+       done
+      }
+
+      # Do a symbolic link so that the libtool archive can be found in
+      # LD_LIBRARY_PATH before the program is installed.
+      func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+      ;;
+    esac
+    exit $EXIT_SUCCESS
+}
+
+{ test "$mode" = link || test "$mode" = relink; } &&
+    func_mode_link ${1+"$@"}
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+    $opt_debug
+    RM="$nonopt"
+    files=
+    rmforce=
+    exit_status=0
+
+    # This variable tells wrapper scripts just to set variables rather
+    # than running their programs.
+    libtool_install_magic="$magic"
+
+    for arg
+    do
+      case $arg in
+      -f) RM="$RM $arg"; rmforce=yes ;;
+      -*) RM="$RM $arg" ;;
+      *) files="$files $arg" ;;
+      esac
+    done
+
+    test -z "$RM" && \
+      func_fatal_help "you must specify an RM program"
+
+    rmdirs=
+
+    origobjdir="$objdir"
+    for file in $files; do
+      func_dirname "$file" "" "."
+      dir="$func_dirname_result"
+      if test "X$dir" = X.; then
+       objdir="$origobjdir"
+      else
+       objdir="$dir/$origobjdir"
+      fi
+      func_basename "$file"
+      name="$func_basename_result"
+      test "$mode" = uninstall && objdir="$dir"
+
+      # Remember objdir for removal later, being careful to avoid duplicates
+      if test "$mode" = clean; then
+       case " $rmdirs " in
+         *" $objdir "*) ;;
+         *) rmdirs="$rmdirs $objdir" ;;
+       esac
+      fi
+
+      # Don't error if the file doesn't exist and rm -f was used.
+      if { test -L "$file"; } >/dev/null 2>&1 ||
+        { test -h "$file"; } >/dev/null 2>&1 ||
+        test -f "$file"; then
+       :
+      elif test -d "$file"; then
+       exit_status=1
+       continue
+      elif test "$rmforce" = yes; then
+       continue
+      fi
+
+      rmfiles="$file"
+
+      case $name in
+      *.la)
+       # Possibly a libtool archive, so verify it.
+       if func_lalib_p "$file"; then
+         func_source $dir/$name
+
+         # Delete the libtool libraries and symlinks.
+         for n in $library_names; do
+           rmfiles="$rmfiles $objdir/$n"
+         done
+         test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+
+         case "$mode" in
+         clean)
+           case "  $library_names " in
+           # "  " in the beginning catches empty $dlname
+           *" $dlname "*) ;;
+           *) rmfiles="$rmfiles $objdir/$dlname" ;;
+           esac
+           test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+           ;;
+         uninstall)
+           if test -n "$library_names"; then
+             # Do each command in the postuninstall commands.
+             func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+           fi
+
+           if test -n "$old_library"; then
+             # Do each command in the old_postuninstall commands.
+             func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1'
+           fi
+           # FIXME: should reinstall the best remaining shared library.
+           ;;
+         esac
+       fi
+       ;;
+
+      *.lo)
+       # Possibly a libtool object, so verify it.
+       if func_lalib_p "$file"; then
+
+         # Read the .lo file
+         func_source $dir/$name
+
+         # Add PIC object to the list of files to remove.
+         if test -n "$pic_object" &&
+            test "$pic_object" != none; then
+           rmfiles="$rmfiles $dir/$pic_object"
+         fi
+
+         # Add non-PIC object to the list of files to remove.
+         if test -n "$non_pic_object" &&
+            test "$non_pic_object" != none; then
+           rmfiles="$rmfiles $dir/$non_pic_object"
+         fi
+       fi
+       ;;
+
+      *)
+       if test "$mode" = clean ; then
+         noexename=$name
+         case $file in
+         *.exe)
+           func_stripname '' '.exe' "$file"
+           file=$func_stripname_result
+           func_stripname '' '.exe' "$name"
+           noexename=$func_stripname_result
+           # $file with .exe has already been added to rmfiles,
+           # add $file without .exe
+           rmfiles="$rmfiles $file"
+           ;;
+         esac
+         # Do a test to see if this is a libtool program.
+         if func_ltwrapper_p "$file"; then
+           if func_ltwrapper_executable_p "$file"; then
+             func_ltwrapper_scriptname "$file"
+             relink_command=
+             func_source $func_ltwrapper_scriptname_result
+             rmfiles="$rmfiles $func_ltwrapper_scriptname_result"
+           else
+             relink_command=
+             func_source $dir/$noexename
+           fi
+
+           # note $name still contains .exe if it was in $file originally
+           # as does the version of $file that was added into $rmfiles
+           rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+           if test "$fast_install" = yes && test -n "$relink_command"; then
+             rmfiles="$rmfiles $objdir/lt-$name"
+           fi
+           if test "X$noexename" != "X$name" ; then
+             rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+           fi
+         fi
+       fi
+       ;;
+      esac
+      func_show_eval "$RM $rmfiles" 'exit_status=1'
+    done
+    objdir="$origobjdir"
+
+    # Try to remove the ${objdir}s in the directories where we deleted files
+    for dir in $rmdirs; do
+      if test -d "$dir"; then
+       func_show_eval "rmdir $dir >/dev/null 2>&1"
+      fi
+    done
+
+    exit $exit_status
+}
+
+{ test "$mode" = uninstall || test "$mode" = clean; } &&
+    func_mode_uninstall ${1+"$@"}
+
+test -z "$mode" && {
+  help="$generic_help"
+  func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+  func_fatal_help "invalid operation mode \`$mode'"
+
+if test -n "$exec_cmd"; then
+  eval exec "$exec_cmd"
+  exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries.  Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them.  This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration.  But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
+# vi:sw=2
+
diff --git a/missing b/missing
new file mode 100755 (executable)
index 0000000..28055d2
--- /dev/null
+++ b/missing
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  autom4te     touch the output file, or create a stub one
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+  s/^gnu-//; t
+  s/^gnu//; t
+  s/^g//; t'`
+
+# Now exit if we have it, but it failed.  Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).  This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+  lex*|yacc*)
+    # Not GNU programs, they don't have --version.
+    ;;
+
+  tar*)
+    if test -n "$run"; then
+       echo 1>&2 "ERROR: \`tar' requires --run"
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       exit 1
+    fi
+    ;;
+
+  *)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       # Could not run --version or --help.  This is probably someone
+       # running `$TOOL --version' or `$TOOL --help' to check whether
+       # $TOOL exists and not knowing $TOOL uses missing.
+       exit 1
+    fi
+    ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+  aclocal*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case $f in
+      *:*) touch_files="$touch_files "`echo "$f" |
+                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+          sed 's/\.am$/.in/' |
+          while read f; do touch "$f"; done
+    ;;
+
+  autom4te*)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+       touch $file
+    else
+       test -z "$file" || exec >$file
+       echo "#! /bin/sh"
+       echo "# Created by GNU Automake missing as a replacement of"
+       echo "#  $ $@"
+       echo "exit 0"
+       chmod +x $file
+       exit 1
+    fi
+    ;;
+
+  bison*|yacc*)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+       case $LASTARG in
+       *.y)
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+           if test -f "$SRCFILE"; then
+                cp "$SRCFILE" y.tab.c
+           fi
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+           if test -f "$SRCFILE"; then
+                cp "$SRCFILE" y.tab.h
+           fi
+         ;;
+       esac
+    fi
+    if test ! -f y.tab.h; then
+       echo >y.tab.h
+    fi
+    if test ! -f y.tab.c; then
+       echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex*|flex*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+       case $LASTARG in
+       *.l)
+           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+           if test -f "$SRCFILE"; then
+                cp "$SRCFILE" lex.yy.c
+           fi
+         ;;
+       esac
+    fi
+    if test ! -f lex.yy.c; then
+       echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+        you modified a dependency of a manual page.  You may need the
+        \`Help2man' package in order for those modifications to take
+        effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+       touch $file
+    else
+       test -z "$file" || exec >$file
+       echo ".ab help2man is required to generate this page"
+       exit $?
+    fi
+    ;;
+
+  makeinfo*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    # The file to touch is that specified with -o ...
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -z "$file"; then
+      # ... or it is the one specified with @setfilename ...
+      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '
+       /^@setfilename/{
+         s/.* \([^ ]*\) *$/\1/
+         p
+         q
+       }' $infile`
+      # ... or it is derived from the source name (dir/f.texi becomes f.info)
+      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+    fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
+    touch $file
+    ;;
+
+  tar*)
+    shift
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+       case $firstarg in
+       *o*)
+           firstarg=`echo "$firstarg" | sed s/o//`
+           tar "$firstarg" "$@" && exit 0
+           ;;
+       esac
+       case $firstarg in
+       *h*)
+           firstarg=`echo "$firstarg" | sed s/h//`
+           tar "$firstarg" "$@" && exit 0
+           ;;
+       esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..9839c03
--- /dev/null
@@ -0,0 +1,1391 @@
+SUBDIRS = libcollectdclient
+if BUILD_WITH_OWN_LIBOCONFIG
+SUBDIRS += liboconfig
+endif
+SUBDIRS += daemon
+
+PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
+
+if COMPILER_IS_GCC
+AM_CFLAGS = -Wall -Werror
+endif
+
+AM_CPPFLAGS = -I$(srcdir)/daemon
+AM_CPPFLAGS += -DPREFIX='"${prefix}"'
+AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
+AM_CPPFLAGS += -DLOCALSTATEDIR='"${localstatedir}"'
+AM_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
+if BUILD_FEATURE_DAEMON
+AM_CPPFLAGS += -DPIDFILE='"${localstatedir}/run/${PACKAGE_NAME}.pid"'
+endif
+AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
+AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+noinst_LTLIBRARIES = libmount.la liblookup.la
+
+libmount_la_SOURCES = utils_mount.c utils_mount.h
+libmount_la_LIBADD = daemon/libcommon.la
+
+liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
+liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la
+
+sbin_PROGRAMS = collectdmon
+bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
+
+collectdmon_SOURCES = collectdmon.c
+collectdmon_CPPFLAGS = $(AM_CPPFLAGS)
+
+collectd_nagios_SOURCES = collectd-nagios.c
+collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_nagios_LDADD =
+if BUILD_WITH_LIBSOCKET
+collectd_nagios_LDADD += -lsocket
+endif
+if BUILD_AIX
+collectd_nagios_LDADD += -lm
+endif
+
+collectd_nagios_LDADD += libcollectdclient/libcollectdclient.la
+collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+
+
+collectdctl_SOURCES = collectdctl.c
+collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectdctl_LDADD =
+if BUILD_WITH_LIBSOCKET
+collectdctl_LDADD += -lsocket
+endif
+if BUILD_AIX
+collectdctl_LDADD += -lm
+endif
+collectdctl_LDADD += libcollectdclient/libcollectdclient.la
+collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+
+collectd_tg_SOURCES = collectd-tg.c
+collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_LDADD = daemon/libheap.la
+if BUILD_WITH_LIBSOCKET
+collectd_tg_LDADD += -lsocket
+endif
+if BUILD_WITH_LIBRT
+collectd_tg_LDADD += -lrt
+endif
+if BUILD_AIX
+collectd_tg_LDADD += -lm
+endif
+if BUILD_WITH_LIBPTHREAD
+collectd_tg_LDADD += -lpthread
+endif
+collectd_tg_LDADD += libcollectdclient/libcollectdclient.la
+collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+
+
+pkglib_LTLIBRARIES =
+
+BUILT_SOURCES =
+CLEANFILES =
+
+if BUILD_PLUGIN_AGGREGATION
+pkglib_LTLIBRARIES += aggregation.la
+aggregation_la_SOURCES = aggregation.c \
+                         utils_vl_lookup.c utils_vl_lookup.h
+aggregation_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+aggregation_la_LIBADD = -lm
+endif
+
+if BUILD_PLUGIN_AMQP
+pkglib_LTLIBRARIES += amqp.la
+amqp_la_SOURCES = amqp.c \
+                 utils_cmd_putval.c utils_cmd_putval.h \
+                 utils_format_graphite.c utils_format_graphite.h \
+                 utils_format_json.c utils_format_json.h
+amqp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
+amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
+amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS)
+endif
+
+if BUILD_PLUGIN_APACHE
+pkglib_LTLIBRARIES += apache.la
+apache_la_SOURCES = apache.c
+apache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+apache_la_CFLAGS = $(AM_CFLAGS)
+apache_la_LIBADD =
+if BUILD_WITH_LIBCURL
+apache_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+apache_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+endif
+
+if BUILD_PLUGIN_APCUPS
+pkglib_LTLIBRARIES += apcups.la
+apcups_la_SOURCES = apcups.c
+apcups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+apcups_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+apcups_la_LIBADD += -lsocket
+endif
+endif
+
+if BUILD_PLUGIN_APPLE_SENSORS
+pkglib_LTLIBRARIES += apple_sensors.la
+apple_sensors_la_SOURCES = apple_sensors.c
+apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+apple_sensors_la_LDFLAGS += -framework IOKit
+endif
+
+if BUILD_PLUGIN_AQUAERO
+pkglib_LTLIBRARIES += aquaero.la
+aquaero_la_SOURCES = aquaero.c
+aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+aquaero_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBAQUAERO5_CFLAGS)
+aquaero_la_LIBADD = $(BUILD_WITH_LIBAQUAERO5_LDFLAGS) -laquaero5
+endif
+
+if BUILD_PLUGIN_ASCENT
+pkglib_LTLIBRARIES += ascent.la
+ascent_la_SOURCES = ascent.c
+ascent_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+ascent_la_CFLAGS = $(AM_CFLAGS) \
+               $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+ascent_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+endif
+
+if BUILD_PLUGIN_BAROMETER
+pkglib_LTLIBRARIES += barometer.la
+barometer_la_SOURCES = barometer.c
+barometer_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+barometer_la_LIBADD = -lm
+endif
+
+if BUILD_PLUGIN_BATTERY
+pkglib_LTLIBRARIES += battery.la
+battery_la_SOURCES = battery.c
+battery_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+battery_la_LIBADD =
+if BUILD_WITH_LIBIOKIT
+battery_la_LDFLAGS += -framework IOKit
+endif
+endif
+
+if BUILD_PLUGIN_BIND
+pkglib_LTLIBRARIES += bind.la
+bind_la_SOURCES = bind.c
+bind_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+bind_la_CFLAGS = $(AM_CFLAGS) \
+                $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+bind_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+endif
+
+if BUILD_PLUGIN_CEPH
+pkglib_LTLIBRARIES += ceph.la
+ceph_la_SOURCES = ceph.c
+ceph_la_CFLAGS = $(AM_CFLAGS)
+ceph_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+ceph_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+ceph_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+endif
+
+if BUILD_PLUGIN_CGROUPS
+pkglib_LTLIBRARIES += cgroups.la
+cgroups_la_SOURCES = cgroups.c \
+                    utils_ignorelist.c utils_ignorelist.h
+cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+cgroups_la_LIBADD = libmount.la
+endif
+
+if BUILD_PLUGIN_CONNTRACK
+pkglib_LTLIBRARIES += conntrack.la
+conntrack_la_SOURCES = conntrack.c
+conntrack_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_CONTEXTSWITCH
+pkglib_LTLIBRARIES += contextswitch.la
+contextswitch_la_SOURCES = contextswitch.c
+contextswitch_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+contextswitch_la_LIBADD =
+if BUILD_WITH_PERFSTAT
+contextswitch_la_LIBADD += -lperfstat
+endif
+endif
+
+if BUILD_PLUGIN_CPU
+pkglib_LTLIBRARIES += cpu.la
+cpu_la_SOURCES = cpu.c
+cpu_la_CFLAGS = $(AM_CFLAGS)
+cpu_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+cpu_la_LIBADD =
+if BUILD_WITH_LIBKSTAT
+cpu_la_LIBADD += -lkstat
+endif
+if BUILD_WITH_LIBDEVINFO
+cpu_la_LIBADD += -ldevinfo
+endif
+if BUILD_WITH_LIBSTATGRAB
+cpu_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+cpu_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+endif
+if BUILD_WITH_PERFSTAT
+cpu_la_LIBADD += -lperfstat
+endif
+endif
+
+if BUILD_PLUGIN_CPUFREQ
+pkglib_LTLIBRARIES += cpufreq.la
+cpufreq_la_SOURCES = cpufreq.c
+cpufreq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_CSV
+pkglib_LTLIBRARIES += csv.la
+csv_la_SOURCES = csv.c
+csv_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_CURL
+pkglib_LTLIBRARIES += curl.la
+curl_la_SOURCES = curl.c
+curl_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+curl_la_CFLAGS = $(AM_CFLAGS)
+curl_la_LIBADD =
+if BUILD_WITH_LIBCURL
+curl_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+curl_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+endif
+
+if BUILD_PLUGIN_CURL_JSON
+pkglib_LTLIBRARIES += curl_json.la
+curl_json_la_SOURCES = curl_json.c
+curl_json_la_CFLAGS = $(AM_CFLAGS)
+curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+curl_json_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+if BUILD_WITH_LIBCURL
+curl_json_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+curl_json_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+endif
+
+if BUILD_PLUGIN_CURL_XML
+pkglib_LTLIBRARIES += curl_xml.la
+curl_xml_la_SOURCES = curl_xml.c
+curl_xml_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+curl_xml_la_CFLAGS = $(AM_CFLAGS) \
+               $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+curl_xml_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+endif
+
+if BUILD_PLUGIN_DBI
+pkglib_LTLIBRARIES += dbi.la
+dbi_la_SOURCES = dbi.c \
+                utils_db_query.c utils_db_query.h
+dbi_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBDBI_CPPFLAGS)
+dbi_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBDBI_LDFLAGS)
+dbi_la_LIBADD = $(BUILD_WITH_LIBDBI_LIBS)
+endif
+
+if BUILD_PLUGIN_DF
+pkglib_LTLIBRARIES += df.la
+df_la_SOURCES = df.c \
+               utils_ignorelist.c utils_ignorelist.h
+df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+df_la_LIBADD = libmount.la
+endif
+
+if BUILD_PLUGIN_DISK
+pkglib_LTLIBRARIES += disk.la
+disk_la_SOURCES = disk.c \
+                 utils_ignorelist.c utils_ignorelist.h
+disk_la_CFLAGS = $(AM_CFLAGS)
+disk_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+disk_la_LIBADD =
+if BUILD_WITH_LIBKSTAT
+disk_la_LIBADD += -lkstat
+endif
+if BUILD_WITH_LIBDEVINFO
+disk_la_LIBADD += -ldevinfo
+endif
+if BUILD_WITH_LIBIOKIT
+disk_la_LDFLAGS += -framework IOKit
+endif
+if BUILD_WITH_LIBSTATGRAB
+disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+disk_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+endif
+if BUILD_WITH_LIBUDEV
+disk_la_LIBADD += -ludev
+endif
+if BUILD_WITH_PERFSTAT
+disk_la_LIBADD += -lperfstat
+endif
+endif
+
+if BUILD_PLUGIN_DNS
+pkglib_LTLIBRARIES += dns.la
+dns_la_SOURCES = dns.c utils_dns.c utils_dns.h
+dns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+dns_la_LIBADD = -lpcap -lpthread
+endif
+
+if BUILD_PLUGIN_DRBD
+pkglib_LTLIBRARIES += drbd.la
+drbd_la_SOURCES = drbd.c
+drbd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+drbd_la_LIBADD = -lpthread
+endif
+
+if BUILD_PLUGIN_EMAIL
+pkglib_LTLIBRARIES += email.la
+email_la_SOURCES = email.c
+email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+email_la_LIBADD = -lpthread
+endif
+
+if BUILD_PLUGIN_ENTROPY
+pkglib_LTLIBRARIES += entropy.la
+entropy_la_SOURCES = entropy.c
+entropy_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_EXEC
+pkglib_LTLIBRARIES += exec.la
+exec_la_SOURCES = exec.c \
+                 utils_cmd_putnotif.c utils_cmd_putnotif.h \
+                 utils_cmd_putval.c utils_cmd_putval.h \
+                 utils_parse_option.h utils_parse_option.c
+exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+exec_la_LIBADD = -lpthread
+endif
+
+if BUILD_PLUGIN_ETHSTAT
+pkglib_LTLIBRARIES += ethstat.la
+ethstat_la_SOURCES = ethstat.c
+ethstat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_FHCOUNT
+pkglib_LTLIBRARIES += fhcount.la
+fhcount_la_SOURCES = fhcount.c
+fhcount_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_FILECOUNT
+pkglib_LTLIBRARIES += filecount.la
+filecount_la_SOURCES = filecount.c
+filecount_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_GMOND
+pkglib_LTLIBRARIES += gmond.la
+gmond_la_SOURCES = gmond.c
+gmond_la_CPPFLAGS = $(AM_CPPFLAGS) $(GANGLIA_CPPFLAGS)
+gmond_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(GANGLIA_LDFLAGS)
+gmond_la_LIBADD = $(GANGLIA_LIBS)
+endif
+
+if BUILD_PLUGIN_HDDTEMP
+pkglib_LTLIBRARIES += hddtemp.la
+hddtemp_la_SOURCES = hddtemp.c
+hddtemp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+hddtemp_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+hddtemp_la_LIBADD += -lsocket
+endif
+endif
+
+if BUILD_PLUGIN_INTERFACE
+pkglib_LTLIBRARIES += interface.la
+interface_la_SOURCES = interface.c \
+                      utils_ignorelist.c utils_ignorelist.h
+interface_la_CFLAGS = $(AM_CFLAGS)
+interface_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+interface_la_LIBADD =
+if BUILD_WITH_LIBSTATGRAB
+interface_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+interface_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+else
+if BUILD_WITH_LIBKSTAT
+interface_la_LIBADD += -lkstat
+endif
+if BUILD_WITH_LIBDEVINFO
+interface_la_LIBADD += -ldevinfo
+endif # BUILD_WITH_LIBDEVINFO
+endif # !BUILD_WITH_LIBSTATGRAB
+if BUILD_WITH_PERFSTAT
+interface_la_LIBADD += -lperfstat
+endif
+endif # BUILD_PLUGIN_INTERFACE
+
+if BUILD_PLUGIN_IPC
+pkglib_LTLIBRARIES += ipc.la
+ipc_la_SOURCES = ipc.c
+ipc_la_CFLAGS = $(AM_CFLAGS)
+ipc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_IPTABLES
+pkglib_LTLIBRARIES += iptables.la
+iptables_la_SOURCES = iptables.c
+iptables_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBIPTC_CPPFLAGS)
+iptables_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+iptables_la_LIBADD = $(BUILD_WITH_LIBIPTC_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_IPMI
+pkglib_LTLIBRARIES += ipmi.la
+ipmi_la_SOURCES = ipmi.c \
+                 utils_ignorelist.c utils_ignorelist.h
+ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
+ipmi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
+endif
+
+if BUILD_PLUGIN_IPVS
+pkglib_LTLIBRARIES += ipvs.la
+ipvs_la_SOURCES = ipvs.c
+if IP_VS_H_NEEDS_KERNEL_CFLAGS
+ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
+endif
+ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_IRQ
+pkglib_LTLIBRARIES += irq.la
+irq_la_SOURCES = irq.c \
+                utils_ignorelist.c utils_ignorelist.h
+irq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_JAVA
+pkglib_LTLIBRARIES += java.la
+java_la_SOURCES = java.c
+java_la_CPPFLAGS = $(AM_CPPFLAGS) $(JAVA_CPPFLAGS)
+java_la_CFLAGS = $(AM_CFLAGS) $(JAVA_CFLAGS)
+java_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(JAVA_LDFLAGS)
+java_la_LIBADD = $(JAVA_LIBS)
+endif
+
+if BUILD_PLUGIN_LOAD
+pkglib_LTLIBRARIES += load.la
+load_la_SOURCES = load.c
+load_la_CFLAGS = $(AM_CFLAGS)
+load_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+load_la_LIBADD =
+if BUILD_WITH_LIBSTATGRAB
+load_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+load_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+endif # BUILD_WITH_LIBSTATGRAB
+if BUILD_WITH_PERFSTAT
+load_la_LIBADD += -lperfstat
+endif
+endif # BUILD_PLUGIN_LOAD
+
+if BUILD_PLUGIN_LOGFILE
+pkglib_LTLIBRARIES += logfile.la
+logfile_la_SOURCES = logfile.c
+logfile_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_LOG_LOGSTASH
+pkglib_LTLIBRARIES += log_logstash.la
+log_logstash_la_SOURCES = log_logstash.c
+log_logstash_la_CFLAGS = $(AM_CFLAGS)
+log_logstash_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+endif
+
+if BUILD_PLUGIN_LPAR
+pkglib_LTLIBRARIES += lpar.la
+lpar_la_SOURCES = lpar.c
+lpar_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+lpar_la_LIBADD = -lperfstat
+endif
+
+if BUILD_PLUGIN_LVM
+pkglib_LTLIBRARIES += lvm.la
+lvm_la_SOURCES = lvm.c
+lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
+endif
+
+if BUILD_PLUGIN_MADWIFI
+pkglib_LTLIBRARIES += madwifi.la
+madwifi_la_SOURCES = madwifi.c madwifi.h \
+                    utils_ignorelist.c utils_ignorelist.h
+madwifi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MATCH_EMPTY_COUNTER
+pkglib_LTLIBRARIES += match_empty_counter.la
+match_empty_counter_la_SOURCES = match_empty_counter.c
+match_empty_counter_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MATCH_HASHED
+pkglib_LTLIBRARIES += match_hashed.la
+match_hashed_la_SOURCES = match_hashed.c
+match_hashed_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MATCH_REGEX
+pkglib_LTLIBRARIES += match_regex.la
+match_regex_la_SOURCES = match_regex.c
+match_regex_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MATCH_TIMEDIFF
+pkglib_LTLIBRARIES += match_timediff.la
+match_timediff_la_SOURCES = match_timediff.c
+match_timediff_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MATCH_VALUE
+pkglib_LTLIBRARIES += match_value.la
+match_value_la_SOURCES = match_value.c
+match_value_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MBMON
+pkglib_LTLIBRARIES += mbmon.la
+mbmon_la_SOURCES = mbmon.c
+mbmon_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+mbmon_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+mbmon_la_LIBADD += -lsocket
+endif
+endif
+
+if BUILD_PLUGIN_MD
+pkglib_LTLIBRARIES += md.la
+md_la_SOURCES = md.c \
+               utils_ignorelist.c utils_ignorelist.h
+md_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MEMCACHEC
+pkglib_LTLIBRARIES += memcachec.la
+memcachec_la_SOURCES = memcachec.c
+memcachec_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMEMCACHED_LDFLAGS)
+memcachec_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMEMCACHED_CPPFLAGS)
+memcachec_la_LIBADD = $(BUILD_WITH_LIBMEMCACHED_LIBS)
+endif
+
+if BUILD_PLUGIN_MEMCACHED
+pkglib_LTLIBRARIES += memcached.la
+memcached_la_SOURCES = memcached.c
+memcached_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+memcached_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+memcached_la_LIBADD += -lsocket
+endif
+endif
+
+if BUILD_PLUGIN_MEMORY
+pkglib_LTLIBRARIES += memory.la
+memory_la_SOURCES = memory.c
+memory_la_CFLAGS = $(AM_CFLAGS)
+memory_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+memory_la_LIBADD =
+if BUILD_WITH_LIBKSTAT
+memory_la_LIBADD += -lkstat
+endif
+if BUILD_WITH_LIBDEVINFO
+memory_la_LIBADD += -ldevinfo
+endif
+if BUILD_WITH_LIBSTATGRAB
+memory_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+memory_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+endif
+if BUILD_WITH_PERFSTAT
+memory_la_LIBADD += -lperfstat
+endif
+endif
+
+if BUILD_PLUGIN_MIC
+pkglib_LTLIBRARIES += mic.la
+mic_la_SOURCES = mic.c \
+                utils_ignorelist.c utils_ignorelist.h
+mic_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_MIC_LIBPATH)
+mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
+mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD)
+endif
+
+if BUILD_PLUGIN_MODBUS
+pkglib_LTLIBRARIES += modbus.la
+modbus_la_SOURCES = modbus.c
+modbus_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS)
+modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
+endif
+
+if BUILD_PLUGIN_MULTIMETER
+pkglib_LTLIBRARIES += multimeter.la
+multimeter_la_SOURCES = multimeter.c
+multimeter_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_MYSQL
+pkglib_LTLIBRARIES += mysql.la
+mysql_la_SOURCES = mysql.c
+mysql_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+mysql_la_CFLAGS = $(AM_CFLAGS)
+mysql_la_LIBADD =
+if BUILD_WITH_LIBMYSQL
+mysql_la_CFLAGS += $(BUILD_WITH_LIBMYSQL_CFLAGS)
+mysql_la_LIBADD += $(BUILD_WITH_LIBMYSQL_LIBS)
+endif
+endif
+
+if BUILD_PLUGIN_NETAPP
+pkglib_LTLIBRARIES += netapp.la
+netapp_la_SOURCES = netapp.c \
+                   utils_ignorelist.c utils_ignorelist.h
+netapp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNETAPP_CPPFLAGS)
+netapp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBNETAPP_LDFLAGS)
+netapp_la_LIBADD = $(LIBNETAPP_LIBS)
+endif
+
+if BUILD_PLUGIN_NETLINK
+pkglib_LTLIBRARIES += netlink.la
+netlink_la_SOURCES = netlink.c
+netlink_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+netlink_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMNL_CFLAGS)
+netlink_la_LIBADD = $(BUILD_WITH_LIBMNL_LIBS)
+endif
+
+if BUILD_PLUGIN_NETWORK
+pkglib_LTLIBRARIES += network.la
+network_la_SOURCES = network.c network.h \
+                    utils_fbhash.c utils_fbhash.h
+network_la_CPPFLAGS = $(AM_CPPFLAGS)
+network_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+network_la_LIBADD = -lpthread
+if BUILD_WITH_LIBSOCKET
+network_la_LIBADD += -lsocket
+endif
+if BUILD_WITH_LIBGCRYPT
+network_la_CPPFLAGS += $(GCRYPT_CPPFLAGS)
+network_la_LDFLAGS += $(GCRYPT_LDFLAGS)
+network_la_LIBADD += $(GCRYPT_LIBS)
+endif
+endif
+
+if BUILD_PLUGIN_NFS
+pkglib_LTLIBRARIES += nfs.la
+nfs_la_SOURCES = nfs.c
+nfs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_FSCACHE
+pkglib_LTLIBRARIES += fscache.la
+fscache_la_SOURCES = fscache.c
+fscache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_NGINX
+pkglib_LTLIBRARIES += nginx.la
+nginx_la_SOURCES = nginx.c
+nginx_la_CFLAGS = $(AM_CFLAGS)
+nginx_la_LIBADD =
+nginx_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+if BUILD_WITH_LIBCURL
+nginx_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+nginx_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+endif
+
+if BUILD_PLUGIN_NOTIFY_DESKTOP
+pkglib_LTLIBRARIES += notify_desktop.la
+notify_desktop_la_SOURCES = notify_desktop.c
+notify_desktop_la_CFLAGS = $(AM_CFLAGS) $(LIBNOTIFY_CFLAGS)
+notify_desktop_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+notify_desktop_la_LIBADD = $(LIBNOTIFY_LIBS)
+endif
+
+if BUILD_PLUGIN_NOTIFY_EMAIL
+pkglib_LTLIBRARIES += notify_email.la
+notify_email_la_SOURCES = notify_email.c
+notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread
+endif
+
+if BUILD_PLUGIN_NTPD
+pkglib_LTLIBRARIES += ntpd.la
+ntpd_la_SOURCES = ntpd.c
+ntpd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+ntpd_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+ntpd_la_LIBADD += -lsocket
+endif
+endif
+
+if BUILD_PLUGIN_NUMA
+pkglib_LTLIBRARIES += numa.la
+numa_la_SOURCES = numa.c
+numa_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_NUT
+pkglib_LTLIBRARIES += nut.la
+nut_la_SOURCES = nut.c
+nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
+nut_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+nut_la_LIBADD = -lpthread $(BUILD_WITH_LIBUPSCLIENT_LIBS)
+endif
+
+if BUILD_PLUGIN_OLSRD
+pkglib_LTLIBRARIES += olsrd.la
+olsrd_la_SOURCES = olsrd.c
+olsrd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+olsrd_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+olsrd_la_LIBADD += -lsocket
+endif
+endif
+
+if BUILD_PLUGIN_ONEWIRE
+pkglib_LTLIBRARIES += onewire.la
+onewire_la_SOURCES = onewire.c \
+                    utils_ignorelist.c utils_ignorelist.h
+onewire_la_CFLAGS = $(AM_CFLAGS)
+onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
+onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_OPENLDAP
+pkglib_LTLIBRARIES += openldap.la
+openldap_la_SOURCES = openldap.c
+openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS)
+openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_LIBADD = -lldap
+endif
+
+if BUILD_PLUGIN_OPENVPN
+pkglib_LTLIBRARIES += openvpn.la
+openvpn_la_SOURCES = openvpn.c
+openvpn_la_CFLAGS = $(AM_CFLAGS)
+openvpn_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_ORACLE
+pkglib_LTLIBRARIES += oracle.la
+oracle_la_SOURCES = oracle.c \
+       utils_db_query.c utils_db_query.h
+oracle_la_CFLAGS = $(AM_CFLAGS)
+oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CFLAGS)
+oracle_la_LIBADD = $(BUILD_WITH_ORACLE_LIBS)
+oracle_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_PERL
+pkglib_LTLIBRARIES += perl.la
+perl_la_SOURCES = perl.c
+# Despite C99 providing the "bool" type thru stdbool.h, Perl defines its own
+# version of that type if HAS_BOOL is not defined... *sigh*
+perl_la_CPPFLAGS = $(AM_CPPFLAGS) -DHAS_BOOL=1
+perl_la_CFLAGS  = $(AM_CFLAGS) \
+               $(PERL_CFLAGS) \
+               -DXS_VERSION=\"$(VERSION)\" -DVERSION=\"$(VERSION)\"
+# Work-around for issues #41 and #42 - Perl 5.10 incorrectly introduced
+# __attribute__nonnull__(3) for Perl_load_module().
+if HAVE_BROKEN_PERL_LOAD_MODULE
+perl_la_CFLAGS += -Wno-nonnull
+endif
+perl_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
+               $(PERL_LDFLAGS)
+perl_la_LIBADD = $(PERL_LIBS)
+endif
+
+if BUILD_PLUGIN_PF
+pkglib_LTLIBRARIES += pf.la
+pf_la_SOURCES = pf.c
+pf_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_PINBA
+pkglib_LTLIBRARIES += pinba.la
+pinba_la_SOURCES = pinba.c
+nodist_pinba_la_SOURCES = pinba.pb-c.c pinba.pb-c.h
+pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+pinba_la_LIBADD = -lprotobuf-c
+endif
+
+if BUILD_PLUGIN_PING
+pkglib_LTLIBRARIES += ping.la
+ping_la_SOURCES = ping.c
+ping_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOPING_CPPFLAGS)
+ping_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOPING_LDFLAGS)
+ping_la_LIBADD = -loping -lm
+endif
+
+if BUILD_PLUGIN_POSTGRESQL
+pkglib_LTLIBRARIES += postgresql.la
+postgresql_la_SOURCES = postgresql.c \
+                utils_db_query.c utils_db_query.h
+postgresql_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPQ_CPPFLAGS)
+postgresql_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
+               $(BUILD_WITH_LIBPQ_LDFLAGS)
+postgresql_la_LIBADD = -lpq
+endif
+
+if BUILD_PLUGIN_POWERDNS
+pkglib_LTLIBRARIES += powerdns.la
+powerdns_la_SOURCES = powerdns.c
+powerdns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_PYTHON
+pkglib_LTLIBRARIES += python.la
+python_la_SOURCES = python.c pyconfig.c pyvalues.c cpython.h
+python_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_PYTHON_CPPFLAGS)
+python_la_CFLAGS = $(AM_CFLAGS)
+if COMPILER_IS_GCC
+python_la_CFLAGS += -fno-strict-aliasing -Wno-strict-aliasing
+endif
+python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_PYTHON_LDFLAGS)
+python_la_LIBADD = $(BUILD_WITH_PYTHON_LIBS)
+endif
+
+if BUILD_PLUGIN_PROCESSES
+pkglib_LTLIBRARIES += processes.la
+processes_la_SOURCES = processes.c
+processes_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+processes_la_LIBADD =
+if BUILD_WITH_LIBKVM_GETPROCS
+processes_la_LIBADD += -lkvm
+endif
+endif
+
+if BUILD_PLUGIN_PROTOCOLS
+pkglib_LTLIBRARIES += protocols.la
+protocols_la_SOURCES = protocols.c \
+                      utils_ignorelist.c utils_ignorelist.h
+protocols_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_REDIS
+pkglib_LTLIBRARIES += redis.la
+redis_la_SOURCES = redis.c
+redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
+redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+redis_la_LIBADD = -lhiredis
+endif
+
+if BUILD_PLUGIN_ROUTEROS
+pkglib_LTLIBRARIES += routeros.la
+routeros_la_SOURCES = routeros.c
+routeros_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBROUTEROS_CPPFLAGS)
+routeros_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBROUTEROS_LDFLAGS)
+routeros_la_LIBADD = -lrouteros
+endif
+
+if BUILD_PLUGIN_RRDCACHED
+pkglib_LTLIBRARIES += rrdcached.la
+rrdcached_la_SOURCES = rrdcached.c utils_rrdcreate.c utils_rrdcreate.h
+rrdcached_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+rrdcached_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
+rrdcached_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_RRDTOOL
+pkglib_LTLIBRARIES += rrdtool.la
+rrdtool_la_SOURCES = rrdtool.c utils_rrdcreate.c utils_rrdcreate.h
+rrdtool_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
+rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_SENSORS
+pkglib_LTLIBRARIES += sensors.la
+sensors_la_SOURCES = sensors.c \
+                    utils_ignorelist.c utils_ignorelist.h
+sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
+sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSENSORS_LDFLAGS)
+sensors_la_LIBADD = -lsensors
+endif
+
+if BUILD_PLUGIN_SERIAL
+pkglib_LTLIBRARIES += serial.la
+serial_la_SOURCES = serial.c
+serial_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_SIGROK
+pkglib_LTLIBRARIES += sigrok.la
+sigrok_la_SOURCES = sigrok.c
+sigrok_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSIGROK_CFLAGS)
+sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSIGROK_LDFLAGS)
+sigrok_la_LIBADD = -lsigrok
+endif
+
+if BUILD_PLUGIN_SMART
+if BUILD_WITH_LIBUDEV
+pkglib_LTLIBRARIES += smart.la
+smart_la_SOURCES = smart.c \
+                  utils_ignorelist.c utils_ignorelist.h
+smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS)
+smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS)
+smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev
+endif
+endif
+
+if BUILD_PLUGIN_SNMP
+pkglib_LTLIBRARIES += snmp.la
+snmp_la_SOURCES = snmp.c
+snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+snmp_la_CFLAGS = $(AM_CFLAGS)
+snmp_la_LIBADD =
+if BUILD_WITH_LIBNETSNMP
+snmp_la_CFLAGS += $(BUILD_WITH_LIBSNMP_CFLAGS)
+snmp_la_LIBADD += $(BUILD_WITH_LIBSNMP_LIBS)
+endif
+if BUILD_WITH_LIBPTHREAD
+snmp_la_LIBADD += -lpthread
+endif
+endif
+
+if BUILD_PLUGIN_STATSD
+pkglib_LTLIBRARIES += statsd.la
+statsd_la_SOURCES = statsd.c \
+                    utils_latency.h utils_latency.c
+statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+statsd_la_LIBADD = -lpthread
+endif
+
+if BUILD_PLUGIN_SWAP
+pkglib_LTLIBRARIES += swap.la
+swap_la_SOURCES = swap.c
+swap_la_CFLAGS = $(AM_CFLAGS)
+swap_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+swap_la_LIBADD =
+if BUILD_WITH_LIBKSTAT
+swap_la_LIBADD += -lkstat
+endif
+if BUILD_WITH_LIBDEVINFO
+swap_la_LIBADD += -ldevinfo
+endif
+if BUILD_WITH_LIBKVM_GETSWAPINFO
+swap_la_LIBADD += -lkvm
+endif
+if BUILD_WITH_LIBSTATGRAB
+swap_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+swap_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+endif
+if BUILD_WITH_PERFSTAT
+swap_la_LIBADD += -lperfstat
+endif
+
+endif
+
+if BUILD_PLUGIN_SYSLOG
+pkglib_LTLIBRARIES += syslog.la
+syslog_la_SOURCES = syslog.c
+syslog_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TABLE
+pkglib_LTLIBRARIES += table.la
+table_la_SOURCES = table.c
+table_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TAIL
+pkglib_LTLIBRARIES += tail.la
+tail_la_SOURCES = tail.c
+tail_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TAIL_CSV
+pkglib_LTLIBRARIES += tail_csv.la
+tail_csv_la_SOURCES = tail_csv.c
+tail_csv_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TAPE
+pkglib_LTLIBRARIES += tape.la
+tape_la_SOURCES = tape.c
+tape_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+tape_la_LIBADD = -lkstat -ldevinfo
+endif
+
+if BUILD_PLUGIN_TARGET_NOTIFICATION
+pkglib_LTLIBRARIES += target_notification.la
+target_notification_la_SOURCES = target_notification.c
+target_notification_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TARGET_REPLACE
+pkglib_LTLIBRARIES += target_replace.la
+target_replace_la_SOURCES = target_replace.c
+target_replace_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TARGET_SCALE
+pkglib_LTLIBRARIES += target_scale.la
+target_scale_la_SOURCES = target_scale.c
+target_scale_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TARGET_SET
+pkglib_LTLIBRARIES += target_set.la
+target_set_la_SOURCES = target_set.c
+target_set_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TARGET_V5UPGRADE
+pkglib_LTLIBRARIES += target_v5upgrade.la
+target_v5upgrade_la_SOURCES = target_v5upgrade.c
+target_v5upgrade_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TCPCONNS
+pkglib_LTLIBRARIES += tcpconns.la
+tcpconns_la_SOURCES = tcpconns.c
+tcpconns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+tcpconns_la_LIBADD =
+if BUILD_WITH_LIBKVM_NLIST
+tcpconns_la_LIBADD += -lkvm
+endif
+endif
+
+if BUILD_PLUGIN_TEAMSPEAK2
+pkglib_LTLIBRARIES += teamspeak2.la
+teamspeak2_la_SOURCES = teamspeak2.c
+teamspeak2_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TED
+pkglib_LTLIBRARIES += ted.la
+ted_la_SOURCES = ted.c
+ted_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_THERMAL
+pkglib_LTLIBRARIES += thermal.la
+thermal_la_SOURCES = thermal.c \
+                    utils_ignorelist.c utils_ignorelist.h
+thermal_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_THRESHOLD
+pkglib_LTLIBRARIES += threshold.la
+threshold_la_SOURCES = threshold.c
+threshold_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_TOKYOTYRANT
+pkglib_LTLIBRARIES += tokyotyrant.la
+tokyotyrant_la_SOURCES = tokyotyrant.c
+tokyotyrant_la_CPPFLAGS  = $(AM_CPPFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
+tokyotyrant_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
+tokyotyrant_la_LIBADD  = $(BUILD_WITH_LIBTOKYOTYRANT_LIBS)
+if BUILD_WITH_LIBSOCKET
+tokyotyrant_la_LIBADD += -lsocket
+endif
+endif
+
+if BUILD_PLUGIN_TURBOSTAT
+pkglib_LTLIBRARIES += turbostat.la
+turbostat_la_SOURCES = turbostat.c
+turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_UNIXSOCK
+pkglib_LTLIBRARIES += unixsock.la
+unixsock_la_SOURCES = unixsock.c \
+                     utils_cmd_flush.h utils_cmd_flush.c \
+                     utils_cmd_getval.h utils_cmd_getval.c \
+                     utils_cmd_getthreshold.h utils_cmd_getthreshold.c \
+                     utils_cmd_listval.h utils_cmd_listval.c \
+                     utils_cmd_putval.h utils_cmd_putval.c \
+                     utils_cmd_putnotif.h utils_cmd_putnotif.c \
+                     utils_parse_option.h utils_parse_option.c
+unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+unixsock_la_LIBADD = -lpthread
+endif
+
+if BUILD_PLUGIN_UPTIME
+pkglib_LTLIBRARIES += uptime.la
+uptime_la_SOURCES = uptime.c
+uptime_la_CFLAGS = $(AM_CFLAGS)
+uptime_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+uptime_la_LIBADD =
+if BUILD_WITH_LIBKSTAT
+uptime_la_LIBADD += -lkstat
+endif
+if BUILD_WITH_PERFSTAT
+uptime_la_LIBADD += -lperfstat
+endif
+endif
+
+if BUILD_PLUGIN_USERS
+pkglib_LTLIBRARIES += users.la
+users_la_SOURCES = users.c
+users_la_CFLAGS = $(AM_CFLAGS)
+users_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+users_la_LIBADD =
+if BUILD_WITH_LIBSTATGRAB
+users_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+users_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+endif
+endif
+
+if BUILD_PLUGIN_UUID
+pkglib_LTLIBRARIES += uuid.la
+uuid_la_SOURCES = uuid.c
+uuid_la_CFLAGS  = $(AM_CFLAGS) $(BUILD_WITH_LIBHAL_CFLAGS)
+uuid_la_LIBADD  = $(BUILD_WITH_LIBHAL_LIBS)
+uuid_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_VARNISH
+pkglib_LTLIBRARIES += varnish.la
+varnish_la_SOURCES = varnish.c
+varnish_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+varnish_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBVARNISH_CFLAGS)
+varnish_la_LIBADD = $(BUILD_WITH_LIBVARNISH_LIBS)
+endif
+
+if BUILD_PLUGIN_VIRT
+pkglib_LTLIBRARIES += virt.la
+virt_la_SOURCES = virt.c \
+                 utils_ignorelist.c utils_ignorelist.h
+virt_la_CFLAGS = $(AM_CFLAGS) \
+               $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+virt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+virt_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_VMEM
+pkglib_LTLIBRARIES += vmem.la
+vmem_la_SOURCES = vmem.c
+vmem_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_VSERVER
+pkglib_LTLIBRARIES += vserver.la
+vserver_la_SOURCES = vserver.c
+vserver_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_WIRELESS
+pkglib_LTLIBRARIES += wireless.la
+wireless_la_SOURCES = wireless.c
+wireless_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_WRITE_GRAPHITE
+pkglib_LTLIBRARIES += write_graphite.la
+write_graphite_la_SOURCES = write_graphite.c \
+                        utils_format_graphite.c utils_format_graphite.h \
+                        utils_format_json.c utils_format_json.h
+write_graphite_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_WRITE_HTTP
+pkglib_LTLIBRARIES += write_http.la
+write_http_la_SOURCES = write_http.c \
+                       utils_format_json.c utils_format_json.h
+write_http_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+write_http_la_CFLAGS = $(AM_CFLAGS)
+write_http_la_LIBADD =
+if BUILD_WITH_LIBCURL
+write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+endif
+
+if BUILD_PLUGIN_WRITE_KAFKA
+pkglib_LTLIBRARIES += write_kafka.la
+write_kafka_la_SOURCES = write_kafka.c \
+                        utils_format_graphite.c utils_format_graphite.h \
+                        utils_format_json.c utils_format_json.h \
+                        utils_cmd_putval.c utils_cmd_putval.h \
+                        utils_crc32.c utils_crc32.h
+write_kafka_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRDKAFKA_CPPFLAGS)
+write_kafka_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
+write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS)
+endif
+
+if BUILD_PLUGIN_WRITE_LOG
+pkglib_LTLIBRARIES += write_log.la
+write_log_la_SOURCES = write_log.c \
+                        utils_format_graphite.c utils_format_graphite.h
+write_log_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_WRITE_MONGODB
+pkglib_LTLIBRARIES += write_mongodb.la
+write_mongodb_la_SOURCES = write_mongodb.c
+write_mongodb_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMONGOC_CPPFLAGS)
+write_mongodb_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMONGOC_LDFLAGS)
+write_mongodb_la_LIBADD = -lmongoc
+endif
+
+if BUILD_PLUGIN_WRITE_REDIS
+pkglib_LTLIBRARIES += write_redis.la
+write_redis_la_SOURCES = write_redis.c
+write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
+write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+write_redis_la_LIBADD = -lhiredis
+endif
+
+if BUILD_PLUGIN_WRITE_RIEMANN
+pkglib_LTLIBRARIES += write_riemann.la
+write_riemann_la_SOURCES = write_riemann.c write_riemann_threshold.c
+nodist_write_riemann_la_SOURCES = riemann.pb-c.c riemann.pb-c.h
+write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+write_riemann_la_LIBADD = -lprotobuf-c
+endif
+
+if BUILD_PLUGIN_WRITE_SENSU
+pkglib_LTLIBRARIES += write_sensu.la
+write_sensu_la_SOURCES = write_sensu.c
+write_sensu_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_WRITE_TSDB
+pkglib_LTLIBRARIES += write_tsdb.la
+write_tsdb_la_SOURCES = write_tsdb.c
+write_tsdb_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+if BUILD_PLUGIN_XMMS
+pkglib_LTLIBRARIES += xmms.la
+xmms_la_SOURCES = xmms.c
+xmms_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBXMMS_CFLAGS)
+xmms_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+xmms_la_LIBADD = $(BUILD_WITH_LIBXMMS_LIBS)
+endif
+
+if BUILD_PLUGIN_ZFS_ARC
+pkglib_LTLIBRARIES += zfs_arc.la
+zfs_arc_la_SOURCES = zfs_arc.c
+zfs_arc_la_CFLAGS = $(AM_CFLAGS)
+zfs_arc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+if BUILD_FREEBSD
+zfs_arc_la_LIBADD = -lm
+else
+if BUILD_LINUX
+# zfs_arc requires no library on linux
+else
+# solaris
+zfs_arc_la_LIBADD = -lkstat
+endif
+endif
+endif
+
+if BUILD_PLUGIN_ZOOKEEPER
+pkglib_LTLIBRARIES += zookeeper.la
+zookeeper_la_SOURCES = zookeeper.c
+zookeeper_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
+BUILT_SOURCES += $(dist_man_MANS)
+
+dist_man_MANS = collectd.1 \
+               collectd.conf.5 \
+               collectd-email.5 \
+               collectd-exec.5 \
+               collectdctl.1 \
+               collectd-java.5 \
+               collectdmon.1 \
+               collectd-nagios.1 \
+               collectd-perl.5 \
+               collectd-python.5 \
+               collectd-snmp.5 \
+               collectd-tg.1 \
+               collectd-threshold.5 \
+               collectd-unixsock.5 \
+               types.db.5
+
+#collectd_1_SOURCES = collectd.pod
+
+EXTRA_DIST = types.db
+
+EXTRA_DIST +=   collectd.conf.pod \
+               collectd-email.pod \
+               collectd-exec.pod \
+               collectdctl.pod \
+               collectd-java.pod \
+               collectdmon.pod \
+               collectd-nagios.pod \
+               collectd-perl.pod \
+               collectd-python.pod \
+               collectd.pod \
+               collectd-snmp.pod \
+               collectd-tg.pod \
+               collectd-threshold.pod \
+               collectd-unixsock.pod \
+               postgresql_default.conf \
+               types.db.pod
+
+.pod.1:
+       pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
+               >.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
+       @if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
+       then \
+               echo "$@ has some POD errors!"; false; \
+       fi
+
+.pod.5:
+       pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
+               >.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
+       @if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
+       then \
+               echo "$@ has some POD errors!"; false; \
+       fi
+
+# Protocol buffer for the "pinba" plugin.
+EXTRA_DIST += pinba.proto
+if HAVE_PROTOC_C
+CLEANFILES += pinba.pb-c.c pinba.pb-c.h
+BUILT_SOURCES += pinba.pb-c.c pinba.pb-c.h
+
+pinba.pb-c.c pinba.pb-c.h: pinba.proto
+       protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto
+endif
+
+# Protocol buffer for the "write_riemann" plugin.
+EXTRA_DIST += riemann.proto
+if HAVE_PROTOC_C
+CLEANFILES += riemann.pb-c.c riemann.pb-c.h
+
+BUILT_SOURCES += riemann.pb-c.c riemann.pb-c.h
+
+riemann.pb-c.c riemann.pb-c.h: riemann.proto
+       protoc-c -I$(srcdir) --c_out . $(srcdir)/riemann.proto
+endif
+
+install-exec-hook:
+       $(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+       if test -e $(DESTDIR)$(sysconfdir)/collectd.conf; \
+       then \
+               $(INSTALL) -m 0640 collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf.pkg-orig; \
+       else \
+               $(INSTALL) -m 0640 collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \
+       fi; \
+       $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+       $(INSTALL) -m 0644 $(srcdir)/types.db $(DESTDIR)$(pkgdatadir)/types.db;
+       $(INSTALL) -m 0644 $(srcdir)/postgresql_default.conf \
+               $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
+
+uninstall-hook:
+       rm -f $(DESTDIR)$(pkgdatadir)/types.db;
+       rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
+       rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
+
+check_PROGRAMS = test_utils_mount test_utils_vl_lookup
+
+test_utils_mount_SOURCES = utils_mount_test.c testing.h
+test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
+
+test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
+
+TESTS = test_utils_mount test_utils_vl_lookup
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644 (file)
index 0000000..d03c64e
--- /dev/null
@@ -0,0 +1,5212 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@BUILD_WITH_OWN_LIBOCONFIG_TRUE@am__append_1 = liboconfig
+@BUILD_FEATURE_DAEMON_TRUE@am__append_2 = -DPIDFILE='"${localstatedir}/run/${PACKAGE_NAME}.pid"'
+sbin_PROGRAMS = collectdmon$(EXEEXT)
+bin_PROGRAMS = collectd-nagios$(EXEEXT) collectdctl$(EXEEXT) \
+       collectd-tg$(EXEEXT)
+@BUILD_WITH_LIBSOCKET_TRUE@am__append_3 = -lsocket
+@BUILD_AIX_TRUE@am__append_4 = -lm
+@BUILD_WITH_LIBSOCKET_TRUE@am__append_5 = -lsocket
+@BUILD_AIX_TRUE@am__append_6 = -lm
+@BUILD_WITH_LIBSOCKET_TRUE@am__append_7 = -lsocket
+@BUILD_WITH_LIBRT_TRUE@am__append_8 = -lrt
+@BUILD_AIX_TRUE@am__append_9 = -lm
+@BUILD_WITH_LIBPTHREAD_TRUE@am__append_10 = -lpthread
+@BUILD_PLUGIN_AGGREGATION_TRUE@am__append_11 = aggregation.la
+@BUILD_PLUGIN_AMQP_TRUE@am__append_12 = amqp.la
+@BUILD_PLUGIN_APACHE_TRUE@am__append_13 = apache.la
+@BUILD_PLUGIN_APACHE_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_14 = $(BUILD_WITH_LIBCURL_CFLAGS)
+@BUILD_PLUGIN_APACHE_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_15 = $(BUILD_WITH_LIBCURL_LIBS)
+@BUILD_PLUGIN_APCUPS_TRUE@am__append_16 = apcups.la
+@BUILD_PLUGIN_APCUPS_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_17 = -lsocket
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@am__append_18 = apple_sensors.la
+@BUILD_PLUGIN_AQUAERO_TRUE@am__append_19 = aquaero.la
+@BUILD_PLUGIN_ASCENT_TRUE@am__append_20 = ascent.la
+@BUILD_PLUGIN_BAROMETER_TRUE@am__append_21 = barometer.la
+@BUILD_PLUGIN_BATTERY_TRUE@am__append_22 = battery.la
+@BUILD_PLUGIN_BATTERY_TRUE@@BUILD_WITH_LIBIOKIT_TRUE@am__append_23 = -framework IOKit
+@BUILD_PLUGIN_BIND_TRUE@am__append_24 = bind.la
+@BUILD_PLUGIN_CEPH_TRUE@am__append_25 = ceph.la
+@BUILD_PLUGIN_CGROUPS_TRUE@am__append_26 = cgroups.la
+@BUILD_PLUGIN_CONNTRACK_TRUE@am__append_27 = conntrack.la
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@am__append_28 = contextswitch.la
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_29 = -lperfstat
+@BUILD_PLUGIN_CPU_TRUE@am__append_30 = cpu.la
+@BUILD_PLUGIN_CPU_TRUE@@BUILD_WITH_LIBKSTAT_TRUE@am__append_31 = -lkstat
+@BUILD_PLUGIN_CPU_TRUE@@BUILD_WITH_LIBDEVINFO_TRUE@am__append_32 = -ldevinfo
+@BUILD_PLUGIN_CPU_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_33 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_PLUGIN_CPU_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_34 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_PLUGIN_CPU_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_35 = -lperfstat
+@BUILD_PLUGIN_CPUFREQ_TRUE@am__append_36 = cpufreq.la
+@BUILD_PLUGIN_CSV_TRUE@am__append_37 = csv.la
+@BUILD_PLUGIN_CURL_TRUE@am__append_38 = curl.la
+@BUILD_PLUGIN_CURL_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_39 = $(BUILD_WITH_LIBCURL_CFLAGS)
+@BUILD_PLUGIN_CURL_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_40 = $(BUILD_WITH_LIBCURL_LIBS)
+@BUILD_PLUGIN_CURL_JSON_TRUE@am__append_41 = curl_json.la
+@BUILD_PLUGIN_CURL_JSON_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_42 = $(BUILD_WITH_LIBCURL_CFLAGS)
+@BUILD_PLUGIN_CURL_JSON_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_43 = $(BUILD_WITH_LIBCURL_LIBS)
+@BUILD_PLUGIN_CURL_XML_TRUE@am__append_44 = curl_xml.la
+@BUILD_PLUGIN_DBI_TRUE@am__append_45 = dbi.la
+@BUILD_PLUGIN_DF_TRUE@am__append_46 = df.la
+@BUILD_PLUGIN_DISK_TRUE@am__append_47 = disk.la
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_LIBKSTAT_TRUE@am__append_48 = -lkstat
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_LIBDEVINFO_TRUE@am__append_49 = -ldevinfo
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_LIBIOKIT_TRUE@am__append_50 = -framework IOKit
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_51 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_52 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_LIBUDEV_TRUE@am__append_53 = -ludev
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_54 = -lperfstat
+@BUILD_PLUGIN_DNS_TRUE@am__append_55 = dns.la
+@BUILD_PLUGIN_DRBD_TRUE@am__append_56 = drbd.la
+@BUILD_PLUGIN_EMAIL_TRUE@am__append_57 = email.la
+@BUILD_PLUGIN_ENTROPY_TRUE@am__append_58 = entropy.la
+@BUILD_PLUGIN_EXEC_TRUE@am__append_59 = exec.la
+@BUILD_PLUGIN_ETHSTAT_TRUE@am__append_60 = ethstat.la
+@BUILD_PLUGIN_FHCOUNT_TRUE@am__append_61 = fhcount.la
+@BUILD_PLUGIN_FILECOUNT_TRUE@am__append_62 = filecount.la
+@BUILD_PLUGIN_GMOND_TRUE@am__append_63 = gmond.la
+@BUILD_PLUGIN_HDDTEMP_TRUE@am__append_64 = hddtemp.la
+@BUILD_PLUGIN_HDDTEMP_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_65 = -lsocket
+@BUILD_PLUGIN_INTERFACE_TRUE@am__append_66 = interface.la
+@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_67 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_68 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_WITH_LIBKSTAT_TRUE@@BUILD_WITH_LIBSTATGRAB_FALSE@am__append_69 = -lkstat
+@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_WITH_LIBDEVINFO_TRUE@@BUILD_WITH_LIBSTATGRAB_FALSE@am__append_70 = -ldevinfo
+@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_71 = -lperfstat
+@BUILD_PLUGIN_IPC_TRUE@am__append_72 = ipc.la
+@BUILD_PLUGIN_IPTABLES_TRUE@am__append_73 = iptables.la
+@BUILD_PLUGIN_IPMI_TRUE@am__append_74 = ipmi.la
+@BUILD_PLUGIN_IPVS_TRUE@am__append_75 = ipvs.la
+@BUILD_PLUGIN_IRQ_TRUE@am__append_76 = irq.la
+@BUILD_PLUGIN_JAVA_TRUE@am__append_77 = java.la
+@BUILD_PLUGIN_LOAD_TRUE@am__append_78 = load.la
+@BUILD_PLUGIN_LOAD_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_79 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_PLUGIN_LOAD_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_80 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_PLUGIN_LOAD_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_81 = -lperfstat
+@BUILD_PLUGIN_LOGFILE_TRUE@am__append_82 = logfile.la
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@am__append_83 = log_logstash.la
+@BUILD_PLUGIN_LPAR_TRUE@am__append_84 = lpar.la
+@BUILD_PLUGIN_LVM_TRUE@am__append_85 = lvm.la
+@BUILD_PLUGIN_MADWIFI_TRUE@am__append_86 = madwifi.la
+@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@am__append_87 = match_empty_counter.la
+@BUILD_PLUGIN_MATCH_HASHED_TRUE@am__append_88 = match_hashed.la
+@BUILD_PLUGIN_MATCH_REGEX_TRUE@am__append_89 = match_regex.la
+@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@am__append_90 = match_timediff.la
+@BUILD_PLUGIN_MATCH_VALUE_TRUE@am__append_91 = match_value.la
+@BUILD_PLUGIN_MBMON_TRUE@am__append_92 = mbmon.la
+@BUILD_PLUGIN_MBMON_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_93 = -lsocket
+@BUILD_PLUGIN_MD_TRUE@am__append_94 = md.la
+@BUILD_PLUGIN_MEMCACHEC_TRUE@am__append_95 = memcachec.la
+@BUILD_PLUGIN_MEMCACHED_TRUE@am__append_96 = memcached.la
+@BUILD_PLUGIN_MEMCACHED_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_97 = -lsocket
+@BUILD_PLUGIN_MEMORY_TRUE@am__append_98 = memory.la
+@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_WITH_LIBKSTAT_TRUE@am__append_99 = -lkstat
+@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_WITH_LIBDEVINFO_TRUE@am__append_100 = -ldevinfo
+@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_101 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_102 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_103 = -lperfstat
+@BUILD_PLUGIN_MIC_TRUE@am__append_104 = mic.la
+@BUILD_PLUGIN_MODBUS_TRUE@am__append_105 = modbus.la
+@BUILD_PLUGIN_MULTIMETER_TRUE@am__append_106 = multimeter.la
+@BUILD_PLUGIN_MYSQL_TRUE@am__append_107 = mysql.la
+@BUILD_PLUGIN_MYSQL_TRUE@@BUILD_WITH_LIBMYSQL_TRUE@am__append_108 = $(BUILD_WITH_LIBMYSQL_CFLAGS)
+@BUILD_PLUGIN_MYSQL_TRUE@@BUILD_WITH_LIBMYSQL_TRUE@am__append_109 = $(BUILD_WITH_LIBMYSQL_LIBS)
+@BUILD_PLUGIN_NETAPP_TRUE@am__append_110 = netapp.la
+@BUILD_PLUGIN_NETLINK_TRUE@am__append_111 = netlink.la
+@BUILD_PLUGIN_NETWORK_TRUE@am__append_112 = network.la
+@BUILD_PLUGIN_NETWORK_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_113 = -lsocket
+@BUILD_PLUGIN_NETWORK_TRUE@@BUILD_WITH_LIBGCRYPT_TRUE@am__append_114 = $(GCRYPT_CPPFLAGS)
+@BUILD_PLUGIN_NETWORK_TRUE@@BUILD_WITH_LIBGCRYPT_TRUE@am__append_115 = $(GCRYPT_LDFLAGS)
+@BUILD_PLUGIN_NETWORK_TRUE@@BUILD_WITH_LIBGCRYPT_TRUE@am__append_116 = $(GCRYPT_LIBS)
+@BUILD_PLUGIN_NFS_TRUE@am__append_117 = nfs.la
+@BUILD_PLUGIN_FSCACHE_TRUE@am__append_118 = fscache.la
+@BUILD_PLUGIN_NGINX_TRUE@am__append_119 = nginx.la
+@BUILD_PLUGIN_NGINX_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_120 = $(BUILD_WITH_LIBCURL_CFLAGS)
+@BUILD_PLUGIN_NGINX_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_121 = $(BUILD_WITH_LIBCURL_LIBS)
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@am__append_122 = notify_desktop.la
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@am__append_123 = notify_email.la
+@BUILD_PLUGIN_NTPD_TRUE@am__append_124 = ntpd.la
+@BUILD_PLUGIN_NTPD_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_125 = -lsocket
+@BUILD_PLUGIN_NUMA_TRUE@am__append_126 = numa.la
+@BUILD_PLUGIN_NUT_TRUE@am__append_127 = nut.la
+@BUILD_PLUGIN_OLSRD_TRUE@am__append_128 = olsrd.la
+@BUILD_PLUGIN_OLSRD_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_129 = -lsocket
+@BUILD_PLUGIN_ONEWIRE_TRUE@am__append_130 = onewire.la
+@BUILD_PLUGIN_OPENLDAP_TRUE@am__append_131 = openldap.la
+@BUILD_PLUGIN_OPENVPN_TRUE@am__append_132 = openvpn.la
+@BUILD_PLUGIN_ORACLE_TRUE@am__append_133 = oracle.la
+@BUILD_PLUGIN_PERL_TRUE@am__append_134 = perl.la
+# Work-around for issues #41 and #42 - Perl 5.10 incorrectly introduced
+# __attribute__nonnull__(3) for Perl_load_module().
+@BUILD_PLUGIN_PERL_TRUE@@HAVE_BROKEN_PERL_LOAD_MODULE_TRUE@am__append_135 = -Wno-nonnull
+@BUILD_PLUGIN_PF_TRUE@am__append_136 = pf.la
+@BUILD_PLUGIN_PINBA_TRUE@am__append_137 = pinba.la
+@BUILD_PLUGIN_PING_TRUE@am__append_138 = ping.la
+@BUILD_PLUGIN_POSTGRESQL_TRUE@am__append_139 = postgresql.la
+@BUILD_PLUGIN_POWERDNS_TRUE@am__append_140 = powerdns.la
+@BUILD_PLUGIN_PYTHON_TRUE@am__append_141 = python.la
+@BUILD_PLUGIN_PYTHON_TRUE@@COMPILER_IS_GCC_TRUE@am__append_142 = -fno-strict-aliasing -Wno-strict-aliasing
+@BUILD_PLUGIN_PROCESSES_TRUE@am__append_143 = processes.la
+@BUILD_PLUGIN_PROCESSES_TRUE@@BUILD_WITH_LIBKVM_GETPROCS_TRUE@am__append_144 = -lkvm
+@BUILD_PLUGIN_PROTOCOLS_TRUE@am__append_145 = protocols.la
+@BUILD_PLUGIN_REDIS_TRUE@am__append_146 = redis.la
+@BUILD_PLUGIN_ROUTEROS_TRUE@am__append_147 = routeros.la
+@BUILD_PLUGIN_RRDCACHED_TRUE@am__append_148 = rrdcached.la
+@BUILD_PLUGIN_RRDTOOL_TRUE@am__append_149 = rrdtool.la
+@BUILD_PLUGIN_SENSORS_TRUE@am__append_150 = sensors.la
+@BUILD_PLUGIN_SERIAL_TRUE@am__append_151 = serial.la
+@BUILD_PLUGIN_SIGROK_TRUE@am__append_152 = sigrok.la
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@am__append_153 = smart.la
+@BUILD_PLUGIN_SNMP_TRUE@am__append_154 = snmp.la
+@BUILD_PLUGIN_SNMP_TRUE@@BUILD_WITH_LIBNETSNMP_TRUE@am__append_155 = $(BUILD_WITH_LIBSNMP_CFLAGS)
+@BUILD_PLUGIN_SNMP_TRUE@@BUILD_WITH_LIBNETSNMP_TRUE@am__append_156 = $(BUILD_WITH_LIBSNMP_LIBS)
+@BUILD_PLUGIN_SNMP_TRUE@@BUILD_WITH_LIBPTHREAD_TRUE@am__append_157 = -lpthread
+@BUILD_PLUGIN_STATSD_TRUE@am__append_158 = statsd.la
+@BUILD_PLUGIN_SWAP_TRUE@am__append_159 = swap.la
+@BUILD_PLUGIN_SWAP_TRUE@@BUILD_WITH_LIBKSTAT_TRUE@am__append_160 = -lkstat
+@BUILD_PLUGIN_SWAP_TRUE@@BUILD_WITH_LIBDEVINFO_TRUE@am__append_161 = -ldevinfo
+@BUILD_PLUGIN_SWAP_TRUE@@BUILD_WITH_LIBKVM_GETSWAPINFO_TRUE@am__append_162 = -lkvm
+@BUILD_PLUGIN_SWAP_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_163 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_PLUGIN_SWAP_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_164 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_PLUGIN_SWAP_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_165 = -lperfstat
+@BUILD_PLUGIN_SYSLOG_TRUE@am__append_166 = syslog.la
+@BUILD_PLUGIN_TABLE_TRUE@am__append_167 = table.la
+@BUILD_PLUGIN_TAIL_TRUE@am__append_168 = tail.la
+@BUILD_PLUGIN_TAIL_CSV_TRUE@am__append_169 = tail_csv.la
+@BUILD_PLUGIN_TAPE_TRUE@am__append_170 = tape.la
+@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@am__append_171 = target_notification.la
+@BUILD_PLUGIN_TARGET_REPLACE_TRUE@am__append_172 = target_replace.la
+@BUILD_PLUGIN_TARGET_SCALE_TRUE@am__append_173 = target_scale.la
+@BUILD_PLUGIN_TARGET_SET_TRUE@am__append_174 = target_set.la
+@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@am__append_175 = target_v5upgrade.la
+@BUILD_PLUGIN_TCPCONNS_TRUE@am__append_176 = tcpconns.la
+@BUILD_PLUGIN_TCPCONNS_TRUE@@BUILD_WITH_LIBKVM_NLIST_TRUE@am__append_177 = -lkvm
+@BUILD_PLUGIN_TEAMSPEAK2_TRUE@am__append_178 = teamspeak2.la
+@BUILD_PLUGIN_TED_TRUE@am__append_179 = ted.la
+@BUILD_PLUGIN_THERMAL_TRUE@am__append_180 = thermal.la
+@BUILD_PLUGIN_THRESHOLD_TRUE@am__append_181 = threshold.la
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@am__append_182 = tokyotyrant.la
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@@BUILD_WITH_LIBSOCKET_TRUE@am__append_183 = -lsocket
+@BUILD_PLUGIN_TURBOSTAT_TRUE@am__append_184 = turbostat.la
+@BUILD_PLUGIN_UNIXSOCK_TRUE@am__append_185 = unixsock.la
+@BUILD_PLUGIN_UPTIME_TRUE@am__append_186 = uptime.la
+@BUILD_PLUGIN_UPTIME_TRUE@@BUILD_WITH_LIBKSTAT_TRUE@am__append_187 = -lkstat
+@BUILD_PLUGIN_UPTIME_TRUE@@BUILD_WITH_PERFSTAT_TRUE@am__append_188 = -lperfstat
+@BUILD_PLUGIN_USERS_TRUE@am__append_189 = users.la
+@BUILD_PLUGIN_USERS_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_190 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_PLUGIN_USERS_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_191 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_PLUGIN_UUID_TRUE@am__append_192 = uuid.la
+@BUILD_PLUGIN_VARNISH_TRUE@am__append_193 = varnish.la
+@BUILD_PLUGIN_VIRT_TRUE@am__append_194 = virt.la
+@BUILD_PLUGIN_VMEM_TRUE@am__append_195 = vmem.la
+@BUILD_PLUGIN_VSERVER_TRUE@am__append_196 = vserver.la
+@BUILD_PLUGIN_WIRELESS_TRUE@am__append_197 = wireless.la
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@am__append_198 = write_graphite.la
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@am__append_199 = write_http.la
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_200 = $(BUILD_WITH_LIBCURL_CFLAGS)
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__append_201 = $(BUILD_WITH_LIBCURL_LIBS)
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@am__append_202 = write_kafka.la
+@BUILD_PLUGIN_WRITE_LOG_TRUE@am__append_203 = write_log.la
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@am__append_204 = write_mongodb.la
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@am__append_205 = write_redis.la
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@am__append_206 = write_riemann.la
+@BUILD_PLUGIN_WRITE_SENSU_TRUE@am__append_207 = write_sensu.la
+@BUILD_PLUGIN_WRITE_TSDB_TRUE@am__append_208 = write_tsdb.la
+@BUILD_PLUGIN_XMMS_TRUE@am__append_209 = xmms.la
+@BUILD_PLUGIN_ZFS_ARC_TRUE@am__append_210 = zfs_arc.la
+@BUILD_PLUGIN_ZOOKEEPER_TRUE@am__append_211 = zookeeper.la
+@HAVE_PROTOC_C_TRUE@am__append_212 = pinba.pb-c.c pinba.pb-c.h \
+@HAVE_PROTOC_C_TRUE@   riemann.pb-c.c riemann.pb-c.h
+@HAVE_PROTOC_C_TRUE@am__append_213 = pinba.pb-c.c pinba.pb-c.h \
+@HAVE_PROTOC_C_TRUE@   riemann.pb-c.c riemann.pb-c.h
+check_PROGRAMS = test_utils_mount$(EXEEXT) \
+       test_utils_vl_lookup$(EXEEXT)
+TESTS = test_utils_mount$(EXEEXT) test_utils_vl_lookup$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+       $(srcdir)/config.h.in $(srcdir)/collectd.conf.in \
+       $(top_srcdir)/libltdl/config/depcomp $(dist_man_MANS) \
+       $(top_srcdir)/libltdl/config/test-driver
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = collectd.conf
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(bindir)" \
+       "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)" \
+       "$(DESTDIR)$(man5dir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES)
+aggregation_la_DEPENDENCIES =
+am__aggregation_la_SOURCES_DIST = aggregation.c utils_vl_lookup.c \
+       utils_vl_lookup.h
+@BUILD_PLUGIN_AGGREGATION_TRUE@am_aggregation_la_OBJECTS =  \
+@BUILD_PLUGIN_AGGREGATION_TRUE@        aggregation.lo \
+@BUILD_PLUGIN_AGGREGATION_TRUE@        utils_vl_lookup.lo
+aggregation_la_OBJECTS = $(am_aggregation_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+aggregation_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(aggregation_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+@BUILD_PLUGIN_AGGREGATION_TRUE@am_aggregation_la_rpath = -rpath \
+@BUILD_PLUGIN_AGGREGATION_TRUE@        $(pkglibdir)
+am__DEPENDENCIES_1 =
+@BUILD_PLUGIN_AMQP_TRUE@amqp_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__amqp_la_SOURCES_DIST = amqp.c utils_cmd_putval.c \
+       utils_cmd_putval.h utils_format_graphite.c \
+       utils_format_graphite.h utils_format_json.c \
+       utils_format_json.h
+@BUILD_PLUGIN_AMQP_TRUE@am_amqp_la_OBJECTS = amqp_la-amqp.lo \
+@BUILD_PLUGIN_AMQP_TRUE@       amqp_la-utils_cmd_putval.lo \
+@BUILD_PLUGIN_AMQP_TRUE@       amqp_la-utils_format_graphite.lo \
+@BUILD_PLUGIN_AMQP_TRUE@       amqp_la-utils_format_json.lo
+amqp_la_OBJECTS = $(am_amqp_la_OBJECTS)
+amqp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(amqp_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_AMQP_TRUE@am_amqp_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_APACHE_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_APACHE_TRUE@apache_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_APACHE_TRUE@     $(am__DEPENDENCIES_2)
+am__apache_la_SOURCES_DIST = apache.c
+@BUILD_PLUGIN_APACHE_TRUE@am_apache_la_OBJECTS = apache_la-apache.lo
+apache_la_OBJECTS = $(am_apache_la_OBJECTS)
+apache_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(apache_la_CFLAGS) \
+       $(CFLAGS) $(apache_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_APACHE_TRUE@am_apache_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_APCUPS_TRUE@apcups_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_APCUPS_TRUE@     $(am__DEPENDENCIES_1)
+am__apcups_la_SOURCES_DIST = apcups.c
+@BUILD_PLUGIN_APCUPS_TRUE@am_apcups_la_OBJECTS = apcups.lo
+apcups_la_OBJECTS = $(am_apcups_la_OBJECTS)
+apcups_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(apcups_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_APCUPS_TRUE@am_apcups_la_rpath = -rpath $(pkglibdir)
+apple_sensors_la_LIBADD =
+am__apple_sensors_la_SOURCES_DIST = apple_sensors.c
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@am_apple_sensors_la_OBJECTS =  \
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@      apple_sensors.lo
+apple_sensors_la_OBJECTS = $(am_apple_sensors_la_OBJECTS)
+apple_sensors_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(apple_sensors_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@am_apple_sensors_la_rpath = -rpath \
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@      $(pkglibdir)
+@BUILD_PLUGIN_AQUAERO_TRUE@aquaero_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_AQUAERO_TRUE@    $(am__DEPENDENCIES_1)
+am__aquaero_la_SOURCES_DIST = aquaero.c
+@BUILD_PLUGIN_AQUAERO_TRUE@am_aquaero_la_OBJECTS =  \
+@BUILD_PLUGIN_AQUAERO_TRUE@    aquaero_la-aquaero.lo
+aquaero_la_OBJECTS = $(am_aquaero_la_OBJECTS)
+aquaero_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(aquaero_la_CFLAGS) \
+       $(CFLAGS) $(aquaero_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_AQUAERO_TRUE@am_aquaero_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_ASCENT_TRUE@ascent_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_ASCENT_TRUE@     $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_ASCENT_TRUE@     $(am__DEPENDENCIES_1)
+am__ascent_la_SOURCES_DIST = ascent.c
+@BUILD_PLUGIN_ASCENT_TRUE@am_ascent_la_OBJECTS = ascent_la-ascent.lo
+ascent_la_OBJECTS = $(am_ascent_la_OBJECTS)
+ascent_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ascent_la_CFLAGS) \
+       $(CFLAGS) $(ascent_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ASCENT_TRUE@am_ascent_la_rpath = -rpath $(pkglibdir)
+barometer_la_DEPENDENCIES =
+am__barometer_la_SOURCES_DIST = barometer.c
+@BUILD_PLUGIN_BAROMETER_TRUE@am_barometer_la_OBJECTS = barometer.lo
+barometer_la_OBJECTS = $(am_barometer_la_OBJECTS)
+barometer_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(barometer_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_BAROMETER_TRUE@am_barometer_la_rpath = -rpath \
+@BUILD_PLUGIN_BAROMETER_TRUE@  $(pkglibdir)
+battery_la_DEPENDENCIES =
+am__battery_la_SOURCES_DIST = battery.c
+@BUILD_PLUGIN_BATTERY_TRUE@am_battery_la_OBJECTS = battery.lo
+battery_la_OBJECTS = $(am_battery_la_OBJECTS)
+battery_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(battery_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_BATTERY_TRUE@am_battery_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_BIND_TRUE@bind_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_BIND_TRUE@       $(am__DEPENDENCIES_1)
+am__bind_la_SOURCES_DIST = bind.c
+@BUILD_PLUGIN_BIND_TRUE@am_bind_la_OBJECTS = bind_la-bind.lo
+bind_la_OBJECTS = $(am_bind_la_OBJECTS)
+bind_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(bind_la_CFLAGS) \
+       $(CFLAGS) $(bind_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_BIND_TRUE@am_bind_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_CEPH_TRUE@ceph_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__ceph_la_SOURCES_DIST = ceph.c
+@BUILD_PLUGIN_CEPH_TRUE@am_ceph_la_OBJECTS = ceph_la-ceph.lo
+ceph_la_OBJECTS = $(am_ceph_la_OBJECTS)
+ceph_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ceph_la_CFLAGS) \
+       $(CFLAGS) $(ceph_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CEPH_TRUE@am_ceph_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_CGROUPS_TRUE@cgroups_la_DEPENDENCIES = libmount.la
+am__cgroups_la_SOURCES_DIST = cgroups.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_CGROUPS_TRUE@am_cgroups_la_OBJECTS = cgroups.lo \
+@BUILD_PLUGIN_CGROUPS_TRUE@    utils_ignorelist.lo
+cgroups_la_OBJECTS = $(am_cgroups_la_OBJECTS)
+cgroups_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(cgroups_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CGROUPS_TRUE@am_cgroups_la_rpath = -rpath $(pkglibdir)
+conntrack_la_LIBADD =
+am__conntrack_la_SOURCES_DIST = conntrack.c
+@BUILD_PLUGIN_CONNTRACK_TRUE@am_conntrack_la_OBJECTS = conntrack.lo
+conntrack_la_OBJECTS = $(am_conntrack_la_OBJECTS)
+conntrack_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(conntrack_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CONNTRACK_TRUE@am_conntrack_la_rpath = -rpath \
+@BUILD_PLUGIN_CONNTRACK_TRUE@  $(pkglibdir)
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@contextswitch_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@      $(am__DEPENDENCIES_1)
+am__contextswitch_la_SOURCES_DIST = contextswitch.c
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@am_contextswitch_la_OBJECTS =  \
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@      contextswitch.lo
+contextswitch_la_OBJECTS = $(am_contextswitch_la_OBJECTS)
+contextswitch_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(contextswitch_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@am_contextswitch_la_rpath = -rpath \
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@      $(pkglibdir)
+@BUILD_PLUGIN_CPU_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_CPU_TRUE@cpu_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_CPU_TRUE@        $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_CPU_TRUE@        $(am__DEPENDENCIES_3) \
+@BUILD_PLUGIN_CPU_TRUE@        $(am__DEPENDENCIES_1)
+am__cpu_la_SOURCES_DIST = cpu.c
+@BUILD_PLUGIN_CPU_TRUE@am_cpu_la_OBJECTS = cpu_la-cpu.lo
+cpu_la_OBJECTS = $(am_cpu_la_OBJECTS)
+cpu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(cpu_la_CFLAGS) $(CFLAGS) \
+       $(cpu_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CPU_TRUE@am_cpu_la_rpath = -rpath $(pkglibdir)
+cpufreq_la_LIBADD =
+am__cpufreq_la_SOURCES_DIST = cpufreq.c
+@BUILD_PLUGIN_CPUFREQ_TRUE@am_cpufreq_la_OBJECTS = cpufreq.lo
+cpufreq_la_OBJECTS = $(am_cpufreq_la_OBJECTS)
+cpufreq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(cpufreq_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CPUFREQ_TRUE@am_cpufreq_la_rpath = -rpath $(pkglibdir)
+csv_la_LIBADD =
+am__csv_la_SOURCES_DIST = csv.c
+@BUILD_PLUGIN_CSV_TRUE@am_csv_la_OBJECTS = csv.lo
+csv_la_OBJECTS = $(am_csv_la_OBJECTS)
+csv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(csv_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CSV_TRUE@am_csv_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_CURL_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_CURL_TRUE@curl_la_DEPENDENCIES = $(am__DEPENDENCIES_4)
+am__curl_la_SOURCES_DIST = curl.c
+@BUILD_PLUGIN_CURL_TRUE@am_curl_la_OBJECTS = curl_la-curl.lo
+curl_la_OBJECTS = $(am_curl_la_OBJECTS)
+curl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(curl_la_CFLAGS) \
+       $(CFLAGS) $(curl_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CURL_TRUE@am_curl_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_CURL_JSON_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_CURL_JSON_TRUE@curl_json_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_CURL_JSON_TRUE@  $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_CURL_JSON_TRUE@  $(am__DEPENDENCIES_5)
+am__curl_json_la_SOURCES_DIST = curl_json.c
+@BUILD_PLUGIN_CURL_JSON_TRUE@am_curl_json_la_OBJECTS =  \
+@BUILD_PLUGIN_CURL_JSON_TRUE@  curl_json_la-curl_json.lo
+curl_json_la_OBJECTS = $(am_curl_json_la_OBJECTS)
+curl_json_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(curl_json_la_CFLAGS) \
+       $(CFLAGS) $(curl_json_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CURL_JSON_TRUE@am_curl_json_la_rpath = -rpath \
+@BUILD_PLUGIN_CURL_JSON_TRUE@  $(pkglibdir)
+@BUILD_PLUGIN_CURL_XML_TRUE@curl_xml_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_CURL_XML_TRUE@   $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_CURL_XML_TRUE@   $(am__DEPENDENCIES_1)
+am__curl_xml_la_SOURCES_DIST = curl_xml.c
+@BUILD_PLUGIN_CURL_XML_TRUE@am_curl_xml_la_OBJECTS =  \
+@BUILD_PLUGIN_CURL_XML_TRUE@   curl_xml_la-curl_xml.lo
+curl_xml_la_OBJECTS = $(am_curl_xml_la_OBJECTS)
+curl_xml_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(curl_xml_la_CFLAGS) \
+       $(CFLAGS) $(curl_xml_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_CURL_XML_TRUE@am_curl_xml_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_DBI_TRUE@dbi_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__dbi_la_SOURCES_DIST = dbi.c utils_db_query.c utils_db_query.h
+@BUILD_PLUGIN_DBI_TRUE@am_dbi_la_OBJECTS = dbi_la-dbi.lo \
+@BUILD_PLUGIN_DBI_TRUE@        dbi_la-utils_db_query.lo
+dbi_la_OBJECTS = $(am_dbi_la_OBJECTS)
+dbi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(dbi_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_DBI_TRUE@am_dbi_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_DF_TRUE@df_la_DEPENDENCIES = libmount.la
+am__df_la_SOURCES_DIST = df.c utils_ignorelist.c utils_ignorelist.h
+@BUILD_PLUGIN_DF_TRUE@am_df_la_OBJECTS = df.lo utils_ignorelist.lo
+df_la_OBJECTS = $(am_df_la_OBJECTS)
+df_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(df_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_DF_TRUE@am_df_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_DISK_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_6 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_DISK_TRUE@disk_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_DISK_TRUE@       $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_DISK_TRUE@       $(am__DEPENDENCIES_6) \
+@BUILD_PLUGIN_DISK_TRUE@       $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_DISK_TRUE@       $(am__DEPENDENCIES_1)
+am__disk_la_SOURCES_DIST = disk.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_DISK_TRUE@am_disk_la_OBJECTS = disk_la-disk.lo \
+@BUILD_PLUGIN_DISK_TRUE@       disk_la-utils_ignorelist.lo
+disk_la_OBJECTS = $(am_disk_la_OBJECTS)
+disk_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(disk_la_CFLAGS) \
+       $(CFLAGS) $(disk_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_DISK_TRUE@am_disk_la_rpath = -rpath $(pkglibdir)
+dns_la_DEPENDENCIES =
+am__dns_la_SOURCES_DIST = dns.c utils_dns.c utils_dns.h
+@BUILD_PLUGIN_DNS_TRUE@am_dns_la_OBJECTS = dns.lo utils_dns.lo
+dns_la_OBJECTS = $(am_dns_la_OBJECTS)
+dns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(dns_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_DNS_TRUE@am_dns_la_rpath = -rpath $(pkglibdir)
+drbd_la_DEPENDENCIES =
+am__drbd_la_SOURCES_DIST = drbd.c
+@BUILD_PLUGIN_DRBD_TRUE@am_drbd_la_OBJECTS = drbd.lo
+drbd_la_OBJECTS = $(am_drbd_la_OBJECTS)
+drbd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(drbd_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_DRBD_TRUE@am_drbd_la_rpath = -rpath $(pkglibdir)
+email_la_DEPENDENCIES =
+am__email_la_SOURCES_DIST = email.c
+@BUILD_PLUGIN_EMAIL_TRUE@am_email_la_OBJECTS = email.lo
+email_la_OBJECTS = $(am_email_la_OBJECTS)
+email_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(email_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_EMAIL_TRUE@am_email_la_rpath = -rpath $(pkglibdir)
+entropy_la_LIBADD =
+am__entropy_la_SOURCES_DIST = entropy.c
+@BUILD_PLUGIN_ENTROPY_TRUE@am_entropy_la_OBJECTS = entropy.lo
+entropy_la_OBJECTS = $(am_entropy_la_OBJECTS)
+entropy_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(entropy_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ENTROPY_TRUE@am_entropy_la_rpath = -rpath $(pkglibdir)
+ethstat_la_LIBADD =
+am__ethstat_la_SOURCES_DIST = ethstat.c
+@BUILD_PLUGIN_ETHSTAT_TRUE@am_ethstat_la_OBJECTS = ethstat.lo
+ethstat_la_OBJECTS = $(am_ethstat_la_OBJECTS)
+ethstat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(ethstat_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ETHSTAT_TRUE@am_ethstat_la_rpath = -rpath $(pkglibdir)
+exec_la_DEPENDENCIES =
+am__exec_la_SOURCES_DIST = exec.c utils_cmd_putnotif.c \
+       utils_cmd_putnotif.h utils_cmd_putval.c utils_cmd_putval.h \
+       utils_parse_option.h utils_parse_option.c
+@BUILD_PLUGIN_EXEC_TRUE@am_exec_la_OBJECTS = exec.lo \
+@BUILD_PLUGIN_EXEC_TRUE@       utils_cmd_putnotif.lo \
+@BUILD_PLUGIN_EXEC_TRUE@       utils_cmd_putval.lo \
+@BUILD_PLUGIN_EXEC_TRUE@       utils_parse_option.lo
+exec_la_OBJECTS = $(am_exec_la_OBJECTS)
+exec_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(exec_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_EXEC_TRUE@am_exec_la_rpath = -rpath $(pkglibdir)
+fhcount_la_LIBADD =
+am__fhcount_la_SOURCES_DIST = fhcount.c
+@BUILD_PLUGIN_FHCOUNT_TRUE@am_fhcount_la_OBJECTS = fhcount.lo
+fhcount_la_OBJECTS = $(am_fhcount_la_OBJECTS)
+fhcount_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(fhcount_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_FHCOUNT_TRUE@am_fhcount_la_rpath = -rpath $(pkglibdir)
+filecount_la_LIBADD =
+am__filecount_la_SOURCES_DIST = filecount.c
+@BUILD_PLUGIN_FILECOUNT_TRUE@am_filecount_la_OBJECTS = filecount.lo
+filecount_la_OBJECTS = $(am_filecount_la_OBJECTS)
+filecount_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(filecount_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_FILECOUNT_TRUE@am_filecount_la_rpath = -rpath \
+@BUILD_PLUGIN_FILECOUNT_TRUE@  $(pkglibdir)
+fscache_la_LIBADD =
+am__fscache_la_SOURCES_DIST = fscache.c
+@BUILD_PLUGIN_FSCACHE_TRUE@am_fscache_la_OBJECTS = fscache.lo
+fscache_la_OBJECTS = $(am_fscache_la_OBJECTS)
+fscache_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(fscache_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_FSCACHE_TRUE@am_fscache_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_GMOND_TRUE@gmond_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_GMOND_TRUE@      $(am__DEPENDENCIES_1)
+am__gmond_la_SOURCES_DIST = gmond.c
+@BUILD_PLUGIN_GMOND_TRUE@am_gmond_la_OBJECTS = gmond_la-gmond.lo
+gmond_la_OBJECTS = $(am_gmond_la_OBJECTS)
+gmond_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(gmond_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_GMOND_TRUE@am_gmond_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_HDDTEMP_TRUE@hddtemp_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_HDDTEMP_TRUE@    $(am__DEPENDENCIES_1)
+am__hddtemp_la_SOURCES_DIST = hddtemp.c
+@BUILD_PLUGIN_HDDTEMP_TRUE@am_hddtemp_la_OBJECTS = hddtemp.lo
+hddtemp_la_OBJECTS = $(am_hddtemp_la_OBJECTS)
+hddtemp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(hddtemp_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_HDDTEMP_TRUE@am_hddtemp_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_7 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_INTERFACE_TRUE@interface_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(am__DEPENDENCIES_7) \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(am__DEPENDENCIES_1)
+am__interface_la_SOURCES_DIST = interface.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_INTERFACE_TRUE@am_interface_la_OBJECTS =  \
+@BUILD_PLUGIN_INTERFACE_TRUE@  interface_la-interface.lo \
+@BUILD_PLUGIN_INTERFACE_TRUE@  interface_la-utils_ignorelist.lo
+interface_la_OBJECTS = $(am_interface_la_OBJECTS)
+interface_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(interface_la_CFLAGS) \
+       $(CFLAGS) $(interface_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_INTERFACE_TRUE@am_interface_la_rpath = -rpath \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(pkglibdir)
+ipc_la_LIBADD =
+am__ipc_la_SOURCES_DIST = ipc.c
+@BUILD_PLUGIN_IPC_TRUE@am_ipc_la_OBJECTS = ipc_la-ipc.lo
+ipc_la_OBJECTS = $(am_ipc_la_OBJECTS)
+ipc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ipc_la_CFLAGS) $(CFLAGS) \
+       $(ipc_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_IPC_TRUE@am_ipc_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_IPMI_TRUE@ipmi_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__ipmi_la_SOURCES_DIST = ipmi.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_IPMI_TRUE@am_ipmi_la_OBJECTS = ipmi_la-ipmi.lo \
+@BUILD_PLUGIN_IPMI_TRUE@       ipmi_la-utils_ignorelist.lo
+ipmi_la_OBJECTS = $(am_ipmi_la_OBJECTS)
+ipmi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ipmi_la_CFLAGS) \
+       $(CFLAGS) $(ipmi_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_IPMI_TRUE@am_ipmi_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_IPTABLES_TRUE@iptables_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_IPTABLES_TRUE@   $(am__DEPENDENCIES_1)
+am__iptables_la_SOURCES_DIST = iptables.c
+@BUILD_PLUGIN_IPTABLES_TRUE@am_iptables_la_OBJECTS =  \
+@BUILD_PLUGIN_IPTABLES_TRUE@   iptables_la-iptables.lo
+iptables_la_OBJECTS = $(am_iptables_la_OBJECTS)
+iptables_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(iptables_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_IPTABLES_TRUE@am_iptables_la_rpath = -rpath $(pkglibdir)
+ipvs_la_LIBADD =
+am__ipvs_la_SOURCES_DIST = ipvs.c
+@BUILD_PLUGIN_IPVS_TRUE@am_ipvs_la_OBJECTS = ipvs_la-ipvs.lo
+ipvs_la_OBJECTS = $(am_ipvs_la_OBJECTS)
+ipvs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ipvs_la_CFLAGS) \
+       $(CFLAGS) $(ipvs_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_IPVS_TRUE@am_ipvs_la_rpath = -rpath $(pkglibdir)
+irq_la_LIBADD =
+am__irq_la_SOURCES_DIST = irq.c utils_ignorelist.c utils_ignorelist.h
+@BUILD_PLUGIN_IRQ_TRUE@am_irq_la_OBJECTS = irq.lo utils_ignorelist.lo
+irq_la_OBJECTS = $(am_irq_la_OBJECTS)
+irq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(irq_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_IRQ_TRUE@am_irq_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_JAVA_TRUE@java_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__java_la_SOURCES_DIST = java.c
+@BUILD_PLUGIN_JAVA_TRUE@am_java_la_OBJECTS = java_la-java.lo
+java_la_OBJECTS = $(am_java_la_OBJECTS)
+java_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(java_la_CFLAGS) \
+       $(CFLAGS) $(java_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_JAVA_TRUE@am_java_la_rpath = -rpath $(pkglibdir)
+liblookup_la_DEPENDENCIES = daemon/libavltree.la daemon/libcommon.la
+am_liblookup_la_OBJECTS = utils_vl_lookup.lo
+liblookup_la_OBJECTS = $(am_liblookup_la_OBJECTS)
+libmount_la_DEPENDENCIES = daemon/libcommon.la
+am_libmount_la_OBJECTS = utils_mount.lo
+libmount_la_OBJECTS = $(am_libmount_la_OBJECTS)
+@BUILD_PLUGIN_LOAD_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_8 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_LOAD_TRUE@load_la_DEPENDENCIES = $(am__DEPENDENCIES_8) \
+@BUILD_PLUGIN_LOAD_TRUE@       $(am__DEPENDENCIES_1)
+am__load_la_SOURCES_DIST = load.c
+@BUILD_PLUGIN_LOAD_TRUE@am_load_la_OBJECTS = load_la-load.lo
+load_la_OBJECTS = $(am_load_la_OBJECTS)
+load_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(load_la_CFLAGS) \
+       $(CFLAGS) $(load_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_LOAD_TRUE@am_load_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@log_logstash_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@       $(am__DEPENDENCIES_1)
+am__log_logstash_la_SOURCES_DIST = log_logstash.c
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@am_log_logstash_la_OBJECTS = log_logstash_la-log_logstash.lo
+log_logstash_la_OBJECTS = $(am_log_logstash_la_OBJECTS)
+log_logstash_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(log_logstash_la_CFLAGS) $(CFLAGS) $(log_logstash_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@am_log_logstash_la_rpath = -rpath \
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@       $(pkglibdir)
+logfile_la_LIBADD =
+am__logfile_la_SOURCES_DIST = logfile.c
+@BUILD_PLUGIN_LOGFILE_TRUE@am_logfile_la_OBJECTS = logfile.lo
+logfile_la_OBJECTS = $(am_logfile_la_OBJECTS)
+logfile_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(logfile_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_LOGFILE_TRUE@am_logfile_la_rpath = -rpath $(pkglibdir)
+lpar_la_DEPENDENCIES =
+am__lpar_la_SOURCES_DIST = lpar.c
+@BUILD_PLUGIN_LPAR_TRUE@am_lpar_la_OBJECTS = lpar.lo
+lpar_la_OBJECTS = $(am_lpar_la_OBJECTS)
+lpar_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(lpar_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_LPAR_TRUE@am_lpar_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_LVM_TRUE@lvm_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__lvm_la_SOURCES_DIST = lvm.c
+@BUILD_PLUGIN_LVM_TRUE@am_lvm_la_OBJECTS = lvm.lo
+lvm_la_OBJECTS = $(am_lvm_la_OBJECTS)
+lvm_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(lvm_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_LVM_TRUE@am_lvm_la_rpath = -rpath $(pkglibdir)
+madwifi_la_LIBADD =
+am__madwifi_la_SOURCES_DIST = madwifi.c madwifi.h utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_MADWIFI_TRUE@am_madwifi_la_OBJECTS = madwifi.lo \
+@BUILD_PLUGIN_MADWIFI_TRUE@    utils_ignorelist.lo
+madwifi_la_OBJECTS = $(am_madwifi_la_OBJECTS)
+madwifi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(madwifi_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MADWIFI_TRUE@am_madwifi_la_rpath = -rpath $(pkglibdir)
+match_empty_counter_la_LIBADD =
+am__match_empty_counter_la_SOURCES_DIST = match_empty_counter.c
+@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@am_match_empty_counter_la_OBJECTS =  \
+@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@        match_empty_counter.lo
+match_empty_counter_la_OBJECTS = $(am_match_empty_counter_la_OBJECTS)
+match_empty_counter_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(match_empty_counter_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@am_match_empty_counter_la_rpath =  \
+@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@        -rpath $(pkglibdir)
+match_hashed_la_LIBADD =
+am__match_hashed_la_SOURCES_DIST = match_hashed.c
+@BUILD_PLUGIN_MATCH_HASHED_TRUE@am_match_hashed_la_OBJECTS =  \
+@BUILD_PLUGIN_MATCH_HASHED_TRUE@       match_hashed.lo
+match_hashed_la_OBJECTS = $(am_match_hashed_la_OBJECTS)
+match_hashed_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(match_hashed_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_MATCH_HASHED_TRUE@am_match_hashed_la_rpath = -rpath \
+@BUILD_PLUGIN_MATCH_HASHED_TRUE@       $(pkglibdir)
+match_regex_la_LIBADD =
+am__match_regex_la_SOURCES_DIST = match_regex.c
+@BUILD_PLUGIN_MATCH_REGEX_TRUE@am_match_regex_la_OBJECTS =  \
+@BUILD_PLUGIN_MATCH_REGEX_TRUE@        match_regex.lo
+match_regex_la_OBJECTS = $(am_match_regex_la_OBJECTS)
+match_regex_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(match_regex_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+@BUILD_PLUGIN_MATCH_REGEX_TRUE@am_match_regex_la_rpath = -rpath \
+@BUILD_PLUGIN_MATCH_REGEX_TRUE@        $(pkglibdir)
+match_timediff_la_LIBADD =
+am__match_timediff_la_SOURCES_DIST = match_timediff.c
+@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@am_match_timediff_la_OBJECTS =  \
+@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@     match_timediff.lo
+match_timediff_la_OBJECTS = $(am_match_timediff_la_OBJECTS)
+match_timediff_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(match_timediff_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@am_match_timediff_la_rpath = -rpath \
+@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@     $(pkglibdir)
+match_value_la_LIBADD =
+am__match_value_la_SOURCES_DIST = match_value.c
+@BUILD_PLUGIN_MATCH_VALUE_TRUE@am_match_value_la_OBJECTS =  \
+@BUILD_PLUGIN_MATCH_VALUE_TRUE@        match_value.lo
+match_value_la_OBJECTS = $(am_match_value_la_OBJECTS)
+match_value_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(match_value_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+@BUILD_PLUGIN_MATCH_VALUE_TRUE@am_match_value_la_rpath = -rpath \
+@BUILD_PLUGIN_MATCH_VALUE_TRUE@        $(pkglibdir)
+@BUILD_PLUGIN_MBMON_TRUE@mbmon_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_MBMON_TRUE@      $(am__DEPENDENCIES_1)
+am__mbmon_la_SOURCES_DIST = mbmon.c
+@BUILD_PLUGIN_MBMON_TRUE@am_mbmon_la_OBJECTS = mbmon.lo
+mbmon_la_OBJECTS = $(am_mbmon_la_OBJECTS)
+mbmon_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(mbmon_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MBMON_TRUE@am_mbmon_la_rpath = -rpath $(pkglibdir)
+md_la_LIBADD =
+am__md_la_SOURCES_DIST = md.c utils_ignorelist.c utils_ignorelist.h
+@BUILD_PLUGIN_MD_TRUE@am_md_la_OBJECTS = md.lo utils_ignorelist.lo
+md_la_OBJECTS = $(am_md_la_OBJECTS)
+md_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(md_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MD_TRUE@am_md_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_MEMCACHEC_TRUE@memcachec_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_MEMCACHEC_TRUE@  $(am__DEPENDENCIES_1)
+am__memcachec_la_SOURCES_DIST = memcachec.c
+@BUILD_PLUGIN_MEMCACHEC_TRUE@am_memcachec_la_OBJECTS =  \
+@BUILD_PLUGIN_MEMCACHEC_TRUE@  memcachec_la-memcachec.lo
+memcachec_la_OBJECTS = $(am_memcachec_la_OBJECTS)
+memcachec_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(memcachec_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MEMCACHEC_TRUE@am_memcachec_la_rpath = -rpath \
+@BUILD_PLUGIN_MEMCACHEC_TRUE@  $(pkglibdir)
+@BUILD_PLUGIN_MEMCACHED_TRUE@memcached_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_MEMCACHED_TRUE@  $(am__DEPENDENCIES_1)
+am__memcached_la_SOURCES_DIST = memcached.c
+@BUILD_PLUGIN_MEMCACHED_TRUE@am_memcached_la_OBJECTS = memcached.lo
+memcached_la_OBJECTS = $(am_memcached_la_OBJECTS)
+memcached_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(memcached_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MEMCACHED_TRUE@am_memcached_la_rpath = -rpath \
+@BUILD_PLUGIN_MEMCACHED_TRUE@  $(pkglibdir)
+@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_9 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_MEMORY_TRUE@memory_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_MEMORY_TRUE@     $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_MEMORY_TRUE@     $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_MEMORY_TRUE@     $(am__DEPENDENCIES_9) \
+@BUILD_PLUGIN_MEMORY_TRUE@     $(am__DEPENDENCIES_1)
+am__memory_la_SOURCES_DIST = memory.c
+@BUILD_PLUGIN_MEMORY_TRUE@am_memory_la_OBJECTS = memory_la-memory.lo
+memory_la_OBJECTS = $(am_memory_la_OBJECTS)
+memory_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(memory_la_CFLAGS) \
+       $(CFLAGS) $(memory_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MEMORY_TRUE@am_memory_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_MIC_TRUE@mic_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__mic_la_SOURCES_DIST = mic.c utils_ignorelist.c utils_ignorelist.h
+@BUILD_PLUGIN_MIC_TRUE@am_mic_la_OBJECTS = mic_la-mic.lo \
+@BUILD_PLUGIN_MIC_TRUE@        mic_la-utils_ignorelist.lo
+mic_la_OBJECTS = $(am_mic_la_OBJECTS)
+mic_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(mic_la_CFLAGS) $(CFLAGS) \
+       $(mic_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MIC_TRUE@am_mic_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_MODBUS_TRUE@modbus_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_MODBUS_TRUE@     $(am__DEPENDENCIES_1)
+am__modbus_la_SOURCES_DIST = modbus.c
+@BUILD_PLUGIN_MODBUS_TRUE@am_modbus_la_OBJECTS = modbus_la-modbus.lo
+modbus_la_OBJECTS = $(am_modbus_la_OBJECTS)
+modbus_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(modbus_la_CFLAGS) \
+       $(CFLAGS) $(modbus_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MODBUS_TRUE@am_modbus_la_rpath = -rpath $(pkglibdir)
+multimeter_la_LIBADD =
+am__multimeter_la_SOURCES_DIST = multimeter.c
+@BUILD_PLUGIN_MULTIMETER_TRUE@am_multimeter_la_OBJECTS =  \
+@BUILD_PLUGIN_MULTIMETER_TRUE@ multimeter.lo
+multimeter_la_OBJECTS = $(am_multimeter_la_OBJECTS)
+multimeter_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(multimeter_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MULTIMETER_TRUE@am_multimeter_la_rpath = -rpath \
+@BUILD_PLUGIN_MULTIMETER_TRUE@ $(pkglibdir)
+@BUILD_PLUGIN_MYSQL_TRUE@@BUILD_WITH_LIBMYSQL_TRUE@am__DEPENDENCIES_10 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_MYSQL_TRUE@mysql_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_MYSQL_TRUE@      $(am__DEPENDENCIES_10)
+am__mysql_la_SOURCES_DIST = mysql.c
+@BUILD_PLUGIN_MYSQL_TRUE@am_mysql_la_OBJECTS = mysql_la-mysql.lo
+mysql_la_OBJECTS = $(am_mysql_la_OBJECTS)
+mysql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(mysql_la_CFLAGS) \
+       $(CFLAGS) $(mysql_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_MYSQL_TRUE@am_mysql_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_NETAPP_TRUE@netapp_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_NETAPP_TRUE@     $(am__DEPENDENCIES_1)
+am__netapp_la_SOURCES_DIST = netapp.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_NETAPP_TRUE@am_netapp_la_OBJECTS = netapp_la-netapp.lo \
+@BUILD_PLUGIN_NETAPP_TRUE@     netapp_la-utils_ignorelist.lo
+netapp_la_OBJECTS = $(am_netapp_la_OBJECTS)
+netapp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(netapp_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NETAPP_TRUE@am_netapp_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_NETLINK_TRUE@netlink_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_NETLINK_TRUE@    $(am__DEPENDENCIES_1)
+am__netlink_la_SOURCES_DIST = netlink.c
+@BUILD_PLUGIN_NETLINK_TRUE@am_netlink_la_OBJECTS =  \
+@BUILD_PLUGIN_NETLINK_TRUE@    netlink_la-netlink.lo
+netlink_la_OBJECTS = $(am_netlink_la_OBJECTS)
+netlink_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(netlink_la_CFLAGS) \
+       $(CFLAGS) $(netlink_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NETLINK_TRUE@am_netlink_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_NETWORK_TRUE@@BUILD_WITH_LIBGCRYPT_TRUE@am__DEPENDENCIES_11 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_NETWORK_TRUE@network_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_NETWORK_TRUE@    $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_NETWORK_TRUE@    $(am__DEPENDENCIES_11)
+am__network_la_SOURCES_DIST = network.c network.h utils_fbhash.c \
+       utils_fbhash.h
+@BUILD_PLUGIN_NETWORK_TRUE@am_network_la_OBJECTS =  \
+@BUILD_PLUGIN_NETWORK_TRUE@    network_la-network.lo \
+@BUILD_PLUGIN_NETWORK_TRUE@    network_la-utils_fbhash.lo
+network_la_OBJECTS = $(am_network_la_OBJECTS)
+network_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(network_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NETWORK_TRUE@am_network_la_rpath = -rpath $(pkglibdir)
+nfs_la_LIBADD =
+am__nfs_la_SOURCES_DIST = nfs.c
+@BUILD_PLUGIN_NFS_TRUE@am_nfs_la_OBJECTS = nfs.lo
+nfs_la_OBJECTS = $(am_nfs_la_OBJECTS)
+nfs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(nfs_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NFS_TRUE@am_nfs_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_NGINX_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__DEPENDENCIES_12 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_NGINX_TRUE@nginx_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_NGINX_TRUE@      $(am__DEPENDENCIES_12)
+am__nginx_la_SOURCES_DIST = nginx.c
+@BUILD_PLUGIN_NGINX_TRUE@am_nginx_la_OBJECTS = nginx_la-nginx.lo
+nginx_la_OBJECTS = $(am_nginx_la_OBJECTS)
+nginx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(nginx_la_CFLAGS) \
+       $(CFLAGS) $(nginx_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NGINX_TRUE@am_nginx_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@notify_desktop_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@     $(am__DEPENDENCIES_1)
+am__notify_desktop_la_SOURCES_DIST = notify_desktop.c
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@am_notify_desktop_la_OBJECTS = notify_desktop_la-notify_desktop.lo
+notify_desktop_la_OBJECTS = $(am_notify_desktop_la_OBJECTS)
+notify_desktop_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(notify_desktop_la_CFLAGS) $(CFLAGS) \
+       $(notify_desktop_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@am_notify_desktop_la_rpath = -rpath \
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@     $(pkglibdir)
+notify_email_la_DEPENDENCIES =
+am__notify_email_la_SOURCES_DIST = notify_email.c
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@am_notify_email_la_OBJECTS =  \
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@       notify_email.lo
+notify_email_la_OBJECTS = $(am_notify_email_la_OBJECTS)
+notify_email_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(notify_email_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@am_notify_email_la_rpath = -rpath \
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@       $(pkglibdir)
+@BUILD_PLUGIN_NTPD_TRUE@ntpd_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__ntpd_la_SOURCES_DIST = ntpd.c
+@BUILD_PLUGIN_NTPD_TRUE@am_ntpd_la_OBJECTS = ntpd.lo
+ntpd_la_OBJECTS = $(am_ntpd_la_OBJECTS)
+ntpd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(ntpd_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NTPD_TRUE@am_ntpd_la_rpath = -rpath $(pkglibdir)
+numa_la_LIBADD =
+am__numa_la_SOURCES_DIST = numa.c
+@BUILD_PLUGIN_NUMA_TRUE@am_numa_la_OBJECTS = numa.lo
+numa_la_OBJECTS = $(am_numa_la_OBJECTS)
+numa_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(numa_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NUMA_TRUE@am_numa_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_NUT_TRUE@nut_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__nut_la_SOURCES_DIST = nut.c
+@BUILD_PLUGIN_NUT_TRUE@am_nut_la_OBJECTS = nut_la-nut.lo
+nut_la_OBJECTS = $(am_nut_la_OBJECTS)
+nut_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(nut_la_CFLAGS) $(CFLAGS) \
+       $(nut_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_NUT_TRUE@am_nut_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_OLSRD_TRUE@olsrd_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_OLSRD_TRUE@      $(am__DEPENDENCIES_1)
+am__olsrd_la_SOURCES_DIST = olsrd.c
+@BUILD_PLUGIN_OLSRD_TRUE@am_olsrd_la_OBJECTS = olsrd.lo
+olsrd_la_OBJECTS = $(am_olsrd_la_OBJECTS)
+olsrd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(olsrd_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_OLSRD_TRUE@am_olsrd_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_ONEWIRE_TRUE@onewire_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_ONEWIRE_TRUE@    $(am__DEPENDENCIES_1)
+am__onewire_la_SOURCES_DIST = onewire.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_ONEWIRE_TRUE@am_onewire_la_OBJECTS =  \
+@BUILD_PLUGIN_ONEWIRE_TRUE@    onewire_la-onewire.lo \
+@BUILD_PLUGIN_ONEWIRE_TRUE@    onewire_la-utils_ignorelist.lo
+onewire_la_OBJECTS = $(am_onewire_la_OBJECTS)
+onewire_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(onewire_la_CFLAGS) \
+       $(CFLAGS) $(onewire_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ONEWIRE_TRUE@am_onewire_la_rpath = -rpath $(pkglibdir)
+openldap_la_DEPENDENCIES =
+am__openldap_la_SOURCES_DIST = openldap.c
+@BUILD_PLUGIN_OPENLDAP_TRUE@am_openldap_la_OBJECTS =  \
+@BUILD_PLUGIN_OPENLDAP_TRUE@   openldap_la-openldap.lo
+openldap_la_OBJECTS = $(am_openldap_la_OBJECTS)
+openldap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(openldap_la_CFLAGS) \
+       $(CFLAGS) $(openldap_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_OPENLDAP_TRUE@am_openldap_la_rpath = -rpath $(pkglibdir)
+openvpn_la_LIBADD =
+am__openvpn_la_SOURCES_DIST = openvpn.c
+@BUILD_PLUGIN_OPENVPN_TRUE@am_openvpn_la_OBJECTS =  \
+@BUILD_PLUGIN_OPENVPN_TRUE@    openvpn_la-openvpn.lo
+openvpn_la_OBJECTS = $(am_openvpn_la_OBJECTS)
+openvpn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(openvpn_la_CFLAGS) \
+       $(CFLAGS) $(openvpn_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_OPENVPN_TRUE@am_openvpn_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_ORACLE_TRUE@oracle_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_ORACLE_TRUE@     $(am__DEPENDENCIES_1)
+am__oracle_la_SOURCES_DIST = oracle.c utils_db_query.c \
+       utils_db_query.h
+@BUILD_PLUGIN_ORACLE_TRUE@am_oracle_la_OBJECTS = oracle_la-oracle.lo \
+@BUILD_PLUGIN_ORACLE_TRUE@     oracle_la-utils_db_query.lo
+oracle_la_OBJECTS = $(am_oracle_la_OBJECTS)
+oracle_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(oracle_la_CFLAGS) \
+       $(CFLAGS) $(oracle_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ORACLE_TRUE@am_oracle_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_PERL_TRUE@perl_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__perl_la_SOURCES_DIST = perl.c
+@BUILD_PLUGIN_PERL_TRUE@am_perl_la_OBJECTS = perl_la-perl.lo
+perl_la_OBJECTS = $(am_perl_la_OBJECTS)
+perl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(perl_la_CFLAGS) \
+       $(CFLAGS) $(perl_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_PERL_TRUE@am_perl_la_rpath = -rpath $(pkglibdir)
+pf_la_LIBADD =
+am__pf_la_SOURCES_DIST = pf.c
+@BUILD_PLUGIN_PF_TRUE@am_pf_la_OBJECTS = pf.lo
+pf_la_OBJECTS = $(am_pf_la_OBJECTS)
+pf_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(pf_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_PF_TRUE@am_pf_la_rpath = -rpath $(pkglibdir)
+pinba_la_DEPENDENCIES =
+am__pinba_la_SOURCES_DIST = pinba.c
+@BUILD_PLUGIN_PINBA_TRUE@am_pinba_la_OBJECTS = pinba.lo
+@BUILD_PLUGIN_PINBA_TRUE@nodist_pinba_la_OBJECTS = pinba.pb-c.lo
+pinba_la_OBJECTS = $(am_pinba_la_OBJECTS) $(nodist_pinba_la_OBJECTS)
+pinba_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(pinba_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_PINBA_TRUE@am_pinba_la_rpath = -rpath $(pkglibdir)
+ping_la_DEPENDENCIES =
+am__ping_la_SOURCES_DIST = ping.c
+@BUILD_PLUGIN_PING_TRUE@am_ping_la_OBJECTS = ping_la-ping.lo
+ping_la_OBJECTS = $(am_ping_la_OBJECTS)
+ping_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(ping_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_PING_TRUE@am_ping_la_rpath = -rpath $(pkglibdir)
+postgresql_la_DEPENDENCIES =
+am__postgresql_la_SOURCES_DIST = postgresql.c utils_db_query.c \
+       utils_db_query.h
+@BUILD_PLUGIN_POSTGRESQL_TRUE@am_postgresql_la_OBJECTS =  \
+@BUILD_PLUGIN_POSTGRESQL_TRUE@ postgresql_la-postgresql.lo \
+@BUILD_PLUGIN_POSTGRESQL_TRUE@ postgresql_la-utils_db_query.lo
+postgresql_la_OBJECTS = $(am_postgresql_la_OBJECTS)
+postgresql_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(postgresql_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_POSTGRESQL_TRUE@am_postgresql_la_rpath = -rpath \
+@BUILD_PLUGIN_POSTGRESQL_TRUE@ $(pkglibdir)
+powerdns_la_LIBADD =
+am__powerdns_la_SOURCES_DIST = powerdns.c
+@BUILD_PLUGIN_POWERDNS_TRUE@am_powerdns_la_OBJECTS = powerdns.lo
+powerdns_la_OBJECTS = $(am_powerdns_la_OBJECTS)
+powerdns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(powerdns_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_POWERDNS_TRUE@am_powerdns_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_PROCESSES_TRUE@processes_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_PROCESSES_TRUE@  $(am__DEPENDENCIES_1)
+am__processes_la_SOURCES_DIST = processes.c
+@BUILD_PLUGIN_PROCESSES_TRUE@am_processes_la_OBJECTS = processes.lo
+processes_la_OBJECTS = $(am_processes_la_OBJECTS)
+processes_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(processes_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_PROCESSES_TRUE@am_processes_la_rpath = -rpath \
+@BUILD_PLUGIN_PROCESSES_TRUE@  $(pkglibdir)
+protocols_la_LIBADD =
+am__protocols_la_SOURCES_DIST = protocols.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_PROTOCOLS_TRUE@am_protocols_la_OBJECTS = protocols.lo \
+@BUILD_PLUGIN_PROTOCOLS_TRUE@  utils_ignorelist.lo
+protocols_la_OBJECTS = $(am_protocols_la_OBJECTS)
+protocols_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(protocols_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_PROTOCOLS_TRUE@am_protocols_la_rpath = -rpath \
+@BUILD_PLUGIN_PROTOCOLS_TRUE@  $(pkglibdir)
+@BUILD_PLUGIN_PYTHON_TRUE@python_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_PYTHON_TRUE@     $(am__DEPENDENCIES_1)
+am__python_la_SOURCES_DIST = python.c pyconfig.c pyvalues.c cpython.h
+@BUILD_PLUGIN_PYTHON_TRUE@am_python_la_OBJECTS = python_la-python.lo \
+@BUILD_PLUGIN_PYTHON_TRUE@     python_la-pyconfig.lo \
+@BUILD_PLUGIN_PYTHON_TRUE@     python_la-pyvalues.lo
+python_la_OBJECTS = $(am_python_la_OBJECTS)
+python_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(python_la_CFLAGS) \
+       $(CFLAGS) $(python_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_PYTHON_TRUE@am_python_la_rpath = -rpath $(pkglibdir)
+redis_la_DEPENDENCIES =
+am__redis_la_SOURCES_DIST = redis.c
+@BUILD_PLUGIN_REDIS_TRUE@am_redis_la_OBJECTS = redis_la-redis.lo
+redis_la_OBJECTS = $(am_redis_la_OBJECTS)
+redis_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(redis_la_CFLAGS) \
+       $(CFLAGS) $(redis_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_REDIS_TRUE@am_redis_la_rpath = -rpath $(pkglibdir)
+routeros_la_DEPENDENCIES =
+am__routeros_la_SOURCES_DIST = routeros.c
+@BUILD_PLUGIN_ROUTEROS_TRUE@am_routeros_la_OBJECTS =  \
+@BUILD_PLUGIN_ROUTEROS_TRUE@   routeros_la-routeros.lo
+routeros_la_OBJECTS = $(am_routeros_la_OBJECTS)
+routeros_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(routeros_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ROUTEROS_TRUE@am_routeros_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_RRDCACHED_TRUE@rrdcached_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_RRDCACHED_TRUE@  $(am__DEPENDENCIES_1)
+am__rrdcached_la_SOURCES_DIST = rrdcached.c utils_rrdcreate.c \
+       utils_rrdcreate.h
+@BUILD_PLUGIN_RRDCACHED_TRUE@am_rrdcached_la_OBJECTS =  \
+@BUILD_PLUGIN_RRDCACHED_TRUE@  rrdcached_la-rrdcached.lo \
+@BUILD_PLUGIN_RRDCACHED_TRUE@  rrdcached_la-utils_rrdcreate.lo
+rrdcached_la_OBJECTS = $(am_rrdcached_la_OBJECTS)
+rrdcached_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(rrdcached_la_CFLAGS) \
+       $(CFLAGS) $(rrdcached_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_RRDCACHED_TRUE@am_rrdcached_la_rpath = -rpath \
+@BUILD_PLUGIN_RRDCACHED_TRUE@  $(pkglibdir)
+@BUILD_PLUGIN_RRDTOOL_TRUE@rrdtool_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_RRDTOOL_TRUE@    $(am__DEPENDENCIES_1)
+am__rrdtool_la_SOURCES_DIST = rrdtool.c utils_rrdcreate.c \
+       utils_rrdcreate.h
+@BUILD_PLUGIN_RRDTOOL_TRUE@am_rrdtool_la_OBJECTS =  \
+@BUILD_PLUGIN_RRDTOOL_TRUE@    rrdtool_la-rrdtool.lo \
+@BUILD_PLUGIN_RRDTOOL_TRUE@    rrdtool_la-utils_rrdcreate.lo
+rrdtool_la_OBJECTS = $(am_rrdtool_la_OBJECTS)
+rrdtool_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(rrdtool_la_CFLAGS) \
+       $(CFLAGS) $(rrdtool_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_RRDTOOL_TRUE@am_rrdtool_la_rpath = -rpath $(pkglibdir)
+sensors_la_DEPENDENCIES =
+am__sensors_la_SOURCES_DIST = sensors.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_SENSORS_TRUE@am_sensors_la_OBJECTS =  \
+@BUILD_PLUGIN_SENSORS_TRUE@    sensors_la-sensors.lo \
+@BUILD_PLUGIN_SENSORS_TRUE@    sensors_la-utils_ignorelist.lo
+sensors_la_OBJECTS = $(am_sensors_la_OBJECTS)
+sensors_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(sensors_la_CFLAGS) \
+       $(CFLAGS) $(sensors_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_SENSORS_TRUE@am_sensors_la_rpath = -rpath $(pkglibdir)
+serial_la_LIBADD =
+am__serial_la_SOURCES_DIST = serial.c
+@BUILD_PLUGIN_SERIAL_TRUE@am_serial_la_OBJECTS = serial.lo
+serial_la_OBJECTS = $(am_serial_la_OBJECTS)
+serial_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(serial_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_SERIAL_TRUE@am_serial_la_rpath = -rpath $(pkglibdir)
+sigrok_la_DEPENDENCIES =
+am__sigrok_la_SOURCES_DIST = sigrok.c
+@BUILD_PLUGIN_SIGROK_TRUE@am_sigrok_la_OBJECTS = sigrok_la-sigrok.lo
+sigrok_la_OBJECTS = $(am_sigrok_la_OBJECTS)
+sigrok_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(sigrok_la_CFLAGS) \
+       $(CFLAGS) $(sigrok_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_SIGROK_TRUE@am_sigrok_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@smart_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__smart_la_SOURCES_DIST = smart.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@am_smart_la_OBJECTS = smart_la-smart.lo \
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@     smart_la-utils_ignorelist.lo
+smart_la_OBJECTS = $(am_smart_la_OBJECTS)
+smart_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(smart_la_CFLAGS) \
+       $(CFLAGS) $(smart_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@am_smart_la_rpath =  \
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@     -rpath \
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@     $(pkglibdir)
+@BUILD_PLUGIN_SNMP_TRUE@@BUILD_WITH_LIBNETSNMP_TRUE@am__DEPENDENCIES_13 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_SNMP_TRUE@snmp_la_DEPENDENCIES = $(am__DEPENDENCIES_13) \
+@BUILD_PLUGIN_SNMP_TRUE@       $(am__DEPENDENCIES_1)
+am__snmp_la_SOURCES_DIST = snmp.c
+@BUILD_PLUGIN_SNMP_TRUE@am_snmp_la_OBJECTS = snmp_la-snmp.lo
+snmp_la_OBJECTS = $(am_snmp_la_OBJECTS)
+snmp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(snmp_la_CFLAGS) \
+       $(CFLAGS) $(snmp_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_SNMP_TRUE@am_snmp_la_rpath = -rpath $(pkglibdir)
+statsd_la_DEPENDENCIES =
+am__statsd_la_SOURCES_DIST = statsd.c utils_latency.h utils_latency.c
+@BUILD_PLUGIN_STATSD_TRUE@am_statsd_la_OBJECTS = statsd.lo \
+@BUILD_PLUGIN_STATSD_TRUE@     utils_latency.lo
+statsd_la_OBJECTS = $(am_statsd_la_OBJECTS)
+statsd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(statsd_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_STATSD_TRUE@am_statsd_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_SWAP_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_14 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_SWAP_TRUE@swap_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_SWAP_TRUE@       $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_SWAP_TRUE@       $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_SWAP_TRUE@       $(am__DEPENDENCIES_14) \
+@BUILD_PLUGIN_SWAP_TRUE@       $(am__DEPENDENCIES_1)
+am__swap_la_SOURCES_DIST = swap.c
+@BUILD_PLUGIN_SWAP_TRUE@am_swap_la_OBJECTS = swap_la-swap.lo
+swap_la_OBJECTS = $(am_swap_la_OBJECTS)
+swap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(swap_la_CFLAGS) \
+       $(CFLAGS) $(swap_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_SWAP_TRUE@am_swap_la_rpath = -rpath $(pkglibdir)
+syslog_la_LIBADD =
+am__syslog_la_SOURCES_DIST = syslog.c
+@BUILD_PLUGIN_SYSLOG_TRUE@am_syslog_la_OBJECTS = syslog.lo
+syslog_la_OBJECTS = $(am_syslog_la_OBJECTS)
+syslog_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(syslog_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_SYSLOG_TRUE@am_syslog_la_rpath = -rpath $(pkglibdir)
+table_la_LIBADD =
+am__table_la_SOURCES_DIST = table.c
+@BUILD_PLUGIN_TABLE_TRUE@am_table_la_OBJECTS = table.lo
+table_la_OBJECTS = $(am_table_la_OBJECTS)
+table_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(table_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TABLE_TRUE@am_table_la_rpath = -rpath $(pkglibdir)
+tail_la_LIBADD =
+am__tail_la_SOURCES_DIST = tail.c
+@BUILD_PLUGIN_TAIL_TRUE@am_tail_la_OBJECTS = tail.lo
+tail_la_OBJECTS = $(am_tail_la_OBJECTS)
+tail_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(tail_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TAIL_TRUE@am_tail_la_rpath = -rpath $(pkglibdir)
+tail_csv_la_LIBADD =
+am__tail_csv_la_SOURCES_DIST = tail_csv.c
+@BUILD_PLUGIN_TAIL_CSV_TRUE@am_tail_csv_la_OBJECTS = tail_csv.lo
+tail_csv_la_OBJECTS = $(am_tail_csv_la_OBJECTS)
+tail_csv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(tail_csv_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TAIL_CSV_TRUE@am_tail_csv_la_rpath = -rpath $(pkglibdir)
+tape_la_DEPENDENCIES =
+am__tape_la_SOURCES_DIST = tape.c
+@BUILD_PLUGIN_TAPE_TRUE@am_tape_la_OBJECTS = tape.lo
+tape_la_OBJECTS = $(am_tape_la_OBJECTS)
+tape_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(tape_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TAPE_TRUE@am_tape_la_rpath = -rpath $(pkglibdir)
+target_notification_la_LIBADD =
+am__target_notification_la_SOURCES_DIST = target_notification.c
+@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@am_target_notification_la_OBJECTS =  \
+@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@        target_notification.lo
+target_notification_la_OBJECTS = $(am_target_notification_la_OBJECTS)
+target_notification_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(target_notification_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@am_target_notification_la_rpath =  \
+@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@        -rpath $(pkglibdir)
+target_replace_la_LIBADD =
+am__target_replace_la_SOURCES_DIST = target_replace.c
+@BUILD_PLUGIN_TARGET_REPLACE_TRUE@am_target_replace_la_OBJECTS =  \
+@BUILD_PLUGIN_TARGET_REPLACE_TRUE@     target_replace.lo
+target_replace_la_OBJECTS = $(am_target_replace_la_OBJECTS)
+target_replace_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(target_replace_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_TARGET_REPLACE_TRUE@am_target_replace_la_rpath = -rpath \
+@BUILD_PLUGIN_TARGET_REPLACE_TRUE@     $(pkglibdir)
+target_scale_la_LIBADD =
+am__target_scale_la_SOURCES_DIST = target_scale.c
+@BUILD_PLUGIN_TARGET_SCALE_TRUE@am_target_scale_la_OBJECTS =  \
+@BUILD_PLUGIN_TARGET_SCALE_TRUE@       target_scale.lo
+target_scale_la_OBJECTS = $(am_target_scale_la_OBJECTS)
+target_scale_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(target_scale_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_TARGET_SCALE_TRUE@am_target_scale_la_rpath = -rpath \
+@BUILD_PLUGIN_TARGET_SCALE_TRUE@       $(pkglibdir)
+target_set_la_LIBADD =
+am__target_set_la_SOURCES_DIST = target_set.c
+@BUILD_PLUGIN_TARGET_SET_TRUE@am_target_set_la_OBJECTS =  \
+@BUILD_PLUGIN_TARGET_SET_TRUE@ target_set.lo
+target_set_la_OBJECTS = $(am_target_set_la_OBJECTS)
+target_set_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(target_set_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TARGET_SET_TRUE@am_target_set_la_rpath = -rpath \
+@BUILD_PLUGIN_TARGET_SET_TRUE@ $(pkglibdir)
+target_v5upgrade_la_LIBADD =
+am__target_v5upgrade_la_SOURCES_DIST = target_v5upgrade.c
+@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@am_target_v5upgrade_la_OBJECTS =  \
+@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@   target_v5upgrade.lo
+target_v5upgrade_la_OBJECTS = $(am_target_v5upgrade_la_OBJECTS)
+target_v5upgrade_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(target_v5upgrade_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@am_target_v5upgrade_la_rpath =  \
+@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@   -rpath $(pkglibdir)
+@BUILD_PLUGIN_TCPCONNS_TRUE@tcpconns_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_TCPCONNS_TRUE@   $(am__DEPENDENCIES_1)
+am__tcpconns_la_SOURCES_DIST = tcpconns.c
+@BUILD_PLUGIN_TCPCONNS_TRUE@am_tcpconns_la_OBJECTS = tcpconns.lo
+tcpconns_la_OBJECTS = $(am_tcpconns_la_OBJECTS)
+tcpconns_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(tcpconns_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TCPCONNS_TRUE@am_tcpconns_la_rpath = -rpath $(pkglibdir)
+teamspeak2_la_LIBADD =
+am__teamspeak2_la_SOURCES_DIST = teamspeak2.c
+@BUILD_PLUGIN_TEAMSPEAK2_TRUE@am_teamspeak2_la_OBJECTS =  \
+@BUILD_PLUGIN_TEAMSPEAK2_TRUE@ teamspeak2.lo
+teamspeak2_la_OBJECTS = $(am_teamspeak2_la_OBJECTS)
+teamspeak2_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(teamspeak2_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TEAMSPEAK2_TRUE@am_teamspeak2_la_rpath = -rpath \
+@BUILD_PLUGIN_TEAMSPEAK2_TRUE@ $(pkglibdir)
+ted_la_LIBADD =
+am__ted_la_SOURCES_DIST = ted.c
+@BUILD_PLUGIN_TED_TRUE@am_ted_la_OBJECTS = ted.lo
+ted_la_OBJECTS = $(am_ted_la_OBJECTS)
+ted_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(ted_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TED_TRUE@am_ted_la_rpath = -rpath $(pkglibdir)
+thermal_la_LIBADD =
+am__thermal_la_SOURCES_DIST = thermal.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_THERMAL_TRUE@am_thermal_la_OBJECTS = thermal.lo \
+@BUILD_PLUGIN_THERMAL_TRUE@    utils_ignorelist.lo
+thermal_la_OBJECTS = $(am_thermal_la_OBJECTS)
+thermal_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(thermal_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_THERMAL_TRUE@am_thermal_la_rpath = -rpath $(pkglibdir)
+threshold_la_LIBADD =
+am__threshold_la_SOURCES_DIST = threshold.c
+@BUILD_PLUGIN_THRESHOLD_TRUE@am_threshold_la_OBJECTS = threshold.lo
+threshold_la_OBJECTS = $(am_threshold_la_OBJECTS)
+threshold_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(threshold_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_THRESHOLD_TRUE@am_threshold_la_rpath = -rpath \
+@BUILD_PLUGIN_THRESHOLD_TRUE@  $(pkglibdir)
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@tokyotyrant_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@        $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@        $(am__DEPENDENCIES_1)
+am__tokyotyrant_la_SOURCES_DIST = tokyotyrant.c
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@am_tokyotyrant_la_OBJECTS =  \
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@        tokyotyrant_la-tokyotyrant.lo
+tokyotyrant_la_OBJECTS = $(am_tokyotyrant_la_OBJECTS)
+tokyotyrant_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(tokyotyrant_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@am_tokyotyrant_la_rpath = -rpath \
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@        $(pkglibdir)
+turbostat_la_LIBADD =
+am__turbostat_la_SOURCES_DIST = turbostat.c
+@BUILD_PLUGIN_TURBOSTAT_TRUE@am_turbostat_la_OBJECTS = turbostat.lo
+turbostat_la_OBJECTS = $(am_turbostat_la_OBJECTS)
+turbostat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(turbostat_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_TURBOSTAT_TRUE@am_turbostat_la_rpath = -rpath \
+@BUILD_PLUGIN_TURBOSTAT_TRUE@  $(pkglibdir)
+unixsock_la_DEPENDENCIES =
+am__unixsock_la_SOURCES_DIST = unixsock.c utils_cmd_flush.h \
+       utils_cmd_flush.c utils_cmd_getval.h utils_cmd_getval.c \
+       utils_cmd_getthreshold.h utils_cmd_getthreshold.c \
+       utils_cmd_listval.h utils_cmd_listval.c utils_cmd_putval.h \
+       utils_cmd_putval.c utils_cmd_putnotif.h utils_cmd_putnotif.c \
+       utils_parse_option.h utils_parse_option.c
+@BUILD_PLUGIN_UNIXSOCK_TRUE@am_unixsock_la_OBJECTS = unixsock.lo \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@   utils_cmd_flush.lo \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@   utils_cmd_getval.lo \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@   utils_cmd_getthreshold.lo \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@   utils_cmd_listval.lo \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@   utils_cmd_putval.lo \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@   utils_cmd_putnotif.lo \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@   utils_parse_option.lo
+unixsock_la_OBJECTS = $(am_unixsock_la_OBJECTS)
+unixsock_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(unixsock_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_UNIXSOCK_TRUE@am_unixsock_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_UPTIME_TRUE@uptime_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_UPTIME_TRUE@     $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_UPTIME_TRUE@     $(am__DEPENDENCIES_1)
+am__uptime_la_SOURCES_DIST = uptime.c
+@BUILD_PLUGIN_UPTIME_TRUE@am_uptime_la_OBJECTS = uptime_la-uptime.lo
+uptime_la_OBJECTS = $(am_uptime_la_OBJECTS)
+uptime_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(uptime_la_CFLAGS) \
+       $(CFLAGS) $(uptime_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_UPTIME_TRUE@am_uptime_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_USERS_TRUE@@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_15 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_USERS_TRUE@users_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_USERS_TRUE@      $(am__DEPENDENCIES_15)
+am__users_la_SOURCES_DIST = users.c
+@BUILD_PLUGIN_USERS_TRUE@am_users_la_OBJECTS = users_la-users.lo
+users_la_OBJECTS = $(am_users_la_OBJECTS)
+users_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(users_la_CFLAGS) \
+       $(CFLAGS) $(users_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_USERS_TRUE@am_users_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_UUID_TRUE@uuid_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__uuid_la_SOURCES_DIST = uuid.c
+@BUILD_PLUGIN_UUID_TRUE@am_uuid_la_OBJECTS = uuid_la-uuid.lo
+uuid_la_OBJECTS = $(am_uuid_la_OBJECTS)
+uuid_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(uuid_la_CFLAGS) \
+       $(CFLAGS) $(uuid_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_UUID_TRUE@am_uuid_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_VARNISH_TRUE@varnish_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_VARNISH_TRUE@    $(am__DEPENDENCIES_1)
+am__varnish_la_SOURCES_DIST = varnish.c
+@BUILD_PLUGIN_VARNISH_TRUE@am_varnish_la_OBJECTS =  \
+@BUILD_PLUGIN_VARNISH_TRUE@    varnish_la-varnish.lo
+varnish_la_OBJECTS = $(am_varnish_la_OBJECTS)
+varnish_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(varnish_la_CFLAGS) \
+       $(CFLAGS) $(varnish_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_VARNISH_TRUE@am_varnish_la_rpath = -rpath $(pkglibdir)
+@BUILD_PLUGIN_VIRT_TRUE@virt_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@BUILD_PLUGIN_VIRT_TRUE@       $(am__DEPENDENCIES_1)
+am__virt_la_SOURCES_DIST = virt.c utils_ignorelist.c \
+       utils_ignorelist.h
+@BUILD_PLUGIN_VIRT_TRUE@am_virt_la_OBJECTS = virt_la-virt.lo \
+@BUILD_PLUGIN_VIRT_TRUE@       virt_la-utils_ignorelist.lo
+virt_la_OBJECTS = $(am_virt_la_OBJECTS)
+virt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(virt_la_CFLAGS) \
+       $(CFLAGS) $(virt_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_VIRT_TRUE@am_virt_la_rpath = -rpath $(pkglibdir)
+vmem_la_LIBADD =
+am__vmem_la_SOURCES_DIST = vmem.c
+@BUILD_PLUGIN_VMEM_TRUE@am_vmem_la_OBJECTS = vmem.lo
+vmem_la_OBJECTS = $(am_vmem_la_OBJECTS)
+vmem_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(vmem_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_VMEM_TRUE@am_vmem_la_rpath = -rpath $(pkglibdir)
+vserver_la_LIBADD =
+am__vserver_la_SOURCES_DIST = vserver.c
+@BUILD_PLUGIN_VSERVER_TRUE@am_vserver_la_OBJECTS = vserver.lo
+vserver_la_OBJECTS = $(am_vserver_la_OBJECTS)
+vserver_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(vserver_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_VSERVER_TRUE@am_vserver_la_rpath = -rpath $(pkglibdir)
+wireless_la_LIBADD =
+am__wireless_la_SOURCES_DIST = wireless.c
+@BUILD_PLUGIN_WIRELESS_TRUE@am_wireless_la_OBJECTS = wireless.lo
+wireless_la_OBJECTS = $(am_wireless_la_OBJECTS)
+wireless_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(wireless_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_WIRELESS_TRUE@am_wireless_la_rpath = -rpath $(pkglibdir)
+write_graphite_la_LIBADD =
+am__write_graphite_la_SOURCES_DIST = write_graphite.c \
+       utils_format_graphite.c utils_format_graphite.h \
+       utils_format_json.c utils_format_json.h
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@am_write_graphite_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@     write_graphite.lo \
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@     utils_format_graphite.lo \
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@     utils_format_json.lo
+write_graphite_la_OBJECTS = $(am_write_graphite_la_OBJECTS)
+write_graphite_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(write_graphite_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@am_write_graphite_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@     $(pkglibdir)
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@@BUILD_WITH_LIBCURL_TRUE@am__DEPENDENCIES_16 = $(am__DEPENDENCIES_1)
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@write_http_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@ $(am__DEPENDENCIES_16)
+am__write_http_la_SOURCES_DIST = write_http.c utils_format_json.c \
+       utils_format_json.h
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@am_write_http_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@ write_http_la-write_http.lo \
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@ write_http_la-utils_format_json.lo
+write_http_la_OBJECTS = $(am_write_http_la_OBJECTS)
+write_http_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(write_http_la_CFLAGS) \
+       $(CFLAGS) $(write_http_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@am_write_http_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@ $(pkglibdir)
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@write_kafka_la_DEPENDENCIES =  \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@        $(am__DEPENDENCIES_1)
+am__write_kafka_la_SOURCES_DIST = write_kafka.c \
+       utils_format_graphite.c utils_format_graphite.h \
+       utils_format_json.c utils_format_json.h utils_cmd_putval.c \
+       utils_cmd_putval.h utils_crc32.c utils_crc32.h
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@am_write_kafka_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@        write_kafka_la-write_kafka.lo \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@        write_kafka_la-utils_format_graphite.lo \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@        write_kafka_la-utils_format_json.lo \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@        write_kafka_la-utils_cmd_putval.lo \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@        write_kafka_la-utils_crc32.lo
+write_kafka_la_OBJECTS = $(am_write_kafka_la_OBJECTS)
+write_kafka_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(write_kafka_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@am_write_kafka_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@        $(pkglibdir)
+write_log_la_LIBADD =
+am__write_log_la_SOURCES_DIST = write_log.c utils_format_graphite.c \
+       utils_format_graphite.h
+@BUILD_PLUGIN_WRITE_LOG_TRUE@am_write_log_la_OBJECTS = write_log.lo \
+@BUILD_PLUGIN_WRITE_LOG_TRUE@  utils_format_graphite.lo
+write_log_la_OBJECTS = $(am_write_log_la_OBJECTS)
+write_log_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(write_log_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_WRITE_LOG_TRUE@am_write_log_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_LOG_TRUE@  $(pkglibdir)
+write_mongodb_la_DEPENDENCIES =
+am__write_mongodb_la_SOURCES_DIST = write_mongodb.c
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@am_write_mongodb_la_OBJECTS = write_mongodb_la-write_mongodb.lo
+write_mongodb_la_OBJECTS = $(am_write_mongodb_la_OBJECTS)
+write_mongodb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(write_mongodb_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@am_write_mongodb_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@      $(pkglibdir)
+write_redis_la_DEPENDENCIES =
+am__write_redis_la_SOURCES_DIST = write_redis.c
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@am_write_redis_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@        write_redis_la-write_redis.lo
+write_redis_la_OBJECTS = $(am_write_redis_la_OBJECTS)
+write_redis_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(write_redis_la_CFLAGS) $(CFLAGS) $(write_redis_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@am_write_redis_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@        $(pkglibdir)
+write_riemann_la_DEPENDENCIES =
+am__write_riemann_la_SOURCES_DIST = write_riemann.c \
+       write_riemann_threshold.c
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@am_write_riemann_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@      write_riemann.lo \
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@      write_riemann_threshold.lo
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@nodist_write_riemann_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@      riemann.pb-c.lo
+write_riemann_la_OBJECTS = $(am_write_riemann_la_OBJECTS) \
+       $(nodist_write_riemann_la_OBJECTS)
+write_riemann_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(write_riemann_la_LDFLAGS) $(LDFLAGS) \
+       -o $@
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@am_write_riemann_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@      $(pkglibdir)
+write_sensu_la_LIBADD =
+am__write_sensu_la_SOURCES_DIST = write_sensu.c
+@BUILD_PLUGIN_WRITE_SENSU_TRUE@am_write_sensu_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_SENSU_TRUE@        write_sensu.lo
+write_sensu_la_OBJECTS = $(am_write_sensu_la_OBJECTS)
+write_sensu_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(write_sensu_la_LDFLAGS) $(LDFLAGS) -o \
+       $@
+@BUILD_PLUGIN_WRITE_SENSU_TRUE@am_write_sensu_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_SENSU_TRUE@        $(pkglibdir)
+write_tsdb_la_LIBADD =
+am__write_tsdb_la_SOURCES_DIST = write_tsdb.c
+@BUILD_PLUGIN_WRITE_TSDB_TRUE@am_write_tsdb_la_OBJECTS =  \
+@BUILD_PLUGIN_WRITE_TSDB_TRUE@ write_tsdb.lo
+write_tsdb_la_OBJECTS = $(am_write_tsdb_la_OBJECTS)
+write_tsdb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(write_tsdb_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_WRITE_TSDB_TRUE@am_write_tsdb_la_rpath = -rpath \
+@BUILD_PLUGIN_WRITE_TSDB_TRUE@ $(pkglibdir)
+@BUILD_PLUGIN_XMMS_TRUE@xmms_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__xmms_la_SOURCES_DIST = xmms.c
+@BUILD_PLUGIN_XMMS_TRUE@am_xmms_la_OBJECTS = xmms_la-xmms.lo
+xmms_la_OBJECTS = $(am_xmms_la_OBJECTS)
+xmms_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(xmms_la_CFLAGS) \
+       $(CFLAGS) $(xmms_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_XMMS_TRUE@am_xmms_la_rpath = -rpath $(pkglibdir)
+zfs_arc_la_DEPENDENCIES =
+am__zfs_arc_la_SOURCES_DIST = zfs_arc.c
+@BUILD_PLUGIN_ZFS_ARC_TRUE@am_zfs_arc_la_OBJECTS =  \
+@BUILD_PLUGIN_ZFS_ARC_TRUE@    zfs_arc_la-zfs_arc.lo
+zfs_arc_la_OBJECTS = $(am_zfs_arc_la_OBJECTS)
+zfs_arc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(zfs_arc_la_CFLAGS) \
+       $(CFLAGS) $(zfs_arc_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ZFS_ARC_TRUE@am_zfs_arc_la_rpath = -rpath $(pkglibdir)
+zookeeper_la_LIBADD =
+am__zookeeper_la_SOURCES_DIST = zookeeper.c
+@BUILD_PLUGIN_ZOOKEEPER_TRUE@am_zookeeper_la_OBJECTS = zookeeper.lo
+zookeeper_la_OBJECTS = $(am_zookeeper_la_OBJECTS)
+zookeeper_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(zookeeper_la_LDFLAGS) $(LDFLAGS) -o $@
+@BUILD_PLUGIN_ZOOKEEPER_TRUE@am_zookeeper_la_rpath = -rpath \
+@BUILD_PLUGIN_ZOOKEEPER_TRUE@  $(pkglibdir)
+PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
+am_collectd_nagios_OBJECTS =  \
+       collectd_nagios-collectd-nagios.$(OBJEXT)
+collectd_nagios_OBJECTS = $(am_collectd_nagios_OBJECTS)
+am_collectd_tg_OBJECTS = collectd_tg-collectd-tg.$(OBJEXT)
+collectd_tg_OBJECTS = $(am_collectd_tg_OBJECTS)
+am_collectdctl_OBJECTS = collectdctl-collectdctl.$(OBJEXT)
+collectdctl_OBJECTS = $(am_collectdctl_OBJECTS)
+am_collectdmon_OBJECTS = collectdmon-collectdmon.$(OBJEXT)
+collectdmon_OBJECTS = $(am_collectdmon_OBJECTS)
+collectdmon_LDADD = $(LDADD)
+am_test_utils_mount_OBJECTS = utils_mount_test.$(OBJEXT)
+test_utils_mount_OBJECTS = $(am_test_utils_mount_OBJECTS)
+test_utils_mount_DEPENDENCIES = libmount.la daemon/libplugin_mock.la
+am_test_utils_vl_lookup_OBJECTS = utils_vl_lookup_test.$(OBJEXT)
+test_utils_vl_lookup_OBJECTS = $(am_test_utils_vl_lookup_OBJECTS)
+test_utils_vl_lookup_DEPENDENCIES = liblookup.la \
+       daemon/libplugin_mock.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/libltdl/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(aggregation_la_SOURCES) $(amqp_la_SOURCES) \
+       $(apache_la_SOURCES) $(apcups_la_SOURCES) \
+       $(apple_sensors_la_SOURCES) $(aquaero_la_SOURCES) \
+       $(ascent_la_SOURCES) $(barometer_la_SOURCES) \
+       $(battery_la_SOURCES) $(bind_la_SOURCES) $(ceph_la_SOURCES) \
+       $(cgroups_la_SOURCES) $(conntrack_la_SOURCES) \
+       $(contextswitch_la_SOURCES) $(cpu_la_SOURCES) \
+       $(cpufreq_la_SOURCES) $(csv_la_SOURCES) $(curl_la_SOURCES) \
+       $(curl_json_la_SOURCES) $(curl_xml_la_SOURCES) \
+       $(dbi_la_SOURCES) $(df_la_SOURCES) $(disk_la_SOURCES) \
+       $(dns_la_SOURCES) $(drbd_la_SOURCES) $(email_la_SOURCES) \
+       $(entropy_la_SOURCES) $(ethstat_la_SOURCES) $(exec_la_SOURCES) \
+       $(fhcount_la_SOURCES) $(filecount_la_SOURCES) \
+       $(fscache_la_SOURCES) $(gmond_la_SOURCES) \
+       $(hddtemp_la_SOURCES) $(interface_la_SOURCES) \
+       $(ipc_la_SOURCES) $(ipmi_la_SOURCES) $(iptables_la_SOURCES) \
+       $(ipvs_la_SOURCES) $(irq_la_SOURCES) $(java_la_SOURCES) \
+       $(liblookup_la_SOURCES) $(libmount_la_SOURCES) \
+       $(load_la_SOURCES) $(log_logstash_la_SOURCES) \
+       $(logfile_la_SOURCES) $(lpar_la_SOURCES) $(lvm_la_SOURCES) \
+       $(madwifi_la_SOURCES) $(match_empty_counter_la_SOURCES) \
+       $(match_hashed_la_SOURCES) $(match_regex_la_SOURCES) \
+       $(match_timediff_la_SOURCES) $(match_value_la_SOURCES) \
+       $(mbmon_la_SOURCES) $(md_la_SOURCES) $(memcachec_la_SOURCES) \
+       $(memcached_la_SOURCES) $(memory_la_SOURCES) $(mic_la_SOURCES) \
+       $(modbus_la_SOURCES) $(multimeter_la_SOURCES) \
+       $(mysql_la_SOURCES) $(netapp_la_SOURCES) $(netlink_la_SOURCES) \
+       $(network_la_SOURCES) $(nfs_la_SOURCES) $(nginx_la_SOURCES) \
+       $(notify_desktop_la_SOURCES) $(notify_email_la_SOURCES) \
+       $(ntpd_la_SOURCES) $(numa_la_SOURCES) $(nut_la_SOURCES) \
+       $(olsrd_la_SOURCES) $(onewire_la_SOURCES) \
+       $(openldap_la_SOURCES) $(openvpn_la_SOURCES) \
+       $(oracle_la_SOURCES) $(perl_la_SOURCES) $(pf_la_SOURCES) \
+       $(pinba_la_SOURCES) $(nodist_pinba_la_SOURCES) \
+       $(ping_la_SOURCES) $(postgresql_la_SOURCES) \
+       $(powerdns_la_SOURCES) $(processes_la_SOURCES) \
+       $(protocols_la_SOURCES) $(python_la_SOURCES) \
+       $(redis_la_SOURCES) $(routeros_la_SOURCES) \
+       $(rrdcached_la_SOURCES) $(rrdtool_la_SOURCES) \
+       $(sensors_la_SOURCES) $(serial_la_SOURCES) \
+       $(sigrok_la_SOURCES) $(smart_la_SOURCES) $(snmp_la_SOURCES) \
+       $(statsd_la_SOURCES) $(swap_la_SOURCES) $(syslog_la_SOURCES) \
+       $(table_la_SOURCES) $(tail_la_SOURCES) $(tail_csv_la_SOURCES) \
+       $(tape_la_SOURCES) $(target_notification_la_SOURCES) \
+       $(target_replace_la_SOURCES) $(target_scale_la_SOURCES) \
+       $(target_set_la_SOURCES) $(target_v5upgrade_la_SOURCES) \
+       $(tcpconns_la_SOURCES) $(teamspeak2_la_SOURCES) \
+       $(ted_la_SOURCES) $(thermal_la_SOURCES) \
+       $(threshold_la_SOURCES) $(tokyotyrant_la_SOURCES) \
+       $(turbostat_la_SOURCES) $(unixsock_la_SOURCES) \
+       $(uptime_la_SOURCES) $(users_la_SOURCES) $(uuid_la_SOURCES) \
+       $(varnish_la_SOURCES) $(virt_la_SOURCES) $(vmem_la_SOURCES) \
+       $(vserver_la_SOURCES) $(wireless_la_SOURCES) \
+       $(write_graphite_la_SOURCES) $(write_http_la_SOURCES) \
+       $(write_kafka_la_SOURCES) $(write_log_la_SOURCES) \
+       $(write_mongodb_la_SOURCES) $(write_redis_la_SOURCES) \
+       $(write_riemann_la_SOURCES) $(nodist_write_riemann_la_SOURCES) \
+       $(write_sensu_la_SOURCES) $(write_tsdb_la_SOURCES) \
+       $(xmms_la_SOURCES) $(zfs_arc_la_SOURCES) \
+       $(zookeeper_la_SOURCES) $(collectd_nagios_SOURCES) \
+       $(collectd_tg_SOURCES) $(collectdctl_SOURCES) \
+       $(collectdmon_SOURCES) $(test_utils_mount_SOURCES) \
+       $(test_utils_vl_lookup_SOURCES)
+DIST_SOURCES = $(am__aggregation_la_SOURCES_DIST) \
+       $(am__amqp_la_SOURCES_DIST) $(am__apache_la_SOURCES_DIST) \
+       $(am__apcups_la_SOURCES_DIST) \
+       $(am__apple_sensors_la_SOURCES_DIST) \
+       $(am__aquaero_la_SOURCES_DIST) $(am__ascent_la_SOURCES_DIST) \
+       $(am__barometer_la_SOURCES_DIST) \
+       $(am__battery_la_SOURCES_DIST) $(am__bind_la_SOURCES_DIST) \
+       $(am__ceph_la_SOURCES_DIST) $(am__cgroups_la_SOURCES_DIST) \
+       $(am__conntrack_la_SOURCES_DIST) \
+       $(am__contextswitch_la_SOURCES_DIST) \
+       $(am__cpu_la_SOURCES_DIST) $(am__cpufreq_la_SOURCES_DIST) \
+       $(am__csv_la_SOURCES_DIST) $(am__curl_la_SOURCES_DIST) \
+       $(am__curl_json_la_SOURCES_DIST) \
+       $(am__curl_xml_la_SOURCES_DIST) $(am__dbi_la_SOURCES_DIST) \
+       $(am__df_la_SOURCES_DIST) $(am__disk_la_SOURCES_DIST) \
+       $(am__dns_la_SOURCES_DIST) $(am__drbd_la_SOURCES_DIST) \
+       $(am__email_la_SOURCES_DIST) $(am__entropy_la_SOURCES_DIST) \
+       $(am__ethstat_la_SOURCES_DIST) $(am__exec_la_SOURCES_DIST) \
+       $(am__fhcount_la_SOURCES_DIST) \
+       $(am__filecount_la_SOURCES_DIST) \
+       $(am__fscache_la_SOURCES_DIST) $(am__gmond_la_SOURCES_DIST) \
+       $(am__hddtemp_la_SOURCES_DIST) \
+       $(am__interface_la_SOURCES_DIST) $(am__ipc_la_SOURCES_DIST) \
+       $(am__ipmi_la_SOURCES_DIST) $(am__iptables_la_SOURCES_DIST) \
+       $(am__ipvs_la_SOURCES_DIST) $(am__irq_la_SOURCES_DIST) \
+       $(am__java_la_SOURCES_DIST) $(liblookup_la_SOURCES) \
+       $(libmount_la_SOURCES) $(am__load_la_SOURCES_DIST) \
+       $(am__log_logstash_la_SOURCES_DIST) \
+       $(am__logfile_la_SOURCES_DIST) $(am__lpar_la_SOURCES_DIST) \
+       $(am__lvm_la_SOURCES_DIST) $(am__madwifi_la_SOURCES_DIST) \
+       $(am__match_empty_counter_la_SOURCES_DIST) \
+       $(am__match_hashed_la_SOURCES_DIST) \
+       $(am__match_regex_la_SOURCES_DIST) \
+       $(am__match_timediff_la_SOURCES_DIST) \
+       $(am__match_value_la_SOURCES_DIST) \
+       $(am__mbmon_la_SOURCES_DIST) $(am__md_la_SOURCES_DIST) \
+       $(am__memcachec_la_SOURCES_DIST) \
+       $(am__memcached_la_SOURCES_DIST) $(am__memory_la_SOURCES_DIST) \
+       $(am__mic_la_SOURCES_DIST) $(am__modbus_la_SOURCES_DIST) \
+       $(am__multimeter_la_SOURCES_DIST) $(am__mysql_la_SOURCES_DIST) \
+       $(am__netapp_la_SOURCES_DIST) $(am__netlink_la_SOURCES_DIST) \
+       $(am__network_la_SOURCES_DIST) $(am__nfs_la_SOURCES_DIST) \
+       $(am__nginx_la_SOURCES_DIST) \
+       $(am__notify_desktop_la_SOURCES_DIST) \
+       $(am__notify_email_la_SOURCES_DIST) \
+       $(am__ntpd_la_SOURCES_DIST) $(am__numa_la_SOURCES_DIST) \
+       $(am__nut_la_SOURCES_DIST) $(am__olsrd_la_SOURCES_DIST) \
+       $(am__onewire_la_SOURCES_DIST) $(am__openldap_la_SOURCES_DIST) \
+       $(am__openvpn_la_SOURCES_DIST) $(am__oracle_la_SOURCES_DIST) \
+       $(am__perl_la_SOURCES_DIST) $(am__pf_la_SOURCES_DIST) \
+       $(am__pinba_la_SOURCES_DIST) $(am__ping_la_SOURCES_DIST) \
+       $(am__postgresql_la_SOURCES_DIST) \
+       $(am__powerdns_la_SOURCES_DIST) \
+       $(am__processes_la_SOURCES_DIST) \
+       $(am__protocols_la_SOURCES_DIST) $(am__python_la_SOURCES_DIST) \
+       $(am__redis_la_SOURCES_DIST) $(am__routeros_la_SOURCES_DIST) \
+       $(am__rrdcached_la_SOURCES_DIST) \
+       $(am__rrdtool_la_SOURCES_DIST) $(am__sensors_la_SOURCES_DIST) \
+       $(am__serial_la_SOURCES_DIST) $(am__sigrok_la_SOURCES_DIST) \
+       $(am__smart_la_SOURCES_DIST) $(am__snmp_la_SOURCES_DIST) \
+       $(am__statsd_la_SOURCES_DIST) $(am__swap_la_SOURCES_DIST) \
+       $(am__syslog_la_SOURCES_DIST) $(am__table_la_SOURCES_DIST) \
+       $(am__tail_la_SOURCES_DIST) $(am__tail_csv_la_SOURCES_DIST) \
+       $(am__tape_la_SOURCES_DIST) \
+       $(am__target_notification_la_SOURCES_DIST) \
+       $(am__target_replace_la_SOURCES_DIST) \
+       $(am__target_scale_la_SOURCES_DIST) \
+       $(am__target_set_la_SOURCES_DIST) \
+       $(am__target_v5upgrade_la_SOURCES_DIST) \
+       $(am__tcpconns_la_SOURCES_DIST) \
+       $(am__teamspeak2_la_SOURCES_DIST) $(am__ted_la_SOURCES_DIST) \
+       $(am__thermal_la_SOURCES_DIST) \
+       $(am__threshold_la_SOURCES_DIST) \
+       $(am__tokyotyrant_la_SOURCES_DIST) \
+       $(am__turbostat_la_SOURCES_DIST) \
+       $(am__unixsock_la_SOURCES_DIST) $(am__uptime_la_SOURCES_DIST) \
+       $(am__users_la_SOURCES_DIST) $(am__uuid_la_SOURCES_DIST) \
+       $(am__varnish_la_SOURCES_DIST) $(am__virt_la_SOURCES_DIST) \
+       $(am__vmem_la_SOURCES_DIST) $(am__vserver_la_SOURCES_DIST) \
+       $(am__wireless_la_SOURCES_DIST) \
+       $(am__write_graphite_la_SOURCES_DIST) \
+       $(am__write_http_la_SOURCES_DIST) \
+       $(am__write_kafka_la_SOURCES_DIST) \
+       $(am__write_log_la_SOURCES_DIST) \
+       $(am__write_mongodb_la_SOURCES_DIST) \
+       $(am__write_redis_la_SOURCES_DIST) \
+       $(am__write_riemann_la_SOURCES_DIST) \
+       $(am__write_sensu_la_SOURCES_DIST) \
+       $(am__write_tsdb_la_SOURCES_DIST) $(am__xmms_la_SOURCES_DIST) \
+       $(am__zfs_arc_la_SOURCES_DIST) \
+       $(am__zookeeper_la_SOURCES_DIST) $(collectd_nagios_SOURCES) \
+       $(collectd_tg_SOURCES) $(collectdctl_SOURCES) \
+       $(collectdmon_SOURCES) $(test_utils_mount_SOURCES) \
+       $(test_utils_vl_lookup_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+       ctags-recursive dvi-recursive html-recursive info-recursive \
+       install-data-recursive install-dvi-recursive \
+       install-exec-recursive install-html-recursive \
+       install-info-recursive install-pdf-recursive \
+       install-ps-recursive install-recursive installcheck-recursive \
+       installdirs-recursive pdf-recursive ps-recursive \
+       tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+man1dir = $(mandir)/man1
+man5dir = $(mandir)/man5
+NROFF = nroff
+MANS = $(dist_man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+       check recheck distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+       $(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red='\e[0;31m'; \
+    grn='\e[0;32m'; \
+    lgn='\e[1;32m'; \
+    blu='\e[1;34m'; \
+    mgn='\e[0;35m'; \
+    brg='\e[1m'; \
+    std='\e[m'; \
+  fi; \
+}
+am__recheck_rx = ^[    ]*:recheck:[    ]*
+am__global_test_result_rx = ^[         ]*:global-test-result:[         ]*
+am__copy_in_global_log_rx = ^[         ]*:copy-in-global-log:[         ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+  recheck = 1; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+        { \
+          if ((getline line2 < ($$0 ".log")) < 0) \
+           recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+        { \
+          recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+        { \
+          break; \
+        } \
+    }; \
+  if (recheck) \
+    print $$0; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+  print "fatal: making $@: " msg | "cat >&2"; \
+  exit 1; \
+} \
+function rst_section(header) \
+{ \
+  print header; \
+  len = length(header); \
+  for (i = 1; i <= len; i = i + 1) \
+    printf "="; \
+  printf "\n\n"; \
+} \
+{ \
+  copy_in_global_log = 1; \
+  global_test_result = "RUN"; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+         fatal("failed to read from " $$0 ".trs"); \
+      if (line ~ /$(am__global_test_result_rx)/) \
+        { \
+          sub("$(am__global_test_result_rx)", "", line); \
+          sub("[       ]*$$", "", line); \
+          global_test_result = line; \
+        } \
+      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+        copy_in_global_log = 0; \
+    }; \
+  if (copy_in_global_log) \
+    { \
+      rst_section(global_test_result ": " $$0); \
+      while ((rc = (getline line < ($$0 ".log"))) != 0) \
+      { \
+        if (rc < 0) \
+          fatal("failed to read from " $$0 ".log"); \
+        print line; \
+      }; \
+      printf "\n"; \
+    }; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this.  Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test.  Creates the
+# directory for the log if needed.  Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log.  Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup);                                     \
+$(am__vpath_adj_setup) $(am__vpath_adj)                        \
+$(am__tty_colors);                                     \
+srcdir=$(srcdir); export srcdir;                       \
+case "$@" in                                           \
+  */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;;   \
+    *) am__odir=.;;                                    \
+esac;                                                  \
+test "x$$am__odir" = x"." || test -d "$$am__odir"      \
+  || $(MKDIR_P) "$$am__odir" || exit $$?;              \
+if test -f "./$$f"; then dir=./;                       \
+elif test -f "$$f"; then dir=;                         \
+else dir="$(srcdir)/"; fi;                             \
+tst=$$dir$$f; log='$@';                                \
+if test -n '$(DISABLE_HARD_ERRORS)'; then              \
+  am__enable_hard_errors=no;                           \
+else                                                   \
+  am__enable_hard_errors=yes;                          \
+fi;                                                    \
+case " $(XFAIL_TESTS) " in                             \
+  *[\ \        ]$$f[\ \        ]* | *[\ \      ]$$dir$$f[\ \   ]*) \
+    am__expect_failure=yes;;                           \
+  *)                                                   \
+    am__expect_failure=no;;                            \
+esac;                                                  \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed).  The result is saved in the shell variable
+# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/libltdl/config/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/libltdl/config/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+       $(TEST_LOG_FLAGS)
+DIST_SUBDIRS = libcollectdclient liboconfig daemon
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_WITH_LIBAQUAERO5_CFLAGS = @BUILD_WITH_LIBAQUAERO5_CFLAGS@
+BUILD_WITH_LIBAQUAERO5_LDFLAGS = @BUILD_WITH_LIBAQUAERO5_LDFLAGS@
+BUILD_WITH_LIBATASMART_CPPFLAGS = @BUILD_WITH_LIBATASMART_CPPFLAGS@
+BUILD_WITH_LIBATASMART_LDFLAGS = @BUILD_WITH_LIBATASMART_LDFLAGS@
+BUILD_WITH_LIBATASMART_LIBS = @BUILD_WITH_LIBATASMART_LIBS@
+BUILD_WITH_LIBCURL_CFLAGS = @BUILD_WITH_LIBCURL_CFLAGS@
+BUILD_WITH_LIBCURL_LIBS = @BUILD_WITH_LIBCURL_LIBS@
+BUILD_WITH_LIBDBI_CPPFLAGS = @BUILD_WITH_LIBDBI_CPPFLAGS@
+BUILD_WITH_LIBDBI_LDFLAGS = @BUILD_WITH_LIBDBI_LDFLAGS@
+BUILD_WITH_LIBDBI_LIBS = @BUILD_WITH_LIBDBI_LIBS@
+BUILD_WITH_LIBHAL_CFLAGS = @BUILD_WITH_LIBHAL_CFLAGS@
+BUILD_WITH_LIBHAL_LIBS = @BUILD_WITH_LIBHAL_LIBS@
+BUILD_WITH_LIBHIREDIS_CPPFLAGS = @BUILD_WITH_LIBHIREDIS_CPPFLAGS@
+BUILD_WITH_LIBHIREDIS_LDFLAGS = @BUILD_WITH_LIBHIREDIS_LDFLAGS@
+BUILD_WITH_LIBIPTC_CPPFLAGS = @BUILD_WITH_LIBIPTC_CPPFLAGS@
+BUILD_WITH_LIBIPTC_LDFLAGS = @BUILD_WITH_LIBIPTC_LDFLAGS@
+BUILD_WITH_LIBLDAP_CPPFLAGS = @BUILD_WITH_LIBLDAP_CPPFLAGS@
+BUILD_WITH_LIBLDAP_LDFLAGS = @BUILD_WITH_LIBLDAP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_CPPFLAGS = @BUILD_WITH_LIBLVM2APP_CPPFLAGS@
+BUILD_WITH_LIBLVM2APP_LDFLAGS = @BUILD_WITH_LIBLVM2APP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_LIBS = @BUILD_WITH_LIBLVM2APP_LIBS@
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS = @BUILD_WITH_LIBMEMCACHED_CPPFLAGS@
+BUILD_WITH_LIBMEMCACHED_LDFLAGS = @BUILD_WITH_LIBMEMCACHED_LDFLAGS@
+BUILD_WITH_LIBMEMCACHED_LIBS = @BUILD_WITH_LIBMEMCACHED_LIBS@
+BUILD_WITH_LIBMNL_CFLAGS = @BUILD_WITH_LIBMNL_CFLAGS@
+BUILD_WITH_LIBMNL_LIBS = @BUILD_WITH_LIBMNL_LIBS@
+BUILD_WITH_LIBMODBUS_CFLAGS = @BUILD_WITH_LIBMODBUS_CFLAGS@
+BUILD_WITH_LIBMODBUS_LIBS = @BUILD_WITH_LIBMODBUS_LIBS@
+BUILD_WITH_LIBMONGOC_CPPFLAGS = @BUILD_WITH_LIBMONGOC_CPPFLAGS@
+BUILD_WITH_LIBMONGOC_LDFLAGS = @BUILD_WITH_LIBMONGOC_LDFLAGS@
+BUILD_WITH_LIBMYSQL_CFLAGS = @BUILD_WITH_LIBMYSQL_CFLAGS@
+BUILD_WITH_LIBMYSQL_LIBS = @BUILD_WITH_LIBMYSQL_LIBS@
+BUILD_WITH_LIBOPING_CPPFLAGS = @BUILD_WITH_LIBOPING_CPPFLAGS@
+BUILD_WITH_LIBOPING_LDFLAGS = @BUILD_WITH_LIBOPING_LDFLAGS@
+BUILD_WITH_LIBOWCAPI_CPPFLAGS = @BUILD_WITH_LIBOWCAPI_CPPFLAGS@
+BUILD_WITH_LIBOWCAPI_LIBS = @BUILD_WITH_LIBOWCAPI_LIBS@
+BUILD_WITH_LIBPQ_CPPFLAGS = @BUILD_WITH_LIBPQ_CPPFLAGS@
+BUILD_WITH_LIBPQ_LDFLAGS = @BUILD_WITH_LIBPQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS = @BUILD_WITH_LIBRABBITMQ_CPPFLAGS@
+BUILD_WITH_LIBRABBITMQ_LDFLAGS = @BUILD_WITH_LIBRABBITMQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_LIBS = @BUILD_WITH_LIBRABBITMQ_LIBS@
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS = @BUILD_WITH_LIBRDKAFKA_CPPFLAGS@
+BUILD_WITH_LIBRDKAFKA_LDFLAGS = @BUILD_WITH_LIBRDKAFKA_LDFLAGS@
+BUILD_WITH_LIBRDKAFKA_LIBS = @BUILD_WITH_LIBRDKAFKA_LIBS@
+BUILD_WITH_LIBROUTEROS_CPPFLAGS = @BUILD_WITH_LIBROUTEROS_CPPFLAGS@
+BUILD_WITH_LIBROUTEROS_LDFLAGS = @BUILD_WITH_LIBROUTEROS_LDFLAGS@
+BUILD_WITH_LIBRRD_CFLAGS = @BUILD_WITH_LIBRRD_CFLAGS@
+BUILD_WITH_LIBRRD_LDFLAGS = @BUILD_WITH_LIBRRD_LDFLAGS@
+BUILD_WITH_LIBSENSORS_CFLAGS = @BUILD_WITH_LIBSENSORS_CFLAGS@
+BUILD_WITH_LIBSENSORS_LDFLAGS = @BUILD_WITH_LIBSENSORS_LDFLAGS@
+BUILD_WITH_LIBSIGROK_CFLAGS = @BUILD_WITH_LIBSIGROK_CFLAGS@
+BUILD_WITH_LIBSIGROK_LDFLAGS = @BUILD_WITH_LIBSIGROK_LDFLAGS@
+BUILD_WITH_LIBSNMP_CFLAGS = @BUILD_WITH_LIBSNMP_CFLAGS@
+BUILD_WITH_LIBSNMP_LIBS = @BUILD_WITH_LIBSNMP_LIBS@
+BUILD_WITH_LIBSTATGRAB_CFLAGS = @BUILD_WITH_LIBSTATGRAB_CFLAGS@
+BUILD_WITH_LIBSTATGRAB_LDFLAGS = @BUILD_WITH_LIBSTATGRAB_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LIBS = @BUILD_WITH_LIBTOKYOTYRANT_LIBS@
+BUILD_WITH_LIBUDEV_CFLAGS = @BUILD_WITH_LIBUDEV_CFLAGS@
+BUILD_WITH_LIBUDEV_LDFLAGS = @BUILD_WITH_LIBUDEV_LDFLAGS@
+BUILD_WITH_LIBUPSCLIENT_CFLAGS = @BUILD_WITH_LIBUPSCLIENT_CFLAGS@
+BUILD_WITH_LIBUPSCLIENT_LIBS = @BUILD_WITH_LIBUPSCLIENT_LIBS@
+BUILD_WITH_LIBVARNISH_CFLAGS = @BUILD_WITH_LIBVARNISH_CFLAGS@
+BUILD_WITH_LIBVARNISH_LIBS = @BUILD_WITH_LIBVARNISH_LIBS@
+BUILD_WITH_LIBVIRT_CFLAGS = @BUILD_WITH_LIBVIRT_CFLAGS@
+BUILD_WITH_LIBVIRT_LIBS = @BUILD_WITH_LIBVIRT_LIBS@
+BUILD_WITH_LIBXML2_CFLAGS = @BUILD_WITH_LIBXML2_CFLAGS@
+BUILD_WITH_LIBXML2_LIBS = @BUILD_WITH_LIBXML2_LIBS@
+BUILD_WITH_LIBXMMS_CFLAGS = @BUILD_WITH_LIBXMMS_CFLAGS@
+BUILD_WITH_LIBXMMS_LIBS = @BUILD_WITH_LIBXMMS_LIBS@
+BUILD_WITH_LIBYAJL_CPPFLAGS = @BUILD_WITH_LIBYAJL_CPPFLAGS@
+BUILD_WITH_LIBYAJL_LDFLAGS = @BUILD_WITH_LIBYAJL_LDFLAGS@
+BUILD_WITH_LIBYAJL_LIBS = @BUILD_WITH_LIBYAJL_LIBS@
+BUILD_WITH_MIC_CPPFLAGS = @BUILD_WITH_MIC_CPPFLAGS@
+BUILD_WITH_MIC_LDADD = @BUILD_WITH_MIC_LDADD@
+BUILD_WITH_MIC_LIBPATH = @BUILD_WITH_MIC_LIBPATH@
+BUILD_WITH_OPENIPMI_CFLAGS = @BUILD_WITH_OPENIPMI_CFLAGS@
+BUILD_WITH_OPENIPMI_LIBS = @BUILD_WITH_OPENIPMI_LIBS@
+BUILD_WITH_ORACLE_CFLAGS = @BUILD_WITH_ORACLE_CFLAGS@
+BUILD_WITH_ORACLE_LIBS = @BUILD_WITH_ORACLE_LIBS@
+BUILD_WITH_PYTHON_CPPFLAGS = @BUILD_WITH_PYTHON_CPPFLAGS@
+BUILD_WITH_PYTHON_LDFLAGS = @BUILD_WITH_PYTHON_LDFLAGS@
+BUILD_WITH_PYTHON_LIBS = @BUILD_WITH_PYTHON_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_LOG_LEVEL = @DEFAULT_LOG_LEVEL@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GANGLIA_CPPFLAGS = @GANGLIA_CPPFLAGS@
+GANGLIA_LDFLAGS = @GANGLIA_LDFLAGS@
+GANGLIA_LIBS = @GANGLIA_LIBS@
+GCRYPT_CPPFLAGS = @GCRYPT_CPPFLAGS@
+GCRYPT_LDFLAGS = @GCRYPT_LDFLAGS@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVA_CFLAGS = @JAVA_CFLAGS@
+JAVA_CPPFLAGS = @JAVA_CPPFLAGS@
+JAVA_LDFLAGS = @JAVA_LDFLAGS@
+JAVA_LIBS = @JAVA_LIBS@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_DIR = @KERNEL_DIR@
+LCC_VERSION_EXTRA = @LCC_VERSION_EXTRA@
+LCC_VERSION_MAJOR = @LCC_VERSION_MAJOR@
+LCC_VERSION_MINOR = @LCC_VERSION_MINOR@
+LCC_VERSION_PATCH = @LCC_VERSION_PATCH@
+LCC_VERSION_STRING = @LCC_VERSION_STRING@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBNETAPP_CPPFLAGS = @LIBNETAPP_CPPFLAGS@
+LIBNETAPP_LDFLAGS = @LIBNETAPP_LDFLAGS@
+LIBNETAPP_LIBS = @LIBNETAPP_LIBS@
+LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
+LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOAD_PLUGIN_CSV = @LOAD_PLUGIN_CSV@
+LOAD_PLUGIN_LOGFILE = @LOAD_PLUGIN_LOGFILE@
+LOAD_PLUGIN_LOG_LOGSTASH = @LOAD_PLUGIN_LOG_LOGSTASH@
+LOAD_PLUGIN_NETWORK = @LOAD_PLUGIN_NETWORK@
+LOAD_PLUGIN_RRDTOOL = @LOAD_PLUGIN_RRDTOOL@
+LOAD_PLUGIN_SYSLOG = @LOAD_PLUGIN_SYSLOG@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_BINDINGS = @PERL_BINDINGS@
+PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_LIBS = @PERL_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_protoc_c = @have_protoc_c@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = libcollectdclient $(am__append_1) daemon
+PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
+@COMPILER_IS_GCC_TRUE@AM_CFLAGS = -Wall -Werror
+AM_CPPFLAGS = -I$(srcdir)/daemon -DPREFIX='"${prefix}"' \
+       -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"' \
+       -DLOCALSTATEDIR='"${localstatedir}"' \
+       -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"' \
+       $(am__append_2) -DPLUGINDIR='"${pkglibdir}"' \
+       -DPKGDATADIR='"${pkgdatadir}"'
+AUTOMAKE_OPTIONS = subdir-objects
+noinst_LTLIBRARIES = libmount.la liblookup.la
+libmount_la_SOURCES = utils_mount.c utils_mount.h
+libmount_la_LIBADD = daemon/libcommon.la
+liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
+liblookup_la_LIBADD = daemon/libavltree.la daemon/libcommon.la
+collectdmon_SOURCES = collectdmon.c
+collectdmon_CPPFLAGS = $(AM_CPPFLAGS)
+collectd_nagios_SOURCES = collectd-nagios.c
+collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_nagios_LDADD = $(am__append_3) $(am__append_4) \
+       libcollectdclient/libcollectdclient.la
+collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+collectdctl_SOURCES = collectdctl.c
+collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectdctl_LDADD = $(am__append_5) $(am__append_6) \
+       libcollectdclient/libcollectdclient.la
+collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+collectd_tg_SOURCES = collectd-tg.c
+collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_LDADD = daemon/libheap.la $(am__append_7) $(am__append_8) \
+       $(am__append_9) $(am__append_10) \
+       libcollectdclient/libcollectdclient.la
+collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+pkglib_LTLIBRARIES = $(am__append_11) $(am__append_12) \
+       $(am__append_13) $(am__append_16) $(am__append_18) \
+       $(am__append_19) $(am__append_20) $(am__append_21) \
+       $(am__append_22) $(am__append_24) $(am__append_25) \
+       $(am__append_26) $(am__append_27) $(am__append_28) \
+       $(am__append_30) $(am__append_36) $(am__append_37) \
+       $(am__append_38) $(am__append_41) $(am__append_44) \
+       $(am__append_45) $(am__append_46) $(am__append_47) \
+       $(am__append_55) $(am__append_56) $(am__append_57) \
+       $(am__append_58) $(am__append_59) $(am__append_60) \
+       $(am__append_61) $(am__append_62) $(am__append_63) \
+       $(am__append_64) $(am__append_66) $(am__append_72) \
+       $(am__append_73) $(am__append_74) $(am__append_75) \
+       $(am__append_76) $(am__append_77) $(am__append_78) \
+       $(am__append_82) $(am__append_83) $(am__append_84) \
+       $(am__append_85) $(am__append_86) $(am__append_87) \
+       $(am__append_88) $(am__append_89) $(am__append_90) \
+       $(am__append_91) $(am__append_92) $(am__append_94) \
+       $(am__append_95) $(am__append_96) $(am__append_98) \
+       $(am__append_104) $(am__append_105) $(am__append_106) \
+       $(am__append_107) $(am__append_110) $(am__append_111) \
+       $(am__append_112) $(am__append_117) $(am__append_118) \
+       $(am__append_119) $(am__append_122) $(am__append_123) \
+       $(am__append_124) $(am__append_126) $(am__append_127) \
+       $(am__append_128) $(am__append_130) $(am__append_131) \
+       $(am__append_132) $(am__append_133) $(am__append_134) \
+       $(am__append_136) $(am__append_137) $(am__append_138) \
+       $(am__append_139) $(am__append_140) $(am__append_141) \
+       $(am__append_143) $(am__append_145) $(am__append_146) \
+       $(am__append_147) $(am__append_148) $(am__append_149) \
+       $(am__append_150) $(am__append_151) $(am__append_152) \
+       $(am__append_153) $(am__append_154) $(am__append_158) \
+       $(am__append_159) $(am__append_166) $(am__append_167) \
+       $(am__append_168) $(am__append_169) $(am__append_170) \
+       $(am__append_171) $(am__append_172) $(am__append_173) \
+       $(am__append_174) $(am__append_175) $(am__append_176) \
+       $(am__append_178) $(am__append_179) $(am__append_180) \
+       $(am__append_181) $(am__append_182) $(am__append_184) \
+       $(am__append_185) $(am__append_186) $(am__append_189) \
+       $(am__append_192) $(am__append_193) $(am__append_194) \
+       $(am__append_195) $(am__append_196) $(am__append_197) \
+       $(am__append_198) $(am__append_199) $(am__append_202) \
+       $(am__append_203) $(am__append_204) $(am__append_205) \
+       $(am__append_206) $(am__append_207) $(am__append_208) \
+       $(am__append_209) $(am__append_210) $(am__append_211)
+BUILT_SOURCES = $(dist_man_MANS) $(am__append_213)
+CLEANFILES = $(am__append_212)
+@BUILD_PLUGIN_AGGREGATION_TRUE@aggregation_la_SOURCES = aggregation.c \
+@BUILD_PLUGIN_AGGREGATION_TRUE@                         utils_vl_lookup.c utils_vl_lookup.h
+
+@BUILD_PLUGIN_AGGREGATION_TRUE@aggregation_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_AGGREGATION_TRUE@aggregation_la_LIBADD = -lm
+@BUILD_PLUGIN_AMQP_TRUE@amqp_la_SOURCES = amqp.c \
+@BUILD_PLUGIN_AMQP_TRUE@                 utils_cmd_putval.c utils_cmd_putval.h \
+@BUILD_PLUGIN_AMQP_TRUE@                 utils_format_graphite.c utils_format_graphite.h \
+@BUILD_PLUGIN_AMQP_TRUE@                 utils_format_json.c utils_format_json.h
+
+@BUILD_PLUGIN_AMQP_TRUE@amqp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
+@BUILD_PLUGIN_AMQP_TRUE@amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
+@BUILD_PLUGIN_AMQP_TRUE@amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS)
+@BUILD_PLUGIN_APACHE_TRUE@apache_la_SOURCES = apache.c
+@BUILD_PLUGIN_APACHE_TRUE@apache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_APACHE_TRUE@apache_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_APACHE_TRUE@     $(am__append_14)
+@BUILD_PLUGIN_APACHE_TRUE@apache_la_LIBADD = $(am__append_15)
+@BUILD_PLUGIN_APCUPS_TRUE@apcups_la_SOURCES = apcups.c
+@BUILD_PLUGIN_APCUPS_TRUE@apcups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_APCUPS_TRUE@apcups_la_LIBADD = $(am__append_17)
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@apple_sensors_la_SOURCES = apple_sensors.c
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@apple_sensors_la_LDFLAGS =  \
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@      $(PLUGIN_LDFLAGS) -framework \
+@BUILD_PLUGIN_APPLE_SENSORS_TRUE@      IOKit
+@BUILD_PLUGIN_AQUAERO_TRUE@aquaero_la_SOURCES = aquaero.c
+@BUILD_PLUGIN_AQUAERO_TRUE@aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_AQUAERO_TRUE@aquaero_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBAQUAERO5_CFLAGS)
+@BUILD_PLUGIN_AQUAERO_TRUE@aquaero_la_LIBADD = $(BUILD_WITH_LIBAQUAERO5_LDFLAGS) -laquaero5
+@BUILD_PLUGIN_ASCENT_TRUE@ascent_la_SOURCES = ascent.c
+@BUILD_PLUGIN_ASCENT_TRUE@ascent_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_ASCENT_TRUE@ascent_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_ASCENT_TRUE@             $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+
+@BUILD_PLUGIN_ASCENT_TRUE@ascent_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+@BUILD_PLUGIN_BAROMETER_TRUE@barometer_la_SOURCES = barometer.c
+@BUILD_PLUGIN_BAROMETER_TRUE@barometer_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_BAROMETER_TRUE@barometer_la_LIBADD = -lm
+@BUILD_PLUGIN_BATTERY_TRUE@battery_la_SOURCES = battery.c
+@BUILD_PLUGIN_BATTERY_TRUE@battery_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
+@BUILD_PLUGIN_BATTERY_TRUE@    $(am__append_23)
+@BUILD_PLUGIN_BATTERY_TRUE@battery_la_LIBADD = 
+@BUILD_PLUGIN_BIND_TRUE@bind_la_SOURCES = bind.c
+@BUILD_PLUGIN_BIND_TRUE@bind_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_BIND_TRUE@bind_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_BIND_TRUE@                $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+
+@BUILD_PLUGIN_BIND_TRUE@bind_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+@BUILD_PLUGIN_CEPH_TRUE@ceph_la_SOURCES = ceph.c
+@BUILD_PLUGIN_CEPH_TRUE@ceph_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_CEPH_TRUE@ceph_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+@BUILD_PLUGIN_CEPH_TRUE@ceph_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+@BUILD_PLUGIN_CEPH_TRUE@ceph_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+@BUILD_PLUGIN_CGROUPS_TRUE@cgroups_la_SOURCES = cgroups.c \
+@BUILD_PLUGIN_CGROUPS_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_CGROUPS_TRUE@cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CGROUPS_TRUE@cgroups_la_LIBADD = libmount.la
+@BUILD_PLUGIN_CONNTRACK_TRUE@conntrack_la_SOURCES = conntrack.c
+@BUILD_PLUGIN_CONNTRACK_TRUE@conntrack_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@contextswitch_la_SOURCES = contextswitch.c
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@contextswitch_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@contextswitch_la_LIBADD =  \
+@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@      $(am__append_29)
+@BUILD_PLUGIN_CPU_TRUE@cpu_la_SOURCES = cpu.c
+@BUILD_PLUGIN_CPU_TRUE@cpu_la_CFLAGS = $(AM_CFLAGS) $(am__append_33)
+@BUILD_PLUGIN_CPU_TRUE@cpu_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CPU_TRUE@cpu_la_LIBADD = $(am__append_31) \
+@BUILD_PLUGIN_CPU_TRUE@        $(am__append_32) $(am__append_34) \
+@BUILD_PLUGIN_CPU_TRUE@        $(am__append_35)
+@BUILD_PLUGIN_CPUFREQ_TRUE@cpufreq_la_SOURCES = cpufreq.c
+@BUILD_PLUGIN_CPUFREQ_TRUE@cpufreq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CSV_TRUE@csv_la_SOURCES = csv.c
+@BUILD_PLUGIN_CSV_TRUE@csv_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CURL_TRUE@curl_la_SOURCES = curl.c
+@BUILD_PLUGIN_CURL_TRUE@curl_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CURL_TRUE@curl_la_CFLAGS = $(AM_CFLAGS) $(am__append_39)
+@BUILD_PLUGIN_CURL_TRUE@curl_la_LIBADD = $(am__append_40)
+@BUILD_PLUGIN_CURL_JSON_TRUE@curl_json_la_SOURCES = curl_json.c
+@BUILD_PLUGIN_CURL_JSON_TRUE@curl_json_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_CURL_JSON_TRUE@  $(am__append_42)
+@BUILD_PLUGIN_CURL_JSON_TRUE@curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+@BUILD_PLUGIN_CURL_JSON_TRUE@curl_json_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+@BUILD_PLUGIN_CURL_JSON_TRUE@curl_json_la_LIBADD =  \
+@BUILD_PLUGIN_CURL_JSON_TRUE@  $(BUILD_WITH_LIBYAJL_LIBS) \
+@BUILD_PLUGIN_CURL_JSON_TRUE@  $(am__append_43)
+@BUILD_PLUGIN_CURL_XML_TRUE@curl_xml_la_SOURCES = curl_xml.c
+@BUILD_PLUGIN_CURL_XML_TRUE@curl_xml_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_CURL_XML_TRUE@curl_xml_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_CURL_XML_TRUE@           $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+
+@BUILD_PLUGIN_CURL_XML_TRUE@curl_xml_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+@BUILD_PLUGIN_DBI_TRUE@dbi_la_SOURCES = dbi.c \
+@BUILD_PLUGIN_DBI_TRUE@                 utils_db_query.c utils_db_query.h
+
+@BUILD_PLUGIN_DBI_TRUE@dbi_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBDBI_CPPFLAGS)
+@BUILD_PLUGIN_DBI_TRUE@dbi_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBDBI_LDFLAGS)
+@BUILD_PLUGIN_DBI_TRUE@dbi_la_LIBADD = $(BUILD_WITH_LIBDBI_LIBS)
+@BUILD_PLUGIN_DF_TRUE@df_la_SOURCES = df.c \
+@BUILD_PLUGIN_DF_TRUE@         utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_DF_TRUE@df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_DF_TRUE@df_la_LIBADD = libmount.la
+@BUILD_PLUGIN_DISK_TRUE@disk_la_SOURCES = disk.c \
+@BUILD_PLUGIN_DISK_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_DISK_TRUE@disk_la_CFLAGS = $(AM_CFLAGS) $(am__append_51)
+@BUILD_PLUGIN_DISK_TRUE@disk_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
+@BUILD_PLUGIN_DISK_TRUE@       $(am__append_50)
+@BUILD_PLUGIN_DISK_TRUE@disk_la_LIBADD = $(am__append_48) \
+@BUILD_PLUGIN_DISK_TRUE@       $(am__append_49) $(am__append_52) \
+@BUILD_PLUGIN_DISK_TRUE@       $(am__append_53) $(am__append_54)
+@BUILD_PLUGIN_DNS_TRUE@dns_la_SOURCES = dns.c utils_dns.c utils_dns.h
+@BUILD_PLUGIN_DNS_TRUE@dns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_DNS_TRUE@dns_la_LIBADD = -lpcap -lpthread
+@BUILD_PLUGIN_DRBD_TRUE@drbd_la_SOURCES = drbd.c
+@BUILD_PLUGIN_DRBD_TRUE@drbd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_DRBD_TRUE@drbd_la_LIBADD = -lpthread
+@BUILD_PLUGIN_EMAIL_TRUE@email_la_SOURCES = email.c
+@BUILD_PLUGIN_EMAIL_TRUE@email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_EMAIL_TRUE@email_la_LIBADD = -lpthread
+@BUILD_PLUGIN_ENTROPY_TRUE@entropy_la_SOURCES = entropy.c
+@BUILD_PLUGIN_ENTROPY_TRUE@entropy_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_EXEC_TRUE@exec_la_SOURCES = exec.c \
+@BUILD_PLUGIN_EXEC_TRUE@                 utils_cmd_putnotif.c utils_cmd_putnotif.h \
+@BUILD_PLUGIN_EXEC_TRUE@                 utils_cmd_putval.c utils_cmd_putval.h \
+@BUILD_PLUGIN_EXEC_TRUE@                 utils_parse_option.h utils_parse_option.c
+
+@BUILD_PLUGIN_EXEC_TRUE@exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_EXEC_TRUE@exec_la_LIBADD = -lpthread
+@BUILD_PLUGIN_ETHSTAT_TRUE@ethstat_la_SOURCES = ethstat.c
+@BUILD_PLUGIN_ETHSTAT_TRUE@ethstat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_FHCOUNT_TRUE@fhcount_la_SOURCES = fhcount.c
+@BUILD_PLUGIN_FHCOUNT_TRUE@fhcount_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_FILECOUNT_TRUE@filecount_la_SOURCES = filecount.c
+@BUILD_PLUGIN_FILECOUNT_TRUE@filecount_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_GMOND_TRUE@gmond_la_SOURCES = gmond.c
+@BUILD_PLUGIN_GMOND_TRUE@gmond_la_CPPFLAGS = $(AM_CPPFLAGS) $(GANGLIA_CPPFLAGS)
+@BUILD_PLUGIN_GMOND_TRUE@gmond_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(GANGLIA_LDFLAGS)
+@BUILD_PLUGIN_GMOND_TRUE@gmond_la_LIBADD = $(GANGLIA_LIBS)
+@BUILD_PLUGIN_HDDTEMP_TRUE@hddtemp_la_SOURCES = hddtemp.c
+@BUILD_PLUGIN_HDDTEMP_TRUE@hddtemp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_HDDTEMP_TRUE@hddtemp_la_LIBADD = $(am__append_65)
+@BUILD_PLUGIN_INTERFACE_TRUE@interface_la_SOURCES = interface.c \
+@BUILD_PLUGIN_INTERFACE_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_INTERFACE_TRUE@interface_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(am__append_67)
+@BUILD_PLUGIN_INTERFACE_TRUE@interface_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_INTERFACE_TRUE@interface_la_LIBADD = $(am__append_68) \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(am__append_69) $(am__append_70) \
+@BUILD_PLUGIN_INTERFACE_TRUE@  $(am__append_71)
+@BUILD_PLUGIN_IPC_TRUE@ipc_la_SOURCES = ipc.c
+@BUILD_PLUGIN_IPC_TRUE@ipc_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_IPC_TRUE@ipc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_IPTABLES_TRUE@iptables_la_SOURCES = iptables.c
+@BUILD_PLUGIN_IPTABLES_TRUE@iptables_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBIPTC_CPPFLAGS)
+@BUILD_PLUGIN_IPTABLES_TRUE@iptables_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_IPTABLES_TRUE@iptables_la_LIBADD = $(BUILD_WITH_LIBIPTC_LDFLAGS)
+@BUILD_PLUGIN_IPMI_TRUE@ipmi_la_SOURCES = ipmi.c \
+@BUILD_PLUGIN_IPMI_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_IPMI_TRUE@ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
+@BUILD_PLUGIN_IPMI_TRUE@ipmi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_IPMI_TRUE@ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
+@BUILD_PLUGIN_IPVS_TRUE@ipvs_la_SOURCES = ipvs.c
+@BUILD_PLUGIN_IPVS_TRUE@@IP_VS_H_NEEDS_KERNEL_CFLAGS_TRUE@ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
+@BUILD_PLUGIN_IPVS_TRUE@ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_IRQ_TRUE@irq_la_SOURCES = irq.c \
+@BUILD_PLUGIN_IRQ_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_IRQ_TRUE@irq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_JAVA_TRUE@java_la_SOURCES = java.c
+@BUILD_PLUGIN_JAVA_TRUE@java_la_CPPFLAGS = $(AM_CPPFLAGS) $(JAVA_CPPFLAGS)
+@BUILD_PLUGIN_JAVA_TRUE@java_la_CFLAGS = $(AM_CFLAGS) $(JAVA_CFLAGS)
+@BUILD_PLUGIN_JAVA_TRUE@java_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(JAVA_LDFLAGS)
+@BUILD_PLUGIN_JAVA_TRUE@java_la_LIBADD = $(JAVA_LIBS)
+@BUILD_PLUGIN_LOAD_TRUE@load_la_SOURCES = load.c
+@BUILD_PLUGIN_LOAD_TRUE@load_la_CFLAGS = $(AM_CFLAGS) $(am__append_79)
+@BUILD_PLUGIN_LOAD_TRUE@load_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_LOAD_TRUE@load_la_LIBADD = $(am__append_80) \
+@BUILD_PLUGIN_LOAD_TRUE@       $(am__append_81)
+@BUILD_PLUGIN_LOGFILE_TRUE@logfile_la_SOURCES = logfile.c
+@BUILD_PLUGIN_LOGFILE_TRUE@logfile_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@log_logstash_la_SOURCES = log_logstash.c
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@log_logstash_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@log_logstash_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+@BUILD_PLUGIN_LOG_LOGSTASH_TRUE@log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+@BUILD_PLUGIN_LPAR_TRUE@lpar_la_SOURCES = lpar.c
+@BUILD_PLUGIN_LPAR_TRUE@lpar_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_LPAR_TRUE@lpar_la_LIBADD = -lperfstat
+@BUILD_PLUGIN_LVM_TRUE@lvm_la_SOURCES = lvm.c
+@BUILD_PLUGIN_LVM_TRUE@lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_LVM_TRUE@lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
+@BUILD_PLUGIN_MADWIFI_TRUE@madwifi_la_SOURCES = madwifi.c madwifi.h \
+@BUILD_PLUGIN_MADWIFI_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_MADWIFI_TRUE@madwifi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@match_empty_counter_la_SOURCES = match_empty_counter.c
+@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@match_empty_counter_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MATCH_HASHED_TRUE@match_hashed_la_SOURCES = match_hashed.c
+@BUILD_PLUGIN_MATCH_HASHED_TRUE@match_hashed_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MATCH_REGEX_TRUE@match_regex_la_SOURCES = match_regex.c
+@BUILD_PLUGIN_MATCH_REGEX_TRUE@match_regex_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@match_timediff_la_SOURCES = match_timediff.c
+@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@match_timediff_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MATCH_VALUE_TRUE@match_value_la_SOURCES = match_value.c
+@BUILD_PLUGIN_MATCH_VALUE_TRUE@match_value_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MBMON_TRUE@mbmon_la_SOURCES = mbmon.c
+@BUILD_PLUGIN_MBMON_TRUE@mbmon_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MBMON_TRUE@mbmon_la_LIBADD = $(am__append_93)
+@BUILD_PLUGIN_MD_TRUE@md_la_SOURCES = md.c \
+@BUILD_PLUGIN_MD_TRUE@         utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_MD_TRUE@md_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MEMCACHEC_TRUE@memcachec_la_SOURCES = memcachec.c
+@BUILD_PLUGIN_MEMCACHEC_TRUE@memcachec_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMEMCACHED_LDFLAGS)
+@BUILD_PLUGIN_MEMCACHEC_TRUE@memcachec_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMEMCACHED_CPPFLAGS)
+@BUILD_PLUGIN_MEMCACHEC_TRUE@memcachec_la_LIBADD = $(BUILD_WITH_LIBMEMCACHED_LIBS)
+@BUILD_PLUGIN_MEMCACHED_TRUE@memcached_la_SOURCES = memcached.c
+@BUILD_PLUGIN_MEMCACHED_TRUE@memcached_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MEMCACHED_TRUE@memcached_la_LIBADD = $(am__append_97)
+@BUILD_PLUGIN_MEMORY_TRUE@memory_la_SOURCES = memory.c
+@BUILD_PLUGIN_MEMORY_TRUE@memory_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_MEMORY_TRUE@     $(am__append_101)
+@BUILD_PLUGIN_MEMORY_TRUE@memory_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MEMORY_TRUE@memory_la_LIBADD = $(am__append_99) \
+@BUILD_PLUGIN_MEMORY_TRUE@     $(am__append_100) $(am__append_102) \
+@BUILD_PLUGIN_MEMORY_TRUE@     $(am__append_103)
+@BUILD_PLUGIN_MIC_TRUE@mic_la_SOURCES = mic.c \
+@BUILD_PLUGIN_MIC_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_MIC_TRUE@mic_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_MIC_LIBPATH)
+@BUILD_PLUGIN_MIC_TRUE@mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
+@BUILD_PLUGIN_MIC_TRUE@mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD)
+@BUILD_PLUGIN_MODBUS_TRUE@modbus_la_SOURCES = modbus.c
+@BUILD_PLUGIN_MODBUS_TRUE@modbus_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MODBUS_TRUE@modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS)
+@BUILD_PLUGIN_MODBUS_TRUE@modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
+@BUILD_PLUGIN_MULTIMETER_TRUE@multimeter_la_SOURCES = multimeter.c
+@BUILD_PLUGIN_MULTIMETER_TRUE@multimeter_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MYSQL_TRUE@mysql_la_SOURCES = mysql.c
+@BUILD_PLUGIN_MYSQL_TRUE@mysql_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_MYSQL_TRUE@mysql_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_MYSQL_TRUE@      $(am__append_108)
+@BUILD_PLUGIN_MYSQL_TRUE@mysql_la_LIBADD = $(am__append_109)
+@BUILD_PLUGIN_NETAPP_TRUE@netapp_la_SOURCES = netapp.c \
+@BUILD_PLUGIN_NETAPP_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_NETAPP_TRUE@netapp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNETAPP_CPPFLAGS)
+@BUILD_PLUGIN_NETAPP_TRUE@netapp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBNETAPP_LDFLAGS)
+@BUILD_PLUGIN_NETAPP_TRUE@netapp_la_LIBADD = $(LIBNETAPP_LIBS)
+@BUILD_PLUGIN_NETLINK_TRUE@netlink_la_SOURCES = netlink.c
+@BUILD_PLUGIN_NETLINK_TRUE@netlink_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NETLINK_TRUE@netlink_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMNL_CFLAGS)
+@BUILD_PLUGIN_NETLINK_TRUE@netlink_la_LIBADD = $(BUILD_WITH_LIBMNL_LIBS)
+@BUILD_PLUGIN_NETWORK_TRUE@network_la_SOURCES = network.c network.h \
+@BUILD_PLUGIN_NETWORK_TRUE@                 utils_fbhash.c utils_fbhash.h
+
+@BUILD_PLUGIN_NETWORK_TRUE@network_la_CPPFLAGS = $(AM_CPPFLAGS) \
+@BUILD_PLUGIN_NETWORK_TRUE@    $(am__append_114)
+@BUILD_PLUGIN_NETWORK_TRUE@network_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
+@BUILD_PLUGIN_NETWORK_TRUE@    $(am__append_115)
+@BUILD_PLUGIN_NETWORK_TRUE@network_la_LIBADD = -lpthread \
+@BUILD_PLUGIN_NETWORK_TRUE@    $(am__append_113) $(am__append_116)
+@BUILD_PLUGIN_NFS_TRUE@nfs_la_SOURCES = nfs.c
+@BUILD_PLUGIN_NFS_TRUE@nfs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_FSCACHE_TRUE@fscache_la_SOURCES = fscache.c
+@BUILD_PLUGIN_FSCACHE_TRUE@fscache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NGINX_TRUE@nginx_la_SOURCES = nginx.c
+@BUILD_PLUGIN_NGINX_TRUE@nginx_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_NGINX_TRUE@      $(am__append_120)
+@BUILD_PLUGIN_NGINX_TRUE@nginx_la_LIBADD = $(am__append_121)
+@BUILD_PLUGIN_NGINX_TRUE@nginx_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@notify_desktop_la_SOURCES = notify_desktop.c
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@notify_desktop_la_CFLAGS = $(AM_CFLAGS) $(LIBNOTIFY_CFLAGS)
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@notify_desktop_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@notify_desktop_la_LIBADD = $(LIBNOTIFY_LIBS)
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@notify_email_la_SOURCES = notify_email.c
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread
+@BUILD_PLUGIN_NTPD_TRUE@ntpd_la_SOURCES = ntpd.c
+@BUILD_PLUGIN_NTPD_TRUE@ntpd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NTPD_TRUE@ntpd_la_LIBADD = $(am__append_125)
+@BUILD_PLUGIN_NUMA_TRUE@numa_la_SOURCES = numa.c
+@BUILD_PLUGIN_NUMA_TRUE@numa_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NUT_TRUE@nut_la_SOURCES = nut.c
+@BUILD_PLUGIN_NUT_TRUE@nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
+@BUILD_PLUGIN_NUT_TRUE@nut_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_NUT_TRUE@nut_la_LIBADD = -lpthread $(BUILD_WITH_LIBUPSCLIENT_LIBS)
+@BUILD_PLUGIN_OLSRD_TRUE@olsrd_la_SOURCES = olsrd.c
+@BUILD_PLUGIN_OLSRD_TRUE@olsrd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_OLSRD_TRUE@olsrd_la_LIBADD = $(am__append_129)
+@BUILD_PLUGIN_ONEWIRE_TRUE@onewire_la_SOURCES = onewire.c \
+@BUILD_PLUGIN_ONEWIRE_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_ONEWIRE_TRUE@onewire_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_ONEWIRE_TRUE@onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
+@BUILD_PLUGIN_ONEWIRE_TRUE@onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
+@BUILD_PLUGIN_ONEWIRE_TRUE@onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_OPENLDAP_TRUE@openldap_la_SOURCES = openldap.c
+@BUILD_PLUGIN_OPENLDAP_TRUE@openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS)
+@BUILD_PLUGIN_OPENLDAP_TRUE@openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+@BUILD_PLUGIN_OPENLDAP_TRUE@openldap_la_LIBADD = -lldap
+@BUILD_PLUGIN_OPENVPN_TRUE@openvpn_la_SOURCES = openvpn.c
+@BUILD_PLUGIN_OPENVPN_TRUE@openvpn_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_OPENVPN_TRUE@openvpn_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_ORACLE_TRUE@oracle_la_SOURCES = oracle.c \
+@BUILD_PLUGIN_ORACLE_TRUE@     utils_db_query.c utils_db_query.h
+
+@BUILD_PLUGIN_ORACLE_TRUE@oracle_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_ORACLE_TRUE@oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CFLAGS)
+@BUILD_PLUGIN_ORACLE_TRUE@oracle_la_LIBADD = $(BUILD_WITH_ORACLE_LIBS)
+@BUILD_PLUGIN_ORACLE_TRUE@oracle_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_PERL_TRUE@perl_la_SOURCES = perl.c
+# Despite C99 providing the "bool" type thru stdbool.h, Perl defines its own
+# version of that type if HAS_BOOL is not defined... *sigh*
+@BUILD_PLUGIN_PERL_TRUE@perl_la_CPPFLAGS = $(AM_CPPFLAGS) -DHAS_BOOL=1
+@BUILD_PLUGIN_PERL_TRUE@perl_la_CFLAGS = $(AM_CFLAGS) $(PERL_CFLAGS) \
+@BUILD_PLUGIN_PERL_TRUE@       -DXS_VERSION=\"$(VERSION)\" \
+@BUILD_PLUGIN_PERL_TRUE@       -DVERSION=\"$(VERSION)\" \
+@BUILD_PLUGIN_PERL_TRUE@       $(am__append_135)
+@BUILD_PLUGIN_PERL_TRUE@perl_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
+@BUILD_PLUGIN_PERL_TRUE@               $(PERL_LDFLAGS)
+
+@BUILD_PLUGIN_PERL_TRUE@perl_la_LIBADD = $(PERL_LIBS)
+@BUILD_PLUGIN_PF_TRUE@pf_la_SOURCES = pf.c
+@BUILD_PLUGIN_PF_TRUE@pf_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_PINBA_TRUE@pinba_la_SOURCES = pinba.c
+@BUILD_PLUGIN_PINBA_TRUE@nodist_pinba_la_SOURCES = pinba.pb-c.c pinba.pb-c.h
+@BUILD_PLUGIN_PINBA_TRUE@pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_PINBA_TRUE@pinba_la_LIBADD = -lprotobuf-c
+@BUILD_PLUGIN_PING_TRUE@ping_la_SOURCES = ping.c
+@BUILD_PLUGIN_PING_TRUE@ping_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOPING_CPPFLAGS)
+@BUILD_PLUGIN_PING_TRUE@ping_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOPING_LDFLAGS)
+@BUILD_PLUGIN_PING_TRUE@ping_la_LIBADD = -loping -lm
+@BUILD_PLUGIN_POSTGRESQL_TRUE@postgresql_la_SOURCES = postgresql.c \
+@BUILD_PLUGIN_POSTGRESQL_TRUE@          utils_db_query.c utils_db_query.h
+
+@BUILD_PLUGIN_POSTGRESQL_TRUE@postgresql_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPQ_CPPFLAGS)
+@BUILD_PLUGIN_POSTGRESQL_TRUE@postgresql_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
+@BUILD_PLUGIN_POSTGRESQL_TRUE@         $(BUILD_WITH_LIBPQ_LDFLAGS)
+
+@BUILD_PLUGIN_POSTGRESQL_TRUE@postgresql_la_LIBADD = -lpq
+@BUILD_PLUGIN_POWERDNS_TRUE@powerdns_la_SOURCES = powerdns.c
+@BUILD_PLUGIN_POWERDNS_TRUE@powerdns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_PYTHON_TRUE@python_la_SOURCES = python.c pyconfig.c pyvalues.c cpython.h
+@BUILD_PLUGIN_PYTHON_TRUE@python_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_PYTHON_CPPFLAGS)
+@BUILD_PLUGIN_PYTHON_TRUE@python_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_PYTHON_TRUE@     $(am__append_142)
+@BUILD_PLUGIN_PYTHON_TRUE@python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_PYTHON_LDFLAGS)
+@BUILD_PLUGIN_PYTHON_TRUE@python_la_LIBADD = $(BUILD_WITH_PYTHON_LIBS)
+@BUILD_PLUGIN_PROCESSES_TRUE@processes_la_SOURCES = processes.c
+@BUILD_PLUGIN_PROCESSES_TRUE@processes_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_PROCESSES_TRUE@processes_la_LIBADD = $(am__append_144)
+@BUILD_PLUGIN_PROTOCOLS_TRUE@protocols_la_SOURCES = protocols.c \
+@BUILD_PLUGIN_PROTOCOLS_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_PROTOCOLS_TRUE@protocols_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_REDIS_TRUE@redis_la_SOURCES = redis.c
+@BUILD_PLUGIN_REDIS_TRUE@redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
+@BUILD_PLUGIN_REDIS_TRUE@redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+@BUILD_PLUGIN_REDIS_TRUE@redis_la_LIBADD = -lhiredis
+@BUILD_PLUGIN_ROUTEROS_TRUE@routeros_la_SOURCES = routeros.c
+@BUILD_PLUGIN_ROUTEROS_TRUE@routeros_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBROUTEROS_CPPFLAGS)
+@BUILD_PLUGIN_ROUTEROS_TRUE@routeros_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBROUTEROS_LDFLAGS)
+@BUILD_PLUGIN_ROUTEROS_TRUE@routeros_la_LIBADD = -lrouteros
+@BUILD_PLUGIN_RRDCACHED_TRUE@rrdcached_la_SOURCES = rrdcached.c utils_rrdcreate.c utils_rrdcreate.h
+@BUILD_PLUGIN_RRDCACHED_TRUE@rrdcached_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_RRDCACHED_TRUE@rrdcached_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
+@BUILD_PLUGIN_RRDCACHED_TRUE@rrdcached_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
+@BUILD_PLUGIN_RRDTOOL_TRUE@rrdtool_la_SOURCES = rrdtool.c utils_rrdcreate.c utils_rrdcreate.h
+@BUILD_PLUGIN_RRDTOOL_TRUE@rrdtool_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_RRDTOOL_TRUE@rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
+@BUILD_PLUGIN_RRDTOOL_TRUE@rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
+@BUILD_PLUGIN_SENSORS_TRUE@sensors_la_SOURCES = sensors.c \
+@BUILD_PLUGIN_SENSORS_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_SENSORS_TRUE@sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
+@BUILD_PLUGIN_SENSORS_TRUE@sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSENSORS_LDFLAGS)
+@BUILD_PLUGIN_SENSORS_TRUE@sensors_la_LIBADD = -lsensors
+@BUILD_PLUGIN_SERIAL_TRUE@serial_la_SOURCES = serial.c
+@BUILD_PLUGIN_SERIAL_TRUE@serial_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_SIGROK_TRUE@sigrok_la_SOURCES = sigrok.c
+@BUILD_PLUGIN_SIGROK_TRUE@sigrok_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSIGROK_CFLAGS)
+@BUILD_PLUGIN_SIGROK_TRUE@sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSIGROK_LDFLAGS)
+@BUILD_PLUGIN_SIGROK_TRUE@sigrok_la_LIBADD = -lsigrok
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@smart_la_SOURCES = smart.c \
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@                utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS)
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS)
+@BUILD_PLUGIN_SMART_TRUE@@BUILD_WITH_LIBUDEV_TRUE@smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev
+@BUILD_PLUGIN_SNMP_TRUE@snmp_la_SOURCES = snmp.c
+@BUILD_PLUGIN_SNMP_TRUE@snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_SNMP_TRUE@snmp_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_SNMP_TRUE@       $(am__append_155)
+@BUILD_PLUGIN_SNMP_TRUE@snmp_la_LIBADD = $(am__append_156) \
+@BUILD_PLUGIN_SNMP_TRUE@       $(am__append_157)
+@BUILD_PLUGIN_STATSD_TRUE@statsd_la_SOURCES = statsd.c \
+@BUILD_PLUGIN_STATSD_TRUE@                    utils_latency.h utils_latency.c
+
+@BUILD_PLUGIN_STATSD_TRUE@statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_STATSD_TRUE@statsd_la_LIBADD = -lpthread
+@BUILD_PLUGIN_SWAP_TRUE@swap_la_SOURCES = swap.c
+@BUILD_PLUGIN_SWAP_TRUE@swap_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_SWAP_TRUE@       $(am__append_163)
+@BUILD_PLUGIN_SWAP_TRUE@swap_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_SWAP_TRUE@swap_la_LIBADD = $(am__append_160) \
+@BUILD_PLUGIN_SWAP_TRUE@       $(am__append_161) $(am__append_162) \
+@BUILD_PLUGIN_SWAP_TRUE@       $(am__append_164) $(am__append_165)
+@BUILD_PLUGIN_SYSLOG_TRUE@syslog_la_SOURCES = syslog.c
+@BUILD_PLUGIN_SYSLOG_TRUE@syslog_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TABLE_TRUE@table_la_SOURCES = table.c
+@BUILD_PLUGIN_TABLE_TRUE@table_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TAIL_TRUE@tail_la_SOURCES = tail.c
+@BUILD_PLUGIN_TAIL_TRUE@tail_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TAIL_CSV_TRUE@tail_csv_la_SOURCES = tail_csv.c
+@BUILD_PLUGIN_TAIL_CSV_TRUE@tail_csv_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TAPE_TRUE@tape_la_SOURCES = tape.c
+@BUILD_PLUGIN_TAPE_TRUE@tape_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TAPE_TRUE@tape_la_LIBADD = -lkstat -ldevinfo
+@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@target_notification_la_SOURCES = target_notification.c
+@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@target_notification_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TARGET_REPLACE_TRUE@target_replace_la_SOURCES = target_replace.c
+@BUILD_PLUGIN_TARGET_REPLACE_TRUE@target_replace_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TARGET_SCALE_TRUE@target_scale_la_SOURCES = target_scale.c
+@BUILD_PLUGIN_TARGET_SCALE_TRUE@target_scale_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TARGET_SET_TRUE@target_set_la_SOURCES = target_set.c
+@BUILD_PLUGIN_TARGET_SET_TRUE@target_set_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@target_v5upgrade_la_SOURCES = target_v5upgrade.c
+@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@target_v5upgrade_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TCPCONNS_TRUE@tcpconns_la_SOURCES = tcpconns.c
+@BUILD_PLUGIN_TCPCONNS_TRUE@tcpconns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TCPCONNS_TRUE@tcpconns_la_LIBADD = $(am__append_177)
+@BUILD_PLUGIN_TEAMSPEAK2_TRUE@teamspeak2_la_SOURCES = teamspeak2.c
+@BUILD_PLUGIN_TEAMSPEAK2_TRUE@teamspeak2_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TED_TRUE@ted_la_SOURCES = ted.c
+@BUILD_PLUGIN_TED_TRUE@ted_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_THERMAL_TRUE@thermal_la_SOURCES = thermal.c \
+@BUILD_PLUGIN_THERMAL_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_THERMAL_TRUE@thermal_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_THRESHOLD_TRUE@threshold_la_SOURCES = threshold.c
+@BUILD_PLUGIN_THRESHOLD_TRUE@threshold_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@tokyotyrant_la_SOURCES = tokyotyrant.c
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@tokyotyrant_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@tokyotyrant_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@tokyotyrant_la_LIBADD = $(BUILD_WITH_LIBTOKYOTYRANT_LIBS) \
+@BUILD_PLUGIN_TOKYOTYRANT_TRUE@        $(am__append_183)
+@BUILD_PLUGIN_TURBOSTAT_TRUE@turbostat_la_SOURCES = turbostat.c
+@BUILD_PLUGIN_TURBOSTAT_TRUE@turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_UNIXSOCK_TRUE@unixsock_la_SOURCES = unixsock.c \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@                 utils_cmd_flush.h utils_cmd_flush.c \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@                 utils_cmd_getval.h utils_cmd_getval.c \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@                 utils_cmd_getthreshold.h utils_cmd_getthreshold.c \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@                 utils_cmd_listval.h utils_cmd_listval.c \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@                 utils_cmd_putval.h utils_cmd_putval.c \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@                 utils_cmd_putnotif.h utils_cmd_putnotif.c \
+@BUILD_PLUGIN_UNIXSOCK_TRUE@                 utils_parse_option.h utils_parse_option.c
+
+@BUILD_PLUGIN_UNIXSOCK_TRUE@unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_UNIXSOCK_TRUE@unixsock_la_LIBADD = -lpthread
+@BUILD_PLUGIN_UPTIME_TRUE@uptime_la_SOURCES = uptime.c
+@BUILD_PLUGIN_UPTIME_TRUE@uptime_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_UPTIME_TRUE@uptime_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_UPTIME_TRUE@uptime_la_LIBADD = $(am__append_187) \
+@BUILD_PLUGIN_UPTIME_TRUE@     $(am__append_188)
+@BUILD_PLUGIN_USERS_TRUE@users_la_SOURCES = users.c
+@BUILD_PLUGIN_USERS_TRUE@users_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_USERS_TRUE@      $(am__append_190)
+@BUILD_PLUGIN_USERS_TRUE@users_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_USERS_TRUE@users_la_LIBADD = $(am__append_191)
+@BUILD_PLUGIN_UUID_TRUE@uuid_la_SOURCES = uuid.c
+@BUILD_PLUGIN_UUID_TRUE@uuid_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHAL_CFLAGS)
+@BUILD_PLUGIN_UUID_TRUE@uuid_la_LIBADD = $(BUILD_WITH_LIBHAL_LIBS)
+@BUILD_PLUGIN_UUID_TRUE@uuid_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_VARNISH_TRUE@varnish_la_SOURCES = varnish.c
+@BUILD_PLUGIN_VARNISH_TRUE@varnish_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_VARNISH_TRUE@varnish_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBVARNISH_CFLAGS)
+@BUILD_PLUGIN_VARNISH_TRUE@varnish_la_LIBADD = $(BUILD_WITH_LIBVARNISH_LIBS)
+@BUILD_PLUGIN_VIRT_TRUE@virt_la_SOURCES = virt.c \
+@BUILD_PLUGIN_VIRT_TRUE@                 utils_ignorelist.c utils_ignorelist.h
+
+@BUILD_PLUGIN_VIRT_TRUE@virt_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_VIRT_TRUE@               $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
+
+@BUILD_PLUGIN_VIRT_TRUE@virt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
+@BUILD_PLUGIN_VIRT_TRUE@virt_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_VMEM_TRUE@vmem_la_SOURCES = vmem.c
+@BUILD_PLUGIN_VMEM_TRUE@vmem_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_VSERVER_TRUE@vserver_la_SOURCES = vserver.c
+@BUILD_PLUGIN_VSERVER_TRUE@vserver_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_WIRELESS_TRUE@wireless_la_SOURCES = wireless.c
+@BUILD_PLUGIN_WIRELESS_TRUE@wireless_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@write_graphite_la_SOURCES = write_graphite.c \
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@                        utils_format_graphite.c utils_format_graphite.h \
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@                        utils_format_json.c utils_format_json.h
+
+@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@write_graphite_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@write_http_la_SOURCES = write_http.c \
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@                 utils_format_json.c utils_format_json.h
+
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@write_http_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@write_http_la_CFLAGS = $(AM_CFLAGS) \
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@ $(am__append_200)
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@write_http_la_LIBADD =  \
+@BUILD_PLUGIN_WRITE_HTTP_TRUE@ $(am__append_201)
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@write_kafka_la_SOURCES = write_kafka.c \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@                        utils_format_graphite.c utils_format_graphite.h \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@                        utils_format_json.c utils_format_json.h \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@                        utils_cmd_putval.c utils_cmd_putval.h \
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@                        utils_crc32.c utils_crc32.h
+
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@write_kafka_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRDKAFKA_CPPFLAGS)
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@write_kafka_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
+@BUILD_PLUGIN_WRITE_KAFKA_TRUE@write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS)
+@BUILD_PLUGIN_WRITE_LOG_TRUE@write_log_la_SOURCES = write_log.c \
+@BUILD_PLUGIN_WRITE_LOG_TRUE@                        utils_format_graphite.c utils_format_graphite.h
+
+@BUILD_PLUGIN_WRITE_LOG_TRUE@write_log_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@write_mongodb_la_SOURCES = write_mongodb.c
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@write_mongodb_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMONGOC_CPPFLAGS)
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@write_mongodb_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMONGOC_LDFLAGS)
+@BUILD_PLUGIN_WRITE_MONGODB_TRUE@write_mongodb_la_LIBADD = -lmongoc
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@write_redis_la_SOURCES = write_redis.c
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+@BUILD_PLUGIN_WRITE_REDIS_TRUE@write_redis_la_LIBADD = -lhiredis
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@write_riemann_la_SOURCES = write_riemann.c write_riemann_threshold.c
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@nodist_write_riemann_la_SOURCES = riemann.pb-c.c riemann.pb-c.h
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@write_riemann_la_LIBADD = -lprotobuf-c
+@BUILD_PLUGIN_WRITE_SENSU_TRUE@write_sensu_la_SOURCES = write_sensu.c
+@BUILD_PLUGIN_WRITE_SENSU_TRUE@write_sensu_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_WRITE_TSDB_TRUE@write_tsdb_la_SOURCES = write_tsdb.c
+@BUILD_PLUGIN_WRITE_TSDB_TRUE@write_tsdb_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_XMMS_TRUE@xmms_la_SOURCES = xmms.c
+@BUILD_PLUGIN_XMMS_TRUE@xmms_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBXMMS_CFLAGS)
+@BUILD_PLUGIN_XMMS_TRUE@xmms_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+@BUILD_PLUGIN_XMMS_TRUE@xmms_la_LIBADD = $(BUILD_WITH_LIBXMMS_LIBS)
+@BUILD_PLUGIN_ZFS_ARC_TRUE@zfs_arc_la_SOURCES = zfs_arc.c
+@BUILD_PLUGIN_ZFS_ARC_TRUE@zfs_arc_la_CFLAGS = $(AM_CFLAGS)
+@BUILD_PLUGIN_ZFS_ARC_TRUE@zfs_arc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+# zfs_arc requires no library on linux
+# solaris
+@BUILD_FREEBSD_FALSE@@BUILD_LINUX_FALSE@@BUILD_PLUGIN_ZFS_ARC_TRUE@zfs_arc_la_LIBADD = -lkstat
+@BUILD_FREEBSD_TRUE@@BUILD_PLUGIN_ZFS_ARC_TRUE@zfs_arc_la_LIBADD = -lm
+@BUILD_PLUGIN_ZOOKEEPER_TRUE@zookeeper_la_SOURCES = zookeeper.c
+@BUILD_PLUGIN_ZOOKEEPER_TRUE@zookeeper_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+dist_man_MANS = collectd.1 \
+               collectd.conf.5 \
+               collectd-email.5 \
+               collectd-exec.5 \
+               collectdctl.1 \
+               collectd-java.5 \
+               collectdmon.1 \
+               collectd-nagios.1 \
+               collectd-perl.5 \
+               collectd-python.5 \
+               collectd-snmp.5 \
+               collectd-tg.1 \
+               collectd-threshold.5 \
+               collectd-unixsock.5 \
+               types.db.5
+
+
+#collectd_1_SOURCES = collectd.pod
+
+# Protocol buffer for the "pinba" plugin.
+
+# Protocol buffer for the "write_riemann" plugin.
+EXTRA_DIST = types.db collectd.conf.pod collectd-email.pod \
+       collectd-exec.pod collectdctl.pod collectd-java.pod \
+       collectdmon.pod collectd-nagios.pod collectd-perl.pod \
+       collectd-python.pod collectd.pod collectd-snmp.pod \
+       collectd-tg.pod collectd-threshold.pod collectd-unixsock.pod \
+       postgresql_default.conf types.db.pod pinba.proto riemann.proto
+test_utils_mount_SOURCES = utils_mount_test.c testing.h
+test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
+test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
+all: $(BUILT_SOURCES) config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .1 .5 .c .lo .log .o .obj .pod .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+       @test -f $@ || rm -f stamp-h1
+       @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+       @rm -f stamp-h1
+       cd $(top_builddir) && $(SHELL) ./config.status src/config.h
+$(srcdir)/config.h.in:  $(am__configure_deps) 
+       ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+       rm -f stamp-h1
+       touch $@
+
+distclean-hdr:
+       -rm -f config.h stamp-h1
+collectd.conf: $(top_builddir)/config.status $(srcdir)/collectd.conf.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+       @list='$(noinst_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
+
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+       list2=; for p in $$list; do \
+         if test -f $$p; then \
+           list2="$$list2 $$p"; \
+         else :; fi; \
+       done; \
+       test -z "$$list2" || { \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \
+       }
+
+uninstall-pkglibLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+       for p in $$list; do \
+         $(am__strip_dir) \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
+       done
+
+clean-pkglibLTLIBRARIES:
+       -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+       @list='$(pkglib_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
+
+aggregation.la: $(aggregation_la_OBJECTS) $(aggregation_la_DEPENDENCIES) $(EXTRA_aggregation_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(aggregation_la_LINK) $(am_aggregation_la_rpath) $(aggregation_la_OBJECTS) $(aggregation_la_LIBADD) $(LIBS)
+
+amqp.la: $(amqp_la_OBJECTS) $(amqp_la_DEPENDENCIES) $(EXTRA_amqp_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(amqp_la_LINK) $(am_amqp_la_rpath) $(amqp_la_OBJECTS) $(amqp_la_LIBADD) $(LIBS)
+
+apache.la: $(apache_la_OBJECTS) $(apache_la_DEPENDENCIES) $(EXTRA_apache_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(apache_la_LINK) $(am_apache_la_rpath) $(apache_la_OBJECTS) $(apache_la_LIBADD) $(LIBS)
+
+apcups.la: $(apcups_la_OBJECTS) $(apcups_la_DEPENDENCIES) $(EXTRA_apcups_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(apcups_la_LINK) $(am_apcups_la_rpath) $(apcups_la_OBJECTS) $(apcups_la_LIBADD) $(LIBS)
+
+apple_sensors.la: $(apple_sensors_la_OBJECTS) $(apple_sensors_la_DEPENDENCIES) $(EXTRA_apple_sensors_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(apple_sensors_la_LINK) $(am_apple_sensors_la_rpath) $(apple_sensors_la_OBJECTS) $(apple_sensors_la_LIBADD) $(LIBS)
+
+aquaero.la: $(aquaero_la_OBJECTS) $(aquaero_la_DEPENDENCIES) $(EXTRA_aquaero_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(aquaero_la_LINK) $(am_aquaero_la_rpath) $(aquaero_la_OBJECTS) $(aquaero_la_LIBADD) $(LIBS)
+
+ascent.la: $(ascent_la_OBJECTS) $(ascent_la_DEPENDENCIES) $(EXTRA_ascent_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ascent_la_LINK) $(am_ascent_la_rpath) $(ascent_la_OBJECTS) $(ascent_la_LIBADD) $(LIBS)
+
+barometer.la: $(barometer_la_OBJECTS) $(barometer_la_DEPENDENCIES) $(EXTRA_barometer_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(barometer_la_LINK) $(am_barometer_la_rpath) $(barometer_la_OBJECTS) $(barometer_la_LIBADD) $(LIBS)
+
+battery.la: $(battery_la_OBJECTS) $(battery_la_DEPENDENCIES) $(EXTRA_battery_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(battery_la_LINK) $(am_battery_la_rpath) $(battery_la_OBJECTS) $(battery_la_LIBADD) $(LIBS)
+
+bind.la: $(bind_la_OBJECTS) $(bind_la_DEPENDENCIES) $(EXTRA_bind_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(bind_la_LINK) $(am_bind_la_rpath) $(bind_la_OBJECTS) $(bind_la_LIBADD) $(LIBS)
+
+ceph.la: $(ceph_la_OBJECTS) $(ceph_la_DEPENDENCIES) $(EXTRA_ceph_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ceph_la_LINK) $(am_ceph_la_rpath) $(ceph_la_OBJECTS) $(ceph_la_LIBADD) $(LIBS)
+
+cgroups.la: $(cgroups_la_OBJECTS) $(cgroups_la_DEPENDENCIES) $(EXTRA_cgroups_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(cgroups_la_LINK) $(am_cgroups_la_rpath) $(cgroups_la_OBJECTS) $(cgroups_la_LIBADD) $(LIBS)
+
+conntrack.la: $(conntrack_la_OBJECTS) $(conntrack_la_DEPENDENCIES) $(EXTRA_conntrack_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(conntrack_la_LINK) $(am_conntrack_la_rpath) $(conntrack_la_OBJECTS) $(conntrack_la_LIBADD) $(LIBS)
+
+contextswitch.la: $(contextswitch_la_OBJECTS) $(contextswitch_la_DEPENDENCIES) $(EXTRA_contextswitch_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(contextswitch_la_LINK) $(am_contextswitch_la_rpath) $(contextswitch_la_OBJECTS) $(contextswitch_la_LIBADD) $(LIBS)
+
+cpu.la: $(cpu_la_OBJECTS) $(cpu_la_DEPENDENCIES) $(EXTRA_cpu_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(cpu_la_LINK) $(am_cpu_la_rpath) $(cpu_la_OBJECTS) $(cpu_la_LIBADD) $(LIBS)
+
+cpufreq.la: $(cpufreq_la_OBJECTS) $(cpufreq_la_DEPENDENCIES) $(EXTRA_cpufreq_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(cpufreq_la_LINK) $(am_cpufreq_la_rpath) $(cpufreq_la_OBJECTS) $(cpufreq_la_LIBADD) $(LIBS)
+
+csv.la: $(csv_la_OBJECTS) $(csv_la_DEPENDENCIES) $(EXTRA_csv_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(csv_la_LINK) $(am_csv_la_rpath) $(csv_la_OBJECTS) $(csv_la_LIBADD) $(LIBS)
+
+curl.la: $(curl_la_OBJECTS) $(curl_la_DEPENDENCIES) $(EXTRA_curl_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(curl_la_LINK) $(am_curl_la_rpath) $(curl_la_OBJECTS) $(curl_la_LIBADD) $(LIBS)
+
+curl_json.la: $(curl_json_la_OBJECTS) $(curl_json_la_DEPENDENCIES) $(EXTRA_curl_json_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(curl_json_la_LINK) $(am_curl_json_la_rpath) $(curl_json_la_OBJECTS) $(curl_json_la_LIBADD) $(LIBS)
+
+curl_xml.la: $(curl_xml_la_OBJECTS) $(curl_xml_la_DEPENDENCIES) $(EXTRA_curl_xml_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(curl_xml_la_LINK) $(am_curl_xml_la_rpath) $(curl_xml_la_OBJECTS) $(curl_xml_la_LIBADD) $(LIBS)
+
+dbi.la: $(dbi_la_OBJECTS) $(dbi_la_DEPENDENCIES) $(EXTRA_dbi_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(dbi_la_LINK) $(am_dbi_la_rpath) $(dbi_la_OBJECTS) $(dbi_la_LIBADD) $(LIBS)
+
+df.la: $(df_la_OBJECTS) $(df_la_DEPENDENCIES) $(EXTRA_df_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(df_la_LINK) $(am_df_la_rpath) $(df_la_OBJECTS) $(df_la_LIBADD) $(LIBS)
+
+disk.la: $(disk_la_OBJECTS) $(disk_la_DEPENDENCIES) $(EXTRA_disk_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(disk_la_LINK) $(am_disk_la_rpath) $(disk_la_OBJECTS) $(disk_la_LIBADD) $(LIBS)
+
+dns.la: $(dns_la_OBJECTS) $(dns_la_DEPENDENCIES) $(EXTRA_dns_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(dns_la_LINK) $(am_dns_la_rpath) $(dns_la_OBJECTS) $(dns_la_LIBADD) $(LIBS)
+
+drbd.la: $(drbd_la_OBJECTS) $(drbd_la_DEPENDENCIES) $(EXTRA_drbd_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(drbd_la_LINK) $(am_drbd_la_rpath) $(drbd_la_OBJECTS) $(drbd_la_LIBADD) $(LIBS)
+
+email.la: $(email_la_OBJECTS) $(email_la_DEPENDENCIES) $(EXTRA_email_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(email_la_LINK) $(am_email_la_rpath) $(email_la_OBJECTS) $(email_la_LIBADD) $(LIBS)
+
+entropy.la: $(entropy_la_OBJECTS) $(entropy_la_DEPENDENCIES) $(EXTRA_entropy_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(entropy_la_LINK) $(am_entropy_la_rpath) $(entropy_la_OBJECTS) $(entropy_la_LIBADD) $(LIBS)
+
+ethstat.la: $(ethstat_la_OBJECTS) $(ethstat_la_DEPENDENCIES) $(EXTRA_ethstat_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ethstat_la_LINK) $(am_ethstat_la_rpath) $(ethstat_la_OBJECTS) $(ethstat_la_LIBADD) $(LIBS)
+
+exec.la: $(exec_la_OBJECTS) $(exec_la_DEPENDENCIES) $(EXTRA_exec_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(exec_la_LINK) $(am_exec_la_rpath) $(exec_la_OBJECTS) $(exec_la_LIBADD) $(LIBS)
+
+fhcount.la: $(fhcount_la_OBJECTS) $(fhcount_la_DEPENDENCIES) $(EXTRA_fhcount_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(fhcount_la_LINK) $(am_fhcount_la_rpath) $(fhcount_la_OBJECTS) $(fhcount_la_LIBADD) $(LIBS)
+
+filecount.la: $(filecount_la_OBJECTS) $(filecount_la_DEPENDENCIES) $(EXTRA_filecount_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(filecount_la_LINK) $(am_filecount_la_rpath) $(filecount_la_OBJECTS) $(filecount_la_LIBADD) $(LIBS)
+
+fscache.la: $(fscache_la_OBJECTS) $(fscache_la_DEPENDENCIES) $(EXTRA_fscache_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(fscache_la_LINK) $(am_fscache_la_rpath) $(fscache_la_OBJECTS) $(fscache_la_LIBADD) $(LIBS)
+
+gmond.la: $(gmond_la_OBJECTS) $(gmond_la_DEPENDENCIES) $(EXTRA_gmond_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(gmond_la_LINK) $(am_gmond_la_rpath) $(gmond_la_OBJECTS) $(gmond_la_LIBADD) $(LIBS)
+
+hddtemp.la: $(hddtemp_la_OBJECTS) $(hddtemp_la_DEPENDENCIES) $(EXTRA_hddtemp_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(hddtemp_la_LINK) $(am_hddtemp_la_rpath) $(hddtemp_la_OBJECTS) $(hddtemp_la_LIBADD) $(LIBS)
+
+interface.la: $(interface_la_OBJECTS) $(interface_la_DEPENDENCIES) $(EXTRA_interface_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(interface_la_LINK) $(am_interface_la_rpath) $(interface_la_OBJECTS) $(interface_la_LIBADD) $(LIBS)
+
+ipc.la: $(ipc_la_OBJECTS) $(ipc_la_DEPENDENCIES) $(EXTRA_ipc_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ipc_la_LINK) $(am_ipc_la_rpath) $(ipc_la_OBJECTS) $(ipc_la_LIBADD) $(LIBS)
+
+ipmi.la: $(ipmi_la_OBJECTS) $(ipmi_la_DEPENDENCIES) $(EXTRA_ipmi_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ipmi_la_LINK) $(am_ipmi_la_rpath) $(ipmi_la_OBJECTS) $(ipmi_la_LIBADD) $(LIBS)
+
+iptables.la: $(iptables_la_OBJECTS) $(iptables_la_DEPENDENCIES) $(EXTRA_iptables_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(iptables_la_LINK) $(am_iptables_la_rpath) $(iptables_la_OBJECTS) $(iptables_la_LIBADD) $(LIBS)
+
+ipvs.la: $(ipvs_la_OBJECTS) $(ipvs_la_DEPENDENCIES) $(EXTRA_ipvs_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ipvs_la_LINK) $(am_ipvs_la_rpath) $(ipvs_la_OBJECTS) $(ipvs_la_LIBADD) $(LIBS)
+
+irq.la: $(irq_la_OBJECTS) $(irq_la_DEPENDENCIES) $(EXTRA_irq_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(irq_la_LINK) $(am_irq_la_rpath) $(irq_la_OBJECTS) $(irq_la_LIBADD) $(LIBS)
+
+java.la: $(java_la_OBJECTS) $(java_la_DEPENDENCIES) $(EXTRA_java_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(java_la_LINK) $(am_java_la_rpath) $(java_la_OBJECTS) $(java_la_LIBADD) $(LIBS)
+
+liblookup.la: $(liblookup_la_OBJECTS) $(liblookup_la_DEPENDENCIES) $(EXTRA_liblookup_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(LINK)  $(liblookup_la_OBJECTS) $(liblookup_la_LIBADD) $(LIBS)
+
+libmount.la: $(libmount_la_OBJECTS) $(libmount_la_DEPENDENCIES) $(EXTRA_libmount_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(LINK)  $(libmount_la_OBJECTS) $(libmount_la_LIBADD) $(LIBS)
+
+load.la: $(load_la_OBJECTS) $(load_la_DEPENDENCIES) $(EXTRA_load_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(load_la_LINK) $(am_load_la_rpath) $(load_la_OBJECTS) $(load_la_LIBADD) $(LIBS)
+
+log_logstash.la: $(log_logstash_la_OBJECTS) $(log_logstash_la_DEPENDENCIES) $(EXTRA_log_logstash_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(log_logstash_la_LINK) $(am_log_logstash_la_rpath) $(log_logstash_la_OBJECTS) $(log_logstash_la_LIBADD) $(LIBS)
+
+logfile.la: $(logfile_la_OBJECTS) $(logfile_la_DEPENDENCIES) $(EXTRA_logfile_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(logfile_la_LINK) $(am_logfile_la_rpath) $(logfile_la_OBJECTS) $(logfile_la_LIBADD) $(LIBS)
+
+lpar.la: $(lpar_la_OBJECTS) $(lpar_la_DEPENDENCIES) $(EXTRA_lpar_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(lpar_la_LINK) $(am_lpar_la_rpath) $(lpar_la_OBJECTS) $(lpar_la_LIBADD) $(LIBS)
+
+lvm.la: $(lvm_la_OBJECTS) $(lvm_la_DEPENDENCIES) $(EXTRA_lvm_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(lvm_la_LINK) $(am_lvm_la_rpath) $(lvm_la_OBJECTS) $(lvm_la_LIBADD) $(LIBS)
+
+madwifi.la: $(madwifi_la_OBJECTS) $(madwifi_la_DEPENDENCIES) $(EXTRA_madwifi_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(madwifi_la_LINK) $(am_madwifi_la_rpath) $(madwifi_la_OBJECTS) $(madwifi_la_LIBADD) $(LIBS)
+
+match_empty_counter.la: $(match_empty_counter_la_OBJECTS) $(match_empty_counter_la_DEPENDENCIES) $(EXTRA_match_empty_counter_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(match_empty_counter_la_LINK) $(am_match_empty_counter_la_rpath) $(match_empty_counter_la_OBJECTS) $(match_empty_counter_la_LIBADD) $(LIBS)
+
+match_hashed.la: $(match_hashed_la_OBJECTS) $(match_hashed_la_DEPENDENCIES) $(EXTRA_match_hashed_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(match_hashed_la_LINK) $(am_match_hashed_la_rpath) $(match_hashed_la_OBJECTS) $(match_hashed_la_LIBADD) $(LIBS)
+
+match_regex.la: $(match_regex_la_OBJECTS) $(match_regex_la_DEPENDENCIES) $(EXTRA_match_regex_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(match_regex_la_LINK) $(am_match_regex_la_rpath) $(match_regex_la_OBJECTS) $(match_regex_la_LIBADD) $(LIBS)
+
+match_timediff.la: $(match_timediff_la_OBJECTS) $(match_timediff_la_DEPENDENCIES) $(EXTRA_match_timediff_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(match_timediff_la_LINK) $(am_match_timediff_la_rpath) $(match_timediff_la_OBJECTS) $(match_timediff_la_LIBADD) $(LIBS)
+
+match_value.la: $(match_value_la_OBJECTS) $(match_value_la_DEPENDENCIES) $(EXTRA_match_value_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(match_value_la_LINK) $(am_match_value_la_rpath) $(match_value_la_OBJECTS) $(match_value_la_LIBADD) $(LIBS)
+
+mbmon.la: $(mbmon_la_OBJECTS) $(mbmon_la_DEPENDENCIES) $(EXTRA_mbmon_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(mbmon_la_LINK) $(am_mbmon_la_rpath) $(mbmon_la_OBJECTS) $(mbmon_la_LIBADD) $(LIBS)
+
+md.la: $(md_la_OBJECTS) $(md_la_DEPENDENCIES) $(EXTRA_md_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(md_la_LINK) $(am_md_la_rpath) $(md_la_OBJECTS) $(md_la_LIBADD) $(LIBS)
+
+memcachec.la: $(memcachec_la_OBJECTS) $(memcachec_la_DEPENDENCIES) $(EXTRA_memcachec_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(memcachec_la_LINK) $(am_memcachec_la_rpath) $(memcachec_la_OBJECTS) $(memcachec_la_LIBADD) $(LIBS)
+
+memcached.la: $(memcached_la_OBJECTS) $(memcached_la_DEPENDENCIES) $(EXTRA_memcached_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(memcached_la_LINK) $(am_memcached_la_rpath) $(memcached_la_OBJECTS) $(memcached_la_LIBADD) $(LIBS)
+
+memory.la: $(memory_la_OBJECTS) $(memory_la_DEPENDENCIES) $(EXTRA_memory_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(memory_la_LINK) $(am_memory_la_rpath) $(memory_la_OBJECTS) $(memory_la_LIBADD) $(LIBS)
+
+mic.la: $(mic_la_OBJECTS) $(mic_la_DEPENDENCIES) $(EXTRA_mic_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(mic_la_LINK) $(am_mic_la_rpath) $(mic_la_OBJECTS) $(mic_la_LIBADD) $(LIBS)
+
+modbus.la: $(modbus_la_OBJECTS) $(modbus_la_DEPENDENCIES) $(EXTRA_modbus_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(modbus_la_LINK) $(am_modbus_la_rpath) $(modbus_la_OBJECTS) $(modbus_la_LIBADD) $(LIBS)
+
+multimeter.la: $(multimeter_la_OBJECTS) $(multimeter_la_DEPENDENCIES) $(EXTRA_multimeter_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(multimeter_la_LINK) $(am_multimeter_la_rpath) $(multimeter_la_OBJECTS) $(multimeter_la_LIBADD) $(LIBS)
+
+mysql.la: $(mysql_la_OBJECTS) $(mysql_la_DEPENDENCIES) $(EXTRA_mysql_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(mysql_la_LINK) $(am_mysql_la_rpath) $(mysql_la_OBJECTS) $(mysql_la_LIBADD) $(LIBS)
+
+netapp.la: $(netapp_la_OBJECTS) $(netapp_la_DEPENDENCIES) $(EXTRA_netapp_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(netapp_la_LINK) $(am_netapp_la_rpath) $(netapp_la_OBJECTS) $(netapp_la_LIBADD) $(LIBS)
+
+netlink.la: $(netlink_la_OBJECTS) $(netlink_la_DEPENDENCIES) $(EXTRA_netlink_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(netlink_la_LINK) $(am_netlink_la_rpath) $(netlink_la_OBJECTS) $(netlink_la_LIBADD) $(LIBS)
+
+network.la: $(network_la_OBJECTS) $(network_la_DEPENDENCIES) $(EXTRA_network_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(network_la_LINK) $(am_network_la_rpath) $(network_la_OBJECTS) $(network_la_LIBADD) $(LIBS)
+
+nfs.la: $(nfs_la_OBJECTS) $(nfs_la_DEPENDENCIES) $(EXTRA_nfs_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(nfs_la_LINK) $(am_nfs_la_rpath) $(nfs_la_OBJECTS) $(nfs_la_LIBADD) $(LIBS)
+
+nginx.la: $(nginx_la_OBJECTS) $(nginx_la_DEPENDENCIES) $(EXTRA_nginx_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(nginx_la_LINK) $(am_nginx_la_rpath) $(nginx_la_OBJECTS) $(nginx_la_LIBADD) $(LIBS)
+
+notify_desktop.la: $(notify_desktop_la_OBJECTS) $(notify_desktop_la_DEPENDENCIES) $(EXTRA_notify_desktop_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(notify_desktop_la_LINK) $(am_notify_desktop_la_rpath) $(notify_desktop_la_OBJECTS) $(notify_desktop_la_LIBADD) $(LIBS)
+
+notify_email.la: $(notify_email_la_OBJECTS) $(notify_email_la_DEPENDENCIES) $(EXTRA_notify_email_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(notify_email_la_LINK) $(am_notify_email_la_rpath) $(notify_email_la_OBJECTS) $(notify_email_la_LIBADD) $(LIBS)
+
+ntpd.la: $(ntpd_la_OBJECTS) $(ntpd_la_DEPENDENCIES) $(EXTRA_ntpd_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ntpd_la_LINK) $(am_ntpd_la_rpath) $(ntpd_la_OBJECTS) $(ntpd_la_LIBADD) $(LIBS)
+
+numa.la: $(numa_la_OBJECTS) $(numa_la_DEPENDENCIES) $(EXTRA_numa_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(numa_la_LINK) $(am_numa_la_rpath) $(numa_la_OBJECTS) $(numa_la_LIBADD) $(LIBS)
+
+nut.la: $(nut_la_OBJECTS) $(nut_la_DEPENDENCIES) $(EXTRA_nut_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(nut_la_LINK) $(am_nut_la_rpath) $(nut_la_OBJECTS) $(nut_la_LIBADD) $(LIBS)
+
+olsrd.la: $(olsrd_la_OBJECTS) $(olsrd_la_DEPENDENCIES) $(EXTRA_olsrd_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(olsrd_la_LINK) $(am_olsrd_la_rpath) $(olsrd_la_OBJECTS) $(olsrd_la_LIBADD) $(LIBS)
+
+onewire.la: $(onewire_la_OBJECTS) $(onewire_la_DEPENDENCIES) $(EXTRA_onewire_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(onewire_la_LINK) $(am_onewire_la_rpath) $(onewire_la_OBJECTS) $(onewire_la_LIBADD) $(LIBS)
+
+openldap.la: $(openldap_la_OBJECTS) $(openldap_la_DEPENDENCIES) $(EXTRA_openldap_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(openldap_la_LINK) $(am_openldap_la_rpath) $(openldap_la_OBJECTS) $(openldap_la_LIBADD) $(LIBS)
+
+openvpn.la: $(openvpn_la_OBJECTS) $(openvpn_la_DEPENDENCIES) $(EXTRA_openvpn_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(openvpn_la_LINK) $(am_openvpn_la_rpath) $(openvpn_la_OBJECTS) $(openvpn_la_LIBADD) $(LIBS)
+
+oracle.la: $(oracle_la_OBJECTS) $(oracle_la_DEPENDENCIES) $(EXTRA_oracle_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(oracle_la_LINK) $(am_oracle_la_rpath) $(oracle_la_OBJECTS) $(oracle_la_LIBADD) $(LIBS)
+
+perl.la: $(perl_la_OBJECTS) $(perl_la_DEPENDENCIES) $(EXTRA_perl_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(perl_la_LINK) $(am_perl_la_rpath) $(perl_la_OBJECTS) $(perl_la_LIBADD) $(LIBS)
+
+pf.la: $(pf_la_OBJECTS) $(pf_la_DEPENDENCIES) $(EXTRA_pf_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(pf_la_LINK) $(am_pf_la_rpath) $(pf_la_OBJECTS) $(pf_la_LIBADD) $(LIBS)
+
+pinba.la: $(pinba_la_OBJECTS) $(pinba_la_DEPENDENCIES) $(EXTRA_pinba_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(pinba_la_LINK) $(am_pinba_la_rpath) $(pinba_la_OBJECTS) $(pinba_la_LIBADD) $(LIBS)
+
+ping.la: $(ping_la_OBJECTS) $(ping_la_DEPENDENCIES) $(EXTRA_ping_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ping_la_LINK) $(am_ping_la_rpath) $(ping_la_OBJECTS) $(ping_la_LIBADD) $(LIBS)
+
+postgresql.la: $(postgresql_la_OBJECTS) $(postgresql_la_DEPENDENCIES) $(EXTRA_postgresql_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(postgresql_la_LINK) $(am_postgresql_la_rpath) $(postgresql_la_OBJECTS) $(postgresql_la_LIBADD) $(LIBS)
+
+powerdns.la: $(powerdns_la_OBJECTS) $(powerdns_la_DEPENDENCIES) $(EXTRA_powerdns_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(powerdns_la_LINK) $(am_powerdns_la_rpath) $(powerdns_la_OBJECTS) $(powerdns_la_LIBADD) $(LIBS)
+
+processes.la: $(processes_la_OBJECTS) $(processes_la_DEPENDENCIES) $(EXTRA_processes_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(processes_la_LINK) $(am_processes_la_rpath) $(processes_la_OBJECTS) $(processes_la_LIBADD) $(LIBS)
+
+protocols.la: $(protocols_la_OBJECTS) $(protocols_la_DEPENDENCIES) $(EXTRA_protocols_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(protocols_la_LINK) $(am_protocols_la_rpath) $(protocols_la_OBJECTS) $(protocols_la_LIBADD) $(LIBS)
+
+python.la: $(python_la_OBJECTS) $(python_la_DEPENDENCIES) $(EXTRA_python_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(python_la_LINK) $(am_python_la_rpath) $(python_la_OBJECTS) $(python_la_LIBADD) $(LIBS)
+
+redis.la: $(redis_la_OBJECTS) $(redis_la_DEPENDENCIES) $(EXTRA_redis_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(redis_la_LINK) $(am_redis_la_rpath) $(redis_la_OBJECTS) $(redis_la_LIBADD) $(LIBS)
+
+routeros.la: $(routeros_la_OBJECTS) $(routeros_la_DEPENDENCIES) $(EXTRA_routeros_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(routeros_la_LINK) $(am_routeros_la_rpath) $(routeros_la_OBJECTS) $(routeros_la_LIBADD) $(LIBS)
+
+rrdcached.la: $(rrdcached_la_OBJECTS) $(rrdcached_la_DEPENDENCIES) $(EXTRA_rrdcached_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(rrdcached_la_LINK) $(am_rrdcached_la_rpath) $(rrdcached_la_OBJECTS) $(rrdcached_la_LIBADD) $(LIBS)
+
+rrdtool.la: $(rrdtool_la_OBJECTS) $(rrdtool_la_DEPENDENCIES) $(EXTRA_rrdtool_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(rrdtool_la_LINK) $(am_rrdtool_la_rpath) $(rrdtool_la_OBJECTS) $(rrdtool_la_LIBADD) $(LIBS)
+
+sensors.la: $(sensors_la_OBJECTS) $(sensors_la_DEPENDENCIES) $(EXTRA_sensors_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(sensors_la_LINK) $(am_sensors_la_rpath) $(sensors_la_OBJECTS) $(sensors_la_LIBADD) $(LIBS)
+
+serial.la: $(serial_la_OBJECTS) $(serial_la_DEPENDENCIES) $(EXTRA_serial_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(serial_la_LINK) $(am_serial_la_rpath) $(serial_la_OBJECTS) $(serial_la_LIBADD) $(LIBS)
+
+sigrok.la: $(sigrok_la_OBJECTS) $(sigrok_la_DEPENDENCIES) $(EXTRA_sigrok_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(sigrok_la_LINK) $(am_sigrok_la_rpath) $(sigrok_la_OBJECTS) $(sigrok_la_LIBADD) $(LIBS)
+
+smart.la: $(smart_la_OBJECTS) $(smart_la_DEPENDENCIES) $(EXTRA_smart_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(smart_la_LINK) $(am_smart_la_rpath) $(smart_la_OBJECTS) $(smart_la_LIBADD) $(LIBS)
+
+snmp.la: $(snmp_la_OBJECTS) $(snmp_la_DEPENDENCIES) $(EXTRA_snmp_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(snmp_la_LINK) $(am_snmp_la_rpath) $(snmp_la_OBJECTS) $(snmp_la_LIBADD) $(LIBS)
+
+statsd.la: $(statsd_la_OBJECTS) $(statsd_la_DEPENDENCIES) $(EXTRA_statsd_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(statsd_la_LINK) $(am_statsd_la_rpath) $(statsd_la_OBJECTS) $(statsd_la_LIBADD) $(LIBS)
+
+swap.la: $(swap_la_OBJECTS) $(swap_la_DEPENDENCIES) $(EXTRA_swap_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(swap_la_LINK) $(am_swap_la_rpath) $(swap_la_OBJECTS) $(swap_la_LIBADD) $(LIBS)
+
+syslog.la: $(syslog_la_OBJECTS) $(syslog_la_DEPENDENCIES) $(EXTRA_syslog_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(syslog_la_LINK) $(am_syslog_la_rpath) $(syslog_la_OBJECTS) $(syslog_la_LIBADD) $(LIBS)
+
+table.la: $(table_la_OBJECTS) $(table_la_DEPENDENCIES) $(EXTRA_table_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(table_la_LINK) $(am_table_la_rpath) $(table_la_OBJECTS) $(table_la_LIBADD) $(LIBS)
+
+tail.la: $(tail_la_OBJECTS) $(tail_la_DEPENDENCIES) $(EXTRA_tail_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(tail_la_LINK) $(am_tail_la_rpath) $(tail_la_OBJECTS) $(tail_la_LIBADD) $(LIBS)
+
+tail_csv.la: $(tail_csv_la_OBJECTS) $(tail_csv_la_DEPENDENCIES) $(EXTRA_tail_csv_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(tail_csv_la_LINK) $(am_tail_csv_la_rpath) $(tail_csv_la_OBJECTS) $(tail_csv_la_LIBADD) $(LIBS)
+
+tape.la: $(tape_la_OBJECTS) $(tape_la_DEPENDENCIES) $(EXTRA_tape_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(tape_la_LINK) $(am_tape_la_rpath) $(tape_la_OBJECTS) $(tape_la_LIBADD) $(LIBS)
+
+target_notification.la: $(target_notification_la_OBJECTS) $(target_notification_la_DEPENDENCIES) $(EXTRA_target_notification_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(target_notification_la_LINK) $(am_target_notification_la_rpath) $(target_notification_la_OBJECTS) $(target_notification_la_LIBADD) $(LIBS)
+
+target_replace.la: $(target_replace_la_OBJECTS) $(target_replace_la_DEPENDENCIES) $(EXTRA_target_replace_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(target_replace_la_LINK) $(am_target_replace_la_rpath) $(target_replace_la_OBJECTS) $(target_replace_la_LIBADD) $(LIBS)
+
+target_scale.la: $(target_scale_la_OBJECTS) $(target_scale_la_DEPENDENCIES) $(EXTRA_target_scale_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(target_scale_la_LINK) $(am_target_scale_la_rpath) $(target_scale_la_OBJECTS) $(target_scale_la_LIBADD) $(LIBS)
+
+target_set.la: $(target_set_la_OBJECTS) $(target_set_la_DEPENDENCIES) $(EXTRA_target_set_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(target_set_la_LINK) $(am_target_set_la_rpath) $(target_set_la_OBJECTS) $(target_set_la_LIBADD) $(LIBS)
+
+target_v5upgrade.la: $(target_v5upgrade_la_OBJECTS) $(target_v5upgrade_la_DEPENDENCIES) $(EXTRA_target_v5upgrade_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(target_v5upgrade_la_LINK) $(am_target_v5upgrade_la_rpath) $(target_v5upgrade_la_OBJECTS) $(target_v5upgrade_la_LIBADD) $(LIBS)
+
+tcpconns.la: $(tcpconns_la_OBJECTS) $(tcpconns_la_DEPENDENCIES) $(EXTRA_tcpconns_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(tcpconns_la_LINK) $(am_tcpconns_la_rpath) $(tcpconns_la_OBJECTS) $(tcpconns_la_LIBADD) $(LIBS)
+
+teamspeak2.la: $(teamspeak2_la_OBJECTS) $(teamspeak2_la_DEPENDENCIES) $(EXTRA_teamspeak2_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(teamspeak2_la_LINK) $(am_teamspeak2_la_rpath) $(teamspeak2_la_OBJECTS) $(teamspeak2_la_LIBADD) $(LIBS)
+
+ted.la: $(ted_la_OBJECTS) $(ted_la_DEPENDENCIES) $(EXTRA_ted_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(ted_la_LINK) $(am_ted_la_rpath) $(ted_la_OBJECTS) $(ted_la_LIBADD) $(LIBS)
+
+thermal.la: $(thermal_la_OBJECTS) $(thermal_la_DEPENDENCIES) $(EXTRA_thermal_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(thermal_la_LINK) $(am_thermal_la_rpath) $(thermal_la_OBJECTS) $(thermal_la_LIBADD) $(LIBS)
+
+threshold.la: $(threshold_la_OBJECTS) $(threshold_la_DEPENDENCIES) $(EXTRA_threshold_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(threshold_la_LINK) $(am_threshold_la_rpath) $(threshold_la_OBJECTS) $(threshold_la_LIBADD) $(LIBS)
+
+tokyotyrant.la: $(tokyotyrant_la_OBJECTS) $(tokyotyrant_la_DEPENDENCIES) $(EXTRA_tokyotyrant_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(tokyotyrant_la_LINK) $(am_tokyotyrant_la_rpath) $(tokyotyrant_la_OBJECTS) $(tokyotyrant_la_LIBADD) $(LIBS)
+
+turbostat.la: $(turbostat_la_OBJECTS) $(turbostat_la_DEPENDENCIES) $(EXTRA_turbostat_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(turbostat_la_LINK) $(am_turbostat_la_rpath) $(turbostat_la_OBJECTS) $(turbostat_la_LIBADD) $(LIBS)
+
+unixsock.la: $(unixsock_la_OBJECTS) $(unixsock_la_DEPENDENCIES) $(EXTRA_unixsock_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(unixsock_la_LINK) $(am_unixsock_la_rpath) $(unixsock_la_OBJECTS) $(unixsock_la_LIBADD) $(LIBS)
+
+uptime.la: $(uptime_la_OBJECTS) $(uptime_la_DEPENDENCIES) $(EXTRA_uptime_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(uptime_la_LINK) $(am_uptime_la_rpath) $(uptime_la_OBJECTS) $(uptime_la_LIBADD) $(LIBS)
+
+users.la: $(users_la_OBJECTS) $(users_la_DEPENDENCIES) $(EXTRA_users_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(users_la_LINK) $(am_users_la_rpath) $(users_la_OBJECTS) $(users_la_LIBADD) $(LIBS)
+
+uuid.la: $(uuid_la_OBJECTS) $(uuid_la_DEPENDENCIES) $(EXTRA_uuid_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(uuid_la_LINK) $(am_uuid_la_rpath) $(uuid_la_OBJECTS) $(uuid_la_LIBADD) $(LIBS)
+
+varnish.la: $(varnish_la_OBJECTS) $(varnish_la_DEPENDENCIES) $(EXTRA_varnish_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(varnish_la_LINK) $(am_varnish_la_rpath) $(varnish_la_OBJECTS) $(varnish_la_LIBADD) $(LIBS)
+
+virt.la: $(virt_la_OBJECTS) $(virt_la_DEPENDENCIES) $(EXTRA_virt_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(virt_la_LINK) $(am_virt_la_rpath) $(virt_la_OBJECTS) $(virt_la_LIBADD) $(LIBS)
+
+vmem.la: $(vmem_la_OBJECTS) $(vmem_la_DEPENDENCIES) $(EXTRA_vmem_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(vmem_la_LINK) $(am_vmem_la_rpath) $(vmem_la_OBJECTS) $(vmem_la_LIBADD) $(LIBS)
+
+vserver.la: $(vserver_la_OBJECTS) $(vserver_la_DEPENDENCIES) $(EXTRA_vserver_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(vserver_la_LINK) $(am_vserver_la_rpath) $(vserver_la_OBJECTS) $(vserver_la_LIBADD) $(LIBS)
+
+wireless.la: $(wireless_la_OBJECTS) $(wireless_la_DEPENDENCIES) $(EXTRA_wireless_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(wireless_la_LINK) $(am_wireless_la_rpath) $(wireless_la_OBJECTS) $(wireless_la_LIBADD) $(LIBS)
+
+write_graphite.la: $(write_graphite_la_OBJECTS) $(write_graphite_la_DEPENDENCIES) $(EXTRA_write_graphite_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_graphite_la_LINK) $(am_write_graphite_la_rpath) $(write_graphite_la_OBJECTS) $(write_graphite_la_LIBADD) $(LIBS)
+
+write_http.la: $(write_http_la_OBJECTS) $(write_http_la_DEPENDENCIES) $(EXTRA_write_http_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_http_la_LINK) $(am_write_http_la_rpath) $(write_http_la_OBJECTS) $(write_http_la_LIBADD) $(LIBS)
+
+write_kafka.la: $(write_kafka_la_OBJECTS) $(write_kafka_la_DEPENDENCIES) $(EXTRA_write_kafka_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_kafka_la_LINK) $(am_write_kafka_la_rpath) $(write_kafka_la_OBJECTS) $(write_kafka_la_LIBADD) $(LIBS)
+
+write_log.la: $(write_log_la_OBJECTS) $(write_log_la_DEPENDENCIES) $(EXTRA_write_log_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_log_la_LINK) $(am_write_log_la_rpath) $(write_log_la_OBJECTS) $(write_log_la_LIBADD) $(LIBS)
+
+write_mongodb.la: $(write_mongodb_la_OBJECTS) $(write_mongodb_la_DEPENDENCIES) $(EXTRA_write_mongodb_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_mongodb_la_LINK) $(am_write_mongodb_la_rpath) $(write_mongodb_la_OBJECTS) $(write_mongodb_la_LIBADD) $(LIBS)
+
+write_redis.la: $(write_redis_la_OBJECTS) $(write_redis_la_DEPENDENCIES) $(EXTRA_write_redis_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_redis_la_LINK) $(am_write_redis_la_rpath) $(write_redis_la_OBJECTS) $(write_redis_la_LIBADD) $(LIBS)
+
+write_riemann.la: $(write_riemann_la_OBJECTS) $(write_riemann_la_DEPENDENCIES) $(EXTRA_write_riemann_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_riemann_la_LINK) $(am_write_riemann_la_rpath) $(write_riemann_la_OBJECTS) $(write_riemann_la_LIBADD) $(LIBS)
+
+write_sensu.la: $(write_sensu_la_OBJECTS) $(write_sensu_la_DEPENDENCIES) $(EXTRA_write_sensu_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_sensu_la_LINK) $(am_write_sensu_la_rpath) $(write_sensu_la_OBJECTS) $(write_sensu_la_LIBADD) $(LIBS)
+
+write_tsdb.la: $(write_tsdb_la_OBJECTS) $(write_tsdb_la_DEPENDENCIES) $(EXTRA_write_tsdb_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(write_tsdb_la_LINK) $(am_write_tsdb_la_rpath) $(write_tsdb_la_OBJECTS) $(write_tsdb_la_LIBADD) $(LIBS)
+
+xmms.la: $(xmms_la_OBJECTS) $(xmms_la_DEPENDENCIES) $(EXTRA_xmms_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(xmms_la_LINK) $(am_xmms_la_rpath) $(xmms_la_OBJECTS) $(xmms_la_LIBADD) $(LIBS)
+
+zfs_arc.la: $(zfs_arc_la_OBJECTS) $(zfs_arc_la_DEPENDENCIES) $(EXTRA_zfs_arc_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(zfs_arc_la_LINK) $(am_zfs_arc_la_rpath) $(zfs_arc_la_OBJECTS) $(zfs_arc_la_LIBADD) $(LIBS)
+
+zookeeper.la: $(zookeeper_la_OBJECTS) $(zookeeper_la_DEPENDENCIES) $(EXTRA_zookeeper_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(zookeeper_la_LINK) $(am_zookeeper_la_rpath) $(zookeeper_la_OBJECTS) $(zookeeper_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+       fi; \
+       for p in $$list; do echo "$$p $$p"; done | \
+       sed 's/$(EXEEXT)$$//' | \
+       while read p p1; do if test -f $$p \
+        || test -f $$p1 \
+         ; then echo "$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n;h' \
+           -e 's|.*|.|' \
+           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+       sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) files[d] = files[d] " " $$1; \
+           else { print "f", $$3 "/" $$4, $$1; } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+           test -z "$$files" || { \
+           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+           } \
+       ; done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       files=`for p in $$list; do echo "$$p"; done | \
+         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+             -e 's/$$/$(EXEEXT)/' \
+       `; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+       @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+
+clean-checkPROGRAMS:
+       @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+       fi; \
+       for p in $$list; do echo "$$p $$p"; done | \
+       sed 's/$(EXEEXT)$$//' | \
+       while read p p1; do if test -f $$p \
+        || test -f $$p1 \
+         ; then echo "$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n;h' \
+           -e 's|.*|.|' \
+           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+       sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) files[d] = files[d] " " $$1; \
+           else { print "f", $$3 "/" $$4, $$1; } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+           test -z "$$files" || { \
+           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+           } \
+       ; done
+
+uninstall-sbinPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+       files=`for p in $$list; do echo "$$p"; done | \
+         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+             -e 's/$$/$(EXEEXT)/' \
+       `; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+       @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+
+collectd-nagios$(EXEEXT): $(collectd_nagios_OBJECTS) $(collectd_nagios_DEPENDENCIES) $(EXTRA_collectd_nagios_DEPENDENCIES) 
+       @rm -f collectd-nagios$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(collectd_nagios_OBJECTS) $(collectd_nagios_LDADD) $(LIBS)
+
+collectd-tg$(EXEEXT): $(collectd_tg_OBJECTS) $(collectd_tg_DEPENDENCIES) $(EXTRA_collectd_tg_DEPENDENCIES) 
+       @rm -f collectd-tg$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(collectd_tg_OBJECTS) $(collectd_tg_LDADD) $(LIBS)
+
+collectdctl$(EXEEXT): $(collectdctl_OBJECTS) $(collectdctl_DEPENDENCIES) $(EXTRA_collectdctl_DEPENDENCIES) 
+       @rm -f collectdctl$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(collectdctl_OBJECTS) $(collectdctl_LDADD) $(LIBS)
+
+collectdmon$(EXEEXT): $(collectdmon_OBJECTS) $(collectdmon_DEPENDENCIES) $(EXTRA_collectdmon_DEPENDENCIES) 
+       @rm -f collectdmon$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(collectdmon_OBJECTS) $(collectdmon_LDADD) $(LIBS)
+
+test_utils_mount$(EXEEXT): $(test_utils_mount_OBJECTS) $(test_utils_mount_DEPENDENCIES) $(EXTRA_test_utils_mount_DEPENDENCIES) 
+       @rm -f test_utils_mount$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_utils_mount_OBJECTS) $(test_utils_mount_LDADD) $(LIBS)
+
+test_utils_vl_lookup$(EXEEXT): $(test_utils_vl_lookup_OBJECTS) $(test_utils_vl_lookup_DEPENDENCIES) $(EXTRA_test_utils_vl_lookup_DEPENDENCIES) 
+       @rm -f test_utils_vl_lookup$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_utils_vl_lookup_OBJECTS) $(test_utils_vl_lookup_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aggregation.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amqp_la-amqp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amqp_la-utils_cmd_putval.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amqp_la-utils_format_graphite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amqp_la-utils_format_json.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apache_la-apache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apcups.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apple_sensors.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aquaero_la-aquaero.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ascent_la-ascent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barometer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/battery.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bind_la-bind.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ceph_la-ceph.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cgroups.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd_nagios-collectd-nagios.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd_tg-collectd-tg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectdctl-collectdctl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectdmon-collectdmon.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conntrack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/contextswitch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu_la-cpu.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpufreq.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curl_json_la-curl_json.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curl_la-curl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curl_xml_la-curl_xml.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbi_la-dbi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbi_la-utils_db_query.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/df.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disk_la-disk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disk_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drbd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/email.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entropy.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ethstat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fhcount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filecount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fscache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmond_la-gmond.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hddtemp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface_la-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interface_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipc_la-ipc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_la-ipmi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipmi_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iptables_la-iptables.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipvs_la-ipvs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/irq.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_la-java.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load_la-load.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_logstash_la-log_logstash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpar.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lvm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/madwifi.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match_empty_counter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match_hashed.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match_regex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match_timediff.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/match_value.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbmon.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcachec_la-memcachec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcached.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory_la-memory.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mic_la-mic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mic_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modbus_la-modbus.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multimeter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mysql_la-mysql.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netapp_la-netapp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netapp_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/netlink_la-netlink.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network_la-network.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network_la-utils_fbhash.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nfs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nginx_la-nginx.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_desktop_la-notify_desktop.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify_email.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntpd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/numa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nut_la-nut.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/olsrd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onewire_la-onewire.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onewire_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openldap_la-openldap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openvpn_la-openvpn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oracle_la-oracle.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oracle_la-utils_db_query.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perl_la-perl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pinba.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pinba.pb-c.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ping_la-ping.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/postgresql_la-postgresql.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/postgresql_la-utils_db_query.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/powerdns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocols.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/python_la-pyconfig.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/python_la-python.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/python_la-pyvalues.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/redis_la-redis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/riemann.pb-c.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/routeros_la-routeros.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdcached_la-rrdcached.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdcached_la-utils_rrdcreate.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdtool_la-rrdtool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdtool_la-utils_rrdcreate.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sensors_la-sensors.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sensors_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serial.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigrok_la-sigrok.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smart_la-smart.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smart_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snmp_la-snmp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statsd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swap_la-swap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syslog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tail.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tail_csv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tape.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target_notification.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target_replace.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target_scale.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target_set.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target_v5upgrade.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcpconns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/teamspeak2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ted.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thermal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threshold.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tokyotyrant_la-tokyotyrant.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/turbostat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unixsock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uptime_la-uptime.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/users_la-users.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_cmd_flush.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_cmd_getthreshold.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_cmd_getval.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_cmd_listval.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_cmd_putnotif.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_cmd_putval.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_dns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_format_graphite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_format_json.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_latency.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_mount.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_mount_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_parse_option.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_vl_lookup.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_vl_lookup_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uuid_la-uuid.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/varnish_la-varnish.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_la-utils_ignorelist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virt_la-virt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vserver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wireless.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_graphite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_http_la-utils_format_json.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_http_la-write_http.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_kafka_la-utils_cmd_putval.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_kafka_la-utils_crc32.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_kafka_la-utils_format_graphite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_kafka_la-utils_format_json.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_kafka_la-write_kafka.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_log.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_mongodb_la-write_mongodb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_redis_la-write_redis.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_riemann.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_riemann_threshold.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_sensu.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/write_tsdb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmms_la-xmms.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_arc_la-zfs_arc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zookeeper.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+amqp_la-amqp.lo: amqp.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT amqp_la-amqp.lo -MD -MP -MF $(DEPDIR)/amqp_la-amqp.Tpo -c -o amqp_la-amqp.lo `test -f 'amqp.c' || echo '$(srcdir)/'`amqp.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/amqp_la-amqp.Tpo $(DEPDIR)/amqp_la-amqp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='amqp.c' object='amqp_la-amqp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o amqp_la-amqp.lo `test -f 'amqp.c' || echo '$(srcdir)/'`amqp.c
+
+amqp_la-utils_cmd_putval.lo: utils_cmd_putval.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT amqp_la-utils_cmd_putval.lo -MD -MP -MF $(DEPDIR)/amqp_la-utils_cmd_putval.Tpo -c -o amqp_la-utils_cmd_putval.lo `test -f 'utils_cmd_putval.c' || echo '$(srcdir)/'`utils_cmd_putval.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/amqp_la-utils_cmd_putval.Tpo $(DEPDIR)/amqp_la-utils_cmd_putval.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_cmd_putval.c' object='amqp_la-utils_cmd_putval.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o amqp_la-utils_cmd_putval.lo `test -f 'utils_cmd_putval.c' || echo '$(srcdir)/'`utils_cmd_putval.c
+
+amqp_la-utils_format_graphite.lo: utils_format_graphite.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT amqp_la-utils_format_graphite.lo -MD -MP -MF $(DEPDIR)/amqp_la-utils_format_graphite.Tpo -c -o amqp_la-utils_format_graphite.lo `test -f 'utils_format_graphite.c' || echo '$(srcdir)/'`utils_format_graphite.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/amqp_la-utils_format_graphite.Tpo $(DEPDIR)/amqp_la-utils_format_graphite.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_format_graphite.c' object='amqp_la-utils_format_graphite.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o amqp_la-utils_format_graphite.lo `test -f 'utils_format_graphite.c' || echo '$(srcdir)/'`utils_format_graphite.c
+
+amqp_la-utils_format_json.lo: utils_format_json.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT amqp_la-utils_format_json.lo -MD -MP -MF $(DEPDIR)/amqp_la-utils_format_json.Tpo -c -o amqp_la-utils_format_json.lo `test -f 'utils_format_json.c' || echo '$(srcdir)/'`utils_format_json.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/amqp_la-utils_format_json.Tpo $(DEPDIR)/amqp_la-utils_format_json.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_format_json.c' object='amqp_la-utils_format_json.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(amqp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o amqp_la-utils_format_json.lo `test -f 'utils_format_json.c' || echo '$(srcdir)/'`utils_format_json.c
+
+apache_la-apache.lo: apache.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(apache_la_CFLAGS) $(CFLAGS) -MT apache_la-apache.lo -MD -MP -MF $(DEPDIR)/apache_la-apache.Tpo -c -o apache_la-apache.lo `test -f 'apache.c' || echo '$(srcdir)/'`apache.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/apache_la-apache.Tpo $(DEPDIR)/apache_la-apache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='apache.c' object='apache_la-apache.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(apache_la_CFLAGS) $(CFLAGS) -c -o apache_la-apache.lo `test -f 'apache.c' || echo '$(srcdir)/'`apache.c
+
+aquaero_la-aquaero.lo: aquaero.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aquaero_la_CFLAGS) $(CFLAGS) -MT aquaero_la-aquaero.lo -MD -MP -MF $(DEPDIR)/aquaero_la-aquaero.Tpo -c -o aquaero_la-aquaero.lo `test -f 'aquaero.c' || echo '$(srcdir)/'`aquaero.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/aquaero_la-aquaero.Tpo $(DEPDIR)/aquaero_la-aquaero.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='aquaero.c' object='aquaero_la-aquaero.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(aquaero_la_CFLAGS) $(CFLAGS) -c -o aquaero_la-aquaero.lo `test -f 'aquaero.c' || echo '$(srcdir)/'`aquaero.c
+
+ascent_la-ascent.lo: ascent.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ascent_la_CFLAGS) $(CFLAGS) -MT ascent_la-ascent.lo -MD -MP -MF $(DEPDIR)/ascent_la-ascent.Tpo -c -o ascent_la-ascent.lo `test -f 'ascent.c' || echo '$(srcdir)/'`ascent.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/ascent_la-ascent.Tpo $(DEPDIR)/ascent_la-ascent.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ascent.c' object='ascent_la-ascent.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ascent_la_CFLAGS) $(CFLAGS) -c -o ascent_la-ascent.lo `test -f 'ascent.c' || echo '$(srcdir)/'`ascent.c
+
+bind_la-bind.lo: bind.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bind_la_CFLAGS) $(CFLAGS) -MT bind_la-bind.lo -MD -MP -MF $(DEPDIR)/bind_la-bind.Tpo -c -o bind_la-bind.lo `test -f 'bind.c' || echo '$(srcdir)/'`bind.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/bind_la-bind.Tpo $(DEPDIR)/bind_la-bind.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='bind.c' object='bind_la-bind.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(bind_la_CFLAGS) $(CFLAGS) -c -o bind_la-bind.lo `test -f 'bind.c' || echo '$(srcdir)/'`bind.c
+
+ceph_la-ceph.lo: ceph.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ceph_la_CPPFLAGS) $(CPPFLAGS) $(ceph_la_CFLAGS) $(CFLAGS) -MT ceph_la-ceph.lo -MD -MP -MF $(DEPDIR)/ceph_la-ceph.Tpo -c -o ceph_la-ceph.lo `test -f 'ceph.c' || echo '$(srcdir)/'`ceph.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/ceph_la-ceph.Tpo $(DEPDIR)/ceph_la-ceph.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ceph.c' object='ceph_la-ceph.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ceph_la_CPPFLAGS) $(CPPFLAGS) $(ceph_la_CFLAGS) $(CFLAGS) -c -o ceph_la-ceph.lo `test -f 'ceph.c' || echo '$(srcdir)/'`ceph.c
+
+cpu_la-cpu.lo: cpu.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cpu_la_CFLAGS) $(CFLAGS) -MT cpu_la-cpu.lo -MD -MP -MF $(DEPDIR)/cpu_la-cpu.Tpo -c -o cpu_la-cpu.lo `test -f 'cpu.c' || echo '$(srcdir)/'`cpu.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/cpu_la-cpu.Tpo $(DEPDIR)/cpu_la-cpu.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='cpu.c' object='cpu_la-cpu.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(cpu_la_CFLAGS) $(CFLAGS) -c -o cpu_la-cpu.lo `test -f 'cpu.c' || echo '$(srcdir)/'`cpu.c
+
+curl_la-curl.lo: curl.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(curl_la_CFLAGS) $(CFLAGS) -MT curl_la-curl.lo -MD -MP -MF $(DEPDIR)/curl_la-curl.Tpo -c -o curl_la-curl.lo `test -f 'curl.c' || echo '$(srcdir)/'`curl.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/curl_la-curl.Tpo $(DEPDIR)/curl_la-curl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='curl.c' object='curl_la-curl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(curl_la_CFLAGS) $(CFLAGS) -c -o curl_la-curl.lo `test -f 'curl.c' || echo '$(srcdir)/'`curl.c
+
+curl_json_la-curl_json.lo: curl_json.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(curl_json_la_CPPFLAGS) $(CPPFLAGS) $(curl_json_la_CFLAGS) $(CFLAGS) -MT curl_json_la-curl_json.lo -MD -MP -MF $(DEPDIR)/curl_json_la-curl_json.Tpo -c -o curl_json_la-curl_json.lo `test -f 'curl_json.c' || echo '$(srcdir)/'`curl_json.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/curl_json_la-curl_json.Tpo $(DEPDIR)/curl_json_la-curl_json.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='curl_json.c' object='curl_json_la-curl_json.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(curl_json_la_CPPFLAGS) $(CPPFLAGS) $(curl_json_la_CFLAGS) $(CFLAGS) -c -o curl_json_la-curl_json.lo `test -f 'curl_json.c' || echo '$(srcdir)/'`curl_json.c
+
+curl_xml_la-curl_xml.lo: curl_xml.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(curl_xml_la_CFLAGS) $(CFLAGS) -MT curl_xml_la-curl_xml.lo -MD -MP -MF $(DEPDIR)/curl_xml_la-curl_xml.Tpo -c -o curl_xml_la-curl_xml.lo `test -f 'curl_xml.c' || echo '$(srcdir)/'`curl_xml.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/curl_xml_la-curl_xml.Tpo $(DEPDIR)/curl_xml_la-curl_xml.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='curl_xml.c' object='curl_xml_la-curl_xml.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(curl_xml_la_CFLAGS) $(CFLAGS) -c -o curl_xml_la-curl_xml.lo `test -f 'curl_xml.c' || echo '$(srcdir)/'`curl_xml.c
+
+dbi_la-dbi.lo: dbi.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dbi_la-dbi.lo -MD -MP -MF $(DEPDIR)/dbi_la-dbi.Tpo -c -o dbi_la-dbi.lo `test -f 'dbi.c' || echo '$(srcdir)/'`dbi.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/dbi_la-dbi.Tpo $(DEPDIR)/dbi_la-dbi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='dbi.c' object='dbi_la-dbi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dbi_la-dbi.lo `test -f 'dbi.c' || echo '$(srcdir)/'`dbi.c
+
+dbi_la-utils_db_query.lo: utils_db_query.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dbi_la-utils_db_query.lo -MD -MP -MF $(DEPDIR)/dbi_la-utils_db_query.Tpo -c -o dbi_la-utils_db_query.lo `test -f 'utils_db_query.c' || echo '$(srcdir)/'`utils_db_query.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/dbi_la-utils_db_query.Tpo $(DEPDIR)/dbi_la-utils_db_query.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_db_query.c' object='dbi_la-utils_db_query.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(dbi_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dbi_la-utils_db_query.lo `test -f 'utils_db_query.c' || echo '$(srcdir)/'`utils_db_query.c
+
+disk_la-disk.lo: disk.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(disk_la_CFLAGS) $(CFLAGS) -MT disk_la-disk.lo -MD -MP -MF $(DEPDIR)/disk_la-disk.Tpo -c -o disk_la-disk.lo `test -f 'disk.c' || echo '$(srcdir)/'`disk.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/disk_la-disk.Tpo $(DEPDIR)/disk_la-disk.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='disk.c' object='disk_la-disk.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(disk_la_CFLAGS) $(CFLAGS) -c -o disk_la-disk.lo `test -f 'disk.c' || echo '$(srcdir)/'`disk.c
+
+disk_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(disk_la_CFLAGS) $(CFLAGS) -MT disk_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/disk_la-utils_ignorelist.Tpo -c -o disk_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/disk_la-utils_ignorelist.Tpo $(DEPDIR)/disk_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='disk_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(disk_la_CFLAGS) $(CFLAGS) -c -o disk_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+gmond_la-gmond.lo: gmond.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gmond_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gmond_la-gmond.lo -MD -MP -MF $(DEPDIR)/gmond_la-gmond.Tpo -c -o gmond_la-gmond.lo `test -f 'gmond.c' || echo '$(srcdir)/'`gmond.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/gmond_la-gmond.Tpo $(DEPDIR)/gmond_la-gmond.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='gmond.c' object='gmond_la-gmond.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(gmond_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gmond_la-gmond.lo `test -f 'gmond.c' || echo '$(srcdir)/'`gmond.c
+
+interface_la-interface.lo: interface.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(interface_la_CFLAGS) $(CFLAGS) -MT interface_la-interface.lo -MD -MP -MF $(DEPDIR)/interface_la-interface.Tpo -c -o interface_la-interface.lo `test -f 'interface.c' || echo '$(srcdir)/'`interface.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/interface_la-interface.Tpo $(DEPDIR)/interface_la-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='interface.c' object='interface_la-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(interface_la_CFLAGS) $(CFLAGS) -c -o interface_la-interface.lo `test -f 'interface.c' || echo '$(srcdir)/'`interface.c
+
+interface_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(interface_la_CFLAGS) $(CFLAGS) -MT interface_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/interface_la-utils_ignorelist.Tpo -c -o interface_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/interface_la-utils_ignorelist.Tpo $(DEPDIR)/interface_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='interface_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(interface_la_CFLAGS) $(CFLAGS) -c -o interface_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+ipc_la-ipc.lo: ipc.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipc_la_CFLAGS) $(CFLAGS) -MT ipc_la-ipc.lo -MD -MP -MF $(DEPDIR)/ipc_la-ipc.Tpo -c -o ipc_la-ipc.lo `test -f 'ipc.c' || echo '$(srcdir)/'`ipc.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/ipc_la-ipc.Tpo $(DEPDIR)/ipc_la-ipc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ipc.c' object='ipc_la-ipc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipc_la_CFLAGS) $(CFLAGS) -c -o ipc_la-ipc.lo `test -f 'ipc.c' || echo '$(srcdir)/'`ipc.c
+
+ipmi_la-ipmi.lo: ipmi.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_la_CFLAGS) $(CFLAGS) -MT ipmi_la-ipmi.lo -MD -MP -MF $(DEPDIR)/ipmi_la-ipmi.Tpo -c -o ipmi_la-ipmi.lo `test -f 'ipmi.c' || echo '$(srcdir)/'`ipmi.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_la-ipmi.Tpo $(DEPDIR)/ipmi_la-ipmi.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ipmi.c' object='ipmi_la-ipmi.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_la_CFLAGS) $(CFLAGS) -c -o ipmi_la-ipmi.lo `test -f 'ipmi.c' || echo '$(srcdir)/'`ipmi.c
+
+ipmi_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_la_CFLAGS) $(CFLAGS) -MT ipmi_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/ipmi_la-utils_ignorelist.Tpo -c -o ipmi_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/ipmi_la-utils_ignorelist.Tpo $(DEPDIR)/ipmi_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='ipmi_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipmi_la_CFLAGS) $(CFLAGS) -c -o ipmi_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+iptables_la-iptables.lo: iptables.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(iptables_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iptables_la-iptables.lo -MD -MP -MF $(DEPDIR)/iptables_la-iptables.Tpo -c -o iptables_la-iptables.lo `test -f 'iptables.c' || echo '$(srcdir)/'`iptables.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/iptables_la-iptables.Tpo $(DEPDIR)/iptables_la-iptables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='iptables.c' object='iptables_la-iptables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(iptables_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iptables_la-iptables.lo `test -f 'iptables.c' || echo '$(srcdir)/'`iptables.c
+
+ipvs_la-ipvs.lo: ipvs.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipvs_la_CFLAGS) $(CFLAGS) -MT ipvs_la-ipvs.lo -MD -MP -MF $(DEPDIR)/ipvs_la-ipvs.Tpo -c -o ipvs_la-ipvs.lo `test -f 'ipvs.c' || echo '$(srcdir)/'`ipvs.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/ipvs_la-ipvs.Tpo $(DEPDIR)/ipvs_la-ipvs.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ipvs.c' object='ipvs_la-ipvs.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipvs_la_CFLAGS) $(CFLAGS) -c -o ipvs_la-ipvs.lo `test -f 'ipvs.c' || echo '$(srcdir)/'`ipvs.c
+
+java_la-java.lo: java.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(java_la_CPPFLAGS) $(CPPFLAGS) $(java_la_CFLAGS) $(CFLAGS) -MT java_la-java.lo -MD -MP -MF $(DEPDIR)/java_la-java.Tpo -c -o java_la-java.lo `test -f 'java.c' || echo '$(srcdir)/'`java.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/java_la-java.Tpo $(DEPDIR)/java_la-java.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='java.c' object='java_la-java.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(java_la_CPPFLAGS) $(CPPFLAGS) $(java_la_CFLAGS) $(CFLAGS) -c -o java_la-java.lo `test -f 'java.c' || echo '$(srcdir)/'`java.c
+
+load_la-load.lo: load.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(load_la_CFLAGS) $(CFLAGS) -MT load_la-load.lo -MD -MP -MF $(DEPDIR)/load_la-load.Tpo -c -o load_la-load.lo `test -f 'load.c' || echo '$(srcdir)/'`load.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/load_la-load.Tpo $(DEPDIR)/load_la-load.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='load.c' object='load_la-load.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(load_la_CFLAGS) $(CFLAGS) -c -o load_la-load.lo `test -f 'load.c' || echo '$(srcdir)/'`load.c
+
+log_logstash_la-log_logstash.lo: log_logstash.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(log_logstash_la_CPPFLAGS) $(CPPFLAGS) $(log_logstash_la_CFLAGS) $(CFLAGS) -MT log_logstash_la-log_logstash.lo -MD -MP -MF $(DEPDIR)/log_logstash_la-log_logstash.Tpo -c -o log_logstash_la-log_logstash.lo `test -f 'log_logstash.c' || echo '$(srcdir)/'`log_logstash.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/log_logstash_la-log_logstash.Tpo $(DEPDIR)/log_logstash_la-log_logstash.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='log_logstash.c' object='log_logstash_la-log_logstash.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(log_logstash_la_CPPFLAGS) $(CPPFLAGS) $(log_logstash_la_CFLAGS) $(CFLAGS) -c -o log_logstash_la-log_logstash.lo `test -f 'log_logstash.c' || echo '$(srcdir)/'`log_logstash.c
+
+memcachec_la-memcachec.lo: memcachec.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(memcachec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT memcachec_la-memcachec.lo -MD -MP -MF $(DEPDIR)/memcachec_la-memcachec.Tpo -c -o memcachec_la-memcachec.lo `test -f 'memcachec.c' || echo '$(srcdir)/'`memcachec.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/memcachec_la-memcachec.Tpo $(DEPDIR)/memcachec_la-memcachec.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='memcachec.c' object='memcachec_la-memcachec.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(memcachec_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o memcachec_la-memcachec.lo `test -f 'memcachec.c' || echo '$(srcdir)/'`memcachec.c
+
+memory_la-memory.lo: memory.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_la_CFLAGS) $(CFLAGS) -MT memory_la-memory.lo -MD -MP -MF $(DEPDIR)/memory_la-memory.Tpo -c -o memory_la-memory.lo `test -f 'memory.c' || echo '$(srcdir)/'`memory.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/memory_la-memory.Tpo $(DEPDIR)/memory_la-memory.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='memory.c' object='memory_la-memory.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memory_la_CFLAGS) $(CFLAGS) -c -o memory_la-memory.lo `test -f 'memory.c' || echo '$(srcdir)/'`memory.c
+
+mic_la-mic.lo: mic.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mic_la_CFLAGS) $(CFLAGS) -MT mic_la-mic.lo -MD -MP -MF $(DEPDIR)/mic_la-mic.Tpo -c -o mic_la-mic.lo `test -f 'mic.c' || echo '$(srcdir)/'`mic.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/mic_la-mic.Tpo $(DEPDIR)/mic_la-mic.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='mic.c' object='mic_la-mic.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mic_la_CFLAGS) $(CFLAGS) -c -o mic_la-mic.lo `test -f 'mic.c' || echo '$(srcdir)/'`mic.c
+
+mic_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mic_la_CFLAGS) $(CFLAGS) -MT mic_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/mic_la-utils_ignorelist.Tpo -c -o mic_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/mic_la-utils_ignorelist.Tpo $(DEPDIR)/mic_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='mic_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mic_la_CFLAGS) $(CFLAGS) -c -o mic_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+modbus_la-modbus.lo: modbus.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(modbus_la_CFLAGS) $(CFLAGS) -MT modbus_la-modbus.lo -MD -MP -MF $(DEPDIR)/modbus_la-modbus.Tpo -c -o modbus_la-modbus.lo `test -f 'modbus.c' || echo '$(srcdir)/'`modbus.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/modbus_la-modbus.Tpo $(DEPDIR)/modbus_la-modbus.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='modbus.c' object='modbus_la-modbus.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(modbus_la_CFLAGS) $(CFLAGS) -c -o modbus_la-modbus.lo `test -f 'modbus.c' || echo '$(srcdir)/'`modbus.c
+
+mysql_la-mysql.lo: mysql.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mysql_la_CFLAGS) $(CFLAGS) -MT mysql_la-mysql.lo -MD -MP -MF $(DEPDIR)/mysql_la-mysql.Tpo -c -o mysql_la-mysql.lo `test -f 'mysql.c' || echo '$(srcdir)/'`mysql.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/mysql_la-mysql.Tpo $(DEPDIR)/mysql_la-mysql.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='mysql.c' object='mysql_la-mysql.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mysql_la_CFLAGS) $(CFLAGS) -c -o mysql_la-mysql.lo `test -f 'mysql.c' || echo '$(srcdir)/'`mysql.c
+
+netapp_la-netapp.lo: netapp.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netapp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netapp_la-netapp.lo -MD -MP -MF $(DEPDIR)/netapp_la-netapp.Tpo -c -o netapp_la-netapp.lo `test -f 'netapp.c' || echo '$(srcdir)/'`netapp.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/netapp_la-netapp.Tpo $(DEPDIR)/netapp_la-netapp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='netapp.c' object='netapp_la-netapp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netapp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netapp_la-netapp.lo `test -f 'netapp.c' || echo '$(srcdir)/'`netapp.c
+
+netapp_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netapp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT netapp_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/netapp_la-utils_ignorelist.Tpo -c -o netapp_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/netapp_la-utils_ignorelist.Tpo $(DEPDIR)/netapp_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='netapp_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(netapp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o netapp_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+netlink_la-netlink.lo: netlink.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netlink_la_CFLAGS) $(CFLAGS) -MT netlink_la-netlink.lo -MD -MP -MF $(DEPDIR)/netlink_la-netlink.Tpo -c -o netlink_la-netlink.lo `test -f 'netlink.c' || echo '$(srcdir)/'`netlink.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/netlink_la-netlink.Tpo $(DEPDIR)/netlink_la-netlink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='netlink.c' object='netlink_la-netlink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(netlink_la_CFLAGS) $(CFLAGS) -c -o netlink_la-netlink.lo `test -f 'netlink.c' || echo '$(srcdir)/'`netlink.c
+
+network_la-network.lo: network.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(network_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT network_la-network.lo -MD -MP -MF $(DEPDIR)/network_la-network.Tpo -c -o network_la-network.lo `test -f 'network.c' || echo '$(srcdir)/'`network.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/network_la-network.Tpo $(DEPDIR)/network_la-network.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='network.c' object='network_la-network.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(network_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o network_la-network.lo `test -f 'network.c' || echo '$(srcdir)/'`network.c
+
+network_la-utils_fbhash.lo: utils_fbhash.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(network_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT network_la-utils_fbhash.lo -MD -MP -MF $(DEPDIR)/network_la-utils_fbhash.Tpo -c -o network_la-utils_fbhash.lo `test -f 'utils_fbhash.c' || echo '$(srcdir)/'`utils_fbhash.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/network_la-utils_fbhash.Tpo $(DEPDIR)/network_la-utils_fbhash.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_fbhash.c' object='network_la-utils_fbhash.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(network_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o network_la-utils_fbhash.lo `test -f 'utils_fbhash.c' || echo '$(srcdir)/'`utils_fbhash.c
+
+nginx_la-nginx.lo: nginx.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nginx_la_CFLAGS) $(CFLAGS) -MT nginx_la-nginx.lo -MD -MP -MF $(DEPDIR)/nginx_la-nginx.Tpo -c -o nginx_la-nginx.lo `test -f 'nginx.c' || echo '$(srcdir)/'`nginx.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/nginx_la-nginx.Tpo $(DEPDIR)/nginx_la-nginx.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='nginx.c' object='nginx_la-nginx.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nginx_la_CFLAGS) $(CFLAGS) -c -o nginx_la-nginx.lo `test -f 'nginx.c' || echo '$(srcdir)/'`nginx.c
+
+notify_desktop_la-notify_desktop.lo: notify_desktop.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(notify_desktop_la_CFLAGS) $(CFLAGS) -MT notify_desktop_la-notify_desktop.lo -MD -MP -MF $(DEPDIR)/notify_desktop_la-notify_desktop.Tpo -c -o notify_desktop_la-notify_desktop.lo `test -f 'notify_desktop.c' || echo '$(srcdir)/'`notify_desktop.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/notify_desktop_la-notify_desktop.Tpo $(DEPDIR)/notify_desktop_la-notify_desktop.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='notify_desktop.c' object='notify_desktop_la-notify_desktop.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(notify_desktop_la_CFLAGS) $(CFLAGS) -c -o notify_desktop_la-notify_desktop.lo `test -f 'notify_desktop.c' || echo '$(srcdir)/'`notify_desktop.c
+
+nut_la-nut.lo: nut.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nut_la_CFLAGS) $(CFLAGS) -MT nut_la-nut.lo -MD -MP -MF $(DEPDIR)/nut_la-nut.Tpo -c -o nut_la-nut.lo `test -f 'nut.c' || echo '$(srcdir)/'`nut.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/nut_la-nut.Tpo $(DEPDIR)/nut_la-nut.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='nut.c' object='nut_la-nut.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(nut_la_CFLAGS) $(CFLAGS) -c -o nut_la-nut.lo `test -f 'nut.c' || echo '$(srcdir)/'`nut.c
+
+onewire_la-onewire.lo: onewire.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(onewire_la_CPPFLAGS) $(CPPFLAGS) $(onewire_la_CFLAGS) $(CFLAGS) -MT onewire_la-onewire.lo -MD -MP -MF $(DEPDIR)/onewire_la-onewire.Tpo -c -o onewire_la-onewire.lo `test -f 'onewire.c' || echo '$(srcdir)/'`onewire.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/onewire_la-onewire.Tpo $(DEPDIR)/onewire_la-onewire.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='onewire.c' object='onewire_la-onewire.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(onewire_la_CPPFLAGS) $(CPPFLAGS) $(onewire_la_CFLAGS) $(CFLAGS) -c -o onewire_la-onewire.lo `test -f 'onewire.c' || echo '$(srcdir)/'`onewire.c
+
+onewire_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(onewire_la_CPPFLAGS) $(CPPFLAGS) $(onewire_la_CFLAGS) $(CFLAGS) -MT onewire_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/onewire_la-utils_ignorelist.Tpo -c -o onewire_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/onewire_la-utils_ignorelist.Tpo $(DEPDIR)/onewire_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='onewire_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(onewire_la_CPPFLAGS) $(CPPFLAGS) $(onewire_la_CFLAGS) $(CFLAGS) -c -o onewire_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+openldap_la-openldap.lo: openldap.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(openldap_la_CFLAGS) $(CFLAGS) -MT openldap_la-openldap.lo -MD -MP -MF $(DEPDIR)/openldap_la-openldap.Tpo -c -o openldap_la-openldap.lo `test -f 'openldap.c' || echo '$(srcdir)/'`openldap.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/openldap_la-openldap.Tpo $(DEPDIR)/openldap_la-openldap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='openldap.c' object='openldap_la-openldap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(openldap_la_CFLAGS) $(CFLAGS) -c -o openldap_la-openldap.lo `test -f 'openldap.c' || echo '$(srcdir)/'`openldap.c
+
+openvpn_la-openvpn.lo: openvpn.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(openvpn_la_CFLAGS) $(CFLAGS) -MT openvpn_la-openvpn.lo -MD -MP -MF $(DEPDIR)/openvpn_la-openvpn.Tpo -c -o openvpn_la-openvpn.lo `test -f 'openvpn.c' || echo '$(srcdir)/'`openvpn.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/openvpn_la-openvpn.Tpo $(DEPDIR)/openvpn_la-openvpn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='openvpn.c' object='openvpn_la-openvpn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(openvpn_la_CFLAGS) $(CFLAGS) -c -o openvpn_la-openvpn.lo `test -f 'openvpn.c' || echo '$(srcdir)/'`openvpn.c
+
+oracle_la-oracle.lo: oracle.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(oracle_la_CPPFLAGS) $(CPPFLAGS) $(oracle_la_CFLAGS) $(CFLAGS) -MT oracle_la-oracle.lo -MD -MP -MF $(DEPDIR)/oracle_la-oracle.Tpo -c -o oracle_la-oracle.lo `test -f 'oracle.c' || echo '$(srcdir)/'`oracle.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/oracle_la-oracle.Tpo $(DEPDIR)/oracle_la-oracle.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='oracle.c' object='oracle_la-oracle.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(oracle_la_CPPFLAGS) $(CPPFLAGS) $(oracle_la_CFLAGS) $(CFLAGS) -c -o oracle_la-oracle.lo `test -f 'oracle.c' || echo '$(srcdir)/'`oracle.c
+
+oracle_la-utils_db_query.lo: utils_db_query.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(oracle_la_CPPFLAGS) $(CPPFLAGS) $(oracle_la_CFLAGS) $(CFLAGS) -MT oracle_la-utils_db_query.lo -MD -MP -MF $(DEPDIR)/oracle_la-utils_db_query.Tpo -c -o oracle_la-utils_db_query.lo `test -f 'utils_db_query.c' || echo '$(srcdir)/'`utils_db_query.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/oracle_la-utils_db_query.Tpo $(DEPDIR)/oracle_la-utils_db_query.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_db_query.c' object='oracle_la-utils_db_query.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(oracle_la_CPPFLAGS) $(CPPFLAGS) $(oracle_la_CFLAGS) $(CFLAGS) -c -o oracle_la-utils_db_query.lo `test -f 'utils_db_query.c' || echo '$(srcdir)/'`utils_db_query.c
+
+perl_la-perl.lo: perl.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(perl_la_CPPFLAGS) $(CPPFLAGS) $(perl_la_CFLAGS) $(CFLAGS) -MT perl_la-perl.lo -MD -MP -MF $(DEPDIR)/perl_la-perl.Tpo -c -o perl_la-perl.lo `test -f 'perl.c' || echo '$(srcdir)/'`perl.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/perl_la-perl.Tpo $(DEPDIR)/perl_la-perl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='perl.c' object='perl_la-perl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(perl_la_CPPFLAGS) $(CPPFLAGS) $(perl_la_CFLAGS) $(CFLAGS) -c -o perl_la-perl.lo `test -f 'perl.c' || echo '$(srcdir)/'`perl.c
+
+ping_la-ping.lo: ping.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ping_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ping_la-ping.lo -MD -MP -MF $(DEPDIR)/ping_la-ping.Tpo -c -o ping_la-ping.lo `test -f 'ping.c' || echo '$(srcdir)/'`ping.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/ping_la-ping.Tpo $(DEPDIR)/ping_la-ping.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='ping.c' object='ping_la-ping.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ping_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ping_la-ping.lo `test -f 'ping.c' || echo '$(srcdir)/'`ping.c
+
+postgresql_la-postgresql.lo: postgresql.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(postgresql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT postgresql_la-postgresql.lo -MD -MP -MF $(DEPDIR)/postgresql_la-postgresql.Tpo -c -o postgresql_la-postgresql.lo `test -f 'postgresql.c' || echo '$(srcdir)/'`postgresql.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/postgresql_la-postgresql.Tpo $(DEPDIR)/postgresql_la-postgresql.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='postgresql.c' object='postgresql_la-postgresql.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(postgresql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o postgresql_la-postgresql.lo `test -f 'postgresql.c' || echo '$(srcdir)/'`postgresql.c
+
+postgresql_la-utils_db_query.lo: utils_db_query.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(postgresql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT postgresql_la-utils_db_query.lo -MD -MP -MF $(DEPDIR)/postgresql_la-utils_db_query.Tpo -c -o postgresql_la-utils_db_query.lo `test -f 'utils_db_query.c' || echo '$(srcdir)/'`utils_db_query.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/postgresql_la-utils_db_query.Tpo $(DEPDIR)/postgresql_la-utils_db_query.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_db_query.c' object='postgresql_la-utils_db_query.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(postgresql_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o postgresql_la-utils_db_query.lo `test -f 'utils_db_query.c' || echo '$(srcdir)/'`utils_db_query.c
+
+python_la-python.lo: python.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(python_la_CPPFLAGS) $(CPPFLAGS) $(python_la_CFLAGS) $(CFLAGS) -MT python_la-python.lo -MD -MP -MF $(DEPDIR)/python_la-python.Tpo -c -o python_la-python.lo `test -f 'python.c' || echo '$(srcdir)/'`python.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/python_la-python.Tpo $(DEPDIR)/python_la-python.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='python.c' object='python_la-python.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(python_la_CPPFLAGS) $(CPPFLAGS) $(python_la_CFLAGS) $(CFLAGS) -c -o python_la-python.lo `test -f 'python.c' || echo '$(srcdir)/'`python.c
+
+python_la-pyconfig.lo: pyconfig.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(python_la_CPPFLAGS) $(CPPFLAGS) $(python_la_CFLAGS) $(CFLAGS) -MT python_la-pyconfig.lo -MD -MP -MF $(DEPDIR)/python_la-pyconfig.Tpo -c -o python_la-pyconfig.lo `test -f 'pyconfig.c' || echo '$(srcdir)/'`pyconfig.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/python_la-pyconfig.Tpo $(DEPDIR)/python_la-pyconfig.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='pyconfig.c' object='python_la-pyconfig.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(python_la_CPPFLAGS) $(CPPFLAGS) $(python_la_CFLAGS) $(CFLAGS) -c -o python_la-pyconfig.lo `test -f 'pyconfig.c' || echo '$(srcdir)/'`pyconfig.c
+
+python_la-pyvalues.lo: pyvalues.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(python_la_CPPFLAGS) $(CPPFLAGS) $(python_la_CFLAGS) $(CFLAGS) -MT python_la-pyvalues.lo -MD -MP -MF $(DEPDIR)/python_la-pyvalues.Tpo -c -o python_la-pyvalues.lo `test -f 'pyvalues.c' || echo '$(srcdir)/'`pyvalues.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/python_la-pyvalues.Tpo $(DEPDIR)/python_la-pyvalues.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='pyvalues.c' object='python_la-pyvalues.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(python_la_CPPFLAGS) $(CPPFLAGS) $(python_la_CFLAGS) $(CFLAGS) -c -o python_la-pyvalues.lo `test -f 'pyvalues.c' || echo '$(srcdir)/'`pyvalues.c
+
+redis_la-redis.lo: redis.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(redis_la_CFLAGS) $(CFLAGS) -MT redis_la-redis.lo -MD -MP -MF $(DEPDIR)/redis_la-redis.Tpo -c -o redis_la-redis.lo `test -f 'redis.c' || echo '$(srcdir)/'`redis.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/redis_la-redis.Tpo $(DEPDIR)/redis_la-redis.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='redis.c' object='redis_la-redis.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(redis_la_CFLAGS) $(CFLAGS) -c -o redis_la-redis.lo `test -f 'redis.c' || echo '$(srcdir)/'`redis.c
+
+routeros_la-routeros.lo: routeros.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(routeros_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT routeros_la-routeros.lo -MD -MP -MF $(DEPDIR)/routeros_la-routeros.Tpo -c -o routeros_la-routeros.lo `test -f 'routeros.c' || echo '$(srcdir)/'`routeros.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/routeros_la-routeros.Tpo $(DEPDIR)/routeros_la-routeros.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='routeros.c' object='routeros_la-routeros.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(routeros_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o routeros_la-routeros.lo `test -f 'routeros.c' || echo '$(srcdir)/'`routeros.c
+
+rrdcached_la-rrdcached.lo: rrdcached.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdcached_la_CFLAGS) $(CFLAGS) -MT rrdcached_la-rrdcached.lo -MD -MP -MF $(DEPDIR)/rrdcached_la-rrdcached.Tpo -c -o rrdcached_la-rrdcached.lo `test -f 'rrdcached.c' || echo '$(srcdir)/'`rrdcached.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/rrdcached_la-rrdcached.Tpo $(DEPDIR)/rrdcached_la-rrdcached.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='rrdcached.c' object='rrdcached_la-rrdcached.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdcached_la_CFLAGS) $(CFLAGS) -c -o rrdcached_la-rrdcached.lo `test -f 'rrdcached.c' || echo '$(srcdir)/'`rrdcached.c
+
+rrdcached_la-utils_rrdcreate.lo: utils_rrdcreate.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdcached_la_CFLAGS) $(CFLAGS) -MT rrdcached_la-utils_rrdcreate.lo -MD -MP -MF $(DEPDIR)/rrdcached_la-utils_rrdcreate.Tpo -c -o rrdcached_la-utils_rrdcreate.lo `test -f 'utils_rrdcreate.c' || echo '$(srcdir)/'`utils_rrdcreate.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/rrdcached_la-utils_rrdcreate.Tpo $(DEPDIR)/rrdcached_la-utils_rrdcreate.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_rrdcreate.c' object='rrdcached_la-utils_rrdcreate.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdcached_la_CFLAGS) $(CFLAGS) -c -o rrdcached_la-utils_rrdcreate.lo `test -f 'utils_rrdcreate.c' || echo '$(srcdir)/'`utils_rrdcreate.c
+
+rrdtool_la-rrdtool.lo: rrdtool.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdtool_la_CFLAGS) $(CFLAGS) -MT rrdtool_la-rrdtool.lo -MD -MP -MF $(DEPDIR)/rrdtool_la-rrdtool.Tpo -c -o rrdtool_la-rrdtool.lo `test -f 'rrdtool.c' || echo '$(srcdir)/'`rrdtool.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/rrdtool_la-rrdtool.Tpo $(DEPDIR)/rrdtool_la-rrdtool.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='rrdtool.c' object='rrdtool_la-rrdtool.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdtool_la_CFLAGS) $(CFLAGS) -c -o rrdtool_la-rrdtool.lo `test -f 'rrdtool.c' || echo '$(srcdir)/'`rrdtool.c
+
+rrdtool_la-utils_rrdcreate.lo: utils_rrdcreate.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdtool_la_CFLAGS) $(CFLAGS) -MT rrdtool_la-utils_rrdcreate.lo -MD -MP -MF $(DEPDIR)/rrdtool_la-utils_rrdcreate.Tpo -c -o rrdtool_la-utils_rrdcreate.lo `test -f 'utils_rrdcreate.c' || echo '$(srcdir)/'`utils_rrdcreate.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/rrdtool_la-utils_rrdcreate.Tpo $(DEPDIR)/rrdtool_la-utils_rrdcreate.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_rrdcreate.c' object='rrdtool_la-utils_rrdcreate.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rrdtool_la_CFLAGS) $(CFLAGS) -c -o rrdtool_la-utils_rrdcreate.lo `test -f 'utils_rrdcreate.c' || echo '$(srcdir)/'`utils_rrdcreate.c
+
+sensors_la-sensors.lo: sensors.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sensors_la_CFLAGS) $(CFLAGS) -MT sensors_la-sensors.lo -MD -MP -MF $(DEPDIR)/sensors_la-sensors.Tpo -c -o sensors_la-sensors.lo `test -f 'sensors.c' || echo '$(srcdir)/'`sensors.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/sensors_la-sensors.Tpo $(DEPDIR)/sensors_la-sensors.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='sensors.c' object='sensors_la-sensors.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sensors_la_CFLAGS) $(CFLAGS) -c -o sensors_la-sensors.lo `test -f 'sensors.c' || echo '$(srcdir)/'`sensors.c
+
+sensors_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sensors_la_CFLAGS) $(CFLAGS) -MT sensors_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/sensors_la-utils_ignorelist.Tpo -c -o sensors_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/sensors_la-utils_ignorelist.Tpo $(DEPDIR)/sensors_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='sensors_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sensors_la_CFLAGS) $(CFLAGS) -c -o sensors_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+sigrok_la-sigrok.lo: sigrok.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sigrok_la_CFLAGS) $(CFLAGS) -MT sigrok_la-sigrok.lo -MD -MP -MF $(DEPDIR)/sigrok_la-sigrok.Tpo -c -o sigrok_la-sigrok.lo `test -f 'sigrok.c' || echo '$(srcdir)/'`sigrok.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/sigrok_la-sigrok.Tpo $(DEPDIR)/sigrok_la-sigrok.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='sigrok.c' object='sigrok_la-sigrok.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sigrok_la_CFLAGS) $(CFLAGS) -c -o sigrok_la-sigrok.lo `test -f 'sigrok.c' || echo '$(srcdir)/'`sigrok.c
+
+smart_la-smart.lo: smart.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smart_la_CFLAGS) $(CFLAGS) -MT smart_la-smart.lo -MD -MP -MF $(DEPDIR)/smart_la-smart.Tpo -c -o smart_la-smart.lo `test -f 'smart.c' || echo '$(srcdir)/'`smart.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/smart_la-smart.Tpo $(DEPDIR)/smart_la-smart.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='smart.c' object='smart_la-smart.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smart_la_CFLAGS) $(CFLAGS) -c -o smart_la-smart.lo `test -f 'smart.c' || echo '$(srcdir)/'`smart.c
+
+smart_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smart_la_CFLAGS) $(CFLAGS) -MT smart_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/smart_la-utils_ignorelist.Tpo -c -o smart_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/smart_la-utils_ignorelist.Tpo $(DEPDIR)/smart_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='smart_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(smart_la_CFLAGS) $(CFLAGS) -c -o smart_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+snmp_la-snmp.lo: snmp.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snmp_la_CFLAGS) $(CFLAGS) -MT snmp_la-snmp.lo -MD -MP -MF $(DEPDIR)/snmp_la-snmp.Tpo -c -o snmp_la-snmp.lo `test -f 'snmp.c' || echo '$(srcdir)/'`snmp.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/snmp_la-snmp.Tpo $(DEPDIR)/snmp_la-snmp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='snmp.c' object='snmp_la-snmp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snmp_la_CFLAGS) $(CFLAGS) -c -o snmp_la-snmp.lo `test -f 'snmp.c' || echo '$(srcdir)/'`snmp.c
+
+swap_la-swap.lo: swap.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(swap_la_CFLAGS) $(CFLAGS) -MT swap_la-swap.lo -MD -MP -MF $(DEPDIR)/swap_la-swap.Tpo -c -o swap_la-swap.lo `test -f 'swap.c' || echo '$(srcdir)/'`swap.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/swap_la-swap.Tpo $(DEPDIR)/swap_la-swap.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='swap.c' object='swap_la-swap.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(swap_la_CFLAGS) $(CFLAGS) -c -o swap_la-swap.lo `test -f 'swap.c' || echo '$(srcdir)/'`swap.c
+
+tokyotyrant_la-tokyotyrant.lo: tokyotyrant.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tokyotyrant_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tokyotyrant_la-tokyotyrant.lo -MD -MP -MF $(DEPDIR)/tokyotyrant_la-tokyotyrant.Tpo -c -o tokyotyrant_la-tokyotyrant.lo `test -f 'tokyotyrant.c' || echo '$(srcdir)/'`tokyotyrant.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/tokyotyrant_la-tokyotyrant.Tpo $(DEPDIR)/tokyotyrant_la-tokyotyrant.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='tokyotyrant.c' object='tokyotyrant_la-tokyotyrant.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tokyotyrant_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tokyotyrant_la-tokyotyrant.lo `test -f 'tokyotyrant.c' || echo '$(srcdir)/'`tokyotyrant.c
+
+uptime_la-uptime.lo: uptime.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uptime_la_CFLAGS) $(CFLAGS) -MT uptime_la-uptime.lo -MD -MP -MF $(DEPDIR)/uptime_la-uptime.Tpo -c -o uptime_la-uptime.lo `test -f 'uptime.c' || echo '$(srcdir)/'`uptime.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/uptime_la-uptime.Tpo $(DEPDIR)/uptime_la-uptime.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='uptime.c' object='uptime_la-uptime.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uptime_la_CFLAGS) $(CFLAGS) -c -o uptime_la-uptime.lo `test -f 'uptime.c' || echo '$(srcdir)/'`uptime.c
+
+users_la-users.lo: users.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(users_la_CFLAGS) $(CFLAGS) -MT users_la-users.lo -MD -MP -MF $(DEPDIR)/users_la-users.Tpo -c -o users_la-users.lo `test -f 'users.c' || echo '$(srcdir)/'`users.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/users_la-users.Tpo $(DEPDIR)/users_la-users.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='users.c' object='users_la-users.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(users_la_CFLAGS) $(CFLAGS) -c -o users_la-users.lo `test -f 'users.c' || echo '$(srcdir)/'`users.c
+
+uuid_la-uuid.lo: uuid.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uuid_la_CFLAGS) $(CFLAGS) -MT uuid_la-uuid.lo -MD -MP -MF $(DEPDIR)/uuid_la-uuid.Tpo -c -o uuid_la-uuid.lo `test -f 'uuid.c' || echo '$(srcdir)/'`uuid.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/uuid_la-uuid.Tpo $(DEPDIR)/uuid_la-uuid.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='uuid.c' object='uuid_la-uuid.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(uuid_la_CFLAGS) $(CFLAGS) -c -o uuid_la-uuid.lo `test -f 'uuid.c' || echo '$(srcdir)/'`uuid.c
+
+varnish_la-varnish.lo: varnish.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(varnish_la_CFLAGS) $(CFLAGS) -MT varnish_la-varnish.lo -MD -MP -MF $(DEPDIR)/varnish_la-varnish.Tpo -c -o varnish_la-varnish.lo `test -f 'varnish.c' || echo '$(srcdir)/'`varnish.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/varnish_la-varnish.Tpo $(DEPDIR)/varnish_la-varnish.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='varnish.c' object='varnish_la-varnish.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(varnish_la_CFLAGS) $(CFLAGS) -c -o varnish_la-varnish.lo `test -f 'varnish.c' || echo '$(srcdir)/'`varnish.c
+
+virt_la-virt.lo: virt.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_la_CFLAGS) $(CFLAGS) -MT virt_la-virt.lo -MD -MP -MF $(DEPDIR)/virt_la-virt.Tpo -c -o virt_la-virt.lo `test -f 'virt.c' || echo '$(srcdir)/'`virt.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/virt_la-virt.Tpo $(DEPDIR)/virt_la-virt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='virt.c' object='virt_la-virt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_la_CFLAGS) $(CFLAGS) -c -o virt_la-virt.lo `test -f 'virt.c' || echo '$(srcdir)/'`virt.c
+
+virt_la-utils_ignorelist.lo: utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_la_CFLAGS) $(CFLAGS) -MT virt_la-utils_ignorelist.lo -MD -MP -MF $(DEPDIR)/virt_la-utils_ignorelist.Tpo -c -o virt_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/virt_la-utils_ignorelist.Tpo $(DEPDIR)/virt_la-utils_ignorelist.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_ignorelist.c' object='virt_la-utils_ignorelist.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(virt_la_CFLAGS) $(CFLAGS) -c -o virt_la-utils_ignorelist.lo `test -f 'utils_ignorelist.c' || echo '$(srcdir)/'`utils_ignorelist.c
+
+write_http_la-write_http.lo: write_http.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(write_http_la_CFLAGS) $(CFLAGS) -MT write_http_la-write_http.lo -MD -MP -MF $(DEPDIR)/write_http_la-write_http.Tpo -c -o write_http_la-write_http.lo `test -f 'write_http.c' || echo '$(srcdir)/'`write_http.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_http_la-write_http.Tpo $(DEPDIR)/write_http_la-write_http.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='write_http.c' object='write_http_la-write_http.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(write_http_la_CFLAGS) $(CFLAGS) -c -o write_http_la-write_http.lo `test -f 'write_http.c' || echo '$(srcdir)/'`write_http.c
+
+write_http_la-utils_format_json.lo: utils_format_json.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(write_http_la_CFLAGS) $(CFLAGS) -MT write_http_la-utils_format_json.lo -MD -MP -MF $(DEPDIR)/write_http_la-utils_format_json.Tpo -c -o write_http_la-utils_format_json.lo `test -f 'utils_format_json.c' || echo '$(srcdir)/'`utils_format_json.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_http_la-utils_format_json.Tpo $(DEPDIR)/write_http_la-utils_format_json.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_format_json.c' object='write_http_la-utils_format_json.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(write_http_la_CFLAGS) $(CFLAGS) -c -o write_http_la-utils_format_json.lo `test -f 'utils_format_json.c' || echo '$(srcdir)/'`utils_format_json.c
+
+write_kafka_la-write_kafka.lo: write_kafka.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT write_kafka_la-write_kafka.lo -MD -MP -MF $(DEPDIR)/write_kafka_la-write_kafka.Tpo -c -o write_kafka_la-write_kafka.lo `test -f 'write_kafka.c' || echo '$(srcdir)/'`write_kafka.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_kafka_la-write_kafka.Tpo $(DEPDIR)/write_kafka_la-write_kafka.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='write_kafka.c' object='write_kafka_la-write_kafka.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write_kafka_la-write_kafka.lo `test -f 'write_kafka.c' || echo '$(srcdir)/'`write_kafka.c
+
+write_kafka_la-utils_format_graphite.lo: utils_format_graphite.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT write_kafka_la-utils_format_graphite.lo -MD -MP -MF $(DEPDIR)/write_kafka_la-utils_format_graphite.Tpo -c -o write_kafka_la-utils_format_graphite.lo `test -f 'utils_format_graphite.c' || echo '$(srcdir)/'`utils_format_graphite.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_kafka_la-utils_format_graphite.Tpo $(DEPDIR)/write_kafka_la-utils_format_graphite.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_format_graphite.c' object='write_kafka_la-utils_format_graphite.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write_kafka_la-utils_format_graphite.lo `test -f 'utils_format_graphite.c' || echo '$(srcdir)/'`utils_format_graphite.c
+
+write_kafka_la-utils_format_json.lo: utils_format_json.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT write_kafka_la-utils_format_json.lo -MD -MP -MF $(DEPDIR)/write_kafka_la-utils_format_json.Tpo -c -o write_kafka_la-utils_format_json.lo `test -f 'utils_format_json.c' || echo '$(srcdir)/'`utils_format_json.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_kafka_la-utils_format_json.Tpo $(DEPDIR)/write_kafka_la-utils_format_json.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_format_json.c' object='write_kafka_la-utils_format_json.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write_kafka_la-utils_format_json.lo `test -f 'utils_format_json.c' || echo '$(srcdir)/'`utils_format_json.c
+
+write_kafka_la-utils_cmd_putval.lo: utils_cmd_putval.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT write_kafka_la-utils_cmd_putval.lo -MD -MP -MF $(DEPDIR)/write_kafka_la-utils_cmd_putval.Tpo -c -o write_kafka_la-utils_cmd_putval.lo `test -f 'utils_cmd_putval.c' || echo '$(srcdir)/'`utils_cmd_putval.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_kafka_la-utils_cmd_putval.Tpo $(DEPDIR)/write_kafka_la-utils_cmd_putval.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_cmd_putval.c' object='write_kafka_la-utils_cmd_putval.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write_kafka_la-utils_cmd_putval.lo `test -f 'utils_cmd_putval.c' || echo '$(srcdir)/'`utils_cmd_putval.c
+
+write_kafka_la-utils_crc32.lo: utils_crc32.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT write_kafka_la-utils_crc32.lo -MD -MP -MF $(DEPDIR)/write_kafka_la-utils_crc32.Tpo -c -o write_kafka_la-utils_crc32.lo `test -f 'utils_crc32.c' || echo '$(srcdir)/'`utils_crc32.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_kafka_la-utils_crc32.Tpo $(DEPDIR)/write_kafka_la-utils_crc32.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_crc32.c' object='write_kafka_la-utils_crc32.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_kafka_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write_kafka_la-utils_crc32.lo `test -f 'utils_crc32.c' || echo '$(srcdir)/'`utils_crc32.c
+
+write_mongodb_la-write_mongodb.lo: write_mongodb.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_mongodb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT write_mongodb_la-write_mongodb.lo -MD -MP -MF $(DEPDIR)/write_mongodb_la-write_mongodb.Tpo -c -o write_mongodb_la-write_mongodb.lo `test -f 'write_mongodb.c' || echo '$(srcdir)/'`write_mongodb.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_mongodb_la-write_mongodb.Tpo $(DEPDIR)/write_mongodb_la-write_mongodb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='write_mongodb.c' object='write_mongodb_la-write_mongodb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(write_mongodb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o write_mongodb_la-write_mongodb.lo `test -f 'write_mongodb.c' || echo '$(srcdir)/'`write_mongodb.c
+
+write_redis_la-write_redis.lo: write_redis.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(write_redis_la_CFLAGS) $(CFLAGS) -MT write_redis_la-write_redis.lo -MD -MP -MF $(DEPDIR)/write_redis_la-write_redis.Tpo -c -o write_redis_la-write_redis.lo `test -f 'write_redis.c' || echo '$(srcdir)/'`write_redis.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/write_redis_la-write_redis.Tpo $(DEPDIR)/write_redis_la-write_redis.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='write_redis.c' object='write_redis_la-write_redis.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(write_redis_la_CFLAGS) $(CFLAGS) -c -o write_redis_la-write_redis.lo `test -f 'write_redis.c' || echo '$(srcdir)/'`write_redis.c
+
+xmms_la-xmms.lo: xmms.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xmms_la_CFLAGS) $(CFLAGS) -MT xmms_la-xmms.lo -MD -MP -MF $(DEPDIR)/xmms_la-xmms.Tpo -c -o xmms_la-xmms.lo `test -f 'xmms.c' || echo '$(srcdir)/'`xmms.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/xmms_la-xmms.Tpo $(DEPDIR)/xmms_la-xmms.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='xmms.c' object='xmms_la-xmms.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xmms_la_CFLAGS) $(CFLAGS) -c -o xmms_la-xmms.lo `test -f 'xmms.c' || echo '$(srcdir)/'`xmms.c
+
+zfs_arc_la-zfs_arc.lo: zfs_arc.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zfs_arc_la_CFLAGS) $(CFLAGS) -MT zfs_arc_la-zfs_arc.lo -MD -MP -MF $(DEPDIR)/zfs_arc_la-zfs_arc.Tpo -c -o zfs_arc_la-zfs_arc.lo `test -f 'zfs_arc.c' || echo '$(srcdir)/'`zfs_arc.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/zfs_arc_la-zfs_arc.Tpo $(DEPDIR)/zfs_arc_la-zfs_arc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='zfs_arc.c' object='zfs_arc_la-zfs_arc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(zfs_arc_la_CFLAGS) $(CFLAGS) -c -o zfs_arc_la-zfs_arc.lo `test -f 'zfs_arc.c' || echo '$(srcdir)/'`zfs_arc.c
+
+collectd_nagios-collectd-nagios.o: collectd-nagios.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_nagios_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectd_nagios-collectd-nagios.o -MD -MP -MF $(DEPDIR)/collectd_nagios-collectd-nagios.Tpo -c -o collectd_nagios-collectd-nagios.o `test -f 'collectd-nagios.c' || echo '$(srcdir)/'`collectd-nagios.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd_nagios-collectd-nagios.Tpo $(DEPDIR)/collectd_nagios-collectd-nagios.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectd-nagios.c' object='collectd_nagios-collectd-nagios.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_nagios_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectd_nagios-collectd-nagios.o `test -f 'collectd-nagios.c' || echo '$(srcdir)/'`collectd-nagios.c
+
+collectd_nagios-collectd-nagios.obj: collectd-nagios.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_nagios_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectd_nagios-collectd-nagios.obj -MD -MP -MF $(DEPDIR)/collectd_nagios-collectd-nagios.Tpo -c -o collectd_nagios-collectd-nagios.obj `if test -f 'collectd-nagios.c'; then $(CYGPATH_W) 'collectd-nagios.c'; else $(CYGPATH_W) '$(srcdir)/collectd-nagios.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd_nagios-collectd-nagios.Tpo $(DEPDIR)/collectd_nagios-collectd-nagios.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectd-nagios.c' object='collectd_nagios-collectd-nagios.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_nagios_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectd_nagios-collectd-nagios.obj `if test -f 'collectd-nagios.c'; then $(CYGPATH_W) 'collectd-nagios.c'; else $(CYGPATH_W) '$(srcdir)/collectd-nagios.c'; fi`
+
+collectd_tg-collectd-tg.o: collectd-tg.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_tg_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectd_tg-collectd-tg.o -MD -MP -MF $(DEPDIR)/collectd_tg-collectd-tg.Tpo -c -o collectd_tg-collectd-tg.o `test -f 'collectd-tg.c' || echo '$(srcdir)/'`collectd-tg.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd_tg-collectd-tg.Tpo $(DEPDIR)/collectd_tg-collectd-tg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectd-tg.c' object='collectd_tg-collectd-tg.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_tg_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectd_tg-collectd-tg.o `test -f 'collectd-tg.c' || echo '$(srcdir)/'`collectd-tg.c
+
+collectd_tg-collectd-tg.obj: collectd-tg.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_tg_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectd_tg-collectd-tg.obj -MD -MP -MF $(DEPDIR)/collectd_tg-collectd-tg.Tpo -c -o collectd_tg-collectd-tg.obj `if test -f 'collectd-tg.c'; then $(CYGPATH_W) 'collectd-tg.c'; else $(CYGPATH_W) '$(srcdir)/collectd-tg.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd_tg-collectd-tg.Tpo $(DEPDIR)/collectd_tg-collectd-tg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectd-tg.c' object='collectd_tg-collectd-tg.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_tg_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectd_tg-collectd-tg.obj `if test -f 'collectd-tg.c'; then $(CYGPATH_W) 'collectd-tg.c'; else $(CYGPATH_W) '$(srcdir)/collectd-tg.c'; fi`
+
+collectdctl-collectdctl.o: collectdctl.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectdctl-collectdctl.o -MD -MP -MF $(DEPDIR)/collectdctl-collectdctl.Tpo -c -o collectdctl-collectdctl.o `test -f 'collectdctl.c' || echo '$(srcdir)/'`collectdctl.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectdctl-collectdctl.Tpo $(DEPDIR)/collectdctl-collectdctl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectdctl.c' object='collectdctl-collectdctl.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectdctl-collectdctl.o `test -f 'collectdctl.c' || echo '$(srcdir)/'`collectdctl.c
+
+collectdctl-collectdctl.obj: collectdctl.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectdctl-collectdctl.obj -MD -MP -MF $(DEPDIR)/collectdctl-collectdctl.Tpo -c -o collectdctl-collectdctl.obj `if test -f 'collectdctl.c'; then $(CYGPATH_W) 'collectdctl.c'; else $(CYGPATH_W) '$(srcdir)/collectdctl.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectdctl-collectdctl.Tpo $(DEPDIR)/collectdctl-collectdctl.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectdctl.c' object='collectdctl-collectdctl.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectdctl-collectdctl.obj `if test -f 'collectdctl.c'; then $(CYGPATH_W) 'collectdctl.c'; else $(CYGPATH_W) '$(srcdir)/collectdctl.c'; fi`
+
+collectdmon-collectdmon.o: collectdmon.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdmon_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectdmon-collectdmon.o -MD -MP -MF $(DEPDIR)/collectdmon-collectdmon.Tpo -c -o collectdmon-collectdmon.o `test -f 'collectdmon.c' || echo '$(srcdir)/'`collectdmon.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectdmon-collectdmon.Tpo $(DEPDIR)/collectdmon-collectdmon.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectdmon.c' object='collectdmon-collectdmon.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdmon_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectdmon-collectdmon.o `test -f 'collectdmon.c' || echo '$(srcdir)/'`collectdmon.c
+
+collectdmon-collectdmon.obj: collectdmon.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdmon_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT collectdmon-collectdmon.obj -MD -MP -MF $(DEPDIR)/collectdmon-collectdmon.Tpo -c -o collectdmon-collectdmon.obj `if test -f 'collectdmon.c'; then $(CYGPATH_W) 'collectdmon.c'; else $(CYGPATH_W) '$(srcdir)/collectdmon.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectdmon-collectdmon.Tpo $(DEPDIR)/collectdmon-collectdmon.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectdmon.c' object='collectdmon-collectdmon.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectdmon_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o collectdmon-collectdmon.obj `if test -f 'collectdmon.c'; then $(CYGPATH_W) 'collectdmon.c'; else $(CYGPATH_W) '$(srcdir)/collectdmon.c'; fi`
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+install-man1: $(dist_man_MANS)
+       @$(NORMAL_INSTALL)
+       @list1=''; \
+       list2='$(dist_man_MANS)'; \
+       test -n "$(man1dir)" \
+         && test -n "`echo $$list1$$list2`" \
+         || exit 0; \
+       echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+       $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+       { for i in $$list1; do echo "$$i"; done;  \
+       if test -n "$$list2"; then \
+         for i in $$list2; do echo "$$i"; done \
+           | sed -n '/\.1[a-z]*$$/p'; \
+       fi; \
+       } | while read p; do \
+         if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; echo "$$p"; \
+       done | \
+       sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+       sed 'N;N;s,\n, ,g' | { \
+       list=; while read file base inst; do \
+         if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+           echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+           $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+         fi; \
+       done; \
+       for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+       while read files; do \
+         test -z "$$files" || { \
+           echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+           $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+       done; }
+
+uninstall-man1:
+       @$(NORMAL_UNINSTALL)
+       @list=''; test -n "$(man1dir)" || exit 0; \
+       files=`{ for i in $$list; do echo "$$i"; done; \
+       l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+         sed -n '/\.1[a-z]*$$/p'; \
+       } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+       dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+install-man5: $(dist_man_MANS)
+       @$(NORMAL_INSTALL)
+       @list1=''; \
+       list2='$(dist_man_MANS)'; \
+       test -n "$(man5dir)" \
+         && test -n "`echo $$list1$$list2`" \
+         || exit 0; \
+       echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
+       $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
+       { for i in $$list1; do echo "$$i"; done;  \
+       if test -n "$$list2"; then \
+         for i in $$list2; do echo "$$i"; done \
+           | sed -n '/\.5[a-z]*$$/p'; \
+       fi; \
+       } | while read p; do \
+         if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; echo "$$p"; \
+       done | \
+       sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+       sed 'N;N;s,\n, ,g' | { \
+       list=; while read file base inst; do \
+         if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+           echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+           $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+         fi; \
+       done; \
+       for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+       while read files; do \
+         test -z "$$files" || { \
+           echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+           $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+       done; }
+
+uninstall-man5:
+       @$(NORMAL_UNINSTALL)
+       @list=''; test -n "$(man5dir)" || exit 0; \
+       files=`{ for i in $$list; do echo "$$i"; done; \
+       l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+         sed -n '/\.5[a-z]*$$/p'; \
+       } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+             -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+       dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+       @fail=; \
+       if $(am__make_keepgoing); then \
+         failcom='fail=yes'; \
+       else \
+         failcom='exit 1'; \
+       fi; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+       rm -f $< $@
+       $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+       @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+       @$(am__set_TESTS_bases); \
+       am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+       redo_bases=`for i in $$bases; do \
+                     am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+                   done`; \
+       if test -n "$$redo_bases"; then \
+         redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+         redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+         if $(am__make_dryrun); then :; else \
+           rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+         fi; \
+       fi; \
+       if test -n "$$am__remaking_logs"; then \
+         echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+              "recursion detected" >&2; \
+       else \
+         am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+       fi; \
+       if $(am__make_dryrun); then :; else \
+         st=0;  \
+         errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+         for i in $$redo_bases; do \
+           test -f $$i.trs && test -r $$i.trs \
+             || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+           test -f $$i.log && test -r $$i.log \
+             || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+         done; \
+         test $$st -eq 0 || exit 1; \
+       fi
+       @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+       ws='[   ]'; \
+       results=`for b in $$bases; do echo $$b.trs; done`; \
+       test -n "$$results" || results=/dev/null; \
+       all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+       pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+       fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+       skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+       xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+       xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+       error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+       if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+         success=true; \
+       else \
+         success=false; \
+       fi; \
+       br='==================='; br=$$br$$br$$br$$br; \
+       result_count () \
+       { \
+           if test x"$$1" = x"--maybe-color"; then \
+             maybe_colorize=yes; \
+           elif test x"$$1" = x"--no-color"; then \
+             maybe_colorize=no; \
+           else \
+             echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+           fi; \
+           shift; \
+           desc=$$1 count=$$2; \
+           if test $$maybe_colorize = yes && test $$count -gt 0; then \
+             color_start=$$3 color_end=$$std; \
+           else \
+             color_start= color_end=; \
+           fi; \
+           echo "$${color_start}# $$desc $$count$${color_end}"; \
+       }; \
+       create_testsuite_report () \
+       { \
+         result_count $$1 "TOTAL:" $$all   "$$brg"; \
+         result_count $$1 "PASS: " $$pass  "$$grn"; \
+         result_count $$1 "SKIP: " $$skip  "$$blu"; \
+         result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+         result_count $$1 "FAIL: " $$fail  "$$red"; \
+         result_count $$1 "XPASS:" $$xpass "$$red"; \
+         result_count $$1 "ERROR:" $$error "$$mgn"; \
+       }; \
+       {                                                               \
+         echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |       \
+           $(am__rst_title);                                           \
+         create_testsuite_report --no-color;                           \
+         echo;                                                         \
+         echo ".. contents:: :depth: 2";                               \
+         echo;                                                         \
+         for b in $$bases; do echo $$b; done                           \
+           | $(am__create_global_log);                                 \
+       } >$(TEST_SUITE_LOG).tmp || exit 1;                             \
+       mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);                     \
+       if $$success; then                                              \
+         col="$$grn";                                                  \
+        else                                                           \
+         col="$$red";                                                  \
+         test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);               \
+       fi;                                                             \
+       echo "$${col}$$br$${std}";                                      \
+       echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}";   \
+       echo "$${col}$$br$${std}";                                      \
+       create_testsuite_report --maybe-color;                          \
+       echo "$$col$$br$$std";                                          \
+       if $$success; then :; else                                      \
+         echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";         \
+         if test -n "$(PACKAGE_BUGREPORT)"; then                       \
+           echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+         fi;                                                           \
+         echo "$$col$$br$$std";                                        \
+       fi;                                                             \
+       $$success || exit 1
+
+check-TESTS:
+       @list='$(RECHECK_LOGS)';           test -z "$$list" || rm -f $$list
+       @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+       log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+       exit $$?;
+recheck: all $(check_PROGRAMS)
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       bases=`for i in $$bases; do echo $$i; done \
+                | $(am__list_recheck_tests)` || exit 1; \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       log_list=`echo $$log_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+               am__force_recheck=am--force-recheck \
+               TEST_LOGS="$$log_list"; \
+       exit $$?
+test_utils_mount.log: test_utils_mount$(EXEEXT)
+       @p='test_utils_mount$(EXEEXT)'; \
+       b='test_utils_mount'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+test_utils_vl_lookup.log: test_utils_vl_lookup$(EXEEXT)
+       @p='test_utils_vl_lookup$(EXEEXT)'; \
+       b='test_utils_vl_lookup'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+       @p='$<'; \
+       $(am__set_b); \
+       $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@      @p='$<'; \
+@am__EXEEXT_TRUE@      $(am__set_b); \
+@am__EXEEXT_TRUE@      $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@      --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@      $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@      "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           $(am__make_dryrun) \
+             || test -d "$(distdir)/$$subdir" \
+             || $(MKDIR_P) "$(distdir)/$$subdir" \
+             || exit 1; \
+           dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+           $(am__relativize); \
+           new_distdir=$$reldir; \
+           dir1=$$subdir; dir2="$(top_distdir)"; \
+           $(am__relativize); \
+           new_top_distdir=$$reldir; \
+           echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+           echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+           ($(am__cd) $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$new_top_distdir" \
+               distdir="$$new_distdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               am__skip_mode_fix=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+       $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+       for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+       -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+       -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+       -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES \
+       clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-pkglibLTLIBRARIES \
+       install-sbinPROGRAMS
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man: install-man1 install-man5
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man \
+       uninstall-pkglibLTLIBRARIES uninstall-sbinPROGRAMS
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) uninstall-hook
+uninstall-man: uninstall-man1 uninstall-man5
+
+.MAKE: $(am__recursive_targets) all check check-am install install-am \
+       install-exec-am install-strip uninstall-am
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+       check-TESTS check-am clean clean-binPROGRAMS \
+       clean-checkPROGRAMS clean-generic clean-libtool \
+       clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES \
+       clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \
+       distclean-compile distclean-generic distclean-hdr \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-binPROGRAMS \
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-exec-hook install-html \
+       install-html-am install-info install-info-am install-man \
+       install-man1 install-man5 install-pdf install-pdf-am \
+       install-pkglibLTLIBRARIES install-ps install-ps-am \
+       install-sbinPROGRAMS install-strip installcheck \
+       installcheck-am installdirs installdirs-am maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       recheck tags tags-am uninstall uninstall-am \
+       uninstall-binPROGRAMS uninstall-hook uninstall-man \
+       uninstall-man1 uninstall-man5 uninstall-pkglibLTLIBRARIES \
+       uninstall-sbinPROGRAMS
+
+
+.pod.1:
+       pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
+               >.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
+       @if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
+       then \
+               echo "$@ has some POD errors!"; false; \
+       fi
+
+.pod.5:
+       pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
+               >.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
+       @if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
+       then \
+               echo "$@ has some POD errors!"; false; \
+       fi
+
+@HAVE_PROTOC_C_TRUE@pinba.pb-c.c pinba.pb-c.h: pinba.proto
+@HAVE_PROTOC_C_TRUE@   protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto
+
+@HAVE_PROTOC_C_TRUE@riemann.pb-c.c riemann.pb-c.h: riemann.proto
+@HAVE_PROTOC_C_TRUE@   protoc-c -I$(srcdir) --c_out . $(srcdir)/riemann.proto
+
+install-exec-hook:
+       $(mkinstalldirs) $(DESTDIR)$(sysconfdir)
+       if test -e $(DESTDIR)$(sysconfdir)/collectd.conf; \
+       then \
+               $(INSTALL) -m 0640 collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf.pkg-orig; \
+       else \
+               $(INSTALL) -m 0640 collectd.conf $(DESTDIR)$(sysconfdir)/collectd.conf; \
+       fi; \
+       $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+       $(INSTALL) -m 0644 $(srcdir)/types.db $(DESTDIR)$(pkgdatadir)/types.db;
+       $(INSTALL) -m 0644 $(srcdir)/postgresql_default.conf \
+               $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
+
+uninstall-hook:
+       rm -f $(DESTDIR)$(pkgdatadir)/types.db;
+       rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
+       rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/aggregation.c b/src/aggregation.c
new file mode 100644 (file)
index 0000000..8175c66
--- /dev/null
@@ -0,0 +1,790 @@
+/**
+ * collectd - src/aggregation.c
+ * Copyright (C) 2012       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+
+#include <pthread.h>
+
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "meta_data.h"
+#include "utils_cache.h" /* for uc_get_rate() */
+#include "utils_subst.h"
+#include "utils_vl_lookup.h"
+
+#define AGG_MATCHES_ALL(str) (strcmp ("/.*/", str) == 0)
+#define AGG_FUNC_PLACEHOLDER "%{aggregation}"
+
+struct aggregation_s /* {{{ */
+{
+  identifier_t ident;
+  unsigned int group_by;
+
+  unsigned int regex_fields;
+
+  char *set_host;
+  char *set_plugin;
+  char *set_plugin_instance;
+  char *set_type_instance;
+
+  _Bool calc_num;
+  _Bool calc_sum;
+  _Bool calc_average;
+  _Bool calc_min;
+  _Bool calc_max;
+  _Bool calc_stddev;
+}; /* }}} */
+typedef struct aggregation_s aggregation_t;
+
+struct agg_instance_s;
+typedef struct agg_instance_s agg_instance_t;
+struct agg_instance_s /* {{{ */
+{
+  pthread_mutex_t lock;
+  identifier_t ident;
+
+  int ds_type;
+
+  derive_t num;
+  gauge_t sum;
+  gauge_t squares_sum;
+
+  gauge_t min;
+  gauge_t max;
+
+  rate_to_value_state_t *state_num;
+  rate_to_value_state_t *state_sum;
+  rate_to_value_state_t *state_average;
+  rate_to_value_state_t *state_min;
+  rate_to_value_state_t *state_max;
+  rate_to_value_state_t *state_stddev;
+
+  agg_instance_t *next;
+}; /* }}} */
+
+static lookup_t *lookup = NULL;
+
+static pthread_mutex_t agg_instance_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static agg_instance_t *agg_instance_list_head = NULL;
+
+static _Bool agg_is_regex (char const *str) /* {{{ */
+{
+  size_t len;
+
+  if (str == NULL)
+    return (0);
+
+  len = strlen (str);
+  if (len < 3)
+    return (0);
+
+  if ((str[0] == '/') && (str[len - 1] == '/'))
+    return (1);
+  else
+    return (0);
+} /* }}} _Bool agg_is_regex */
+
+static void agg_destroy (aggregation_t *agg) /* {{{ */
+{
+  sfree (agg);
+} /* }}} void agg_destroy */
+
+/* Frees all dynamically allocated memory within the instance. */
+static void agg_instance_destroy (agg_instance_t *inst) /* {{{ */
+{
+  if (inst == NULL)
+    return;
+
+  /* Remove this instance from the global list of instances. */
+  pthread_mutex_lock (&agg_instance_list_lock);
+  if (agg_instance_list_head == inst)
+    agg_instance_list_head = inst->next;
+  else if (agg_instance_list_head != NULL)
+  {
+    agg_instance_t *prev = agg_instance_list_head;
+    while ((prev != NULL) && (prev->next != inst))
+      prev = prev->next;
+    if (prev != NULL)
+      prev->next = inst->next;
+  }
+  pthread_mutex_unlock (&agg_instance_list_lock);
+
+  sfree (inst->state_num);
+  sfree (inst->state_sum);
+  sfree (inst->state_average);
+  sfree (inst->state_min);
+  sfree (inst->state_max);
+  sfree (inst->state_stddev);
+
+  memset (inst, 0, sizeof (*inst));
+  inst->ds_type = -1;
+  inst->min = NAN;
+  inst->max = NAN;
+} /* }}} void agg_instance_destroy */
+
+static int agg_instance_create_name (agg_instance_t *inst, /* {{{ */
+    value_list_t const *vl, aggregation_t const *agg)
+{
+#define COPY_FIELD(buffer, buffer_size, field, group_mask, all_value) do { \
+  if (agg->set_ ## field != NULL) \
+    sstrncpy (buffer, agg->set_ ## field, buffer_size); \
+  else if ((agg->regex_fields & group_mask) \
+      && (agg->group_by & group_mask)) \
+    sstrncpy (buffer, vl->field, buffer_size); \
+  else if ((agg->regex_fields & group_mask) \
+      && (AGG_MATCHES_ALL (agg->ident.field))) \
+    sstrncpy (buffer, all_value, buffer_size); \
+  else \
+    sstrncpy (buffer, agg->ident.field, buffer_size); \
+} while (0)
+
+  /* Host */
+  COPY_FIELD (inst->ident.host, sizeof (inst->ident.host),
+      host, LU_GROUP_BY_HOST, "global");
+
+  /* Plugin */
+  if (agg->set_plugin != NULL)
+    sstrncpy (inst->ident.plugin, agg->set_plugin,
+        sizeof (inst->ident.plugin));
+  else
+    sstrncpy (inst->ident.plugin, "aggregation", sizeof (inst->ident.plugin));
+
+  /* Plugin instance */
+  if (agg->set_plugin_instance != NULL)
+    sstrncpy (inst->ident.plugin_instance, agg->set_plugin_instance,
+        sizeof (inst->ident.plugin_instance));
+  else
+  {
+    char tmp_plugin[DATA_MAX_NAME_LEN];
+    char tmp_plugin_instance[DATA_MAX_NAME_LEN] = "";
+
+    if ((agg->regex_fields & LU_GROUP_BY_PLUGIN)
+        && (agg->group_by & LU_GROUP_BY_PLUGIN))
+      sstrncpy (tmp_plugin, vl->plugin, sizeof (tmp_plugin));
+    else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN)
+        && (AGG_MATCHES_ALL (agg->ident.plugin)))
+      sstrncpy (tmp_plugin, "", sizeof (tmp_plugin));
+    else
+      sstrncpy (tmp_plugin, agg->ident.plugin, sizeof (tmp_plugin));
+
+    if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE)
+        && (agg->group_by & LU_GROUP_BY_PLUGIN_INSTANCE))
+      sstrncpy (tmp_plugin_instance, vl->plugin_instance,
+          sizeof (tmp_plugin_instance));
+    else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE)
+        && (AGG_MATCHES_ALL (agg->ident.plugin_instance)))
+      sstrncpy (tmp_plugin_instance, "", sizeof (tmp_plugin_instance));
+    else
+      sstrncpy (tmp_plugin_instance, agg->ident.plugin_instance,
+          sizeof (tmp_plugin_instance));
+
+    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)
+      ssnprintf (inst->ident.plugin_instance,
+          sizeof (inst->ident.plugin_instance),
+          "%s-%s", tmp_plugin, AGG_FUNC_PLACEHOLDER);
+    else if (strcmp ("", tmp_plugin_instance) != 0)
+      ssnprintf (inst->ident.plugin_instance,
+          sizeof (inst->ident.plugin_instance),
+          "%s-%s", tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
+    else
+      ssnprintf (inst->ident.plugin_instance,
+          sizeof (inst->ident.plugin_instance),
+          "%s-%s-%s", tmp_plugin, tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
+  }
+
+  /* Type */
+  sstrncpy (inst->ident.type, agg->ident.type, sizeof (inst->ident.type));
+
+  /* Type instance */
+  COPY_FIELD (inst->ident.type_instance, sizeof (inst->ident.type_instance),
+      type_instance, LU_GROUP_BY_TYPE_INSTANCE, "");
+
+#undef COPY_FIELD
+
+  return (0);
+} /* }}} int agg_instance_create_name */
+
+/* Create a new aggregation instance. */
+static agg_instance_t *agg_instance_create (data_set_t const *ds, /* {{{ */
+    value_list_t const *vl, aggregation_t *agg)
+{
+  agg_instance_t *inst;
+
+  DEBUG ("aggregation plugin: Creating new instance.");
+
+  inst = malloc (sizeof (*inst));
+  if (inst == NULL)
+  {
+    ERROR ("aggregation plugin: malloc() failed.");
+    return (NULL);
+  }
+  memset (inst, 0, sizeof (*inst));
+  pthread_mutex_init (&inst->lock, /* attr = */ NULL);
+
+  inst->ds_type = ds->ds[0].type;
+
+  agg_instance_create_name (inst, vl, agg);
+
+  inst->min = NAN;
+  inst->max = NAN;
+
+#define INIT_STATE(field) do { \
+  inst->state_ ## field = NULL; \
+  if (agg->calc_ ## field) { \
+    inst->state_ ## field = malloc (sizeof (*inst->state_ ## field)); \
+    if (inst->state_ ## field == NULL) { \
+      agg_instance_destroy (inst); \
+      ERROR ("aggregation plugin: malloc() failed."); \
+      return (NULL); \
+    } \
+    memset (inst->state_ ## field, 0, sizeof (*inst->state_ ## field)); \
+  } \
+} while (0)
+
+  INIT_STATE (num);
+  INIT_STATE (sum);
+  INIT_STATE (average);
+  INIT_STATE (min);
+  INIT_STATE (max);
+  INIT_STATE (stddev);
+
+#undef INIT_STATE
+
+  pthread_mutex_lock (&agg_instance_list_lock);
+  inst->next = agg_instance_list_head;
+  agg_instance_list_head = inst;
+  pthread_mutex_unlock (&agg_instance_list_lock);
+
+  return (inst);
+} /* }}} agg_instance_t *agg_instance_create */
+
+/* Update the num, sum, min, max, ... fields of the aggregation instance, if
+ * the rate of the value list is available. Value lists with more than one data
+ * source are not supported and will return an error. Returns zero on success
+ * and non-zero otherwise. */
+static int agg_instance_update (agg_instance_t *inst, /* {{{ */
+    data_set_t const *ds, value_list_t const *vl)
+{
+  gauge_t *rate;
+
+  if (ds->ds_num != 1)
+  {
+    ERROR ("aggregation plugin: The \"%s\" type (data set) has more than one "
+        "data source. This is currently not supported by this plugin. "
+        "Sorry.", ds->type);
+    return (EINVAL);
+  }
+
+  rate = uc_get_rate (ds, vl);
+  if (rate == NULL)
+  {
+    char ident[6 * DATA_MAX_NAME_LEN];
+    FORMAT_VL (ident, sizeof (ident), vl);
+    ERROR ("aggregation plugin: Unable to read the current rate of \"%s\".",
+        ident);
+    return (ENOENT);
+  }
+
+  if (isnan (rate[0]))
+  {
+    sfree (rate);
+    return (0);
+  }
+
+  pthread_mutex_lock (&inst->lock);
+
+  inst->num++;
+  inst->sum += rate[0];
+  inst->squares_sum += (rate[0] * rate[0]);
+
+  if (isnan (inst->min) || (inst->min > rate[0]))
+    inst->min = rate[0];
+  if (isnan (inst->max) || (inst->max < rate[0]))
+    inst->max = rate[0];
+
+  pthread_mutex_unlock (&inst->lock);
+
+  sfree (rate);
+  return (0);
+} /* }}} int agg_instance_update */
+
+static int agg_instance_read_func (agg_instance_t *inst, /* {{{ */
+  char const *func, gauge_t rate, rate_to_value_state_t *state,
+  value_list_t *vl, char const *pi_prefix, cdtime_t t)
+{
+  value_t v;
+  int status;
+
+  if (pi_prefix[0] != 0)
+    subst_string (vl->plugin_instance, sizeof (vl->plugin_instance),
+        pi_prefix, AGG_FUNC_PLACEHOLDER, func);
+  else
+    sstrncpy (vl->plugin_instance, func, sizeof (vl->plugin_instance));
+
+  memset (&v, 0, sizeof (v));
+  status = rate_to_value (&v, rate, state, inst->ds_type, t);
+  if (status != 0)
+  {
+    /* If this is the first iteration and rate_to_value() was asked to return a
+     * COUNTER or a DERIVE, it will return EAGAIN. Catch this and handle
+     * gracefully. */
+    if (status == EAGAIN)
+      return (0);
+
+    WARNING ("aggregation plugin: rate_to_value failed with status %i.",
+        status);
+    return (-1);
+  }
+
+  vl->values = &v;
+  vl->values_len = 1;
+
+  plugin_dispatch_values (vl);
+
+  vl->values = NULL;
+  vl->values_len = 0;
+
+  return (0);
+} /* }}} int agg_instance_read_func */
+
+static int agg_instance_read (agg_instance_t *inst, cdtime_t t) /* {{{ */
+{
+  value_list_t vl = VALUE_LIST_INIT;
+
+  /* Pre-set all the fields in the value list that will not change per
+   * aggregation type (sum, average, ...). The struct will be re-used and must
+   * therefore be dispatched using the "secure" function. */
+
+  vl.time = t;
+  vl.interval = 0;
+
+  vl.meta = meta_data_create ();
+  if (vl.meta == NULL)
+  {
+    ERROR ("aggregation plugin: meta_data_create failed.");
+    return (-1);
+  }
+  meta_data_add_boolean (vl.meta, "aggregation:created", 1);
+
+  sstrncpy (vl.host, inst->ident.host, sizeof (vl.host));
+  sstrncpy (vl.plugin, inst->ident.plugin, sizeof (vl.plugin));
+  sstrncpy (vl.type, inst->ident.type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, inst->ident.type_instance,
+      sizeof (vl.type_instance));
+
+#define READ_FUNC(func, rate) do { \
+  if (inst->state_ ## func != NULL) { \
+    agg_instance_read_func (inst, #func, rate, \
+        inst->state_ ## func, &vl, inst->ident.plugin_instance, t); \
+  } \
+} while (0)
+
+  pthread_mutex_lock (&inst->lock);
+
+  READ_FUNC (num, (gauge_t) inst->num);
+
+  /* All other aggregations are only defined when there have been any values
+   * at all. */
+  if (inst->num > 0)
+  {
+    READ_FUNC (sum, inst->sum);
+    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));
+  }
+
+  /* Reset internal state. */
+  inst->num = 0;
+  inst->sum = 0.0;
+  inst->squares_sum = 0.0;
+  inst->min = NAN;
+  inst->max = NAN;
+
+  pthread_mutex_unlock (&inst->lock);
+
+  meta_data_destroy (vl.meta);
+  vl.meta = NULL;
+
+  return (0);
+} /* }}} int agg_instance_read */
+
+/* lookup_class_callback_t for utils_vl_lookup */
+static void *agg_lookup_class_callback ( /* {{{ */
+    data_set_t const *ds, value_list_t const *vl, void *user_class)
+{
+  return (agg_instance_create (ds, vl, (aggregation_t *) user_class));
+} /* }}} void *agg_class_callback */
+
+/* lookup_obj_callback_t for utils_vl_lookup */
+static int agg_lookup_obj_callback (data_set_t const *ds, /* {{{ */
+    value_list_t const *vl,
+    __attribute__((unused)) void *user_class,
+    void *user_obj)
+{
+  return (agg_instance_update ((agg_instance_t *) user_obj, ds, vl));
+} /* }}} int agg_lookup_obj_callback */
+
+/* lookup_free_class_callback_t for utils_vl_lookup */
+static void agg_lookup_free_class_callback (void *user_class) /* {{{ */
+{
+  agg_destroy ((aggregation_t *) user_class);
+} /* }}} void agg_lookup_free_class_callback */
+
+/* lookup_free_obj_callback_t for utils_vl_lookup */
+static void agg_lookup_free_obj_callback (void *user_obj) /* {{{ */
+{
+  agg_instance_destroy ((agg_instance_t *) user_obj);
+} /* }}} void agg_lookup_free_obj_callback */
+
+/*
+ * <Plugin "aggregation">
+ *   <Aggregation>
+ *     Plugin "cpu"
+ *     Type "cpu"
+ *
+ *     GroupBy Host
+ *     GroupBy TypeInstance
+ *
+ *     CalculateNum true
+ *     CalculateSum true
+ *     CalculateAverage true
+ *     CalculateMinimum true
+ *     CalculateMaximum true
+ *     CalculateStddev true
+ *   </Aggregation>
+ * </Plugin>
+ */
+static int agg_config_handle_group_by (oconfig_item_t const *ci, /* {{{ */
+    aggregation_t *agg)
+{
+  int i;
+
+  for (i = 0; i < ci->values_num; i++)
+  {
+    char const *value;
+
+    if (ci->values[i].type != OCONFIG_TYPE_STRING)
+    {
+      ERROR ("aggregation plugin: Argument %i of the \"GroupBy\" option "
+          "is not a string.", i + 1);
+      continue;
+    }
+
+    value = ci->values[i].value.string;
+
+    if (strcasecmp ("Host", value) == 0)
+      agg->group_by |= LU_GROUP_BY_HOST;
+    else if (strcasecmp ("Plugin", value) == 0)
+      agg->group_by |= LU_GROUP_BY_PLUGIN;
+    else if (strcasecmp ("PluginInstance", value) == 0)
+      agg->group_by |= LU_GROUP_BY_PLUGIN_INSTANCE;
+    else if (strcasecmp ("TypeInstance", value) == 0)
+      agg->group_by |= LU_GROUP_BY_TYPE_INSTANCE;
+    else if (strcasecmp ("Type", value) == 0)
+      ERROR ("aggregation plugin: Grouping by type is not supported.");
+    else
+      WARNING ("aggregation plugin: The \"%s\" argument to the \"GroupBy\" "
+          "option is invalid and will be ignored.", value);
+  } /* for (ci->values) */
+
+  return (0);
+} /* }}} int agg_config_handle_group_by */
+
+static int agg_config_aggregation (oconfig_item_t *ci) /* {{{ */
+{
+  aggregation_t *agg;
+  _Bool is_valid;
+  int status;
+  int i;
+
+  agg = malloc (sizeof (*agg));
+  if (agg == NULL)
+  {
+    ERROR ("aggregation plugin: malloc failed.");
+    return (-1);
+  }
+  memset (agg, 0, sizeof (*agg));
+
+  sstrncpy (agg->ident.host, "/.*/", sizeof (agg->ident.host));
+  sstrncpy (agg->ident.plugin, "/.*/", sizeof (agg->ident.plugin));
+  sstrncpy (agg->ident.plugin_instance, "/.*/",
+      sizeof (agg->ident.plugin_instance));
+  sstrncpy (agg->ident.type, "/.*/", sizeof (agg->ident.type));
+  sstrncpy (agg->ident.type_instance, "/.*/",
+      sizeof (agg->ident.type_instance));
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      cf_util_get_string_buffer (child, agg->ident.host,
+          sizeof (agg->ident.host));
+    else if (strcasecmp ("Plugin", child->key) == 0)
+      cf_util_get_string_buffer (child, agg->ident.plugin,
+          sizeof (agg->ident.plugin));
+    else if (strcasecmp ("PluginInstance", child->key) == 0)
+      cf_util_get_string_buffer (child, agg->ident.plugin_instance,
+          sizeof (agg->ident.plugin_instance));
+    else if (strcasecmp ("Type", child->key) == 0)
+      cf_util_get_string_buffer (child, agg->ident.type,
+          sizeof (agg->ident.type));
+    else if (strcasecmp ("TypeInstance", child->key) == 0)
+      cf_util_get_string_buffer (child, agg->ident.type_instance,
+          sizeof (agg->ident.type_instance));
+    else if (strcasecmp ("SetHost", child->key) == 0)
+      cf_util_get_string (child, &agg->set_host);
+    else if (strcasecmp ("SetPlugin", child->key) == 0)
+      cf_util_get_string (child, &agg->set_plugin);
+    else if (strcasecmp ("SetPluginInstance", child->key) == 0)
+      cf_util_get_string (child, &agg->set_plugin_instance);
+    else if (strcasecmp ("SetTypeInstance", child->key) == 0)
+      cf_util_get_string (child, &agg->set_type_instance);
+    else if (strcasecmp ("GroupBy", child->key) == 0)
+      agg_config_handle_group_by (child, agg);
+    else if (strcasecmp ("CalculateNum", child->key) == 0)
+      cf_util_get_boolean (child, &agg->calc_num);
+    else if (strcasecmp ("CalculateSum", child->key) == 0)
+      cf_util_get_boolean (child, &agg->calc_sum);
+    else if (strcasecmp ("CalculateAverage", child->key) == 0)
+      cf_util_get_boolean (child, &agg->calc_average);
+    else if (strcasecmp ("CalculateMinimum", child->key) == 0)
+      cf_util_get_boolean (child, &agg->calc_min);
+    else if (strcasecmp ("CalculateMaximum", child->key) == 0)
+      cf_util_get_boolean (child, &agg->calc_max);
+    else if (strcasecmp ("CalculateStddev", child->key) == 0)
+      cf_util_get_boolean (child, &agg->calc_stddev);
+    else
+      WARNING ("aggregation plugin: The \"%s\" key is not allowed inside "
+          "<Aggregation /> blocks and will be ignored.", child->key);
+  }
+
+  if (agg_is_regex (agg->ident.host))
+    agg->regex_fields |= LU_GROUP_BY_HOST;
+  if (agg_is_regex (agg->ident.plugin))
+    agg->regex_fields |= LU_GROUP_BY_PLUGIN;
+  if (agg_is_regex (agg->ident.plugin_instance))
+    agg->regex_fields |= LU_GROUP_BY_PLUGIN_INSTANCE;
+  if (agg_is_regex (agg->ident.type_instance))
+    agg->regex_fields |= LU_GROUP_BY_TYPE_INSTANCE;
+
+  /* Sanity checking */
+  is_valid = 1;
+  if (strcmp ("/.*/", agg->ident.type) == 0) /* {{{ */
+  {
+    ERROR ("aggregation plugin: It appears you did not specify the required "
+        "\"Type\" option in this aggregation. "
+        "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", "
+        "Type \"%s\", TypeInstance \"%s\")",
+        agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance,
+        agg->ident.type, agg->ident.type_instance);
+    is_valid = 0;
+  }
+  else if (strchr (agg->ident.type, '/') != NULL)
+  {
+    ERROR ("aggregation plugin: The \"Type\" may not contain the '/' "
+        "character. Especially, it may not be a regex. The current "
+        "value is \"%s\".", agg->ident.type);
+    is_valid = 0;
+  } /* }}} */
+
+  /* Check that there is at least one regex field without a grouping. {{{ */
+  if ((agg->regex_fields & ~agg->group_by) == 0)
+  {
+    ERROR ("aggregation plugin: An aggregation must contain at least one "
+        "wildcard. This is achieved by leaving at least one of the \"Host\", "
+        "\"Plugin\", \"PluginInstance\" and \"TypeInstance\" options blank "
+        "or using a regular expression and not grouping by that field. "
+        "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", "
+        "Type \"%s\", TypeInstance \"%s\")",
+        agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance,
+        agg->ident.type, agg->ident.type_instance);
+    is_valid = 0;
+  } /* }}} */
+
+  /* Check that all grouping fields are regular expressions. {{{ */
+  if (agg->group_by & ~agg->regex_fields)
+  {
+    ERROR ("aggregation plugin: Only wildcard fields (fields for which a "
+        "regular expression is configured or which are left blank) can be "
+        "specified in the \"GroupBy\" option. "
+        "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", "
+        "Type \"%s\", TypeInstance \"%s\")",
+        agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance,
+        agg->ident.type, agg->ident.type_instance);
+    is_valid = 0;
+  } /* }}} */
+
+  if (!agg->calc_num && !agg->calc_sum && !agg->calc_average /* {{{ */
+      && !agg->calc_min && !agg->calc_max && !agg->calc_stddev)
+  {
+    ERROR ("aggregation plugin: No aggregation function has been specified. "
+        "Without this, I don't know what I should be calculating. "
+        "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", "
+        "Type \"%s\", TypeInstance \"%s\")",
+        agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance,
+        agg->ident.type, agg->ident.type_instance);
+    is_valid = 0;
+  } /* }}} */
+
+  if (!is_valid) /* {{{ */
+  {
+    sfree (agg);
+    return (-1);
+  } /* }}} */
+
+  status = lookup_add (lookup, &agg->ident, agg->group_by, agg);
+  if (status != 0)
+  {
+    ERROR ("aggregation plugin: lookup_add failed with status %i.", status);
+    sfree (agg);
+    return (-1);
+  }
+
+  DEBUG ("aggregation plugin: Successfully added aggregation: "
+      "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", "
+      "Type \"%s\", TypeInstance \"%s\")",
+      agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance,
+      agg->ident.type, agg->ident.type_instance);
+  return (0);
+} /* }}} int agg_config_aggregation */
+
+static int agg_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  pthread_mutex_lock (&agg_instance_list_lock);
+
+  if (lookup == NULL)
+  {
+    lookup = lookup_create (agg_lookup_class_callback,
+        agg_lookup_obj_callback,
+        agg_lookup_free_class_callback,
+        agg_lookup_free_obj_callback);
+    if (lookup == NULL)
+    {
+      pthread_mutex_unlock (&agg_instance_list_lock);
+      ERROR ("aggregation plugin: lookup_create failed.");
+      return (-1);
+    }
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Aggregation", child->key) == 0)
+      agg_config_aggregation (child);
+    else
+      WARNING ("aggregation plugin: The \"%s\" key is not allowed inside "
+          "<Plugin aggregation /> blocks and will be ignored.", child->key);
+  }
+
+  pthread_mutex_unlock (&agg_instance_list_lock);
+
+  return (0);
+} /* }}} int agg_config */
+
+static int agg_read (void) /* {{{ */
+{
+  agg_instance_t *this;
+  cdtime_t t;
+  int success;
+
+  t = cdtime ();
+  success = 0;
+
+  pthread_mutex_lock (&agg_instance_list_lock);
+
+  /* agg_instance_list_head only holds data, after the "write" callback has
+   * been called with a matching value list at least once. So on startup,
+   * there's a race between the aggregations read() and write() callback. If
+   * the read() callback is called first, agg_instance_list_head is NULL and
+   * "success" may be zero. This is expected and should not result in an error.
+   * Therefore we need to handle this case separately. */
+  if (agg_instance_list_head == NULL)
+  {
+    pthread_mutex_unlock (&agg_instance_list_lock);
+    return (0);
+  }
+
+  for (this = agg_instance_list_head; this != NULL; this = this->next)
+  {
+    int status;
+
+    status = agg_instance_read (this, t);
+    if (status != 0)
+      WARNING ("aggregation plugin: Reading an aggregation instance "
+          "failed with status %i.", status);
+    else
+      success++;
+  }
+
+  pthread_mutex_unlock (&agg_instance_list_lock);
+
+  return ((success > 0) ? 0 : -1);
+} /* }}} int agg_read */
+
+static int agg_write (data_set_t const *ds, value_list_t const *vl, /* {{{ */
+    __attribute__((unused)) user_data_t *user_data)
+{
+  _Bool created_by_aggregation = 0;
+  int status;
+
+  /* Ignore values that were created by the aggregation plugin to avoid weird
+   * effects. */
+  (void) meta_data_get_boolean (vl->meta, "aggregation:created",
+      &created_by_aggregation);
+  if (created_by_aggregation)
+    return (0);
+
+  if (lookup == NULL)
+    status = ENOENT;
+  else
+  {
+    status = lookup_search (lookup, ds, vl);
+    if (status > 0)
+      status = 0;
+  }
+
+  return (status);
+} /* }}} int agg_write */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("aggregation", agg_config);
+  plugin_register_read ("aggregation", agg_read);
+  plugin_register_write ("aggregation", agg_write, /* user_data = */ NULL);
+}
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
diff --git a/src/amqp.c b/src/amqp.c
new file mode 100644 (file)
index 0000000..97359cf
--- /dev/null
@@ -0,0 +1,1131 @@
+/**
+ * collectd - src/amqp.c
+ * Copyright (C) 2009       Sebastien Pahl
+ * Copyright (C) 2010-2012  Florian Forster
+ *
+ * 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:
+ *   Sebastien Pahl <sebastien.pahl at dotcloud.com>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_cmd_putval.h"
+#include "utils_format_json.h"
+#include "utils_format_graphite.h"
+
+#include <pthread.h>
+
+#include <amqp.h>
+#include <amqp_framing.h>
+
+#ifdef HAVE_AMQP_TCP_SOCKET_H
+# include <amqp_tcp_socket.h>
+#endif
+#ifdef HAVE_AMQP_SOCKET_H
+# include <amqp_socket.h>
+#endif
+#ifdef HAVE_AMQP_TCP_SOCKET
+#if defined HAVE_DECL_AMQP_SOCKET_CLOSE && !HAVE_DECL_AMQP_SOCKET_CLOSE
+/* rabbitmq-c does not currently ship amqp_socket.h
+ * and, thus, does not define this function. */
+int amqp_socket_close(amqp_socket_t *);
+#endif
+#endif
+
+/* Defines for the delivery mode. I have no idea why they're not defined by the
+ * library.. */
+#define CAMQP_DM_VOLATILE   1
+#define CAMQP_DM_PERSISTENT 2
+
+#define CAMQP_FORMAT_COMMAND    1
+#define CAMQP_FORMAT_JSON       2
+#define CAMQP_FORMAT_GRAPHITE   3
+
+#define CAMQP_CHANNEL 1
+
+/*
+ * Data types
+ */
+struct camqp_config_s
+{
+    _Bool   publish;
+    char   *name;
+
+    char   *host;
+    int     port;
+    char   *vhost;
+    char   *user;
+    char   *password;
+
+    char   *exchange;
+    char   *routing_key;
+
+    /* Number of seconds to wait before connection is retried */
+    int     connection_retry_delay;
+
+    /* publish only */
+    uint8_t delivery_mode;
+    _Bool   store_rates;
+    int     format;
+    /* publish & graphite format only */
+    char    *prefix;
+    char    *postfix;
+    char    escape_char;
+    unsigned int graphite_flags;
+
+    /* subscribe only */
+    char   *exchange_type;
+    char   *queue;
+    _Bool   queue_durable;
+    _Bool   queue_auto_delete;
+
+    amqp_connection_state_t connection;
+    pthread_mutex_t lock;
+};
+typedef struct camqp_config_s camqp_config_t;
+
+/*
+ * Global variables
+ */
+static const char *def_host       = "localhost";
+static const char *def_vhost      = "/";
+static const char *def_user       = "guest";
+static const char *def_password   = "guest";
+static const char *def_exchange   = "amq.fanout";
+
+static pthread_t *subscriber_threads     = NULL;
+static size_t     subscriber_threads_num = 0;
+static _Bool      subscriber_threads_running = 1;
+
+#define CONF(c,f) (((c)->f != NULL) ? (c)->f : def_##f)
+
+/*
+ * Functions
+ */
+static void camqp_close_connection (camqp_config_t *conf) /* {{{ */
+{
+    int sockfd;
+
+    if ((conf == NULL) || (conf->connection == NULL))
+        return;
+
+    sockfd = amqp_get_sockfd (conf->connection);
+    amqp_channel_close (conf->connection, CAMQP_CHANNEL, AMQP_REPLY_SUCCESS);
+    amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS);
+    amqp_destroy_connection (conf->connection);
+    close (sockfd);
+    conf->connection = NULL;
+} /* }}} void camqp_close_connection */
+
+static void camqp_config_free (void *ptr) /* {{{ */
+{
+    camqp_config_t *conf = ptr;
+
+    if (conf == NULL)
+        return;
+
+    camqp_close_connection (conf);
+
+    sfree (conf->name);
+    sfree (conf->host);
+    sfree (conf->vhost);
+    sfree (conf->user);
+    sfree (conf->password);
+    sfree (conf->exchange);
+    sfree (conf->exchange_type);
+    sfree (conf->queue);
+    sfree (conf->routing_key);
+    sfree (conf->prefix);
+    sfree (conf->postfix);
+
+
+    sfree (conf);
+} /* }}} void camqp_config_free */
+
+static char *camqp_bytes_cstring (amqp_bytes_t *in) /* {{{ */
+{
+    char *ret;
+
+    if ((in == NULL) || (in->bytes == NULL))
+        return (NULL);
+
+    ret = malloc (in->len + 1);
+    if (ret == NULL)
+        return (NULL);
+
+    memcpy (ret, in->bytes, in->len);
+    ret[in->len] = 0;
+
+    return (ret);
+} /* }}} char *camqp_bytes_cstring */
+
+static _Bool camqp_is_error (camqp_config_t *conf) /* {{{ */
+{
+    amqp_rpc_reply_t r;
+
+    r = amqp_get_rpc_reply (conf->connection);
+    if (r.reply_type == AMQP_RESPONSE_NORMAL)
+        return (0);
+
+    return (1);
+} /* }}} _Bool camqp_is_error */
+
+static char *camqp_strerror (camqp_config_t *conf, /* {{{ */
+        char *buffer, size_t buffer_size)
+{
+    amqp_rpc_reply_t r;
+
+    r = amqp_get_rpc_reply (conf->connection);
+    switch (r.reply_type)
+    {
+        case AMQP_RESPONSE_NORMAL:
+            sstrncpy (buffer, "Success", sizeof (buffer));
+            break;
+
+        case AMQP_RESPONSE_NONE:
+            sstrncpy (buffer, "Missing RPC reply type", sizeof (buffer));
+            break;
+
+        case AMQP_RESPONSE_LIBRARY_EXCEPTION:
+#if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO
+            if (r.library_errno)
+                return (sstrerror (r.library_errno, buffer, buffer_size));
+#else
+            if (r.library_error)
+                return (sstrerror (r.library_error, buffer, buffer_size));
+#endif
+            else
+                sstrncpy (buffer, "End of stream", sizeof (buffer));
+            break;
+
+        case AMQP_RESPONSE_SERVER_EXCEPTION:
+            if (r.reply.id == AMQP_CONNECTION_CLOSE_METHOD)
+            {
+                amqp_connection_close_t *m = r.reply.decoded;
+                char *tmp = camqp_bytes_cstring (&m->reply_text);
+                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);
+                ssnprintf (buffer, buffer_size, "Server channel error %d: %s",
+                        m->reply_code, tmp);
+                sfree (tmp);
+            }
+            else
+            {
+                ssnprintf (buffer, buffer_size, "Server error method %#"PRIx32,
+                        r.reply.id);
+            }
+            break;
+
+        default:
+            ssnprintf (buffer, buffer_size, "Unknown reply type %i",
+                    (int) r.reply_type);
+    }
+
+    return (buffer);
+} /* }}} char *camqp_strerror */
+
+#if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO
+static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */
+{
+    amqp_exchange_declare_ok_t *ed_ret;
+
+    if (conf->exchange_type == NULL)
+        return (0);
+
+    ed_ret = amqp_exchange_declare (conf->connection,
+            /* channel     = */ CAMQP_CHANNEL,
+            /* exchange    = */ amqp_cstring_bytes (conf->exchange),
+            /* type        = */ amqp_cstring_bytes (conf->exchange_type),
+            /* passive     = */ 0,
+            /* durable     = */ 0,
+            /* auto_delete = */ 1,
+            /* arguments   = */ AMQP_EMPTY_TABLE);
+    if ((ed_ret == NULL) && camqp_is_error (conf))
+    {
+        char errbuf[1024];
+        ERROR ("amqp plugin: amqp_exchange_declare failed: %s",
+                camqp_strerror (conf, errbuf, sizeof (errbuf)));
+        camqp_close_connection (conf);
+        return (-1);
+    }
+
+    INFO ("amqp plugin: Successfully created exchange \"%s\" "
+            "with type \"%s\".",
+            conf->exchange, conf->exchange_type);
+
+    return (0);
+} /* }}} int camqp_create_exchange */
+#else
+static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */
+{
+    amqp_exchange_declare_ok_t *ed_ret;
+    amqp_table_t argument_table;
+    struct amqp_table_entry_t_ argument_table_entries[1];
+
+    if (conf->exchange_type == NULL)
+        return (0);
+
+    /* Valid arguments: "auto_delete", "internal" */
+    argument_table.num_entries = STATIC_ARRAY_SIZE (argument_table_entries);
+    argument_table.entries = argument_table_entries;
+    argument_table_entries[0].key = amqp_cstring_bytes ("auto_delete");
+    argument_table_entries[0].value.kind = AMQP_FIELD_KIND_BOOLEAN;
+    argument_table_entries[0].value.value.boolean = 1;
+
+    ed_ret = amqp_exchange_declare (conf->connection,
+            /* channel     = */ CAMQP_CHANNEL,
+            /* exchange    = */ amqp_cstring_bytes (conf->exchange),
+            /* type        = */ amqp_cstring_bytes (conf->exchange_type),
+            /* passive     = */ 0,
+            /* durable     = */ 0,
+#if defined(AMQP_VERSION) && AMQP_VERSION >= 0x00060000
+            /* auto delete = */ 0,
+            /* internal    = */ 0,
+#endif
+            /* arguments   = */ argument_table);
+    if ((ed_ret == NULL) && camqp_is_error (conf))
+    {
+        char errbuf[1024];
+        ERROR ("amqp plugin: amqp_exchange_declare failed: %s",
+                camqp_strerror (conf, errbuf, sizeof (errbuf)));
+        camqp_close_connection (conf);
+        return (-1);
+    }
+
+    INFO ("amqp plugin: Successfully created exchange \"%s\" "
+            "with type \"%s\".",
+            conf->exchange, conf->exchange_type);
+
+    return (0);
+} /* }}} int camqp_create_exchange */
+#endif
+
+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);
+    if (qd_ret == NULL)
+    {
+        ERROR ("amqp plugin: amqp_queue_declare failed.");
+        camqp_close_connection (conf);
+        return (-1);
+    }
+
+    if (conf->queue == NULL)
+    {
+        conf->queue = camqp_bytes_cstring (&qd_ret->queue);
+        if (conf->queue == NULL)
+        {
+            ERROR ("amqp plugin: camqp_bytes_cstring failed.");
+            camqp_close_connection (conf);
+            return (-1);
+        }
+
+        INFO ("amqp plugin: Created queue \"%s\".", conf->queue);
+    }
+    DEBUG ("amqp plugin: Successfully created queue \"%s\".", conf->queue);
+
+    /* bind to an exchange */
+    if (conf->exchange != NULL)
+    {
+        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);
+        if ((qb_ret == NULL) && camqp_is_error (conf))
+        {
+            char errbuf[1024];
+            ERROR ("amqp plugin: amqp_queue_bind failed: %s",
+                    camqp_strerror (conf, errbuf, sizeof (errbuf)));
+            camqp_close_connection (conf);
+            return (-1);
+        }
+
+        DEBUG ("amqp plugin: Successfully bound queue \"%s\" to exchange \"%s\".",
+                conf->queue, conf->exchange);
+    } /* if (conf->exchange != NULL) */
+
+    cm_ret = amqp_basic_consume (conf->connection,
+            /* channel      = */ CAMQP_CHANNEL,
+            /* queue        = */ amqp_cstring_bytes (conf->queue),
+            /* consumer_tag = */ AMQP_EMPTY_BYTES,
+            /* no_local     = */ 0,
+            /* no_ack       = */ 1,
+            /* exclusive    = */ 0,
+            /* arguments    = */ AMQP_EMPTY_TABLE
+        );
+    if ((cm_ret == NULL) && camqp_is_error (conf))
+    {
+        char errbuf[1024];
+        ERROR ("amqp plugin: amqp_basic_consume failed: %s",
+                    camqp_strerror (conf, errbuf, sizeof (errbuf)));
+        camqp_close_connection (conf);
+        return (-1);
+    }
+
+    return (0);
+} /* }}} int camqp_setup_queue */
+
+static int camqp_connect (camqp_config_t *conf) /* {{{ */
+{
+    static time_t last_connect_time = 0;
+
+    amqp_rpc_reply_t reply;
+    int status;
+#ifdef HAVE_AMQP_TCP_SOCKET
+    amqp_socket_t *socket;
+#else
+    int sockfd;
+#endif
+
+    if (conf->connection != NULL)
+        return (0);
+
+    time_t now = time(NULL);
+    if (now < (last_connect_time + conf->connection_retry_delay))
+    {
+        DEBUG("amqp plugin: skipping connection retry, "
+            "ConnectionRetryDelay: %d", conf->connection_retry_delay);
+        return(1);
+    }
+    else
+    {
+        DEBUG ("amqp plugin: retrying connection");
+        last_connect_time = now;
+    }
+
+    conf->connection = amqp_new_connection ();
+    if (conf->connection == NULL)
+    {
+        ERROR ("amqp plugin: amqp_new_connection failed.");
+        return (ENOMEM);
+    }
+
+#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);
+    if (! socket)
+    {
+        ERROR ("amqp plugin: amqp_tcp_socket_new failed.");
+        amqp_destroy_connection (conf->connection);
+        conf->connection = NULL;
+        return (ENOMEM);
+    }
+
+    status = amqp_socket_open (socket, CONF(conf, host), conf->port);
+    if (status < 0)
+    {
+        char errbuf[1024];
+        status *= -1;
+        ERROR ("amqp plugin: amqp_socket_open failed: %s",
+                sstrerror (status, errbuf, sizeof (errbuf)));
+        amqp_destroy_connection (conf->connection);
+        conf->connection = NULL;
+        return (status);
+    }
+#else /* HAVE_AMQP_TCP_SOCKET */
+# define CLOSE_SOCKET() close(sockfd)
+    /* this interface is deprecated as of rabbitmq-c 0.4 */
+    sockfd = amqp_open_socket (CONF(conf, host), conf->port);
+    if (sockfd < 0)
+    {
+        char errbuf[1024];
+        status = (-1) * sockfd;
+        ERROR ("amqp plugin: amqp_open_socket failed: %s",
+                sstrerror (status, errbuf, sizeof (errbuf)));
+        amqp_destroy_connection (conf->connection);
+        conf->connection = NULL;
+        return (status);
+    }
+    amqp_set_sockfd (conf->connection, sockfd);
+#endif
+
+    reply = amqp_login (conf->connection, CONF(conf, vhost),
+            /* channel max = */      0,
+            /* frame max   = */ 131072,
+            /* heartbeat   = */      0,
+            /* authentication = */ AMQP_SASL_METHOD_PLAIN,
+            CONF(conf, user), CONF(conf, password));
+    if (reply.reply_type != AMQP_RESPONSE_NORMAL)
+    {
+        ERROR ("amqp plugin: amqp_login (vhost = %s, user = %s) failed.",
+                CONF(conf, vhost), CONF(conf, user));
+        amqp_destroy_connection (conf->connection);
+        CLOSE_SOCKET ();
+        conf->connection = NULL;
+        return (1);
+    }
+
+    amqp_channel_open (conf->connection, /* channel = */ 1);
+    /* FIXME: Is checking "reply.reply_type" really correct here? How does
+     * it get set? --octo */
+    if (reply.reply_type != AMQP_RESPONSE_NORMAL)
+    {
+        ERROR ("amqp plugin: amqp_channel_open failed.");
+        amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS);
+        amqp_destroy_connection (conf->connection);
+        CLOSE_SOCKET ();
+        conf->connection = NULL;
+        return (1);
+    }
+
+    INFO ("amqp plugin: Successfully opened connection to vhost \"%s\" "
+            "on %s:%i.", CONF(conf, vhost), CONF(conf, host), conf->port);
+
+    status = camqp_create_exchange (conf);
+    if (status != 0)
+        return (status);
+
+    if (!conf->publish)
+        return (camqp_setup_queue (conf));
+    return (0);
+} /* }}} int camqp_connect */
+
+static int camqp_shutdown (void) /* {{{ */
+{
+    size_t i;
+
+    DEBUG ("amqp plugin: Shutting down %zu subscriber threads.",
+            subscriber_threads_num);
+
+    subscriber_threads_running = 0;
+    for (i = 0; i < subscriber_threads_num; i++)
+    {
+        /* FIXME: Sending a signal is not very elegant here. Maybe find out how
+         * to use a timeout in the thread and check for the variable in regular
+         * intervals. */
+        pthread_kill (subscriber_threads[i], SIGTERM);
+        pthread_join (subscriber_threads[i], /* retval = */ NULL);
+    }
+
+    subscriber_threads_num = 0;
+    sfree (subscriber_threads);
+
+    DEBUG ("amqp plugin: All subscriber threads exited.");
+
+    return (0);
+} /* }}} int camqp_shutdown */
+
+/*
+ * Subscribing code
+ */
+static int camqp_read_body (camqp_config_t *conf, /* {{{ */
+        size_t body_size, const char *content_type)
+{
+    char body[body_size + 1];
+    char *body_ptr;
+    size_t received;
+    amqp_frame_t frame;
+    int status;
+
+    memset (body, 0, sizeof (body));
+    body_ptr = &body[0];
+    received = 0;
+
+    while (received < body_size)
+    {
+        status = amqp_simple_wait_frame (conf->connection, &frame);
+        if (status < 0)
+        {
+            char errbuf[1024];
+            status = (-1) * status;
+            ERROR ("amqp plugin: amqp_simple_wait_frame failed: %s",
+                    sstrerror (status, errbuf, sizeof (errbuf)));
+            camqp_close_connection (conf);
+            return (status);
+        }
+
+        if (frame.frame_type != AMQP_FRAME_BODY)
+        {
+            NOTICE ("amqp plugin: Unexpected frame type: %#"PRIx8,
+                    frame.frame_type);
+            return (-1);
+        }
+
+        if ((body_size - received) < frame.payload.body_fragment.len)
+        {
+            WARNING ("amqp plugin: Body is larger than indicated by header.");
+            return (-1);
+        }
+
+        memcpy (body_ptr, frame.payload.body_fragment.bytes,
+                frame.payload.body_fragment.len);
+        body_ptr += frame.payload.body_fragment.len;
+        received += frame.payload.body_fragment.len;
+    } /* while (received < body_size) */
+
+    if (strcasecmp ("text/collectd", content_type) == 0)
+    {
+        status = handle_putval (stderr, body);
+        if (status != 0)
+            ERROR ("amqp plugin: handle_putval failed with status %i.",
+                    status);
+        return (status);
+    }
+    else if (strcasecmp ("application/json", content_type) == 0)
+    {
+        ERROR ("amqp plugin: camqp_read_body: Parsing JSON data has not "
+                "been implemented yet. FIXME!");
+        return (0);
+    }
+    else
+    {
+        ERROR ("amqp plugin: camqp_read_body: Unknown content type \"%s\".",
+                content_type);
+        return (EINVAL);
+    }
+
+    /* not reached */
+    return (0);
+} /* }}} int camqp_read_body */
+
+static int camqp_read_header (camqp_config_t *conf) /* {{{ */
+{
+    int status;
+    amqp_frame_t frame;
+    amqp_basic_properties_t *properties;
+    char *content_type;
+
+    status = amqp_simple_wait_frame (conf->connection, &frame);
+    if (status < 0)
+    {
+        char errbuf[1024];
+        status = (-1) * status;
+        ERROR ("amqp plugin: amqp_simple_wait_frame failed: %s",
+                    sstrerror (status, errbuf, sizeof (errbuf)));
+        camqp_close_connection (conf);
+        return (status);
+    }
+
+    if (frame.frame_type != AMQP_FRAME_HEADER)
+    {
+        NOTICE ("amqp plugin: Unexpected frame type: %#"PRIx8,
+                frame.frame_type);
+        return (-1);
+    }
+
+    properties = frame.payload.properties.decoded;
+    content_type = camqp_bytes_cstring (&properties->content_type);
+    if (content_type == NULL)
+    {
+        ERROR ("amqp plugin: Unable to determine content type.");
+        return (-1);
+    }
+
+    status = camqp_read_body (conf,
+            (size_t) frame.payload.properties.body_size,
+            content_type);
+
+    sfree (content_type);
+    return (status);
+} /* }}} int camqp_read_header */
+
+static void *camqp_subscribe_thread (void *user_data) /* {{{ */
+{
+    camqp_config_t *conf = user_data;
+    int status;
+
+    cdtime_t interval = plugin_get_interval ();
+
+    while (subscriber_threads_running)
+    {
+        amqp_frame_t frame;
+
+        status = camqp_connect (conf);
+        if (status != 0)
+        {
+            struct timespec ts_interval;
+            ERROR ("amqp plugin: camqp_connect failed. "
+                    "Will sleep for %.3f seconds.",
+                    CDTIME_T_TO_DOUBLE (interval));
+            CDTIME_T_TO_TIMESPEC (interval, &ts_interval);
+            nanosleep (&ts_interval, /* remaining = */ NULL);
+            continue;
+        }
+
+        status = amqp_simple_wait_frame (conf->connection, &frame);
+        if (status < 0)
+        {
+            struct timespec ts_interval;
+            ERROR ("amqp plugin: amqp_simple_wait_frame failed. "
+                    "Will sleep for %.3f seconds.",
+                    CDTIME_T_TO_DOUBLE (interval));
+            camqp_close_connection (conf);
+            CDTIME_T_TO_TIMESPEC (interval, &ts_interval);
+            nanosleep (&ts_interval, /* remaining = */ NULL);
+            continue;
+        }
+
+        if (frame.frame_type != AMQP_FRAME_METHOD)
+        {
+            DEBUG ("amqp plugin: Unexpected frame type: %#"PRIx8,
+                    frame.frame_type);
+            continue;
+        }
+
+        if (frame.payload.method.id != AMQP_BASIC_DELIVER_METHOD)
+        {
+            DEBUG ("amqp plugin: Unexpected method id: %#"PRIx32,
+                    frame.payload.method.id);
+            continue;
+        }
+
+        status = camqp_read_header (conf);
+
+        amqp_maybe_release_buffers (conf->connection);
+    } /* while (subscriber_threads_running) */
+
+    camqp_config_free (conf);
+    pthread_exit (NULL);
+    return (NULL);
+} /* }}} void *camqp_subscribe_thread */
+
+static int camqp_subscribe_init (camqp_config_t *conf) /* {{{ */
+{
+    int status;
+    pthread_t *tmp;
+
+    tmp = realloc (subscriber_threads,
+            sizeof (*subscriber_threads) * (subscriber_threads_num + 1));
+    if (tmp == NULL)
+    {
+        ERROR ("amqp plugin: realloc failed.");
+        camqp_config_free (conf);
+        return (ENOMEM);
+    }
+    subscriber_threads = tmp;
+    tmp = subscriber_threads + subscriber_threads_num;
+    memset (tmp, 0, sizeof (*tmp));
+
+    status = plugin_thread_create (tmp, /* attr = */ NULL,
+            camqp_subscribe_thread, conf);
+    if (status != 0)
+    {
+        char errbuf[1024];
+        ERROR ("amqp plugin: pthread_create failed: %s",
+                sstrerror (status, errbuf, sizeof (errbuf)));
+        camqp_config_free (conf);
+        return (status);
+    }
+
+    subscriber_threads_num++;
+
+    return (0);
+} /* }}} int camqp_subscribe_init */
+
+/*
+ * Publishing code
+ */
+/* XXX: You must hold "conf->lock" when calling this function! */
+static int camqp_write_locked (camqp_config_t *conf, /* {{{ */
+        const char *buffer, const char *routing_key)
+{
+    amqp_basic_properties_t props;
+    int status;
+
+    status = camqp_connect (conf);
+    if (status != 0)
+        return (status);
+
+    memset (&props, 0, sizeof (props));
+    props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG
+        | AMQP_BASIC_DELIVERY_MODE_FLAG
+        | AMQP_BASIC_APP_ID_FLAG;
+    if (conf->format == CAMQP_FORMAT_COMMAND)
+        props.content_type = amqp_cstring_bytes("text/collectd");
+    else if (conf->format == CAMQP_FORMAT_JSON)
+        props.content_type = amqp_cstring_bytes("application/json");
+    else if (conf->format == CAMQP_FORMAT_GRAPHITE)
+        props.content_type = amqp_cstring_bytes("text/graphite");
+    else
+        assert (23 == 42);
+    props.delivery_mode = conf->delivery_mode;
+    props.app_id = amqp_cstring_bytes("collectd");
+
+    status = amqp_basic_publish(conf->connection,
+                /* channel = */ 1,
+                amqp_cstring_bytes(CONF(conf, exchange)),
+                amqp_cstring_bytes (routing_key),
+                /* mandatory = */ 0,
+                /* immediate = */ 0,
+                &props,
+                amqp_cstring_bytes(buffer));
+    if (status != 0)
+    {
+        ERROR ("amqp plugin: amqp_basic_publish failed with status %i.",
+                status);
+        camqp_close_connection (conf);
+    }
+
+    return (status);
+} /* }}} int camqp_write_locked */
+
+static int camqp_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+        user_data_t *user_data)
+{
+    camqp_config_t *conf = user_data->data;
+    char routing_key[6 * DATA_MAX_NAME_LEN];
+    char buffer[8192];
+    int status;
+
+    if ((ds == NULL) || (vl == NULL) || (conf == NULL))
+        return (EINVAL);
+
+    memset (buffer, 0, sizeof (buffer));
+
+    if (conf->routing_key != NULL)
+    {
+        sstrncpy (routing_key, conf->routing_key, sizeof (routing_key));
+    }
+    else
+    {
+        size_t i;
+        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). */
+        for (i = 0; routing_key[i] != 0; i++)
+        {
+            if (routing_key[i] == '.')
+                routing_key[i] = '/';
+            else if (routing_key[i] == '/')
+                routing_key[i] = '.';
+        }
+    }
+
+    if (conf->format == CAMQP_FORMAT_COMMAND)
+    {
+        status = create_putval (buffer, sizeof (buffer), ds, vl);
+        if (status != 0)
+        {
+            ERROR ("amqp plugin: create_putval failed with status %i.",
+                    status);
+            return (status);
+        }
+    }
+    else if (conf->format == CAMQP_FORMAT_JSON)
+    {
+        size_t bfree = sizeof (buffer);
+        size_t bfill = 0;
+
+        format_json_initialize (buffer, &bfill, &bfree);
+        format_json_value_list (buffer, &bfill, &bfree, ds, vl, conf->store_rates);
+        format_json_finalize (buffer, &bfill, &bfree);
+    }
+    else if (conf->format == CAMQP_FORMAT_GRAPHITE)
+    {
+        status = format_graphite (buffer, sizeof (buffer), ds, vl,
+                    conf->prefix, conf->postfix, conf->escape_char,
+                    conf->graphite_flags);
+        if (status != 0)
+        {
+            ERROR ("amqp plugin: format_graphite failed with status %i.",
+                    status);
+            return (status);
+        }
+    }
+    else
+    {
+        ERROR ("amqp plugin: Invalid format (%i).", conf->format);
+        return (-1);
+    }
+
+    pthread_mutex_lock (&conf->lock);
+    status = camqp_write_locked (conf, buffer, routing_key);
+    pthread_mutex_unlock (&conf->lock);
+
+    return (status);
+} /* }}} int camqp_write */
+
+/*
+ * Config handling
+ */
+static int camqp_config_set_format (oconfig_item_t *ci, /* {{{ */
+        camqp_config_t *conf)
+{
+    char *string;
+    int status;
+
+    string = NULL;
+    status = cf_util_get_string (ci, &string);
+    if (status != 0)
+        return (status);
+
+    assert (string != NULL);
+    if (strcasecmp ("Command", string) == 0)
+        conf->format = CAMQP_FORMAT_COMMAND;
+    else if (strcasecmp ("JSON", string) == 0)
+        conf->format = CAMQP_FORMAT_JSON;
+    else if (strcasecmp ("Graphite", string) == 0)
+        conf->format = CAMQP_FORMAT_GRAPHITE;
+    else
+    {
+        WARNING ("amqp plugin: Invalid format string: %s",
+                string);
+    }
+
+    free (string);
+
+    return (0);
+} /* }}} int config_set_string */
+
+static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */
+        _Bool publish)
+{
+    camqp_config_t *conf;
+    int status;
+    int i;
+
+    conf = malloc (sizeof (*conf));
+    if (conf == NULL)
+    {
+        ERROR ("amqp plugin: malloc failed.");
+        return (ENOMEM);
+    }
+
+    /* Initialize "conf" {{{ */
+    memset (conf, 0, sizeof (*conf));
+    conf->publish = publish;
+    conf->name = NULL;
+    conf->format = CAMQP_FORMAT_COMMAND;
+    conf->host = NULL;
+    conf->port = 5672;
+    conf->vhost = NULL;
+    conf->user = NULL;
+    conf->password = NULL;
+    conf->exchange = NULL;
+    conf->routing_key = NULL;
+    conf->connection_retry_delay = 0;
+
+    /* publish only */
+    conf->delivery_mode = CAMQP_DM_VOLATILE;
+    conf->store_rates = 0;
+    conf->graphite_flags = 0;
+    /* publish & graphite only */
+    conf->prefix = NULL;
+    conf->postfix = NULL;
+    conf->escape_char = '_';
+    /* subscribe only */
+    conf->exchange_type = NULL;
+    conf->queue = NULL;
+    conf->queue_durable = 0;
+    conf->queue_auto_delete = 1;
+    /* general */
+    conf->connection = NULL;
+    pthread_mutex_init (&conf->lock, /* attr = */ NULL);
+    /* }}} */
+
+    status = cf_util_get_string (ci, &conf->name);
+    if (status != 0)
+    {
+        sfree (conf);
+        return (status);
+    }
+
+    for (i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp ("Host", child->key) == 0)
+            status = cf_util_get_string (child, &conf->host);
+        else if (strcasecmp ("Port", child->key) == 0)
+        {
+            status = cf_util_get_port_number (child);
+            if (status > 0)
+            {
+                conf->port = status;
+                status = 0;
+            }
+        }
+        else if (strcasecmp ("VHost", child->key) == 0)
+            status = cf_util_get_string (child, &conf->vhost);
+        else if (strcasecmp ("User", child->key) == 0)
+            status = cf_util_get_string (child, &conf->user);
+        else if (strcasecmp ("Password", child->key) == 0)
+            status = cf_util_get_string (child, &conf->password);
+        else if (strcasecmp ("Exchange", child->key) == 0)
+            status = cf_util_get_string (child, &conf->exchange);
+        else if ((strcasecmp ("ExchangeType", child->key) == 0) && !publish)
+            status = cf_util_get_string (child, &conf->exchange_type);
+        else if ((strcasecmp ("Queue", child->key) == 0) && !publish)
+            status = cf_util_get_string (child, &conf->queue);
+        else if ((strcasecmp ("QueueDurable", child->key) == 0) && !publish)
+            status = cf_util_get_boolean (child, &conf->queue_durable);
+        else if ((strcasecmp ("QueueAutoDelete", child->key) == 0) && !publish)
+            status = cf_util_get_boolean (child, &conf->queue_auto_delete);
+        else if (strcasecmp ("RoutingKey", child->key) == 0)
+            status = cf_util_get_string (child, &conf->routing_key);
+        else if ((strcasecmp ("Persistent", child->key) == 0) && publish)
+        {
+            _Bool tmp = 0;
+            status = cf_util_get_boolean (child, &tmp);
+            if (tmp)
+                conf->delivery_mode = CAMQP_DM_PERSISTENT;
+            else
+                conf->delivery_mode = CAMQP_DM_VOLATILE;
+        }
+        else if ((strcasecmp ("StoreRates", child->key) == 0) && publish)
+        {
+            status = cf_util_get_boolean (child, &conf->store_rates);
+            (void) cf_util_get_flag (child, &conf->graphite_flags,
+                    GRAPHITE_STORE_RATES);
+        }
+        else if ((strcasecmp ("Format", child->key) == 0) && publish)
+            status = camqp_config_set_format (child, conf);
+        else if ((strcasecmp ("GraphiteSeparateInstances", child->key) == 0) && publish)
+            status = cf_util_get_flag (child, &conf->graphite_flags,
+                    GRAPHITE_SEPARATE_INSTANCES);
+        else if ((strcasecmp ("GraphiteAlwaysAppendDS", child->key) == 0) && publish)
+            status = cf_util_get_flag (child, &conf->graphite_flags,
+                    GRAPHITE_ALWAYS_APPEND_DS);
+        else if ((strcasecmp ("GraphitePrefix", child->key) == 0) && publish)
+            status = cf_util_get_string (child, &conf->prefix);
+        else if ((strcasecmp ("GraphitePostfix", child->key) == 0) && publish)
+            status = cf_util_get_string (child, &conf->postfix);
+        else if ((strcasecmp ("GraphiteEscapeChar", child->key) == 0) && publish)
+        {
+            char *tmp_buff = NULL;
+            status = cf_util_get_string (child, &tmp_buff);
+            if (strlen (tmp_buff) > 1)
+                WARNING ("amqp plugin: The option \"GraphiteEscapeChar\" handles "
+                        "only one character. Others will be ignored.");
+            conf->escape_char = tmp_buff[0];
+            sfree (tmp_buff);
+        }
+        else if (strcasecmp ("ConnectionRetryDelay", child->key) == 0)
+            status = cf_util_get_int (child, &conf->connection_retry_delay);
+        else
+            WARNING ("amqp plugin: Ignoring unknown "
+                    "configuration option \"%s\".", child->key);
+
+        if (status != 0)
+            break;
+    } /* for (i = 0; i < ci->children_num; i++) */
+
+    if ((status == 0) && (conf->exchange == NULL))
+    {
+        if (conf->exchange_type != NULL)
+            WARNING ("amqp plugin: The option \"ExchangeType\" was given "
+                    "without the \"Exchange\" option. It will be ignored.");
+
+        if (!publish && (conf->routing_key != NULL))
+            WARNING ("amqp plugin: The option \"RoutingKey\" was given "
+                    "without the \"Exchange\" option. It will be ignored.");
+
+    }
+
+    if (status != 0)
+    {
+        camqp_config_free (conf);
+        return (status);
+    }
+
+    if (conf->exchange != NULL)
+    {
+        DEBUG ("amqp plugin: camqp_config_connection: exchange = %s;",
+                conf->exchange);
+    }
+
+    if (publish)
+    {
+        char cbname[128];
+        user_data_t ud = { conf, camqp_config_free };
+
+        ssnprintf (cbname, sizeof (cbname), "amqp/%s", conf->name);
+
+        status = plugin_register_write (cbname, camqp_write, &ud);
+        if (status != 0)
+        {
+            camqp_config_free (conf);
+            return (status);
+        }
+    }
+    else
+    {
+        status = camqp_subscribe_init (conf);
+        if (status != 0)
+        {
+            camqp_config_free (conf);
+            return (status);
+        }
+    }
+
+    return (0);
+} /* }}} int camqp_config_connection */
+
+static int camqp_config (oconfig_item_t *ci) /* {{{ */
+{
+    int i;
+
+    for (i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp ("Publish", child->key) == 0)
+            camqp_config_connection (child, /* publish = */ 1);
+        else if (strcasecmp ("Subscribe", child->key) == 0)
+            camqp_config_connection (child, /* publish = */ 0);
+        else
+            WARNING ("amqp plugin: Ignoring unknown config option \"%s\".",
+                    child->key);
+    } /* for (ci->children_num) */
+
+    return (0);
+} /* }}} int camqp_config */
+
+void module_register (void)
+{
+    plugin_register_complex_config ("amqp", camqp_config);
+    plugin_register_shutdown ("amqp", camqp_shutdown);
+} /* void module_register */
+
+/* vim: set sw=4 sts=4 et fdm=marker : */
diff --git a/src/apache.c b/src/apache.c
new file mode 100644 (file)
index 0000000..0c6318e
--- /dev/null
@@ -0,0 +1,623 @@
+/**
+ * collectd - src/apache.c
+ * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2007       Florent EppO Monbillard
+ * Copyright (C) 2009       Amit Gupta
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Florent EppO Monbillard <eppo at darox.net>
+ *   - connections/lighttpd extension
+ *   Amit Gupta <amit.gupta221 at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <curl/curl.h>
+
+enum server_enum
+{
+       APACHE = 0,
+       LIGHTTPD
+};
+
+struct apache_s
+{
+       int server_type;
+       char *name;
+       char *host;
+       char *url;
+       char *user;
+       char *pass;
+       _Bool verify_peer;
+       _Bool verify_host;
+       char *cacert;
+       char *ssl_ciphers;
+       char *server; /* user specific server type */
+       char *apache_buffer;
+       char apache_curl_error[CURL_ERROR_SIZE];
+       size_t apache_buffer_size;
+       size_t apache_buffer_fill;
+       int timeout;
+       CURL *curl;
+}; /* apache_s */
+
+typedef struct apache_s apache_t;
+
+/* TODO: Remove this prototype */
+static int apache_read_host (user_data_t *user_data);
+
+static void apache_free (apache_t *st)
+{
+       if (st == NULL)
+               return;
+
+       sfree (st->name);
+       sfree (st->host);
+       sfree (st->url);
+       sfree (st->user);
+       sfree (st->pass);
+       sfree (st->cacert);
+       sfree (st->ssl_ciphers);
+       sfree (st->server);
+       sfree (st->apache_buffer);
+       if (st->curl) {
+               curl_easy_cleanup(st->curl);
+               st->curl = NULL;
+       }
+} /* apache_free */
+
+static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb,
+               void *user_data)
+{
+       size_t len = size * nmemb;
+       apache_t *st;
+
+       st = user_data;
+       if (st == NULL)
+       {
+               ERROR ("apache plugin: apache_curl_callback: "
+                               "user_data pointer is NULL.");
+               return (0);
+       }
+
+       if (len <= 0)
+               return (len);
+
+       if ((st->apache_buffer_fill + len) >= st->apache_buffer_size)
+       {
+               char *temp;
+
+               temp = (char *) realloc (st->apache_buffer,
+                               st->apache_buffer_fill + len + 1);
+               if (temp == NULL)
+               {
+                       ERROR ("apache plugin: realloc failed.");
+                       return (0);
+               }
+               st->apache_buffer = temp;
+               st->apache_buffer_size = st->apache_buffer_fill + len + 1;
+       }
+
+       memcpy (st->apache_buffer + st->apache_buffer_fill, (char *) buf, len);
+       st->apache_buffer_fill += len;
+       st->apache_buffer[st->apache_buffer_fill] = 0;
+
+       return (len);
+} /* int apache_curl_callback */
+
+static size_t apache_header_callback (void *buf, size_t size, size_t nmemb,
+               void *user_data)
+{
+       size_t len = size * nmemb;
+       apache_t *st;
+
+       st = user_data;
+       if (st == NULL)
+       {
+               ERROR ("apache plugin: apache_header_callback: "
+                               "user_data pointer is NULL.");
+               return (0);
+       }
+
+       if (len <= 0)
+               return (len);
+
+       /* look for the Server header */
+       if (strncasecmp (buf, "Server: ", strlen ("Server: ")) != 0)
+               return (len);
+
+       if (strstr (buf, "Apache") != NULL)
+               st->server_type = APACHE;
+       else if (strstr (buf, "lighttpd") != NULL)
+               st->server_type = LIGHTTPD;
+       else if (strstr (buf, "IBM_HTTP_Server") != NULL)
+               st->server_type = APACHE;
+       else
+       {
+               const char *hdr = buf;
+
+               hdr += strlen ("Server: ");
+               NOTICE ("apache plugin: Unknown server software: %s", hdr);
+       }
+
+       return (len);
+} /* apache_header_callback */
+
+/* Configuration handling functiions
+ * <Plugin apache>
+ *   <Instance "instance_name">
+ *     URL ...
+ *   </Instance>
+ *   URL ...
+ * </Plugin>
+ */
+static int config_add (oconfig_item_t *ci)
+{
+       apache_t *st;
+       int i;
+       int status;
+
+       st = malloc (sizeof (*st));
+       if (st == NULL)
+       {
+               ERROR ("apache plugin: malloc failed.");
+               return (-1);
+       }
+       memset (st, 0, sizeof (*st));
+
+       st->timeout = -1;
+
+       status = cf_util_get_string (ci, &st->name);
+       if (status != 0)
+       {
+               sfree (st);
+               return (status);
+       }
+       assert (st->name != NULL);
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("URL", child->key) == 0)
+                       status = cf_util_get_string (child, &st->url);
+               else if (strcasecmp ("Host", child->key) == 0)
+                       status = cf_util_get_string (child, &st->host);
+               else if (strcasecmp ("User", child->key) == 0)
+                       status = cf_util_get_string (child, &st->user);
+               else if (strcasecmp ("Password", child->key) == 0)
+                       status = cf_util_get_string (child, &st->pass);
+               else if (strcasecmp ("VerifyPeer", child->key) == 0)
+                       status = cf_util_get_boolean (child, &st->verify_peer);
+               else if (strcasecmp ("VerifyHost", child->key) == 0)
+                       status = cf_util_get_boolean (child, &st->verify_host);
+               else if (strcasecmp ("CACert", child->key) == 0)
+                       status = cf_util_get_string (child, &st->cacert);
+               else if (strcasecmp ("SSLCiphers", child->key) == 0)
+                       status = cf_util_get_string (child, &st->ssl_ciphers);
+               else if (strcasecmp ("Server", child->key) == 0)
+                       status = cf_util_get_string (child, &st->server);
+               else if (strcasecmp ("Timeout", child->key) == 0)
+                       status = cf_util_get_int (child, &st->timeout);
+               else
+               {
+                       WARNING ("apache plugin: Option `%s' not allowed here.",
+                                       child->key);
+                       status = -1;
+               }
+
+               if (status != 0)
+                       break;
+       }
+
+       /* Check if struct is complete.. */
+       if ((status == 0) && (st->url == NULL))
+       {
+               ERROR ("apache plugin: Instance `%s': "
+                               "No URL has been configured.",
+                               st->name);
+               status = -1;
+       }
+
+       if (status == 0)
+       {
+               user_data_t ud;
+               char callback_name[3*DATA_MAX_NAME_LEN];
+
+               memset (&ud, 0, sizeof (ud));
+               ud.data = st;
+               ud.free_func = (void *) apache_free;
+
+               memset (callback_name, 0, sizeof (callback_name));
+               ssnprintf (callback_name, sizeof (callback_name),
+                               "apache/%s/%s",
+                               (st->host != NULL) ? st->host : hostname_g,
+                               (st->name != NULL) ? st->name : "default"),
+
+               status = plugin_register_complex_read (/* group = */ NULL,
+                               /* name      = */ callback_name,
+                               /* callback  = */ apache_read_host,
+                               /* interval  = */ NULL,
+                               /* user_data = */ &ud);
+       }
+
+       if (status != 0)
+       {
+               apache_free (st);
+               return (-1);
+       }
+
+       return (0);
+} /* int config_add */
+
+static int config (oconfig_item_t *ci)
+{
+       int status = 0;
+       int i;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Instance", child->key) == 0)
+                       config_add (child);
+               else
+                       WARNING ("apache plugin: The configuration option "
+                                       "\"%s\" is not allowed here. Did you "
+                                       "forget to add an <Instance /> block "
+                                       "around the configuration?",
+                                       child->key);
+       } /* for (ci->children) */
+
+       return (status);
+} /* int config */
+
+/* initialize curl for each host */
+static int init_host (apache_t *st) /* {{{ */
+{
+       assert (st->url != NULL);
+       /* (Assured by `config_add') */
+
+       if (st->curl != NULL)
+       {
+               curl_easy_cleanup (st->curl);
+               st->curl = NULL;
+       }
+
+       if ((st->curl = curl_easy_init ()) == NULL)
+       {
+               ERROR ("apache plugin: init_host: `curl_easy_init' failed.");
+               return (-1);
+       }
+
+       curl_easy_setopt (st->curl, CURLOPT_NOSIGNAL, 1L);
+       curl_easy_setopt (st->curl, CURLOPT_WRITEFUNCTION, apache_curl_callback);
+       curl_easy_setopt (st->curl, CURLOPT_WRITEDATA, st);
+
+       /* not set as yet if the user specified string doesn't match apache or
+        * lighttpd, then ignore it. Headers will be parsed to find out the
+        * server type */
+       st->server_type = -1;
+
+       if (st->server != NULL)
+       {
+               if (strcasecmp(st->server, "apache") == 0)
+                       st->server_type = APACHE;
+               else if (strcasecmp(st->server, "lighttpd") == 0)
+                       st->server_type = LIGHTTPD;
+               else if (strcasecmp(st->server, "ibm_http_server") == 0)
+                       st->server_type = APACHE;
+               else
+                       WARNING ("apache plugin: Unknown `Server' setting: %s",
+                                       st->server);
+       }
+
+       /* if not found register a header callback to determine the server_type */
+       if (st->server_type == -1)
+       {
+               curl_easy_setopt (st->curl, CURLOPT_HEADERFUNCTION, apache_header_callback);
+               curl_easy_setopt (st->curl, CURLOPT_WRITEHEADER, st);
+       }
+
+       curl_easy_setopt (st->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+       curl_easy_setopt (st->curl, CURLOPT_ERRORBUFFER, st->apache_curl_error);
+
+       if (st->user != NULL)
+       {
+#ifdef HAVE_CURLOPT_USERNAME
+               curl_easy_setopt (st->curl, CURLOPT_USERNAME, st->user);
+               curl_easy_setopt (st->curl, CURLOPT_PASSWORD,
+                               (st->pass == NULL) ? "" : st->pass);
+#else
+               static char credentials[1024];
+               int status;
+
+               status = ssnprintf (credentials, sizeof (credentials), "%s:%s",
+                               st->user, (st->pass == NULL) ? "" : st->pass);
+               if ((status < 0) || ((size_t) status >= sizeof (credentials)))
+               {
+                       ERROR ("apache plugin: init_host: Returning an error "
+                                       "because the credentials have been "
+                                       "truncated.");
+                       curl_easy_cleanup (st->curl);
+                       st->curl = NULL;
+                       return (-1);
+               }
+
+               curl_easy_setopt (st->curl, CURLOPT_USERPWD, credentials);
+#endif
+       }
+
+       curl_easy_setopt (st->curl, CURLOPT_URL, st->url);
+       curl_easy_setopt (st->curl, CURLOPT_FOLLOWLOCATION, 1L);
+       curl_easy_setopt (st->curl, CURLOPT_MAXREDIRS, 50L);
+
+       curl_easy_setopt (st->curl, CURLOPT_SSL_VERIFYPEER,
+                       (long) st->verify_peer);
+       curl_easy_setopt (st->curl, CURLOPT_SSL_VERIFYHOST,
+                       st->verify_host ? 2L : 0L);
+       if (st->cacert != NULL)
+               curl_easy_setopt (st->curl, CURLOPT_CAINFO, st->cacert);
+       if (st->ssl_ciphers != NULL)
+               curl_easy_setopt (st->curl, CURLOPT_SSL_CIPHER_LIST,st->ssl_ciphers);
+
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+       if (st->timeout >= 0)
+               curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS, (long) st->timeout);
+       else
+               curl_easy_setopt (st->curl, CURLOPT_TIMEOUT_MS,
+                               CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
+       return (0);
+} /* }}} int init_host */
+
+static void submit_value (const char *type, const char *type_instance,
+               value_t value, apache_t *st)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = &value;
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, (st->host != NULL) ? st->host : hostname_g,
+                       sizeof (vl.host));
+
+       sstrncpy (vl.plugin, "apache", sizeof (vl.plugin));
+       if (st->name != NULL)
+               sstrncpy (vl.plugin_instance, st->name,
+                               sizeof (vl.plugin_instance));
+
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance,
+                               sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void submit_value */
+
+static void submit_derive (const char *type, const char *type_instance,
+               derive_t c, apache_t *st)
+{
+       value_t v;
+       v.derive = c;
+       submit_value (type, type_instance, v, st);
+} /* void submit_derive */
+
+static void submit_gauge (const char *type, const char *type_instance,
+               gauge_t g, apache_t *st)
+{
+       value_t v;
+       v.gauge = g;
+       submit_value (type, type_instance, v, st);
+} /* void submit_gauge */
+
+static void submit_scoreboard (char *buf, apache_t *st)
+{
+       /*
+        * Scoreboard Key:
+        * "_" Waiting for Connection, "S" Starting up,
+        * "R" Reading Request for apache and read-POST for lighttpd,
+        * "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
+        * "C" Closing connection, "L" Logging, "G" Gracefully finishing,
+        * "I" Idle cleanup of worker, "." Open slot with no current process
+        * Lighttpd specific legends -
+        * "E" hard error, "." connect, "h" handle-request,
+        * "q" request-start, "Q" request-end, "s" response-start
+        * "S" response-end, "r" read
+        */
+       long long open      = 0LL;
+       long long waiting   = 0LL;
+       long long starting  = 0LL;
+       long long reading   = 0LL;
+       long long sending   = 0LL;
+       long long keepalive = 0LL;
+       long long dnslookup = 0LL;
+       long long closing   = 0LL;
+       long long logging   = 0LL;
+       long long finishing = 0LL;
+       long long idle_cleanup = 0LL;
+
+       /* lighttpd specific */
+       long long hard_error     = 0LL;
+       long long lighttpd_read  = 0LL;
+       long long handle_request = 0LL;
+       long long request_start  = 0LL;
+       long long request_end    = 0LL;
+       long long response_start = 0LL;
+       long long response_end   = 0LL;
+
+       int i;
+       for (i = 0; buf[i] != '\0'; i++)
+       {
+               if (buf[i] == '.') open++;
+               else if (buf[i] == '_') waiting++;
+               else if (buf[i] == 'S') starting++;
+               else if (buf[i] == 'R') reading++;
+               else if (buf[i] == 'W') sending++;
+               else if (buf[i] == 'K') keepalive++;
+               else if (buf[i] == 'D') dnslookup++;
+               else if (buf[i] == 'C') closing++;
+               else if (buf[i] == 'L') logging++;
+               else if (buf[i] == 'G') finishing++;
+               else if (buf[i] == 'I') idle_cleanup++;
+               else if (buf[i] == 'r') lighttpd_read++;
+               else if (buf[i] == 'h') handle_request++;
+               else if (buf[i] == 'E') hard_error++;
+               else if (buf[i] == 'q') request_start++;
+               else if (buf[i] == 'Q') request_end++;
+               else if (buf[i] == 's') response_start++;
+               else if (buf[i] == 'S') response_end++;
+       }
+
+       if (st->server_type == APACHE)
+       {
+               submit_gauge ("apache_scoreboard", "open"     , open, st);
+               submit_gauge ("apache_scoreboard", "waiting"  , waiting, st);
+               submit_gauge ("apache_scoreboard", "starting" , starting, st);
+               submit_gauge ("apache_scoreboard", "reading"  , reading, st);
+               submit_gauge ("apache_scoreboard", "sending"  , sending, st);
+               submit_gauge ("apache_scoreboard", "keepalive", keepalive, st);
+               submit_gauge ("apache_scoreboard", "dnslookup", dnslookup, st);
+               submit_gauge ("apache_scoreboard", "closing"  , closing, st);
+               submit_gauge ("apache_scoreboard", "logging"  , logging, st);
+               submit_gauge ("apache_scoreboard", "finishing", finishing, st);
+               submit_gauge ("apache_scoreboard", "idle_cleanup", idle_cleanup, st);
+       }
+       else
+       {
+               submit_gauge ("apache_scoreboard", "connect"       , open, st);
+               submit_gauge ("apache_scoreboard", "close"         , closing, st);
+               submit_gauge ("apache_scoreboard", "hard_error"    , hard_error, st);
+               submit_gauge ("apache_scoreboard", "read"          , lighttpd_read, st);
+               submit_gauge ("apache_scoreboard", "read_post"     , reading, st);
+               submit_gauge ("apache_scoreboard", "write"         , sending, st);
+               submit_gauge ("apache_scoreboard", "handle_request", handle_request, st);
+               submit_gauge ("apache_scoreboard", "request_start" , request_start, st);
+               submit_gauge ("apache_scoreboard", "request_end"   , request_end, st);
+               submit_gauge ("apache_scoreboard", "response_start", response_start, st);
+               submit_gauge ("apache_scoreboard", "response_end"  , response_end, st);
+       }
+}
+
+static int apache_read_host (user_data_t *user_data) /* {{{ */
+{
+       int i;
+
+       char *ptr;
+       char *saveptr;
+       char *lines[16];
+       int   lines_num = 0;
+
+       char *fields[4];
+       int   fields_num;
+
+       apache_t *st;
+
+       st = user_data->data;
+
+       assert (st->url != NULL);
+       /* (Assured by `config_add') */
+
+       if (st->curl == NULL)
+       {
+               int status;
+
+               status = init_host (st);
+               if (status != 0)
+                       return (-1);
+       }
+       assert (st->curl != NULL);
+
+       st->apache_buffer_fill = 0;
+       if (curl_easy_perform (st->curl) != CURLE_OK)
+       {
+               ERROR ("apache: curl_easy_perform failed: %s",
+                               st->apache_curl_error);
+               return (-1);
+       }
+
+       /* fallback - server_type to apache if not set at this time */
+       if (st->server_type == -1)
+       {
+               WARNING ("apache plugin: Unable to determine server software "
+                               "automatically. Will assume Apache.");
+               st->server_type = APACHE;
+       }
+
+       ptr = st->apache_buffer;
+       saveptr = NULL;
+       while ((lines[lines_num] = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
+       {
+               ptr = NULL;
+               lines_num++;
+
+               if (lines_num >= 16)
+                       break;
+       }
+
+       for (i = 0; i < lines_num; i++)
+       {
+               fields_num = strsplit (lines[i], fields, 4);
+
+               if (fields_num == 3)
+               {
+                       if ((strcmp (fields[0], "Total") == 0)
+                                       && (strcmp (fields[1], "Accesses:") == 0))
+                               submit_derive ("apache_requests", "",
+                                               atoll (fields[2]), st);
+                       else if ((strcmp (fields[0], "Total") == 0)
+                                       && (strcmp (fields[1], "kBytes:") == 0))
+                               submit_derive ("apache_bytes", "",
+                                               1024LL * atoll (fields[2]), st);
+               }
+               else if (fields_num == 2)
+               {
+                       if (strcmp (fields[0], "Scoreboard:") == 0)
+                               submit_scoreboard (fields[1], st);
+                       else if ((strcmp (fields[0], "BusyServers:") == 0) /* Apache 1.* */
+                                       || (strcmp (fields[0], "BusyWorkers:") == 0) /* Apache 2.* */)
+                               submit_gauge ("apache_connections", NULL, atol (fields[1]), st);
+                       else if ((strcmp (fields[0], "IdleServers:") == 0) /* Apache 1.x */
+                                       || (strcmp (fields[0], "IdleWorkers:") == 0) /* Apache 2.x */)
+                               submit_gauge ("apache_idle_workers", NULL, atol (fields[1]), st);
+               }
+       }
+
+       st->apache_buffer_fill = 0;
+
+       return (0);
+} /* }}} int apache_read_host */
+
+static int apache_init (void) /* {{{ */
+{
+       /* Call this while collectd is still single-threaded to avoid
+        * initialization issues in libgcrypt. */
+       curl_global_init (CURL_GLOBAL_SSL);
+       return (0);
+} /* }}} int apache_init */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("apache", config);
+       plugin_register_init ("apache", apache_init);
+} /* void module_register */
+
+/* vim: set sw=8 noet fdm=marker : */
diff --git a/src/apcups.c b/src/apcups.c
new file mode 100644 (file)
index 0000000..be7673c
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * collectd - src/apcups.c
+ * Copyright (C) 2006-2012  Florian octo Forster
+ * Copyright (C) 2006       Anthony Gialluca <tonyabg at charter.net>
+ * Copyright (C) 2000-2004  Kern Sibbald
+ * Copyright (C) 1996-1999  Andre M. Hedrick <andre at suse.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General
+ * Public License as published by the Free Software Foundation.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Anthony Gialluca <tonyabg at charter.net>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"      /* rrd_update_file */
+#include "plugin.h"      /* plugin_register, plugin_submit */
+#include "configfile.h"  /* cf_register */
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#define NISPORT 3551
+#define MAXSTRING               256
+#define MODULE_NAME "apcups"
+
+#define APCUPS_DEFAULT_HOST "localhost"
+
+/*
+ * Private data types
+ */
+struct apc_detail_s
+{
+       double linev;
+       double loadpct;
+       double bcharge;
+       double timeleft;
+       double outputv;
+       double itemp;
+       double battv;
+       double linefreq;
+};
+
+/*
+ * Private variables
+ */
+/* Default values for contacting daemon */
+static char *conf_host = NULL;
+static int   conf_port = NISPORT;
+/* Defaults to false for backwards compatibility. */
+static _Bool conf_report_seconds = 0;
+
+static int global_sockfd = -1;
+
+static int count_retries = 0;
+static int count_iterations = 0;
+static _Bool close_socket = 0;
+
+static const char *config_keys[] =
+{
+       "Host",
+       "Port",
+       "ReportSeconds"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int net_shutdown (int *fd)
+{
+       uint16_t packet_size = 0;
+
+       if ((fd == NULL) || (*fd < 0))
+               return (EINVAL);
+
+       swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+       close (*fd);
+       *fd = -1;
+
+       return (0);
+} /* int net_shutdown */
+
+/* Close the network connection */
+static int apcups_shutdown (void)
+{
+       if (global_sockfd < 0)
+               return (0);
+
+       net_shutdown (&global_sockfd);
+       return (0);
+} /* int apcups_shutdown */
+
+/*
+ * Open a TCP connection to the UPS network server
+ * Returns -1 on error
+ * Returns socket file descriptor otherwise
+ */
+static int net_open (char *host, int port)
+{
+       int              sd;
+       int              status;
+       char             port_str[8];
+       struct addrinfo  ai_hints;
+       struct addrinfo *ai_return;
+       struct addrinfo *ai_list;
+
+       assert ((port > 0x00000000) && (port <= 0x0000FFFF));
+
+       /* Convert the port to a string */
+       ssnprintf (port_str, sizeof (port_str), "%i", port);
+
+       /* Resolve name */
+       memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
+       ai_hints.ai_family   = AF_INET; /* XXX: Change this to `AF_UNSPEC' if apcupsd can handle IPv6 */
+       ai_hints.ai_socktype = SOCK_STREAM;
+
+       status = getaddrinfo (host, port_str, &ai_hints, &ai_return);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               INFO ("getaddrinfo failed: %s",
+                               (status == EAI_SYSTEM)
+                               ? sstrerror (errno, errbuf, sizeof (errbuf))
+                               : gai_strerror (status));
+               return (-1);
+       }
+
+       /* Create socket */
+       sd = -1;
+       for (ai_list = ai_return; ai_list != NULL; ai_list = ai_list->ai_next)
+       {
+               sd = socket (ai_list->ai_family, ai_list->ai_socktype, ai_list->ai_protocol);
+               if (sd >= 0)
+                       break;
+       }
+       /* `ai_list' still holds the current description of the socket.. */
+
+       if (sd < 0)
+       {
+               DEBUG ("Unable to open a socket");
+               freeaddrinfo (ai_return);
+               return (-1);
+       }
+
+       status = connect (sd, ai_list->ai_addr, ai_list->ai_addrlen);
+
+       freeaddrinfo (ai_return);
+
+       if (status != 0) /* `connect(2)' failed */
+       {
+               char errbuf[1024];
+               INFO ("connect failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (sd);
+               return (-1);
+       }
+
+       DEBUG ("Done opening a socket %i", sd);
+
+       return (sd);
+} /* int net_open (char *host, char *service, int port) */
+
+/*
+ * Receive a message from the other end. Each message consists of
+ * two packets. The first is a header that contains the size
+ * of the data that follows in the second packet.
+ * Returns number of bytes read
+ * Returns 0 on end of file
+ * Returns -1 on hard end of file (i.e. network connection close)
+ * Returns -2 on error
+ */
+static int net_recv (int *sockfd, char *buf, int buflen)
+{
+       uint16_t packet_size;
+
+       /* get data size -- in short */
+       if (sread (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0)
+       {
+               close (*sockfd);
+               *sockfd = -1;
+               return (-1);
+       }
+
+       packet_size = ntohs (packet_size);
+       if (packet_size > buflen)
+       {
+               ERROR ("apcups plugin: Received %"PRIu16" bytes of payload "
+                               "but have only %i bytes of buffer available.",
+                               packet_size, buflen);
+               close (*sockfd);
+               *sockfd = -1;
+               return (-2);
+       }
+
+       if (packet_size == 0)
+               return (0);
+
+       /* now read the actual data */
+       if (sread (*sockfd, (void *) buf, packet_size) != 0)
+       {
+               close (*sockfd);
+               *sockfd = -1;
+               return (-1);
+       }
+
+       return ((int) packet_size);
+} /* static int net_recv (int *sockfd, char *buf, int buflen) */
+
+/*
+ * Send a message over the network. The send consists of
+ * two network packets. The first is sends a short containing
+ * the length of the data packet which follows.
+ * Returns zero on success
+ * Returns non-zero on error
+ */
+static int net_send (int *sockfd, char *buff, int len)
+{
+       uint16_t packet_size;
+
+       assert (len > 0);
+       assert (*sockfd >= 0);
+
+       /* send short containing size of data packet */
+       packet_size = htons ((uint16_t) len);
+
+       if (swrite (*sockfd, (void *) &packet_size, sizeof (packet_size)) != 0)
+       {
+               close (*sockfd);
+               *sockfd = -1;
+               return (-1);
+       }
+
+       /* send data packet */
+       if (swrite (*sockfd, (void *) buff, len) != 0)
+       {
+               close (*sockfd);
+               *sockfd = -1;
+               return (-2);
+       }
+
+       return (0);
+}
+
+/* Get and print status from apcupsd NIS server */
+static int apc_query_server (char *host, int port,
+               struct apc_detail_s *apcups_detail)
+{
+       int     n;
+       char    recvline[1024];
+       char   *tokptr;
+       char   *toksaveptr;
+       char   *key;
+       double  value;
+       _Bool retry = 1;
+       int status;
+
+#if APCMAIN
+# define PRINT_VALUE(name, val) printf("  Found property: name = %s; value = %f;\n", name, val)
+#else
+# define PRINT_VALUE(name, val) /**/
+#endif
+
+       while (retry)
+       {
+               if (global_sockfd < 0)
+               {
+                       global_sockfd = net_open (host, port);
+                       if (global_sockfd < 0)
+                       {
+                               ERROR ("apcups plugin: Connecting to the "
+                                               "apcupsd failed.");
+                               return (-1);
+                       }
+               }
+
+
+               status = net_send (&global_sockfd, "status", strlen ("status"));
+               if (status != 0)
+               {
+                       /* net_send is closing the socket on error. */
+                       assert (global_sockfd < 0);
+                       if (retry)
+                       {
+                               retry = 0;
+                               count_retries++;
+                               continue;
+                       }
+
+                       ERROR ("apcups plugin: Writing to the socket failed.");
+                       return (-1);
+               }
+
+               break;
+       } /* while (retry) */
+
+        /* When collectd's collection interval is larger than apcupsd's
+         * timeout, we would have to retry / re-connect each iteration. Try to
+         * detect this situation and shut down the socket gracefully in that
+         * case. Otherwise, keep the socket open to avoid overhead. */
+       count_iterations++;
+       if ((count_iterations == 10) && (count_retries > 2))
+       {
+               NOTICE ("apcups plugin: There have been %i retries in the "
+                               "first %i iterations. Will close the socket "
+                               "in future iterations.",
+                               count_retries, count_iterations);
+               close_socket = 1;
+       }
+
+       while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
+       {
+               assert ((unsigned int)n < sizeof (recvline));
+               recvline[n] = '\0';
+#if APCMAIN
+               printf ("net_recv = `%s';\n", recvline);
+#endif /* if APCMAIN */
+
+               toksaveptr = NULL;
+               tokptr = strtok_r (recvline, " :\t", &toksaveptr);
+               while (tokptr != NULL)
+               {
+                       key = tokptr;
+                       if ((tokptr = strtok_r (NULL, " :\t", &toksaveptr)) == NULL)
+                               continue;
+                       value = atof (tokptr);
+
+                       PRINT_VALUE (key, value);
+
+                       if (strcmp ("LINEV", key) == 0)
+                               apcups_detail->linev = value;
+                       else if (strcmp ("BATTV", key) == 0)
+                               apcups_detail->battv = value;
+                       else if (strcmp ("ITEMP", key) == 0)
+                               apcups_detail->itemp = value;
+                       else if (strcmp ("LOADPCT", key) == 0)
+                               apcups_detail->loadpct = value;
+                       else if (strcmp ("BCHARGE", key) == 0)
+                               apcups_detail->bcharge = value;
+                       else if (strcmp ("OUTPUTV", key) == 0)
+                               apcups_detail->outputv = value;
+                       else if (strcmp ("LINEFREQ", key) == 0)
+                               apcups_detail->linefreq = value;
+                       else if (strcmp ("TIMELEFT", key) == 0)
+                       {
+                               /* Convert minutes to seconds if requested by
+                                * the user. */
+                               if (conf_report_seconds)
+                                       value *= 60.0;
+                               apcups_detail->timeleft = value;
+                       }
+
+                       tokptr = strtok_r (NULL, ":", &toksaveptr);
+               } /* while (tokptr != NULL) */
+       }
+       status = errno; /* save errno, net_shutdown() may re-set it. */
+
+       if (close_socket)
+               net_shutdown (&global_sockfd);
+
+       if (n < 0)
+       {
+               char errbuf[1024];
+               ERROR ("apcups plugin: Reading from socket failed: %s",
+                               sstrerror (status, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       return (0);
+}
+
+static int apcups_config (const char *key, const char *value)
+{
+       if (strcasecmp (key, "host") == 0)
+       {
+               if (conf_host != NULL)
+               {
+                       free (conf_host);
+                       conf_host = NULL;
+               }
+               if ((conf_host = strdup (value)) == NULL)
+                       return (1);
+       }
+       else if (strcasecmp (key, "Port") == 0)
+       {
+               int port_tmp = atoi (value);
+               if (port_tmp < 1 || port_tmp > 65535)
+               {
+                       WARNING ("apcups plugin: Invalid port: %i", port_tmp);
+                       return (1);
+               }
+               conf_port = port_tmp;
+       }
+       else if (strcasecmp (key, "ReportSeconds") == 0)
+       {
+               if (IS_TRUE (value))
+                       conf_report_seconds = 1;
+               else
+                       conf_report_seconds = 0;
+       }
+       else
+       {
+               return (-1);
+       }
+       return (0);
+}
+
+static void apc_submit_generic (char *type, char *type_inst, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "apcups", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void apc_submit (struct apc_detail_s *apcups_detail)
+{
+       apc_submit_generic ("voltage",    "input",   apcups_detail->linev);
+       apc_submit_generic ("voltage",    "output",  apcups_detail->outputv);
+       apc_submit_generic ("voltage",    "battery", apcups_detail->battv);
+       apc_submit_generic ("charge",     "",        apcups_detail->bcharge);
+       apc_submit_generic ("percent",    "load",    apcups_detail->loadpct);
+       apc_submit_generic ("timeleft",   "",        apcups_detail->timeleft);
+       apc_submit_generic ("temperature", "",       apcups_detail->itemp);
+       apc_submit_generic ("frequency",  "input",   apcups_detail->linefreq);
+}
+
+static int apcups_read (void)
+{
+       struct apc_detail_s apcups_detail;
+       int status;
+
+       apcups_detail.linev    =   -1.0;
+       apcups_detail.outputv  =   -1.0;
+       apcups_detail.battv    =   -1.0;
+       apcups_detail.loadpct  =   -1.0;
+       apcups_detail.bcharge  =   -1.0;
+       apcups_detail.timeleft =    NAN;
+       apcups_detail.itemp    = -300.0;
+       apcups_detail.linefreq =   -1.0;
+
+       status = apc_query_server (conf_host == NULL
+                       ? APCUPS_DEFAULT_HOST
+                       : conf_host,
+                       conf_port, &apcups_detail);
+
+       /*
+        * if we did not connect then do not bother submitting
+        * zeros. We want rrd files to have NAN.
+        */
+       if (status != 0)
+       {
+               DEBUG ("apc_query_server (%s, %i) = %i",
+                               conf_host == NULL
+                               ? APCUPS_DEFAULT_HOST
+                               : conf_host,
+                               conf_port, status);
+               return (-1);
+       }
+
+       apc_submit (&apcups_detail);
+
+       return (0);
+} /* apcups_read */
+
+void module_register (void)
+{
+       plugin_register_config ("apcups", apcups_config, config_keys,
+                       config_keys_num);
+       plugin_register_read ("apcups", apcups_read);
+       plugin_register_shutdown ("apcups", apcups_shutdown);
+} /* void module_register */
diff --git a/src/apple_sensors.c b/src/apple_sensors.c
new file mode 100644 (file)
index 0000000..19d5a49
--- /dev/null
@@ -0,0 +1,244 @@
+/**
+ * collectd - src/apple_sensors.c
+ * Copyright (C) 2006,2007  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if HAVE_CTYPE_H
+#  include <ctype.h>
+#endif
+
+#if HAVE_MACH_MACH_TYPES_H
+#  include <mach/mach_types.h>
+#endif
+#if HAVE_MACH_MACH_INIT_H
+#  include <mach/mach_init.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#if HAVE_MACH_MACH_PORT_H
+#  include <mach/mach_port.h>
+#endif
+#if HAVE_COREFOUNDATION_COREFOUNDATION_H
+#  include <CoreFoundation/CoreFoundation.h>
+#endif
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+
+static mach_port_t io_master_port = MACH_PORT_NULL;
+
+static int as_init (void)
+{
+       kern_return_t status;
+       
+       if (io_master_port != MACH_PORT_NULL)
+       {
+               mach_port_deallocate (mach_task_self (),
+                               io_master_port);
+               io_master_port = MACH_PORT_NULL;
+       }
+
+       status = IOMasterPort (MACH_PORT_NULL, &io_master_port);
+       if (status != kIOReturnSuccess)
+       {
+               ERROR ("IOMasterPort failed: %s",
+                               mach_error_string (status));
+               io_master_port = MACH_PORT_NULL;
+               return (-1);
+       }
+
+       return (0);
+}
+
+static void as_submit (const char *type, const char *type_instance,
+               double val)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       DEBUG ("type = %s; type_instance = %s; val = %f;",
+                       type, type_instance, val);
+
+       values[0].gauge = val;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "apple_sensors", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int as_read (void)
+{
+       kern_return_t   status;
+       io_iterator_t   iterator;
+       io_object_t     io_obj;
+       CFMutableDictionaryRef prop_dict;
+       CFTypeRef       property;
+
+       char   type[128];
+       char   inst[128];
+       int    value_int;
+       double value_double;
+       int    i;
+
+       if (!io_master_port || (io_master_port == MACH_PORT_NULL))
+               return (-1);
+
+       status = IOServiceGetMatchingServices (io_master_port,
+                       IOServiceNameMatching("IOHWSensor"),
+                       &iterator);
+       if (status != kIOReturnSuccess)
+               {
+               ERROR ("IOServiceGetMatchingServices failed: %s",
+                               mach_error_string (status));
+               return (-1);
+       }
+
+       while ((io_obj = IOIteratorNext (iterator)))
+       {
+               prop_dict = NULL;
+               status = IORegistryEntryCreateCFProperties (io_obj,
+                               &prop_dict,
+                               kCFAllocatorDefault,
+                               kNilOptions);
+               if (status != kIOReturnSuccess)
+               {
+                       DEBUG ("IORegistryEntryCreateCFProperties failed: %s",
+                                       mach_error_string (status));
+                       continue;
+               }
+
+               /* Copy the sensor type. */
+               property = NULL;
+               if (!CFDictionaryGetValueIfPresent (prop_dict,
+                                       CFSTR ("type"),
+                                       &property))
+                       continue;
+               if (CFGetTypeID (property) != CFStringGetTypeID ())
+                       continue;
+               if (!CFStringGetCString (property,
+                                       type, sizeof (type),
+                                       kCFStringEncodingASCII))
+                       continue;
+               type[sizeof (type) - 1] = '\0';
+
+               /* Copy the sensor location. This will be used as `instance'. */
+               property = NULL;
+               if (!CFDictionaryGetValueIfPresent (prop_dict,
+                                       CFSTR ("location"),
+                                       &property))
+                       continue;
+               if (CFGetTypeID (property) != CFStringGetTypeID ())
+                       continue;
+               if (!CFStringGetCString (property,
+                                       inst, sizeof (inst),
+                                       kCFStringEncodingASCII))
+                       continue;
+               inst[sizeof (inst) - 1] = '\0';
+               for (i = 0; i < 128; i++)
+               {
+                       if (inst[i] == '\0')
+                               break;
+                       else if (isalnum (inst[i]))
+                               inst[i] = (char) tolower (inst[i]);
+                       else
+                               inst[i] = '_';
+               }
+
+               /* Get the actual value. Some computation, based on the `type'
+                * is neccessary. */
+               property = NULL;
+               if (!CFDictionaryGetValueIfPresent (prop_dict,
+                                       CFSTR ("current-value"),
+                                       &property))
+                       continue;
+               if (CFGetTypeID (property) != CFNumberGetTypeID ())
+                       continue;
+               if (!CFNumberGetValue (property,
+                                       kCFNumberIntType,
+                                       &value_int))
+                       continue;
+
+               /* Found e.g. in the 1.5GHz PowerBooks */
+               if (strcmp (type, "temperature") == 0)
+               {
+                       value_double = ((double) value_int) / 65536.0;
+                       sstrncpy (type, "temperature", sizeof (type));
+               }
+               else if (strcmp (type, "temp") == 0)
+               {
+                       value_double = ((double) value_int) / 10.0;
+                       sstrncpy (type, "temperature", sizeof (type));
+               }
+               else if (strcmp (type, "fanspeed") == 0)
+               {
+                       value_double = ((double) value_int) / 65536.0;
+                       sstrncpy (type, "fanspeed", sizeof (type));
+               }
+               else if (strcmp (type, "voltage") == 0)
+               {
+                       /* Leave this to the battery plugin. */
+                       continue;
+               }
+               else if (strcmp (type, "adc") == 0)
+               {
+                       value_double = ((double) value_int) / 10.0;
+                       sstrncpy (type, "fanspeed", sizeof (type));
+               }
+               else
+               {
+                       DEBUG ("apple_sensors: Read unknown sensor type: %s",
+                                       type);
+                       value_double = (double) value_int;
+               }
+
+               as_submit (type, inst, value_double);
+
+               CFRelease (prop_dict);
+               IOObjectRelease (io_obj);
+       } /* while (iterator) */
+
+       IOObjectRelease (iterator);
+
+       return (0);
+} /* int as_read */
+
+void module_register (void)
+{
+       plugin_register_init ("apple_sensors", as_init);
+       plugin_register_read ("apple_sensors", as_read);
+} /* void module_register */
diff --git a/src/aquaero.c b/src/aquaero.c
new file mode 100644 (file)
index 0000000..5db988e
--- /dev/null
@@ -0,0 +1,193 @@
+/**
+ * collectd - src/aquaero.c
+ * Copyright (C) 2013  Alex Deymo
+ *
+ * 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:
+ *   Alex Deymo
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <libaquaero5.h>
+
+/*
+ * Private variables
+ */
+/* Default values for contacting daemon */
+static char *conf_device = NULL;
+
+static int aquaero_config (oconfig_item_t *ci)
+{
+       int i;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Device", child->key))
+                       cf_util_get_string (child, &conf_device);
+               else
+               {
+                       ERROR ("aquaero plugin: Unknown config option \"%s\".",
+                                       child->key);
+               }
+       }
+
+       return (0);
+}
+
+static int aquaero_shutdown (void)
+{
+       libaquaero5_exit();
+       return (0);
+} /* int aquaero_shutdown */
+
+static void aquaero_submit (const char *type, const char *type_instance,
+               double value)
+{
+       const char *instance = conf_device?conf_device:"default";
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       /* Don't report undefined values. */
+       if (value == AQ5_FLOAT_UNDEF)
+               return;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "aquaero", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* int aquaero_submit */
+
+/* aquaero_submit_array submits every value of a given array of values */
+static void aquaero_submit_array (const char *type,
+               const char *type_instance_prefix, double *value_array, int len)
+{
+       char type_instance[DATA_MAX_NAME_LEN];
+       int i;
+
+       for (i = 0; i < len; i++)
+       {
+               if (value_array[i] == AQ5_FLOAT_UNDEF)
+                       continue;
+
+               snprintf (type_instance, sizeof (type_instance), "%s%d",
+                               type_instance_prefix, i + 1);
+               aquaero_submit (type, type_instance, value_array[i]);
+       }
+}
+
+static int aquaero_read (void)
+{
+       aq5_data_t aq_data;
+       aq5_settings_t aq_sett;
+       char *err_msg = NULL;
+       char type_instance[DATA_MAX_NAME_LEN];
+       int i;
+
+       if (libaquaero5_poll(conf_device, &aq_data, &err_msg) < 0)
+       {
+               char errbuf[1024];
+               ERROR ("aquaero plugin: Failed to poll device \"%s\": %s (%s)",
+                               conf_device ? conf_device : "default", err_msg,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       if (libaquaero5_getsettings(conf_device, &aq_sett, &err_msg) < 0)
+       {
+               char errbuf[1024];
+               ERROR ("aquaero plugin: Failed to get settings "
+                               "for device \"%s\": %s (%s)",
+                               conf_device ? conf_device : "default", err_msg,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       /* CPU Temperature sensor */
+       aquaero_submit("temperature", "cpu", aq_data.cpu_temp[0]);
+
+       /* Temperature sensors */
+       aquaero_submit_array("temperature", "sensor", aq_data.temp,
+                       AQ5_NUM_TEMP);
+
+       /* Virtual temperature sensors */
+       aquaero_submit_array("temperature", "virtual", aq_data.vtemp,
+                       AQ5_NUM_VIRT_SENSORS);
+
+       /* Software temperature sensors */
+       aquaero_submit_array("temperature", "software", aq_data.stemp,
+                       AQ5_NUM_SOFT_SENSORS);
+
+       /* Other temperature sensors */
+       aquaero_submit_array("temperature", "other", aq_data.otemp,
+                       AQ5_NUM_OTHER_SENSORS);
+
+       /* Fans */
+       for (i = 0; i < AQ5_NUM_FAN; i++)
+       {
+               if ((aq_sett.fan_data_source[i] == NONE)
+                               || (aq_data.fan_vrm_temp[i] != AQ5_FLOAT_UNDEF))
+                       continue;
+
+               snprintf (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]);
+               aquaero_submit ("voltage", type_instance,
+                               aq_data.fan_voltage[i]);
+               aquaero_submit ("current", type_instance,
+                               aq_data.fan_current[i]);
+
+               /* Report the voltage reglator module (VRM) temperature with a
+                * different type instance. */
+               snprintf (type_instance, sizeof (type_instance),
+                               "fan%d-vrm", i + 1);
+               aquaero_submit ("temperature", type_instance,
+                               aq_data.fan_vrm_temp[i]);
+       }
+
+       /* Flow sensors */
+       aquaero_submit_array("flow", "sensor", aq_data.flow, AQ5_NUM_FLOW);
+
+       /* Liquid level */
+       aquaero_submit_array("percent", "waterlevel",
+                       aq_data.level, AQ5_NUM_LEVEL);
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_complex_config ("aquaero", aquaero_config);
+       plugin_register_read ("aquaero", aquaero_read);
+       plugin_register_shutdown ("aquaero", aquaero_shutdown);
+} /* void module_register */
+
+/* vim: set sw=8 sts=8 noet : */
diff --git a/src/ascent.c b/src/ascent.c
new file mode 100644 (file)
index 0000000..11175af
--- /dev/null
@@ -0,0 +1,642 @@
+/**
+ * collectd - src/ascent.c
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <curl/curl.h>
+#include <libxml/parser.h>
+
+static char *races_list[] = /* {{{ */
+{
+  NULL,
+  "Human",    /*  1 */
+  "Orc",      /*  2 */
+  "Dwarf",    /*  3 */
+  "Nightelf", /*  4 */
+  "Undead",   /*  5 */
+  "Tauren",   /*  6 */
+  "Gnome",    /*  7 */
+  "Troll",    /*  8 */
+  NULL,
+  "Bloodelf", /* 10 */
+  "Draenei"   /* 11 */
+}; /* }}} */
+#define RACES_LIST_LENGTH STATIC_ARRAY_SIZE (races_list)
+
+static char *classes_list[] = /* {{{ */
+{
+  NULL,
+  "Warrior", /*  1 */
+  "Paladin", /*  2 */
+  "Hunter",  /*  3 */
+  "Rogue",   /*  4 */
+  "Priest",  /*  5 */
+  NULL,
+  "Shaman",  /*  7 */
+  "Mage",    /*  8 */
+  "Warlock", /*  9 */
+  NULL,
+  "Druid"    /* 11 */
+}; /* }}} */
+#define CLASSES_LIST_LENGTH STATIC_ARRAY_SIZE (classes_list)
+
+static char *genders_list[] = /* {{{ */
+{
+  "Male",
+  "Female"
+}; /* }}} */
+#define GENDERS_LIST_LENGTH STATIC_ARRAY_SIZE (genders_list)
+
+struct player_stats_s
+{
+  int races[RACES_LIST_LENGTH];
+  int classes[CLASSES_LIST_LENGTH];
+  int genders[GENDERS_LIST_LENGTH];
+  int level_sum;
+  int level_num;
+  int latency_sum;
+  int latency_num;
+};
+typedef struct player_stats_s player_stats_t;
+
+struct player_info_s
+{
+  int race;
+  int class;
+  int gender;
+  int level;
+  int latency;
+};
+typedef struct player_info_s player_info_t;
+#define PLAYER_INFO_STATIC_INIT { -1, -1, -1, -1, -1 }
+
+static char *url         = NULL;
+static char *user        = NULL;
+static char *pass        = NULL;
+static char *verify_peer = NULL;
+static char *verify_host = NULL;
+static char *cacert      = NULL;
+static char *timeout     = NULL;
+
+static CURL *curl = NULL;
+
+static char  *ascent_buffer = NULL;
+static size_t ascent_buffer_size = 0;
+static size_t ascent_buffer_fill = 0;
+static char   ascent_curl_error[CURL_ERROR_SIZE];
+
+static const char *config_keys[] =
+{
+  "URL",
+  "User",
+  "Password",
+  "VerifyPeer",
+  "VerifyHost",
+  "CACert",
+  "Timeout",
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int ascent_submit_gauge (const char *plugin_instance, /* {{{ */
+    const char *type, const char *type_instance, gauge_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "ascent", sizeof (vl.plugin));
+
+  if (plugin_instance != NULL)
+    sstrncpy (vl.plugin_instance, plugin_instance,
+        sizeof (vl.plugin_instance));
+
+  sstrncpy (vl.type, type, sizeof (vl.type));
+
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+  return (0);
+} /* }}} int ascent_submit_gauge */
+
+static size_t ascent_curl_callback (void *buf, size_t size, size_t nmemb, /* {{{ */
+    void __attribute__((unused)) *stream)
+{
+  size_t len = size * nmemb;
+
+  if (len <= 0)
+    return (len);
+
+  if ((ascent_buffer_fill + len) >= ascent_buffer_size)
+  {
+    char *temp;
+
+    temp = (char *) realloc (ascent_buffer,
+        ascent_buffer_fill + len + 1);
+    if (temp == NULL)
+    {
+      ERROR ("ascent plugin: realloc failed.");
+      return (0);
+    }
+    ascent_buffer = temp;
+    ascent_buffer_size = ascent_buffer_fill + len + 1;
+  }
+
+  memcpy (ascent_buffer + ascent_buffer_fill, (char *) buf, len);
+  ascent_buffer_fill += len;
+  ascent_buffer[ascent_buffer_fill] = 0;
+
+  return (len);
+} /* }}} size_t ascent_curl_callback */
+
+static int ascent_submit_players (player_stats_t *ps) /* {{{ */
+{
+  size_t i;
+  gauge_t value;
+
+  for (i = 0; i < RACES_LIST_LENGTH; i++)
+    if (races_list[i] != NULL)
+      ascent_submit_gauge ("by-race", "players", races_list[i],
+          (gauge_t) ps->races[i]);
+
+  for (i = 0; i < CLASSES_LIST_LENGTH; i++)
+    if (classes_list[i] != NULL)
+      ascent_submit_gauge ("by-class", "players", classes_list[i],
+          (gauge_t) ps->classes[i]);
+
+  for (i = 0; i < GENDERS_LIST_LENGTH; i++)
+    if (genders_list[i] != NULL)
+      ascent_submit_gauge ("by-gender", "players", genders_list[i],
+          (gauge_t) ps->genders[i]);
+
+  if (ps->level_num <= 0)
+    value = NAN;
+  else
+    value = ((double) ps->level_sum) / ((double) ps->level_num);
+  ascent_submit_gauge (NULL, "gauge", "avg-level", value);
+
+  /* Latency is in ms, but we store seconds. */
+  if (ps->latency_num <= 0)
+    value = NAN;
+  else
+    value = ((double) ps->latency_sum) / (1000.0 * ((double) ps->latency_num));
+  ascent_submit_gauge (NULL, "latency", "average", value);
+
+  return (0);
+} /* }}} int ascent_submit_players */
+
+static int ascent_account_player (player_stats_t *ps, /* {{{ */
+    player_info_t *pi)
+{
+  if (pi->race >= 0)
+  {
+    if (((size_t) pi->race >= RACES_LIST_LENGTH)
+        || (races_list[pi->race] == NULL))
+      ERROR ("ascent plugin: Ignoring invalid numeric race %i.", pi->race);
+    else
+      ps->races[pi->race]++;
+  }
+
+  if (pi->class >= 0)
+  {
+    if (((size_t) pi->class >= CLASSES_LIST_LENGTH)
+        || (classes_list[pi->class] == NULL))
+      ERROR ("ascent plugin: Ignoring invalid numeric class %i.", pi->class);
+    else
+      ps->classes[pi->class]++;
+  }
+
+  if (pi->gender >= 0)
+  {
+    if (((size_t) pi->gender >= GENDERS_LIST_LENGTH)
+        || (genders_list[pi->gender] == NULL))
+      ERROR ("ascent plugin: Ignoring invalid numeric gender %i.",
+          pi->gender);
+    else
+      ps->genders[pi->gender]++;
+  }
+
+
+  if (pi->level > 0)
+  {
+    ps->level_sum += pi->level;
+    ps->level_num++;
+  }
+
+  if (pi->latency >= 0)
+  {
+    ps->latency_sum += pi->latency;
+    ps->latency_num++;
+  }
+
+  return (0);
+} /* }}} int ascent_account_player */
+
+static int ascent_xml_submit_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */
+    const char *plugin_instance, const char *type, const char *type_instance)
+{
+  char *str_ptr;
+  gauge_t value;
+
+  str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
+  if (str_ptr == NULL)
+  {
+    ERROR ("ascent plugin: ascent_xml_submit_gauge: xmlNodeListGetString failed.");
+    return (-1);
+  }
+
+  if (strcasecmp ("N/A", str_ptr) == 0)
+    value = NAN;
+  else
+  {
+    char *end_ptr = NULL;
+    value = strtod (str_ptr, &end_ptr);
+    if (str_ptr == end_ptr)
+    {
+      xmlFree(str_ptr);
+      ERROR ("ascent plugin: ascent_xml_submit_gauge: strtod failed.");
+      return (-1);
+    }
+  }
+  xmlFree(str_ptr);
+
+  return (ascent_submit_gauge (plugin_instance, type, type_instance, value));
+} /* }}} int ascent_xml_submit_gauge */
+
+static int ascent_xml_read_int (xmlDoc *doc, xmlNode *node, /* {{{ */
+    int *ret_value)
+{
+  char *str_ptr;
+  int value;
+
+  str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
+  if (str_ptr == NULL)
+  {
+    ERROR ("ascent plugin: ascent_xml_read_int: xmlNodeListGetString failed.");
+    return (-1);
+  }
+
+  if (strcasecmp ("N/A", str_ptr) == 0)
+    value = -1;
+  else
+  {
+    char *end_ptr = NULL;
+    value = strtol (str_ptr, &end_ptr, 0);
+    if (str_ptr == end_ptr)
+    {
+      xmlFree(str_ptr);
+      ERROR ("ascent plugin: ascent_xml_read_int: strtol failed.");
+      return (-1);
+    }
+  }
+  xmlFree(str_ptr);
+
+  *ret_value = value;
+  return (0);
+} /* }}} int ascent_xml_read_int */
+
+static int ascent_xml_sessions_plr (xmlDoc *doc, xmlNode *node, /* {{{ */
+    player_info_t *pi)
+{
+  xmlNode *child;
+
+  for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+  {
+    if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
+      /* ignore */;
+    else if (xmlStrcmp ((const xmlChar *) "race", child->name) == 0)
+      ascent_xml_read_int (doc, child, &pi->race);
+    else if (xmlStrcmp ((const xmlChar *) "class", child->name) == 0)
+      ascent_xml_read_int (doc, child, &pi->class);
+    else if (xmlStrcmp ((const xmlChar *) "gender", child->name) == 0)
+      ascent_xml_read_int (doc, child, &pi->gender);
+    else if (xmlStrcmp ((const xmlChar *) "level", child->name) == 0)
+      ascent_xml_read_int (doc, child, &pi->level);
+    else if (xmlStrcmp ((const xmlChar *) "latency", child->name) == 0)
+      ascent_xml_read_int (doc, child, &pi->latency);
+    else if ((xmlStrcmp ((const xmlChar *) "name", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "pvprank", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "map", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "areaid", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "xpos", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "ypos", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "onime", child->name) == 0))
+      /* ignore */;
+    else
+    {
+      WARNING ("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name);
+    }
+  } /* for (child) */
+
+  return (0);
+} /* }}} int ascent_xml_sessions_plr */
+
+static int ascent_xml_sessions (xmlDoc *doc, xmlNode *node) /* {{{ */
+{
+  xmlNode *child;
+  player_stats_t ps;
+
+  memset (&ps, 0, sizeof (ps));
+
+  for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+  {
+    if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
+      /* ignore */;
+    else if (xmlStrcmp ((const xmlChar *) "plr", child->name) == 0)
+    {
+      int status;
+      player_info_t pi = PLAYER_INFO_STATIC_INIT;
+
+      status = ascent_xml_sessions_plr (doc, child, &pi);
+      if (status == 0)
+        ascent_account_player (&ps, &pi);
+    }
+    else
+    {
+      WARNING ("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name);
+    }
+  } /* for (child) */
+
+  ascent_submit_players (&ps);
+
+  return (0);
+} /* }}} int ascent_xml_sessions */
+
+static int ascent_xml_status (xmlDoc *doc, xmlNode *node) /* {{{ */
+{
+  xmlNode *child;
+
+  for (child = node->xmlChildrenNode; child != NULL; child = child->next)
+  {
+    if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
+      /* ignore */;
+    else if (xmlStrcmp ((const xmlChar *) "alliance", child->name) == 0)
+      ascent_xml_submit_gauge (doc, child, NULL, "players", "alliance");
+    else if (xmlStrcmp ((const xmlChar *) "horde", child->name) == 0)
+      ascent_xml_submit_gauge (doc, child, NULL, "players", "horde");
+    else if (xmlStrcmp ((const xmlChar *) "qplayers", child->name) == 0)
+      ascent_xml_submit_gauge (doc, child, NULL, "players", "queued");
+    else if ((xmlStrcmp ((const xmlChar *) "acceptedconns", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "avglat", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "cdbquerysize", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "cpu", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "fthreads", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "gmcount", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "lastupdate", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "ontime", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "oplayers", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "peakcount", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "platform", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "ram", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "threads", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "uptime", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "wdbquerysize", child->name) == 0))
+      /* ignore */;
+    else
+    {
+      WARNING ("ascent plugin: ascent_xml_status: Unknown tag: %s", child->name);
+    }
+  } /* for (child) */
+
+  return (0);
+} /* }}} int ascent_xml_status */
+
+static int ascent_xml (const char *data) /* {{{ */
+{
+  xmlDoc *doc;
+  xmlNode *cur;
+  xmlNode *child;
+
+#if 0
+  doc = xmlParseMemory (data, strlen (data),
+      /* URL = */ "ascent.xml",
+      /* encoding = */ NULL,
+      /* options = */ 0);
+#else
+  doc = xmlParseMemory (data, strlen (data));
+#endif
+  if (doc == NULL)
+  {
+    ERROR ("ascent plugin: xmlParseMemory failed.");
+    return (-1);
+  }
+
+  cur = xmlDocGetRootElement (doc);
+  if (cur == NULL)
+  {
+    ERROR ("ascent plugin: XML document is empty.");
+    xmlFreeDoc (doc);
+    return (-1);
+  }
+
+  if (xmlStrcmp ((const xmlChar *) "serverpage", cur->name) != 0)
+  {
+    ERROR ("ascent plugin: XML root element is not \"serverpage\".");
+    xmlFreeDoc (doc);
+    return (-1);
+  }
+
+  for (child = cur->xmlChildrenNode; child != NULL; child = child->next)
+  {
+    if ((xmlStrcmp ((const xmlChar *) "comment", child->name) == 0)
+        || (xmlStrcmp ((const xmlChar *) "text", child->name) == 0))
+      /* ignore */;
+    else if (xmlStrcmp ((const xmlChar *) "status", child->name) == 0)
+      ascent_xml_status (doc, child);
+    else if (xmlStrcmp ((const xmlChar *) "instances", child->name) == 0)
+      /* ignore for now */;
+    else if (xmlStrcmp ((const xmlChar *) "gms", child->name) == 0)
+      /* ignore for now */;
+    else if (xmlStrcmp ((const xmlChar *) "sessions", child->name) == 0)
+      ascent_xml_sessions (doc, child);
+    else
+    {
+      WARNING ("ascent plugin: ascent_xml: Unknown tag: %s", child->name);
+    }
+  } /* for (child) */
+
+  xmlFreeDoc (doc);
+  return (0);
+} /* }}} int ascent_xml */
+
+static int config_set (char **var, const char *value) /* {{{ */
+{
+  if (*var != NULL)
+  {
+    free (*var);
+    *var = NULL;
+  }
+
+  if ((*var = strdup (value)) == NULL)
+    return (1);
+  else
+    return (0);
+} /* }}} int config_set */
+
+static int ascent_config (const char *key, const char *value) /* {{{ */
+{
+  if (strcasecmp (key, "URL") == 0)
+    return (config_set (&url, value));
+  else if (strcasecmp (key, "User") == 0)
+    return (config_set (&user, value));
+  else if (strcasecmp (key, "Password") == 0)
+    return (config_set (&pass, value));
+  else if (strcasecmp (key, "VerifyPeer") == 0)
+    return (config_set (&verify_peer, value));
+  else if (strcasecmp (key, "VerifyHost") == 0)
+    return (config_set (&verify_host, value));
+  else if (strcasecmp (key, "CACert") == 0)
+    return (config_set (&cacert, value));
+  else if (strcasecmp (key, "Timeout") == 0)
+    return (config_set (&timeout, value));
+  else
+    return (-1);
+} /* }}} int ascent_config */
+
+static int ascent_init (void) /* {{{ */
+{
+  if (url == NULL)
+  {
+    WARNING ("ascent plugin: ascent_init: No URL configured, "
+        "returning an error.");
+    return (-1);
+  }
+
+  if (curl != NULL)
+  {
+    curl_easy_cleanup (curl);
+  }
+
+  if ((curl = curl_easy_init ()) == NULL)
+  {
+    ERROR ("ascent plugin: ascent_init: curl_easy_init failed.");
+    return (-1);
+  }
+
+  curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L);
+  curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ascent_curl_callback);
+  curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+  curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, ascent_curl_error);
+
+  if (user != NULL)
+  {
+#ifdef HAVE_CURLOPT_USERNAME
+    curl_easy_setopt (curl, CURLOPT_USERNAME, user);
+    curl_easy_setopt (curl, CURLOPT_PASSWORD, (pass == NULL) ? "" : pass);
+#else
+    static char credentials[1024];
+    int status;
+
+    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.");
+      return (-1);
+    }
+
+    curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
+#endif
+  }
+
+  curl_easy_setopt (curl, CURLOPT_URL, url);
+  curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
+  curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
+
+  if ((verify_peer == NULL) || IS_TRUE (verify_peer))
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1L);
+  else
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L);
+
+  if ((verify_host == NULL) || IS_TRUE (verify_host))
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2L);
+  else
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0L);
+
+  if (cacert != NULL)
+    curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
+
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+  if (timeout != NULL)
+    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, atol(timeout));
+  else
+    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
+       CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
+  return (0);
+} /* }}} int ascent_init */
+
+static int ascent_read (void) /* {{{ */
+{
+  int status;
+
+  if (curl == NULL)
+  {
+    ERROR ("ascent plugin: I don't have a CURL object.");
+    return (-1);
+  }
+
+  if (url == NULL)
+  {
+    ERROR ("ascent plugin: No URL has been configured.");
+    return (-1);
+  }
+
+  ascent_buffer_fill = 0;
+  if (curl_easy_perform (curl) != CURLE_OK)
+  {
+    ERROR ("ascent plugin: curl_easy_perform failed: %s",
+        ascent_curl_error);
+    return (-1);
+  }
+
+  status = ascent_xml (ascent_buffer);
+  if (status != 0)
+    return (-1);
+  else
+    return (0);
+} /* }}} int ascent_read */
+
+void module_register (void)
+{
+  plugin_register_config ("ascent", ascent_config, config_keys, config_keys_num);
+  plugin_register_init ("ascent", ascent_init);
+  plugin_register_read ("ascent", ascent_read);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 ts=8 et fdm=marker : */
diff --git a/src/barometer.c b/src/barometer.c
new file mode 100644 (file)
index 0000000..2bfd51e
--- /dev/null
@@ -0,0 +1,1891 @@
+/**
+ * collectd - src/barometer.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; only version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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:
+ *   Tomas Menzl
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_cache.h"
+#include "plugin.h"
+
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#include <math.h>
+
+/* ------------ MPL115 defines ------------ */
+/* I2C address of the MPL115 sensor */
+#define MPL115_I2C_ADDRESS          0x60
+                                    
+/* register addresses */            
+#define MPL115_ADDR_CONV            0x00
+#define MPL115_ADDR_COEFFS          0x04
+                                    
+/* register sizes */                
+#define MPL115_NUM_CONV             4
+#define MPL115_NUM_COEFFS           12
+                                    
+/* commands / addresses */          
+#define MPL115_CMD_CONVERT_PRESS    0x10
+#define MPL115_CMD_CONVERT_TEMP     0x11
+#define MPL115_CMD_CONVERT_BOTH     0x12
+                                    
+#define MPL115_CONVERSION_RETRIES   5
+
+
+/* ------------ MPL3115 defines ------------ */
+/* MPL3115 I2C address */
+#define MPL3115_I2C_ADDRESS         0x60
+
+/* register addresses (only the interesting ones) */
+#define MPL3115_REG_STATUS          0x00
+#define MPL3115_REG_OUT_P_MSB       0x01
+#define MPL3115_REG_OUT_P_CSB       0x02
+#define MPL3115_REG_OUT_P_LSB       0x03
+#define MPL3115_REG_OUT_T_MSB       0x04
+#define MPL3115_REG_OUT_T_LSB       0x05
+#define MPL3115_REG_DR_STATUS       0x06
+#define MPL3115_REG_WHO_AM_I        0x0C
+#define MPL3115_REG_SYSMOD          0x11
+#define MPL3115_REG_PT_DATA_CFG     0x13
+#define MPL3115_REG_BAR_IN_MSB      0x14
+#define MPL3115_REG_BAR_IN_LSB      0x15
+#define MPL3115_REG_CTRL_REG1       0x26
+#define MPL3115_REG_CTRL_REG2       0x27
+#define MPL3115_REG_CTRL_REG3       0x28
+#define MPL3115_REG_CTRL_REG4       0x29
+#define MPL3115_REG_CTRL_REG5       0x2A
+#define MPL3115_REG_OFF_P           0x2B
+#define MPL3115_REG_OFF_T           0x2C
+#define MPL3115_REG_OFF_H           0x2D
+
+/* Register values, masks */
+#define MPL3115_WHO_AM_I_RESP       0xC4
+
+#define MPL3115_PT_DATA_DREM        0x04
+#define MPL3115_PT_DATA_PDEF        0x02
+#define MPL3115_PT_DATA_TDEF        0x01
+                                    
+#define MPL3115_DR_STATUS_TDR       0x02
+#define MPL3115_DR_STATUS_PDR       0x04
+#define MPL3115_DR_STATUS_PTDR      0x08
+#define MPL3115_DR_STATUS_DR        (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR)
+                                    
+#define MPL3115_DR_STATUS_TOW       0x20
+#define MPL3115_DR_STATUS_POW       0x40
+#define MPL3115_DR_STATUS_PTOW      0x80
+
+#define MPL3115_CTRL_REG1_ALT       0x80
+#define MPL3115_CTRL_REG1_RAW       0x40
+#define MPL3115_CTRL_REG1_OST_MASK  0x38
+#define MPL3115_CTRL_REG1_OST_1     0x00
+#define MPL3115_CTRL_REG1_OST_2     0x08
+#define MPL3115_CTRL_REG1_OST_4     0x10
+#define MPL3115_CTRL_REG1_OST_8     0x18
+#define MPL3115_CTRL_REG1_OST_16    0x20
+#define MPL3115_CTRL_REG1_OST_32    0x28
+#define MPL3115_CTRL_REG1_OST_64    0x30
+#define MPL3115_CTRL_REG1_OST_128   0x38
+#define MPL3115_CTRL_REG1_RST       0x04
+#define MPL3115_CTRL_REG1_OST       0x02
+#define MPL3115_CTRL_REG1_SBYB      0x01
+#define MPL3115_CTRL_REG1_SBYB_MASK 0xFE
+
+#define MPL3115_NUM_CONV_VALS       5
+
+
+/* ------------ BMP085 defines ------------ */
+/* I2C address of the BMP085 sensor */
+#define BMP085_I2C_ADDRESS          0x77
+
+/* register addresses */            
+#define BMP085_ADDR_ID_REG          0xD0
+#define BMP085_ADDR_VERSION         0xD1
+
+#define BMP085_ADDR_CONV            0xF6
+
+#define BMP085_ADDR_CTRL_REG        0xF4
+#define BMP085_ADDR_COEFFS          0xAA
+
+/* register sizes */                
+#define BMP085_NUM_COEFFS           22
+
+/* commands, values */
+#define BMP085_CHIP_ID              0x55
+
+#define BMP085_CMD_CONVERT_TEMP     0x2E
+
+#define BMP085_CMD_CONVERT_PRESS_0  0x34
+#define BMP085_CMD_CONVERT_PRESS_1  0x74
+#define BMP085_CMD_CONVERT_PRESS_2  0xB4
+#define BMP085_CMD_CONVERT_PRESS_3  0xF4
+
+/* in us */
+#define BMP085_TIME_CNV_TEMP        4500
+
+#define BMP085_TIME_CNV_PRESS_0     4500
+#define BMP085_TIME_CNV_PRESS_1     7500
+#define BMP085_TIME_CNV_PRESS_2    13500
+#define BMP085_TIME_CNV_PRESS_3    25500
+
+
+/* ------------ Normalization ------------ */
+/* Mean sea level pressure normalization methods */
+#define MSLP_NONE          0
+#define MSLP_INTERNATIONAL 1
+#define MSLP_DEU_WETT      2
+
+/** Temperature reference history depth for averaging. See #get_reference_temperature */
+#define REF_TEMP_AVG_NUM   5
+
+
+/* ------------------------------------------ */
+
+/** Supported sensor types */
+enum Sensor_type {
+    Sensor_none = 0,
+    Sensor_MPL115,
+    Sensor_MPL3115,
+    Sensor_BMP085
+};
+
+static const char *config_keys[] =
+{
+    "Device",
+    "Oversampling",
+    "PressureOffset",    /**< only for MPL3115 */
+    "TemperatureOffset", /**< only for MPL3115 */
+    "Altitude",
+    "Normalization",
+    "TemperatureSensor"
+};
+
+static int    config_keys_num     = STATIC_ARRAY_SIZE(config_keys);
+                                  
+static char * config_device       = NULL;  /**< I2C bus device */
+static int    config_oversample   = 1;     /**< averaging window */
+
+static double config_press_offset = 0.0;   /**< pressure offset */
+static double config_temp_offset  = 0.0;   /**< temperature offset */
+
+static double config_altitude     = NAN;   /**< altitude */
+static int    config_normalize    = 0;     /**< normalization method */
+                                  
+static _Bool  configured          = 0;     /**< the whole plugin config status */
+                                  
+static int    i2c_bus_fd          = -1;    /**< I2C bus device FD */
+
+static enum Sensor_type sensor_type = Sensor_none; /**< detected/used sensor type */
+
+static __s32  mpl3115_oversample  = 0;    /**< MPL3115 CTRL1 oversample setting */
+
+// BMP085 configuration
+static unsigned      bmp085_oversampling; /**< BMP085 oversampling (0-3) */
+static unsigned long bmp085_timeCnvPress; /**< BMP085 conversion time for pressure in us */
+static __u8          bmp085_cmdCnvPress;  /**< BMP085 pressure conversion command */
+
+
+/* MPL115 conversion coefficients */
+static double mpl115_coeffA0;
+static double mpl115_coeffB1;
+static double mpl115_coeffB2;
+static double mpl115_coeffC12;
+static double mpl115_coeffC11;
+static double mpl115_coeffC22;
+
+/* BMP085 conversion coefficients */
+static short bmp085_AC1;
+static short bmp085_AC2;
+static short bmp085_AC3;
+static unsigned short bmp085_AC4;
+static unsigned short bmp085_AC5;
+static unsigned short bmp085_AC6;
+static short bmp085_B1;
+static short bmp085_B2;
+static short bmp085_MB;
+static short bmp085_MC;
+static short bmp085_MD;
+
+
+
+/* ------------------------ averaging ring buffer ------------------------ */
+/*  Used only for MPL115. MPL3115 supports real oversampling in the device so */
+/*  no need for any postprocessing. */
+
+static _Bool avg_initialized = 0;    /**< already initialized by real values */
+
+typedef struct averaging_s {
+    long int * ring_buffer;
+    int        ring_buffer_size;
+    long int   ring_buffer_sum;
+    int        ring_buffer_head;
+} averaging_t;
+
+
+static averaging_t pressure_averaging    = { NULL, 0, 0L, 0 };
+static averaging_t temperature_averaging = { NULL, 0, 0L, 0 };
+
+
+/** 
+ * Create / allocate averaging buffer
+ *
+ * The buffer is initialized with zeros.
+ *
+ * @param avg  pointer to ring buffer to be allocated
+ * @param size requested buffer size
+ *
+ * @return Zero when successful
+ */
+static int averaging_create(averaging_t * avg, int size)
+{
+    int a;
+
+    avg->ring_buffer = (long int *) malloc(size * sizeof(*avg));
+    if (avg->ring_buffer == NULL)
+    {
+        ERROR ("barometer: averaging_create - ring buffer allocation of size %d failed",
+               size);
+        return -1;
+    }
+
+    for (a=0; a<size; ++a)
+    {
+      avg->ring_buffer[a] = 0L;
+    }
+
+    avg->ring_buffer_size = size;
+    avg->ring_buffer_sum  = 0L;
+    avg->ring_buffer_head = 0;
+
+    return 0;
+}
+
+
+/**
+ * Delete / free existing averaging buffer
+ *
+ * @param avg  pointer to the ring buffer to be deleted
+ */
+static void averaging_delete(averaging_t * avg)
+{
+    if (avg->ring_buffer != NULL)
+    {
+        free(avg->ring_buffer);
+        avg->ring_buffer = NULL;
+    }
+    avg->ring_buffer_size = 0;
+    avg->ring_buffer_sum  = 0L;
+    avg->ring_buffer_head = 0;
+}
+
+
+/*
+ * Add new sample to the averaging buffer
+ *
+ * A new averaged value is returned. Note that till the buffer is full
+ * returned value is inaccurate as it is an average of real values and initial
+ * zeros.
+ *
+ * @param avg    pointer to the ring buffer
+ * @param sample new sample value
+ *
+ * @return Averaged sample value
+ */
+static double averaging_add_sample(averaging_t * avg, long int sample)
+{
+    double result;
+
+    avg->ring_buffer_sum += sample - avg->ring_buffer[avg->ring_buffer_head];
+    avg->ring_buffer[avg->ring_buffer_head] = sample;
+    avg->ring_buffer_head = (avg->ring_buffer_head+1) % avg->ring_buffer_size;
+    result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size);
+    
+    DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf", 
+           sample, 
+           result);
+
+    return result;
+}
+
+
+/* ------------------------ temperature refference ------------------------ */
+
+/**
+ * Linked list type of temperature sensor references
+ */
+typedef struct temperature_list_s {
+    char                      * sensor_name; /**< sensor name/reference */
+    size_t                      num_values;  /**< number of values (usually one) */
+    _Bool                       initialized; /**< sensor already provides data */
+    struct temperature_list_s * next;        /**< next in the list */
+} temperature_list_t;
+
+static temperature_list_t * temp_list = NULL;
+
+
+/*
+ * Add new sensor to the temperature reference list
+ *
+ * @param list   the list
+ * @param sensor reference name (as provided by the config file)
+ *
+ * @return Zero when successful
+ */
+static int temp_list_add(temperature_list_t * list, const char * sensor)
+{
+    temperature_list_t * new_temp;
+
+    new_temp = (temperature_list_t *) malloc(sizeof(*new_temp));
+    if(new_temp == NULL)
+        return -1;
+
+    new_temp->sensor_name = strdup(sensor);
+    new_temp->initialized = 0;
+    new_temp->num_values = 0;
+    if(new_temp->sensor_name == NULL)
+    {
+        free(new_temp);
+        return -1;
+    }
+
+    new_temp->next = temp_list;
+    temp_list = new_temp;
+    return 0;
+}
+
+
+/*
+ * Delete the whole temperature reference list
+ *
+ * @param list the list to be deleted
+ */
+static void temp_list_delete(temperature_list_t ** list)
+{
+    temperature_list_t * tmp;
+
+    while (*list != NULL)
+    {
+        tmp = (*list);
+        (*list) = (*list)->next;
+        free(tmp->sensor_name);
+        free(tmp);
+        tmp = NULL;
+    }
+}
+
+
+/*
+ * Get reference temperature value
+ *
+ * First initially uc_get_rate_by_name is tried. At the startup due to nondeterministic
+ * order the temperature may not be read yet (then it fails and first measurment gives
+ * only absolute air pressure reading which is acceptable). Once it succedes (should be
+ * second measurement at the latest) we use average of few last readings from
+ * uc_get_history_by_name. It may take few readings to start filling so again we use
+ * uc_get_rate_by_name as a fallback.
+ * The idea is to use basic "noise" filtering (history averaging) across all the values
+ * which given sensor provides (up to given depth). Then we get minimum among
+ * the sensors.
+ *
+ * @param result where the result is stored. When not available NAN is stored.
+ *
+ * @return Zero when successful
+ */
+static int get_reference_temperature(double * result)
+{
+    temperature_list_t * list = temp_list;
+
+    gauge_t * values = NULL;   /**< rate values */
+    size_t    values_num = 0;  /**< number of rate values */
+    int i;
+
+    gauge_t values_history[REF_TEMP_AVG_NUM];
+
+    double avg_sum;  /**< Value sum for computing average */
+    int    avg_num;  /**< Number of values for computing average */
+    double average;  /**< Resulting value average */
+
+    *result = NAN;
+
+    while(list != NULL)
+    {
+        avg_sum = 0.0;
+        avg_num = 0;
+
+        /* First time need to read current rate to learn how many values are
+           there (typically for temperature it would be just one).
+           We do not expect dynamic changing of number of temperarure values
+           in runtime yet (are there any such cases?). */
+        if(!list->initialized)
+        {
+            if(uc_get_rate_by_name(list->sensor_name,
+                                   &values,
+                                   &values_num))
+            {
+                DEBUG ("barometer: get_reference_temperature - rate \"%s\" not found yet",
+                       list->sensor_name);
+                list = list->next;
+                continue;
+            }
+
+            DEBUG ("barometer: get_reference_temperature - initialize \"%s\", %zu vals",
+                   list->sensor_name,
+                   values_num);
+
+            list->initialized = 1;
+            list->num_values = values_num;
+
+            for(i=0; i<values_num; ++i)
+            {
+                DEBUG ("barometer: get_reference_temperature - rate %d: %lf **",
+                       i,
+                       values[i]);
+                if(!isnan(values[i]))
+                {
+                    avg_sum += values[i];
+                    ++avg_num;
+                }
+            }
+            free(values);
+            values = NULL;
+        }
+
+        /* It is OK to get here the first time as well, in the worst case
+           the history will full of NANs. */
+        if(uc_get_history_by_name(list->sensor_name,
+                                  values_history,
+                                  REF_TEMP_AVG_NUM,
+                                  list->num_values))
+        {
+            ERROR ("barometer: get_reference_temperature - history \"%s\" lost",
+                   list->sensor_name);
+            list->initialized = 0;
+            list->num_values = 0;
+            list = list->next;
+            continue;
+        }
+            
+        for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
+        {
+            DEBUG ("barometer: get_reference_temperature - history %d: %lf",
+                   i,
+                   values_history[i]);
+            if(!isnan(values_history[i]))
+            {
+                avg_sum += values_history[i];
+                ++avg_num;
+            }
+        }
+
+        if(avg_num == 0)   /* still no history? fallback to current */
+        {
+            if(uc_get_rate_by_name(list->sensor_name,
+                                   &values,
+                                   &values_num))
+            {
+                ERROR ("barometer: get_reference_temperature - rate \"%s\" lost",
+                       list->sensor_name);
+                list->initialized = 0;
+                list->num_values = 0;
+                list = list->next;
+                continue;
+            }
+
+            for(i=0; i<values_num; ++i)
+            {
+                DEBUG ("barometer: get_reference_temperature - rate last %d: %lf **",
+                       i,
+                       values[i]);
+                if(!isnan(values[i]))
+                {
+                    avg_sum += values[i];
+                    ++avg_num;
+                }
+            }
+            free(values);
+            values = NULL;
+        }
+
+        if(avg_num == 0)
+        {
+            ERROR ("barometer: get_reference_temperature - could not read \"%s\"",
+                   list->sensor_name);
+            list->initialized = 0;
+            list->num_values = 0;
+        }
+        else
+        {
+            average = avg_sum / (double) avg_num;
+            if(isnan(*result))
+                *result=average;
+            else if(*result>average)
+                *result=average;
+        }
+        list = list->next;
+    }  /* while sensor list */
+    
+    if(*result == NAN)
+    {
+        ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
+        return -1;
+    }
+    DEBUG ("barometer: get_reference_temperature - temp is %lf", *result);
+    return 0;
+}
+
+
+/* ------------------------ MPL115 access ------------------------ */
+
+/** 
+ * Detect presence of a MPL115 pressure sensor.
+ *
+ * Unfortunately there seems to be no ID register so we just try to read first
+ * conversion coefficient from device at MPL115 address and hope it is really
+ * MPL115. We should use this check as the last resort (which would be the typical
+ * case anyway since MPL115 is the least accurate sensor).
+ * As a sideeffect will leave set I2C slave address.
+ * 
+ * @return 1 if MPL115, 0 otherwise
+ */
+static int MPL115_detect(void)
+{
+    __s32 res;
+    char errbuf[1024];
+
+    if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0)
+    {
+        ERROR("barometer: MPL115_detect problem setting i2c slave address to 0x%02X: %s",
+              MPL115_I2C_ADDRESS,
+              sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 0 ;
+    }
+
+    res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS);
+    if(res >= 0)
+    {
+        DEBUG ("barometer: MPL115_detect - positive detection");
+        return 1;
+    }
+
+    DEBUG ("barometer: MPL115_detect - negative detection");
+    return 0;
+}
+
+/** 
+ * Read the MPL115 sensor conversion coefficients.
+ *
+ * These are (device specific) constants so we can read them just once.
+ *
+ * @return Zero when successful
+ */
+static int MPL115_read_coeffs(void)
+{
+    uint8_t mpl115_coeffs[MPL115_NUM_COEFFS]; 
+    int32_t res;
+
+    int8_t  sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
+    int8_t  sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
+    int16_t sia0, sib1, sib2, sic12, sic11, sic22;
+      
+    char errbuf[1024];
+
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
+                                        MPL115_ADDR_COEFFS, 
+                                        MPL115_NUM_COEFFS, 
+                                        mpl115_coeffs);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL115_read_coeffs - problem reading data: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+   
+    /* Using perhaps less elegant/efficient code, but more readable. */
+    /* a0: 16total 1sign 12int 4fract 0pad */
+    sia0MSB = mpl115_coeffs[0];
+    sia0LSB = mpl115_coeffs[1];
+    sia0 = (int16_t) sia0MSB <<8;          /* s16 type, Shift to MSB */
+    sia0 += (int16_t) sia0LSB & 0x00FF;    /* Add LSB to 16bit number */
+    mpl115_coeffA0 = (double) (sia0);
+    mpl115_coeffA0 /= 8.0;                 /* 3 fract bits */
+    
+    /* b1: 16total 1sign 2int 13fract 0pad */
+    sib1MSB= mpl115_coeffs[2];
+    sib1LSB= mpl115_coeffs[3];
+    sib1 = sib1MSB <<8;                    /* Shift to MSB */
+    sib1 += sib1LSB & 0x00FF;              /* Add LSB to 16bit number */
+    mpl115_coeffB1 = (double) (sib1);
+    mpl115_coeffB1 /= 8192.0;              /* 13 fract */
+    
+    /* b2: 16total 1sign 1int 14fract 0pad */
+    sib2MSB= mpl115_coeffs[4];
+    sib2LSB= mpl115_coeffs[5];
+    sib2 = sib2MSB <<8;                     /* Shift to MSB */
+    sib2 += sib2LSB & 0x00FF;               /* Add LSB to 16bit number */
+    mpl115_coeffB2 = (double) (sib2);
+    mpl115_coeffB2 /= 16384.0;              /* 14 fract */
+
+    /* c12: 14total 1sign 0int 13fract 9pad */
+    sic12MSB= mpl115_coeffs[6];
+    sic12LSB= mpl115_coeffs[7];
+    sic12 = sic12MSB <<8;                   /* Shift to MSB only by 8 for MSB */
+    sic12 += sic12LSB & 0x00FF;
+    mpl115_coeffC12 = (double) (sic12);
+    mpl115_coeffC12 /= 4.0;                 /* 16-14=2 */
+    mpl115_coeffC12 /= 4194304.0;           /* 13+9=22 fract */
+
+    /* c11: 11total 1sign 0int 11fract 11pad */
+    sic11MSB= mpl115_coeffs[8];
+    sic11LSB= mpl115_coeffs[9];
+    sic11 = sic11MSB <<8;                   /* Shift to MSB only by 8 for MSB */
+    sic11 += sic11LSB & 0x00FF;
+    mpl115_coeffC11 = (double) (sic11);
+    mpl115_coeffC11 /= 32.0;               /* 16-11=5 */
+    mpl115_coeffC11 /= 4194304.0;          /* 11+11=22 fract */
+
+    /* c12: 11total 1sign 0int 10fract 15pad */
+    sic22MSB= mpl115_coeffs[10];
+    sic22LSB= mpl115_coeffs[11];
+    sic22 = sic22MSB <<8;                   /* Shift to MSB only by 8 for MSB */
+    sic22 += sic22LSB & 0x00FF;
+    mpl115_coeffC22 = (double) (sic22);
+    mpl115_coeffC22 /= 32.0; //16-11=5
+    mpl115_coeffC22 /= 33554432.0;          /* 10+15=25 fract */
+
+    DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, c11=%lf, c22=%lf",
+          mpl115_coeffA0, 
+          mpl115_coeffB1, 
+          mpl115_coeffB2, 
+          mpl115_coeffC12, 
+          mpl115_coeffC11, 
+          mpl115_coeffC22);
+    return 0;
+}
+
+
+/**
+ * Convert raw adc values to real data using the sensor coefficients.
+ *
+ * @param adc_pressure adc pressure value to be converted
+ * @param adc_temp     adc temperature value to be converted
+ * @param pressure     computed real pressure
+ * @param temperature  computed real temperature
+ */
+static void MPL115_convert_adc_to_real(double   adc_pressure,
+                                       double   adc_temp,
+                                       double * pressure,
+                                       double * temperature)
+{
+    double Pcomp;
+    Pcomp = mpl115_coeffA0 +                                            \
+        (mpl115_coeffB1 + mpl115_coeffC11*adc_pressure + mpl115_coeffC12*adc_temp) * adc_pressure + \
+        (mpl115_coeffB2 + mpl115_coeffC22*adc_temp) * adc_temp;
+    
+    *pressure = ((1150.0-500.0) * Pcomp / 1023.0) + 500.0;
+    *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
+    DEBUG ("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C",
+           *pressure,
+           *temperature);
+}
+
+
+/** 
+ * Read sensor averegaed measurements
+ *
+ * @param pressure    averaged measured pressure
+ * @param temperature averaged measured temperature
+ *
+ * @return Zero when successful
+ */
+static int MPL115_read_averaged(double * pressure, double * temperature)
+{
+    uint8_t mpl115_conv[MPL115_NUM_CONV]; 
+    int8_t  res;
+    int     retries;
+    int     conv_pressure;
+    int     conv_temperature;
+    double  adc_pressure;
+    double  adc_temperature;
+    char    errbuf[1024];
+
+    *pressure    = 0.0;
+    *temperature = 0.0;
+   
+    /* start conversion of both temp and presure */
+    retries = MPL115_CONVERSION_RETRIES;
+    while (retries>0)
+    {
+        /* write 1 to start conversion */
+        res = i2c_smbus_write_byte_data (i2c_bus_fd,
+                                         MPL115_CMD_CONVERT_BOTH,
+                                         0x01);
+        if (res >= 0)
+            break;
+
+        --retries;
+        if(retries>0)
+        {
+            ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, " \
+                   "will retry at most %d more times",
+                   sstrerror (errno, errbuf, sizeof (errbuf)),
+                   retries);
+        }
+        else
+        {
+            ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, "\
+                   "too many failed retries",
+                   sstrerror (errno, errbuf, sizeof (errbuf)));
+            return -1;
+        }
+    }
+
+    usleep (10000); /* wait 10ms for the conversion */
+
+    retries=MPL115_CONVERSION_RETRIES;
+    while (retries>0)
+    {
+        res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
+                                            MPL115_ADDR_CONV,
+                                            MPL115_NUM_CONV,
+                                            mpl115_conv); 
+        if (res >= 0)
+            break;
+
+        --retries;
+        if (retries>0)
+        {
+            ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \
+                   "will retry at most %d more times",
+                   sstrerror (errno, errbuf, sizeof (errbuf)),
+                   retries);
+        }
+        else
+        {
+            ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \
+                   "too many failed retries",
+                   sstrerror (errno, errbuf, sizeof (errbuf)));
+            return -1;
+        }
+    }
+    
+    conv_pressure    = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
+    conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
+    DEBUG ("barometer: MPL115_read_averaged, raw pressure ADC value = %d, " \
+           "raw temperature ADC value = %d",
+           conv_pressure,
+           conv_temperature);
+
+    adc_pressure    = averaging_add_sample (&pressure_averaging, conv_pressure);
+    adc_temperature = averaging_add_sample (&temperature_averaging, conv_temperature);
+
+    MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature);
+
+    DEBUG ("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / temperature = %lf, " \
+           "real pressure = %lf hPa / temperature = %lf C",
+           adc_pressure,
+           adc_temperature,
+           *pressure,
+           *temperature);
+    
+    return 0;
+}
+
+/* ------------------------ MPL3115 access ------------------------ */
+
+/** 
+ * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
+ *
+ * As a sideeffect will leave set I2C slave address.
+ * 
+ * @return 1 if MPL3115, 0 otherwise
+ */
+static int MPL3115_detect(void)
+{
+    __s32 res;
+    char errbuf[1024];
+
+    if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0)
+    {
+        ERROR("barometer: MPL3115_detect problem setting i2c slave address to 0x%02X: %s",
+              MPL3115_I2C_ADDRESS,
+              sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 0 ;
+    }
+
+    res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I);
+    if(res == MPL3115_WHO_AM_I_RESP)
+    {
+        DEBUG ("barometer: MPL3115_detect - positive detection");
+        return 1;
+    }
+
+    DEBUG ("barometer: MPL3115_detect - negative detection");
+    return 0;
+}
+
+/** 
+ * Adjusts oversampling to values supported by MPL3115
+ *
+ * MPL3115 supports only power of 2 in the range 1 to 128. 
+ */
+static void MPL3115_adjust_oversampling(void)
+{
+    int new_val = 0;
+
+    if(config_oversample > 100)
+    {
+        new_val = 128;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_128;
+    }
+    else if(config_oversample > 48)
+    {
+        new_val = 64;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_64;
+    }
+    else if(config_oversample > 24)
+    {
+        new_val = 32;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_32;
+    }
+    else if(config_oversample > 12)
+    {
+        new_val = 16;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_16;
+    }
+    else if(config_oversample > 6)
+    {
+        new_val = 8;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_8;
+    }
+    else if(config_oversample > 3)
+    {
+        new_val = 4;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_4;
+    }
+    else if(config_oversample > 1)
+    {
+        new_val = 2;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_2;
+    }
+    else
+    {
+        new_val = 1;
+        mpl3115_oversample = MPL3115_CTRL_REG1_OST_1;
+    }
+
+    DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from %d to %d",
+          config_oversample, 
+          new_val);
+    config_oversample = new_val;
+}
+
+/** 
+ * Read sensor averegaed measurements
+ *
+ * @param pressure    averaged measured pressure
+ * @param temperature averaged measured temperature
+ *
+ * @return Zero when successful
+ */
+static int MPL3115_read(double * pressure, double * temperature)
+{
+    __s32 res;
+    __s32 ctrl ;
+    __u8 data[MPL3115_NUM_CONV_VALS];
+    long int tmp_value = 0;
+    char errbuf[1024];
+    
+    /* Set Active - activate the device from standby */
+    res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_read - cannot read CTRL_REG1: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+    ctrl = res;
+    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
+                                    MPL3115_REG_CTRL_REG1, 
+                                    ctrl | MPL3115_CTRL_REG1_SBYB);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_read - problem activating: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+    
+    /* base sleep is 5ms x OST */
+    usleep(5000 * config_oversample);
+      
+    /* check the flags/status if ready */
+    res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_read - cannot read status register: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+    
+    while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR)
+    {
+        /* try some extra sleep... */
+        usleep(10000);
+        
+        /* ... and repeat the check. The conversion has to finish sooner or later. */
+        res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
+        if (res < 0)
+        {
+            ERROR ("barometer: MPL3115_read - cannot read status register: %s",
+                   sstrerror (errno, errbuf, sizeof (errbuf)));
+            return 1;
+        }
+    }
+    
+    /* Now read all the data in one block. There is address autoincrement. */
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
+                                        MPL3115_REG_OUT_P_MSB, 
+                                        MPL3115_NUM_CONV_VALS,
+                                        data);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_read - cannot read data registers: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+    
+    tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
+    *pressure = ((double) tmp_value) / 4.0 / 16.0 / 100.0;
+    DEBUG ("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure);
+    
+    if(data[3] > 0x7F)
+    {
+        data[3] = ~data[3] + 1;
+        *temperature = data[3];
+        *temperature = - *temperature;
+    }
+    else
+    {
+        *temperature = data[3];
+    }
+    
+    *temperature += (double)(data[4]) / 256.0;
+    DEBUG ("barometer: MPL3115_read - temperature = %lf C", *temperature);
+    
+    return 0;
+}
+
+/** 
+ * Initialize MPL3115 for barometeric measurements
+ * 
+ * @return 0 if successful
+ */
+static int MPL3115_init_sensor(void)
+{
+    __s32 res;
+    __s8 offset;
+    char errbuf[1024];
+    
+    /* Reset the sensor. It will reset immediately without ACKing */
+    /* the transaction, so no error handling here. */
+    i2c_smbus_write_byte_data(i2c_bus_fd, 
+                              MPL3115_REG_CTRL_REG1, 
+                              MPL3115_CTRL_REG1_RST);
+    
+    /* wait some time for the reset to finish */
+    usleep(100000);
+
+    /* now it should be in standby already so we can go and configure it */
+    
+    /*  Set temperature offset. */
+    /*  result = ADCtemp + offset [C] */
+    offset = (__s8) (config_temp_offset * 16.0);
+    res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_init_sensor - problem setting temp offset: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+    
+    /*  Set pressure offset. */
+    /*  result = ADCpress + offset [hPa] */
+    offset = (__s8) (config_press_offset * 100.0 / 4.0);
+    res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_P, offset);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_init_sensor - problem setting pressure offset: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+
+    /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */
+    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
+                                    MPL3115_REG_PT_DATA_CFG,
+                                    MPL3115_PT_DATA_DREM        \
+                                    | MPL3115_PT_DATA_PDEF      \
+                                    | MPL3115_PT_DATA_TDEF);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+
+    /* Set to barometer with an OSR */ 
+    res = i2c_smbus_write_byte_data(i2c_bus_fd, 
+                                    MPL3115_REG_CTRL_REG1, 
+                                    mpl3115_oversample);
+    if (res < 0)
+    {
+        ERROR ("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+
+    return 0;
+}
+
+/* ------------------------ BMP085 access ------------------------ */
+
+/** 
+ * Detect presence of a BMP085 pressure sensor by checking its ID register
+ *
+ * As a sideeffect will leave set I2C slave address.
+ * 
+ * @return 1 if BMP085, 0 otherwise
+ */
+static int BMP085_detect(void)
+{
+    __s32 res;
+    char errbuf[1024];
+
+    if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0)
+    {
+        ERROR("barometer: BMP085_detect - problem setting i2c slave address to 0x%02X: %s",
+              BMP085_I2C_ADDRESS,
+              sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 0 ;
+    }
+
+    res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG);
+    if(res == BMP085_CHIP_ID)
+    {
+        DEBUG ("barometer: BMP085_detect - positive detection");
+
+        /* get version */
+        res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION );
+        if (res < 0)
+        {
+            ERROR("barometer: BMP085_detect - problem checking chip version: %s",
+                  sstrerror (errno, errbuf, sizeof (errbuf)));
+            return 0 ;
+        }
+        DEBUG ("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X",
+               res & 0x0f,
+               (res & 0xf0) >> 4);
+        return 1;
+    }
+
+    DEBUG ("barometer: BMP085_detect - negative detection");
+    return 0;
+}
+
+
+/** 
+ * Adjusts oversampling settings to values supported by BMP085
+ *
+ * BMP085 supports only 1,2,4 or 8 samples. 
+ */
+static void BMP085_adjust_oversampling(void)
+{
+    int new_val = 0;
+
+    if( config_oversample > 6 ) /* 8 */
+    {
+        new_val = 8;
+        bmp085_oversampling = 3;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3;
+    }
+    else if( config_oversample > 3 ) /* 4 */
+    {
+        new_val = 4;
+        bmp085_oversampling = 2;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2;
+    }
+    else if( config_oversample > 1 ) /* 2 */
+    {
+        new_val = 2;
+        bmp085_oversampling = 1;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1;
+    }
+    else /* 1 */
+    {
+        new_val = 1;
+        bmp085_oversampling = 0;
+        bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0;
+        bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0;
+    }
+
+    DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from %d to %d",
+          config_oversample, 
+          new_val);
+    config_oversample = new_val;
+}
+
+
+/** 
+ * Read the BMP085 sensor conversion coefficients.
+ *
+ * These are (device specific) constants so we can read them just once.
+ *
+ * @return Zero when successful
+ */
+static int BMP085_read_coeffs(void)
+{
+    __s32 res;
+    __u8 coeffs[BMP085_NUM_COEFFS]; 
+    char errbuf[1024];
+
+    res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
+                                        BMP085_ADDR_COEFFS,
+                                        BMP085_NUM_COEFFS, 
+                                        coeffs);
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read_coeffs - problem reading data: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+    
+    bmp085_AC1 = ((int16_t)  coeffs[0]  <<8) | (int16_t)  coeffs[1];
+    bmp085_AC2 = ((int16_t)  coeffs[2]  <<8) | (int16_t)  coeffs[3];
+    bmp085_AC3 = ((int16_t)  coeffs[4]  <<8) | (int16_t)  coeffs[5];
+    bmp085_AC4 = ((uint16_t) coeffs[6]  <<8) | (uint16_t) coeffs[7];
+    bmp085_AC5 = ((uint16_t) coeffs[8]  <<8) | (uint16_t) coeffs[9];
+    bmp085_AC6 = ((uint16_t) coeffs[10] <<8) | (uint16_t) coeffs[11];
+    bmp085_B1 =  ((int16_t)  coeffs[12] <<8) | (int16_t)  coeffs[13];
+    bmp085_B2 =  ((int16_t)  coeffs[14] <<8) | (int16_t)  coeffs[15];
+    bmp085_MB =  ((int16_t)  coeffs[16] <<8) | (int16_t)  coeffs[17];
+    bmp085_MC =  ((int16_t)  coeffs[18] <<8) | (int16_t)  coeffs[19];
+    bmp085_MD =  ((int16_t)  coeffs[20] <<8) | (int16_t)  coeffs[21];
+
+    DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u,"\
+          " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d",
+          bmp085_AC1,
+          bmp085_AC2,
+          bmp085_AC3,
+          bmp085_AC4,
+          bmp085_AC5,
+          bmp085_AC6,
+          bmp085_B1,
+          bmp085_B2,
+          bmp085_MB,
+          bmp085_MC,
+          bmp085_MD);
+
+    return 0;
+}
+
+
+/**
+ * Convert raw BMP085 adc values to real data using the sensor coefficients.
+ *
+ * @param adc_pressure adc pressure value to be converted
+ * @param adc_temp     adc temperature value to be converted
+ * @param pressure     computed real pressure
+ * @param temperature  computed real temperature
+ */
+static void BMP085_convert_adc_to_real(long adc_pressure,
+                                       long adc_temperature,
+                                       double * pressure,
+                                       double * temperature)
+
+{
+    long X1, X2, X3;
+    long B3, B5, B6;
+    unsigned long B4, B7;
+
+    long T;
+    long P;
+
+
+    /* calculate real temperature */
+    X1 = ( (adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15;
+    X2 = (bmp085_MC << 11) / (X1 + bmp085_MD);
+
+    /* B5, T */
+    B5 = X1 + X2;
+    T = (B5 + 8) >> 4;
+    *temperature = (double)T * 0.1;
+
+    /* calculate real pressure */
+    /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept */
+
+    /* B6, B3 */
+    B6 = B5 - 4000;
+    X1 = ((bmp085_B2 * ((B6 * B6)>>12)) >> 11 );
+    X2 = (((long)bmp085_AC2 * B6) >> 11);
+    X3 = X1 + X2;
+    B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2;
+    
+    /* B4 */
+    X1 = (((long)bmp085_AC3*B6) >> 13);
+    X2 = (bmp085_B1*((B6*B6) >> 12) ) >> 16;
+    X3 = ((X1 + X2) + 2 ) >> 2;
+    B4 = ((long)bmp085_AC4* (unsigned long)(X3 + 32768)) >> 15;
+    
+    /* B7, P */
+    B7 =  (unsigned long)(adc_pressure - B3)*(50000>>bmp085_oversampling);
+    if( B7 < 0x80000000 )
+    {
+        P = (B7 << 1) / B4;
+    }
+    else
+    {
+        P = (B7/B4) << 1;
+    }
+    X1 = (P >> 8) * (P >> 8);
+    X1 = (X1 * 3038) >> 16;
+    X2 = ((-7357) * P) >> 16;
+    P = P + ( ( X1 + X2 + 3791 ) >> 4);
+    
+    *pressure = P / 100.0; // in [hPa] 
+    DEBUG ("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C",
+           *pressure,
+           *temperature);
+}
+
+    
+/** 
+ * Read compensated sensor measurements
+ *
+ * @param pressure    averaged measured pressure
+ * @param temperature averaged measured temperature
+ *
+ * @return Zero when successful
+ */
+static int BMP085_read(double * pressure, double * temperature)
+{
+    __s32 res;
+    __u8 measBuff[3];
+
+    long adc_pressure;
+    long adc_temperature;
+
+    char errbuf[1024];
+
+    /* start conversion of temperature */
+    res = i2c_smbus_write_byte_data( i2c_bus_fd,
+                                     BMP085_ADDR_CTRL_REG,
+                                     BMP085_CMD_CONVERT_TEMP );
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem requesting temperature conversion: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */
+
+    res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
+                                         BMP085_ADDR_CONV, 
+                                         2,
+                                         measBuff); 
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem reading temperature data: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    adc_temperature = ( (unsigned short)measBuff[0] << 8 ) + measBuff[1]; 
+    
+
+    /* get presure */
+    res = i2c_smbus_write_byte_data( i2c_bus_fd,
+                                     BMP085_ADDR_CTRL_REG, 
+                                     bmp085_cmdCnvPress );
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem requesting pressure conversion: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    usleep(bmp085_timeCnvPress); /* wait for the conversion */
+
+    res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
+                                         BMP085_ADDR_CONV, 
+                                         3,
+                                         measBuff );
+    if (res < 0)
+    {
+        ERROR ("barometer: BMP085_read - problem reading pressure data: %s",
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return 1;
+    }
+
+    adc_pressure = (long)((((ulong)measBuff[0]<<16) | ((ulong)measBuff[1]<<8) | (ulong)measBuff[2] ) >> (8 - bmp085_oversampling));
+    
+
+    DEBUG ("barometer: BMP085_read - raw pressure ADC value = %ld, " \
+           "raw temperature ADC value = %ld",
+           adc_pressure,
+           adc_temperature);
+
+    BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature);
+
+    return 0;
+}
+
+
+
+/* ------------------------ Sensor detection ------------------------ */
+/** 
+ * Detect presence of a supported sensor.
+ *
+ * As a sideeffect will leave set I2C slave address.
+ * The detection is done in the order BMP085, MPL3115, MPL115 and stops after
+ * first sensor beeing found.
+ * 
+ * @return detected sensor type
+ */
+enum Sensor_type Detect_sensor_type(void)
+{
+    if(BMP085_detect())
+        return Sensor_BMP085;
+
+    else if(MPL3115_detect())
+        return Sensor_MPL3115;
+
+    else if(MPL115_detect())
+        return Sensor_MPL115;
+
+    return Sensor_none;
+}
+
+/* ------------------------ Common functionality ------------------------ */
+
+/**
+ * Convert absolute pressure (in hPa) to mean sea level pressure
+ *
+ * Implemented methods are:
+ * - MSLP_NONE - no converions, returns absolute pressure
+ *
+ * - MSLP_INTERNATIONAL - see http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
+ *           Requires #config_altitude
+ *
+ * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See 
+ *                http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
+ *           Requires both #config_altitude and temperature reference(s).
+ *
+ * @param abs_pressure absloute pressure to be converted
+ *
+ * @return mean sea level pressure if successful, NAN otherwise
+ */
+static double abs_to_mean_sea_level_pressure(double abs_pressure)
+{
+    double mean = -1.0;
+    double temp = 0.0;
+    int result = 0;
+
+    if (config_normalize >= MSLP_DEU_WETT)
+    {
+        result = get_reference_temperature(&temp);
+        if(result)
+        {
+            return NAN;
+        }
+    }
+
+    switch(config_normalize)
+    {
+    case MSLP_NONE:
+        mean = abs_pressure;
+        break;
+        
+    case MSLP_INTERNATIONAL:
+        mean = abs_pressure / \
+            pow(1.0 - 0.0065*config_altitude/288.15, 9.80665*0.0289644/(8.31447*0.0065));
+        break;
+        
+    case MSLP_DEU_WETT:
+    {
+        double E; /* humidity */
+        double x;
+        if(temp<9.1)
+            E = 5.6402 * (-0.0916 + exp(0.06*temp) );
+        else
+            E = 18.2194 * (1.0463 - exp(-0.0666*temp) );
+        x = 9.80665 / (287.05 * (temp+273.15 + 0.12*E + 0.0065*config_altitude/2)) * config_altitude;
+        mean = abs_pressure * exp(x);
+    }
+    break;
+
+    default:
+        ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d", 
+               config_normalize);
+        mean = abs_pressure;
+        break;
+    }
+
+    DEBUG ("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, method = %d, meanPressure = %lf hPa",
+           abs_pressure,
+           config_normalize,
+           mean);
+
+    return mean; 
+}
+
+/* ------------------------ main plugin callbacks ------------------------ */
+
+/** 
+ * Main plugin configuration callback (using simple config)
+ * 
+ * @param key   configuration key we should process
+ * @param value configuration value we should process
+ * 
+ * @return Zero when successful.
+ */
+static int collectd_barometer_config (const char *key, const char *value)
+{
+    DEBUG("barometer: collectd_barometer_config");
+
+    if (strcasecmp (key, "Device") == 0)
+    {
+        sfree (config_device);
+        config_device = strdup (value);
+    }
+    else if (strcasecmp (key, "Oversampling") == 0)
+    {
+        int oversampling_tmp = atoi (value);
+        if (oversampling_tmp < 1 || oversampling_tmp > 1024)
+        {
+            WARNING ("barometer: collectd_barometer_config: invalid oversampling: %d." \
+                     " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for MPL3115) or 1 to 8 (for BMP085).",
+                     oversampling_tmp);
+            return 1;
+        }
+        config_oversample = oversampling_tmp;
+    }
+    else if (strcasecmp (key, "Altitude") == 0)
+    {
+        config_altitude = atof (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);
+            return 1;
+        }
+        config_normalize = normalize_tmp;
+    }
+    else if (strcasecmp (key, "TemperatureSensor") == 0)
+    {
+        if(temp_list_add(temp_list, value))
+        {
+            return -1;
+        }
+    }
+    else if (strcasecmp (key, "PressureOffset") == 0)
+    {
+        config_press_offset = atof(value);
+    }
+    else if (strcasecmp (key, "TemperatureOffset") == 0)
+    {
+        config_temp_offset = atof(value);
+    }
+    else 
+    {
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/** 
+ * Shutdown callback.
+ * 
+ * Close I2C and delete all the buffers.
+ * 
+ * @return Zero when successful (at the moment the only possible outcome)
+ */
+static int collectd_barometer_shutdown(void)
+{
+    DEBUG ("barometer: collectd_barometer_shutdown");
+
+    if(sensor_type == Sensor_MPL115)
+    {
+        averaging_delete (&pressure_averaging);
+        averaging_delete (&temperature_averaging);
+
+        temp_list_delete(&temp_list);
+    }
+
+    if (i2c_bus_fd > 0)
+    {
+        close (i2c_bus_fd);
+        i2c_bus_fd = -1;
+        sfree (config_device);
+    }
+
+    return 0;
+}
+
+
+/** 
+ * Plugin read callback for MPL115.
+ * 
+ *  Dispatching will create values:
+ *  - <hostname>/barometer-mpl115/pressure-normalized
+ *  - <hostname>/barometer-mpl115/pressure-absolute
+ *  - <hostname>/barometer-mpl115/temperature
+ *
+ * @return Zero when successful.
+ */
+static int MPL115_collectd_barometer_read (void)
+{
+    int result = 0;
+
+    double pressure        = 0.0;
+    double temperature     = 0.0;
+    double norm_pressure   = 0.0;
+
+    value_list_t vl = VALUE_LIST_INIT;
+    value_t      values[1];
+    
+    DEBUG("barometer: MPL115_collectd_barometer_read");
+
+    if (!configured)
+    {
+        return -1;
+    }
+
+    /* Rather than delaying init, we will intitialize during first read. This
+       way at least we have a better chance to have the reference temperature
+       already available. */
+    if(!avg_initialized)
+    {
+        int i;
+        for(i=0; i<config_oversample-1; ++i)
+        {
+            result = MPL115_read_averaged(&pressure, &temperature);
+            if(result)
+            {
+                ERROR ("barometer: MPL115_collectd_barometer_read - mpl115 read, ignored during init");
+            }
+            DEBUG("barometer: MPL115_collectd_barometer_read - init %d / %d", i+1, config_oversample-1);
+            usleep(20000);
+        }
+        avg_initialized = 1;
+    }
+
+    result = MPL115_read_averaged(&pressure, &temperature);
+    if(result)
+        return result;
+
+    norm_pressure = abs_to_mean_sea_level_pressure(pressure);
+
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
+    sstrncpy (vl.plugin_instance, "mpl115", sizeof (vl.plugin_instance));
+
+    vl.values_len = 1;
+    vl.values = values;
+
+    /* dispatch normalized air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
+    values[0].gauge = norm_pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch absolute air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
+    values[0].gauge = pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch sensor temperature */
+    sstrncpy (vl.type, "temperature", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+    values[0].gauge = temperature;
+    plugin_dispatch_values (&vl);
+
+    return 0;
+}
+
+
+/** 
+ * Plugin read callback for MPL3115.
+ * 
+ *  Dispatching will create values:
+ *  - <hostname>/barometer-mpl3115/pressure-normalized
+ *  - <hostname>/barometer-mpl3115/pressure-absolute
+ *  - <hostname>/barometer-mpl3115/temperature
+ *
+ * @return Zero when successful.
+ */
+static int MPL3115_collectd_barometer_read (void)
+{
+    int result = 0;
+    
+    double pressure        = 0.0;
+    double temperature     = 0.0;
+    double norm_pressure   = 0.0;
+    
+    value_list_t vl = VALUE_LIST_INIT;
+    value_t      values[1];
+    
+    DEBUG("barometer: MPL3115_collectd_barometer_read");
+    
+    if (!configured)
+    {
+        return -1;
+    }
+    
+    result = MPL3115_read(&pressure, &temperature);
+    if(result)
+        return result;
+
+    norm_pressure = abs_to_mean_sea_level_pressure(pressure);
+
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
+    sstrncpy (vl.plugin_instance, "mpl3115", sizeof (vl.plugin_instance));
+
+    vl.values_len = 1;
+    vl.values = values;
+
+    /* dispatch normalized air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
+    values[0].gauge = norm_pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch absolute air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
+    values[0].gauge = pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch sensor temperature */
+    sstrncpy (vl.type, "temperature", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+    values[0].gauge = temperature;
+    plugin_dispatch_values (&vl);
+
+    return 0;
+}
+
+
+/** 
+ * Plugin read callback for BMP085.
+ * 
+ *  Dispatching will create values:
+ *  - <hostname>/barometer-bmp085/pressure-normalized
+ *  - <hostname>/barometer-bmp085/pressure-absolute
+ *  - <hostname>/barometer-bmp085/temperature
+ *
+ * @return Zero when successful.
+ */
+static int BMP085_collectd_barometer_read (void)
+{
+    int result = 0;
+    
+    double pressure        = 0.0;
+    double temperature     = 0.0;
+    double norm_pressure   = 0.0;
+    
+    value_list_t vl = VALUE_LIST_INIT;
+    value_t      values[1];
+    
+    DEBUG("barometer: BMP085_collectd_barometer_read");
+    
+    if (!configured)
+    {
+        return -1;
+    }
+    
+    result = BMP085_read(&pressure, &temperature);
+    if(result)
+        return result;
+
+    norm_pressure = abs_to_mean_sea_level_pressure(pressure);
+
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
+    sstrncpy (vl.plugin_instance, "bmp085", sizeof (vl.plugin_instance));
+
+    vl.values_len = 1;
+    vl.values = values;
+
+    /* dispatch normalized air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
+    values[0].gauge = norm_pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch absolute air pressure */
+    sstrncpy (vl.type, "pressure", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
+    values[0].gauge = pressure;
+    plugin_dispatch_values (&vl);
+
+    /* dispatch sensor temperature */
+    sstrncpy (vl.type, "temperature", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+    values[0].gauge = temperature;
+    plugin_dispatch_values (&vl);
+
+    return 0;
+}
+
+
+/** 
+ * Initialization callback
+ * 
+ * Check config, initialize I2C bus access, conversion coefficients and averaging
+ * ring buffers
+ * 
+ * @return Zero when successful.
+ */
+static int collectd_barometer_init (void)
+{
+    char errbuf[1024];
+
+    DEBUG ("barometer: collectd_barometer_init");
+
+    if (config_device == NULL)
+    {
+        ERROR("barometer: collectd_barometer_init I2C bus device not configured");
+        return -1;
+    }
+
+    if (config_normalize >= MSLP_INTERNATIONAL && isnan(config_altitude))
+    {
+        ERROR("barometer: collectd_barometer_init no altitude configured " \
+              "for mean sea level pressure normalization.");
+        return -1;
+    }
+
+    if (config_normalize == MSLP_DEU_WETT
+        &&
+        temp_list == NULL)
+    {
+        ERROR("barometer: collectd_barometer_init no temperature reference "\
+              "configured for mean sea level pressure normalization.");
+        return -1;
+    }
+
+
+    i2c_bus_fd = open(config_device, O_RDWR);
+    if (i2c_bus_fd < 0)
+    {
+        ERROR ("barometer: collectd_barometer_init problem opening I2C bus device \"%s\": %s (is loaded mod i2c-dev?)",
+               config_device,
+               sstrerror (errno, errbuf, sizeof (errbuf)));
+        return -1;
+    }
+
+    /* detect sensor type - this will also set slave address */
+    sensor_type = Detect_sensor_type();
+
+    /* init correct sensor type */
+    switch(sensor_type)
+    {
+/* MPL3115 */
+    case Sensor_MPL3115:
+    {
+        MPL3115_adjust_oversampling();
+        
+        if(MPL3115_init_sensor())
+            return -1;
+        
+        plugin_register_read ("barometer", MPL3115_collectd_barometer_read);
+    }
+    break;
+
+/* MPL115 */
+    case Sensor_MPL115:
+    {
+        if (averaging_create (&pressure_averaging, config_oversample))
+        {
+            ERROR("barometer: collectd_barometer_init pressure averaging init failed");
+            return -1;
+        }
+        
+        if (averaging_create (&temperature_averaging, config_oversample))
+        {
+            ERROR("barometer: collectd_barometer_init temperature averaging init failed");
+            return -1;
+        }
+        
+        if (MPL115_read_coeffs() < 0)
+            return -1;
+        
+        plugin_register_read ("barometer", MPL115_collectd_barometer_read);
+    }
+    break;
+
+/* BMP085 */
+    case Sensor_BMP085:
+    {
+        BMP085_adjust_oversampling();
+
+        if (BMP085_read_coeffs() < 0)
+            return -1;
+
+        plugin_register_read ("barometer", BMP085_collectd_barometer_read);
+    }
+    break;
+
+/* anything else -> error */
+    default:
+        ERROR("barometer: collectd_barometer_init - no supported sensor found");
+        return -1;
+    }
+        
+
+    configured = 1;
+    return 0;
+}
+
+/* ------------------------ plugin register / entry point ------------------------ */
+
+/** 
+ * Plugin "entry" - register all callback.
+ * 
+ */
+void module_register (void)
+{
+    plugin_register_config ("barometer", 
+                            collectd_barometer_config, 
+                            config_keys, 
+                            config_keys_num);
+    plugin_register_init ("barometer", collectd_barometer_init);
+    plugin_register_shutdown ("barometer", collectd_barometer_shutdown);
+}
diff --git a/src/battery.c b/src/battery.c
new file mode 100644 (file)
index 0000000..9b060dd
--- /dev/null
@@ -0,0 +1,830 @@
+/**
+ * collectd - src/battery.c
+ * Copyright (C) 2006-2014  Florian octo Forster
+ * Copyright (C) 2008       Michał Mirosław
+ * Copyright (C) 2014       Andy Parkins
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Michał Mirosław <mirq-linux at rere.qmqm.pl>
+ *   Andy Parkins <andyp at fussylogic.co.uk>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_complain.h"
+
+#if HAVE_MACH_MACH_TYPES_H
+#  include <mach/mach_types.h>
+#endif
+#if HAVE_MACH_MACH_INIT_H
+#  include <mach/mach_init.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#if HAVE_COREFOUNDATION_COREFOUNDATION_H
+#  include <CoreFoundation/CoreFoundation.h>
+#endif
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+#  include <IOKit/ps/IOPowerSources.h>
+#endif
+#if HAVE_IOKIT_PS_IOPSKEYS_H
+#  include <IOKit/ps/IOPSKeys.h>
+#endif
+
+#if !HAVE_IOKIT_IOKITLIB_H && !HAVE_IOKIT_PS_IOPOWERSOURCES_H && !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
+       /* No global variables */
+/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
+
+#elif KERNEL_LINUX
+# define PROC_PMU_PATH_FORMAT "/proc/pmu/battery_%i"
+# define PROC_ACPI_PATH "/proc/acpi/battery"
+# define PROC_ACPI_FACTOR 0.001
+# define SYSFS_PATH "/sys/class/power_supply"
+# define SYSFS_FACTOR 0.000001
+#endif /* KERNEL_LINUX */
+
+static _Bool report_percent = 0;
+static _Bool report_degraded = 0;
+
+static void battery_submit2 (char const *plugin_instance, /* {{{ */
+               char const *type, char const *type_instance, gauge_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "battery", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* }}} void battery_submit2 */
+
+static void battery_submit (char const *plugin_instance, /* {{{ */
+               char const *type, gauge_t value)
+{
+       battery_submit2 (plugin_instance, type, NULL, value);
+} /* }}} void battery_submit */
+
+static void submit_capacity (char const *plugin_instance, /* {{{ */
+               gauge_t capacity_charged,
+               gauge_t capacity_full,
+               gauge_t capacity_design)
+{
+       if (report_percent && (capacity_charged > capacity_full))
+               return;
+       if (report_degraded && (capacity_full > capacity_design))
+               return;
+
+       if (report_percent)
+       {
+               gauge_t capacity_max;
+
+               if (report_degraded)
+                       capacity_max = capacity_design;
+               else
+                       capacity_max = capacity_full;
+
+               battery_submit2 (plugin_instance, "percent", "charged",
+                               100.0 * capacity_charged / capacity_max);
+               battery_submit2 (plugin_instance, "percent", "discharged",
+                               100.0 * (capacity_full - capacity_charged) / capacity_max);
+
+               if (report_degraded)
+                       battery_submit2 (plugin_instance, "percent", "degraded",
+                                       100.0 * (capacity_design - capacity_full) / capacity_max);
+       }
+       else if (report_degraded) /* && !report_percent */
+       {
+               battery_submit2 (plugin_instance, "capacity", "charged",
+                               capacity_charged);
+               battery_submit2 (plugin_instance, "capacity", "discharged",
+                               (capacity_full - capacity_charged));
+               battery_submit2 (plugin_instance, "capacity", "degraded",
+                               (capacity_design - capacity_full));
+       }
+       else /* !report_percent && !report_degraded */
+       {
+               battery_submit (plugin_instance, "capacity", capacity_charged);
+       }
+} /* }}} void submit_capacity */
+
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
+static double dict_get_double (CFDictionaryRef dict, char *key_string) /* {{{ */
+{
+       double      val_double;
+       long long   val_int;
+       CFNumberRef val_obj;
+       CFStringRef key_obj;
+
+       key_obj = CFStringCreateWithCString (kCFAllocatorDefault, key_string,
+                       kCFStringEncodingASCII);
+       if (key_obj == NULL)
+       {
+               DEBUG ("CFStringCreateWithCString (%s) failed.\n", key_string);
+               return (NAN);
+       }
+
+       if ((val_obj = CFDictionaryGetValue (dict, key_obj)) == NULL)
+       {
+               DEBUG ("CFDictionaryGetValue (%s) failed.", key_string);
+               CFRelease (key_obj);
+               return (NAN);
+       }
+       CFRelease (key_obj);
+
+       if (CFGetTypeID (val_obj) == CFNumberGetTypeID ())
+       {
+               if (CFNumberIsFloatType (val_obj))
+               {
+                       CFNumberGetValue (val_obj,
+                                       kCFNumberDoubleType,
+                                       &val_double);
+               }
+               else
+               {
+                       CFNumberGetValue (val_obj,
+                                       kCFNumberLongLongType,
+                                       &val_int);
+                       val_double = val_int;
+               }
+       }
+       else
+       {
+               DEBUG ("CFGetTypeID (val_obj) = %i", (int) CFGetTypeID (val_obj));
+               return (NAN);
+       }
+
+       return (val_double);
+} /* }}} double dict_get_double */
+
+# if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+static void get_via_io_power_sources (double *ret_charge, /* {{{ */
+               double *ret_current,
+               double *ret_voltage)
+{
+       CFTypeRef       ps_raw;
+       CFArrayRef      ps_array;
+       int             ps_array_len;
+       CFDictionaryRef ps_dict;
+       CFTypeRef       ps_obj;
+
+       double temp_double;
+       int i;
+
+       ps_raw       = IOPSCopyPowerSourcesInfo ();
+       ps_array     = IOPSCopyPowerSourcesList (ps_raw);
+       ps_array_len = CFArrayGetCount (ps_array);
+
+       DEBUG ("ps_array_len == %i", ps_array_len);
+
+       for (i = 0; i < ps_array_len; i++)
+       {
+               ps_obj  = CFArrayGetValueAtIndex (ps_array, i);
+               ps_dict = IOPSGetPowerSourceDescription (ps_raw, ps_obj);
+
+               if (ps_dict == NULL)
+               {
+                       DEBUG ("IOPSGetPowerSourceDescription failed.");
+                       continue;
+               }
+
+               if (CFGetTypeID (ps_dict) != CFDictionaryGetTypeID ())
+               {
+                       DEBUG ("IOPSGetPowerSourceDescription did not return a CFDictionaryRef");
+                       continue;
+               }
+
+               /* FIXME: Check if this is really an internal battery */
+
+               if (isnan (*ret_charge))
+               {
+                       /* This is the charge in percent. */
+                       temp_double = dict_get_double (ps_dict,
+                                       kIOPSCurrentCapacityKey);
+                       if (!isnan ((temp_double))
+                                       && (temp_double >= 0.0)
+                                       && (temp_double <= 100.0))
+                               *ret_charge = temp_double;
+               }
+
+               if (isnan (*ret_current))
+               {
+                       temp_double = dict_get_double (ps_dict,
+                                       kIOPSCurrentKey);
+                       if (!isnan (temp_double))
+                               *ret_current = temp_double / 1000.0;
+               }
+
+               if (isnan (*ret_voltage))
+               {
+                       temp_double = dict_get_double (ps_dict,
+                                       kIOPSVoltageKey);
+                       if (!isnan (temp_double))
+                               *ret_voltage = temp_double / 1000.0;
+               }
+       }
+
+       CFRelease(ps_array);
+       CFRelease(ps_raw);
+} /* }}} void get_via_io_power_sources */
+# endif /* HAVE_IOKIT_PS_IOPOWERSOURCES_H */
+
+# if HAVE_IOKIT_IOKITLIB_H
+static void get_via_generic_iokit (double *ret_capacity_full, /* {{{ */
+               double *ret_capacity_design,
+               double *ret_current,
+               double *ret_voltage)
+{
+       kern_return_t   status;
+       io_iterator_t   iterator;
+       io_object_t     io_obj;
+
+       CFDictionaryRef bat_root_dict;
+       CFArrayRef      bat_info_arry;
+       CFIndex         bat_info_arry_len;
+       CFIndex         bat_info_arry_pos;
+       CFDictionaryRef bat_info_dict;
+
+       double temp_double;
+
+       status = IOServiceGetMatchingServices (kIOMasterPortDefault,
+                       IOServiceNameMatching ("battery"),
+                       &iterator);
+       if (status != kIOReturnSuccess)
+       {
+               DEBUG ("IOServiceGetMatchingServices failed.");
+               return;
+       }
+
+       while ((io_obj = IOIteratorNext (iterator)))
+       {
+               status = IORegistryEntryCreateCFProperties (io_obj,
+                               (CFMutableDictionaryRef *) &bat_root_dict,
+                               kCFAllocatorDefault,
+                               kNilOptions);
+               if (status != kIOReturnSuccess)
+               {
+                       DEBUG ("IORegistryEntryCreateCFProperties failed.");
+                       continue;
+               }
+
+               bat_info_arry = (CFArrayRef) CFDictionaryGetValue (bat_root_dict,
+                               CFSTR ("IOBatteryInfo"));
+               if (bat_info_arry == NULL)
+               {
+                       CFRelease (bat_root_dict);
+                       continue;
+               }
+               bat_info_arry_len = CFArrayGetCount (bat_info_arry);
+
+               for (bat_info_arry_pos = 0;
+                               bat_info_arry_pos < bat_info_arry_len;
+                               bat_info_arry_pos++)
+               {
+                       bat_info_dict = (CFDictionaryRef) CFArrayGetValueAtIndex (bat_info_arry, bat_info_arry_pos);
+
+                       if (isnan (*ret_capacity_full))
+                       {
+                               temp_double = dict_get_double (bat_info_dict, "Capacity");
+                               *ret_capacity_full = temp_double / 1000.0;
+                       }
+
+                       if (isnan (*ret_capacity_design))
+                       {
+                               temp_double = dict_get_double (bat_info_dict, "AbsoluteMaxCapacity");
+                               *ret_capacity_design = temp_double / 1000.0;
+                       }
+
+                       if (isnan (*ret_current))
+                       {
+                               temp_double = dict_get_double (bat_info_dict, "Current");
+                               *ret_current = temp_double / 1000.0;
+                       }
+
+                       if (isnan (*ret_voltage))
+                       {
+                               temp_double = dict_get_double (bat_info_dict, "Voltage");
+                               *ret_voltage = temp_double / 1000.0;
+                       }
+               }
+               
+               CFRelease (bat_root_dict);
+       }
+
+       IOObjectRelease (iterator);
+} /* }}} void get_via_generic_iokit */
+# endif /* HAVE_IOKIT_IOKITLIB_H */
+
+static int battery_read (void) /* {{{ */
+{
+       gauge_t current = NAN; /* Current in A */
+       gauge_t voltage = NAN; /* Voltage in V */
+
+       /* We only get the charged capacity as a percentage from
+        * IOPowerSources. IOKit, on the other hand, only reports the full
+        * capacity. We use the two to calculate the current charged capacity. */
+       gauge_t charge_rel = NAN; /* Current charge in percent */
+       gauge_t capacity_charged = NAN; /* Charged capacity */
+       gauge_t capacity_full = NAN; /* Total capacity */
+       gauge_t capacity_design = NAN; /* Full design capacity */
+
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+       get_via_io_power_sources (&charge_rel, &current, &voltage);
+#endif
+#if HAVE_IOKIT_IOKITLIB_H
+       get_via_generic_iokit (&capacity_full, &capacity_design, &current, &voltage);
+#endif
+
+       capacity_charged = charge_rel * capacity_full / 100.0;
+       submit_capacity ("0", capacity_charged, capacity_full, capacity_design);
+
+       if (!isnan (current))
+               battery_submit ("0", "current", current);
+       if (!isnan (voltage))
+               battery_submit ("0", "voltage", voltage);
+
+       return (0);
+} /* }}} int battery_read */
+/* #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
+ * newline) and parses that number. */
+static int sysfs_file_to_buffer(char const *dir, /* {{{ */
+               char const *power_supply,
+               char const *basename,
+               char *buffer, size_t buffer_size)
+{
+       int status;
+       FILE *fp;
+       char filename[PATH_MAX];
+
+       ssnprintf (filename, sizeof (filename), "%s/%s/%s",
+                       dir, power_supply, basename);
+
+       /* No file isn't the end of the world -- not every system will be
+        * reporting the same set of statistics */
+       if (access (filename, R_OK) != 0)
+               return ENOENT;
+
+       fp = fopen (filename, "r");
+       if (fp == NULL)
+       {
+               status = errno;
+               if (status != ENOENT)
+               {
+                       char errbuf[1024];
+                       WARNING ("battery plugin: fopen (%s) failed: %s", filename,
+                                       sstrerror (status, errbuf, sizeof (errbuf)));
+               }
+               return status;
+       }
+
+       if (fgets (buffer, buffer_size, fp) == NULL)
+       {
+               status = errno;
+               if (status != ENODEV)
+               {
+                       char errbuf[1024];
+                       WARNING ("battery plugin: fgets (%s) failed: %s", filename,
+                                       sstrerror (status, errbuf, sizeof (errbuf)));
+               }
+               fclose (fp);
+               return status;
+       }
+
+       strstripnewline (buffer);
+
+       fclose (fp);
+       return 0;
+} /* }}} int sysfs_file_to_buffer */
+
+/* Reads a file which contains only a number (and optionally a trailing
+ * newline) and parses that number. */
+static int sysfs_file_to_gauge(char const *dir, /* {{{ */
+               char const *power_supply,
+               char const *basename, gauge_t *ret_value)
+{
+       int status;
+       char buffer[32] = "";
+
+       status = sysfs_file_to_buffer (dir, power_supply, basename, buffer, sizeof (buffer));
+       if (status != 0)
+               return (status);
+
+       return (strtogauge (buffer, ret_value));
+} /* }}} sysfs_file_to_gauge */
+
+static int read_sysfs_capacity (char const *dir, /* {{{ */
+               char const *power_supply,
+               char const *plugin_instance)
+{
+       gauge_t capacity_charged = NAN;
+       gauge_t capacity_full = NAN;
+       gauge_t capacity_design = NAN;
+       int status;
+
+       status = sysfs_file_to_gauge (dir, power_supply, "energy_now", &capacity_charged);
+       if (status != 0)
+               return (status);
+
+       status = sysfs_file_to_gauge (dir, power_supply, "energy_full", &capacity_full);
+       if (status != 0)
+               return (status);
+
+       status = sysfs_file_to_gauge (dir, power_supply, "energy_full_design", &capacity_design);
+       if (status != 0)
+               return (status);
+
+       submit_capacity (plugin_instance,
+                       capacity_charged * SYSFS_FACTOR,
+                       capacity_full * SYSFS_FACTOR,
+                       capacity_design * SYSFS_FACTOR);
+       return (0);
+} /* }}} int read_sysfs_capacity */
+
+static int read_sysfs_callback (char const *dir, /* {{{ */
+               char const *power_supply,
+               void *user_data)
+{
+       int *battery_index = user_data;
+
+       char const *plugin_instance;
+       char buffer[32];
+       gauge_t v = NAN;
+       _Bool discharging = 0;
+       int status;
+
+       /* Ignore non-battery directories, such as AC power. */
+       status = sysfs_file_to_buffer (dir, power_supply, "type", buffer, sizeof (buffer));
+       if (status != 0)
+               return (0);
+       if (strcasecmp ("Battery", buffer) != 0)
+               return (0);
+
+       (void) sysfs_file_to_buffer (dir, power_supply, "status", buffer, sizeof (buffer));
+       if (strcasecmp ("Discharging", buffer) == 0)
+               discharging = 1;
+
+       /* FIXME: This is a dirty hack for backwards compatibility: The battery
+        * plugin, for a very long time, has had the plugin_instance
+        * hard-coded to "0". So, to keep backwards compatibility, we'll use
+        * "0" for the first battery we find and the power_supply name for all
+        * following. This should be reverted in a future major version. */
+       plugin_instance = (*battery_index == 0) ? "0" : power_supply;
+       (*battery_index)++;
+
+       read_sysfs_capacity (dir, power_supply, plugin_instance);
+
+       if (sysfs_file_to_gauge (dir, power_supply, "power_now", &v) == 0)
+       {
+               if (discharging)
+                       v *= -1.0;
+               battery_submit (plugin_instance, "power", v * SYSFS_FACTOR);
+       }
+       if (sysfs_file_to_gauge (dir, power_supply, "current_now", &v) == 0)
+       {
+               if (discharging)
+                       v *= -1.0;
+               battery_submit (plugin_instance, "current", v * SYSFS_FACTOR);
+       }
+
+       if (sysfs_file_to_gauge (dir, power_supply, "voltage_now", &v) == 0)
+               battery_submit (plugin_instance, "voltage", v * SYSFS_FACTOR);
+
+       return (0);
+} /* }}} int read_sysfs_callback */
+
+static int read_sysfs (void) /* {{{ */
+{
+       int status;
+       int battery_counter = 0;
+
+       if (access (SYSFS_PATH, R_OK) != 0)
+               return (ENOENT);
+
+       status = walk_directory (SYSFS_PATH, read_sysfs_callback,
+                       /* user_data = */ &battery_counter,
+                       /* include hidden */ 0);
+       return (status);
+} /* }}} int read_sysfs */
+
+static int read_acpi_full_capacity (char const *dir, /* {{{ */
+               char const *power_supply,
+               gauge_t *ret_capacity_full,
+               gauge_t *ret_capacity_design)
+
+{
+       char filename[PATH_MAX];
+       char buffer[1024];
+
+       FILE *fh;
+
+       ssnprintf (filename, sizeof (filename), "%s/%s/info", dir, power_supply);
+       fh = fopen (filename, "r");
+       if ((fh = fopen (filename, "r")) == NULL)
+               return (errno);
+
+       /* last full capacity:      40090 mWh */
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               gauge_t *value_ptr;
+               int fields_num;
+               char *fields[8];
+               int index;
+
+               if (strncmp ("last full capacity:", buffer, strlen ("last full capacity:")) == 0)
+               {
+                       value_ptr = ret_capacity_full;
+                       index = 3;
+               }
+               else if (strncmp ("design capacity:", buffer, strlen ("design capacity:")) == 0)
+               {
+                       value_ptr = ret_capacity_design;
+                       index = 2;
+               }
+               else
+               {
+                       continue;
+               }
+
+               fields_num = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (fields_num <= index)
+                       continue;
+
+               strtogauge (fields[index], value_ptr);
+       }
+
+       fclose (fh);
+       return (0);
+} /* }}} int read_acpi_full_capacity */
+
+static int read_acpi_callback (char const *dir, /* {{{ */
+               char const *power_supply,
+               void *user_data)
+{
+       int *battery_index = user_data;
+
+       gauge_t power = NAN;
+       gauge_t voltage = NAN;
+       gauge_t capacity_charged = NAN;
+       gauge_t capacity_full = NAN;
+       gauge_t capacity_design = NAN;
+       _Bool charging = 0;
+       _Bool is_current = 0;
+
+       char const *plugin_instance;
+       char filename[PATH_MAX];
+       char buffer[1024];
+
+       FILE *fh;
+
+       ssnprintf (filename, sizeof (filename), "%s/%s/state", dir, power_supply);
+       fh = fopen (filename, "r");
+       if ((fh = fopen (filename, "r")) == NULL)
+       {
+               if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOENT))
+                       return (0);
+               else
+                       return (errno);
+       }
+
+       /*
+        * [11:00] <@tokkee> $ cat /proc/acpi/battery/BAT1/state
+        * [11:00] <@tokkee> present:                 yes
+        * [11:00] <@tokkee> capacity state:          ok
+        * [11:00] <@tokkee> charging state:          charging
+        * [11:00] <@tokkee> present rate:            1724 mA
+        * [11:00] <@tokkee> remaining capacity:      4136 mAh
+        * [11:00] <@tokkee> present voltage:         12428 mV
+        */
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               char *fields[8];
+               int numfields;
+
+               numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (numfields < 3)
+                       continue;
+
+               if ((strcmp (fields[0], "charging") == 0)
+                               && (strcmp (fields[1], "state:") == 0))
+               {
+                       if (strcmp (fields[2], "charging") == 0)
+                               charging = 1;
+                       else
+                               charging = 0;
+                       continue;
+               }
+
+               /* The unit of "present rate" depends on the battery. Modern
+                * batteries export power (watts), older batteries (used to)
+                * export current (amperes). We check the fourth column and try
+                * to find old batteries this way. */
+               if ((strcmp (fields[0], "present") == 0)
+                               && (strcmp (fields[1], "rate:") == 0))
+               {
+                       strtogauge (fields[2], &power);
+
+                       if ((numfields >= 4) && (strcmp ("mA", fields[3]) == 0))
+                               is_current = 1;
+               }
+               else if ((strcmp (fields[0], "remaining") == 0)
+                               && (strcmp (fields[1], "capacity:") == 0))
+                       strtogauge (fields[2], &capacity_charged);
+               else if ((strcmp (fields[0], "present") == 0)
+                               && (strcmp (fields[1], "voltage:") == 0))
+                       strtogauge (fields[2], &voltage);
+       } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
+
+       fclose (fh);
+
+       if (!charging)
+               power *= -1.0;
+
+       /* FIXME: This is a dirty hack for backwards compatibility: The battery
+        * plugin, for a very long time, has had the plugin_instance
+        * hard-coded to "0". So, to keep backwards compatibility, we'll use
+        * "0" for the first battery we find and the power_supply name for all
+        * following. This should be reverted in a future major version. */
+       plugin_instance = (*battery_index == 0) ? "0" : power_supply;
+       (*battery_index)++;
+
+       read_acpi_full_capacity (dir, power_supply, &capacity_full, &capacity_design);
+
+       submit_capacity (plugin_instance,
+                       capacity_charged * PROC_ACPI_FACTOR,
+                       capacity_full * PROC_ACPI_FACTOR,
+                       capacity_design * PROC_ACPI_FACTOR);
+
+       battery_submit (plugin_instance,
+                       is_current ? "current" : "power",
+                       power * PROC_ACPI_FACTOR);
+       battery_submit (plugin_instance, "voltage", voltage * PROC_ACPI_FACTOR);
+
+       return 0;
+} /* }}} int read_acpi_callback */
+
+static int read_acpi (void) /* {{{ */
+{
+       int status;
+       int battery_counter = 0;
+
+       if (access (PROC_ACPI_PATH, R_OK) != 0)
+               return (ENOENT);
+
+       status = walk_directory (PROC_ACPI_PATH, read_acpi_callback,
+                       /* user_data = */ &battery_counter,
+                       /* include hidden */ 0);
+       return (status);
+} /* }}} int read_acpi */
+
+static int read_pmu (void) /* {{{ */
+{
+       int i;
+
+       /* The upper limit here is just a safeguard. If there is a system with
+        * more than 100 batteries, this can easily be increased. */
+       for (i = 0; i < 100; i++)
+       {
+               FILE *fh;
+
+               char buffer[1024];
+               char filename[PATH_MAX];
+               char plugin_instance[DATA_MAX_NAME_LEN];
+
+               gauge_t current = NAN;
+               gauge_t voltage = NAN;
+               gauge_t charge  = NAN;
+
+               ssnprintf (filename, sizeof (filename), PROC_PMU_PATH_FORMAT, i);
+               if (access (filename, R_OK) != 0)
+                       break;
+
+               ssnprintf (plugin_instance, sizeof (plugin_instance), "%i", i);
+
+               fh = fopen (filename, "r");
+               if (fh == NULL)
+               {
+                       if (errno == ENOENT)
+                               break;
+                       else if ((errno == EAGAIN) || (errno == EINTR))
+                               continue;
+                       else
+                               return (errno);
+               }
+
+               while (fgets (buffer, sizeof (buffer), fh) != NULL)
+               {
+                       char *fields[8];
+                       int numfields;
+
+                       numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+                       if (numfields < 3)
+                               continue;
+
+                       if (strcmp ("current", fields[0]) == 0)
+                               strtogauge (fields[2], &current);
+                       else if (strcmp ("voltage", fields[0]) == 0)
+                               strtogauge (fields[2], &voltage);
+                       else if (strcmp ("charge", fields[0]) == 0)
+                               strtogauge (fields[2], &charge);
+               }
+
+               fclose (fh);
+               fh = NULL;
+
+               battery_submit (plugin_instance, "charge", charge / 1000.0);
+               battery_submit (plugin_instance, "current", current / 1000.0);
+               battery_submit (plugin_instance, "voltage", voltage / 1000.0);
+       }
+
+       if (i == 0)
+               return (ENOENT);
+       return (0);
+} /* }}} int read_pmu */
+
+static int battery_read (void) /* {{{ */
+{
+       int status;
+
+       DEBUG ("battery plugin: Trying sysfs ...");
+       status = read_sysfs ();
+       if (status == 0)
+               return (0);
+
+       DEBUG ("battery plugin: Trying acpi ...");
+       status = read_acpi ();
+       if (status == 0)
+               return (0);
+
+       DEBUG ("battery plugin: Trying pmu ...");
+       status = read_pmu ();
+       if (status == 0)
+               return (0);
+
+       ERROR ("battery plugin: Add available input methods failed.");
+       return (-1);
+} /* }}} int battery_read */
+#endif /* KERNEL_LINUX */
+
+static int battery_config (oconfig_item_t *ci)
+{
+       int i;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("ValuesPercentage", child->key) == 0)
+                       cf_util_get_boolean (child, &report_percent);
+               else if (strcasecmp ("ReportDegraded", child->key) == 0)
+                       cf_util_get_boolean (child, &report_degraded);
+               else
+                       WARNING ("battery plugin: Ignoring unknown "
+                                       "configuration option \"%s\".",
+                                       child->key);
+       }
+
+       return (0);
+} /* }}} int battery_config */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("battery", battery_config);
+       plugin_register_read ("battery", battery_read);
+} /* void module_register */
diff --git a/src/bind.c b/src/bind.c
new file mode 100644 (file)
index 0000000..2ad50f1
--- /dev/null
@@ -0,0 +1,1813 @@
+/**
+ * collectd - src/bind.c
+ * Copyright (C) 2009       Bruno Prémont
+ * Copyright (C) 2009,2010  Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Bruno Prémont <bonbons at linux-vserver.org>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "config.h"
+
+#if STRPTIME_NEEDS_STANDARDS
+# ifndef _ISOC99_SOURCE
+#  define _ISOC99_SOURCE 1
+# endif
+# ifndef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE 200112L
+# endif
+# ifndef _XOPEN_SOURCE
+#  define _XOPEN_SOURCE 500
+# endif
+#endif /* STRPTIME_NEEDS_STANDARDS */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+/* Some versions of libcurl don't include this themselves and then don't have
+ * fd_set available. */
+#if HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#include <curl/curl.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+#ifndef BIND_DEFAULT_URL
+# define BIND_DEFAULT_URL "http://localhost:8053/"
+#endif
+
+/* 
+ * Some types used for the callback functions. `translation_table_ptr_t' and
+ * `list_info_ptr_t' are passed to the callbacks in the `void *user_data'
+ * pointer.
+ */
+typedef int (*list_callback_t) (const char *name, value_t value,
+    time_t current_time, void *user_data);
+
+struct cb_view_s
+{
+  char *name;
+
+  int qtypes;
+  int resolver_stats;
+  int cacherrsets;
+
+  char **zones;
+  size_t zones_num;
+};
+typedef struct cb_view_s cb_view_t;
+
+struct translation_info_s
+{
+  const char *xml_name;
+  const char *type;
+  const char *type_instance;
+};
+typedef struct translation_info_s translation_info_t;
+
+struct translation_table_ptr_s
+{
+  const translation_info_t *table;
+  size_t table_length;
+  const char *plugin_instance;
+};
+typedef struct translation_table_ptr_s translation_table_ptr_t;
+
+struct list_info_ptr_s
+{
+  const char *plugin_instance;
+  const char *type;
+};
+typedef struct list_info_ptr_s list_info_ptr_t;
+
+/* FIXME: Enabled by default for backwards compatibility. */
+/* TODO: Remove time parsing code. */
+static _Bool config_parse_time = 1;
+
+static char *url                   = NULL;
+static int global_opcodes          = 1;
+static int global_qtypes           = 1;
+static int global_server_stats     = 1;
+static int global_zone_maint_stats = 1;
+static int global_resolver_stats   = 0;
+static int global_memory_stats     = 1;
+static int timeout                 = -1;
+
+static cb_view_t *views = NULL;
+static size_t     views_num = 0;
+
+static CURL *curl = NULL;
+
+static char  *bind_buffer = NULL;
+static size_t bind_buffer_size = 0;
+static size_t bind_buffer_fill = 0;
+static char   bind_curl_error[CURL_ERROR_SIZE];
+
+/* Translation table for the `nsstats' values. */
+static const translation_info_t nsstats_translation_table[] = /* {{{ */
+{
+  /* Requests */
+  { "Requestv4",       "dns_request",  "IPv4"        },
+  { "Requestv6",       "dns_request",  "IPv6"        },
+  { "ReqEdns0",        "dns_request",  "EDNS0"       },
+  { "ReqBadEDNSVer",   "dns_request",  "BadEDNSVer"  },
+  { "ReqTSIG",         "dns_request",  "TSIG"        },
+  { "ReqSIG0",         "dns_request",  "SIG0"        },
+  { "ReqBadSIG",       "dns_request",  "BadSIG"      },
+  { "ReqTCP",          "dns_request",  "TCP"         },
+  /* Rejects */
+  { "AuthQryRej",      "dns_reject",   "authorative" },
+  { "RecQryRej",       "dns_reject",   "recursive"   },
+  { "XfrRej",          "dns_reject",   "transfer"    },
+  { "UpdateRej",       "dns_reject",   "update"      },
+  /* Responses */
+  { "Response",        "dns_response", "normal"      },
+  { "TruncatedResp",   "dns_response", "truncated"   },
+  { "RespEDNS0",       "dns_response", "EDNS0"       },
+  { "RespTSIG",        "dns_response", "TSIG"        },
+  { "RespSIG0",        "dns_response", "SIG0"        },
+  /* Queries */
+  { "QryAuthAns",      "dns_query",    "authorative" },
+  { "QryNoauthAns",    "dns_query",    "nonauth"     },
+  { "QryReferral",     "dns_query",    "referral"    },
+  { "QryRecursion",    "dns_query",    "recursion"   },
+  { "QryDuplicate",    "dns_query",    "dupliate"    },
+  { "QryDropped",      "dns_query",    "dropped"     },
+  { "QryFailure",      "dns_query",    "failure"     },
+  /* Response codes */
+  { "QrySuccess",      "dns_rcode",    "tx-NOERROR"  },
+  { "QryNxrrset",      "dns_rcode",    "tx-NXRRSET"  },
+  { "QrySERVFAIL",     "dns_rcode",    "tx-SERVFAIL" },
+  { "QryFORMERR",      "dns_rcode",    "tx-FORMERR"  },
+  { "QryNXDOMAIN",     "dns_rcode",    "tx-NXDOMAIN" }
+#if 0
+  { "XfrReqDone",      "type", "type_instance"       },
+  { "UpdateReqFwd",    "type", "type_instance"       },
+  { "UpdateRespFwd",   "type", "type_instance"       },
+  { "UpdateFwdFail",   "type", "type_instance"       },
+  { "UpdateDone",      "type", "type_instance"       },
+  { "UpdateFail",      "type", "type_instance"       },
+  { "UpdateBadPrereq", "type", "type_instance"       },
+#endif
+};
+static int nsstats_translation_table_length =
+  STATIC_ARRAY_SIZE (nsstats_translation_table);
+/* }}} */
+
+/* Translation table for the `zonestats' values. */
+static const translation_info_t zonestats_translation_table[] = /* {{{ */
+{
+  /* Notify's */
+  { "NotifyOutv4",     "dns_notify",   "tx-IPv4"     },
+  { "NotifyOutv6",     "dns_notify",   "tx-IPv6"     },
+  { "NotifyInv4",      "dns_notify",   "rx-IPv4"     },
+  { "NotifyInv6",      "dns_notify",   "rx-IPv6"     },
+  { "NotifyRej",       "dns_notify",   "rejected"    },
+  /* SOA/AXFS/IXFS requests */
+  { "SOAOutv4",        "dns_opcode",   "SOA-IPv4"    },
+  { "SOAOutv6",        "dns_opcode",   "SOA-IPv6"    },
+  { "AXFRReqv4",       "dns_opcode",   "AXFR-IPv4"   },
+  { "AXFRReqv6",       "dns_opcode",   "AXFR-IPv6"   },
+  { "IXFRReqv4",       "dns_opcode",   "IXFR-IPv4"   },
+  { "IXFRReqv6",       "dns_opcode",   "IXFR-IPv6"   },
+  /* Domain transfers */
+  { "XfrSuccess",      "dns_transfer", "success"     },
+  { "XfrFail",         "dns_transfer", "failure"     }
+};
+static int zonestats_translation_table_length =
+  STATIC_ARRAY_SIZE (zonestats_translation_table);
+/* }}} */
+
+/* Translation table for the `resstats' values. */
+static const translation_info_t resstats_translation_table[] = /* {{{ */
+{
+  /* Generic resolver information */
+  { "Queryv4",         "dns_query",    "IPv4"        },
+  { "Queryv6",         "dns_query",    "IPv6"        },
+  { "Responsev4",      "dns_response", "IPv4"        },
+  { "Responsev6",      "dns_response", "IPv6"        },
+  /* Received response codes */
+  { "NXDOMAIN",        "dns_rcode",    "rx-NXDOMAIN" },
+  { "SERVFAIL",        "dns_rcode",    "rx-SERVFAIL" },
+  { "FORMERR",         "dns_rcode",    "rx-FORMERR"  },
+  { "OtherError",      "dns_rcode",    "rx-OTHER"    },
+  { "EDNS0Fail",       "dns_rcode",    "rx-EDNS0Fail"},
+  /* Received responses */
+  { "Mismatch",        "dns_response", "mismatch"    },
+  { "Truncated",       "dns_response", "truncated"   },
+  { "Lame",            "dns_response", "lame"        },
+  { "Retry",           "dns_query",    "retry"       },
+#if 0
+  { "GlueFetchv4",     "type", "type_instance" },
+  { "GlueFetchv6",     "type", "type_instance" },
+  { "GlueFetchv4Fail", "type", "type_instance" },
+  { "GlueFetchv6Fail", "type", "type_instance" },
+#endif
+  /* DNSSEC information */
+  { "ValAttempt",      "dns_resolver", "DNSSEC-attempt" },
+  { "ValOk",           "dns_resolver", "DNSSEC-okay"    },
+  { "ValNegOk",        "dns_resolver", "DNSSEC-negokay" },
+  { "ValFail",         "dns_resolver", "DNSSEC-fail"    }
+};
+static int resstats_translation_table_length =
+  STATIC_ARRAY_SIZE (resstats_translation_table);
+/* }}} */
+
+/* Translation table for the `memory/summary' values. */
+static const translation_info_t memsummary_translation_table[] = /* {{{ */
+{
+  { "TotalUse",        "memory",       "TotalUse"    },
+  { "InUse",           "memory",       "InUse"       },
+  { "BlockSize",       "memory",       "BlockSize"   },
+  { "ContextSize",     "memory",       "ContextSize" },
+  { "Lost",            "memory",       "Lost"        }
+};
+static int memsummary_translation_table_length =
+  STATIC_ARRAY_SIZE (memsummary_translation_table);
+/* }}} */
+
+static void submit (time_t ts, const char *plugin_instance, /* {{{ */
+    const char *type, const char *type_instance, value_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0] = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  if (config_parse_time)
+    vl.time = TIME_T_TO_CDTIME_T (ts);
+  sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+  sstrncpy(vl.plugin, "bind", sizeof(vl.plugin));
+  if (plugin_instance) {
+    sstrncpy(vl.plugin_instance, plugin_instance,
+        sizeof(vl.plugin_instance));
+    replace_special (vl.plugin_instance, sizeof (vl.plugin_instance));
+  }
+  sstrncpy(vl.type, type, sizeof(vl.type));
+  if (type_instance) {
+    sstrncpy(vl.type_instance, type_instance,
+        sizeof(vl.type_instance));
+    replace_special (vl.type_instance, sizeof (vl.type_instance));
+  }
+  plugin_dispatch_values(&vl);
+} /* }}} void submit */
+
+static size_t bind_curl_callback (void *buf, size_t size, /* {{{ */
+    size_t nmemb, void __attribute__((unused)) *stream)
+{
+  size_t len = size * nmemb;
+
+  if (len <= 0)
+    return (len);
+
+  if ((bind_buffer_fill + len) >= bind_buffer_size)
+  {
+    char *temp;
+
+    temp = realloc(bind_buffer, bind_buffer_fill + len + 1);
+    if (temp == NULL)
+    {
+      ERROR ("bind plugin: realloc failed.");
+      return (0);
+    }
+    bind_buffer = temp;
+    bind_buffer_size = bind_buffer_fill + len + 1;
+  }
+
+  memcpy (bind_buffer + bind_buffer_fill, (char *) buf, len);
+  bind_buffer_fill += len;
+  bind_buffer[bind_buffer_fill] = 0;
+
+  return (len);
+} /* }}} size_t bind_curl_callback */
+
+/*
+ * Callback, that's called with a translation table.
+ * (Plugin instance is fixed, type and type instance come from lookup table.)
+ */
+static int bind_xml_table_callback (const char *name, value_t value, /* {{{ */
+    time_t current_time, void *user_data)
+{
+  translation_table_ptr_t *table = (translation_table_ptr_t *) user_data;
+  size_t i;
+
+  if (table == NULL)
+    return (-1);
+
+  for (i = 0; i < table->table_length; i++)
+  {
+    if (strcmp (table->table[i].xml_name, name) != 0)
+      continue;
+
+    submit (current_time,
+        table->plugin_instance,
+        table->table[i].type,
+        table->table[i].type_instance,
+        value);
+    break;
+  }
+
+  return (0);
+} /* }}} int bind_xml_table_callback */
+
+/*
+ * Callback, that's used for lists.
+ * (Plugin instance and type are fixed, xml name is used as type instance.)
+ */
+static int bind_xml_list_callback (const char *name, /* {{{ */
+    value_t value, time_t current_time, void *user_data)
+{
+  list_info_ptr_t *list_info = (list_info_ptr_t *) user_data;
+
+  if (list_info == NULL)
+    return (-1);
+
+  submit (current_time,
+      list_info->plugin_instance,
+      list_info->type,
+      /* type instance = */ name,
+      value);
+
+  return (0);
+} /* }}} int bind_xml_list_callback */
+
+static int bind_xml_read_derive (xmlDoc *doc, xmlNode *node, /* {{{ */
+    derive_t *ret_value)
+{
+  char *str_ptr;
+  value_t value;
+  int status;
+
+  str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
+  if (str_ptr == NULL)
+  {
+    ERROR ("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed.");
+    return (-1);
+  }
+
+  status = parse_value (str_ptr, &value, DS_TYPE_DERIVE);
+  if (status != 0)
+  {
+    ERROR ("bind plugin: Parsing string \"%s\" to derive value failed.",
+        str_ptr);
+    xmlFree(str_ptr);
+    return (-1);
+  }
+
+  xmlFree(str_ptr);
+  *ret_value = value.derive;
+  return (0);
+} /* }}} int bind_xml_read_derive */
+
+static int bind_xml_read_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */
+    gauge_t *ret_value)
+{
+  char *str_ptr, *end_ptr;
+  double value;
+
+  str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
+  if (str_ptr == NULL)
+  {
+    ERROR ("bind plugin: bind_xml_read_gauge: xmlNodeListGetString failed.");
+    return (-1);
+  }
+
+  errno = 0;
+  value = strtod (str_ptr, &end_ptr);
+  xmlFree(str_ptr);
+  if (str_ptr == end_ptr || errno)
+  {
+    if (errno && (value < 0))
+      ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with underflow.");
+    else if (errno && (value > 0))
+      ERROR ("bind plugin: bind_xml_read_gauge: strtod failed with overflow.");
+    else
+      ERROR ("bind plugin: bind_xml_read_gauge: strtod failed.");
+    return (-1);
+  }
+
+  *ret_value = (gauge_t) value;
+  return (0);
+} /* }}} int bind_xml_read_gauge */
+
+static int bind_xml_read_timestamp (const char *xpath_expression, /* {{{ */
+    xmlDoc *doc, xmlXPathContext *xpathCtx, time_t *ret_value)
+{
+  xmlXPathObject *xpathObj = NULL;
+  xmlNode *node;
+  char *str_ptr;
+  char *tmp;
+  struct tm tm;
+
+  xpathObj = xmlXPathEvalExpression (BAD_CAST xpath_expression, xpathCtx);
+  if (xpathObj == NULL)
+  {
+    ERROR ("bind plugin: Unable to evaluate XPath expression `%s'.",
+        xpath_expression);
+    return (-1);
+  }
+
+  if ((xpathObj->nodesetval == NULL) || (xpathObj->nodesetval->nodeNr < 1))
+  {
+    xmlXPathFreeObject (xpathObj);
+    return (-1);
+  }
+
+  if (xpathObj->nodesetval->nodeNr != 1)
+  {
+    NOTICE ("bind plugin: Evaluating the XPath expression `%s' returned "
+        "%i nodes. Only handling the first one.",
+        xpath_expression, xpathObj->nodesetval->nodeNr);
+  }
+
+  node = xpathObj->nodesetval->nodeTab[0];
+
+  if (node->xmlChildrenNode == NULL)
+  {
+    ERROR ("bind plugin: bind_xml_read_timestamp: "
+        "node->xmlChildrenNode == NULL");
+    xmlXPathFreeObject (xpathObj);
+    return (-1);
+  }
+
+  str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1);
+  if (str_ptr == NULL)
+  {
+    ERROR ("bind plugin: bind_xml_read_timestamp: xmlNodeListGetString failed.");
+    xmlXPathFreeObject (xpathObj);
+    return (-1);
+  }
+
+  memset (&tm, 0, sizeof(tm));
+  tmp = strptime (str_ptr, "%Y-%m-%dT%T", &tm);
+  xmlFree(str_ptr);
+  if (tmp == NULL)
+  {
+    ERROR ("bind plugin: bind_xml_read_timestamp: strptime failed.");
+    xmlXPathFreeObject (xpathObj);
+    return (-1);
+  }
+
+  *ret_value = mktime(&tm);
+
+  xmlXPathFreeObject (xpathObj);
+  return (0);
+} /* }}} int bind_xml_read_timestamp */
+
+/* 
+ * bind_parse_generic_name_value
+ *
+ * Reads statistics in the form:
+ * <foo>
+ *   <name>QUERY</name>
+ *   <counter>123</counter>
+ * </foo>
+ */
+static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ */
+    list_callback_t list_callback,
+    void *user_data,
+    xmlDoc *doc, xmlXPathContext *xpathCtx,
+    time_t current_time, int ds_type)
+{
+  xmlXPathObject *xpathObj = NULL;
+  int num_entries;
+  int i;
+
+  xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
+  if (xpathObj == NULL)
+  {
+    ERROR("bind plugin: Unable to evaluate XPath expression `%s'.",
+        xpath_expression);
+    return (-1);
+  }
+
+  num_entries = 0;
+  /* Iterate over all matching nodes. */
+  for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+  {
+    xmlNode *name_node = NULL;
+    xmlNode *counter = NULL;
+    xmlNode *parent;
+    xmlNode *child;
+
+    parent = xpathObj->nodesetval->nodeTab[i];
+    DEBUG ("bind plugin: bind_parse_generic_name_value: parent->name = %s;",
+        (char *) parent->name);
+
+    /* Iterate over all child nodes. */
+    for (child = parent->xmlChildrenNode;
+        child != NULL;
+        child = child->next)
+    {
+      if (child->type != XML_ELEMENT_NODE)
+        continue;
+
+      if (xmlStrcmp (BAD_CAST "name", child->name) == 0)
+        name_node = child;
+      else if (xmlStrcmp (BAD_CAST "counter", child->name) == 0)
+        counter = child;
+    }
+
+    if ((name_node != NULL) && (counter != NULL))
+    {
+      char *name = (char *) xmlNodeListGetString (doc,
+          name_node->xmlChildrenNode, 1);
+      value_t value;
+      int status;
+
+      if (ds_type == DS_TYPE_GAUGE)
+        status = bind_xml_read_gauge (doc, counter, &value.gauge);
+      else
+        status = bind_xml_read_derive (doc, counter, &value.derive);
+      if (status != 0)
+        continue;
+
+      status = (*list_callback) (name, value, current_time, user_data);
+      if (status == 0)
+        num_entries++;
+
+      xmlFree (name);
+    }
+  }
+
+  DEBUG ("bind plugin: Found %d %s for XPath expression `%s'",
+      num_entries, (num_entries == 1) ? "entry" : "entries",
+      xpath_expression);
+
+  xmlXPathFreeObject(xpathObj);
+
+  return (0);
+} /* }}} int bind_parse_generic_name_value */
+
+/* 
+ * bind_parse_generic_value_list
+ *
+ * Reads statistics in the form:
+ * <foo>
+ *   <name0>123</name0>
+ *   <name1>234</name1>
+ *   <name2>345</name2>
+ *   :
+ * </foo>
+ */
+static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ */
+    list_callback_t list_callback,
+    void *user_data,
+    xmlDoc *doc, xmlXPathContext *xpathCtx,
+    time_t current_time, int ds_type)
+{
+  xmlXPathObject *xpathObj = NULL;
+  int num_entries;
+  int i;
+
+  xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
+  if (xpathObj == NULL)
+  {
+    ERROR("bind plugin: Unable to evaluate XPath expression `%s'.",
+        xpath_expression);
+    return (-1);
+  }
+
+  num_entries = 0;
+  /* Iterate over all matching nodes. */
+  for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+  {
+    xmlNode *child;
+
+    /* Iterate over all child nodes. */
+    for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
+        child != NULL;
+        child = child->next)
+    {
+      char *node_name;
+      value_t value;
+      int status;
+
+      if (child->type != XML_ELEMENT_NODE)
+        continue;
+
+      node_name = (char *) child->name;
+
+      if (ds_type == DS_TYPE_GAUGE)
+        status = bind_xml_read_gauge (doc, child, &value.gauge);
+      else
+        status = bind_xml_read_derive (doc, child, &value.derive);
+      if (status != 0)
+        continue;
+
+      status = (*list_callback) (node_name, value, current_time, user_data);
+      if (status == 0)
+        num_entries++;
+    }
+  }
+
+  DEBUG ("bind plugin: Found %d %s for XPath expression `%s'",
+      num_entries, (num_entries == 1) ? "entry" : "entries",
+      xpath_expression);
+
+  xmlXPathFreeObject(xpathObj);
+
+  return (0);
+} /* }}} int bind_parse_generic_value_list */
+
+/*
+ * bind_parse_generic_name_attr_value_list
+ *
+ * Reads statistics in the form:
+ * <foo>
+ *   <counter name="name0">123</counter>
+ *   <counter name="name1">234</counter>
+ *   <counter name="name2">345</counter>
+ *   :
+ * </foo>
+ */
+static int bind_parse_generic_name_attr_value_list (const char *xpath_expression, /* {{{ */
+    list_callback_t list_callback,
+    void *user_data,
+    xmlDoc *doc, xmlXPathContext *xpathCtx,
+    time_t current_time, int ds_type)
+{
+  xmlXPathObject *xpathObj = NULL;
+  int num_entries;
+  int i;
+
+  xpathObj = xmlXPathEvalExpression(BAD_CAST xpath_expression, xpathCtx);
+  if (xpathObj == NULL)
+  {
+    ERROR("bind plugin: Unable to evaluate XPath expression `%s'.",
+        xpath_expression);
+    return (-1);
+  }
+
+  num_entries = 0;
+  /* Iterate over all matching nodes. */
+  for (i = 0; xpathObj->nodesetval && (i < xpathObj->nodesetval->nodeNr); i++)
+  {
+    xmlNode *child;
+
+    /* Iterate over all child nodes. */
+    for (child = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
+        child != NULL;
+        child = child->next)
+    {
+      if (child->type != XML_ELEMENT_NODE)
+        continue;
+
+      if (strncmp ("counter", (char *) child->name, strlen ("counter")) != 0)
+        continue;
+
+      char *attr_name;
+      value_t value;
+      int status;
+
+      attr_name = (char *) xmlGetProp (child, BAD_CAST "name");
+      if (attr_name == NULL)
+      {
+        DEBUG ("bind plugin: found <counter> without name.");
+        continue;
+      }
+      if (ds_type == DS_TYPE_GAUGE)
+        status = bind_xml_read_gauge (doc, child, &value.gauge);
+      else
+        status = bind_xml_read_derive (doc, child, &value.derive);
+      if (status != 0)
+        continue;
+
+      status = (*list_callback) (attr_name, value, current_time, user_data);
+      if (status == 0)
+        num_entries++;
+    }
+  }
+
+  DEBUG ("bind plugin: Found %d %s for XPath expression `%s'",
+      num_entries, (num_entries == 1) ? "entry" : "entries",
+      xpath_expression);
+
+  xmlXPathFreeObject(xpathObj);
+
+  return (0);
+} /* }}} int bind_parse_generic_name_attr_value_list */
+
+static int bind_xml_stats_handle_zone (int version, xmlDoc *doc, /* {{{ */
+    xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view,
+    time_t current_time)
+{
+  xmlXPathObject *path_obj;
+  char *zone_name = NULL;
+  int i;
+  size_t j;
+
+  if (version >= 3)
+  {
+    char *n = (char *) xmlGetProp (node, BAD_CAST "name");
+    char *c = (char *) xmlGetProp (node, BAD_CAST "rdataclass");
+    if (n && c)
+    {
+      zone_name = (char *) xmlMalloc(strlen(n) + strlen(c) + 2);
+      snprintf(zone_name, strlen(n) + strlen(c) + 2, "%s/%s", n, c);
+    }
+    xmlFree(n);
+    xmlFree(c);
+  }
+  else
+  {
+    path_obj = xmlXPathEvalExpression (BAD_CAST "name", path_ctx);
+    if (path_obj == NULL)
+    {
+      ERROR ("bind plugin: xmlXPathEvalExpression failed.");
+      return (-1);
+    }
+
+    for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
+    {
+      zone_name = (char *) xmlNodeListGetString (doc,
+          path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1);
+      if (zone_name != NULL)
+        break;
+    }
+    xmlXPathFreeObject (path_obj);
+  }
+
+  if (zone_name == NULL)
+  {
+    ERROR ("bind plugin: Could not determine zone name.");
+    return (-1);
+  }
+
+  for (j = 0; j < view->zones_num; j++)
+  {
+    if (strcasecmp (zone_name, view->zones[j]) == 0)
+      break;
+  }
+
+  xmlFree (zone_name);
+  zone_name = NULL;
+
+  if (j >= views->zones_num)
+    return (0);
+
+  zone_name = view->zones[j];
+
+  DEBUG ("bind plugin: bind_xml_stats_handle_zone: Found zone `%s'.",
+      zone_name);
+
+  { /* Parse the <counters> tag {{{ */
+    char plugin_instance[DATA_MAX_NAME_LEN];
+    translation_table_ptr_t table_ptr =
+    { 
+      nsstats_translation_table,
+      nsstats_translation_table_length,
+      plugin_instance
+    };
+
+    ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-zone-%s",
+        view->name, zone_name);
+
+    if (version == 3)
+    {
+      list_info_ptr_t list_info =
+      {
+        plugin_instance,
+        /* type = */ "dns_qtype"
+      };
+      bind_parse_generic_name_attr_value_list (/* xpath = */ "counters[@type='rcode']",
+        /* callback = */ bind_xml_table_callback,
+        /* user_data = */ &table_ptr,
+        doc, path_ctx, current_time, DS_TYPE_COUNTER);
+      bind_parse_generic_name_attr_value_list (/* xpath = */ "counters[@type='qtype']",
+        /* callback = */ bind_xml_list_callback,
+        /* user_data = */ &list_info,
+        doc, path_ctx, current_time, DS_TYPE_COUNTER);
+    }
+    else
+    {
+      bind_parse_generic_value_list (/* xpath = */ "counters",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, path_ctx, current_time, DS_TYPE_COUNTER);
+    }
+  } /* }}} */
+
+  return (0);
+} /* }}} int bind_xml_stats_handle_zone */
+
+static int bind_xml_stats_search_zones (int version, xmlDoc *doc, /* {{{ */
+    xmlXPathContext *path_ctx, xmlNode *node, cb_view_t *view,
+    time_t current_time)
+{
+  xmlXPathObject *zone_nodes = NULL;
+  xmlXPathContext *zone_path_context;
+  int i;
+
+  zone_path_context = xmlXPathNewContext (doc);
+  if (zone_path_context == NULL)
+  {
+    ERROR ("bind plugin: xmlXPathNewContext failed.");
+    return (-1);
+  }
+
+  zone_nodes = xmlXPathEvalExpression (BAD_CAST "zones/zone", path_ctx);
+  if (zone_nodes == NULL)
+  {
+    ERROR ("bind plugin: Cannot find any <view> tags.");
+    xmlXPathFreeContext (zone_path_context);
+    return (-1);
+  }
+
+  for (i = 0; i < zone_nodes->nodesetval->nodeNr; i++)
+  {
+    xmlNode *node;
+
+    node = zone_nodes->nodesetval->nodeTab[i];
+    assert (node != NULL);
+
+    zone_path_context->node = node;
+
+    bind_xml_stats_handle_zone (version, doc, zone_path_context, node, view,
+        current_time);
+  }
+
+  xmlXPathFreeObject (zone_nodes);
+  xmlXPathFreeContext (zone_path_context);
+  return (0);
+} /* }}} int bind_xml_stats_search_zones */
+
+static int bind_xml_stats_handle_view (int version, xmlDoc *doc, /* {{{ */
+    xmlXPathContext *path_ctx, xmlNode *node, time_t current_time)
+{
+  char *view_name = NULL;
+  cb_view_t *view;
+  int i;
+  size_t j;
+
+  if (version == 3)
+  {
+    view_name = (char*) xmlGetProp(node, BAD_CAST "name");
+
+    if (view_name == NULL)
+    {
+      ERROR ("bind plugin: Could not determine view name.");
+      return (-1);
+    }
+
+    for (j = 0; j < views_num; j++)
+    {
+      if (strcasecmp (view_name, views[j].name) == 0)
+        break;
+    }
+
+    xmlFree (view_name);
+    view_name = NULL;
+  }
+  else
+  {
+    xmlXPathObject *path_obj;
+    path_obj = xmlXPathEvalExpression (BAD_CAST "name", path_ctx);
+    if (path_obj == NULL)
+    {
+      ERROR ("bind plugin: xmlXPathEvalExpression failed.");
+      return (-1);
+    }
+
+    for (i = 0; path_obj->nodesetval && (i < path_obj->nodesetval->nodeNr); i++)
+    {
+      view_name = (char *) xmlNodeListGetString (doc,
+          path_obj->nodesetval->nodeTab[i]->xmlChildrenNode, 1);
+      if (view_name != NULL)
+        break;
+    }
+
+    if (view_name == NULL)
+    {
+      ERROR ("bind plugin: Could not determine view name.");
+      xmlXPathFreeObject (path_obj);
+      return (-1);
+    }
+
+    for (j = 0; j < views_num; j++)
+    {
+      if (strcasecmp (view_name, views[j].name) == 0)
+        break;
+    }
+
+    xmlFree (view_name);
+    xmlXPathFreeObject (path_obj);
+
+    view_name = NULL;
+    path_obj = NULL;
+  }
+
+
+  if (j >= views_num)
+    return (0);
+
+  view = views + j;
+
+  DEBUG ("bind plugin: bind_xml_stats_handle_view: Found view `%s'.",
+      view->name);
+
+  if (view->qtypes != 0) /* {{{ */
+  {
+    char plugin_instance[DATA_MAX_NAME_LEN];
+    list_info_ptr_t list_info =
+    {
+      plugin_instance,
+      /* type = */ "dns_qtype"
+    };
+
+    ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-qtypes",
+        view->name);
+    if (version == 3)
+    {
+      bind_parse_generic_name_attr_value_list (/* xpath = */ "counters[@type='resqtype']",
+        /* callback = */ bind_xml_list_callback,
+        /* user_data = */ &list_info,
+        doc, path_ctx, current_time, DS_TYPE_COUNTER);
+    }
+    else
+    {
+      bind_parse_generic_name_value (/* xpath = */ "rdtype",
+        /* callback = */ bind_xml_list_callback,
+        /* user_data = */ &list_info,
+        doc, path_ctx, current_time, DS_TYPE_COUNTER);
+    }
+  } /* }}} */
+
+  if (view->resolver_stats != 0) /* {{{ */
+  {
+    char plugin_instance[DATA_MAX_NAME_LEN];
+    translation_table_ptr_t table_ptr =
+    { 
+      resstats_translation_table,
+      resstats_translation_table_length,
+      plugin_instance
+    };
+
+    ssnprintf (plugin_instance, sizeof (plugin_instance),
+        "%s-resolver_stats", view->name);
+    if (version == 3)
+    {
+      bind_parse_generic_name_attr_value_list ("counters[@type='resstats']",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, path_ctx, current_time, DS_TYPE_COUNTER);
+    }
+    else
+    {
+      bind_parse_generic_name_value ("resstat",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, path_ctx, current_time, DS_TYPE_COUNTER);
+    }
+  } /* }}} */
+
+  /* Record types in the cache */
+  if (view->cacherrsets != 0) /* {{{ */
+  {
+    char plugin_instance[DATA_MAX_NAME_LEN];
+    list_info_ptr_t list_info =
+    {
+      plugin_instance,
+      /* type = */ "dns_qtype_cached"
+    };
+
+    ssnprintf (plugin_instance, sizeof (plugin_instance), "%s-cache_rr_sets",
+        view->name);
+
+    bind_parse_generic_name_value (/* xpath = */ "cache/rrset",
+        /* callback = */ bind_xml_list_callback,
+        /* user_data = */ &list_info,
+        doc, path_ctx, current_time, DS_TYPE_GAUGE);
+  } /* }}} */
+
+  if (view->zones_num > 0)
+    bind_xml_stats_search_zones (version, doc, path_ctx, node, view,
+        current_time);
+
+  return (0);
+} /* }}} int bind_xml_stats_handle_view */
+
+static int bind_xml_stats_search_views (int version, xmlDoc *doc, /* {{{ */
+    xmlXPathContext *xpathCtx, xmlNode *statsnode, time_t current_time)
+{
+  xmlXPathObject *view_nodes = NULL;
+  xmlXPathContext *view_path_context;
+  int i;
+
+  view_path_context = xmlXPathNewContext (doc);
+  if (view_path_context == NULL)
+  {
+    ERROR ("bind plugin: xmlXPathNewContext failed.");
+    return (-1);
+  }
+
+  view_nodes = xmlXPathEvalExpression (BAD_CAST "views/view", xpathCtx);
+  if (view_nodes == NULL)
+  {
+    ERROR ("bind plugin: Cannot find any <view> tags.");
+    xmlXPathFreeContext (view_path_context);
+    return (-1);
+  }
+
+  for (i = 0; i < view_nodes->nodesetval->nodeNr; i++)
+  {
+    xmlNode *node;
+
+    node = view_nodes->nodesetval->nodeTab[i];
+    assert (node != NULL);
+
+    view_path_context->node = node;
+
+    bind_xml_stats_handle_view (version, doc, view_path_context, node,
+        current_time);
+  }
+
+  xmlXPathFreeObject (view_nodes);
+  xmlXPathFreeContext (view_path_context);
+  return (0);
+} /* }}} int bind_xml_stats_search_views */
+
+static void bind_xml_stats_v3 (xmlDoc *doc, /* {{{ */
+    xmlXPathContext *xpathCtx, xmlNode *statsnode, time_t current_time)
+{
+  /* XPath:     server/counters[@type='opcode']
+   * Variables: QUERY, IQUERY, NOTIFY, UPDATE, ...
+   * Layout v3:
+   *   <counters type="opcode">
+   *     <counter name="A">1</counter>
+   *     :
+   *   </counters>
+   */
+  if (global_opcodes != 0)
+  {
+    list_info_ptr_t list_info =
+    {
+      /* plugin instance = */ "global-opcodes",
+      /* type = */ "dns_opcode"
+    };
+    bind_parse_generic_name_attr_value_list (/* xpath = */ "server/counters[@type='opcode']",
+      /* callback = */ bind_xml_list_callback,
+      /* user_data = */ &list_info,
+      doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+  }
+
+  /* XPath:     server/counters[@type='qtype']
+   * Variables: RESERVED0, A, NS, CNAME, SOA, MR, PTR, HINFO, MX, TXT, RP,
+   *            X25, PX, AAAA, LOC, SRV, NAPTR, A6, DS, RRSIG, NSEC, DNSKEY,
+   *            SPF, TKEY, IXFR, AXFR, ANY, ..., Others
+   * Layout v3:
+   *   <counters type="opcode">
+   *     <counter name="A">1</counter>
+   *     :
+   *   </counters>
+   */
+  if (global_qtypes != 0)
+  {
+    list_info_ptr_t list_info =
+    {
+      /* plugin instance = */ "global-qtypes",
+      /* type = */ "dns_qtype"
+    };
+
+    bind_parse_generic_name_attr_value_list (/* xpath = */ "server/counters[@type='qtype']",
+        /* callback = */ bind_xml_list_callback,
+        /* user_data = */ &list_info,
+        doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+  }
+
+  /* XPath:     server/counters[@type='nsstat']
+   * Variables: Requestv4, Requestv6, ReqEdns0, ReqBadEDNSVer, ReqTSIG,
+   *            ReqSIG0, ReqBadSIG, ReqTCP, AuthQryRej, RecQryRej, XfrRej,
+   *            UpdateRej, Response, TruncatedResp, RespEDNS0, RespTSIG,
+   *            RespSIG0, QrySuccess, QryAuthAns, QryNoauthAns, QryReferral,
+   *            QryNxrrset, QrySERVFAIL, QryFORMERR, QryNXDOMAIN, QryRecursion,
+   *            QryDuplicate, QryDropped, QryFailure, XfrReqDone, UpdateReqFwd,
+   *            UpdateRespFwd, UpdateFwdFail, UpdateDone, UpdateFail,
+   *            UpdateBadPrereq
+   * Layout v3:
+   *   <counters type="nsstat"
+   *     <counter name="Requestv4">1</counter>
+   *     <counter name="Requestv6">0</counter>
+   *     :
+   *   </counter>
+   */
+  if (global_server_stats)
+  {
+    translation_table_ptr_t table_ptr =
+    {
+      nsstats_translation_table,
+      nsstats_translation_table_length,
+      /* plugin_instance = */ "global-server_stats"
+    };
+
+    bind_parse_generic_name_attr_value_list ("server/counters[@type='nsstat']",
+        /* callback = */ bind_xml_table_callback,
+        /* user_data = */ &table_ptr,
+        doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+  }
+
+  /* XPath:     server/zonestats, server/zonestat, server/counters[@type='zonestat']
+   * Variables: NotifyOutv4, NotifyOutv6, NotifyInv4, NotifyInv6, NotifyRej,
+   *            SOAOutv4, SOAOutv6, AXFRReqv4, AXFRReqv6, IXFRReqv4, IXFRReqv6,
+   *            XfrSuccess, XfrFail
+   * Layout v3:
+   *   <counters type="zonestat"
+   *     <counter name="NotifyOutv4">0</counter>
+   *     <counter name="NotifyOutv6">0</counter>
+   *     :
+   *   </counter>
+   */
+  if (global_zone_maint_stats)
+  {
+    translation_table_ptr_t table_ptr =
+    {
+      zonestats_translation_table,
+      zonestats_translation_table_length,
+      /* plugin_instance = */ "global-zone_maint_stats"
+    };
+
+    bind_parse_generic_name_attr_value_list ("server/counters[@type='zonestat']",
+        /* callback = */ bind_xml_table_callback,
+        /* user_data = */ &table_ptr,
+        doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+  }
+
+  /* XPath:     server/resstats, server/counters[@type='resstat']
+   * Variables: Queryv4, Queryv6, Responsev4, Responsev6, NXDOMAIN, SERVFAIL,
+   *            FORMERR, OtherError, EDNS0Fail, Mismatch, Truncated, Lame,
+   *            Retry, GlueFetchv4, GlueFetchv6, GlueFetchv4Fail,
+   *            GlueFetchv6Fail, ValAttempt, ValOk, ValNegOk, ValFail
+   * Layout v3:
+   *   <counters type="resstat"
+   *     <counter name="Queryv4">0</counter>
+   *     <counter name="Queryv6">0</counter>
+   *     :
+   *   </counter>
+   */
+  if (global_resolver_stats != 0)
+  {
+    translation_table_ptr_t table_ptr =
+    {
+      resstats_translation_table,
+      resstats_translation_table_length,
+      /* plugin_instance = */ "global-resolver_stats"
+    };
+
+    bind_parse_generic_name_attr_value_list ("server/counters[@type='resstat']",
+        /* callback = */ bind_xml_table_callback,
+        /* user_data = */ &table_ptr,
+        doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+  }
+} /* }}} bind_xml_stats_v3 */
+
+static void bind_xml_stats_v1_v2 (int version, xmlDoc *doc, /* {{{ */
+    xmlXPathContext *xpathCtx, xmlNode *statsnode, time_t current_time)
+{
+  /* XPath:     server/requests/opcode, server/counters[@type='opcode']
+   * Variables: QUERY, IQUERY, NOTIFY, UPDATE, ...
+   * Layout V1 and V2:
+   *   <opcode>
+   *     <name>A</name>
+   *     <counter>1</counter>
+   *   </opcode>
+   *   :
+   */
+  if (global_opcodes != 0)
+  {
+    list_info_ptr_t list_info =
+    {
+      /* plugin instance = */ "global-opcodes",
+      /* type = */ "dns_opcode"
+    };
+
+    bind_parse_generic_name_value (/* xpath = */ "server/requests/opcode",
+        /* callback = */ bind_xml_list_callback,
+        /* user_data = */ &list_info,
+        doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+  }
+
+  /* XPath:     server/queries-in/rdtype, server/counters[@type='qtype']
+   * Variables: RESERVED0, A, NS, CNAME, SOA, MR, PTR, HINFO, MX, TXT, RP,
+   *            X25, PX, AAAA, LOC, SRV, NAPTR, A6, DS, RRSIG, NSEC, DNSKEY,
+   *            SPF, TKEY, IXFR, AXFR, ANY, ..., Others
+   * Layout v1 or v2:
+   *   <rdtype>
+   *     <name>A</name>
+   *     <counter>1</counter>
+   *   </rdtype>
+   *   :
+   */
+  if (global_qtypes != 0)
+  {
+    list_info_ptr_t list_info =
+    {
+      /* plugin instance = */ "global-qtypes",
+      /* type = */ "dns_qtype"
+    };
+
+    bind_parse_generic_name_value (/* xpath = */ "server/queries-in/rdtype",
+        /* callback = */ bind_xml_list_callback,
+        /* user_data = */ &list_info,
+        doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+  }
+
+  /* XPath:     server/nsstats, server/nsstat, server/counters[@type='nsstat']
+   * Variables: Requestv4, Requestv6, ReqEdns0, ReqBadEDNSVer, ReqTSIG,
+   *            ReqSIG0, ReqBadSIG, ReqTCP, AuthQryRej, RecQryRej, XfrRej,
+   *            UpdateRej, Response, TruncatedResp, RespEDNS0, RespTSIG,
+   *            RespSIG0, QrySuccess, QryAuthAns, QryNoauthAns, QryReferral,
+   *            QryNxrrset, QrySERVFAIL, QryFORMERR, QryNXDOMAIN, QryRecursion,
+   *            QryDuplicate, QryDropped, QryFailure, XfrReqDone, UpdateReqFwd,
+   *            UpdateRespFwd, UpdateFwdFail, UpdateDone, UpdateFail,
+   *            UpdateBadPrereq
+   * Layout v1:
+   *   <nsstats>
+   *     <Requestv4>1</Requestv4>
+   *     <Requestv6>0</Requestv6>
+   *     :
+   *   </nsstats>
+   * Layout v2:
+   *   <nsstat>
+   *     <name>Requestv4</name>
+   *     <counter>1</counter>
+   *   </nsstat>
+   *   <nsstat>
+   *     <name>Requestv6</name>
+   *     <counter>0</counter>
+   *   </nsstat>
+   *   :
+   */
+  if (global_server_stats)
+  {
+    translation_table_ptr_t table_ptr =
+    {
+      nsstats_translation_table,
+      nsstats_translation_table_length,
+      /* plugin_instance = */ "global-server_stats"
+    };
+
+    if (version == 1)
+    {
+      bind_parse_generic_value_list ("server/nsstats",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+    }
+    else
+    {
+      bind_parse_generic_name_value ("server/nsstat",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+    }
+  }
+
+  /* XPath:     server/zonestats, server/zonestat, server/counters[@type='zonestat']
+   * Variables: NotifyOutv4, NotifyOutv6, NotifyInv4, NotifyInv6, NotifyRej,
+   *            SOAOutv4, SOAOutv6, AXFRReqv4, AXFRReqv6, IXFRReqv4, IXFRReqv6,
+   *            XfrSuccess, XfrFail
+   * Layout v1:
+   *   <zonestats>
+   *     <NotifyOutv4>0</NotifyOutv4>
+   *     <NotifyOutv6>0</NotifyOutv6>
+   *     :
+   *   </zonestats>
+   * Layout v2:
+   *   <zonestat>
+   *     <name>NotifyOutv4</name>
+   *     <counter>0</counter>
+   *   </zonestat>
+   *   <zonestat>
+   *     <name>NotifyOutv6</name>
+   *     <counter>0</counter>
+   *   </zonestat>
+   *   :
+   */
+  if (global_zone_maint_stats)
+  {
+    translation_table_ptr_t table_ptr =
+    {
+      zonestats_translation_table,
+      zonestats_translation_table_length,
+      /* plugin_instance = */ "global-zone_maint_stats"
+    };
+
+    if (version == 1)
+    {
+      bind_parse_generic_value_list ("server/zonestats",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+    }
+    else
+    {
+      bind_parse_generic_name_value ("server/zonestat",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+    }
+  }
+
+  /* XPath:     server/resstats, server/counters[@type='resstat']
+   * Variables: Queryv4, Queryv6, Responsev4, Responsev6, NXDOMAIN, SERVFAIL,
+   *            FORMERR, OtherError, EDNS0Fail, Mismatch, Truncated, Lame,
+   *            Retry, GlueFetchv4, GlueFetchv6, GlueFetchv4Fail,
+   *            GlueFetchv6Fail, ValAttempt, ValOk, ValNegOk, ValFail
+   * Layout v1:
+   *   <resstats>
+   *     <Queryv4>0</Queryv4>
+   *     <Queryv6>0</Queryv6>
+   *     :
+   *   </resstats>
+   * Layout v2:
+   *   <resstat>
+   *     <name>Queryv4</name>
+   *     <counter>0</counter>
+   *   </resstat>
+   *   <resstat>
+   *     <name>Queryv6</name>
+   *     <counter>0</counter>
+   *   </resstat>
+   *   :
+   */
+  if (global_resolver_stats != 0)
+  {
+    translation_table_ptr_t table_ptr =
+    {
+      resstats_translation_table,
+      resstats_translation_table_length,
+      /* plugin_instance = */ "global-resolver_stats"
+    };
+
+    if (version == 1)
+    {
+      bind_parse_generic_value_list ("server/resstats",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+    }
+    else
+    {
+      bind_parse_generic_name_value ("server/resstat",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, xpathCtx, current_time, DS_TYPE_COUNTER);
+    }
+  }
+} /* }}} bind_xml_stats_v1_v2 */
+
+static int bind_xml_stats (int version, xmlDoc *doc, /* {{{ */
+    xmlXPathContext *xpathCtx, xmlNode *statsnode)
+{
+  time_t current_time = 0;
+  int status;
+
+  xpathCtx->node = statsnode;
+
+  /* TODO: Check `server/boot-time' to recognize server restarts. */
+
+  status = bind_xml_read_timestamp ("server/current-time",
+      doc, xpathCtx, &current_time);
+  if (status != 0)
+  {
+    ERROR ("bind plugin: Reading `server/current-time' failed.");
+    return (-1);
+  }
+  DEBUG ("bind plugin: Current server time is %i.", (int) current_time);
+
+  if (version == 3)
+  {
+    bind_xml_stats_v3(doc, xpathCtx, statsnode, current_time);
+  }
+  else
+  {
+    bind_xml_stats_v1_v2(version, doc, xpathCtx, statsnode, current_time);
+  }
+
+  /* XPath:  memory/summary
+   * Variables: TotalUse, InUse, BlockSize, ContextSize, Lost
+   * Layout: v2 and v3:
+   *   <summary>
+   *     <TotalUse>6587096</TotalUse>
+   *     <InUse>1345424</InUse>
+   *     <BlockSize>5505024</BlockSize>
+   *     <ContextSize>3732456</ContextSize>
+   *     <Lost>0</Lost>
+   *   </summary>
+   */
+  if (global_memory_stats != 0)
+  {
+    translation_table_ptr_t table_ptr =
+    {
+      memsummary_translation_table,
+      memsummary_translation_table_length,
+      /* plugin_instance = */ "global-memory_stats"
+    };
+
+    bind_parse_generic_value_list ("memory/summary",
+          /* callback = */ bind_xml_table_callback,
+          /* user_data = */ &table_ptr,
+          doc, xpathCtx, current_time, DS_TYPE_GAUGE);
+  }
+
+  if (views_num > 0)
+    bind_xml_stats_search_views (version, doc, xpathCtx, statsnode,
+        current_time);
+
+  return 0;
+} /* }}} int bind_xml_stats */
+
+static int bind_xml (const char *data) /* {{{ */
+{
+  xmlDoc *doc = NULL;
+  xmlXPathContext *xpathCtx = NULL;
+  xmlXPathObject *xpathObj = NULL;
+  int ret = -1;
+  int i;
+
+  doc = xmlParseMemory (data, strlen (data));
+  if (doc == NULL)
+  {
+    ERROR ("bind plugin: xmlParseMemory failed.");
+    return (-1);
+  }
+
+  xpathCtx = xmlXPathNewContext (doc);
+  if (xpathCtx == NULL)
+  {
+    ERROR ("bind plugin: xmlXPathNewContext failed.");
+    xmlFreeDoc (doc);
+    return (-1);
+  }
+
+  //
+  // version 3.* of statistics XML (since BIND9.9)
+  //
+
+  xpathObj = xmlXPathEvalExpression (BAD_CAST "/statistics", xpathCtx);
+  if (xpathObj == NULL || xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr == 0)
+  {
+    DEBUG ("bind plugin: Statistics appears not to be v3");
+    // we will fallback to v1 or v2 detection
+    if (xpathObj != NULL) { xmlXPathFreeObject (xpathObj); }
+  }
+  else
+  {
+    for (i = 0; i < xpathObj->nodesetval->nodeNr; i++)
+    {
+      xmlNode *node;
+      char *attr_version;
+
+      node = xpathObj->nodesetval->nodeTab[i];
+      assert (node != NULL);
+
+      attr_version = (char *) xmlGetProp (node, BAD_CAST "version");
+      if (attr_version == NULL)
+      {
+        NOTICE ("bind plugin: Found <statistics> tag doesn't have a "
+            "`version' attribute.");
+        continue;
+      }
+      DEBUG ("bind plugin: Found: <statistics version=\"%s\">", attr_version);
+
+      if (strncmp ("3.", attr_version, strlen ("3.")) != 0)
+      {
+        /* TODO: Use the complaint mechanism here. */
+        NOTICE ("bind plugin: Found <statistics> tag with version `%s'. "
+            "Unfortunately I have no clue how to parse that. "
+            "Please open a bug report for this.", attr_version);
+        xmlFree (attr_version);
+        continue;
+      }
+      ret = bind_xml_stats (3, doc, xpathCtx, node);
+
+      xmlFree (attr_version);
+      /* One <statistics> node ought to be enough. */
+      break;
+    }
+
+    // we are finished, early-return
+    xmlXPathFreeObject (xpathObj);
+    xmlXPathFreeContext (xpathCtx);
+    xmlFreeDoc (doc);
+
+    return (ret);
+  }
+
+  //
+  // versions 1.* or 2.* of statistics XML
+  //
+
+  xpathObj = xmlXPathEvalExpression (BAD_CAST "/isc/bind/statistics", xpathCtx);
+  if (xpathObj == NULL)
+  {
+    ERROR ("bind plugin: Cannot find the <statistics> tag.");
+    xmlXPathFreeContext (xpathCtx);
+    xmlFreeDoc (doc);
+    return (-1);
+  }
+  else if (xpathObj->nodesetval == NULL)
+  {
+    ERROR ("bind plugin: xmlXPathEvalExpression failed.");
+    xmlXPathFreeObject (xpathObj);
+    xmlXPathFreeContext (xpathCtx);
+    xmlFreeDoc (doc);
+    return (-1);
+  }
+
+  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++)
+  {
+    xmlNode *node;
+    char *attr_version;
+    int parsed_version = 0;
+
+    node = xpathObj->nodesetval->nodeTab[i];
+    assert (node != NULL);
+
+    attr_version = (char *) xmlGetProp (node, BAD_CAST "version");
+    if (attr_version == NULL)
+    {
+      NOTICE ("bind plugin: Found <statistics> tag doesn't have a "
+          "`version' attribute.");
+      continue;
+    }
+    DEBUG ("bind plugin: Found: <statistics version=\"%s\">", attr_version);
+
+    /* At the time this plugin was written, version "1.0" was used by
+     * BIND 9.5.0, version "2.0" was used by BIND 9.5.1 and 9.6.0. We assume
+     * that "1.*" and "2.*" don't introduce structural changes, so we just
+     * check for the first two characters here. */
+    if (strncmp ("1.", attr_version, strlen ("1.")) == 0)
+      parsed_version = 1;
+    else if (strncmp ("2.", attr_version, strlen ("2.")) == 0)
+      parsed_version = 2;
+    else
+    {
+      /* TODO: Use the complaint mechanism here. */
+      NOTICE ("bind plugin: Found <statistics> tag with version `%s'. "
+          "Unfortunately I have no clue how to parse that. "
+          "Please open a bug report for this.", attr_version);
+      xmlFree (attr_version);
+      continue;
+    }
+
+    ret = bind_xml_stats (parsed_version,
+        doc, xpathCtx, node);
+
+    xmlFree (attr_version);
+    /* One <statistics> node ought to be enough. */
+    break;
+  }
+
+  xmlXPathFreeObject (xpathObj);
+  xmlXPathFreeContext (xpathCtx);
+  xmlFreeDoc (doc);
+
+  return (ret);
+} /* }}} int bind_xml */
+
+static int bind_config_set_bool (const char *name, int *var, /* {{{ */
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || ( ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+  {
+    WARNING ("bind plugin: The `%s' option needs "
+        "exactly one boolean argument.", name);
+    return (-1);
+  }
+
+  if (ci->values[0].value.boolean)
+    *var = 1;
+  else
+    *var = 0;
+  return 0;
+} /* }}} int bind_config_set_bool */
+
+static int bind_config_add_view_zone (cb_view_t *view, /* {{{ */
+    oconfig_item_t *ci)
+{
+  char **tmp;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("bind plugin: The `Zone' option needs "
+        "exactly one string argument.");
+    return (-1);
+  }
+
+  tmp = (char **) realloc (view->zones,
+      sizeof (char *) * (view->zones_num + 1));
+  if (tmp == NULL)
+  {
+    ERROR ("bind plugin: realloc failed.");
+    return (-1);
+  }
+  view->zones = tmp;
+
+  view->zones[view->zones_num] = strdup (ci->values[0].value.string);
+  if (view->zones[view->zones_num] == NULL)
+  {
+    ERROR ("bind plugin: strdup failed.");
+    return (-1);
+  }
+  view->zones_num++;
+
+  return (0);
+} /* }}} int bind_config_add_view_zone */
+
+static int bind_config_add_view (oconfig_item_t *ci) /* {{{ */
+{
+  cb_view_t *tmp;
+  int i;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("bind plugin: `View' blocks need exactly one string argument.");
+    return (-1);
+  }
+
+  tmp = (cb_view_t *) realloc (views, sizeof (*views) * (views_num + 1));
+  if (tmp == NULL)
+  {
+    ERROR ("bind plugin: realloc failed.");
+    return (-1);
+  }
+  views = tmp;
+  tmp = views + views_num;
+
+  memset (tmp, 0, sizeof (*tmp));
+  tmp->qtypes = 1;
+  tmp->resolver_stats = 1;
+  tmp->cacherrsets = 1;
+  tmp->zones = NULL;
+  tmp->zones_num = 0;
+
+  tmp->name = strdup (ci->values[0].value.string);
+  if (tmp->name == NULL)
+  {
+    ERROR ("bind plugin: strdup failed.");
+    free (tmp);
+    return (-1);
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("QTypes", child->key) == 0)
+      bind_config_set_bool ("QTypes", &tmp->qtypes, child);
+    else if (strcasecmp ("ResolverStats", child->key) == 0)
+      bind_config_set_bool ("ResolverStats", &tmp->resolver_stats, child);
+    else if (strcasecmp ("CacheRRSets", child->key) == 0)
+      bind_config_set_bool ("CacheRRSets", &tmp->cacherrsets, child);
+    else if (strcasecmp ("Zone", child->key) == 0)
+      bind_config_add_view_zone (tmp, child);
+    else
+    {
+      WARNING ("bind plugin: Unknown configuration option "
+          "`%s' in view `%s' will be ignored.", child->key, tmp->name);
+    }
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  views_num++;
+  return (0);
+} /* }}} int bind_config_add_view */
+
+static int bind_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Url", child->key) == 0) {
+      if ((child->values_num != 1) || (child->values[0].type != OCONFIG_TYPE_STRING))
+      {
+        WARNING ("bind plugin: The `Url' option needs "
+                 "exactly one string argument.");
+        return (-1);
+      }
+
+      url = strdup (child->values[0].value.string);
+    } else if (strcasecmp ("OpCodes", child->key) == 0)
+      bind_config_set_bool ("OpCodes", &global_opcodes, child);
+    else if (strcasecmp ("QTypes", child->key) == 0)
+      bind_config_set_bool ("QTypes", &global_qtypes, child);
+    else if (strcasecmp ("ServerStats", child->key) == 0)
+      bind_config_set_bool ("ServerStats", &global_server_stats, child);
+    else if (strcasecmp ("ZoneMaintStats", child->key) == 0)
+      bind_config_set_bool ("ZoneMaintStats", &global_zone_maint_stats, child);
+    else if (strcasecmp ("ResolverStats", child->key) == 0)
+      bind_config_set_bool ("ResolverStats", &global_resolver_stats, child);
+    else if (strcasecmp ("MemoryStats", child->key) == 0)
+      bind_config_set_bool ("MemoryStats", &global_memory_stats, child);
+    else if (strcasecmp ("View", child->key) == 0)
+      bind_config_add_view (child);
+    else if (strcasecmp ("ParseTime", child->key) == 0)
+      cf_util_get_boolean (child, &config_parse_time);
+    else if (strcasecmp ("Timeout", child->key) == 0)
+      cf_util_get_int (child, &timeout);
+    else
+    {
+      WARNING ("bind plugin: Unknown configuration option "
+          "`%s' will be ignored.", child->key);
+    }
+  }
+
+  return (0);
+} /* }}} int bind_config */
+
+static int bind_init (void) /* {{{ */
+{
+  if (curl != NULL)
+    return (0);
+
+  curl = curl_easy_init ();
+  if (curl == NULL)
+  {
+    ERROR ("bind plugin: bind_init: curl_easy_init failed.");
+    return (-1);
+  }
+
+  curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L);
+  curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, bind_curl_callback);
+  curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+  curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error);
+  curl_easy_setopt (curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL);
+  curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
+  curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+  curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (timeout >= 0) ?
+      (long) timeout : CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
+
+  return (0);
+} /* }}} int bind_init */
+
+static int bind_read (void) /* {{{ */
+{
+  int status;
+
+  if (curl == NULL)
+  {
+    ERROR ("bind plugin: I don't have a CURL object.");
+    return (-1);
+  }
+
+  bind_buffer_fill = 0;
+  if (curl_easy_perform (curl) != CURLE_OK)
+  {
+    ERROR ("bind plugin: curl_easy_perform failed: %s",
+        bind_curl_error);
+    return (-1);
+  }
+
+  status = bind_xml (bind_buffer);
+  if (status != 0)
+    return (-1);
+  else
+    return (0);
+} /* }}} int bind_read */
+
+static int bind_shutdown (void) /* {{{ */
+{
+  if (curl != NULL)
+  {
+    curl_easy_cleanup (curl);
+    curl = NULL;
+  }
+
+  return (0);
+} /* }}} int bind_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("bind", bind_config);
+  plugin_register_init ("bind", bind_init);
+  plugin_register_read ("bind", bind_read);
+  plugin_register_shutdown ("bind", bind_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 ts=8 et fdm=marker : */
diff --git a/src/ceph.c b/src/ceph.c
new file mode 100644 (file)
index 0000000..56e349c
--- /dev/null
@@ -0,0 +1,1580 @@
+/**
+ * collectd - src/ceph.c
+ * Copyright (C) 2011  New Dream Network
+ *
+ * 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:
+ *   Colin McCabe <cmccabe@alumni.cmu.edu>
+ *   Dennis Zou <yunzou@cisco.com>
+ *   Dan Ryder <daryder@cisco.com>
+ **/
+
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <yajl/yajl_parse.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+#include <yajl/yajl_version.h>
+#endif
+
+#include <limits.h>
+#include <poll.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <math.h>
+#include <inttypes.h>
+
+#define RETRY_AVGCOUNT -1
+
+#if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+# define HAVE_YAJL_V2 1
+#endif
+
+#define RETRY_ON_EINTR(ret, expr) \
+    while(1) { \
+        ret = expr; \
+        if(ret >= 0) \
+            break; \
+        ret = -errno; \
+        if(ret != -EINTR) \
+            break; \
+    }
+
+/** Timeout interval in seconds */
+#define CEPH_TIMEOUT_INTERVAL 1
+
+/** Maximum path length for a UNIX domain socket on this system */
+#define UNIX_DOMAIN_SOCK_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path))
+
+/** Yajl callback returns */
+#define CEPH_CB_CONTINUE 1
+#define CEPH_CB_ABORT 0
+
+#if HAVE_YAJL_V2
+typedef size_t yajl_len_t;
+#else
+typedef unsigned int yajl_len_t;
+#endif
+
+/** Number of types for ceph defined in types.db */
+#define CEPH_DSET_TYPES_NUM 3
+/** ceph types enum */
+enum ceph_dset_type_d
+{
+    DSET_LATENCY = 0,
+    DSET_BYTES = 1,
+    DSET_RATE = 2,
+    DSET_TYPE_UNFOUND = 1000
+};
+
+/** Valid types for ceph defined in types.db */
+const char * ceph_dset_types [CEPH_DSET_TYPES_NUM] =
+                                   {"ceph_latency", "ceph_bytes", "ceph_rate"};
+
+/******* ceph_daemon *******/
+struct ceph_daemon
+{
+    /** Version of the admin_socket interface */
+    uint32_t version;
+    /** daemon name **/
+    char name[DATA_MAX_NAME_LEN];
+
+    /** Path to the socket that we use to talk to the ceph daemon */
+    char asok_path[UNIX_DOMAIN_SOCK_PATH_MAX];
+
+    /** Number of counters */
+    int ds_num;
+    /** Track ds types */
+    uint32_t *ds_types;
+    /** Track ds names to match with types */
+    char **ds_names;
+
+    /**
+     * Keep track of last data for latency values so we can calculate rate
+     * since last poll.
+     */
+    struct last_data **last_poll_data;
+    /** index of last poll data */
+    int last_idx;
+};
+
+/******* JSON parsing *******/
+typedef int (*node_handler_t)(void *, const char*, const char*);
+
+/** Track state and handler while parsing JSON */
+struct yajl_struct
+{
+    node_handler_t handler;
+    void * handler_arg;
+    struct {
+      char key[DATA_MAX_NAME_LEN];
+      int key_len;
+    } state[YAJL_MAX_DEPTH];
+    int depth;
+};
+typedef struct yajl_struct yajl_struct;
+
+enum perfcounter_type_d
+{
+    PERFCOUNTER_LATENCY = 0x4, PERFCOUNTER_DERIVE = 0x8,
+};
+
+/** Give user option to use default (long run = since daemon started) avg */
+static int long_run_latency_avg = 0;
+
+/**
+ * Give user option to use default type for special cases -
+ * filestore.journal_wr_bytes is currently only metric here. Ceph reports the
+ * type as a sum/count pair and will calculate it the same as a latency value.
+ * All other "bytes" metrics (excluding the used/capacity bytes for the OSD)
+ * use the DERIVE type. Unless user specifies to use given type, convert this
+ * metric to use DERIVE.
+ */
+static int convert_special_metrics = 1;
+
+/** Array of daemons to monitor */
+static struct ceph_daemon **g_daemons = NULL;
+
+/** Number of elements in g_daemons */
+static int g_num_daemons = 0;
+
+/**
+ * A set of data that we build up in memory while parsing the JSON.
+ */
+struct values_tmp
+{
+    /** ceph daemon we are processing data for*/
+    struct ceph_daemon *d;
+    /** track avgcount across counters for avgcount/sum latency pairs */
+    uint64_t avgcount;
+    /** current index of counters - used to get type of counter */
+    int index;
+    /** do we already have an avgcount for latency pair */
+    int avgcount_exists;
+    /**
+     * similar to index, but current index of latency type counters -
+     * used to get last poll data of counter
+     */
+    int latency_index;
+    /**
+     * values list - maintain across counters since
+     * host/plugin/plugin instance are always the same
+     */
+    value_list_t vlist;
+};
+
+/**
+ * A set of count/sum pairs to keep track of latency types and get difference
+ * between this poll data and last poll data.
+ */
+struct last_data
+{
+    char ds_name[DATA_MAX_NAME_LEN];
+    double last_sum;
+    uint64_t last_count;
+};
+
+/******* network I/O *******/
+enum cstate_t
+{
+    CSTATE_UNCONNECTED = 0,
+    CSTATE_WRITE_REQUEST,
+    CSTATE_READ_VERSION,
+    CSTATE_READ_AMT,
+    CSTATE_READ_JSON,
+};
+
+enum request_type_t
+{
+    ASOK_REQ_VERSION = 0,
+    ASOK_REQ_DATA = 1,
+    ASOK_REQ_SCHEMA = 2,
+    ASOK_REQ_NONE = 1000,
+};
+
+struct cconn
+{
+    /** The Ceph daemon that we're talking to */
+    struct ceph_daemon *d;
+
+    /** Request type */
+    uint32_t request_type;
+
+    /** The connection state */
+    enum cstate_t state;
+
+    /** The socket we use to talk to this daemon */
+    int asok;
+
+    /** The amount of data remaining to read / write. */
+    uint32_t amt;
+
+    /** Length of the JSON to read */
+    uint32_t json_len;
+
+    /** Buffer containing JSON data */
+    unsigned char *json;
+
+    /** Keep data important to yajl processing */
+    struct yajl_struct yajl;
+};
+
+static int ceph_cb_null(void *ctx)
+{
+    return CEPH_CB_CONTINUE;
+}
+
+static int ceph_cb_boolean(void *ctx, int bool_val)
+{
+    return CEPH_CB_CONTINUE;
+}
+
+static int
+ceph_cb_number(void *ctx, const char *number_val, yajl_len_t number_len)
+{
+    yajl_struct *yajl = (yajl_struct*)ctx;
+    char buffer[number_len+1];
+    int i, latency_type = 0, result;
+    char key[128];
+
+    memcpy(buffer, number_val, number_len);
+    buffer[sizeof(buffer) - 1] = 0;
+
+    ssnprintf(key, yajl->state[0].key_len, "%s", yajl->state[0].key);
+    for(i = 1; i < yajl->depth; i++)
+    {
+        if((i == yajl->depth-1) && ((strcmp(yajl->state[i].key,"avgcount") == 0)
+                || (strcmp(yajl->state[i].key,"sum") == 0)))
+        {
+            if(convert_special_metrics)
+            {
+                /**
+                 * Special case for filestore:JournalWrBytes. For some reason,
+                 * Ceph schema encodes this as a count/sum pair while all
+                 * other "Bytes" data (excluding used/capacity bytes for OSD
+                 * space) uses a single "Derive" type. To spare further
+                 * confusion, keep this KPI as the same type of other "Bytes".
+                 * Instead of keeping an "average" or "rate", use the "sum" in
+                 * the pair and assign that to the derive value.
+                 */
+                if((strcmp(yajl->state[i-1].key, "journal_wr_bytes") == 0) &&
+                        (strcmp(yajl->state[i-2].key,"filestore") == 0) &&
+                        (strcmp(yajl->state[i].key,"avgcount") == 0))
+                {
+                    DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes");
+                    yajl->depth = (yajl->depth - 1);
+                    return CEPH_CB_CONTINUE;
+                }
+            }
+            //probably a avgcount/sum pair. if not - we'll try full key later
+            latency_type = 1;
+            break;
+        }
+        strncat(key, ".", 1);
+        strncat(key, yajl->state[i].key, yajl->state[i].key_len+1);
+    }
+
+    result = yajl->handler(yajl->handler_arg, buffer, key);
+
+    if((result == RETRY_AVGCOUNT) && latency_type)
+    {
+        strncat(key, ".", 1);
+        strncat(key, yajl->state[yajl->depth-1].key,
+                yajl->state[yajl->depth-1].key_len+1);
+        result = yajl->handler(yajl->handler_arg, buffer, key);
+    }
+
+    if(result == -ENOMEM)
+    {
+        ERROR("ceph plugin: memory allocation failed");
+        return CEPH_CB_ABORT;
+    }
+
+    yajl->depth = (yajl->depth - 1);
+    return CEPH_CB_CONTINUE;
+}
+
+static int ceph_cb_string(void *ctx, const unsigned char *string_val,
+        yajl_len_t string_len)
+{
+    return CEPH_CB_CONTINUE;
+}
+
+static int ceph_cb_start_map(void *ctx)
+{
+    return CEPH_CB_CONTINUE;
+}
+
+static int
+ceph_cb_map_key(void *ctx, const unsigned char *key, yajl_len_t string_len)
+{
+    yajl_struct *yajl = (yajl_struct*)ctx;
+
+    if((yajl->depth+1)  >= YAJL_MAX_DEPTH)
+    {
+        ERROR("ceph plugin: depth exceeds max, aborting.");
+        return CEPH_CB_ABORT;
+    }
+
+    char buffer[string_len+1];
+
+    memcpy(buffer, key, string_len);
+    buffer[sizeof(buffer) - 1] = 0;
+
+    snprintf(yajl->state[yajl->depth].key, sizeof(buffer), "%s", buffer);
+    yajl->state[yajl->depth].key_len = sizeof(buffer);
+    yajl->depth = (yajl->depth + 1);
+
+    return CEPH_CB_CONTINUE;
+}
+
+static int ceph_cb_end_map(void *ctx)
+{
+    yajl_struct *yajl = (yajl_struct*)ctx;
+
+    yajl->depth = (yajl->depth - 1);
+    return CEPH_CB_CONTINUE;
+}
+
+static int ceph_cb_start_array(void *ctx)
+{
+    return CEPH_CB_CONTINUE;
+}
+
+static int ceph_cb_end_array(void *ctx)
+{
+    return CEPH_CB_CONTINUE;
+}
+
+static yajl_callbacks callbacks = {
+        ceph_cb_null,
+        ceph_cb_boolean,
+        NULL,
+        NULL,
+        ceph_cb_number,
+        ceph_cb_string,
+        ceph_cb_start_map,
+        ceph_cb_map_key,
+        ceph_cb_end_map,
+        ceph_cb_start_array,
+        ceph_cb_end_array
+};
+
+static void ceph_daemon_print(const struct ceph_daemon *d)
+{
+    DEBUG("ceph plugin: name=%s, asok_path=%s", d->name, d->asok_path);
+}
+
+static void ceph_daemons_print(void)
+{
+    int i;
+    for(i = 0; i < g_num_daemons; ++i)
+    {
+        ceph_daemon_print(g_daemons[i]);
+    }
+}
+
+static void ceph_daemon_free(struct ceph_daemon *d)
+{
+    int i = 0;
+    for(; i < d->last_idx; i++)
+    {
+        sfree(d->last_poll_data[i]);
+    }
+    sfree(d->last_poll_data);
+    d->last_poll_data = NULL;
+    d->last_idx = 0;
+    for(i = 0; i < d->ds_num; i++)
+    {
+        sfree(d->ds_names[i]);
+    }
+    sfree(d->ds_types);
+    sfree(d->ds_names);
+    sfree(d);
+}
+
+/**
+ * Compact ds name by removing special characters and trimming length to
+ * DATA_MAX_NAME_LEN if necessary
+ */
+static void compact_ds_name(char *source, char *dest)
+{
+    int keys_num = 0, i;
+    char *save_ptr = NULL, *tmp_ptr = source;
+    char *keys[16];
+    char len_str[3];
+    char tmp[DATA_MAX_NAME_LEN];
+    size_t key_chars_remaining = (DATA_MAX_NAME_LEN-1);
+    int reserved = 0;
+    int offset = 0;
+    memset(tmp, 0, sizeof(tmp));
+    if(source == NULL || dest == NULL || source[0] == '\0' || dest[0] != '\0')
+    {
+        return;
+    }
+    size_t src_len = strlen(source);
+    snprintf(len_str, sizeof(len_str), "%zu", src_len);
+    unsigned char append_status = 0x0;
+    append_status |= (source[src_len - 1] == '-') ? 0x1 : 0x0;
+    append_status |= (source[src_len - 1] == '+') ? 0x2 : 0x0;
+    while ((keys[keys_num] = strtok_r(tmp_ptr, ":_-+", &save_ptr)) != NULL)
+    {
+        tmp_ptr = NULL;
+        /** capitalize 1st char **/
+        keys[keys_num][0] = toupper(keys[keys_num][0]);
+        keys_num++;
+        if(keys_num >= 16)
+        {
+            break;
+        }
+    }
+    /** concatenate each part of source string **/
+    for(i = 0; i < keys_num; i++)
+    {
+        strncat(tmp, keys[i], key_chars_remaining);
+        key_chars_remaining -= strlen(keys[i]);
+    }
+    tmp[DATA_MAX_NAME_LEN - 1] = '\0';
+    /** to coordinate limitation of length of type_instance
+     *  we will truncate ds_name
+     *  when the its length is more than
+     *  DATA_MAX_NAME_LEN
+     */
+    if(strlen(tmp) > DATA_MAX_NAME_LEN - 1)
+    {
+        append_status |= 0x4;
+        /** we should reserve space for
+         * len_str
+         */
+        reserved += 2;
+    }
+    if(append_status & 0x1)
+    {
+        /** we should reserve space for
+         * "Minus"
+         */
+        reserved += 5;
+    }
+    if(append_status & 0x2)
+    {
+        /** we should reserve space for
+         * "Plus"
+         */
+        reserved += 4;
+    }
+    snprintf(dest, DATA_MAX_NAME_LEN - reserved, "%s", tmp);
+    offset = strlen(dest);
+    switch (append_status)
+    {
+        case 0x1:
+            memcpy(dest + offset, "Minus", 5);
+            break;
+        case 0x2:
+            memcpy(dest + offset, "Plus", 5);
+            break;
+        case 0x4:
+            memcpy(dest + offset, len_str, 2);
+            break;
+        case 0x5:
+            memcpy(dest + offset, "Minus", 5);
+            memcpy(dest + offset + 5, len_str, 2);
+            break;
+        case 0x6:
+            memcpy(dest + offset, "Plus", 4);
+            memcpy(dest + offset + 4, len_str, 2);
+            break;
+        default:
+            break;
+    }
+}
+
+/**
+ * Parse key to remove "type" if this is for schema and initiate compaction
+ */
+static int parse_keys(const char *key_str, char *ds_name)
+{
+    char *ptr, *rptr;
+    size_t ds_name_len = 0;
+    /**
+     * allow up to 100 characters before compaction - compact_ds_name will not
+     * allow more than DATA_MAX_NAME_LEN chars
+     */
+    int max_str_len = 100;
+    char tmp_ds_name[max_str_len];
+    memset(tmp_ds_name, 0, sizeof(tmp_ds_name));
+    if(ds_name == NULL || key_str == NULL ||  key_str[0] == '\0' ||
+                                                            ds_name[0] != '\0')
+    {
+        return -1;
+    }
+    if((ptr = strchr(key_str, '.')) == NULL
+            || (rptr = strrchr(key_str, '.')) == NULL)
+    {
+        memcpy(tmp_ds_name, key_str, max_str_len - 1);
+        goto compact;
+    }
+
+    ds_name_len = (rptr - ptr) > max_str_len ? max_str_len : (rptr - ptr);
+    if((ds_name_len == 0) || strncmp(rptr + 1, "type", 4))
+    { /** copy whole key **/
+        memcpy(tmp_ds_name, key_str, max_str_len - 1);
+    }
+    else
+    {/** more than two keys **/
+        memcpy(tmp_ds_name, key_str, ((rptr - key_str) > (max_str_len - 1) ?
+                (max_str_len - 1) : (rptr - key_str)));
+    }
+
+    compact: compact_ds_name(tmp_ds_name, ds_name);
+    return 0;
+}
+
+/**
+ * while parsing ceph admin socket schema, save counter name and type for later
+ * data processing
+ */
+static int ceph_daemon_add_ds_entry(struct ceph_daemon *d, const char *name,
+        int pc_type)
+{
+    uint32_t type;
+    char ds_name[DATA_MAX_NAME_LEN];
+    memset(ds_name, 0, sizeof(ds_name));
+
+    if(convert_special_metrics)
+    {
+        /**
+         * Special case for filestore:JournalWrBytes. For some reason, Ceph
+         * schema encodes this as a count/sum pair while all other "Bytes" data
+         * (excluding used/capacity bytes for OSD space) uses a single "Derive"
+         * type. To spare further confusion, keep this KPI as the same type of
+         * other "Bytes". Instead of keeping an "average" or "rate", use the
+         * "sum" in the pair and assign that to the derive value.
+         */
+        if((strcmp(name,"filestore.journal_wr_bytes.type") == 0))
+        {
+            pc_type = 10;
+        }
+    }
+
+    d->ds_names = realloc(d->ds_names, sizeof(char *) * (d->ds_num + 1));
+    if(!d->ds_names)
+    {
+        return -ENOMEM;
+    }
+
+    d->ds_types = realloc(d->ds_types, sizeof(uint32_t) * (d->ds_num + 1));
+    if(!d->ds_types)
+    {
+        return -ENOMEM;
+    }
+
+    d->ds_names[d->ds_num] = malloc(sizeof(char) * DATA_MAX_NAME_LEN);
+    if(!d->ds_names[d->ds_num])
+    {
+        return -ENOMEM;
+    }
+
+    type = (pc_type & PERFCOUNTER_DERIVE) ? DSET_RATE :
+            ((pc_type & PERFCOUNTER_LATENCY) ? DSET_LATENCY : DSET_BYTES);
+    d->ds_types[d->ds_num] = type;
+
+    if(parse_keys(name, ds_name))
+    {
+        return 1;
+    }
+
+    sstrncpy(d->ds_names[d->ds_num], ds_name, DATA_MAX_NAME_LEN -1);
+    d->ds_num = (d->ds_num + 1);
+
+    return 0;
+}
+
+/******* ceph_config *******/
+static int cc_handle_str(struct oconfig_item_s *item, char *dest, int dest_len)
+{
+    const char *val;
+    if(item->values_num != 1)
+    {
+        return -ENOTSUP;
+    }
+    if(item->values[0].type != OCONFIG_TYPE_STRING)
+    {
+        return -ENOTSUP;
+    }
+    val = item->values[0].value.string;
+    if(snprintf(dest, dest_len, "%s", val) > (dest_len - 1))
+    {
+        ERROR("ceph plugin: configuration parameter '%s' is too long.\n",
+                item->key);
+        return -ENAMETOOLONG;
+    }
+    return 0;
+}
+
+static int cc_handle_bool(struct oconfig_item_s *item, int *dest)
+{
+    if(item->values_num != 1)
+    {
+        return -ENOTSUP;
+    }
+
+    if(item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+    {
+        return -ENOTSUP;
+    }
+
+    *dest = (item->values[0].value.boolean) ? 1 : 0;
+    return 0;
+}
+
+static int cc_add_daemon_config(oconfig_item_t *ci)
+{
+    int ret, i;
+    struct ceph_daemon *array, *nd, cd;
+    memset(&cd, 0, sizeof(struct ceph_daemon));
+
+    if((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+    {
+        WARNING("ceph plugin: `Daemon' blocks need exactly one string "
+                "argument.");
+        return (-1);
+    }
+
+    ret = cc_handle_str(ci, cd.name, DATA_MAX_NAME_LEN);
+    if(ret)
+    {
+        return ret;
+    }
+
+    for(i=0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if(strcasecmp("SocketPath", child->key) == 0)
+        {
+            ret = cc_handle_str(child, cd.asok_path, sizeof(cd.asok_path));
+            if(ret)
+            {
+                return ret;
+            }
+        }
+        else
+        {
+            WARNING("ceph plugin: ignoring unknown option %s", child->key);
+        }
+    }
+    if(cd.name[0] == '\0')
+    {
+        ERROR("ceph plugin: you must configure a daemon name.\n");
+        return -EINVAL;
+    }
+    else if(cd.asok_path[0] == '\0')
+    {
+        ERROR("ceph plugin(name=%s): you must configure an administrative "
+        "socket path.\n", cd.name);
+        return -EINVAL;
+    }
+    else if(!((cd.asok_path[0] == '/') ||
+            (cd.asok_path[0] == '.' && cd.asok_path[1] == '/')))
+    {
+        ERROR("ceph plugin(name=%s): administrative socket paths must begin "
+                "with '/' or './' Can't parse: '%s'\n", cd.name, cd.asok_path);
+        return -EINVAL;
+    }
+
+    array = realloc(g_daemons,
+                    sizeof(struct ceph_daemon *) * (g_num_daemons + 1));
+    if(array == NULL)
+    {
+        /* The positive return value here indicates that this is a
+         * runtime error, not a configuration error.  */
+        return ENOMEM;
+    }
+    g_daemons = (struct ceph_daemon**) array;
+    nd = malloc(sizeof(struct ceph_daemon));
+    if(!nd)
+    {
+        return ENOMEM;
+    }
+    memcpy(nd, &cd, sizeof(struct ceph_daemon));
+    g_daemons[g_num_daemons++] = nd;
+    return 0;
+}
+
+static int ceph_config(oconfig_item_t *ci)
+{
+    int ret, i;
+
+    for(i = 0; i < ci->children_num; ++i)
+    {
+        oconfig_item_t *child = ci->children + i;
+        if(strcasecmp("Daemon", child->key) == 0)
+        {
+            ret = cc_add_daemon_config(child);
+            if(ret == ENOMEM)
+            {
+                ERROR("ceph plugin: Couldn't allocate memory");
+                return ret;
+            }
+            else if(ret)
+            {
+                //process other daemons and ignore this one
+                continue;
+            }
+        }
+        else if(strcasecmp("LongRunAvgLatency", child->key) == 0)
+        {
+            ret = cc_handle_bool(child, &long_run_latency_avg);
+            if(ret)
+            {
+                return ret;
+            }
+        }
+        else if(strcasecmp("ConvertSpecialMetricTypes", child->key) == 0)
+        {
+            ret = cc_handle_bool(child, &convert_special_metrics);
+            if(ret)
+            {
+                return ret;
+            }
+        }
+        else
+        {
+            WARNING("ceph plugin: ignoring unknown option %s", child->key);
+        }
+    }
+    return 0;
+}
+
+/**
+ * Parse JSON and get error message if present
+ */
+static int
+traverse_json(const unsigned char *json, uint32_t json_len, yajl_handle hand)
+{
+    yajl_status status = yajl_parse(hand, json, json_len);
+    unsigned char *msg;
+
+    switch(status)
+    {
+        case yajl_status_error:
+            msg = yajl_get_error(hand, /* verbose = */ 1,
+                                       /* jsonText = */ (unsigned char *) json,
+                                                      (unsigned int) json_len);
+            ERROR ("ceph plugin: yajl_parse failed: %s", msg);
+            yajl_free_error(hand, msg);
+            return 1;
+        case yajl_status_client_canceled:
+            return 1;
+        default:
+            return 0;
+    }
+}
+
+/**
+ * Add entry for each counter while parsing schema
+ */
+static int
+node_handler_define_schema(void *arg, const char *val, const char *key)
+{
+    struct ceph_daemon *d = (struct ceph_daemon *) arg;
+    int pc_type;
+    pc_type = atoi(val);
+    return ceph_daemon_add_ds_entry(d, key, pc_type);
+}
+
+/**
+ * Latency counter does not yet have an entry in last poll data - add it.
+ */
+static int add_last(struct ceph_daemon *d, const char *ds_n, double cur_sum,
+        uint64_t cur_count)
+{
+    d->last_poll_data[d->last_idx] = malloc(1 * sizeof(struct last_data));
+    if(!d->last_poll_data[d->last_idx])
+    {
+        return -ENOMEM;
+    }
+    sstrncpy(d->last_poll_data[d->last_idx]->ds_name,ds_n,
+            sizeof(d->last_poll_data[d->last_idx]->ds_name));
+    d->last_poll_data[d->last_idx]->last_sum = cur_sum;
+    d->last_poll_data[d->last_idx]->last_count = cur_count;
+    d->last_idx = (d->last_idx + 1);
+    return 0;
+}
+
+/**
+ * Update latency counter or add new entry if it doesn't exist
+ */
+static int update_last(struct ceph_daemon *d, const char *ds_n, int index,
+        double cur_sum, uint64_t cur_count)
+{
+    if((d->last_idx > index) && (strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0))
+    {
+        d->last_poll_data[index]->last_sum = cur_sum;
+        d->last_poll_data[index]->last_count = cur_count;
+        return 0;
+    }
+
+    if(!d->last_poll_data)
+    {
+        d->last_poll_data = malloc(1 * sizeof(struct last_data *));
+        if(!d->last_poll_data)
+        {
+            return -ENOMEM;
+        }
+    }
+    else
+    {
+        struct last_data **tmp_last = realloc(d->last_poll_data,
+                ((d->last_idx+1) * sizeof(struct last_data *)));
+        if(!tmp_last)
+        {
+            return -ENOMEM;
+        }
+        d->last_poll_data = tmp_last;
+    }
+    return add_last(d, ds_n, cur_sum, cur_count);
+}
+
+/**
+ * If using index guess failed (shouldn't happen, but possible if counters
+ * get rearranged), resort to searching for counter name
+ */
+static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n)
+{
+    int i = 0;
+    for(; i < d->last_idx; i++)
+    {
+        if(strcmp(d->last_poll_data[i]->ds_name, ds_n) == 0)
+        {
+            return i;
+        }
+    }
+    return -1;
+}
+
+/**
+ * Calculate average b/t current data and last poll data
+ * if last poll data exists
+ */
+static double get_last_avg(struct ceph_daemon *d, const char *ds_n, int index,
+        double cur_sum, uint64_t cur_count)
+{
+    double result = -1.1, sum_delt = 0.0;
+    uint64_t count_delt = 0;
+    int tmp_index = 0;
+    if(d->last_idx > index)
+    {
+        if(strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0)
+        {
+            tmp_index = index;
+        }
+        //test previous index
+        else if((index > 0) && (strcmp(d->last_poll_data[index-1]->ds_name, ds_n) == 0))
+        {
+            tmp_index = (index - 1);
+        }
+        else
+        {
+            tmp_index = backup_search_for_last_avg(d, ds_n);
+        }
+
+        if((tmp_index > -1) && (cur_count > d->last_poll_data[tmp_index]->last_count))
+        {
+            sum_delt = (cur_sum - d->last_poll_data[tmp_index]->last_sum);
+            count_delt = (cur_count - d->last_poll_data[tmp_index]->last_count);
+            result = (sum_delt / count_delt);
+        }
+    }
+
+    if(result == -1.1)
+    {
+        result = NAN;
+    }
+    if(update_last(d, ds_n, tmp_index, cur_sum, cur_count) == -ENOMEM)
+    {
+        return -ENOMEM;
+    }
+    return result;
+}
+
+/**
+ * If using index guess failed, resort to searching for counter name
+ */
+static uint32_t backup_search_for_type(struct ceph_daemon *d, char *ds_name)
+{
+    int idx = 0;
+    for(; idx < d->ds_num; idx++)
+    {
+        if(strcmp(d->ds_names[idx], ds_name) == 0)
+        {
+            return d->ds_types[idx];
+        }
+    }
+    return DSET_TYPE_UNFOUND;
+}
+
+/**
+ * Process counter data and dispatch values
+ */
+static int node_handler_fetch_data(void *arg, const char *val, const char *key)
+{
+    value_t uv;
+    double tmp_d;
+    uint64_t tmp_u;
+    struct values_tmp *vtmp = (struct values_tmp*) arg;
+    uint32_t type = DSET_TYPE_UNFOUND;
+    int index = vtmp->index;
+
+    char ds_name[DATA_MAX_NAME_LEN];
+    memset(ds_name, 0, sizeof(ds_name));
+
+    if(parse_keys(key, ds_name))
+    {
+        return 1;
+    }
+
+    if(index >= vtmp->d->ds_num)
+    {
+        //don't overflow bounds of array
+        index = (vtmp->d->ds_num - 1);
+    }
+
+    /**
+     * counters should remain in same order we parsed schema... we maintain the
+     * index variable to keep track of current point in list of counters. first
+     * use index to guess point in array for retrieving type. if that doesn't
+     * work, use the old way to get the counter type
+     */
+    if(strcmp(ds_name, vtmp->d->ds_names[index]) == 0)
+    {
+        //found match
+        type = vtmp->d->ds_types[index];
+    }
+    else if((index > 0) && (strcmp(ds_name, vtmp->d->ds_names[index-1]) == 0))
+    {
+        //try previous key
+        type = vtmp->d->ds_types[index-1];
+    }
+
+    if(type == DSET_TYPE_UNFOUND)
+    {
+        //couldn't find right type by guessing, check the old way
+        type = backup_search_for_type(vtmp->d, ds_name);
+    }
+
+    switch(type)
+    {
+        case DSET_LATENCY:
+            if(vtmp->avgcount_exists == -1)
+            {
+                sscanf(val, "%" PRIu64, &vtmp->avgcount);
+                vtmp->avgcount_exists = 0;
+                //return after saving avgcount - don't dispatch value
+                //until latency calculation
+                return 0;
+            }
+            else
+            {
+                double sum, result;
+                sscanf(val, "%lf", &sum);
+
+                if(vtmp->avgcount == 0)
+                {
+                    vtmp->avgcount = 1;
+                }
+
+                /** User wants latency values as long run avg */
+                if(long_run_latency_avg)
+                {
+                    result = (sum / vtmp->avgcount);
+                }
+                else
+                {
+                    result = get_last_avg(vtmp->d, ds_name, vtmp->latency_index, sum, vtmp->avgcount);
+                    if(result == -ENOMEM)
+                    {
+                        return -ENOMEM;
+                    }
+                }
+
+                uv.gauge = result;
+                vtmp->avgcount_exists = -1;
+                vtmp->latency_index = (vtmp->latency_index + 1);
+            }
+            break;
+        case DSET_BYTES:
+            sscanf(val, "%lf", &tmp_d);
+            uv.gauge = tmp_d;
+            break;
+        case DSET_RATE:
+            sscanf(val, "%" PRIu64, &tmp_u);
+            uv.derive = tmp_u;
+            break;
+        case DSET_TYPE_UNFOUND:
+        default:
+            ERROR("ceph plugin: ds %s was not properly initialized.", ds_name);
+            return -1;
+    }
+
+    sstrncpy(vtmp->vlist.type, ceph_dset_types[type], sizeof(vtmp->vlist.type));
+    sstrncpy(vtmp->vlist.type_instance, ds_name, sizeof(vtmp->vlist.type_instance));
+    vtmp->vlist.values = &uv;
+    vtmp->vlist.values_len = 1;
+
+    vtmp->index = (vtmp->index + 1);
+    plugin_dispatch_values(&vtmp->vlist);
+
+    return 0;
+}
+
+static int cconn_connect(struct cconn *io)
+{
+    struct sockaddr_un address;
+    int flags, fd, err;
+    if(io->state != CSTATE_UNCONNECTED)
+    {
+        ERROR("ceph plugin: cconn_connect: io->state != CSTATE_UNCONNECTED");
+        return -EDOM;
+    }
+    fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if(fd < 0)
+    {
+        int err = -errno;
+        ERROR("ceph plugin: cconn_connect: socket(PF_UNIX, SOCK_STREAM, 0) "
+            "failed: error %d", err);
+        return err;
+    }
+    memset(&address, 0, sizeof(struct sockaddr_un));
+    address.sun_family = AF_UNIX;
+    snprintf(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)
+    {
+        ERROR("ceph plugin: cconn_connect: connect(%d) failed: error %d",
+            fd, err);
+        return err;
+    }
+
+    flags = fcntl(fd, F_GETFL, 0);
+    if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0)
+    {
+        err = -errno;
+        ERROR("ceph plugin: cconn_connect: fcntl(%d, O_NONBLOCK) error %d",
+            fd, err);
+        return err;
+    }
+    io->asok = fd;
+    io->state = CSTATE_WRITE_REQUEST;
+    io->amt = 0;
+    io->json_len = 0;
+    io->json = NULL;
+    return 0;
+}
+
+static void cconn_close(struct cconn *io)
+{
+    io->state = CSTATE_UNCONNECTED;
+    if(io->asok != -1)
+    {
+        int res;
+        RETRY_ON_EINTR(res, close(io->asok));
+    }
+    io->asok = -1;
+    io->amt = 0;
+    io->json_len = 0;
+    sfree(io->json);
+    io->json = NULL;
+}
+
+/* Process incoming JSON counter data */
+static int
+cconn_process_data(struct cconn *io, yajl_struct *yajl, yajl_handle hand)
+{
+    int ret;
+    struct values_tmp *vtmp = calloc(1, sizeof(struct values_tmp) * 1);
+    if(!vtmp)
+    {
+        return -ENOMEM;
+    }
+
+    vtmp->vlist = (value_list_t)VALUE_LIST_INIT;
+    sstrncpy(vtmp->vlist.host, hostname_g, sizeof(vtmp->vlist.host));
+    sstrncpy(vtmp->vlist.plugin, "ceph", sizeof(vtmp->vlist.plugin));
+    sstrncpy(vtmp->vlist.plugin_instance, io->d->name, sizeof(vtmp->vlist.plugin_instance));
+
+    vtmp->d = io->d;
+    vtmp->avgcount_exists = -1;
+    vtmp->latency_index = 0;
+    vtmp->index = 0;
+    yajl->handler_arg = vtmp;
+    ret = traverse_json(io->json, io->json_len, hand);
+    sfree(vtmp);
+    return ret;
+}
+
+/**
+ * Initiate JSON parsing and print error if one occurs
+ */
+static int cconn_process_json(struct cconn *io)
+{
+    if((io->request_type != ASOK_REQ_DATA) &&
+            (io->request_type != ASOK_REQ_SCHEMA))
+    {
+        return -EDOM;
+    }
+
+    int result = 1;
+    yajl_handle hand;
+    yajl_status status;
+
+    hand = yajl_alloc(&callbacks,
+#if HAVE_YAJL_V2
+      /* alloc funcs = */ NULL,
+#else
+      /* alloc funcs = */ NULL, NULL,
+#endif
+      /* context = */ (void *)(&io->yajl));
+
+    if(!hand)
+    {
+        ERROR ("ceph plugin: yajl_alloc failed.");
+        return ENOMEM;
+    }
+
+    io->yajl.depth = 0;
+
+    switch(io->request_type)
+    {
+        case ASOK_REQ_DATA:
+            io->yajl.handler = node_handler_fetch_data;
+            result = cconn_process_data(io, &io->yajl, hand);
+            break;
+        case ASOK_REQ_SCHEMA:
+            //init daemon specific variables
+            io->d->ds_num = 0;
+            io->d->last_idx = 0;
+            io->d->last_poll_data = NULL;
+            io->yajl.handler = node_handler_define_schema;
+            io->yajl.handler_arg = io->d;
+            result = traverse_json(io->json, io->json_len, hand);
+            break;
+    }
+
+    if(result)
+    {
+        goto done;
+    }
+
+#if HAVE_YAJL_V2
+    status = yajl_complete_parse(hand);
+#else
+    status = yajl_parse_complete(hand);
+#endif
+
+    if (status != yajl_status_ok)
+    {
+      unsigned char *errmsg = yajl_get_error (hand, /* verbose = */ 0,
+          /* jsonText = */ NULL, /* jsonTextLen = */ 0);
+      ERROR ("ceph plugin: yajl_parse_complete failed: %s",
+          (char *) errmsg);
+      yajl_free_error (hand, errmsg);
+      yajl_free (hand);
+      return 1;
+    }
+
+    done:
+    yajl_free (hand);
+    return result;
+}
+
+static int cconn_validate_revents(struct cconn *io, int revents)
+{
+    if(revents & POLLERR)
+    {
+        ERROR("ceph plugin: cconn_validate_revents(name=%s): got POLLERR",
+            io->d->name);
+        return -EIO;
+    }
+    switch (io->state)
+    {
+        case CSTATE_WRITE_REQUEST:
+            return (revents & POLLOUT) ? 0 : -EINVAL;
+        case CSTATE_READ_VERSION:
+        case CSTATE_READ_AMT:
+        case CSTATE_READ_JSON:
+            return (revents & POLLIN) ? 0 : -EINVAL;
+        default:
+            ERROR("ceph plugin: cconn_validate_revents(name=%s) got to "
+                "illegal state on line %d", io->d->name, __LINE__);
+            return -EDOM;
+    }
+}
+
+/** Handle a network event for a connection */
+static int cconn_handle_event(struct cconn *io)
+{
+    int ret;
+    switch (io->state)
+    {
+        case CSTATE_UNCONNECTED:
+            ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal "
+                "state on line %d", io->d->name, __LINE__);
+
+            return -EDOM;
+        case CSTATE_WRITE_REQUEST:
+        {
+            char cmd[32];
+            snprintf(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));
+            DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,amt=%d,ret=%d)",
+                    io->d->name, io->state, io->amt, ret);
+            if(ret < 0)
+            {
+                return ret;
+            }
+            io->amt += ret;
+            if(io->amt >= cmd_len)
+            {
+                io->amt = 0;
+                switch (io->request_type)
+                {
+                    case ASOK_REQ_VERSION:
+                        io->state = CSTATE_READ_VERSION;
+                        break;
+                    default:
+                        io->state = CSTATE_READ_AMT;
+                        break;
+                }
+            }
+            return 0;
+        }
+        case CSTATE_READ_VERSION:
+        {
+            RETRY_ON_EINTR(ret,
+                    read(io->asok, ((char*)(&io->d->version)) + io->amt,
+                            sizeof(io->d->version) - io->amt));
+            DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)",
+                    io->d->name, io->state, ret);
+            if(ret < 0)
+            {
+                return ret;
+            }
+            io->amt += ret;
+            if(io->amt >= sizeof(io->d->version))
+            {
+                io->d->version = ntohl(io->d->version);
+                if(io->d->version != 1)
+                {
+                    ERROR("ceph plugin: cconn_handle_event(name=%s) not "
+                        "expecting version %d!", io->d->name, io->d->version);
+                    return -ENOTSUP;
+                }
+                DEBUG("ceph plugin: cconn_handle_event(name=%s): identified as "
+                        "version %d", io->d->name, io->d->version);
+                io->amt = 0;
+                cconn_close(io);
+                io->request_type = ASOK_REQ_SCHEMA;
+            }
+            return 0;
+        }
+        case CSTATE_READ_AMT:
+        {
+            RETRY_ON_EINTR(ret,
+                    read(io->asok, ((char*)(&io->json_len)) + io->amt,
+                            sizeof(io->json_len) - io->amt));
+            DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)",
+                    io->d->name, io->state, ret);
+            if(ret < 0)
+            {
+                return ret;
+            }
+            io->amt += ret;
+            if(io->amt >= sizeof(io->json_len))
+            {
+                io->json_len = ntohl(io->json_len);
+                io->amt = 0;
+                io->state = CSTATE_READ_JSON;
+                io->json = calloc(1, io->json_len + 1);
+                if(!io->json)
+                {
+                    ERROR("ceph plugin: error callocing io->json");
+                    return -ENOMEM;
+                }
+            }
+            return 0;
+        }
+        case CSTATE_READ_JSON:
+        {
+            RETRY_ON_EINTR(ret,
+                   read(io->asok, io->json + io->amt, io->json_len - io->amt));
+            DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)",
+                    io->d->name, io->state, ret);
+            if(ret < 0)
+            {
+                return ret;
+            }
+            io->amt += ret;
+            if(io->amt >= io->json_len)
+            {
+                ret = cconn_process_json(io);
+                if(ret)
+                {
+                    return ret;
+                }
+                cconn_close(io);
+                io->request_type = ASOK_REQ_NONE;
+            }
+            return 0;
+        }
+        default:
+            ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal "
+                "state on line %d", io->d->name, __LINE__);
+            return -EDOM;
+    }
+}
+
+static int cconn_prepare(struct cconn *io, struct pollfd* fds)
+{
+    int ret;
+    if(io->request_type == ASOK_REQ_NONE)
+    {
+        /* The request has already been serviced. */
+        return 0;
+    }
+    else if((io->request_type == ASOK_REQ_DATA) && (io->d->ds_num == 0))
+    {
+        /* If there are no counters to report on, don't bother
+         * connecting */
+        return 0;
+    }
+
+    switch (io->state)
+    {
+        case CSTATE_UNCONNECTED:
+            ret = cconn_connect(io);
+            if(ret > 0)
+            {
+                return -ret;
+            }
+            else if(ret < 0)
+            {
+                return ret;
+            }
+            fds->fd = io->asok;
+            fds->events = POLLOUT;
+            return 1;
+        case CSTATE_WRITE_REQUEST:
+            fds->fd = io->asok;
+            fds->events = POLLOUT;
+            return 1;
+        case CSTATE_READ_VERSION:
+        case CSTATE_READ_AMT:
+        case CSTATE_READ_JSON:
+            fds->fd = io->asok;
+            fds->events = POLLIN;
+            return 1;
+        default:
+            ERROR("ceph plugin: cconn_prepare(name=%s) got to illegal state "
+                "on line %d", io->d->name, __LINE__);
+            return -EDOM;
+    }
+}
+
+/** Returns the difference between two struct timevals in milliseconds.
+ * On overflow, we return max/min int.
+ */
+static int milli_diff(const struct timeval *t1, const struct timeval *t2)
+{
+    int64_t ret;
+    int sec_diff = t1->tv_sec - t2->tv_sec;
+    int usec_diff = t1->tv_usec - t2->tv_usec;
+    ret = usec_diff / 1000;
+    ret += (sec_diff * 1000);
+    return (ret > INT_MAX) ? INT_MAX : ((ret < INT_MIN) ? INT_MIN : (int)ret);
+}
+
+/** This handles the actual network I/O to talk to the Ceph daemons.
+ */
+static int cconn_main_loop(uint32_t request_type)
+{
+    int i, ret, some_unreachable = 0;
+    struct timeval end_tv;
+    struct cconn io_array[g_num_daemons];
+
+    DEBUG("ceph plugin: entering cconn_main_loop(request_type = %d)", request_type);
+
+    /* create cconn array */
+    memset(io_array, 0, sizeof(io_array));
+    for(i = 0; i < g_num_daemons; ++i)
+    {
+        io_array[i].d = g_daemons[i];
+        io_array[i].request_type = request_type;
+        io_array[i].state = CSTATE_UNCONNECTED;
+    }
+
+    /** Calculate the time at which we should give up */
+    gettimeofday(&end_tv, NULL);
+    end_tv.tv_sec += CEPH_TIMEOUT_INTERVAL;
+
+    while (1)
+    {
+        int nfds, diff;
+        struct timeval tv;
+        struct cconn *polled_io_array[g_num_daemons];
+        struct pollfd fds[g_num_daemons];
+        memset(fds, 0, sizeof(fds));
+        nfds = 0;
+        for(i = 0; i < g_num_daemons; ++i)
+        {
+            struct cconn *io = io_array + i;
+            ret = cconn_prepare(io, fds + nfds);
+            if(ret < 0)
+            {
+                WARNING("ceph plugin: cconn_prepare(name=%s,i=%d,st=%d)=%d",
+                        io->d->name, i, io->state, ret);
+                cconn_close(io);
+                io->request_type = ASOK_REQ_NONE;
+                some_unreachable = 1;
+            }
+            else if(ret == 1)
+            {
+                polled_io_array[nfds++] = io_array + i;
+            }
+        }
+        if(nfds == 0)
+        {
+            /* finished */
+            ret = 0;
+            goto done;
+        }
+        gettimeofday(&tv, NULL);
+        diff = milli_diff(&end_tv, &tv);
+        if(diff <= 0)
+        {
+            /* Timed out */
+            ret = -ETIMEDOUT;
+            WARNING("ceph plugin: cconn_main_loop: timed out.");
+            goto done;
+        }
+        RETRY_ON_EINTR(ret, poll(fds, nfds, diff));
+        if(ret < 0)
+        {
+            ERROR("ceph plugin: poll(2) error: %d", ret);
+            goto done;
+        }
+        for(i = 0; i < nfds; ++i)
+        {
+            struct cconn *io = polled_io_array[i];
+            int revents = fds[i].revents;
+            if(revents == 0)
+            {
+                /* do nothing */
+            }
+            else if(cconn_validate_revents(io, revents))
+            {
+                WARNING("ceph plugin: cconn(name=%s,i=%d,st=%d): "
+                "revents validation error: "
+                "revents=0x%08x", io->d->name, i, io->state, revents);
+                cconn_close(io);
+                io->request_type = ASOK_REQ_NONE;
+                some_unreachable = 1;
+            }
+            else
+            {
+                int ret = cconn_handle_event(io);
+                if(ret)
+                {
+                    WARNING("ceph plugin: cconn_handle_event(name=%s,"
+                    "i=%d,st=%d): error %d", io->d->name, i, io->state, ret);
+                    cconn_close(io);
+                    io->request_type = ASOK_REQ_NONE;
+                    some_unreachable = 1;
+                }
+            }
+        }
+    }
+    done: for(i = 0; i < g_num_daemons; ++i)
+    {
+        cconn_close(io_array + i);
+    }
+    if(some_unreachable)
+    {
+        DEBUG("ceph plugin: cconn_main_loop: some Ceph daemons were unreachable.");
+    }
+    else
+    {
+        DEBUG("ceph plugin: cconn_main_loop: reached all Ceph daemons :)");
+    }
+    return ret;
+}
+
+static int ceph_read(void)
+{
+    return cconn_main_loop(ASOK_REQ_DATA);
+}
+
+/******* lifecycle *******/
+static int ceph_init(void)
+{
+    int ret;
+    ceph_daemons_print();
+
+    ret = cconn_main_loop(ASOK_REQ_VERSION);
+
+    return (ret) ? ret : 0;
+}
+
+static int ceph_shutdown(void)
+{
+    int i;
+    for(i = 0; i < g_num_daemons; ++i)
+    {
+        ceph_daemon_free(g_daemons[i]);
+    }
+    sfree(g_daemons);
+    g_daemons = NULL;
+    g_num_daemons = 0;
+    DEBUG("ceph plugin: finished ceph_shutdown");
+    return 0;
+}
+
+void module_register(void)
+{
+    plugin_register_complex_config("ceph", ceph_config);
+    plugin_register_init("ceph", ceph_init);
+    plugin_register_read("ceph", ceph_read);
+    plugin_register_shutdown("ceph", ceph_shutdown);
+}
diff --git a/src/cgroups.c b/src/cgroups.c
new file mode 100644 (file)
index 0000000..6d41972
--- /dev/null
@@ -0,0 +1,256 @@
+/**
+ * collectd - src/cgroups.c
+ * Copyright (C) 2011  Michael Stapelberg
+ * Copyright (C) 2013  Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Michael Stapelberg <michael at stapelberg.de>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_mount.h"
+#include "utils_ignorelist.h"
+
+static char const *config_keys[] =
+{
+       "CGroup",
+       "IgnoreSelected"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *il_cgroup = NULL;
+
+__attribute__ ((nonnull(1)))
+__attribute__ ((nonnull(2)))
+static void cgroups_submit_one (char const *plugin_instance,
+               char const *type_instance, value_t value)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = &value;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "cgroups", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "cpu", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance,
+                       sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void cgroups_submit_one */
+
+/*
+ * This callback reads the user/system CPU time for each cgroup.
+ */
+static int read_cpuacct_procs (const char *dirname, char const *cgroup_name,
+    void *user_data)
+{
+       char abs_path[PATH_MAX];
+       struct stat statbuf;
+       char buf[1024];
+       int status;
+
+       FILE *fh;
+
+       if (ignorelist_match (il_cgroup, cgroup_name))
+               return (0);
+
+       ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, cgroup_name);
+
+       status = lstat (abs_path, &statbuf);
+       if (status != 0)
+       {
+               ERROR ("cgroups plugin: stat (\"%s\") failed.",
+                               abs_path);
+               return (-1);
+       }
+
+       /* We are only interested in directories, so skip everything else. */
+       if (!S_ISDIR (statbuf.st_mode))
+               return (0);
+
+       ssnprintf (abs_path, sizeof (abs_path), "%s/%s/cpuacct.stat",
+                       dirname, cgroup_name);
+       fh = fopen (abs_path, "r");
+       if (fh == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("cgroups plugin: fopen (\"%s\") failed: %s",
+                               abs_path,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buf, sizeof (buf), fh) != NULL)
+       {
+               char *fields[8];
+               int numfields = 0;
+               char *key;
+               size_t key_len;
+               value_t value;
+
+               /* Expected format:
+                *
+                *   user: 12345
+                *   system: 23456
+                *
+                * Or:
+                *
+                *   user 12345
+                *   system 23456
+                */
+               strstripnewline (buf);
+               numfields = strsplit (buf, fields, STATIC_ARRAY_SIZE (fields));
+               if (numfields != 2)
+                       continue;
+
+               key = fields[0];
+               key_len = strlen (key);
+               if (key_len < 2)
+                       continue;
+
+               /* Strip colon off the first column, if found */
+               if (key[key_len - 1] == ':')
+                       key[key_len - 1] = 0;
+
+               status = parse_value (fields[1], &value, DS_TYPE_DERIVE);
+               if (status != 0)
+                       continue;
+
+               cgroups_submit_one (cgroup_name, key, value);
+       }
+
+       fclose (fh);
+       return (0);
+} /* int read_cpuacct_procs */
+
+/*
+ * Gets called for every file/folder in /sys/fs/cgroup/cpu,cpuacct (or
+ * wherever cpuacct is mounted on the system). Calls walk_directory with the
+ * read_cpuacct_procs callback on every folder it finds, such as "system".
+ */
+static int read_cpuacct_root (const char *dirname, const char *filename,
+               void *user_data)
+{
+       char abs_path[PATH_MAX];
+       struct stat statbuf;
+       int status;
+
+       ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, filename);
+
+       status = lstat (abs_path, &statbuf);
+       if (status != 0)
+       {
+               ERROR ("cgroups plugin: stat (%s) failed.", abs_path);
+               return (-1);
+       }
+
+       if (S_ISDIR (statbuf.st_mode))
+       {
+               status = walk_directory (abs_path, read_cpuacct_procs,
+                               /* user_data = */ NULL,
+                               /* include_hidden = */ 0);
+               return (status);
+       }
+
+       return (0);
+}
+
+static int cgroups_init (void)
+{
+       if (il_cgroup == NULL)
+               il_cgroup = ignorelist_create (1);
+
+       return (0);
+}
+
+static int cgroups_config (const char *key, const char *value)
+{
+       cgroups_init ();
+
+       if (strcasecmp (key, "CGroup") == 0)
+       {
+               if (ignorelist_add (il_cgroup, value))
+                       return (1);
+               return (0);
+       }
+       else if (strcasecmp (key, "IgnoreSelected") == 0)
+       {
+               if (IS_TRUE (value))
+                       ignorelist_set_invert (il_cgroup, 0);
+               else
+                       ignorelist_set_invert (il_cgroup, 1);
+               return (0);
+       }
+
+       return (-1);
+}
+
+static int cgroups_read (void)
+{
+       cu_mount_t *mnt_list;
+       cu_mount_t *mnt_ptr;
+       _Bool cgroup_found = 0;
+
+       mnt_list = NULL;
+       if (cu_mount_getlist (&mnt_list) == NULL)
+       {
+               ERROR ("cgroups plugin: cu_mount_getlist failed.");
+               return (-1);
+       }
+
+       for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
+       {
+               /* Find the cgroup mountpoint which contains the cpuacct
+                * controller. */
+               if ((strcmp(mnt_ptr->type, "cgroup") != 0)
+                               || !cu_mount_checkoption(mnt_ptr->options,
+                                       "cpuacct", /* full = */ 1))
+                       continue;
+
+               walk_directory (mnt_ptr->dir, read_cpuacct_root,
+                               /* user_data = */ NULL,
+                               /* include_hidden = */ 0);
+               cgroup_found = 1;
+               /* It doesn't make sense to check other cpuacct mount-points
+                * (if any), they contain the same data. */
+               break;
+       }
+
+       cu_mount_freelist (mnt_list);
+
+       if (!cgroup_found)
+       {
+               WARNING ("cgroups plugin: Unable to find cgroup "
+                               "mount-point with the \"cpuacct\" option.");
+               return (-1);
+       }
+
+       return (0);
+} /* int cgroup_read */
+
+void module_register (void)
+{
+       plugin_register_config ("cgroups", cgroups_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("cgroups", cgroups_init);
+       plugin_register_read ("cgroups", cgroups_read);
+} /* void module_register */
diff --git a/src/collectd-email.5 b/src/collectd-email.5
new file mode 100644 (file)
index 0000000..93ae464
--- /dev/null
@@ -0,0 +1,202 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-EMAIL 5"
+.TH COLLECTD-EMAIL 5 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-email \- Documentation of collectd's "email plugin"
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 8
+\&  # See collectd.conf(5)
+\&  LoadPlugin email
+\&  # ...
+\&  <Plugin email>
+\&    SocketGroup "collectd"
+\&    SocketPerms "0770"
+\&    MaxConns 5
+\&  </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \f(CW\*(C`email plugin\*(C'\fR opens an UNIX-socket over which one can submit email
+statistics, such as the number of \*(L"ham\*(R", \*(L"spam\*(R", \*(L"virus\*(R", etc. mails
+received/handled, spam scores and matched spam checks.
+.PP
+This plugin is intended to be used with the
+Mail::SpamAssassin::Plugin::Collectd SpamAssassin-plugin which is included
+in \fIcontrib/\fR, but is of course not limited to that use.
+.SH "OPERATION"
+.IX Header "OPERATION"
+This plugin collects data indirectly by providing a UNIX-socket that external
+programs can connect to. A simple line based protocol is used to communicate
+with the plugin:
+.IP "\(bu" 4
+E\-Mail type (e.g. \*(L"ham\*(R", \*(L"spam\*(R", \*(L"virus\*(R", ...) and size (bytes):
+.Sp
+.Vb 1
+\&  e:<type>:<size>
+.Ve
+.Sp
+If \f(CW\*(C`size\*(C'\fR is less than or equal to zero, \f(CW\*(C`size\*(C'\fR is ignored.
+.IP "\(bu" 4
+Spam score:
+.Sp
+.Vb 1
+\&  s:<value>
+.Ve
+.IP "\(bu" 4
+Successful spam checks (e.g. \*(L"\s-1BAYES_99\*(R", \*(L"SUBJECT_DRUG_GAP_C\*(R", ...\s0):
+.Sp
+.Vb 1
+\&  c:<type1>[,<type2>,...]
+.Ve
+.Sp
+Each line is limited to 256 characters (including the newline character). 
+Longer lines will be ignored.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+The \f(CW\*(C`email plugin\*(C'\fR has been written by Sebastian Harl <sh\ at\ tokkee.org>.
+.PP
+The SpamAssassin-plugin has been written by Alexander Wirt <formorer\ at\ formorer.de>.
+.PP
+This manpage has been written by Florian Forster <octo\ at\ collectd.org>.
diff --git a/src/collectd-email.pod b/src/collectd-email.pod
new file mode 100644 (file)
index 0000000..282098e
--- /dev/null
@@ -0,0 +1,74 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-email - Documentation of collectd's C<email plugin>
+
+=head1 SYNOPSIS
+
+  # See collectd.conf(5)
+  LoadPlugin email
+  # ...
+  <Plugin email>
+    SocketGroup "collectd"
+    SocketPerms "0770"
+    MaxConns 5
+  </Plugin>
+
+=head1 DESCRIPTION
+
+The C<email plugin> opens an UNIX-socket over which one can submit email
+statistics, such as the number of "ham", "spam", "virus", etc. mails
+received/handled, spam scores and matched spam checks.
+
+This plugin is intended to be used with the
+L<Mail::SpamAssassin::Plugin::Collectd> SpamAssassin-plugin which is included
+in F<contrib/>, but is of course not limited to that use.
+
+=head1 OPERATION
+
+This plugin collects data indirectly by providing a UNIX-socket that external
+programs can connect to. A simple line based protocol is used to communicate
+with the plugin:
+
+=over 4
+
+=item
+
+E-Mail type (e.g. "ham", "spam", "virus", ...) and size (bytes):
+
+  e:<type>:<size>
+
+If C<size> is less than or equal to zero, C<size> is ignored.
+
+=item
+
+Spam score:
+
+  s:<value>
+
+=item
+
+Successful spam checks (e.g. "BAYES_99", "SUBJECT_DRUG_GAP_C", ...):
+
+  c:<type1>[,<type2>,...]
+
+Each line is limited to 256 characters (including the newline character). 
+Longer lines will be ignored.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>
+
+=head1 AUTHOR
+
+The C<email plugin> has been written by Sebastian Harl E<lt>shE<nbsp>atE<nbsp>tokkee.orgE<gt>.
+
+The SpamAssassin-plugin has been written by Alexander Wirt E<lt>formorerE<nbsp>atE<nbsp>formorer.deE<gt>.
+
+This manpage has been written by Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt>.
+
+=cut
diff --git a/src/collectd-exec.5 b/src/collectd-exec.5
new file mode 100644 (file)
index 0000000..3d9b591
--- /dev/null
@@ -0,0 +1,411 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-EXEC 5"
+.TH COLLECTD-EXEC 5 "2015-05-20" "5.4.2.911.g0c88d3b" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-exec \- Documentation of collectd's "exec plugin"
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 8
+\&  # See collectd.conf(5)
+\&  LoadPlugin exec
+\&  # ...
+\&  <Plugin exec>
+\&    Exec "myuser:mygroup" "myprog"
+\&    Exec "otheruser" "/path/to/another/binary" "arg0" "arg1"
+\&    NotificationExec "user" "/usr/lib/collectd/exec/handle_notification"
+\&  </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \f(CW\*(C`exec plugin\*(C'\fR forks of an executable either to receive values or to
+dispatch notifications to the outside world. The syntax of the configuration is
+explained in \fIcollectd.conf\fR\|(5) but summarized in the above synopsis.
+.PP
+If you want/need better performance or more functionality you should take a
+long look at the \f(CW\*(C`perl plugin\*(C'\fR, \fIcollectd\-perl\fR\|(5).
+.SH "EXECUTABLE TYPES"
+.IX Header "EXECUTABLE TYPES"
+There are currently two types of executables that can be executed by the
+\&\f(CW\*(C`exec plugin\*(C'\fR:
+.ie n .IP """Exec""" 4
+.el .IP "\f(CWExec\fR" 4
+.IX Item "Exec"
+These programs are forked and values that it writes to \f(CW\*(C`STDOUT\*(C'\fR are read back.
+The executable is forked in a fashion similar to init: It is forked once and
+not again until it exits. If it exited, it will be forked again after at most
+\&\fIInterval\fR seconds. It is perfectly legal for the executable to run for a long
+time and continuously write values to \f(CW\*(C`STDOUT\*(C'\fR.
+.Sp
+See \*(L"\s-1EXEC DATA FORMAT\*(R"\s0 below for a description of the output format expected
+from these programs.
+.Sp
+\&\fBWarning:\fR If the executable only writes one value and then exits I will be
+executed every \fIInterval\fR seconds. If \fIInterval\fR is short (the default is 10
+seconds) this may result in serious system load.
+.ie n .IP """NotificationExec""" 4
+.el .IP "\f(CWNotificationExec\fR" 4
+.IX Item "NotificationExec"
+The program is forked once for each notification that is handled by the daemon.
+The notification is passed to the program on \f(CW\*(C`STDIN\*(C'\fR in a fashion similar to
+HTTP-headers. In contrast to programs specified with \f(CW\*(C`Exec\*(C'\fR the execution of
+this program is not serialized, so that several instances of this program may
+run at once if multiple notifications are received.
+.Sp
+See \*(L"\s-1NOTIFICATION DATA FORMAT\*(R"\s0 below for a description of the data passed to
+these programs.
+.SH "EXEC DATA FORMAT"
+.IX Header "EXEC DATA FORMAT"
+The forked executable is expected to print values to \f(CW\*(C`STDOUT\*(C'\fR. The expected
+format is as follows:
+.IP "Comments" 4
+.IX Item "Comments"
+Each line beginning with a \f(CW\*(C`#\*(C'\fR (hash mark) is ignored.
+.IP "\fB\s-1PUTVAL\s0\fR \fIIdentifier\fR [\fIOptionList\fR] \fIValuelist\fR" 4
+.IX Item "PUTVAL Identifier [OptionList] Valuelist"
+Submits one or more values (identified by \fIIdentifier\fR, see below) to the
+daemon which will dispatch it to all it's write-plugins.
+.Sp
+An \fIIdentifier\fR is of the form
+\&\f(CW\*(C`\f(CIhost\f(CW\f(CB/\f(CW\f(CIplugin\f(CW\f(CB\-\f(CW\f(CIinstance\f(CW\f(CB/\f(CW\f(CItype\f(CW\f(CB\-\f(CW\f(CIinstance\f(CW\*(C'\fR with both
+\&\fIinstance\fR\-parts being optional. If they're omitted the hyphen must be
+omitted, too. \fIplugin\fR and each \fIinstance\fR\-part may be chosen freely as long
+as the tuple (plugin, plugin instance, type instance) uniquely identifies the
+plugin within collectd. \fItype\fR identifies the type and number of values
+(i.\ e. data-set) passed to collectd. A large list of predefined
+data-sets is available in the \fBtypes.db\fR file. See \fItypes.db\fR\|(5) for a
+description of the format of this file.
+.Sp
+The \fIOptionList\fR is an optional list of \fIOptions\fR, where each option is a
+key-value-pair. A list of currently understood options can be found below, all
+other options will be ignored. Values that contain spaces must be quoted with
+double quotes.
+.Sp
+\&\fIValuelist\fR is a colon-separated list of the time and the values, each either
+an integer if the data-source is a counter, or a double if the data-source is
+of type \*(L"gauge\*(R". You can submit an undefined gauge-value by using \fBU\fR. When
+submitting \fBU\fR to a counter the behavior is undefined. The time is given as
+epoch (i.\ e. standard \s-1UNIX\s0 time).
+.Sp
+You can mix options and values, but the order is important: Options only
+effect following values, so specifying an option as last field is allowed, but
+useless. Also, an option applies to \fBall\fR following values, so you don't need
+to re-set an option over and over again.
+.Sp
+The currently defined \fBOptions\fR are:
+.RS 4
+.IP "\fBinterval=\fR\fIseconds\fR" 4
+.IX Item "interval=seconds"
+Gives the interval in which the data identified by \fIIdentifier\fR is being
+collected.
+.RE
+.RS 4
+.Sp
+Please note that this is the same format as used in the \fBunixsock plugin\fR, see
+\&\fIcollectd\-unixsock\fR\|(5). There's also a bit more information on identifiers in
+case you're confused.
+.Sp
+Since examples usually let one understand a lot better, here are some:
+.Sp
+.Vb 2
+\&  PUTVAL leeloo/cpu\-0/cpu\-idle N:2299366
+\&  PUTVAL alice/interface/if_octets\-eth0 interval=10 1180647081:421465:479194
+.Ve
+.RE
+.IP "\fB\s-1PUTNOTIF\s0\fR [\fIOptionList\fR] \fBmessage=\fR\fIMessage\fR" 4
+.IX Item "PUTNOTIF [OptionList] message=Message"
+Submits a notification to the daemon which will then dispatch it to all plugins
+which have registered for receiving notifications.
+.Sp
+The \fB\s-1PUTNOTIF\s0\fR if followed by a list of options which further describe the
+notification. The \fBmessage\fR option is special in that it will consume the rest
+of the line as its value. The \fBmessage\fR, \fBseverity\fR, and \fBtime\fR options are
+mandatory.
+.Sp
+Valid options are:
+.RS 4
+.IP "\fBmessage=\fR\fIMessage\fR (\fB\s-1REQUIRED\s0\fR)" 4
+.IX Item "message=Message (REQUIRED)"
+Sets the message of the notification. This is the message that will be made
+accessible to the user, so it should contain some useful information. As with
+all options: If the message includes spaces, it must be quoted with double
+quotes. This option is mandatory.
+.IP "\fBseverity=failure\fR|\fBwarning\fR|\fBokay\fR (\fB\s-1REQUIRED\s0\fR)" 4
+.IX Item "severity=failure|warning|okay (REQUIRED)"
+Sets the severity of the notification. This option is mandatory.
+.IP "\fBtime=\fR\fITime\fR (\fB\s-1REQUIRED\s0\fR)" 4
+.IX Item "time=Time (REQUIRED)"
+Sets the time of the notification. The time is given as \*(L"epoch\*(R", i.\ e. as
+seconds since January 1st, 1970, 00:00:00. This option is mandatory.
+.IP "\fBhost=\fR\fIHostname\fR" 4
+.IX Item "host=Hostname"
+.PD 0
+.IP "\fBplugin=\fR\fIPlugin\fR" 4
+.IX Item "plugin=Plugin"
+.IP "\fBplugin_instance=\fR\fIPlugin-Instance\fR" 4
+.IX Item "plugin_instance=Plugin-Instance"
+.IP "\fBtype=\fR\fIType\fR" 4
+.IX Item "type=Type"
+.IP "\fBtype_instance=\fR\fIType-Instance\fR" 4
+.IX Item "type_instance=Type-Instance"
+.PD
+These \*(L"associative\*(R" options establish a relation between this notification and
+collected performance data. This connection is purely informal, i.\ e. the
+daemon itself doesn't do anything with this information. However, websites or
+GUIs may use this information to place notifications near the affected graph or
+table. All the options are optional, but \fBplugin_instance\fR without \fBplugin\fR
+or \fBtype_instance\fR without \fBtype\fR doesn't make much sense and should be
+avoided.
+.IP "\fBtype:key=\fR\fIvalue\fR" 4
+.IX Item "type:key=value"
+Sets user defined meta information. The \fBtype\fR key is a single character
+defining the type of the meta information.
+.Sp
+The current supported types are:
+.RS 4
+.IP "\fBs\fR A string passed as-is." 8
+.IX Item "s A string passed as-is."
+.RE
+.RS 4
+.RE
+.RE
+.RS 4
+.RE
+.PP
+Please note that this is the same format as used in the \fBunixsock plugin\fR, see
+\&\fIcollectd\-unixsock\fR\|(5).
+.PP
+When collectd exits it sends a \fB\s-1SIGTERM\s0\fR to all still running
+child-processes upon which they have to quit.
+.SH "NOTIFICATION DATA FORMAT"
+.IX Header "NOTIFICATION DATA FORMAT"
+The notification executables receive values rather than providing them. In
+fact, after the program is started \f(CW\*(C`STDOUT\*(C'\fR is connected to \f(CW\*(C`/dev/null\*(C'\fR.
+.PP
+The data is passed to the executables over \f(CW\*(C`STDIN\*(C'\fR in a format very similar to
+\&\s-1HTTP:\s0 At first there is a \*(L"header\*(R" with one line per field. Every line consists
+of a field name, ended by a colon, and the associated value until end-of-line.
+The \*(L"header\*(R" is ended by two newlines immediately following another,
+i.e. an empty line. The rest, basically the \*(L"body\*(R", is the message of the
+notification.
+.PP
+The following is an example notification passed to a program:
+.PP
+.Vb 5
+\&  Severity: FAILURE
+\&  Time: 1200928930.515
+\&  Host: myhost.mydomain.org
+\&  \en
+\&  This is a test notification to demonstrate the format
+.Ve
+.PP
+The following header files are currently used. Please note, however, that you
+should ignore unknown header files to be as forward-compatible as possible.
+.IP "\fBSeverity\fR" 4
+.IX Item "Severity"
+Severity of the notification. May either be \fB\s-1FAILURE\s0\fR, \fB\s-1WARNING\s0\fR, or \fB\s-1OKAY\s0\fR.
+.IP "\fBTime\fR" 4
+.IX Item "Time"
+The time in epoch, i.e. as seconds since 1970\-01\-01 00:00:00 \s-1UTC.\s0 The value
+currently has millisecond precision (i.e. three decimal places), but scripts
+should accept arbitrary numbers of decimal places, including no decimal places.
+.IP "\fBHost\fR" 4
+.IX Item "Host"
+.PD 0
+.IP "\fBPlugin\fR" 4
+.IX Item "Plugin"
+.IP "\fBPluginInstance\fR" 4
+.IX Item "PluginInstance"
+.IP "\fBType\fR" 4
+.IX Item "Type"
+.IP "\fBTypeInstance\fR" 4
+.IX Item "TypeInstance"
+.PD
+Identification of the performance data this notification is associated with.
+All of these fields are optional because notifications do not \fBneed\fR to be
+associated with a certain value.
+.SH "ENVIRONMENT"
+.IX Header "ENVIRONMENT"
+The following environment variables are set by the plugin before calling
+\&\fIexec\fR:
+.IP "\s-1COLLECTD_INTERVAL\s0" 4
+.IX Item "COLLECTD_INTERVAL"
+Value of the global interval setting.
+.IP "\s-1COLLECTD_HOSTNAME\s0" 4
+.IX Item "COLLECTD_HOSTNAME"
+Hostname used by \fIcollectd\fR to dispatch local values.
+.SH "USING NAGIOS PLUGINS"
+.IX Header "USING NAGIOS PLUGINS"
+Though the interface is far from perfect, there are tons of plugins for Nagios.
+You can use these plugins with collectd by using a simple transition layer,
+\&\f(CW\*(C`exec\-nagios.px\*(C'\fR, which is shipped with the collectd distribution in the
+\&\f(CW\*(C`contrib/\*(C'\fR directory. It is a simple Perl script that comes with embedded
+documentation. To see it, run the following command:
+.PP
+.Vb 1
+\&  perldoc exec\-nagios.px
+.Ve
+.PP
+This script expects a configuration file, \f(CW\*(C`exec\-nagios.conf\*(C'\fR. You can find an
+example in the \f(CW\*(C`contrib/\*(C'\fR directory, too.
+.PP
+Even a simple mechanism to submit \*(L"performance data\*(R" to collectd is
+implemented. If you need a more sophisticated setup, please rewrite the plugin
+to make use of collectd's more powerful interface.
+.SH "CAVEATS"
+.IX Header "CAVEATS"
+.IP "\(bu" 4
+The user, the binary is executed as, may not have root privileges, i.\ e.
+must have an \s-1UID\s0 that is non-zero. This is for your own good.
+.IP "\(bu" 4
+Early versions of the plugin did not use a command but treated all lines as if
+they were arguments to the \fI\s-1PUTVAL\s0\fR command. When the \fI\s-1PUTNOTIF\s0\fR command was
+implemented, this behavior was kept for lines which start with an unknown
+command for backwards compatibility. This compatibility code has been removed
+in \fIcollectd\ 5\fR.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-perl\fR\|(5),
+\&\fIcollectd\-unixsock\fR\|(5),
+\&\fIfork\fR\|(2), \fIexec\fR\|(3)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo@collectd.org>
diff --git a/src/collectd-exec.pod b/src/collectd-exec.pod
new file mode 100644 (file)
index 0000000..10f9f61
--- /dev/null
@@ -0,0 +1,311 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-exec - Documentation of collectd's C<exec plugin>
+
+=head1 SYNOPSIS
+
+  # See collectd.conf(5)
+  LoadPlugin exec
+  # ...
+  <Plugin exec>
+    Exec "myuser:mygroup" "myprog"
+    Exec "otheruser" "/path/to/another/binary" "arg0" "arg1"
+    NotificationExec "user" "/usr/lib/collectd/exec/handle_notification"
+  </Plugin>
+
+=head1 DESCRIPTION
+
+The C<exec plugin> forks of an executable either to receive values or to
+dispatch notifications to the outside world. The syntax of the configuration is
+explained in L<collectd.conf(5)> but summarized in the above synopsis.
+
+If you want/need better performance or more functionality you should take a
+long look at the C<perl plugin>, L<collectd-perl(5)>.
+
+=head1 EXECUTABLE TYPES
+
+There are currently two types of executables that can be executed by the
+C<exec plugin>:
+
+=over 4
+
+=item C<Exec>
+
+These programs are forked and values that it writes to C<STDOUT> are read back.
+The executable is forked in a fashion similar to L<init>: It is forked once and
+not again until it exits. If it exited, it will be forked again after at most
+I<Interval> seconds. It is perfectly legal for the executable to run for a long
+time and continuously write values to C<STDOUT>.
+
+See L<EXEC DATA FORMAT> below for a description of the output format expected
+from these programs.
+
+B<Warning:> If the executable only writes one value and then exits I will be
+executed every I<Interval> seconds. If I<Interval> is short (the default is 10
+seconds) this may result in serious system load.
+
+=item C<NotificationExec>
+
+The program is forked once for each notification that is handled by the daemon.
+The notification is passed to the program on C<STDIN> in a fashion similar to
+HTTP-headers. In contrast to programs specified with C<Exec> the execution of
+this program is not serialized, so that several instances of this program may
+run at once if multiple notifications are received.
+
+See L<NOTIFICATION DATA FORMAT> below for a description of the data passed to
+these programs.
+
+=back
+
+=head1 EXEC DATA FORMAT
+
+The forked executable is expected to print values to C<STDOUT>. The expected
+format is as follows:
+
+=over 4
+
+=item Comments
+
+Each line beginning with a C<#> (hash mark) is ignored.
+
+=item B<PUTVAL> I<Identifier> [I<OptionList>] I<Valuelist>
+
+Submits one or more values (identified by I<Identifier>, see below) to the
+daemon which will dispatch it to all it's write-plugins.
+
+An I<Identifier> is of the form
+C<I<host>B</>I<plugin>B<->I<instance>B</>I<type>B<->I<instance>> with both
+I<instance>-parts being optional. If they're omitted the hyphen must be
+omitted, too. I<plugin> and each I<instance>-part may be chosen freely as long
+as the tuple (plugin, plugin instance, type instance) uniquely identifies the
+plugin within collectd. I<type> identifies the type and number of values
+(i.E<nbsp>e. data-set) passed to collectd. A large list of predefined
+data-sets is available in the B<types.db> file. See L<types.db(5)> for a
+description of the format of this file.
+
+The I<OptionList> is an optional list of I<Options>, where each option is a
+key-value-pair. A list of currently understood options can be found below, all
+other options will be ignored. Values that contain spaces must be quoted with
+double quotes.
+
+I<Valuelist> is a colon-separated list of the time and the values, each either
+an integer if the data-source is a counter, or a double if the data-source is
+of type "gauge". You can submit an undefined gauge-value by using B<U>. When
+submitting B<U> to a counter the behavior is undefined. The time is given as
+epoch (i.E<nbsp>e. standard UNIX time).
+
+You can mix options and values, but the order is important: Options only
+effect following values, so specifying an option as last field is allowed, but
+useless. Also, an option applies to B<all> following values, so you don't need
+to re-set an option over and over again.
+
+The currently defined B<Options> are:
+
+=over 4
+
+=item B<interval=>I<seconds>
+
+Gives the interval in which the data identified by I<Identifier> is being
+collected.
+
+=back
+
+Please note that this is the same format as used in the B<unixsock plugin>, see
+L<collectd-unixsock(5)>. There's also a bit more information on identifiers in
+case you're confused.
+
+Since examples usually let one understand a lot better, here are some:
+
+  PUTVAL leeloo/cpu-0/cpu-idle N:2299366
+  PUTVAL alice/interface/if_octets-eth0 interval=10 1180647081:421465:479194
+
+=item B<PUTNOTIF> [I<OptionList>] B<message=>I<Message>
+
+Submits a notification to the daemon which will then dispatch it to all plugins
+which have registered for receiving notifications. 
+
+The B<PUTNOTIF> if followed by a list of options which further describe the
+notification. The B<message> option is special in that it will consume the rest
+of the line as its value. The B<message>, B<severity>, and B<time> options are
+mandatory.
+
+Valid options are:
+
+=over 4
+
+=item B<message=>I<Message> (B<REQUIRED>)
+
+Sets the message of the notification. This is the message that will be made
+accessible to the user, so it should contain some useful information. As with
+all options: If the message includes spaces, it must be quoted with double
+quotes. This option is mandatory.
+
+=item B<severity=failure>|B<warning>|B<okay> (B<REQUIRED>)
+
+Sets the severity of the notification. This option is mandatory.
+
+=item B<time=>I<Time> (B<REQUIRED>)
+
+Sets the time of the notification. The time is given as "epoch", i.E<nbsp>e. as
+seconds since January 1st, 1970, 00:00:00. This option is mandatory.
+
+=item B<host=>I<Hostname>
+
+=item B<plugin=>I<Plugin>
+
+=item B<plugin_instance=>I<Plugin-Instance>
+
+=item B<type=>I<Type>
+
+=item B<type_instance=>I<Type-Instance>
+
+These "associative" options establish a relation between this notification and
+collected performance data. This connection is purely informal, i.E<nbsp>e. the
+daemon itself doesn't do anything with this information. However, websites or
+GUIs may use this information to place notifications near the affected graph or
+table. All the options are optional, but B<plugin_instance> without B<plugin>
+or B<type_instance> without B<type> doesn't make much sense and should be
+avoided.
+
+=item B<type:key=>I<value>
+
+Sets user defined meta information. The B<type> key is a single character
+defining the type of the meta information.
+
+The current supported types are:
+
+=over 8
+
+=item B<s> A string passed as-is.
+
+=back
+
+=back
+
+=back
+
+Please note that this is the same format as used in the B<unixsock plugin>, see
+L<collectd-unixsock(5)>.
+
+When collectd exits it sends a B<SIGTERM> to all still running
+child-processes upon which they have to quit.
+
+=head1 NOTIFICATION DATA FORMAT
+
+The notification executables receive values rather than providing them. In
+fact, after the program is started C<STDOUT> is connected to C</dev/null>.
+
+The data is passed to the executables over C<STDIN> in a format very similar to
+HTTP: At first there is a "header" with one line per field. Every line consists
+of a field name, ended by a colon, and the associated value until end-of-line.
+The "header" is ended by two newlines immediately following another,
+i.e. an empty line. The rest, basically the "body", is the message of the
+notification.
+
+The following is an example notification passed to a program:
+
+  Severity: FAILURE
+  Time: 1200928930.515
+  Host: myhost.mydomain.org
+  \n
+  This is a test notification to demonstrate the format
+
+The following header files are currently used. Please note, however, that you
+should ignore unknown header files to be as forward-compatible as possible.
+
+=over 4
+
+=item B<Severity>
+
+Severity of the notification. May either be B<FAILURE>, B<WARNING>, or B<OKAY>.
+
+=item B<Time>
+
+The time in epoch, i.e. as seconds since 1970-01-01 00:00:00 UTC. The value
+currently has millisecond precision (i.e. three decimal places), but scripts
+should accept arbitrary numbers of decimal places, including no decimal places.
+
+=item B<Host>
+
+=item B<Plugin>
+
+=item B<PluginInstance>
+
+=item B<Type>
+
+=item B<TypeInstance>
+
+Identification of the performance data this notification is associated with.
+All of these fields are optional because notifications do not B<need> to be
+associated with a certain value.
+
+=back
+
+=head1 ENVIRONMENT
+
+The following environment variables are set by the plugin before calling
+I<exec>:
+
+=over 4
+
+=item COLLECTD_INTERVAL
+
+Value of the global interval setting.
+
+=item COLLECTD_HOSTNAME
+
+Hostname used by I<collectd> to dispatch local values.
+
+=back
+
+=head1 USING NAGIOS PLUGINS
+
+Though the interface is far from perfect, there are tons of plugins for Nagios.
+You can use these plugins with collectd by using a simple transition layer,
+C<exec-nagios.px>, which is shipped with the collectd distribution in the
+C<contrib/> directory. It is a simple Perl script that comes with embedded
+documentation. To see it, run the following command:
+
+  perldoc exec-nagios.px
+
+This script expects a configuration file, C<exec-nagios.conf>. You can find an
+example in the C<contrib/> directory, too.
+
+Even a simple mechanism to submit "performance data" to collectd is
+implemented. If you need a more sophisticated setup, please rewrite the plugin
+to make use of collectd's more powerful interface.
+
+=head1 CAVEATS
+
+=over 4
+
+=item
+
+The user, the binary is executed as, may not have root privileges, i.E<nbsp>e.
+must have an UID that is non-zero. This is for your own good.
+
+=item
+
+Early versions of the plugin did not use a command but treated all lines as if
+they were arguments to the I<PUTVAL> command. When the I<PUTNOTIF> command was
+implemented, this behavior was kept for lines which start with an unknown
+command for backwards compatibility. This compatibility code has been removed
+in I<collectdE<nbsp>5>.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-perl(5)>,
+L<collectd-unixsock(5)>,
+L<fork(2)>, L<exec(3)>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octo@collectd.orgE<gt>
+
+=cut
diff --git a/src/collectd-java.5 b/src/collectd-java.5
new file mode 100644 (file)
index 0000000..2eaf391
--- /dev/null
@@ -0,0 +1,741 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-JAVA 5"
+.TH COLLECTD-JAVA 5 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-java \- Documentation of collectd's "java plugin"
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 4
+\& LoadPlugin "java"
+\& <Plugin "java">
+\&   JVMArg "\-verbose:jni"
+\&   JVMArg "\-Djava.class.path=/opt/collectd/lib/collectd/bindings/java"
+\&   
+\&   LoadPlugin "org.collectd.java.Foobar"
+\&   <Plugin "org.collectd.java.Foobar">
+\&     # To be parsed by the plugin
+\&   </Plugin>
+\& </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \fIJava\fR plugin embeds a \fIJava Virtual Machine\fR (\s-1JVM\s0) into \fIcollectd\fR and
+provides a Java interface to part of collectd's \s-1API.\s0 This makes it possible to
+write additions to the daemon in Java.
+.PP
+This plugin is similar in nature to, but shares no code with, the \fIPerl\fR
+plugin by Sebastian Harl, see \fIcollectd\-perl\fR\|(5) for details.
+.SH "CONFIGURATION"
+.IX Header "CONFIGURATION"
+A short outline of this plugin's configuration can be seen in \*(L"\s-1SYNOPSIS\*(R"\s0
+above. For a complete list of all configuration options and their semantics
+please read "Plugin \f(CW\*(C`java\*(C'\fR" in \fIcollectd.conf\fR\|(5).
+.SH "OVERVIEW"
+.IX Header "OVERVIEW"
+When writing additions for collectd in Java, the underlying C base is mostly
+hidden from you. All complex data types are converted to their Java counterparts
+before they're passed to your functions. These Java classes reside in the
+\&\fIorg.collectd.api\fR namespace.
+.PP
+The \fIJava\fR plugin will create one object of each class configured with the
+\&\fBLoadPlugin\fR option. The constructor of this class can then register \*(L"callback
+methods\*(R", i.\ e. methods that will be called by the daemon when
+appropriate.
+.PP
+The available classes are:
+.IP "\fBorg.collectd.api.Collectd\fR" 4
+.IX Item "org.collectd.api.Collectd"
+All \s-1API\s0 functions exported to Java are implemented as static functions of this
+class. See \*(L"\s-1EXPORTED API FUNCTIONS\*(R"\s0 below.
+.IP "\fBorg.collectd.api.OConfigValue\fR" 4
+.IX Item "org.collectd.api.OConfigValue"
+Corresponds to \f(CW\*(C`oconfig_value_t\*(C'\fR, defined in \fIsrc/liboconfig/oconfig.h\fR.
+.IP "\fBorg.collectd.api.OConfigItem\fR" 4
+.IX Item "org.collectd.api.OConfigItem"
+Corresponds to \f(CW\*(C`oconfig_item_t\*(C'\fR, defined in \fIsrc/liboconfig/oconfig.h\fR.
+.IP "\fBorg.collectd.api.DataSource\fR" 4
+.IX Item "org.collectd.api.DataSource"
+Corresponds to \f(CW\*(C`data_source_t\*(C'\fR, defined in \fIsrc/plugin.h\fR.
+.IP "\fBorg.collectd.api.DataSet\fR" 4
+.IX Item "org.collectd.api.DataSet"
+Corresponds to \f(CW\*(C`data_set_t\*(C'\fR, defined in \fIsrc/plugin.h\fR.
+.IP "\fBorg.collectd.api.ValueList\fR" 4
+.IX Item "org.collectd.api.ValueList"
+Corresponds to \f(CW\*(C`value_list_t\*(C'\fR, defined in \fIsrc/plugin.h\fR.
+.IP "\fBorg.collectd.api.Notification\fR" 4
+.IX Item "org.collectd.api.Notification"
+Corresponds to \f(CW\*(C`notification_t\*(C'\fR, defined in \fIsrc/plugin.h\fR.
+.PP
+In the remainder of this document, we'll use the short form of these names, for
+example \fBValueList\fR. In order to be able to use these abbreviated names, you
+need to \fBimport\fR the classes.
+.SH "EXPORTED API FUNCTIONS"
+.IX Header "EXPORTED API FUNCTIONS"
+All collectd \s-1API\s0 functions that are available to Java plugins are implemented
+as \fIpublic\ static\fR functions of the \fBCollectd\fR class. This makes
+calling these functions pretty straight forward. For example, to send an error
+message to the daemon, you'd do something like this:
+.PP
+.Vb 1
+\&  Collectd.logError ("That wasn\*(Aqt chicken!");
+.Ve
+.PP
+The following are the currently exported functions.
+.SS "registerConfig"
+.IX Subsection "registerConfig"
+Signature: \fIint\fR \fBregisterConfig\fR (\fIString\fR name,
+\&\fICollectdConfigInterface\fR object);
+.PP
+Registers the \fBconfig\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"config callback\*(R" below.
+.SS "registerInit"
+.IX Subsection "registerInit"
+Signature: \fIint\fR \fBregisterInit\fR (\fIString\fR name,
+\&\fICollectdInitInterface\fR object);
+.PP
+Registers the \fBinit\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"init callback\*(R" below.
+.SS "registerRead"
+.IX Subsection "registerRead"
+Signature: \fIint\fR \fBregisterRead\fR (\fIString\fR name,
+\&\fICollectdReadInterface\fR object)
+.PP
+Registers the \fBread\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"read callback\*(R" below.
+.SS "registerWrite"
+.IX Subsection "registerWrite"
+Signature: \fIint\fR \fBregisterWrite\fR (\fIString\fR name,
+\&\fICollectdWriteInterface\fR object)
+.PP
+Registers the \fBwrite\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"write callback\*(R" below.
+.SS "registerFlush"
+.IX Subsection "registerFlush"
+Signature: \fIint\fR \fBregisterFlush\fR (\fIString\fR name,
+\&\fICollectdFlushInterface\fR object)
+.PP
+Registers the \fBflush\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"flush callback\*(R" below.
+.SS "registerShutdown"
+.IX Subsection "registerShutdown"
+Signature: \fIint\fR \fBregisterShutdown\fR (\fIString\fR name,
+\&\fICollectdShutdownInterface\fR object);
+.PP
+Registers the \fBshutdown\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"shutdown callback\*(R" below.
+.SS "registerLog"
+.IX Subsection "registerLog"
+Signature: \fIint\fR \fBregisterLog\fR (\fIString\fR name,
+\&\fICollectdLogInterface\fR object);
+.PP
+Registers the \fBlog\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"log callback\*(R" below.
+.SS "registerNotification"
+.IX Subsection "registerNotification"
+Signature: \fIint\fR \fBregisterNotification\fR (\fIString\fR name,
+\&\fICollectdNotificationInterface\fR object);
+.PP
+Registers the \fBnotification\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"notification callback\*(R" below.
+.SS "registerMatch"
+.IX Subsection "registerMatch"
+Signature: \fIint\fR \fBregisterMatch\fR (\fIString\fR name,
+\&\fICollectdMatchFactoryInterface\fR object);
+.PP
+Registers the \fBcreateMatch\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"match callback\*(R" below.
+.SS "registerTarget"
+.IX Subsection "registerTarget"
+Signature: \fIint\fR \fBregisterTarget\fR (\fIString\fR name,
+\&\fICollectdTargetFactoryInterface\fR object);
+.PP
+Registers the \fBcreateTarget\fR function of \fIobject\fR with the daemon.
+.PP
+Returns zero upon success and non-zero when an error occurred.
+.PP
+See \*(L"target callback\*(R" below.
+.SS "dispatchValues"
+.IX Subsection "dispatchValues"
+Signature: \fIint\fR \fBdispatchValues\fR (\fIValueList\fR)
+.PP
+Passes the values represented by the \fBValueList\fR object to the
+\&\f(CW\*(C`plugin_dispatch_values\*(C'\fR function of the daemon. The \*(L"data set\*(R" (or list of
+\&\*(L"data sources\*(R") associated with the object are ignored, because
+\&\f(CW\*(C`plugin_dispatch_values\*(C'\fR will automatically lookup the required data set. It
+is therefore absolutely okay to leave this blank.
+.PP
+Returns zero upon success or non-zero upon failure.
+.SS "getDS"
+.IX Subsection "getDS"
+Signature: \fIDataSet\fR \fBgetDS\fR (\fIString\fR)
+.PP
+Returns the appropriate \fItype\fR or \fBnull\fR if the type is not defined.
+.SS "logError"
+.IX Subsection "logError"
+Signature: \fIvoid\fR \fBlogError\fR (\fIString\fR)
+.PP
+Sends a log message with severity \fB\s-1ERROR\s0\fR to the daemon.
+.SS "logWarning"
+.IX Subsection "logWarning"
+Signature: \fIvoid\fR \fBlogWarning\fR (\fIString\fR)
+.PP
+Sends a log message with severity \fB\s-1WARNING\s0\fR to the daemon.
+.SS "logNotice"
+.IX Subsection "logNotice"
+Signature: \fIvoid\fR \fBlogNotice\fR (\fIString\fR)
+.PP
+Sends a log message with severity \fB\s-1NOTICE\s0\fR to the daemon.
+.SS "logInfo"
+.IX Subsection "logInfo"
+Signature: \fIvoid\fR \fBlogInfo\fR (\fIString\fR)
+.PP
+Sends a log message with severity \fB\s-1INFO\s0\fR to the daemon.
+.SS "logDebug"
+.IX Subsection "logDebug"
+Signature: \fIvoid\fR \fBlogDebug\fR (\fIString\fR)
+.PP
+Sends a log message with severity \fB\s-1DEBUG\s0\fR to the daemon.
+.SH "REGISTERING CALLBACKS"
+.IX Header "REGISTERING CALLBACKS"
+When starting up, collectd creates an object of each configured class. The
+constructor of this class should then register \*(L"callbacks\*(R" with the daemon,
+using the appropriate static functions in \fBCollectd\fR,
+see \*(L"\s-1EXPORTED API FUNCTIONS\*(R"\s0 above. To register a callback, the object being
+passed to one of the register functions must implement an appropriate
+interface, which are all in the \fBorg.collectd.api\fR namespace.
+.PP
+A constructor may register any number of these callbacks, even none. An object
+without callback methods is never actively called by collectd, but may still
+call the exported \s-1API\s0 functions. One could, for example, start a new thread in
+the constructor and dispatch (submit to the daemon) values asynchronously,
+whenever one is available.
+.PP
+Each callback method is now explained in more detail:
+.SS "config callback"
+.IX Subsection "config callback"
+Interface: \fBorg.collectd.api.CollectdConfigInterface\fR
+.PP
+Signature: \fIint\fR \fBconfig\fR (\fIOConfigItem\fR ci)
+.PP
+This method is passed a \fBOConfigItem\fR object, if both, method and
+configuration, are available. \fBOConfigItem\fR is the root of a tree representing
+the configuration for this plugin. The root itself is the representation of the
+\&\fB<Plugin\ />\fR block, so in next to all cases the children of the
+root are the first interesting objects.
+.PP
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and the plugin will be disabled entirely.
+.PP
+See \*(L"registerConfig\*(R" above.
+.SS "init callback"
+.IX Subsection "init callback"
+Interface: \fBorg.collectd.api.CollectdInitInterface\fR
+.PP
+Signature: \fIint\fR \fBinit\fR ()
+.PP
+This method is called after the configuration has been handled. It is
+supposed to set up the plugin. e.\ g. start threads, open connections, or
+check if can do anything useful at all.
+.PP
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and the plugin will be disabled entirely.
+.PP
+See \*(L"registerInit\*(R" above.
+.SS "read callback"
+.IX Subsection "read callback"
+Interface: \fBorg.collectd.api.CollectdReadInterface\fR
+.PP
+Signature: \fIint\fR \fBread\fR ()
+.PP
+This method is called periodically and is supposed to gather statistics in
+whatever fashion. These statistics are represented as a \fBValueList\fR object and
+sent to the daemon using dispatchValues.
+.PP
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+Currently, returning non-zero does not have any other effects. In particular,
+Java \*(L"read\*(R"\-methods are not suspended for increasing intervals like C
+\&\*(L"read\*(R"\-functions.
+.PP
+See \*(L"registerRead\*(R" above.
+.SS "write callback"
+.IX Subsection "write callback"
+Interface: \fBorg.collectd.api.CollectdWriteInterface\fR
+.PP
+Signature: \fIint\fR \fBwrite\fR (\fIValueList\fR vl)
+.PP
+This method is called whenever a value is dispatched to the daemon. The
+corresponding C \*(L"write\*(R"\-functions are passed a \f(CW\*(C`data_set_t\*(C'\fR, so they can
+decide which values are absolute values (gauge) and which are counter values.
+To get the corresponding \f(CW\*(C`List<DataSource>\*(C'\fR, call the \fBgetDataSource\fR
+method of the \fBValueList\fR object.
+.PP
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+.PP
+See \*(L"registerWrite\*(R" above.
+.SS "flush callback"
+.IX Subsection "flush callback"
+Interface: \fBorg.collectd.api.CollectdFlushInterface\fR
+.PP
+Signature: \fIint\fR \fBflush\fR (\fIint\fR timeout, \fIString\fR identifier)
+.PP
+This method is called when the daemon received a flush command. This can either
+be done using the \f(CW\*(C`USR1\*(C'\fR signal (see \fIcollectd\fR\|(1)) or using the \fIunixsock\fR
+plugin (see \fIcollectd\-unixsock\fR\|(5)).
+.PP
+If \fItimeout\fR is greater than zero, only values older than this number of
+seconds should be flushed. To signal that all values should be flushed
+regardless of age, this argument is set to a negative number.
+.PP
+The \fIidentifier\fR specifies which value should be flushed. If it is not
+possible to flush one specific value, flush all values. To signal that all
+values should be flushed, this argument is set to \fInull\fR.
+.PP
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+.PP
+See \*(L"registerFlush\*(R" above.
+.SS "shutdown callback"
+.IX Subsection "shutdown callback"
+Interface: \fBorg.collectd.api.CollectdShutdownInterface\fR
+.PP
+Signature: \fIint\fR \fBshutdown\fR ()
+.PP
+This method is called when the daemon is shutting down. You should not rely on
+the destructor to clean up behind the object but use this function instead.
+.PP
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+.PP
+See \*(L"registerShutdown\*(R" above.
+.SS "log callback"
+.IX Subsection "log callback"
+Interface: \fBorg.collectd.api.CollectdLogInterface\fR
+.PP
+Signature: \fIvoid\fR \fBlog\fR (\fIint\fR severity, \fIString\fR message)
+.PP
+This callback can be used to receive log messages from the daemon.
+.PP
+The argument \fIseverity\fR is one of:
+.IP "\(bu" 4
+org.collectd.api.Collectd.LOG_ERR
+.IP "\(bu" 4
+org.collectd.api.Collectd.LOG_WARNING
+.IP "\(bu" 4
+org.collectd.api.Collectd.LOG_NOTICE
+.IP "\(bu" 4
+org.collectd.api.Collectd.LOG_INFO
+.IP "\(bu" 4
+org.collectd.api.Collectd.LOG_DEBUG
+.PP
+The function does not return any value.
+.PP
+See \*(L"registerLog\*(R" above.
+.SS "notification callback"
+.IX Subsection "notification callback"
+Interface: \fBorg.collectd.api.CollectdNotificationInterface\fR
+.PP
+Signature: \fIint\fR \fBnotification\fR (\fINotification\fR n)
+.PP
+This callback can be used to receive notifications from the daemon.
+.PP
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+.PP
+See \*(L"registerNotification\*(R" above.
+.SS "match callback"
+.IX Subsection "match callback"
+The match (and target, see \*(L"target callback\*(R" below) callbacks work a bit
+different from the other callbacks above: You don't register a match callback
+with the daemon directly, but you register a function which, when called,
+creates an appropriate object. The object creating the \*(L"match\*(R" objects is
+called \*(L"match factory\*(R".
+.PP
+See \*(L"registerMatch\*(R" above.
+.PP
+\fIFactory object\fR
+.IX Subsection "Factory object"
+.PP
+Interface: \fBorg.collectd.api.CollectdMatchFactoryInterface\fR
+.PP
+Signature: \fICollectdMatchInterface\fR \fBcreateMatch\fR
+(\fIOConfigItem\fR ci);
+.PP
+Called by the daemon to create \*(L"match\*(R" objects.
+.PP
+Returns: A new object which implements the \fBCollectdMatchInterface\fR interface.
+.PP
+\fIMatch object\fR
+.IX Subsection "Match object"
+.PP
+Interface: \fBorg.collectd.api.CollectdMatchInterface\fR
+.PP
+Signature: \fIint\fR \fBmatch\fR (\fIDataSet\fR ds, \fIValueList\fR vl);
+.PP
+Called when processing a chain to determine whether or not a \fIValueList\fR
+matches. How values are matches is up to the implementing class.
+.PP
+Has to return one of:
+.IP "\(bu" 4
+\&\fBCollectd.FC_MATCH_NO_MATCH\fR
+.IP "\(bu" 4
+\&\fBCollectd.FC_MATCH_MATCHES\fR
+.SS "target callback"
+.IX Subsection "target callback"
+The target (and match, see \*(L"match callback\*(R" above) callbacks work a bit
+different from the other callbacks above: You don't register a target callback
+with the daemon directly, but you register a function which, when called,
+creates an appropriate object. The object creating the \*(L"target\*(R" objects is
+called \*(L"target factory\*(R".
+.PP
+See \*(L"registerTarget\*(R" above.
+.PP
+\fIFactory object\fR
+.IX Subsection "Factory object"
+.PP
+Interface: \fBorg.collectd.api.CollectdTargetFactoryInterface\fR
+.PP
+Signature: \fICollectdTargetInterface\fR \fBcreateTarget\fR
+(\fIOConfigItem\fR ci);
+.PP
+Called by the daemon to create \*(L"target\*(R" objects.
+.PP
+Returns: A new object which implements the \fBCollectdTargetInterface\fR
+interface.
+.PP
+\fITarget object\fR
+.IX Subsection "Target object"
+.PP
+Interface: \fBorg.collectd.api.CollectdTargetInterface\fR
+.PP
+Signature: \fIint\fR \fBinvoke\fR (\fIDataSet\fR ds, \fIValueList\fR vl);
+.PP
+Called when processing a chain to perform some action. The action performed is
+up to the implementing class.
+.PP
+Has to return one of:
+.IP "\(bu" 4
+\&\fBCollectd.FC_TARGET_CONTINUE\fR
+.IP "\(bu" 4
+\&\fBCollectd.FC_TARGET_STOP\fR
+.IP "\(bu" 4
+\&\fBCollectd.FC_TARGET_RETURN\fR
+.SH "EXAMPLE"
+.IX Header "EXAMPLE"
+This short example demonstrates how to register a read callback with the
+daemon:
+.PP
+.Vb 2
+\&  import org.collectd.api.Collectd;
+\&  import org.collectd.api.ValueList;
+\&  
+\&  import org.collectd.api.CollectdReadInterface;
+\&  
+\&  public class Foobar implements CollectdReadInterface
+\&  {
+\&    public Foobar ()
+\&    {
+\&      Collectd.registerRead ("Foobar", this);
+\&    }
+\&    
+\&    public int read ()
+\&    {
+\&      ValueList vl;
+\&      
+\&      /* Do something... */
+\&      
+\&      Collectd.dispatchValues (vl);
+\&    }
+\&  }
+.Ve
+.SH "PLUGINS"
+.IX Header "PLUGINS"
+The following plugins are implemented in \fIJava\fR. Both, the \fBLoadPlugin\fR
+option and the \fBPlugin\fR block must be inside the
+\&\fB<Plugin\ java>\fR block (see above).
+.SS "GenericJMX plugin"
+.IX Subsection "GenericJMX plugin"
+The GenericJMX plugin reads \fIManaged Beans\fR (MBeans) from an \fIMBeanServer\fR
+using \s-1JMX. JMX\s0 is a generic framework to provide and query various management
+information. The interface is used by Java processes to provide internal
+statistics as well as by the \fIJava Virtual Machine\fR (\s-1JVM\s0) to provide
+information about the memory used, threads and so on.
+.PP
+The configuration of the \fIGenericJMX plugin\fR consists of two blocks: \fIMBean\fR
+blocks that define a mapping of MBean attributes to the XtypesX used by
+\&\fIcollectd\fR, and \fIConnection\fR blocks which define the parameters needed to
+connect to an \fIMBeanServer\fR and what data to collect. The configuration of the
+\&\fI\s-1SNMP\s0 plugin\fR is similar in nature, in case you know it.
+.PP
+\fIMBean blocks\fR
+.IX Subsection "MBean blocks"
+.PP
+\&\fIMBean\fR blocks specify what data is retrieved from \fIMBeans\fR and how that data
+is mapped on the \fIcollectd\fR data types. The block requires one string
+argument, a name. This name is used in the \fIConnection\fR blocks (see below) to
+refer to a specific \fIMBean\fR block. Therefore, the names must be unique.
+.PP
+The following options are recognized within \fIMBean\fR blocks:
+.IP "\fBObjectName\fR \fIpattern\fR" 4
+.IX Item "ObjectName pattern"
+Sets the pattern which is used to retrieve \fIMBeans\fR from the \fIMBeanServer\fR.
+If more than one MBean is returned you should use the \fBInstanceFrom\fR option
+(see below) to make the identifiers unique.
+.Sp
+See also:
+<http://java.sun.com/javase/6/docs/api/javax/management/ObjectName.html>
+.IP "\fBInstancePrefix\fR \fIprefix\fR" 4
+.IX Item "InstancePrefix prefix"
+Prefixes the generated \fIplugin instance\fR with \fIprefix\fR. \fI(optional)\fR
+.IP "\fBInstanceFrom\fR \fIproperty\fR" 4
+.IX Item "InstanceFrom property"
+The \fIobject names\fR used by \s-1JMX\s0 to identify \fIMBeans\fR include so called
+\&\fIXpropertiesX\fR which are basically key-value-pairs. If the given object name
+is not unique and multiple MBeans are returned, the values of those properties
+usually differ. You can use this option to build the \fIplugin instance\fR from
+the appropriate property values. This option is optional and may be repeated to
+generate the \fIplugin instance\fR from multiple property values.
+.IP "\fB<value />\fR blocks" 4
+.IX Item "<value /> blocks"
+The \fIvalue\fR blocks map one or more attributes of an \fIMBean\fR to a value list
+in \fIcollectd\fR. There must be at least one Value block within each \fIMBean\fR
+block.
+.RS 4
+.IP "\fBType\fR type" 4
+.IX Item "Type type"
+Sets the data set used within \fIcollectd\fR to handle the values of the \fIMBean\fR
+attribute.
+.IP "\fBInstancePrefix\fR \fIprefix\fR" 4
+.IX Item "InstancePrefix prefix"
+Works like the option of the same name directly beneath the \fIMBean\fR block, but
+sets the type instance instead. \fI(optional)\fR
+.IP "\fBInstanceFrom\fR \fIprefix\fR" 4
+.IX Item "InstanceFrom prefix"
+Works like the option of the same name directly beneath the \fIMBean\fR block, but
+sets the type instance instead. \fI(optional)\fR
+.IP "\fBTable\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Table true|false"
+Set this to true if the returned attribute is a \fIcomposite type\fR. If set to
+true, the keys within the \fIcomposite type\fR is appended to the
+\&\fItype instance\fR.
+.IP "\fBAttribute\fR \fIpath\fR" 4
+.IX Item "Attribute path"
+Sets the name of the attribute from which to read the value. You can access the
+keys of composite types by using a dot to concatenate the key name to the
+attribute name. For example: Xattrib0.key42X. If \fBTable\fR is set to \fBtrue\fR
+\&\fIpath\fR must point to a \fIcomposite type\fR, otherwise it must point to a numeric
+type.
+.RE
+.RS 4
+.RE
+.PP
+\fIConnection blocks\fR
+.IX Subsection "Connection blocks"
+.PP
+Connection blocks specify \fIhow\fR to connect to an \fIMBeanServer\fR and what data
+to retrieve. The following configuration options are available:
+.IP "\fBHost\fR \fIname\fR" 4
+.IX Item "Host name"
+Host name used when dispatching the values to \fIcollectd\fR. The option sets this
+field only, it is \fInot\fR used to connect to anything and doesn't need to be a
+real, resolvable name.
+.IP "\fBServiceURL\fR \fI\s-1URL\s0\fR" 4
+.IX Item "ServiceURL URL"
+Specifies how the \fIMBeanServer\fR can be reached. Any string accepted by the
+\&\fIJMXServiceURL\fR is valid.
+.Sp
+See also:
+<http://java.sun.com/javase/6/docs/api/javax/management/remote/JMXServiceURL.html>
+.IP "\fBUser\fR \fIname\fR" 4
+.IX Item "User name"
+Use \fIname\fR to authenticate to the server. If not configured, XmonitorRoleX
+will be used.
+.IP "\fBPassword\fR \fIpassword\fR" 4
+.IX Item "Password password"
+Use \fIpassword\fR to authenticate to the server. If not given, unauthenticated
+access is used.
+.IP "\fBInstancePrefix\fR \fIprefix\fR" 4
+.IX Item "InstancePrefix prefix"
+Prefixes the generated \fIplugin instance\fR with \fIprefix\fR. If a second
+\&\fIInstancePrefix\fR is specified in a referenced \fIMBean\fR block, the prefix
+specified in the \fIConnection\fR block will appear at the beginning of the
+\&\fIplugin instance\fR, the prefix specified in the \fIMBean\fR block will be appended
+to it.
+.IP "\fBCollect\fR \fImbean_block_name\fR" 4
+.IX Item "Collect mbean_block_name"
+Configures which of the \fIMBean\fR blocks to use with this connection. May be
+repeated to collect multiple \fIMBeans\fR from this server.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-perl\fR\|(5),
+\&\fItypes.db\fR\|(5)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo\ at\ collectd.org>
diff --git a/src/collectd-java.pod b/src/collectd-java.pod
new file mode 100644 (file)
index 0000000..aade08a
--- /dev/null
@@ -0,0 +1,697 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-java - Documentation of collectd's "java plugin"
+
+=head1 SYNOPSIS
+
+ LoadPlugin "java"
+ <Plugin "java">
+   JVMArg "-verbose:jni"
+   JVMArg "-Djava.class.path=/opt/collectd/lib/collectd/bindings/java"
+   
+   LoadPlugin "org.collectd.java.Foobar"
+   <Plugin "org.collectd.java.Foobar">
+     # To be parsed by the plugin
+   </Plugin>
+ </Plugin>
+
+=head1 DESCRIPTION
+
+The I<Java> plugin embeds a I<Java Virtual Machine> (JVM) into I<collectd> and
+provides a Java interface to part of collectd's API. This makes it possible to
+write additions to the daemon in Java.
+
+This plugin is similar in nature to, but shares no code with, the I<Perl>
+plugin by Sebastian Harl, see L<collectd-perl(5)> for details.
+
+=head1 CONFIGURATION
+
+A short outline of this plugin's configuration can be seen in L<"SYNOPSIS">
+above. For a complete list of all configuration options and their semantics
+please read L<collectd.conf(5)/Plugin C<java>>.
+
+=head1 OVERVIEW
+
+When writing additions for collectd in Java, the underlying C base is mostly
+hidden from you. All complex data types are converted to their Java counterparts
+before they're passed to your functions. These Java classes reside in the
+I<org.collectd.api> namespace.
+
+The I<Java> plugin will create one object of each class configured with the
+B<LoadPlugin> option. The constructor of this class can then register "callback
+methods", i.E<nbsp>e. methods that will be called by the daemon when
+appropriate.
+
+The available classes are:
+
+=over 4
+
+=item B<org.collectd.api.Collectd>
+
+All API functions exported to Java are implemented as static functions of this
+class. See L<"EXPORTED API FUNCTIONS"> below.
+
+=item B<org.collectd.api.OConfigValue>
+
+Corresponds to C<oconfig_value_t>, defined in F<src/liboconfig/oconfig.h>.
+
+=item B<org.collectd.api.OConfigItem>
+
+Corresponds to C<oconfig_item_t>, defined in F<src/liboconfig/oconfig.h>.
+
+=item B<org.collectd.api.DataSource>
+
+Corresponds to C<data_source_t>, defined in F<src/plugin.h>.
+
+=item B<org.collectd.api.DataSet>
+
+Corresponds to C<data_set_t>, defined in F<src/plugin.h>.
+
+=item B<org.collectd.api.ValueList>
+
+Corresponds to C<value_list_t>, defined in F<src/plugin.h>.
+
+=item B<org.collectd.api.Notification>
+
+Corresponds to C<notification_t>, defined in F<src/plugin.h>.
+
+=back
+
+In the remainder of this document, we'll use the short form of these names, for
+example B<ValueList>. In order to be able to use these abbreviated names, you
+need to B<import> the classes.
+
+=head1 EXPORTED API FUNCTIONS
+
+All collectd API functions that are available to Java plugins are implemented
+as I<publicE<nbsp>static> functions of the B<Collectd> class. This makes
+calling these functions pretty straight forward. For example, to send an error
+message to the daemon, you'd do something like this:
+
+  Collectd.logError ("That wasn't chicken!");
+
+The following are the currently exported functions.
+
+=head2 registerConfig
+
+Signature: I<int> B<registerConfig> (I<String> name,
+I<CollectdConfigInterface> object);
+
+Registers the B<config> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"config callback"> below.
+
+=head2 registerInit
+
+Signature: I<int> B<registerInit> (I<String> name,
+I<CollectdInitInterface> object);
+
+Registers the B<init> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"init callback"> below.
+
+=head2 registerRead
+
+Signature: I<int> B<registerRead> (I<String> name,
+I<CollectdReadInterface> object)
+
+Registers the B<read> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"read callback"> below.
+
+=head2 registerWrite
+
+Signature: I<int> B<registerWrite> (I<String> name,
+I<CollectdWriteInterface> object)
+
+Registers the B<write> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"write callback"> below.
+
+=head2 registerFlush
+
+Signature: I<int> B<registerFlush> (I<String> name,
+I<CollectdFlushInterface> object)
+
+Registers the B<flush> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"flush callback"> below.
+
+=head2 registerShutdown
+
+Signature: I<int> B<registerShutdown> (I<String> name,
+I<CollectdShutdownInterface> object);
+
+Registers the B<shutdown> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"shutdown callback"> below.
+
+=head2 registerLog
+
+Signature: I<int> B<registerLog> (I<String> name,
+I<CollectdLogInterface> object);
+
+Registers the B<log> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"log callback"> below.
+
+=head2 registerNotification
+
+Signature: I<int> B<registerNotification> (I<String> name,
+I<CollectdNotificationInterface> object);
+
+Registers the B<notification> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"notification callback"> below.
+
+=head2 registerMatch
+
+Signature: I<int> B<registerMatch> (I<String> name,
+I<CollectdMatchFactoryInterface> object);
+
+Registers the B<createMatch> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"match callback"> below.
+
+=head2 registerTarget
+
+Signature: I<int> B<registerTarget> (I<String> name,
+I<CollectdTargetFactoryInterface> object);
+
+Registers the B<createTarget> function of I<object> with the daemon.
+
+Returns zero upon success and non-zero when an error occurred.
+
+See L<"target callback"> below.
+
+=head2 dispatchValues
+
+Signature: I<int> B<dispatchValues> (I<ValueList>)
+
+Passes the values represented by the B<ValueList> object to the
+C<plugin_dispatch_values> function of the daemon. The "data set" (or list of
+"data sources") associated with the object are ignored, because
+C<plugin_dispatch_values> will automatically lookup the required data set. It
+is therefore absolutely okay to leave this blank.
+
+Returns zero upon success or non-zero upon failure.
+
+=head2 getDS
+
+Signature: I<DataSet> B<getDS> (I<String>)
+
+Returns the appropriate I<type> or B<null> if the type is not defined.
+
+=head2 logError
+
+Signature: I<void> B<logError> (I<String>)
+
+Sends a log message with severity B<ERROR> to the daemon.
+
+=head2 logWarning
+
+Signature: I<void> B<logWarning> (I<String>)
+
+Sends a log message with severity B<WARNING> to the daemon.
+
+=head2 logNotice
+
+Signature: I<void> B<logNotice> (I<String>)
+
+Sends a log message with severity B<NOTICE> to the daemon.
+
+=head2 logInfo
+
+Signature: I<void> B<logInfo> (I<String>)
+
+Sends a log message with severity B<INFO> to the daemon.
+
+=head2 logDebug
+
+Signature: I<void> B<logDebug> (I<String>)
+
+Sends a log message with severity B<DEBUG> to the daemon.
+
+=head1 REGISTERING CALLBACKS
+
+When starting up, collectd creates an object of each configured class. The
+constructor of this class should then register "callbacks" with the daemon,
+using the appropriate static functions in B<Collectd>,
+see L<"EXPORTED API FUNCTIONS"> above. To register a callback, the object being
+passed to one of the register functions must implement an appropriate
+interface, which are all in the B<org.collectd.api> namespace.
+
+A constructor may register any number of these callbacks, even none. An object
+without callback methods is never actively called by collectd, but may still
+call the exported API functions. One could, for example, start a new thread in
+the constructor and dispatch (submit to the daemon) values asynchronously,
+whenever one is available.
+
+Each callback method is now explained in more detail:
+
+=head2 config callback
+
+Interface: B<org.collectd.api.CollectdConfigInterface>
+
+Signature: I<int> B<config> (I<OConfigItem> ci)
+
+This method is passed a B<OConfigItem> object, if both, method and
+configuration, are available. B<OConfigItem> is the root of a tree representing
+the configuration for this plugin. The root itself is the representation of the
+B<E<lt>PluginE<nbsp>/E<gt>> block, so in next to all cases the children of the
+root are the first interesting objects.
+
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and the plugin will be disabled entirely.
+
+See L<"registerConfig"> above.
+
+=head2 init callback
+
+Interface: B<org.collectd.api.CollectdInitInterface>
+
+Signature: I<int> B<init> ()
+
+This method is called after the configuration has been handled. It is
+supposed to set up the plugin. e.E<nbsp>g. start threads, open connections, or
+check if can do anything useful at all.
+
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and the plugin will be disabled entirely.
+
+See L<"registerInit"> above.
+
+=head2 read callback
+
+Interface: B<org.collectd.api.CollectdReadInterface>
+
+Signature: I<int> B<read> ()
+
+This method is called periodically and is supposed to gather statistics in
+whatever fashion. These statistics are represented as a B<ValueList> object and
+sent to the daemon using L<dispatchValues|"dispatchValues">.
+
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+Currently, returning non-zero does not have any other effects. In particular,
+Java "read"-methods are not suspended for increasing intervals like C
+"read"-functions.
+
+See L<"registerRead"> above.
+
+=head2 write callback
+
+Interface: B<org.collectd.api.CollectdWriteInterface>
+
+Signature: I<int> B<write> (I<ValueList> vl)
+
+This method is called whenever a value is dispatched to the daemon. The
+corresponding C "write"-functions are passed a C<data_set_t>, so they can
+decide which values are absolute values (gauge) and which are counter values.
+To get the corresponding C<ListE<lt>DataSourceE<gt>>, call the B<getDataSource>
+method of the B<ValueList> object.
+
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+
+See L<"registerWrite"> above.
+
+=head2 flush callback
+
+Interface: B<org.collectd.api.CollectdFlushInterface>
+
+Signature: I<int> B<flush> (I<int> timeout, I<String> identifier)
+
+This method is called when the daemon received a flush command. This can either
+be done using the C<USR1> signal (see L<collectd(1)>) or using the I<unixsock>
+plugin (see L<collectd-unixsock(5)>).
+
+If I<timeout> is greater than zero, only values older than this number of
+seconds should be flushed. To signal that all values should be flushed
+regardless of age, this argument is set to a negative number.
+
+The I<identifier> specifies which value should be flushed. If it is not
+possible to flush one specific value, flush all values. To signal that all
+values should be flushed, this argument is set to I<null>.
+
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+
+See L<"registerFlush"> above.
+
+=head2 shutdown callback
+
+Interface: B<org.collectd.api.CollectdShutdownInterface>
+
+Signature: I<int> B<shutdown> ()
+
+This method is called when the daemon is shutting down. You should not rely on
+the destructor to clean up behind the object but use this function instead.
+
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+
+See L<"registerShutdown"> above.
+
+=head2 log callback
+
+Interface: B<org.collectd.api.CollectdLogInterface>
+
+Signature: I<void> B<log> (I<int> severity, I<String> message)
+
+This callback can be used to receive log messages from the daemon.
+
+The argument I<severity> is one of:
+
+=over 4
+
+=item *
+
+org.collectd.api.Collectd.LOG_ERR
+
+=item *
+
+org.collectd.api.Collectd.LOG_WARNING
+
+=item *
+
+org.collectd.api.Collectd.LOG_NOTICE
+
+=item *
+
+org.collectd.api.Collectd.LOG_INFO
+
+=item *
+
+org.collectd.api.Collectd.LOG_DEBUG
+
+=back
+
+The function does not return any value.
+
+See L<"registerLog"> above.
+
+=head2 notification callback
+
+Interface: B<org.collectd.api.CollectdNotificationInterface>
+
+Signature: I<int> B<notification> (I<Notification> n)
+
+This callback can be used to receive notifications from the daemon.
+
+To signal success, this method has to return zero. Anything else will be
+considered an error condition and cause an appropriate message to be logged.
+
+See L<"registerNotification"> above.
+
+=head2 match callback
+
+The match (and target, see L<"target callback"> below) callbacks work a bit
+different from the other callbacks above: You don't register a match callback
+with the daemon directly, but you register a function which, when called,
+creates an appropriate object. The object creating the "match" objects is
+called "match factory".
+
+See L<"registerMatch"> above.
+
+=head3 Factory object
+
+Interface: B<org.collectd.api.CollectdMatchFactoryInterface>
+
+Signature: I<CollectdMatchInterface> B<createMatch>
+(I<OConfigItem> ci);
+
+Called by the daemon to create "match" objects.
+
+Returns: A new object which implements the B<CollectdMatchInterface> interface.
+
+=head3 Match object
+
+Interface: B<org.collectd.api.CollectdMatchInterface>
+
+Signature: I<int> B<match> (I<DataSet> ds, I<ValueList> vl);
+
+Called when processing a chain to determine whether or not a I<ValueList>
+matches. How values are matches is up to the implementing class.
+
+Has to return one of:
+
+=over 4
+
+=item *
+
+B<Collectd.FC_MATCH_NO_MATCH>
+
+=item *
+
+B<Collectd.FC_MATCH_MATCHES>
+
+=back
+
+=head2 target callback
+
+The target (and match, see L<"match callback"> above) callbacks work a bit
+different from the other callbacks above: You don't register a target callback
+with the daemon directly, but you register a function which, when called,
+creates an appropriate object. The object creating the "target" objects is
+called "target factory".
+
+See L<"registerTarget"> above.
+
+=head3 Factory object
+
+Interface: B<org.collectd.api.CollectdTargetFactoryInterface>
+
+Signature: I<CollectdTargetInterface> B<createTarget>
+(I<OConfigItem> ci);
+
+Called by the daemon to create "target" objects.
+
+Returns: A new object which implements the B<CollectdTargetInterface>
+interface.
+
+=head3 Target object
+
+Interface: B<org.collectd.api.CollectdTargetInterface>
+
+Signature: I<int> B<invoke> (I<DataSet> ds, I<ValueList> vl);
+
+Called when processing a chain to perform some action. The action performed is
+up to the implementing class.
+
+Has to return one of:
+
+=over 4
+
+=item *
+
+B<Collectd.FC_TARGET_CONTINUE>
+
+=item *
+
+B<Collectd.FC_TARGET_STOP>
+
+=item *
+
+B<Collectd.FC_TARGET_RETURN>
+
+=back
+
+=head1 EXAMPLE
+
+This short example demonstrates how to register a read callback with the
+daemon:
+
+  import org.collectd.api.Collectd;
+  import org.collectd.api.ValueList;
+  
+  import org.collectd.api.CollectdReadInterface;
+  
+  public class Foobar implements CollectdReadInterface
+  {
+    public Foobar ()
+    {
+      Collectd.registerRead ("Foobar", this);
+    }
+    
+    public int read ()
+    {
+      ValueList vl;
+      
+      /* Do something... */
+      
+      Collectd.dispatchValues (vl);
+    }
+  }
+
+=head1 PLUGINS
+
+The following plugins are implemented in I<Java>. Both, the B<LoadPlugin>
+option and the B<Plugin> block must be inside the
+B<E<lt>PluginE<nbsp>javaE<gt>> block (see above).
+
+=head2 GenericJMX plugin
+
+The GenericJMX plugin reads I<Managed Beans> (MBeans) from an I<MBeanServer>
+using JMX. JMX is a generic framework to provide and query various management
+information. The interface is used by Java processes to provide internal
+statistics as well as by the I<Java Virtual Machine> (JVM) to provide
+information about the memory used, threads and so on. 
+
+The configuration of the I<GenericJMX plugin> consists of two blocks: I<MBean>
+blocks that define a mapping of MBean attributes to the “types” used by
+I<collectd>, and I<Connection> blocks which define the parameters needed to
+connect to an I<MBeanServer> and what data to collect. The configuration of the
+I<SNMP plugin> is similar in nature, in case you know it.
+
+=head3   MBean blocks
+
+I<MBean> blocks specify what data is retrieved from I<MBeans> and how that data
+is mapped on the I<collectd> data types. The block requires one string
+argument, a name. This name is used in the I<Connection> blocks (see below) to
+refer to a specific I<MBean> block. Therefore, the names must be unique.
+
+The following options are recognized within I<MBean> blocks: 
+
+=over 4
+
+=item B<ObjectName> I<pattern>
+
+Sets the pattern which is used to retrieve I<MBeans> from the I<MBeanServer>.
+If more than one MBean is returned you should use the B<InstanceFrom> option
+(see below) to make the identifiers unique.
+
+See also:
+L<http://java.sun.com/javase/6/docs/api/javax/management/ObjectName.html>
+
+=item B<InstancePrefix> I<prefix>
+
+Prefixes the generated I<plugin instance> with I<prefix>. I<(optional)>
+
+=item B<InstanceFrom> I<property>
+
+The I<object names> used by JMX to identify I<MBeans> include so called
+I<“properties”> which are basically key-value-pairs. If the given object name
+is not unique and multiple MBeans are returned, the values of those properties
+usually differ. You can use this option to build the I<plugin instance> from
+the appropriate property values. This option is optional and may be repeated to
+generate the I<plugin instance> from multiple property values. 
+
+=item B<E<lt>value /E<gt>> blocks
+
+The I<value> blocks map one or more attributes of an I<MBean> to a value list
+in I<collectd>. There must be at least one Value block within each I<MBean>
+block.
+
+=over 4
+
+=item B<Type> type
+
+Sets the data set used within I<collectd> to handle the values of the I<MBean>
+attribute.
+
+=item B<InstancePrefix> I<prefix>
+
+Works like the option of the same name directly beneath the I<MBean> block, but
+sets the type instance instead. I<(optional)>
+
+=item B<InstanceFrom> I<prefix>
+
+Works like the option of the same name directly beneath the I<MBean> block, but
+sets the type instance instead. I<(optional)>
+
+=item B<Table> B<true>|B<false>
+
+Set this to true if the returned attribute is a I<composite type>. If set to
+true, the keys within the I<composite type> is appended to the
+I<type instance>.
+
+=item B<Attribute> I<path>
+
+Sets the name of the attribute from which to read the value. You can access the
+keys of composite types by using a dot to concatenate the key name to the
+attribute name. For example: “attrib0.key42”. If B<Table> is set to B<true>
+I<path> must point to a I<composite type>, otherwise it must point to a numeric
+type. 
+
+=back
+
+=back
+
+=head3 Connection blocks
+
+Connection blocks specify I<how> to connect to an I<MBeanServer> and what data
+to retrieve. The following configuration options are available:
+
+=over 4
+
+=item B<Host> I<name>
+
+Host name used when dispatching the values to I<collectd>. The option sets this
+field only, it is I<not> used to connect to anything and doesn't need to be a
+real, resolvable name.
+
+=item B<ServiceURL> I<URL>
+
+Specifies how the I<MBeanServer> can be reached. Any string accepted by the
+I<JMXServiceURL> is valid.
+
+See also:
+L<http://java.sun.com/javase/6/docs/api/javax/management/remote/JMXServiceURL.html>
+
+=item B<User> I<name>
+
+Use I<name> to authenticate to the server. If not configured, “monitorRole”
+will be used.
+
+=item B<Password> I<password>
+
+Use I<password> to authenticate to the server. If not given, unauthenticated
+access is used.
+
+=item B<InstancePrefix> I<prefix>
+
+Prefixes the generated I<plugin instance> with I<prefix>. If a second
+I<InstancePrefix> is specified in a referenced I<MBean> block, the prefix
+specified in the I<Connection> block will appear at the beginning of the
+I<plugin instance>, the prefix specified in the I<MBean> block will be appended
+to it.
+
+=item B<Collect> I<mbean_block_name>
+
+Configures which of the I<MBean> blocks to use with this connection. May be
+repeated to collect multiple I<MBeans> from this server. 
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-perl(5)>,
+L<types.db(5)>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt>
+
diff --git a/src/collectd-nagios.1 b/src/collectd-nagios.1
new file mode 100644 (file)
index 0000000..aa5193f
--- /dev/null
@@ -0,0 +1,242 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-NAGIOS 1"
+.TH COLLECTD-NAGIOS 1 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-nagios \- Nagios plugin for querying collectd
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+collectd-nagios \fB\-s\fR \fIsocket\fR \fB\-n\fR \fIvalue_spec\fR \fB\-H\fR \fIhostname\fR \fI[options]\fR
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+This small program is the glue between collectd and nagios. collectd collects
+various performance statistics which it provides via the \f(CW\*(C`unixsock plugin\*(C'\fR,
+see \fIcollectd\-unixsock\fR\|(5). This program is called by Nagios, connects to the
+\&\s-1UNIX\s0 socket and reads the values from collectd. It then returns \fB\s-1OKAY\s0\fR,
+\&\fB\s-1WARNING\s0\fR or \fB\s-1CRITICAL\s0\fR depending on the values and the ranges provided by
+Nagios.
+.SH "ARGUMENTS AND OPTIONS"
+.IX Header "ARGUMENTS AND OPTIONS"
+The following arguments and options are required and understood by
+collectd-nagios. The order of the arguments generally doesn't matter, as long
+as no argument is passed more than once.
+.IP "\fB\-s\fR \fIsocket\fR" 4
+.IX Item "-s socket"
+Path of the \s-1UNIX\s0 socket opened by collectd's \f(CW\*(C`unixsock plugin\*(C'\fR.
+.IP "\fB\-n\fR \fIvalue_spec\fR" 4
+.IX Item "-n value_spec"
+The value to read from collectd. The argument is in the form
+\&\f(CW\*(C`plugin[\-instance]/type[\-instance]\*(C'\fR.
+.IP "\fB\-H\fR \fIhostname\fR" 4
+.IX Item "-H hostname"
+Hostname to query the values for.
+.IP "\fB\-d\fR \fIdata_source\fR" 4
+.IX Item "-d data_source"
+Each \fIvalue_spec\fR may be made of multiple \*(L"data sources\*(R". With this option you
+can select one or more data sources. To select multiple data sources simply
+specify this option again. If multiple data sources are examined they are
+handled according to the consolidation function given with the \fB\-g\fR option.
+.IP "\fB\-g\fR \fBnone\fR\fI|\fR\fBaverage\fR\fI|\fR\fBsum\fR" 4
+.IX Item "-g none|average|sum"
+When multiple data sources are selected from a value spec, they can be handled
+differently depending on this option. The values of the following meaning:
+.RS 4
+.IP "\fBnone\fR" 4
+.IX Item "none"
+No consolidation if done and the warning and critical regions are applied to
+each value independently.
+.IP "\fBaverage\fR" 4
+.IX Item "average"
+The warning and critical ranges are applied to the average of all values.
+.IP "\fBsum\fR" 4
+.IX Item "sum"
+The warning and critical ranges are applied to the sum of all values.
+.IP "\fBpercentage\fR" 4
+.IX Item "percentage"
+The warning and critical ranges are applied to the ratio (in percent) of the
+first value and the sum of all values. A warning is returned if the first
+value is not defined or if all values sum up to zero.
+.RE
+.RS 4
+.RE
+.IP "\fB\-c\fR \fIrange\fR" 4
+.IX Item "-c range"
+.PD 0
+.IP "\fB\-w\fR \fIrange\fR" 4
+.IX Item "-w range"
+.PD
+Set the critical (\fB\-c\fR) and warning (\fB\-w\fR) ranges. These options mostly
+follow the normal syntax of Nagios plugins. The general format is
+"\fImin\fR\fB:\fR\fImax\fR". If a value is smaller than \fImin\fR or bigger than \fImax\fR, a
+\&\fIwarning\fR or \fIcritical\fR status is returned, otherwise the status is
+\&\fIsuccess\fR.
+.Sp
+The tilde sign (\fB~\fR) can be used to explicitly specify infinity. If \fB~\fR is
+used as a \fImin\fR value, negative infinity is used. In case of \fImax\fR, it is
+interpreted as positive infinity.
+.Sp
+If the first character of the \fIrange\fR is the at\ sign (\fB@\fR), the meaning
+of the range will be inverted. I.\ e. all values \fIwithin\fR the range will
+yield a \fIwarning\fR or \fIcritical\fR status, while all values \fIoutside\fR the range
+will result in a \fIsuccess\fR status.
+.Sp
+\&\fImin\fR (and the colon) may be omitted,
+\&\fImin\fR is then assumed to be zero. If \fImax\fR (but not the trailing colon) is
+omitted, \fImax\fR is assumed to be positive infinity.
+.IP "\fB\-m\fR" 4
+.IX Item "-m"
+If this option is given, \*(L"Not a Number\*(R" (NaN) is treated as \fIcritical\fR. By
+default, the \fInone\fR consolidation reports NaNs as \fIwarning\fR. Other
+consolidations simply ignore NaN values.
+.SH "RETURN VALUE"
+.IX Header "RETURN VALUE"
+As usual for Nagios plugins, this program writes a short, one line status
+message to \s-1STDOUT\s0 and signals success or failure with it's return value. It
+exits with a return value of \fB0\fR for \fIsuccess\fR, \fB1\fR for \fIwarning\fR and \fB2\fR
+for \fIcritical\fR. If the values are not available or some other error occurred,
+it returns \fB3\fR for \fIunknown\fR.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-unixsock\fR\|(5),
+<http://nagios.org/>
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo\ at\ collectd.org>
diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c
new file mode 100644 (file)
index 0000000..2719093
--- /dev/null
@@ -0,0 +1,746 @@
+/**
+ * collectd-nagios - src/collectd-nagios.c
+ * Copyright (C) 2008-2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if !defined(__GNUC__) || !__GNUC__
+# define __attribute__(x) /**/
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <assert.h>
+
+#if NAN_STATIC_DEFAULT
+# include <math.h>
+/* #endif NAN_STATIC_DEFAULT*/
+#elif NAN_STATIC_ISOC
+# ifndef __USE_ISOC99
+#  define DISABLE_ISOC99 1
+#  define __USE_ISOC99 1
+# endif /* !defined(__USE_ISOC99) */
+# include <math.h>
+# if DISABLE_ISOC99
+#  undef DISABLE_ISOC99
+#  undef __USE_ISOC99
+# endif /* DISABLE_ISOC99 */
+/* #endif NAN_STATIC_ISOC */
+#elif NAN_ZERO_ZERO
+# include <math.h>
+# ifdef NAN
+#  undef NAN
+# endif
+# define NAN (0.0 / 0.0)
+# ifndef isnan
+#  define isnan(f) ((f) != (f))
+# endif /* !defined(isnan) */
+# ifndef isfinite
+#  define isfinite(f) (((f) - (f)) == 0.0)
+# endif
+# ifndef isinf
+#  define isinf(f) (!isfinite(f) && !isnan(f))
+# endif
+#endif /* NAN_ZERO_ZERO */
+
+#include "libcollectdclient/collectd/client.h"
+
+#define RET_OKAY     0
+#define RET_WARNING  1
+#define RET_CRITICAL 2
+#define RET_UNKNOWN  3
+
+#define CON_NONE     0
+#define CON_AVERAGE  1
+#define CON_SUM      2
+#define CON_PERCENTAGE  3
+
+struct range_s
+{
+       double min;
+       double max;
+       int    invert;
+};
+typedef struct range_s range_t;
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+static char *socket_file_g = NULL;
+static char *value_string_g = NULL;
+static char *hostname_g = NULL;
+
+static range_t range_critical_g;
+static range_t range_warning_g;
+static int consolitation_g = CON_NONE;
+static _Bool nan_is_error_g = 0;
+
+static char **match_ds_g = NULL;
+static int    match_ds_num_g = 0;
+
+/* `strdup' is an XSI extension. I don't want to pull in all of XSI just for
+ * that, so here's an own implementation.. It's easy enough. The GCC attributes
+ * are supposed to get good performance..  -octo */
+__attribute__((malloc, nonnull (1)))
+static char *cn_strdup (const char *str) /* {{{ */
+{
+  size_t strsize;
+  char *ret;
+
+  strsize = strlen (str) + 1;
+  ret = (char *) malloc (strsize);
+  if (ret != NULL)
+    memcpy (ret, str, strsize);
+  return (ret);
+} /* }}} char *cn_strdup */
+
+static int filter_ds (size_t *values_num,
+               double **values, char ***values_names)
+{
+       gauge_t *new_values;
+       char   **new_names;
+
+       size_t i;
+
+       if (match_ds_g == NULL)
+               return (RET_OKAY);
+
+       new_values = (gauge_t *)calloc (match_ds_num_g, sizeof (*new_values));
+       if (new_values == NULL)
+       {
+               fprintf (stderr, "malloc failed: %s\n", strerror (errno));
+               return (RET_UNKNOWN);
+       }
+
+       new_names = (char **)calloc (match_ds_num_g, sizeof (*new_names));
+       if (new_names == NULL)
+       {
+               fprintf (stderr, "malloc failed: %s\n", strerror (errno));
+               free (new_values);
+               return (RET_UNKNOWN);
+       }
+
+       for (i = 0; i < (size_t) match_ds_num_g; i++)
+       {
+               size_t j;
+
+               /* match_ds_g keeps pointers into argv but the names will be freed */
+               new_names[i] = cn_strdup (match_ds_g[i]);
+               if (new_names[i] == NULL)
+               {
+                       fprintf (stderr, "cn_strdup failed: %s\n", strerror (errno));
+                       free (new_values);
+                       for (j = 0; j < i; j++)
+                               free (new_names[j]);
+                       free (new_names);
+                       return (RET_UNKNOWN);
+               }
+
+               for (j = 0; j < *values_num; j++)
+                       if (strcasecmp (new_names[i], (*values_names)[j]) == 0)
+                               break;
+
+               if (j == *values_num)
+               {
+                       printf ("ERROR: DS `%s' is not available.\n", new_names[i]);
+                       free (new_values);
+                       for (j = 0; j <= i; j++)
+                               free (new_names[j]);
+                       free (new_names);
+                       return (RET_CRITICAL);
+               }
+
+               new_values[i] = (*values)[j];
+       }
+
+       free (*values);
+       for (i = 0; i < *values_num; i++)
+               free ((*values_names)[i]);
+       free (*values_names);
+
+       *values       = new_values;
+       *values_names = new_names;
+       *values_num   = match_ds_num_g;
+       return (RET_OKAY);
+} /* int filter_ds */
+
+static void parse_range (char *string, range_t *range)
+{
+       char *min_ptr;
+       char *max_ptr;
+
+       if (*string == '@')
+       {
+               range->invert = 1;
+               string++;
+       }
+
+       max_ptr = strchr (string, ':');
+       if (max_ptr == NULL)
+       {
+               min_ptr = NULL;
+               max_ptr = string;
+       }
+       else
+       {
+               min_ptr = string;
+               *max_ptr = '\0';
+               max_ptr++;
+       }
+
+       assert (max_ptr != NULL);
+
+       /* `10' == `0:10' */
+       if (min_ptr == NULL)
+               range->min = 0.0;
+       /* :10 == ~:10 == -inf:10 */
+       else if ((*min_ptr == '\0') || (*min_ptr == '~'))
+               range->min = NAN;
+       else
+               range->min = atof (min_ptr);
+
+       if ((*max_ptr == '\0') || (*max_ptr == '~'))
+               range->max = NAN;
+       else
+               range->max = atof (max_ptr);
+} /* void parse_range */
+
+static int match_range (range_t *range, double value)
+{
+       int ret = 0;
+
+       if (!isnan (range->min) && (range->min > value))
+               ret = 1;
+       if (!isnan (range->max) && (range->max < value))
+               ret = 1;
+
+       return (((ret - range->invert) == 0) ? 0 : 1);
+} /* int match_range */
+
+static void usage (const char *name)
+{
+       fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
+                       "\n"
+                       "Valid options are:\n"
+                       "  -s <socket>    Path to collectd's UNIX-socket.\n"
+                       "  -n <v_spec>    Value specification to get from collectd.\n"
+                       "                 Format: `plugin-instance/type-instance'\n"
+                       "  -d <ds>        Select the DS to examine. May be repeated to examine multiple\n"
+                       "                 DSes. By default all DSes are used.\n"
+                       "  -g <consol>    Method to use to consolidate several DSes.\n"
+                       "                 See below for a list of valid arguments.\n"
+                       "  -H <host>      Hostname to query the values for.\n"
+                       "  -c <range>     Critical range\n"
+                       "  -w <range>     Warning range\n"
+                       "  -m             Treat \"Not a Number\" (NaN) as critical (default: warning)\n"
+                       "\n"
+                       "Consolidation functions:\n"
+                       "  none:          Apply the warning- and critical-ranges to each data-source\n"
+                       "                 individually.\n"
+                       "  average:       Calculate the average of all matching DSes and apply the\n"
+                       "                 warning- and critical-ranges to the calculated average.\n"
+                       "  sum:           Apply the ranges to the sum of all DSes.\n"
+                       "  percentage:    Apply the ranges to the ratio (in percent) of the first value\n"
+                       "                 and the sum of all values."
+                       "\n", name);
+       exit (1);
+} /* void usage */
+
+static int do_listval (lcc_connection_t *connection)
+{
+       lcc_identifier_t *ret_ident = NULL;
+       size_t ret_ident_num = 0;
+
+       char *hostname = NULL;
+
+       int status;
+       size_t i;
+
+       status = lcc_listval (connection, &ret_ident, &ret_ident_num);
+       if (status != 0) {
+               printf ("UNKNOWN: %s\n", lcc_strerror (connection));
+               if (ret_ident != NULL)
+                       free (ret_ident);
+               return (RET_UNKNOWN);
+       }
+
+       status = lcc_sort_identifiers (connection, ret_ident, ret_ident_num);
+       if (status != 0) {
+               printf ("UNKNOWN: %s\n", lcc_strerror (connection));
+               if (ret_ident != NULL)
+                       free (ret_ident);
+               return (RET_UNKNOWN);
+       }
+
+       for (i = 0; i < ret_ident_num; ++i) {
+               char id[1024];
+
+               if ((hostname_g != NULL) && (strcasecmp (hostname_g, ret_ident[i].host)))
+                       continue;
+
+               if ((hostname == NULL) || strcasecmp (hostname, ret_ident[i].host))
+               {
+                       if (hostname != NULL)
+                               free (hostname);
+                       hostname = strdup (ret_ident[i].host);
+                       printf ("Host: %s\n", hostname);
+               }
+
+               /* empty hostname; not to be printed again */
+               ret_ident[i].host[0] = '\0';
+
+               status = lcc_identifier_to_string (connection,
+                               id, sizeof (id), ret_ident + i);
+               if (status != 0) {
+                       printf ("ERROR: listval: Failed to convert returned "
+                                       "identifier to a string: %s\n",
+                                       lcc_strerror (connection));
+                       continue;
+               }
+
+               /* skip over the (empty) hostname and following '/' */
+               printf ("\t%s\n", id + 1);
+       }
+
+       if (ret_ident != NULL)
+               free (ret_ident);
+       return (RET_OKAY);
+} /* int do_listval */
+
+static int do_check_con_none (size_t values_num,
+               double *values, char **values_names)
+{
+       int num_critical = 0;
+       int num_warning  = 0;
+       int num_okay = 0;
+       const char *status_str = "UNKNOWN";
+       int status_code = RET_UNKNOWN;
+       size_t i;
+
+       for (i = 0; i < values_num; i++)
+       {
+               if (isnan (values[i]))
+               {
+                       if (nan_is_error_g)
+                               num_critical++;
+                       else
+                               num_warning++;
+               }
+               else if (match_range (&range_critical_g, values[i]) != 0)
+                       num_critical++;
+               else if (match_range (&range_warning_g, values[i]) != 0)
+                       num_warning++;
+               else
+                       num_okay++;
+       }
+
+       if ((num_critical == 0) && (num_warning == 0) && (num_okay == 0))
+       {
+               printf ("WARNING: No defined values found\n");
+               return (RET_WARNING);
+       }
+       else if ((num_critical == 0) && (num_warning == 0))
+       {
+               status_str = "OKAY";
+               status_code = RET_OKAY;
+       }
+       else if (num_critical == 0)
+       {
+               status_str = "WARNING";
+               status_code = RET_WARNING;
+       }
+       else
+       {
+               status_str = "CRITICAL";
+               status_code = RET_CRITICAL;
+       }
+
+       printf ("%s: %i critical, %i warning, %i okay", status_str,
+                       num_critical, num_warning, num_okay);
+       if (values_num > 0)
+       {
+               printf (" |");
+               for (i = 0; i < values_num; i++)
+                       printf (" %s=%f;;;;", values_names[i], values[i]);
+       }
+       printf ("\n");
+
+       return (status_code);
+} /* int do_check_con_none */
+
+static int do_check_con_average (size_t values_num,
+               double *values, char **values_names)
+{
+       size_t i;
+       double total;
+       int total_num;
+       double average;
+       const char *status_str = "UNKNOWN";
+       int status_code = RET_UNKNOWN;
+
+       total = 0.0;
+       total_num = 0;
+       for (i = 0; i < values_num; i++)
+       {
+               if (isnan (values[i]))
+               {
+                       if (!nan_is_error_g)
+                               continue;
+
+                       printf ("CRITICAL: Data source \"%s\" is NaN\n",
+                                       values_names[i]);
+                       return (RET_CRITICAL);
+               }
+
+               total += values[i];
+               total_num++;
+       }
+
+       if (total_num == 0)
+       {
+               printf ("WARNING: No defined values found\n");
+               return (RET_WARNING);
+       }
+
+       average = total / total_num;
+
+       if (match_range (&range_critical_g, average) != 0)
+       {
+               status_str = "CRITICAL";
+               status_code = RET_CRITICAL;
+       }
+       else if (match_range (&range_warning_g, average) != 0)
+       {
+               status_str = "WARNING";
+               status_code = RET_WARNING;
+       }
+       else
+       {
+               status_str = "OKAY";
+               status_code = RET_OKAY;
+       }
+
+       printf ("%s: %g average |", status_str, average);
+       for (i = 0; i < values_num; i++)
+               printf (" %s=%f;;;;", values_names[i], values[i]);
+       printf ("\n");
+
+       return (status_code);
+} /* int do_check_con_average */
+
+static int do_check_con_sum (size_t values_num,
+               double *values, char **values_names)
+{
+       size_t i;
+       double total;
+       int total_num;
+       const char *status_str = "UNKNOWN";
+       int status_code = RET_UNKNOWN;
+
+       total = 0.0;
+       total_num = 0;
+       for (i = 0; i < values_num; i++)
+       {
+               if (isnan (values[i]))
+               {
+                       if (!nan_is_error_g)
+                               continue;
+
+                       printf ("CRITICAL: Data source \"%s\" is NaN\n",
+                                       values_names[i]);
+                       return (RET_CRITICAL);
+               }
+
+               total += values[i];
+               total_num++;
+       }
+
+       if (total_num == 0)
+       {
+               printf ("WARNING: No defined values found\n");
+               return (RET_WARNING);
+       }
+
+       if (match_range (&range_critical_g, total) != 0)
+       {
+               status_str = "CRITICAL";
+               status_code = RET_CRITICAL;
+       }
+       else if (match_range (&range_warning_g, total) != 0)
+       {
+               status_str = "WARNING";
+               status_code = RET_WARNING;
+       }
+       else
+       {
+               status_str = "OKAY";
+               status_code = RET_OKAY;
+       }
+
+       printf ("%s: %g sum |", status_str, total);
+       for (i = 0; i < values_num; i++)
+               printf (" %s=%f;;;;", values_names[i], values[i]);
+       printf ("\n");
+
+       return (status_code);
+} /* int do_check_con_sum */
+
+static int do_check_con_percentage (size_t values_num,
+               double *values, char **values_names)
+{
+       size_t i;
+       double sum = 0.0;
+       double percentage;
+
+       const char *status_str  = "UNKNOWN";
+       int         status_code = RET_UNKNOWN;
+
+       if ((values_num < 1) || (isnan (values[0])))
+       {
+               printf ("WARNING: The first value is not defined\n");
+               return (RET_WARNING);
+       }
+
+       for (i = 0; i < values_num; i++)
+       {
+               if (isnan (values[i]))
+               {
+                       if (!nan_is_error_g)
+                               continue;
+
+                       printf ("CRITICAL: Data source \"%s\" is NaN\n",
+                                       values_names[i]);
+                       return (RET_CRITICAL);
+               }
+
+               sum += values[i];
+       }
+
+       if (sum == 0.0)
+       {
+               printf ("WARNING: Values sum up to zero\n");
+               return (RET_WARNING);
+       }
+
+       percentage = 100.0 * values[0] / sum;
+
+       if (match_range (&range_critical_g, percentage) != 0)
+       {
+               status_str  = "CRITICAL";
+               status_code = RET_CRITICAL;
+       }
+       else if (match_range (&range_warning_g, percentage) != 0)
+       {
+               status_str  = "WARNING";
+               status_code = RET_WARNING;
+       }
+       else
+       {
+               status_str  = "OKAY";
+               status_code = RET_OKAY;
+       }
+
+       printf ("%s: %lf percent |", status_str, percentage);
+       for (i = 0; i < values_num; i++)
+               printf (" %s=%lf;;;;", values_names[i], values[i]);
+       return (status_code);
+} /* int do_check_con_percentage */
+
+static int do_check (lcc_connection_t *connection)
+{
+       gauge_t *values;
+       char   **values_names;
+       size_t   values_num;
+       char ident_str[1024];
+       lcc_identifier_t ident;
+       size_t i;
+       int status;
+
+       snprintf (ident_str, sizeof (ident_str), "%s/%s",
+                       hostname_g, value_string_g);
+       ident_str[sizeof (ident_str) - 1] = 0;
+
+       memset (&ident, 0, sizeof (ident));
+       status = lcc_string_to_identifier (connection, &ident, ident_str);
+       if (status != 0)
+       {
+               printf ("ERROR: Creating an identifier failed: %s.\n",
+                               lcc_strerror (connection));
+               LCC_DESTROY (connection);
+               return (RET_CRITICAL);
+       }
+
+       status = lcc_getval (connection, &ident,
+                       &values_num, &values, &values_names);
+       if (status != 0)
+       {
+               printf ("ERROR: Retrieving values from the daemon failed: %s.\n",
+                               lcc_strerror (connection));
+               LCC_DESTROY (connection);
+               return (RET_CRITICAL);
+       }
+
+       LCC_DESTROY (connection);
+
+       status = filter_ds (&values_num, &values, &values_names);
+       if (status != RET_OKAY)
+               return (status);
+
+       status = RET_UNKNOWN;
+       if (consolitation_g == CON_NONE)
+               status =  do_check_con_none (values_num, values, values_names);
+       else if (consolitation_g == CON_AVERAGE)
+               status =  do_check_con_average (values_num, values, values_names);
+       else if (consolitation_g == CON_SUM)
+               status = do_check_con_sum (values_num, values, values_names);
+       else if (consolitation_g == CON_PERCENTAGE)
+               status = do_check_con_percentage (values_num, values, values_names);
+
+       free (values);
+       if (values_names != NULL)
+               for (i = 0; i < values_num; i++)
+                       free (values_names[i]);
+       free (values_names);
+
+       return (status);
+} /* int do_check */
+
+int main (int argc, char **argv)
+{
+       char address[1024];
+       lcc_connection_t *connection;
+
+       int status;
+
+       range_critical_g.min = NAN;
+       range_critical_g.max = NAN;
+       range_critical_g.invert = 0;
+
+       range_warning_g.min = NAN;
+       range_warning_g.max = NAN;
+       range_warning_g.invert = 0;
+
+       while (42)
+       {
+               int c;
+
+               c = getopt (argc, argv, "w:c:s:n:H:g:d:hm");
+               if (c < 0)
+                       break;
+
+               switch (c)
+               {
+                       case 'c':
+                               parse_range (optarg, &range_critical_g);
+                               break;
+                       case 'w':
+                               parse_range (optarg, &range_warning_g);
+                               break;
+                       case 's':
+                               socket_file_g = optarg;
+                               break;
+                       case 'n':
+                               value_string_g = optarg;
+                               break;
+                       case 'H':
+                               hostname_g = optarg;
+                               break;
+                       case 'g':
+                               if (strcasecmp (optarg, "none") == 0)
+                                       consolitation_g = CON_NONE;
+                               else if (strcasecmp (optarg, "average") == 0)
+                                       consolitation_g = CON_AVERAGE;
+                               else if (strcasecmp (optarg, "sum") == 0)
+                                       consolitation_g = CON_SUM;
+                               else if (strcasecmp (optarg, "percentage") == 0)
+                                       consolitation_g = CON_PERCENTAGE;
+                               else
+                               {
+                                       fprintf (stderr, "Unknown consolidation function `%s'.\n",
+                                                       optarg);
+                                       usage (argv[0]);
+                               }
+                               break;
+                       case 'd':
+                       {
+                               char **tmp;
+                               tmp = (char **) realloc (match_ds_g,
+                                               (match_ds_num_g + 1)
+                                               * sizeof (char *));
+                               if (tmp == NULL)
+                               {
+                                       fprintf (stderr, "realloc failed: %s\n",
+                                                       strerror (errno));
+                                       return (RET_UNKNOWN);
+                               }
+                               match_ds_g = tmp;
+                               match_ds_g[match_ds_num_g] = cn_strdup (optarg);
+                               if (match_ds_g[match_ds_num_g] == NULL)
+                               {
+                                       fprintf (stderr, "cn_strdup failed: %s\n",
+                                                       strerror (errno));
+                                       return (RET_UNKNOWN);
+                               }
+                               match_ds_num_g++;
+                               break;
+                       }
+                       case 'm':
+                               nan_is_error_g = 1;
+                               break;
+                       default:
+                               usage (argv[0]);
+               } /* switch (c) */
+       }
+
+       if ((socket_file_g == NULL) || (value_string_g == NULL)
+                       || ((hostname_g == NULL) && (strcasecmp (value_string_g, "LIST"))))
+       {
+               fprintf (stderr, "Missing required arguments.\n");
+               usage (argv[0]);
+       }
+
+       snprintf (address, sizeof (address), "unix:%s", socket_file_g);
+       address[sizeof (address) - 1] = 0;
+
+       connection = NULL;
+       status = lcc_connect (address, &connection);
+       if (status != 0)
+       {
+               printf ("ERROR: Connecting to daemon at %s failed.\n",
+                               socket_file_g);
+               return (RET_CRITICAL);
+       }
+
+       if (0 == strcasecmp (value_string_g, "LIST"))
+               return (do_listval (connection));
+
+       return (do_check (connection));
+} /* int main */
diff --git a/src/collectd-nagios.pod b/src/collectd-nagios.pod
new file mode 100644 (file)
index 0000000..e28ff4b
--- /dev/null
@@ -0,0 +1,126 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-nagios - Nagios plugin for querying collectd
+
+=head1 SYNOPSIS
+
+collectd-nagios B<-s> I<socket> B<-n> I<value_spec> B<-H> I<hostname> I<[options]>
+
+=head1 DESCRIPTION
+
+This small program is the glue between collectd and nagios. collectd collects
+various performance statistics which it provides via the C<unixsock plugin>,
+see L<collectd-unixsock(5)>. This program is called by Nagios, connects to the
+UNIX socket and reads the values from collectd. It then returns B<OKAY>,
+B<WARNING> or B<CRITICAL> depending on the values and the ranges provided by
+Nagios.
+
+=head1 ARGUMENTS AND OPTIONS
+
+The following arguments and options are required and understood by
+collectd-nagios. The order of the arguments generally doesn't matter, as long
+as no argument is passed more than once.
+
+=over 4
+
+=item B<-s> I<socket>
+
+Path of the UNIX socket opened by collectd's C<unixsock plugin>.
+
+=item B<-n> I<value_spec>
+
+The value to read from collectd. The argument is in the form
+C<plugin[-instance]/type[-instance]>.
+
+=item B<-H> I<hostname>
+
+Hostname to query the values for.
+
+=item B<-d> I<data_source>
+
+Each I<value_spec> may be made of multiple "data sources". With this option you
+can select one or more data sources. To select multiple data sources simply
+specify this option again. If multiple data sources are examined they are
+handled according to the consolidation function given with the B<-g> option.
+
+=item B<-g> B<none>I<|>B<average>I<|>B<sum>
+
+When multiple data sources are selected from a value spec, they can be handled
+differently depending on this option. The values of the following meaning:
+
+=over 4
+
+=item B<none>
+
+No consolidation if done and the warning and critical regions are applied to
+each value independently.
+
+=item B<average>
+
+The warning and critical ranges are applied to the average of all values.
+
+=item B<sum>
+
+The warning and critical ranges are applied to the sum of all values.
+
+=item B<percentage>
+
+The warning and critical ranges are applied to the ratio (in percent) of the
+first value and the sum of all values. A warning is returned if the first
+value is not defined or if all values sum up to zero.
+
+=back
+
+=item B<-c> I<range>
+
+=item B<-w> I<range>
+
+Set the critical (B<-c>) and warning (B<-w>) ranges. These options mostly
+follow the normal syntax of Nagios plugins. The general format is
+"I<min>B<:>I<max>". If a value is smaller than I<min> or bigger than I<max>, a
+I<warning> or I<critical> status is returned, otherwise the status is
+I<success>.
+
+The tilde sign (B<~>) can be used to explicitly specify infinity. If B<~> is
+used as a I<min> value, negative infinity is used. In case of I<max>, it is
+interpreted as positive infinity.
+
+If the first character of the I<range> is the atE<nbsp>sign (B<@>), the meaning
+of the range will be inverted. I.E<nbsp>e. all values I<within> the range will
+yield a I<warning> or I<critical> status, while all values I<outside> the range
+will result in a I<success> status.
+
+I<min> (and the colon) may be omitted,
+I<min> is then assumed to be zero. If I<max> (but not the trailing colon) is
+omitted, I<max> is assumed to be positive infinity.
+
+=item B<-m>
+
+If this option is given, "Not a Number" (NaN) is treated as I<critical>. By
+default, the I<none> consolidation reports NaNs as I<warning>. Other
+consolidations simply ignore NaN values.
+
+=back
+
+=head1 RETURN VALUE
+
+As usual for Nagios plugins, this program writes a short, one line status
+message to STDOUT and signals success or failure with it's return value. It
+exits with a return value of B<0> for I<success>, B<1> for I<warning> and B<2>
+for I<critical>. If the values are not available or some other error occurred,
+it returns B<3> for I<unknown>.
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-unixsock(5)>,
+L<http://nagios.org/>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt>
+
+=cut
diff --git a/src/collectd-perl.5 b/src/collectd-perl.5
new file mode 100644 (file)
index 0000000..a1064b2
--- /dev/null
@@ -0,0 +1,858 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-PERL 5"
+.TH COLLECTD-PERL 5 "2015-05-20" "5.4.2.911.g0c88d3b" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-perl \- Documentation of collectd's "perl plugin"
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 7
+\&  LoadPlugin perl
+\&  # ...
+\&  <Plugin perl>
+\&    IncludeDir "/path/to/perl/plugins"
+\&    BaseName "Collectd::Plugins"
+\&    EnableDebugger ""
+\&    LoadPlugin "FooBar"
+\&
+\&    <Plugin FooBar>
+\&      Foo "Bar"
+\&    </Plugin>
+\&  </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \f(CW\*(C`perl plugin\*(C'\fR embeds a Perl-interpreter into collectd and provides an
+interface to collectd's plugin system. This makes it possible to write plugins
+for collectd in Perl. This is a lot more efficient than executing a
+Perl-script every time you want to read a value with the \f(CW\*(C`exec plugin\*(C'\fR (see
+\&\fIcollectd\-exec\fR\|(5)) and provides a lot more functionality, too.
+.SH "CONFIGURATION"
+.IX Header "CONFIGURATION"
+.IP "\fBLoadPlugin\fR \fIPlugin\fR" 4
+.IX Item "LoadPlugin Plugin"
+Loads the Perl plugin \fIPlugin\fR. This does basically the same as \fBuse\fR would
+do in a Perl program. As a side effect, the first occurrence of this option
+causes the Perl-interpreter to be initialized.
+.IP "\fBBaseName\fR \fIName\fR" 4
+.IX Item "BaseName Name"
+Prepends \fIName\fR\fB::\fR to all plugin names loaded after this option. This is
+provided for convenience to keep plugin names short. All Perl-based plugins
+provided with the \fIcollectd\fR distributions reside in the \f(CW\*(C`Collectd::Plugins\*(C'\fR
+namespace.
+.IP "<\fBPlugin\fR \fIName\fR> block" 4
+.IX Item "<Plugin Name> block"
+This block may be used to pass on configuration settings to a Perl plugin. The
+configuration is converted into a config-item data type which is passed to the
+registered configuration callback. See below for details about the config-item
+data type and how to register callbacks.
+.Sp
+The \fIname\fR identifies the callback. It is used literally and independent of
+the \fBBaseName\fR setting.
+.IP "\fBEnableDebugger\fR \fIPackage\fR[=\fIoption\fR,...]" 4
+.IX Item "EnableDebugger Package[=option,...]"
+Run collectd under the control of the Perl source debugger. If \fIPackage\fR is
+not the empty string, control is passed to the debugging, profiling, or
+tracing module installed as Devel::\fIPackage\fR. A comma-separated list of
+options may be specified after the \*(L"=\*(R" character. Please note that you may not
+leave out the \fIPackage\fR option even if you specify \fB""\fR. This is the same as
+using the \fB\-d:Package\fR command line option.
+.Sp
+See perldebug for detailed documentation about debugging Perl.
+.Sp
+This option does not prevent collectd from daemonizing, so you should start
+collectd with the \fB\-f\fR command line option. Else you will not be able to use
+the command line driven interface of the debugger.
+.IP "\fBIncludeDir\fR \fIDir\fR" 4
+.IX Item "IncludeDir Dir"
+Adds \fIDir\fR to the \fB\f(CB@INC\fB\fR array. This is the same as using the \fB\-IDir\fR
+command line option or \fBuse lib Dir\fR in the source code. Please note that it
+only has effect on plugins loaded after this option.
+.SH "WRITING YOUR OWN PLUGINS"
+.IX Header "WRITING YOUR OWN PLUGINS"
+Writing your own plugins is quite simple. collectd manages plugins by means of
+\&\fBdispatch functions\fR which call the appropriate \fBcallback functions\fR
+registered by the plugins. Any plugin basically consists of the implementation
+of these callback functions and initializing code which registers the
+functions with collectd. See the section \*(L"\s-1EXAMPLES\*(R"\s0 below for a really basic
+example. The following types of \fBcallback functions\fR are known to collectd
+(all of them are optional):
+.IP "configuration functions" 4
+.IX Item "configuration functions"
+This type of functions is called during configuration if an appropriate
+\&\fBPlugin\fR block has been encountered. It is called once for each \fBPlugin\fR
+block which matches the name of the callback as provided with the
+\&\fBplugin_register\fR method \- see below.
+.IP "init functions" 4
+.IX Item "init functions"
+This type of functions is called once after loading the module and before any
+calls to the read and write functions. It should be used to initialize the
+internal state of the plugin (e.\ g. open sockets, ...). If the return
+value evaluates to \fBfalse\fR, the plugin will be disabled.
+.IP "read functions" 4
+.IX Item "read functions"
+This type of function is used to collect the actual data. It is called once
+per interval (see the \fBInterval\fR configuration option of collectd). Usually
+it will call \fBplugin_dispatch_values\fR to dispatch the values to collectd
+which will pass them on to all registered \fBwrite functions\fR. If the return
+value evaluates to \fBfalse\fR the plugin will be skipped for an increasing
+amount of time until it returns \fBtrue\fR again.
+.IP "write functions" 4
+.IX Item "write functions"
+This type of function is used to write the dispatched values. It is called
+once for each call to \fBplugin_dispatch_values\fR.
+.IP "flush functions" 4
+.IX Item "flush functions"
+This type of function is used to flush internal caches of plugins. It is
+usually triggered by the user only. Any plugin which caches data before
+writing it to disk should provide this kind of callback function.
+.IP "log functions" 4
+.IX Item "log functions"
+This type of function is used to pass messages of plugins or the daemon itself
+to the user.
+.IP "notification function" 4
+.IX Item "notification function"
+This type of function is used to act upon notifications. In general, a
+notification is a status message that may be associated with a data instance.
+Usually, a notification is generated by the daemon if a configured threshold
+has been exceeded (see the section \*(L"\s-1THRESHOLD CONFIGURATION\*(R"\s0 in
+\&\fIcollectd.conf\fR\|(5) for more details), but any plugin may dispatch
+notifications as well.
+.IP "shutdown functions" 4
+.IX Item "shutdown functions"
+This type of function is called once before the daemon shuts down. It should
+be used to clean up the plugin (e.g. close sockets, ...).
+.PP
+Any function (except log functions) may set the \fB$@\fR variable to describe
+errors in more detail. The message will be passed on to the user using
+collectd's logging mechanism.
+.PP
+See the documentation of the \fBplugin_register\fR method in the section
+\&\*(L"\s-1METHODS\*(R"\s0 below for the number and types of arguments passed to each
+\&\fBcallback function\fR. This section also explains how to register \fBcallback
+functions\fR with collectd.
+.PP
+To enable a plugin, copy it to a place where Perl can find it (i.\ e. a
+directory listed in the \fB\f(CB@INC\fB\fR array) just as any other Perl plugin and add
+an appropriate \fBLoadPlugin\fR option to the configuration file. After
+restarting collectd you're done.
+.SH "DATA TYPES"
+.IX Header "DATA TYPES"
+The following complex types are used to pass values between the Perl plugin
+and collectd:
+.IP "Config-Item" 4
+.IX Item "Config-Item"
+A config-item is one structure which keeps the information provided in the
+configuration file. The array of children keeps one entry for each
+configuration option. Each such entry is another config-item structure, which
+may nest further if nested blocks are used.
+.Sp
+.Vb 5
+\&  {
+\&    key      => key,
+\&    values   => [ val1, val2, ... ],
+\&    children => [ { ... }, { ... }, ... ]
+\&  }
+.Ve
+.IP "Data-Set" 4
+.IX Item "Data-Set"
+A data-set is a list of one or more data-sources. Each data-source defines a
+name, type, min\- and max-value and the data-set wraps them up into one
+structure. The general layout looks like this:
+.Sp
+.Vb 6
+\&  [{
+\&    name => \*(Aqdata_source_name\*(Aq,
+\&    type => DS_TYPE_COUNTER || DS_TYPE_GAUGE || DS_TYPE_DERIVE || DS_TYPE_ABSOLUTE,
+\&    min  => value || undef,
+\&    max  => value || undef
+\&  }, ...]
+.Ve
+.IP "Value-List" 4
+.IX Item "Value-List"
+A value-list is one structure which features an array of values and fields to
+identify the values, i.\ e. time and host, plugin name and
+plugin-instance as well as a type and type-instance. Since the \*(L"type\*(R" is not
+included in the value-list but is passed as an extra argument, the general
+layout looks like this:
+.Sp
+.Vb 10
+\&  {
+\&    values => [123, 0.5],
+\&    time   => time (),
+\&    interval => plugin_get_interval (),
+\&    host   => $hostname_g,
+\&    plugin => \*(Aqmyplugin\*(Aq,
+\&    type   => \*(Aqmyplugin\*(Aq,
+\&    plugin_instance => \*(Aq\*(Aq,
+\&    type_instance   => \*(Aq\*(Aq
+\&  }
+.Ve
+.IP "Notification" 4
+.IX Item "Notification"
+A notification is one structure defining the severity, time and message of the
+status message as well as an identification of a data instance. Also, it
+includes an optional list of user-defined meta information represented as
+(name, value) pairs:
+.Sp
+.Vb 11
+\&  {
+\&    severity => NOTIF_FAILURE || NOTIF_WARNING || NOTIF_OKAY,
+\&    time     => time (),
+\&    message  => \*(Aqstatus message\*(Aq,
+\&    host     => $hostname_g,
+\&    plugin   => \*(Aqmyplugin\*(Aq,
+\&    type     => \*(Aqmytype\*(Aq,
+\&    plugin_instance => \*(Aq\*(Aq,
+\&    type_instance   => \*(Aq\*(Aq,
+\&    meta     => [ { name => <name>, value => <value> }, ... ]
+\&  }
+.Ve
+.IP "Match-Proc" 4
+.IX Item "Match-Proc"
+A match-proc is one structure storing the callbacks of a \*(L"match\*(R" of the filter
+chain infrastructure. The general layout looks like this:
+.Sp
+.Vb 5
+\&  {
+\&    create  => \*(Aqmy_create\*(Aq,
+\&    destroy => \*(Aqmy_destroy\*(Aq,
+\&    match   => \*(Aqmy_match\*(Aq
+\&  }
+.Ve
+.IP "Target-Proc" 4
+.IX Item "Target-Proc"
+A target-proc is one structure storing the callbacks of a \*(L"target\*(R" of the
+filter chain infrastructure. The general layout looks like this:
+.Sp
+.Vb 5
+\&  {
+\&    create  => \*(Aqmy_create\*(Aq,
+\&    destroy => \*(Aqmy_destroy\*(Aq,
+\&    invoke  => \*(Aqmy_invoke\*(Aq
+\&  }
+.Ve
+.SH "METHODS"
+.IX Header "METHODS"
+The following functions provide the C\-interface to Perl-modules. They are
+exported by the \*(L":plugin\*(R" export tag (see the section \*(L"\s-1EXPORTS\*(R"\s0 below).
+.IP "\fBplugin_register\fR (\fItype\fR, \fIname\fR, \fIdata\fR)" 4
+.IX Item "plugin_register (type, name, data)"
+Registers a callback-function or data-set.
+.Sp
+\&\fItype\fR can be one of:
+.RS 4
+.IP "\s-1TYPE_CONFIG\s0" 4
+.IX Item "TYPE_CONFIG"
+.PD 0
+.IP "\s-1TYPE_INIT\s0" 4
+.IX Item "TYPE_INIT"
+.IP "\s-1TYPE_READ\s0" 4
+.IX Item "TYPE_READ"
+.IP "\s-1TYPE_WRITE\s0" 4
+.IX Item "TYPE_WRITE"
+.IP "\s-1TYPE_FLUSH\s0" 4
+.IX Item "TYPE_FLUSH"
+.IP "\s-1TYPE_LOG\s0" 4
+.IX Item "TYPE_LOG"
+.IP "\s-1TYPE_NOTIF\s0" 4
+.IX Item "TYPE_NOTIF"
+.IP "\s-1TYPE_SHUTDOWN\s0" 4
+.IX Item "TYPE_SHUTDOWN"
+.IP "\s-1TYPE_DATASET\s0" 4
+.IX Item "TYPE_DATASET"
+.RE
+.RS 4
+.PD
+.Sp
+\&\fIname\fR is the name of the callback-function or the type of the data-set,
+depending on the value of \fItype\fR. (Please note that the type of the data-set
+is the value passed as \fIname\fR here and has nothing to do with the \fItype\fR
+argument which simply tells \fBplugin_register\fR what is being registered.)
+.Sp
+The last argument, \fIdata\fR, is either a function name or an array-reference.
+If \fItype\fR is \fB\s-1TYPE_DATASET\s0\fR, then the \fIdata\fR argument must be an
+array-reference which points to an array of hashes. Each hash describes one
+data-set. For the exact layout see \fBData-Set\fR above. Please note that
+there is a large number of predefined data-sets available in the \fBtypes.db\fR
+file which are automatically registered with collectd \- see \fItypes.db\fR\|(5) for
+a description of the format of this file.
+.Sp
+\&\fBNote\fR: Using \fBplugin_register\fR to register a data-set is deprecated. Add
+the new type to a custom \fItypes.db\fR\|(5) file instead. This functionality might
+be removed in a future version of collectd.
+.Sp
+If the \fItype\fR argument is any of the other types (\fB\s-1TYPE_INIT\s0\fR, \fB\s-1TYPE_READ\s0\fR,
+\&...) then \fIdata\fR is expected to be a function name. If the name is not
+prefixed with the plugin's package name collectd will add it automatically.
+The interface slightly differs from the C interface (which expects a function
+pointer instead) because Perl does not support to share references to
+subroutines between threads.
+.Sp
+These functions are called in the various stages of the daemon (see the
+section \*(L"\s-1WRITING YOUR OWN PLUGINS\*(R"\s0 above) and are passed the following
+arguments:
+.IP "\s-1TYPE_CONFIG\s0" 4
+.IX Item "TYPE_CONFIG"
+The only argument passed is \fIconfig-item\fR. See above for the layout of this
+data type.
+.IP "\s-1TYPE_INIT\s0" 4
+.IX Item "TYPE_INIT"
+.PD 0
+.IP "\s-1TYPE_READ\s0" 4
+.IX Item "TYPE_READ"
+.IP "\s-1TYPE_SHUTDOWN\s0" 4
+.IX Item "TYPE_SHUTDOWN"
+.PD
+No arguments are passed.
+.IP "\s-1TYPE_WRITE\s0" 4
+.IX Item "TYPE_WRITE"
+The arguments passed are \fItype\fR, \fIdata-set\fR, and \fIvalue-list\fR. \fItype\fR is a
+string. For the layout of \fIdata-set\fR and \fIvalue-list\fR see above.
+.IP "\s-1TYPE_FLUSH\s0" 4
+.IX Item "TYPE_FLUSH"
+The arguments passed are \fItimeout\fR and \fIidentifier\fR. \fItimeout\fR indicates
+that only data older than \fItimeout\fR seconds is to be flushed. \fIidentifier\fR
+specifies which values are to be flushed.
+.IP "\s-1TYPE_LOG\s0" 4
+.IX Item "TYPE_LOG"
+The arguments are \fIlog-level\fR and \fImessage\fR. The log level is small for
+important messages and high for less important messages. The least important
+level is \fB\s-1LOG_DEBUG\s0\fR, the most important level is \fB\s-1LOG_ERR\s0\fR. In between there
+are (from least to most important): \fB\s-1LOG_INFO\s0\fR, \fB\s-1LOG_NOTICE\s0\fR, and
+\&\fB\s-1LOG_WARNING\s0\fR. \fImessage\fR is simply a string \fBwithout\fR a newline at the end.
+.IP "\s-1TYPE_NOTIF\s0" 4
+.IX Item "TYPE_NOTIF"
+The only argument passed is \fInotification\fR. See above for the layout of this
+data type.
+.RE
+.RS 4
+.RE
+.IP "\fBplugin_unregister\fR (\fItype\fR, \fIplugin\fR)" 4
+.IX Item "plugin_unregister (type, plugin)"
+Removes a callback or data-set from collectd's internal list of
+functions\ / datasets.
+.IP "\fBplugin_dispatch_values\fR (\fIvalue-list\fR)" 4
+.IX Item "plugin_dispatch_values (value-list)"
+Submits a \fIvalue-list\fR to the daemon. If the data-set identified by
+\&\fIvalue-list\fR\->{\fItype\fR}
+is found (and the number of values matches the number of data-sources) then the
+type, data-set and value-list is passed to all write-callbacks that are
+registered with the daemon.
+.IP "\fBplugin_write\fR ([\fBplugins\fR => \fI...\fR][, \fBdatasets\fR => \fI...\fR], \fBvaluelists\fR => \fI...\fR)" 4
+.IX Item "plugin_write ([plugins => ...][, datasets => ...], valuelists => ...)"
+Calls the write function of the given \fIplugins\fR with the provided \fIdata
+sets\fR and \fIvalue lists\fR. In contrast to \fBplugin_dispatch_values\fR, it does
+not update collectd's internal cache and bypasses the filter mechanism (see
+\&\fIcollectd.conf\fR\|(5) for details). If the \fBplugins\fR argument has been omitted,
+the values will be dispatched to all registered write plugins. If the
+\&\fBdatasets\fR argument has been omitted, the required data sets are looked up
+according to the \f(CW\*(C`type\*(C'\fR member in the appropriate value list. The value of
+all three arguments may either be a single scalar or a reference to an array.
+If the \fBdatasets\fR argument has been specified, the number of data sets has to
+equal the number of specified value lists.
+.IP "\fBplugin_flush\fR ([\fBtimeout\fR => \fItimeout\fR][, \fBplugins\fR => \fI...\fR][, \fBidentifiers\fR => \fI...\fR])" 4
+.IX Item "plugin_flush ([timeout => timeout][, plugins => ...][, identifiers => ...])"
+Flush one or more plugins. \fItimeout\fR and the specified \fIidentifiers\fR are
+passed on to the registered flush-callbacks. If omitted, the timeout defaults
+to \f(CW\*(C`\-1\*(C'\fR. The identifier defaults to the undefined value. If the \fBplugins\fR
+argument has been specified, only named plugins will be flushed. The value of
+the \fBplugins\fR and \fBidentifiers\fR arguments may either be a string or a
+reference to an array of strings.
+.IP "\fBplugin_dispatch_notification\fR (\fInotification\fR)" 4
+.IX Item "plugin_dispatch_notification (notification)"
+Submits a \fInotification\fR to the daemon which will then pass it to all
+notification-callbacks that are registered.
+.IP "\fBplugin_log\fR (\fIlog-level\fR, \fImessage\fR)" 4
+.IX Item "plugin_log (log-level, message)"
+Submits a \fImessage\fR of level \fIlog-level\fR to collectd's logging mechanism.
+The message is passed to all log-callbacks that are registered with collectd.
+.IP "\fB\s-1ERROR\s0\fR, \fB\s-1WARNING\s0\fR, \fB\s-1NOTICE\s0\fR, \fB\s-1INFO\s0\fR, \fB\s-1DEBUG\s0\fR (\fImessage\fR)" 4
+.IX Item "ERROR, WARNING, NOTICE, INFO, DEBUG (message)"
+Wrappers around \fBplugin_log\fR, using \fB\s-1LOG_ERR\s0\fR, \fB\s-1LOG_WARNING\s0\fR,
+\&\fB\s-1LOG_NOTICE\s0\fR, \fB\s-1LOG_INFO\s0\fR and \fB\s-1LOG_DEBUG\s0\fR respectively as \fIlog-level\fR.
+.IP "\fBplugin_get_interval\fR ()" 4
+.IX Item "plugin_get_interval ()"
+Returns the interval of the current plugin as a floating point number in
+seconds. This value depends on the interval configured within the
+\&\f(CW\*(C`LoadPlugin perl\*(C'\fR block or the global interval (see \fIcollectd.conf\fR\|(5) for
+details).
+.PP
+The following function provides the filter chain C\-interface to Perl-modules.
+It is exported by the \*(L":filter_chain\*(R" export tag (see the section \*(L"\s-1EXPORTS\*(R"\s0
+below).
+.IP "\fBfc_register\fR (\fItype\fR, \fIname\fR, \fIproc\fR)" 4
+.IX Item "fc_register (type, name, proc)"
+Registers filter chain callbacks with collectd.
+.Sp
+\&\fItype\fR may be any of:
+.RS 4
+.IP "\s-1FC_MATCH\s0" 4
+.IX Item "FC_MATCH"
+.PD 0
+.IP "\s-1FC_TARGET\s0" 4
+.IX Item "FC_TARGET"
+.RE
+.RS 4
+.PD
+.Sp
+\&\fIname\fR is the name of the match or target. By this name, the callbacks are
+identified in the configuration file when specifying a \fBMatch\fR or \fBTarget\fR
+block (see \fIcollectd.conf\fR\|(5) for details).
+.Sp
+\&\fIproc\fR is a hash reference. The hash includes up to three callbacks: an
+optional constructor (\fBcreate\fR) and destructor (\fBdestroy\fR) and a mandatory
+\&\fBmatch\fR or \fBinvoke\fR callback. \fBmatch\fR is called whenever processing an
+appropriate match, while \fBinvoke\fR is called whenever processing an
+appropriate target (see the section \*(L"\s-1FILTER CONFIGURATION\*(R"\s0 in
+\&\fIcollectd.conf\fR\|(5) for details). Just like any other callbacks, filter chain
+callbacks are identified by the function name rather than a function pointer
+because Perl does not support to share references to subroutines between
+threads. The following arguments are passed to the callbacks:
+.IP "create" 4
+.IX Item "create"
+The arguments passed are \fIconfig-item\fR and \fIuser-data\fR. See above for the
+layout of the config-item data-type. \fIuser-data\fR is a reference to a scalar
+value that may be used to store any information specific to this particular
+instance. The daemon does not care about this information at all. It's for the
+plugin's use only.
+.IP "destroy" 4
+.IX Item "destroy"
+The only argument passed is \fIuser-data\fR which is a reference to the user data
+initialized in the \fBcreate\fR callback. This callback may be used to cleanup
+instance-specific information and settings.
+.IP "match, invoke" 4
+.IX Item "match, invoke"
+The arguments passed are \fIdata-set\fR, \fIvalue-list\fR, \fImeta\fR and \fIuser-data\fR.
+See above for the layout of the data-set and value-list data-types. \fImeta\fR is
+a pointer to an array of meta information, just like the \fBmeta\fR member of the
+notification data-type (see above). \fIuser-data\fR is a reference to the user
+data initialized in the \fBcreate\fR callback.
+.RE
+.RS 4
+.RE
+.SH "GLOBAL VARIABLES"
+.IX Header "GLOBAL VARIABLES"
+.ie n .IP "\fB\fB$hostname_g\fB\fR" 4
+.el .IP "\fB\f(CB$hostname_g\fB\fR" 4
+.IX Item "$hostname_g"
+As the name suggests this variable keeps the hostname of the system collectd
+is running on. The value might be influenced by the \fBHostname\fR or
+\&\fBFQDNLookup\fR configuration options (see \fIcollectd.conf\fR\|(5) for details).
+.ie n .IP "\fB\fB$interval_g\fB\fR" 4
+.el .IP "\fB\f(CB$interval_g\fB\fR" 4
+.IX Item "$interval_g"
+This variable keeps the interval in seconds in which the read functions are
+queried (see the \fBInterval\fR configuration option).
+.Sp
+\&\fBNote:\fR This variable should no longer be used in favor of
+\&\f(CW\*(C`plugin_get_interval()\*(C'\fR (see above). This function takes any plugin-specific
+interval settings into account (see the \f(CW\*(C`Interval\*(C'\fR option of \f(CW\*(C`LoadPlugin\*(C'\fR in
+\&\fIcollectd.conf\fR\|(5) for details).
+.PP
+Any changes to these variables will be globally visible in collectd.
+.SH "EXPORTS"
+.IX Header "EXPORTS"
+By default no symbols are exported. However, the following export tags are
+available (\fB:all\fR will export all of them):
+.IP "\fB:plugin\fR" 4
+.IX Item ":plugin"
+.RS 4
+.PD 0
+.IP "\fBplugin_register\fR ()" 4
+.IX Item "plugin_register ()"
+.IP "\fBplugin_unregister\fR ()" 4
+.IX Item "plugin_unregister ()"
+.IP "\fBplugin_dispatch_values\fR ()" 4
+.IX Item "plugin_dispatch_values ()"
+.IP "\fBplugin_flush\fR ()" 4
+.IX Item "plugin_flush ()"
+.IP "\fBplugin_flush_one\fR ()" 4
+.IX Item "plugin_flush_one ()"
+.IP "\fBplugin_flush_all\fR ()" 4
+.IX Item "plugin_flush_all ()"
+.IP "\fBplugin_dispatch_notification\fR ()" 4
+.IX Item "plugin_dispatch_notification ()"
+.IP "\fBplugin_log\fR ()" 4
+.IX Item "plugin_log ()"
+.RE
+.RS 4
+.RE
+.IP "\fB:types\fR" 4
+.IX Item ":types"
+.RS 4
+.IP "\fB\s-1TYPE_CONFIG\s0\fR" 4
+.IX Item "TYPE_CONFIG"
+.IP "\fB\s-1TYPE_INIT\s0\fR" 4
+.IX Item "TYPE_INIT"
+.IP "\fB\s-1TYPE_READ\s0\fR" 4
+.IX Item "TYPE_READ"
+.IP "\fB\s-1TYPE_WRITE\s0\fR" 4
+.IX Item "TYPE_WRITE"
+.IP "\fB\s-1TYPE_FLUSH\s0\fR" 4
+.IX Item "TYPE_FLUSH"
+.IP "\fB\s-1TYPE_SHUTDOWN\s0\fR" 4
+.IX Item "TYPE_SHUTDOWN"
+.IP "\fB\s-1TYPE_LOG\s0\fR" 4
+.IX Item "TYPE_LOG"
+.IP "\fB\s-1TYPE_DATASET\s0\fR" 4
+.IX Item "TYPE_DATASET"
+.RE
+.RS 4
+.RE
+.IP "\fB:ds_types\fR" 4
+.IX Item ":ds_types"
+.RS 4
+.IP "\fB\s-1DS_TYPE_COUNTER\s0\fR" 4
+.IX Item "DS_TYPE_COUNTER"
+.IP "\fB\s-1DS_TYPE_GAUGE\s0\fR" 4
+.IX Item "DS_TYPE_GAUGE"
+.IP "\fB\s-1DS_TYPE_DERIVE\s0\fR" 4
+.IX Item "DS_TYPE_DERIVE"
+.IP "\fB\s-1DS_TYPE_ABSOLUTE\s0\fR" 4
+.IX Item "DS_TYPE_ABSOLUTE"
+.RE
+.RS 4
+.RE
+.IP "\fB:log\fR" 4
+.IX Item ":log"
+.RS 4
+.IP "\fB\s-1ERROR\s0\fR ()" 4
+.IX Item "ERROR ()"
+.IP "\fB\s-1WARNING\s0\fR ()" 4
+.IX Item "WARNING ()"
+.IP "\fB\s-1NOTICE\s0\fR ()" 4
+.IX Item "NOTICE ()"
+.IP "\fB\s-1INFO\s0\fR ()" 4
+.IX Item "INFO ()"
+.IP "\fB\s-1DEBUG\s0\fR ()" 4
+.IX Item "DEBUG ()"
+.IP "\fB\s-1LOG_ERR\s0\fR" 4
+.IX Item "LOG_ERR"
+.IP "\fB\s-1LOG_WARNING\s0\fR" 4
+.IX Item "LOG_WARNING"
+.IP "\fB\s-1LOG_NOTICE\s0\fR" 4
+.IX Item "LOG_NOTICE"
+.IP "\fB\s-1LOG_INFO\s0\fR" 4
+.IX Item "LOG_INFO"
+.IP "\fB\s-1LOG_DEBUG\s0\fR" 4
+.IX Item "LOG_DEBUG"
+.RE
+.RS 4
+.RE
+.IP "\fB:filter_chain\fR" 4
+.IX Item ":filter_chain"
+.RS 4
+.IP "\fBfc_register\fR" 4
+.IX Item "fc_register"
+.IP "\fB\s-1FC_MATCH_NO_MATCH\s0\fR" 4
+.IX Item "FC_MATCH_NO_MATCH"
+.IP "\fB\s-1FC_MATCH_MATCHES\s0\fR" 4
+.IX Item "FC_MATCH_MATCHES"
+.IP "\fB\s-1FC_TARGET_CONTINUE\s0\fR" 4
+.IX Item "FC_TARGET_CONTINUE"
+.IP "\fB\s-1FC_TARGET_STOP\s0\fR" 4
+.IX Item "FC_TARGET_STOP"
+.IP "\fB\s-1FC_TARGET_RETURN\s0\fR" 4
+.IX Item "FC_TARGET_RETURN"
+.RE
+.RS 4
+.RE
+.IP "\fB:fc_types\fR" 4
+.IX Item ":fc_types"
+.RS 4
+.IP "\fB\s-1FC_MATCH\s0\fR" 4
+.IX Item "FC_MATCH"
+.IP "\fB\s-1FC_TARGET\s0\fR" 4
+.IX Item "FC_TARGET"
+.RE
+.RS 4
+.RE
+.IP "\fB:notif\fR" 4
+.IX Item ":notif"
+.RS 4
+.IP "\fB\s-1NOTIF_FAILURE\s0\fR" 4
+.IX Item "NOTIF_FAILURE"
+.IP "\fB\s-1NOTIF_WARNING\s0\fR" 4
+.IX Item "NOTIF_WARNING"
+.IP "\fB\s-1NOTIF_OKAY\s0\fR" 4
+.IX Item "NOTIF_OKAY"
+.RE
+.RS 4
+.RE
+.IP "\fB:globals\fR" 4
+.IX Item ":globals"
+.RS 4
+.ie n .IP "\fB\fB$hostname_g\fB\fR" 4
+.el .IP "\fB\f(CB$hostname_g\fB\fR" 4
+.IX Item "$hostname_g"
+.ie n .IP "\fB\fB$interval_g\fB\fR" 4
+.el .IP "\fB\f(CB$interval_g\fB\fR" 4
+.IX Item "$interval_g"
+.RE
+.RS 4
+.RE
+.PD
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+Any Perl plugin will start similar to:
+.PP
+.Vb 1
+\&  package Collectd::Plugins::FooBar;
+\&
+\&  use strict;
+\&  use warnings;
+\&
+\&  use Collectd qw( :all );
+.Ve
+.PP
+A very simple read function might look like:
+.PP
+.Vb 7
+\&  sub foobar_read
+\&  {
+\&    my $vl = { plugin => \*(Aqfoobar\*(Aq, type => \*(Aqgauge\*(Aq };
+\&    $vl\->{\*(Aqvalues\*(Aq} = [ rand(42) ];
+\&    plugin_dispatch_values ($vl);
+\&    return 1;
+\&  }
+.Ve
+.PP
+A very simple write function might look like:
+.PP
+.Vb 8
+\&  sub foobar_write
+\&  {
+\&    my ($type, $ds, $vl) = @_;
+\&    for (my $i = 0; $i < scalar (@$ds); ++$i) {
+\&      print "$vl\->{\*(Aqplugin\*(Aq} ($vl\->{\*(Aqtype\*(Aq}): $vl\->{\*(Aqvalues\*(Aq}\->[$i]\en";
+\&    }
+\&    return 1;
+\&  }
+.Ve
+.PP
+A very simple match callback might look like:
+.PP
+.Vb 9
+\&  sub foobar_match
+\&  {
+\&    my ($ds, $vl, $meta, $user_data) = @_;
+\&    if (matches($ds, $vl)) {
+\&      return FC_MATCH_MATCHES;
+\&    } else {
+\&      return FC_MATCH_NO_MATCH;
+\&    }
+\&  }
+.Ve
+.PP
+To register those functions with collectd:
+.PP
+.Vb 2
+\&  plugin_register (TYPE_READ, "foobar", "foobar_read");
+\&  plugin_register (TYPE_WRITE, "foobar", "foobar_write");
+\&
+\&  fc_register (FC_MATCH, "foobar", "foobar_match");
+.Ve
+.PP
+See the section \*(L"\s-1DATA TYPES\*(R"\s0 above for a complete documentation of the data
+types used by the read, write and match functions.
+.SH "NOTES"
+.IX Header "NOTES"
+.IP "\(bu" 4
+Please feel free to send in new plugins to collectd's mailing list at
+<collectd\ at\ collectd.org> for review and, possibly,
+inclusion in the main distribution. In the latter case, we will take care of
+keeping the plugin up to date and adapting it to new versions of collectd.
+.Sp
+Before submitting your plugin, please take a look at
+<http://collectd.org/dev\-info.shtml>.
+.SH "CAVEATS"
+.IX Header "CAVEATS"
+.IP "\(bu" 4
+collectd is heavily multi-threaded. Each collectd thread accessing the perl
+plugin will be mapped to a Perl interpreter thread (see \fIthreads\fR\|(3perl)).
+Any such thread will be created and destroyed transparently and on-the-fly.
+.Sp
+Hence, any plugin has to be thread-safe if it provides several entry points
+from collectd (i.\ e. if it registers more than one callback or if a
+registered callback may be called more than once in parallel). Please note
+that no data is shared between threads by default. You have to use the
+\&\fBthreads::shared\fR module to do so.
+.IP "\(bu" 4
+Each function name registered with collectd has to be available before the
+first thread has been created (i.\ e. basically at compile time). This
+basically means that hacks (yes, I really consider this to be a hack) like
+\&\f(CW\*(C`*foo = \e&bar; plugin_register (TYPE_READ, "plugin", "foo");\*(C'\fR most likely
+will not work. This is due to the fact that the symbol table is not shared
+across different threads.
+.IP "\(bu" 4
+Each plugin is usually only loaded once and kept in memory for performance
+reasons. Therefore, \s-1END\s0 blocks are only executed once when collectd shuts
+down. You should not rely on \s-1END\s0 blocks anyway \- use \fBshutdown functions\fR
+instead.
+.IP "\(bu" 4
+The perl plugin exports the internal \s-1API\s0 of collectd which is considered
+unstable and subject to change at any time. We try hard to not break backwards
+compatibility in the Perl \s-1API\s0 during the life cycle of one major release.
+However, this cannot be guaranteed at all times. Watch out for warnings
+dispatched by the perl plugin after upgrades.
+.SH "KNOWN BUGS"
+.IX Header "KNOWN BUGS"
+.IP "\(bu" 4
+Currently, it is not possible to flush a single Perl plugin only. You can
+either flush all Perl plugins or none at all and you have to use \f(CW\*(C`perl\*(C'\fR as
+plugin name when doing so.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-exec\fR\|(5),
+\&\fItypes.db\fR\|(5),
+\&\fIperl\fR\|(1),
+\&\fIthreads\fR\|(3perl),
+\&\fIthreads::shared\fR\|(3perl),
+\&\fIperldebug\fR\|(1)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+The \f(CW\*(C`perl plugin\*(C'\fR has been written by Sebastian Harl
+<sh\ at\ tokkee.org>.
+.PP
+This manpage has been written by Florian Forster
+<octo\ at\ collectd.org> and Sebastian Harl
+<sh\ at\ tokkee.org>.
diff --git a/src/collectd-perl.pod b/src/collectd-perl.pod
new file mode 100644 (file)
index 0000000..7308648
--- /dev/null
@@ -0,0 +1,795 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-perl - Documentation of collectd's C<perl plugin>
+
+=head1 SYNOPSIS
+
+  LoadPlugin perl
+  # ...
+  <Plugin perl>
+    IncludeDir "/path/to/perl/plugins"
+    BaseName "Collectd::Plugins"
+    EnableDebugger ""
+    LoadPlugin "FooBar"
+
+    <Plugin FooBar>
+      Foo "Bar"
+    </Plugin>
+  </Plugin>
+
+=head1 DESCRIPTION
+
+The C<perl plugin> embeds a Perl-interpreter into collectd and provides an
+interface to collectd's plugin system. This makes it possible to write plugins
+for collectd in Perl. This is a lot more efficient than executing a
+Perl-script every time you want to read a value with the C<exec plugin> (see
+L<collectd-exec(5)>) and provides a lot more functionality, too.
+
+=head1 CONFIGURATION
+
+=over 4
+
+=item B<LoadPlugin> I<Plugin>
+
+Loads the Perl plugin I<Plugin>. This does basically the same as B<use> would
+do in a Perl program. As a side effect, the first occurrence of this option
+causes the Perl-interpreter to be initialized.
+
+=item B<BaseName> I<Name>
+
+Prepends I<Name>B<::> to all plugin names loaded after this option. This is
+provided for convenience to keep plugin names short. All Perl-based plugins
+provided with the I<collectd> distributions reside in the C<Collectd::Plugins>
+namespace.
+
+=item E<lt>B<Plugin> I<Name>E<gt> block
+
+This block may be used to pass on configuration settings to a Perl plugin. The
+configuration is converted into a config-item data type which is passed to the
+registered configuration callback. See below for details about the config-item
+data type and how to register callbacks.
+
+The I<name> identifies the callback. It is used literally and independent of
+the B<BaseName> setting.
+
+=item B<EnableDebugger> I<Package>[=I<option>,...]
+
+Run collectd under the control of the Perl source debugger. If I<Package> is
+not the empty string, control is passed to the debugging, profiling, or
+tracing module installed as Devel::I<Package>. A comma-separated list of
+options may be specified after the "=" character. Please note that you may not
+leave out the I<Package> option even if you specify B<"">. This is the same as
+using the B<-d:Package> command line option.
+
+See L<perldebug> for detailed documentation about debugging Perl.
+
+This option does not prevent collectd from daemonizing, so you should start
+collectd with the B<-f> command line option. Else you will not be able to use
+the command line driven interface of the debugger.
+
+=item B<IncludeDir> I<Dir>
+
+Adds I<Dir> to the B<@INC> array. This is the same as using the B<-IDir>
+command line option or B<use lib Dir> in the source code. Please note that it
+only has effect on plugins loaded after this option.
+
+=back
+
+=head1 WRITING YOUR OWN PLUGINS
+
+Writing your own plugins is quite simple. collectd manages plugins by means of
+B<dispatch functions> which call the appropriate B<callback functions>
+registered by the plugins. Any plugin basically consists of the implementation
+of these callback functions and initializing code which registers the
+functions with collectd. See the section "EXAMPLES" below for a really basic
+example. The following types of B<callback functions> are known to collectd
+(all of them are optional):
+
+=over 4
+
+=item configuration functions
+
+This type of functions is called during configuration if an appropriate
+B<Plugin> block has been encountered. It is called once for each B<Plugin>
+block which matches the name of the callback as provided with the
+B<plugin_register> method - see below.
+
+=item init functions
+
+This type of functions is called once after loading the module and before any
+calls to the read and write functions. It should be used to initialize the
+internal state of the plugin (e.E<nbsp>g. open sockets, ...). If the return
+value evaluates to B<false>, the plugin will be disabled.
+
+=item read functions
+
+This type of function is used to collect the actual data. It is called once
+per interval (see the B<Interval> configuration option of collectd). Usually
+it will call B<plugin_dispatch_values> to dispatch the values to collectd
+which will pass them on to all registered B<write functions>. If the return
+value evaluates to B<false> the plugin will be skipped for an increasing
+amount of time until it returns B<true> again.
+
+=item write functions
+
+This type of function is used to write the dispatched values. It is called
+once for each call to B<plugin_dispatch_values>.
+
+=item flush functions
+
+This type of function is used to flush internal caches of plugins. It is
+usually triggered by the user only. Any plugin which caches data before
+writing it to disk should provide this kind of callback function.
+
+=item log functions
+
+This type of function is used to pass messages of plugins or the daemon itself
+to the user.
+
+=item notification function
+
+This type of function is used to act upon notifications. In general, a
+notification is a status message that may be associated with a data instance.
+Usually, a notification is generated by the daemon if a configured threshold
+has been exceeded (see the section "THRESHOLD CONFIGURATION" in
+L<collectd.conf(5)> for more details), but any plugin may dispatch
+notifications as well.
+
+=item shutdown functions
+
+This type of function is called once before the daemon shuts down. It should
+be used to clean up the plugin (e.g. close sockets, ...).
+
+=back
+
+Any function (except log functions) may set the B<$@> variable to describe
+errors in more detail. The message will be passed on to the user using
+collectd's logging mechanism.
+
+See the documentation of the B<plugin_register> method in the section
+"METHODS" below for the number and types of arguments passed to each
+B<callback function>. This section also explains how to register B<callback
+functions> with collectd.
+
+To enable a plugin, copy it to a place where Perl can find it (i.E<nbsp>e. a
+directory listed in the B<@INC> array) just as any other Perl plugin and add
+an appropriate B<LoadPlugin> option to the configuration file. After
+restarting collectd you're done.
+
+=head1 DATA TYPES
+
+The following complex types are used to pass values between the Perl plugin
+and collectd:
+
+=over 4
+
+=item Config-Item
+
+A config-item is one structure which keeps the information provided in the
+configuration file. The array of children keeps one entry for each
+configuration option. Each such entry is another config-item structure, which
+may nest further if nested blocks are used.
+
+  {
+    key      => key,
+    values   => [ val1, val2, ... ],
+    children => [ { ... }, { ... }, ... ]
+  }
+
+=item Data-Set
+
+A data-set is a list of one or more data-sources. Each data-source defines a
+name, type, min- and max-value and the data-set wraps them up into one
+structure. The general layout looks like this:
+
+  [{
+    name => 'data_source_name',
+    type => DS_TYPE_COUNTER || DS_TYPE_GAUGE || DS_TYPE_DERIVE || DS_TYPE_ABSOLUTE,
+    min  => value || undef,
+    max  => value || undef
+  }, ...]
+
+=item Value-List
+
+A value-list is one structure which features an array of values and fields to
+identify the values, i.E<nbsp>e. time and host, plugin name and
+plugin-instance as well as a type and type-instance. Since the "type" is not
+included in the value-list but is passed as an extra argument, the general
+layout looks like this:
+
+  {
+    values => [123, 0.5],
+    time   => time (),
+    interval => plugin_get_interval (),
+    host   => $hostname_g,
+    plugin => 'myplugin',
+    type   => 'myplugin',
+    plugin_instance => '',
+    type_instance   => ''
+  }
+
+=item Notification
+
+A notification is one structure defining the severity, time and message of the
+status message as well as an identification of a data instance. Also, it
+includes an optional list of user-defined meta information represented as
+(name, value) pairs:
+
+  {
+    severity => NOTIF_FAILURE || NOTIF_WARNING || NOTIF_OKAY,
+    time     => time (),
+    message  => 'status message',
+    host     => $hostname_g,
+    plugin   => 'myplugin',
+    type     => 'mytype',
+    plugin_instance => '',
+    type_instance   => '',
+    meta     => [ { name => <name>, value => <value> }, ... ]
+  }
+
+=item Match-Proc
+
+A match-proc is one structure storing the callbacks of a "match" of the filter
+chain infrastructure. The general layout looks like this:
+
+  {
+    create  => 'my_create',
+    destroy => 'my_destroy',
+    match   => 'my_match'
+  }
+
+=item Target-Proc
+
+A target-proc is one structure storing the callbacks of a "target" of the
+filter chain infrastructure. The general layout looks like this:
+
+  {
+    create  => 'my_create',
+    destroy => 'my_destroy',
+    invoke  => 'my_invoke'
+  }
+
+=back
+
+=head1 METHODS
+
+The following functions provide the C-interface to Perl-modules. They are
+exported by the ":plugin" export tag (see the section "EXPORTS" below).
+
+=over 4
+
+=item B<plugin_register> (I<type>, I<name>, I<data>)
+
+Registers a callback-function or data-set.
+
+I<type> can be one of:
+
+=over 4
+
+=item TYPE_CONFIG
+
+=item TYPE_INIT
+
+=item TYPE_READ
+
+=item TYPE_WRITE
+
+=item TYPE_FLUSH
+
+=item TYPE_LOG
+
+=item TYPE_NOTIF
+
+=item TYPE_SHUTDOWN
+
+=item TYPE_DATASET
+
+=back
+
+I<name> is the name of the callback-function or the type of the data-set,
+depending on the value of I<type>. (Please note that the type of the data-set
+is the value passed as I<name> here and has nothing to do with the I<type>
+argument which simply tells B<plugin_register> what is being registered.)
+
+The last argument, I<data>, is either a function name or an array-reference.
+If I<type> is B<TYPE_DATASET>, then the I<data> argument must be an
+array-reference which points to an array of hashes. Each hash describes one
+data-set. For the exact layout see B<Data-Set> above. Please note that
+there is a large number of predefined data-sets available in the B<types.db>
+file which are automatically registered with collectd - see L<types.db(5)> for
+a description of the format of this file.
+
+B<Note>: Using B<plugin_register> to register a data-set is deprecated. Add
+the new type to a custom L<types.db(5)> file instead. This functionality might
+be removed in a future version of collectd.
+
+If the I<type> argument is any of the other types (B<TYPE_INIT>, B<TYPE_READ>,
+...) then I<data> is expected to be a function name. If the name is not
+prefixed with the plugin's package name collectd will add it automatically.
+The interface slightly differs from the C interface (which expects a function
+pointer instead) because Perl does not support to share references to
+subroutines between threads.
+
+These functions are called in the various stages of the daemon (see the
+section "WRITING YOUR OWN PLUGINS" above) and are passed the following
+arguments:
+
+=over 4
+
+=item TYPE_CONFIG
+
+The only argument passed is I<config-item>. See above for the layout of this
+data type.
+
+=item TYPE_INIT
+
+=item TYPE_READ
+
+=item TYPE_SHUTDOWN
+
+No arguments are passed.
+
+=item TYPE_WRITE
+
+The arguments passed are I<type>, I<data-set>, and I<value-list>. I<type> is a
+string. For the layout of I<data-set> and I<value-list> see above.
+
+=item TYPE_FLUSH
+
+The arguments passed are I<timeout> and I<identifier>. I<timeout> indicates
+that only data older than I<timeout> seconds is to be flushed. I<identifier>
+specifies which values are to be flushed.
+
+=item TYPE_LOG
+
+The arguments are I<log-level> and I<message>. The log level is small for
+important messages and high for less important messages. The least important
+level is B<LOG_DEBUG>, the most important level is B<LOG_ERR>. In between there
+are (from least to most important): B<LOG_INFO>, B<LOG_NOTICE>, and
+B<LOG_WARNING>. I<message> is simply a string B<without> a newline at the end.
+
+=item TYPE_NOTIF
+
+The only argument passed is I<notification>. See above for the layout of this
+data type.
+
+=back
+
+=item B<plugin_unregister> (I<type>, I<plugin>)
+
+Removes a callback or data-set from collectd's internal list of
+functionsE<nbsp>/ datasets.
+
+=item B<plugin_dispatch_values> (I<value-list>)
+
+Submits a I<value-list> to the daemon. If the data-set identified by
+I<value-list>->{I<type>}
+is found (and the number of values matches the number of data-sources) then the
+type, data-set and value-list is passed to all write-callbacks that are
+registered with the daemon.
+
+=item B<plugin_write> ([B<plugins> => I<...>][, B<datasets> => I<...>],
+B<valuelists> => I<...>)
+
+Calls the write function of the given I<plugins> with the provided I<data
+sets> and I<value lists>. In contrast to B<plugin_dispatch_values>, it does
+not update collectd's internal cache and bypasses the filter mechanism (see
+L<collectd.conf(5)> for details). If the B<plugins> argument has been omitted,
+the values will be dispatched to all registered write plugins. If the
+B<datasets> argument has been omitted, the required data sets are looked up
+according to the C<type> member in the appropriate value list. The value of
+all three arguments may either be a single scalar or a reference to an array.
+If the B<datasets> argument has been specified, the number of data sets has to
+equal the number of specified value lists.
+
+=item B<plugin_flush> ([B<timeout> => I<timeout>][, B<plugins> => I<...>][,
+B<identifiers> => I<...>])
+
+Flush one or more plugins. I<timeout> and the specified I<identifiers> are
+passed on to the registered flush-callbacks. If omitted, the timeout defaults
+to C<-1>. The identifier defaults to the undefined value. If the B<plugins>
+argument has been specified, only named plugins will be flushed. The value of
+the B<plugins> and B<identifiers> arguments may either be a string or a
+reference to an array of strings.
+
+=item B<plugin_dispatch_notification> (I<notification>)
+
+Submits a I<notification> to the daemon which will then pass it to all
+notification-callbacks that are registered.
+
+=item B<plugin_log> (I<log-level>, I<message>)
+
+Submits a I<message> of level I<log-level> to collectd's logging mechanism.
+The message is passed to all log-callbacks that are registered with collectd.
+
+=item B<ERROR>, B<WARNING>, B<NOTICE>, B<INFO>, B<DEBUG> (I<message>)
+
+Wrappers around B<plugin_log>, using B<LOG_ERR>, B<LOG_WARNING>,
+B<LOG_NOTICE>, B<LOG_INFO> and B<LOG_DEBUG> respectively as I<log-level>.
+
+=item B<plugin_get_interval> ()
+
+Returns the interval of the current plugin as a floating point number in
+seconds. This value depends on the interval configured within the
+C<LoadPlugin perl> block or the global interval (see L<collectd.conf(5)> for
+details).
+
+=back
+
+The following function provides the filter chain C-interface to Perl-modules.
+It is exported by the ":filter_chain" export tag (see the section "EXPORTS"
+below).
+
+=over 4
+
+=item B<fc_register> (I<type>, I<name>, I<proc>)
+
+Registers filter chain callbacks with collectd.
+
+I<type> may be any of:
+
+=over 4
+
+=item FC_MATCH
+
+=item FC_TARGET
+
+=back
+
+I<name> is the name of the match or target. By this name, the callbacks are
+identified in the configuration file when specifying a B<Match> or B<Target>
+block (see L<collectd.conf(5)> for details).
+
+I<proc> is a hash reference. The hash includes up to three callbacks: an
+optional constructor (B<create>) and destructor (B<destroy>) and a mandatory
+B<match> or B<invoke> callback. B<match> is called whenever processing an
+appropriate match, while B<invoke> is called whenever processing an
+appropriate target (see the section "FILTER CONFIGURATION" in
+L<collectd.conf(5)> for details). Just like any other callbacks, filter chain
+callbacks are identified by the function name rather than a function pointer
+because Perl does not support to share references to subroutines between
+threads. The following arguments are passed to the callbacks:
+
+=over 4
+
+=item create
+
+The arguments passed are I<config-item> and I<user-data>. See above for the
+layout of the config-item data-type. I<user-data> is a reference to a scalar
+value that may be used to store any information specific to this particular
+instance. The daemon does not care about this information at all. It's for the
+plugin's use only.
+
+=item destroy
+
+The only argument passed is I<user-data> which is a reference to the user data
+initialized in the B<create> callback. This callback may be used to cleanup
+instance-specific information and settings.
+
+=item match, invoke
+
+The arguments passed are I<data-set>, I<value-list>, I<meta> and I<user-data>.
+See above for the layout of the data-set and value-list data-types. I<meta> is
+a pointer to an array of meta information, just like the B<meta> member of the
+notification data-type (see above). I<user-data> is a reference to the user
+data initialized in the B<create> callback.
+
+=back
+
+=back
+
+=head1 GLOBAL VARIABLES
+
+=over 4
+
+=item B<$hostname_g>
+
+As the name suggests this variable keeps the hostname of the system collectd
+is running on. The value might be influenced by the B<Hostname> or
+B<FQDNLookup> configuration options (see L<collectd.conf(5)> for details).
+
+=item B<$interval_g>
+
+This variable keeps the interval in seconds in which the read functions are
+queried (see the B<Interval> configuration option).
+
+B<Note:> This variable should no longer be used in favor of
+C<plugin_get_interval()> (see above). This function takes any plugin-specific
+interval settings into account (see the C<Interval> option of C<LoadPlugin> in
+L<collectd.conf(5)> for details).
+
+=back
+
+Any changes to these variables will be globally visible in collectd.
+
+=head1 EXPORTS
+
+By default no symbols are exported. However, the following export tags are
+available (B<:all> will export all of them):
+
+=over 4
+
+=item B<:plugin>
+
+=over 4
+
+=item B<plugin_register> ()
+
+=item B<plugin_unregister> ()
+
+=item B<plugin_dispatch_values> ()
+
+=item B<plugin_flush> ()
+
+=item B<plugin_flush_one> ()
+
+=item B<plugin_flush_all> ()
+
+=item B<plugin_dispatch_notification> ()
+
+=item B<plugin_log> ()
+
+=back
+
+=item B<:types>
+
+=over 4
+
+=item B<TYPE_CONFIG>
+
+=item B<TYPE_INIT>
+
+=item B<TYPE_READ>
+
+=item B<TYPE_WRITE>
+
+=item B<TYPE_FLUSH>
+
+=item B<TYPE_SHUTDOWN>
+
+=item B<TYPE_LOG>
+
+=item B<TYPE_DATASET>
+
+=back
+
+=item B<:ds_types>
+
+=over 4
+
+=item B<DS_TYPE_COUNTER>
+
+=item B<DS_TYPE_GAUGE>
+
+=item B<DS_TYPE_DERIVE>
+
+=item B<DS_TYPE_ABSOLUTE>
+
+=back
+
+=item B<:log>
+
+=over 4
+
+=item B<ERROR> ()
+
+=item B<WARNING> ()
+
+=item B<NOTICE> ()
+
+=item B<INFO> ()
+
+=item B<DEBUG> ()
+
+=item B<LOG_ERR>
+
+=item B<LOG_WARNING>
+
+=item B<LOG_NOTICE>
+
+=item B<LOG_INFO>
+
+=item B<LOG_DEBUG>
+
+=back
+
+=item B<:filter_chain>
+
+=over 4
+
+=item B<fc_register>
+
+=item B<FC_MATCH_NO_MATCH>
+
+=item B<FC_MATCH_MATCHES>
+
+=item B<FC_TARGET_CONTINUE>
+
+=item B<FC_TARGET_STOP>
+
+=item B<FC_TARGET_RETURN>
+
+=back
+
+=item B<:fc_types>
+
+=over 4
+
+=item B<FC_MATCH>
+
+=item B<FC_TARGET>
+
+=back
+
+=item B<:notif>
+
+=over 4
+
+=item B<NOTIF_FAILURE>
+
+=item B<NOTIF_WARNING>
+
+=item B<NOTIF_OKAY>
+
+=back
+
+=item B<:globals>
+
+=over 4
+
+=item B<$hostname_g>
+
+=item B<$interval_g>
+
+=back
+
+=back
+
+=head1 EXAMPLES
+
+Any Perl plugin will start similar to:
+
+  package Collectd::Plugins::FooBar;
+
+  use strict;
+  use warnings;
+
+  use Collectd qw( :all );
+
+A very simple read function might look like:
+
+  sub foobar_read
+  {
+    my $vl = { plugin => 'foobar', type => 'gauge' };
+    $vl->{'values'} = [ rand(42) ];
+    plugin_dispatch_values ($vl);
+    return 1;
+  }
+
+A very simple write function might look like:
+
+  sub foobar_write
+  {
+    my ($type, $ds, $vl) = @_;
+    for (my $i = 0; $i < scalar (@$ds); ++$i) {
+      print "$vl->{'plugin'} ($vl->{'type'}): $vl->{'values'}->[$i]\n";
+    }
+    return 1;
+  }
+
+A very simple match callback might look like:
+
+  sub foobar_match
+  {
+    my ($ds, $vl, $meta, $user_data) = @_;
+    if (matches($ds, $vl)) {
+      return FC_MATCH_MATCHES;
+    } else {
+      return FC_MATCH_NO_MATCH;
+    }
+  }
+
+To register those functions with collectd:
+
+  plugin_register (TYPE_READ, "foobar", "foobar_read");
+  plugin_register (TYPE_WRITE, "foobar", "foobar_write");
+
+  fc_register (FC_MATCH, "foobar", "foobar_match");
+
+See the section "DATA TYPES" above for a complete documentation of the data
+types used by the read, write and match functions.
+
+=head1 NOTES
+
+=over 4
+
+=item
+
+Please feel free to send in new plugins to collectd's mailing list at
+E<lt>collectdE<nbsp>atE<nbsp>collectd.orgE<gt> for review and, possibly,
+inclusion in the main distribution. In the latter case, we will take care of
+keeping the plugin up to date and adapting it to new versions of collectd.
+
+Before submitting your plugin, please take a look at
+L<http://collectd.org/dev-info.shtml>.
+
+=back
+
+=head1 CAVEATS
+
+=over 4
+
+=item
+
+collectd is heavily multi-threaded. Each collectd thread accessing the perl
+plugin will be mapped to a Perl interpreter thread (see L<threads(3perl)>).
+Any such thread will be created and destroyed transparently and on-the-fly.
+
+Hence, any plugin has to be thread-safe if it provides several entry points
+from collectd (i.E<nbsp>e. if it registers more than one callback or if a
+registered callback may be called more than once in parallel). Please note
+that no data is shared between threads by default. You have to use the
+B<threads::shared> module to do so.
+
+=item
+
+Each function name registered with collectd has to be available before the
+first thread has been created (i.E<nbsp>e. basically at compile time). This
+basically means that hacks (yes, I really consider this to be a hack) like
+C<*foo = \&bar; plugin_register (TYPE_READ, "plugin", "foo");> most likely
+will not work. This is due to the fact that the symbol table is not shared
+across different threads.
+
+=item
+
+Each plugin is usually only loaded once and kept in memory for performance
+reasons. Therefore, END blocks are only executed once when collectd shuts
+down. You should not rely on END blocks anyway - use B<shutdown functions>
+instead.
+
+=item
+
+The perl plugin exports the internal API of collectd which is considered
+unstable and subject to change at any time. We try hard to not break backwards
+compatibility in the Perl API during the life cycle of one major release.
+However, this cannot be guaranteed at all times. Watch out for warnings
+dispatched by the perl plugin after upgrades.
+
+=back
+
+=head1 KNOWN BUGS
+
+=over 4
+
+=item
+
+Currently, it is not possible to flush a single Perl plugin only. You can
+either flush all Perl plugins or none at all and you have to use C<perl> as
+plugin name when doing so.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-exec(5)>,
+L<types.db(5)>,
+L<perl(1)>,
+L<threads(3perl)>,
+L<threads::shared(3perl)>,
+L<perldebug(1)>
+
+=head1 AUTHOR
+
+The C<perl plugin> has been written by Sebastian Harl
+E<lt>shE<nbsp>atE<nbsp>tokkee.orgE<gt>.
+
+This manpage has been written by Florian Forster
+E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt> and Sebastian Harl
+E<lt>shE<nbsp>atE<nbsp>tokkee.orgE<gt>.
+
+=cut
+
diff --git a/src/collectd-python.5 b/src/collectd-python.5
new file mode 100644 (file)
index 0000000..e6091f9
--- /dev/null
@@ -0,0 +1,760 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-PYTHON 5"
+.TH COLLECTD-PYTHON 5 "2015-05-20" "5.4.2.911.g0c88d3b" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-python \- Documentation of collectd's "python plugin"
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 7
+\&  LoadPlugin python
+\&  # ...
+\&  <Plugin python>
+\&    ModulePath "/path/to/your/python/modules"
+\&    LogTraces true
+\&    Interactive false
+\&    Import "spam"
+\&
+\&    <Module spam>
+\&      spam "wonderful" "lovely"
+\&    </Module>
+\&  </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \f(CW\*(C`python plugin\*(C'\fR embeds a Python-interpreter into collectd and provides an
+interface to collectd's plugin system. This makes it possible to write plugins
+for collectd in Python. This is a lot more efficient than executing a
+Python-script every time you want to read a value with the \f(CW\*(C`exec plugin\*(C'\fR (see
+\&\fIcollectd\-exec\fR\|(5)) and provides a lot more functionality, too.
+.PP
+The minimum required Python version is \fI2.3\fR.
+.SH "CONFIGURATION"
+.IX Header "CONFIGURATION"
+.IP "\fBLoadPlugin\fR \fIPlugin\fR" 4
+.IX Item "LoadPlugin Plugin"
+Loads the Python plugin \fIPlugin\fR.
+.IP "\fBEncoding\fR \fIName\fR" 4
+.IX Item "Encoding Name"
+The default encoding for Unicode objects you pass to collectd. If you omit this
+option it will default to \fBascii\fR on \fIPython 2\fR. On \fIPython 3\fR it will
+always be \fButf\-8\fR, as this function was removed, so this will be silently
+ignored.
+These defaults are hardcoded in Python and will ignore everything else,
+including your locale.
+.IP "\fBModulePath\fR \fIName\fR" 4
+.IX Item "ModulePath Name"
+Prepends \fIName\fR to \fBsys.path\fR. You won't be able to import any scripts you
+wrote unless they are located in one of the directories in this list. Please
+note that it only has effect on plugins loaded after this option. You can
+use multiple \fBModulePath\fR lines to add more than one directory.
+.IP "\fBLogTraces\fR \fIbool\fR" 4
+.IX Item "LogTraces bool"
+If a Python script throws an exception it will be logged by collectd with the
+name of the exception and the message. If you set this option to true it will
+also log the full stacktrace just like the default output of an interactive
+Python interpreter. This should probably be set to false most of the time but
+is very useful for development and debugging of new modules.
+.IP "\fBInteractive\fR \fIbool\fR" 4
+.IX Item "Interactive bool"
+This option will cause the module to launch an interactive Python interpreter
+that reads from and writes to the terminal. Note that collectd will terminate
+right after starting up if you try to run it as a daemon while this option is
+enabled so make sure to start collectd with the \fB\-f\fR option.
+.Sp
+The \fBcollectd\fR module is \fInot\fR imported into the interpreter's globals. You
+have to do it manually. Be sure to read the help text of the module, it can be
+used as a reference guide during coding.
+.Sp
+This interactive session will behave slightly differently from a daemonized
+collectd script as well as from a normal Python interpreter:
+.RS 4
+.IP "\(bu" 4
+\&\fB1.\fR collectd will try to import the \fBreadline\fR module to give you a decent
+way of entering your commands. The daemonized collectd won't do that.
+.IP "\(bu" 4
+\&\fB2.\fR collectd will block \fI\s-1SIGINT\s0\fR. Pressing \fICtrl+C\fR will usually cause
+collectd to shut down. This would be problematic in an interactive session,
+therefore this signal will be blocked. You can still use it to interrupt
+syscalls like sleep and pause but it won't generate a \fIKeyboardInterrupt\fR
+exception either.
+.Sp
+To quit collectd send \fI\s-1EOF\s0\fR (press \fICtrl+D\fR at the beginning of a new line).
+.IP "\(bu" 4
+\&\fB3.\fR collectd handles \fI\s-1SIGCHLD\s0\fR. This means that Python won't be able to
+determine the return code of spawned processes with \fIsystem()\fR, \fIpopen()\fR and
+subprocess. This will result in Python not using external programs like less
+to display help texts. You can override this behavior with the \fB\s-1PAGER\s0\fR
+environment variable, e.g. \fIexport PAGER=less\fR before starting collectd.
+Depending on your version of Python this might or might not result in an
+\&\fBOSError\fR exception which can be ignored.
+.Sp
+If you really need to spawn new processes from Python you can register an init
+callback and reset the action for \s-1SIGCHLD\s0 to the default behavior. Please note
+that this \fIwill\fR break the exec plugin. Do not even load the exec plugin if
+you intend to do this!
+.Sp
+There is an example script located in \fBcontrib/python/getsigchld.py\fR  to do
+this. If you import this from \fIcollectd.conf\fR \s-1SIGCHLD\s0 will be handled
+normally and spawning processes from Python will work as intended.
+.RE
+.RS 4
+.RE
+.IP "<\fBModule\fR \fIName\fR> block" 4
+.IX Item "<Module Name> block"
+This block may be used to pass on configuration settings to a Python module.
+The configuration is converted into an instance of the \fBConfig\fR class which is
+passed to the registered configuration callback. See below for details about
+the \fBConfig\fR class and how to register callbacks.
+.Sp
+The \fIname\fR identifies the callback.
+.SH "STRINGS"
+.IX Header "STRINGS"
+There are a lot of places where strings are sent from collectd to Python and
+from Python to collectd. How exactly this works depends on whether byte or
+unicode strings or Python2 or Python3 are used.
+.PP
+Python2 has \fIstr\fR, which is just bytes, and \fIunicode\fR. Python3 has \fIstr\fR,
+which is a unicode object, and \fIbytes\fR.
+.PP
+When passing strings from Python to collectd all of these object are supported
+in all places, however \fIstr\fR should be used if possible. These strings must
+not contain a \s-1NUL\s0 byte. Ignoring this will result in a \fITypeError\fR exception.
+If a byte string was used it will be used as is by collectd. If a unicode
+object was used it will be encoded using the default encoding (see above). If
+this is not possible Python will raise a \fIUnicodeEncodeError\fR exception.
+.PP
+When passing strings from collectd to Python the behavior depends on the
+Python version used. Python2 will always receive a \fIstr\fR object. Python3 will
+usually receive a \fIstr\fR object as well, however the original string will be
+decoded to unicode using the default encoding. If this fails because the
+string is not a valid sequence for this encoding a \fIbytes\fR object will be
+returned instead.
+.SH "WRITING YOUR OWN PLUGINS"
+.IX Header "WRITING YOUR OWN PLUGINS"
+Writing your own plugins is quite simple. collectd manages plugins by means of
+\&\fBdispatch functions\fR which call the appropriate \fBcallback functions\fR
+registered by the plugins. Any plugin basically consists of the implementation
+of these callback functions and initializing code which registers the
+functions with collectd. See the section \*(L"\s-1EXAMPLES\*(R"\s0 below for a really basic
+example. The following types of \fBcallback functions\fR are known to collectd
+(all of them are optional):
+.IP "configuration functions" 4
+.IX Item "configuration functions"
+These are called during configuration if an appropriate
+\&\fBModule\fR block has been encountered. It is called once for each \fBModule\fR
+block which matches the name of the callback as provided with the
+\&\fBregister_config\fR method \- see below.
+.Sp
+Python thread support has not been initialized at this point so do not use any
+threading functions here!
+.IP "init functions" 4
+.IX Item "init functions"
+These are called once after loading the module and before any
+calls to the read and write functions. It should be used to initialize the
+internal state of the plugin (e.\ g. open sockets, ...). This is the
+earliest point where you may use threads.
+.IP "read functions" 4
+.IX Item "read functions"
+These are used to collect the actual data. It is called once
+per interval (see the \fBInterval\fR configuration option of collectd). Usually
+it will call \fBplugin_dispatch_values\fR to dispatch the values to collectd
+which will pass them on to all registered \fBwrite functions\fR. If this function
+throws any kind of exception the plugin will be skipped for an increasing
+amount of time until it returns normally again.
+.IP "write functions" 4
+.IX Item "write functions"
+These are used to write the dispatched values. It is called
+once for every value that was dispatched by any plugin.
+.IP "flush functions" 4
+.IX Item "flush functions"
+These are used to flush internal caches of plugins. It is
+usually triggered by the user only. Any plugin which caches data before
+writing it to disk should provide this kind of callback function.
+.IP "log functions" 4
+.IX Item "log functions"
+These are used to pass messages of plugins or the daemon itself
+to the user.
+.IP "notification function" 4
+.IX Item "notification function"
+These are used to act upon notifications. In general, a
+notification is a status message that may be associated with a data instance.
+Usually, a notification is generated by the daemon if a configured threshold
+has been exceeded (see the section \*(L"\s-1THRESHOLD CONFIGURATION\*(R"\s0 in
+\&\fIcollectd.conf\fR\|(5) for more details), but any plugin may dispatch
+notifications as well.
+.IP "shutdown functions" 4
+.IX Item "shutdown functions"
+These are called once before the daemon shuts down. It should
+be used to clean up the plugin (e.g. close sockets, ...).
+.PP
+Any function (except log functions) may throw an exception in case of
+errors. The exception will be passed on to the user using collectd's logging
+mechanism. If a log callback throws an exception it will be printed to standard
+error instead.
+.PP
+See the documentation of the various \fBregister_\fR methods in the section
+\&\*(L"\s-1FUNCTIONS\*(R"\s0 below for the number and types of arguments passed to each
+\&\fBcallback function\fR. This section also explains how to register \fBcallback
+functions\fR with collectd.
+.PP
+To enable a module, copy it to a place where Python can find it (i.\ e. a
+directory listed in \fBsys.path\fR) just as any other Python plugin and add
+an appropriate \fBImport\fR option to the configuration file. After restarting
+collectd you're done.
+.SH "CLASSES"
+.IX Header "CLASSES"
+The following complex types are used to pass values between the Python plugin
+and collectd:
+.SS "Signed"
+.IX Subsection "Signed"
+The Signed class is just a long. It has all its methods and behaves exactly
+like any other long object. It is used to indicate if an integer was or should
+be stored as a signed or unsigned integer object.
+.PP
+.Vb 1
+\& class Signed(long)
+.Ve
+.PP
+This is a long by another name. Use it in meta data dicts
+to choose the way it is stored in the meta data.
+.SS "Unsigned"
+.IX Subsection "Unsigned"
+The Unsigned class is just a long. It has all its methods and behaves exactly
+like any other long object. It is used to indicate if an integer was or should
+be stored as a signed or unsigned integer object.
+.PP
+.Vb 1
+\& class Unsigned(long)
+.Ve
+.PP
+This is a long by another name. Use it in meta data dicts
+to choose the way it is stored in the meta data.
+.SS "Config"
+.IX Subsection "Config"
+The Config class is an object which keeps the information provided in the
+configuration file. The sequence of children keeps one entry for each
+configuration option. Each such entry is another Config instance, which
+may nest further if nested blocks are used.
+.PP
+.Vb 1
+\& class Config(object)
+.Ve
+.PP
+This represents a piece of collectd's config file. It is passed to scripts with
+config callbacks (see \fBregister_config\fR) and is of little use if created
+somewhere else.
+.PP
+It has no methods beyond the bare minimum and only exists for its data members.
+.PP
+Data descriptors defined here:
+.IP "parent" 4
+.IX Item "parent"
+This represents the parent of this node. On the root node
+of the config tree it will be None.
+.IP "key" 4
+.IX Item "key"
+This is the keyword of this item, i.e. the first word of any given line in the
+config file. It will always be a string.
+.IP "values" 4
+.IX Item "values"
+This is a tuple (which might be empty) of all value, i.e. words following the
+keyword in any given line in the config file.
+.Sp
+Every item in this tuple will be either a string, a float or a boolean,
+depending on the contents of the configuration file.
+.IP "children" 4
+.IX Item "children"
+This is a tuple of child nodes. For most nodes this will be empty. If this node
+represents a block instead of a single line of the config file it will contain
+all nodes in this block.
+.SS "PluginData"
+.IX Subsection "PluginData"
+This should not be used directly but it is the base class for both Values and
+Notification. It is used to identify the source of a value or notification.
+.PP
+.Vb 1
+\& class PluginData(object)
+.Ve
+.PP
+This is an internal class that is the base for Values and Notification. It is
+pretty useless by itself and was therefore not exported to the collectd module.
+.PP
+Data descriptors defined here:
+.IP "host" 4
+.IX Item "host"
+The hostname of the host this value was read from. For dispatching this can be
+set to an empty string which means the local hostname as defined in
+collectd.conf.
+.IP "plugin" 4
+.IX Item "plugin"
+The name of the plugin that read the data. Setting this member to an empty
+string will insert \*(L"python\*(R" upon dispatching.
+.IP "plugin_instance" 4
+.IX Item "plugin_instance"
+Plugin instance string. May be empty.
+.IP "time" 4
+.IX Item "time"
+This is the Unix timestamp of the time this value was read. For dispatching
+values this can be set to zero which means \*(L"now\*(R". This means the time the value
+is actually dispatched, not the time it was set to 0.
+.IP "type" 4
+.IX Item "type"
+The type of this value. This type has to be defined in your \fItypes.db\fR.
+Attempting to set it to any other value will raise a \fITypeError\fR exception.
+Assigning a type is mandatory, calling dispatch without doing so will raise a
+\&\fIRuntimeError\fR exception.
+.IP "type_instance" 4
+.IX Item "type_instance"
+Type instance string. May be empty.
+.SS "Values"
+.IX Subsection "Values"
+A Value is an object which features a sequence of values. It is based on the
+\&\fIPluginData\fR type and uses its members to identify the values.
+.PP
+.Vb 1
+\& class Values(PluginData)
+.Ve
+.PP
+A Values object used for dispatching values to collectd and receiving values
+from write callbacks.
+.PP
+Method resolution order:
+.IP "Values" 4
+.IX Item "Values"
+.PD 0
+.IP "PluginData" 4
+.IX Item "PluginData"
+.IP "object" 4
+.IX Item "object"
+.PD
+.PP
+Methods defined here:
+.IP "\fBdispatch\fR([type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) \-> None." 4
+.IX Item "dispatch([type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) -> None."
+Dispatch this instance to the collectd process. The object has members for each
+of the possible arguments for this method. For a detailed explanation of these
+parameters see the member of the same same.
+.Sp
+If you do not submit a parameter the value saved in its member will be
+submitted. If you do provide a parameter it will be used instead, without
+altering the member.
+.IP "\fBwrite\fR([destination][, type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) \-> None." 4
+.IX Item "write([destination][, type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) -> None."
+Write this instance to a single plugin or all plugins if \*(L"destination\*(R" is
+omitted. This will bypass the main collectd process and all filtering and
+caching. Other than that it works similar to \*(L"dispatch\*(R". In most cases
+\&\*(L"dispatch\*(R" should be used instead of \*(L"write\*(R".
+.PP
+Data descriptors defined here:
+.IP "interval" 4
+.IX Item "interval"
+The interval is the timespan in seconds between two submits for the same data
+source. This value has to be a positive integer, so you can't submit more than
+one value per second. If this member is set to a non-positive value, the
+default value as specified in the config file will be used (default: 10).
+.Sp
+If you submit values more often than the specified interval, the average will
+be used. If you submit less values, your graphs will have gaps.
+.IP "values" 4
+.IX Item "values"
+These are the actual values that get dispatched to collectd. It has to be a
+sequence (a tuple or list) of numbers. The size of the sequence and the type of
+its content depend on the type member your \fItypes.db\fR file. For more
+information on this read the \fItypes.db\fR\|(5) manual page.
+.Sp
+If the sequence does not have the correct size upon dispatch a \fIRuntimeError\fR
+exception will be raised. If the content of the sequence is not a number, a
+\&\fITypeError\fR exception will be raised.
+.IP "meta" 4
+.IX Item "meta"
+These are the meta data for this Value object.
+It has to be a dictionary of numbers, strings or bools. All keys must be
+strings. \fIint\fR and <long> objects will be dispatched as signed integers unless
+they are between 2**63 and 2**64\-1, which will result in a unsigned integer.
+You can force one of these storage classes by using the classes
+\&\fBcollectd.Signed\fR and \fBcollectd.Unsigned\fR. A meta object received by a write
+callback will always contain \fBSigned\fR or \fBUnsigned\fR objects.
+.SS "Notification"
+.IX Subsection "Notification"
+A notification is an object defining the severity and message of the status
+message as well as an identification of a data instance by means of the members
+of \fIPluginData\fR on which it is based.
+.PP
+class Notification(PluginData)
+The Notification class is a wrapper around the collectd notification.
+It can be used to notify other plugins about bad stuff happening. It works
+similar to Values but has a severity and a message instead of interval
+and time.
+Notifications can be dispatched at any time and can be received with
+register_notification.
+.PP
+Method resolution order:
+.IP "Notification" 4
+.IX Item "Notification"
+.PD 0
+.IP "PluginData" 4
+.IX Item "PluginData"
+.IP "object" 4
+.IX Item "object"
+.PD
+.PP
+Methods defined here:
+.IP "\fBdispatch\fR([type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) \-> None.  Dispatch a value list." 4
+.IX Item "dispatch([type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) -> None. Dispatch a value list."
+Dispatch this instance to the collectd process. The object has members for each
+of the possible arguments for this method. For a detailed explanation of these
+parameters see the member of the same same.
+.Sp
+If you do not submit a parameter the value saved in its member will be
+submitted. If you do provide a parameter it will be used instead, without
+altering the member.
+.PP
+Data descriptors defined here:
+.IP "message" 4
+.IX Item "message"
+Some kind of description of what's going on and why this Notification was
+generated.
+.IP "severity" 4
+.IX Item "severity"
+The severity of this notification. Assign or compare to \fI\s-1NOTIF_FAILURE\s0\fR,
+\&\fI\s-1NOTIF_WARNING\s0\fR or \fI\s-1NOTIF_OKAY\s0\fR.
+.SH "FUNCTIONS"
+.IX Header "FUNCTIONS"
+The following functions provide the C\-interface to Python-modules.
+.IP "\fBregister_*\fR(\fIcallback\fR[, \fIdata\fR][, \fIname\fR]) \-> identifier" 4
+.IX Item "register_*(callback[, data][, name]) -> identifier"
+There are eight different register functions to get callback for eight
+different events. With one exception all of them are called as shown above.
+.RS 4
+.IP "\(bu" 4
+\&\fIcallback\fR is a callable object that will be called every time the event is
+triggered.
+.IP "\(bu" 4
+\&\fIdata\fR is an optional object that will be passed back to the callback function
+every time it is called. If you omit this parameter no object is passed back to
+your callback, not even None.
+.IP "\(bu" 4
+\&\fIname\fR is an optional identifier for this callback. The default name is
+\&\fBpython\fR.\fImodule\fR. \fImodule\fR is taken from the \fB_\|_module_\|_\fR attribute of
+your callback function. Every callback needs a unique identifier, so if you
+want to register the same callback multiple times in the same module you need to
+specify a name here. Otherwise it's safe to ignore this parameter.
+.IP "\(bu" 4
+\&\fIidentifier\fR is the full identifier assigned to this callback.
+.RE
+.RS 4
+.Sp
+These functions are called in the various stages of the daemon (see the section
+\&\*(L"\s-1WRITING YOUR OWN PLUGINS\*(R"\s0 above) and are passed the following arguments:
+.IP "register_config" 4
+.IX Item "register_config"
+The only argument passed is a \fIConfig\fR object. See above for the layout of this
+data type.
+Note that you cannot receive the whole config files this way, only \fBModule\fR
+blocks inside the Python configuration block. Additionally you will only
+receive blocks where your callback identifier matches \fBpython.\fR\fIblockname\fR.
+.IP "register_init" 4
+.IX Item "register_init"
+The callback will be called without arguments.
+.IP "register_read(callback[, interval][, data][, name]) \-> \fIidentifier\fR" 4
+.IX Item "register_read(callback[, interval][, data][, name]) -> identifier"
+This function takes an additional parameter: \fIinterval\fR. It specifies the
+time between calls to the callback function.
+.Sp
+The callback will be called without arguments.
+.IP "register_shutdown" 4
+.IX Item "register_shutdown"
+The callback will be called without arguments.
+.IP "register_write" 4
+.IX Item "register_write"
+The callback function will be called with one argument passed, which will be a
+\&\fIValues\fR object. For the layout of \fIValues\fR see above.
+If this callback function throws an exception the next call will be delayed by
+an increasing interval.
+.IP "register_flush" 4
+.IX Item "register_flush"
+Like \fBregister_config\fR is important for this callback because it determines
+what flush requests the plugin will receive.
+.Sp
+The arguments passed are \fItimeout\fR and \fIidentifier\fR. \fItimeout\fR indicates
+that only data older than \fItimeout\fR seconds is to be flushed. \fIidentifier\fR
+specifies which values are to be flushed.
+.IP "register_log" 4
+.IX Item "register_log"
+The arguments are \fIseverity\fR and \fImessage\fR. The severity is an integer and
+small for important messages and high for less important messages. The least
+important level is \fB\s-1LOG_DEBUG\s0\fR, the most important level is \fB\s-1LOG_ERR\s0\fR. In
+between there are (from least to most important): \fB\s-1LOG_INFO\s0\fR, \fB\s-1LOG_NOTICE\s0\fR,
+and \fB\s-1LOG_WARNING\s0\fR. \fImessage\fR is simply a string \fBwithout\fR a newline at the
+end.
+.Sp
+If this callback throws an exception it will \fBnot\fR be logged. It will just be
+printed to \fBsys.stderr\fR which usually means silently ignored.
+.IP "register_notification" 4
+.IX Item "register_notification"
+The only argument passed is a \fINotification\fR object. See above for the layout of this
+data type.
+.RE
+.RS 4
+.RE
+.IP "\fBunregister_*\fR(\fIidentifier\fR) \-> None" 4
+.IX Item "unregister_*(identifier) -> None"
+Removes a callback or data-set from collectd's internal list of callback
+functions. Every \fIregister_*\fR function has an \fIunregister_*\fR function.
+\&\fIidentifier\fR is either the string that was returned by the register function
+or a callback function. The identifier will be constructed in the same way as
+for the register functions.
+.IP "\fBget_dataset\fR(\fIname\fR) \-> \fIdefinition\fR" 4
+.IX Item "get_dataset(name) -> definition"
+Returns the definition of a dataset specified by \fIname\fR. \fIdefinition\fR is a list
+of tuples, each representing one data source. Each tuple has 4 values:
+.RS 4
+.IP "name" 4
+.IX Item "name"
+A string, the name of the data source.
+.IP "type" 4
+.IX Item "type"
+A string that is equal to either of the variables \fB\s-1DS_TYPE_COUNTER\s0\fR,
+\&\fB\s-1DS_TYPE_GAUGE\s0\fR, \fB\s-1DS_TYPE_DERIVE\s0\fR or \fB\s-1DS_TYPE_ABSOLUTE\s0\fR.
+.IP "min" 4
+.IX Item "min"
+A float or None, the minimum value.
+.IP "max" 4
+.IX Item "max"
+A float or None, the maximum value.
+.RE
+.RS 4
+.RE
+.IP "\fBflush\fR(\fIplugin\fR[, \fItimeout\fR][, \fIidentifier\fR]) \-> None" 4
+.IX Item "flush(plugin[, timeout][, identifier]) -> None"
+Flush one or all plugins. \fItimeout\fR and the specified \fIidentifiers\fR are
+passed on to the registered flush-callbacks. If omitted, the timeout defaults
+to \f(CW\*(C`\-1\*(C'\fR. The identifier defaults to None. If the \fBplugin\fR argument has been
+specified, only named plugin will be flushed.
+.IP "\fBerror\fR, \fBwarning\fR, \fBnotice\fR, \fBinfo\fR, \fBdebug\fR(\fImessage\fR)" 4
+.IX Item "error, warning, notice, info, debug(message)"
+Log a message with the specified severity.
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+Any Python module will start similar to:
+.PP
+.Vb 1
+\&  import collectd
+.Ve
+.PP
+A very simple read function might look like:
+.PP
+.Vb 4
+\&  def read(data=None):
+\&    vl = collectd.Values(type=\*(Aqgauge\*(Aq)
+\&    vl.plugin=\*(Aqpython.spam\*(Aq
+\&    vl.dispatch(values=[random.random() * 100])
+.Ve
+.PP
+A very simple write function might look like:
+.PP
+.Vb 3
+\&  def write(vl, data=None):
+\&    for i in vl.values:
+\&      print "%s (%s): %f" % (vl.plugin, vl.type, i)
+.Ve
+.PP
+To register those functions with collectd:
+.PP
+.Vb 2
+\&  collectd.register_read(read);
+\&  collectd.register_write(write);
+.Ve
+.PP
+See the section \*(L"\s-1CLASSES\*(R"\s0 above for a complete documentation of the data
+types used by the read, write and match functions.
+.SH "NOTES"
+.IX Header "NOTES"
+.IP "\(bu" 4
+Please feel free to send in new plugins to collectd's mailing list at
+<collectd\ at\ collectd.org> for review and, possibly,
+inclusion in the main distribution. In the latter case, we will take care of
+keeping the plugin up to date and adapting it to new versions of collectd.
+.Sp
+Before submitting your plugin, please take a look at
+<http://collectd.org/dev\-info.shtml>.
+.SH "CAVEATS"
+.IX Header "CAVEATS"
+.IP "\(bu" 4
+collectd is heavily multi-threaded. Each collectd thread accessing the Python
+plugin will be mapped to a Python interpreter thread. Any such thread will be
+created and destroyed transparently and on-the-fly.
+.Sp
+Hence, any plugin has to be thread-safe if it provides several entry points
+from collectd (i.\ e. if it registers more than one callback or if a
+registered callback may be called more than once in parallel).
+.IP "\(bu" 4
+The Python thread module is initialized just before calling the init callbacks.
+This means you must not use Python's threading module prior to this point. This
+includes all config and possibly other callback as well.
+.IP "\(bu" 4
+The python plugin exports the internal \s-1API\s0 of collectd which is considered
+unstable and subject to change at any time. We try hard to not break backwards
+compatibility in the Python \s-1API\s0 during the life cycle of one major release.
+However, this cannot be guaranteed at all times. Watch out for warnings
+dispatched by the python plugin after upgrades.
+.SH "KNOWN BUGS"
+.IX Header "KNOWN BUGS"
+.IP "\(bu" 4
+Not all aspects of the collectd \s-1API\s0 are accessible from Python. This includes
+but is not limited to filters and data sets.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-perl\fR\|(5),
+\&\fIcollectd\-exec\fR\|(5),
+\&\fItypes.db\fR\|(5),
+\&\fIpython\fR\|(1),
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+The \f(CW\*(C`python plugin\*(C'\fR has been written by
+Sven Trenkel <collectd\ at\ semidefinite.de>.
+.PP
+This manpage has been written by Sven Trenkel
+<collectd\ at\ semidefinite.de>.
+It is based on the \fIcollectd\-perl\fR\|(5) manual page by
+Florian Forster <octo\ at\ collectd.org> and
+Sebastian Harl <sh\ at\ tokkee.org>.
diff --git a/src/collectd-python.pod b/src/collectd-python.pod
new file mode 100644 (file)
index 0000000..0da891f
--- /dev/null
@@ -0,0 +1,757 @@
+# 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.
+
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-python - Documentation of collectd's C<python plugin>
+
+=head1 SYNOPSIS
+
+  LoadPlugin python
+  # ...
+  <Plugin python>
+    ModulePath "/path/to/your/python/modules"
+    LogTraces true
+    Interactive false
+    Import "spam"
+
+    <Module spam>
+      spam "wonderful" "lovely"
+    </Module>
+  </Plugin>
+
+=head1 DESCRIPTION
+
+The C<python plugin> embeds a Python-interpreter into collectd and provides an
+interface to collectd's plugin system. This makes it possible to write plugins
+for collectd in Python. This is a lot more efficient than executing a
+Python-script every time you want to read a value with the C<exec plugin> (see
+L<collectd-exec(5)>) and provides a lot more functionality, too.
+
+The minimum required Python version is I<2.3>.
+
+=head1 CONFIGURATION
+
+=over 4
+
+=item B<LoadPlugin> I<Plugin>
+
+Loads the Python plugin I<Plugin>.
+
+=item B<Encoding> I<Name>
+
+The default encoding for Unicode objects you pass to collectd. If you omit this
+option it will default to B<ascii> on I<Python 2>. On I<Python 3> it will
+always be B<utf-8>, as this function was removed, so this will be silently
+ignored.
+These defaults are hardcoded in Python and will ignore everything else,
+including your locale.
+
+=item B<ModulePath> I<Name>
+
+Prepends I<Name> to B<sys.path>. You won't be able to import any scripts you
+wrote unless they are located in one of the directories in this list. Please
+note that it only has effect on plugins loaded after this option. You can
+use multiple B<ModulePath> lines to add more than one directory.
+
+=item B<LogTraces> I<bool>
+
+If a Python script throws an exception it will be logged by collectd with the
+name of the exception and the message. If you set this option to true it will
+also log the full stacktrace just like the default output of an interactive
+Python interpreter. This should probably be set to false most of the time but
+is very useful for development and debugging of new modules.
+
+=item B<Interactive> I<bool>
+
+This option will cause the module to launch an interactive Python interpreter
+that reads from and writes to the terminal. Note that collectd will terminate
+right after starting up if you try to run it as a daemon while this option is
+enabled so make sure to start collectd with the B<-f> option.
+
+The B<collectd> module is I<not> imported into the interpreter's globals. You
+have to do it manually. Be sure to read the help text of the module, it can be
+used as a reference guide during coding.
+
+This interactive session will behave slightly differently from a daemonized
+collectd script as well as from a normal Python interpreter:
+
+=over 4
+
+=item
+
+B<1.> collectd will try to import the B<readline> module to give you a decent
+way of entering your commands. The daemonized collectd won't do that.
+
+=item
+
+B<2.> collectd will block I<SIGINT>. Pressing I<Ctrl+C> will usually cause
+collectd to shut down. This would be problematic in an interactive session,
+therefore this signal will be blocked. You can still use it to interrupt
+syscalls like sleep and pause but it won't generate a I<KeyboardInterrupt>
+exception either.
+
+To quit collectd send I<EOF> (press I<Ctrl+D> at the beginning of a new line).
+
+=item
+
+B<3.> collectd handles I<SIGCHLD>. This means that Python won't be able to
+determine the return code of spawned processes with system(), popen() and
+subprocess. This will result in Python not using external programs like less
+to display help texts. You can override this behavior with the B<PAGER>
+environment variable, e.g. I<export PAGER=less> before starting collectd.
+Depending on your version of Python this might or might not result in an
+B<OSError> exception which can be ignored.
+
+If you really need to spawn new processes from Python you can register an init
+callback and reset the action for SIGCHLD to the default behavior. Please note
+that this I<will> break the exec plugin. Do not even load the exec plugin if
+you intend to do this!
+
+There is an example script located in B<contrib/python/getsigchld.py>  to do
+this. If you import this from I<collectd.conf> SIGCHLD will be handled
+normally and spawning processes from Python will work as intended.
+
+=back
+
+=item E<lt>B<Module> I<Name>E<gt> block
+
+This block may be used to pass on configuration settings to a Python module.
+The configuration is converted into an instance of the B<Config> class which is
+passed to the registered configuration callback. See below for details about
+the B<Config> class and how to register callbacks.
+
+The I<name> identifies the callback.
+
+=back
+
+=head1 STRINGS
+
+There are a lot of places where strings are sent from collectd to Python and
+from Python to collectd. How exactly this works depends on whether byte or
+unicode strings or Python2 or Python3 are used.
+
+Python2 has I<str>, which is just bytes, and I<unicode>. Python3 has I<str>,
+which is a unicode object, and I<bytes>.
+
+When passing strings from Python to collectd all of these object are supported
+in all places, however I<str> should be used if possible. These strings must
+not contain a NUL byte. Ignoring this will result in a I<TypeError> exception.
+If a byte string was used it will be used as is by collectd. If a unicode
+object was used it will be encoded using the default encoding (see above). If
+this is not possible Python will raise a I<UnicodeEncodeError> exception.
+
+When passing strings from collectd to Python the behavior depends on the
+Python version used. Python2 will always receive a I<str> object. Python3 will
+usually receive a I<str> object as well, however the original string will be
+decoded to unicode using the default encoding. If this fails because the
+string is not a valid sequence for this encoding a I<bytes> object will be
+returned instead.
+
+=head1 WRITING YOUR OWN PLUGINS
+
+Writing your own plugins is quite simple. collectd manages plugins by means of
+B<dispatch functions> which call the appropriate B<callback functions>
+registered by the plugins. Any plugin basically consists of the implementation
+of these callback functions and initializing code which registers the
+functions with collectd. See the section "EXAMPLES" below for a really basic
+example. The following types of B<callback functions> are known to collectd
+(all of them are optional):
+
+=over 4
+
+=item configuration functions
+
+These are called during configuration if an appropriate
+B<Module> block has been encountered. It is called once for each B<Module>
+block which matches the name of the callback as provided with the
+B<register_config> method - see below.
+
+Python thread support has not been initialized at this point so do not use any
+threading functions here!
+
+=item init functions
+
+These are called once after loading the module and before any
+calls to the read and write functions. It should be used to initialize the
+internal state of the plugin (e.E<nbsp>g. open sockets, ...). This is the
+earliest point where you may use threads.
+
+=item read functions
+
+These are used to collect the actual data. It is called once
+per interval (see the B<Interval> configuration option of collectd). Usually
+it will call B<plugin_dispatch_values> to dispatch the values to collectd
+which will pass them on to all registered B<write functions>. If this function
+throws any kind of exception the plugin will be skipped for an increasing
+amount of time until it returns normally again.
+
+=item write functions
+
+These are used to write the dispatched values. It is called
+once for every value that was dispatched by any plugin.
+
+=item flush functions
+
+These are used to flush internal caches of plugins. It is
+usually triggered by the user only. Any plugin which caches data before
+writing it to disk should provide this kind of callback function.
+
+=item log functions
+
+These are used to pass messages of plugins or the daemon itself
+to the user.
+
+=item notification function
+
+These are used to act upon notifications. In general, a
+notification is a status message that may be associated with a data instance.
+Usually, a notification is generated by the daemon if a configured threshold
+has been exceeded (see the section "THRESHOLD CONFIGURATION" in
+L<collectd.conf(5)> for more details), but any plugin may dispatch
+notifications as well.
+
+=item shutdown functions
+
+These are called once before the daemon shuts down. It should
+be used to clean up the plugin (e.g. close sockets, ...).
+
+=back
+
+Any function (except log functions) may throw an exception in case of
+errors. The exception will be passed on to the user using collectd's logging
+mechanism. If a log callback throws an exception it will be printed to standard
+error instead.
+
+See the documentation of the various B<register_> methods in the section
+"FUNCTIONS" below for the number and types of arguments passed to each
+B<callback function>. This section also explains how to register B<callback
+functions> with collectd.
+
+To enable a module, copy it to a place where Python can find it (i.E<nbsp>e. a
+directory listed in B<sys.path>) just as any other Python plugin and add
+an appropriate B<Import> option to the configuration file. After restarting
+collectd you're done.
+
+=head1 CLASSES
+
+The following complex types are used to pass values between the Python plugin
+and collectd:
+
+=head2 Signed
+
+The Signed class is just a long. It has all its methods and behaves exactly
+like any other long object. It is used to indicate if an integer was or should
+be stored as a signed or unsigned integer object.
+
+ class Signed(long)
+
+This is a long by another name. Use it in meta data dicts
+to choose the way it is stored in the meta data.
+
+=head2 Unsigned
+
+The Unsigned class is just a long. It has all its methods and behaves exactly
+like any other long object. It is used to indicate if an integer was or should
+be stored as a signed or unsigned integer object.
+
+ class Unsigned(long)
+
+This is a long by another name. Use it in meta data dicts
+to choose the way it is stored in the meta data.
+
+=head2 Config
+
+The Config class is an object which keeps the information provided in the
+configuration file. The sequence of children keeps one entry for each
+configuration option. Each such entry is another Config instance, which
+may nest further if nested blocks are used.
+
+ class Config(object)
+
+This represents a piece of collectd's config file. It is passed to scripts with
+config callbacks (see B<register_config>) and is of little use if created
+somewhere else.
+
+It has no methods beyond the bare minimum and only exists for its data members.
+
+Data descriptors defined here:
+
+=over 4
+
+=item parent
+
+This represents the parent of this node. On the root node
+of the config tree it will be None.
+
+=item key
+
+This is the keyword of this item, i.e. the first word of any given line in the
+config file. It will always be a string.
+
+=item values
+
+This is a tuple (which might be empty) of all value, i.e. words following the
+keyword in any given line in the config file.
+
+Every item in this tuple will be either a string, a float or a boolean,
+depending on the contents of the configuration file.
+
+=item children
+
+This is a tuple of child nodes. For most nodes this will be empty. If this node
+represents a block instead of a single line of the config file it will contain
+all nodes in this block.
+
+=back
+
+=head2 PluginData
+
+This should not be used directly but it is the base class for both Values and
+Notification. It is used to identify the source of a value or notification.
+
+ class PluginData(object)
+
+This is an internal class that is the base for Values and Notification. It is
+pretty useless by itself and was therefore not exported to the collectd module.
+
+Data descriptors defined here:
+
+=over 4
+
+=item host
+
+The hostname of the host this value was read from. For dispatching this can be
+set to an empty string which means the local hostname as defined in
+collectd.conf.
+
+=item plugin
+
+The name of the plugin that read the data. Setting this member to an empty
+string will insert "python" upon dispatching.
+
+=item plugin_instance
+
+Plugin instance string. May be empty.
+
+=item time
+
+This is the Unix timestamp of the time this value was read. For dispatching
+values this can be set to zero which means "now". This means the time the value
+is actually dispatched, not the time it was set to 0.
+
+=item type
+
+The type of this value. This type has to be defined in your I<types.db>.
+Attempting to set it to any other value will raise a I<TypeError> exception.
+Assigning a type is mandatory, calling dispatch without doing so will raise a
+I<RuntimeError> exception.
+
+=item type_instance
+
+Type instance string. May be empty.
+
+=back
+
+=head2 Values
+
+A Value is an object which features a sequence of values. It is based on the
+I<PluginData> type and uses its members to identify the values.
+
+ class Values(PluginData)
+
+A Values object used for dispatching values to collectd and receiving values
+from write callbacks.
+
+Method resolution order:
+
+=over 4
+
+=item Values
+
+=item PluginData
+
+=item object
+
+=back
+
+Methods defined here:
+
+=over 4
+
+=item B<dispatch>([type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) -> None.
+
+Dispatch this instance to the collectd process. The object has members for each
+of the possible arguments for this method. For a detailed explanation of these
+parameters see the member of the same same.
+
+If you do not submit a parameter the value saved in its member will be
+submitted. If you do provide a parameter it will be used instead, without
+altering the member.
+
+=item B<write>([destination][, type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) -> None.
+
+Write this instance to a single plugin or all plugins if "destination" is
+omitted. This will bypass the main collectd process and all filtering and
+caching. Other than that it works similar to "dispatch". In most cases
+"dispatch" should be used instead of "write".
+
+=back
+
+Data descriptors defined here:
+
+=over 4
+
+=item interval
+
+The interval is the timespan in seconds between two submits for the same data
+source. This value has to be a positive integer, so you can't submit more than
+one value per second. If this member is set to a non-positive value, the
+default value as specified in the config file will be used (default: 10).
+
+If you submit values more often than the specified interval, the average will
+be used. If you submit less values, your graphs will have gaps.
+
+=item values
+
+These are the actual values that get dispatched to collectd. It has to be a
+sequence (a tuple or list) of numbers. The size of the sequence and the type of
+its content depend on the type member your I<types.db> file. For more
+information on this read the L<types.db(5)> manual page.
+
+If the sequence does not have the correct size upon dispatch a I<RuntimeError>
+exception will be raised. If the content of the sequence is not a number, a
+I<TypeError> exception will be raised.
+
+=item meta
+
+These are the meta data for this Value object.
+It has to be a dictionary of numbers, strings or bools. All keys must be
+strings. I<int> and <long> objects will be dispatched as signed integers unless
+they are between 2**63 and 2**64-1, which will result in a unsigned integer.
+You can force one of these storage classes by using the classes
+B<collectd.Signed> and B<collectd.Unsigned>. A meta object received by a write
+callback will always contain B<Signed> or B<Unsigned> objects.
+
+=back
+
+=head2 Notification
+
+A notification is an object defining the severity and message of the status
+message as well as an identification of a data instance by means of the members
+of I<PluginData> on which it is based.
+
+class Notification(PluginData)
+The Notification class is a wrapper around the collectd notification.
+It can be used to notify other plugins about bad stuff happening. It works
+similar to Values but has a severity and a message instead of interval
+and time.
+Notifications can be dispatched at any time and can be received with
+register_notification.
+
+Method resolution order:
+
+=over 4
+
+=item Notification
+
+=item PluginData
+
+=item object
+
+=back
+
+Methods defined here:
+
+=over 4
+
+=item B<dispatch>([type][, values][, plugin_instance][, type_instance][, plugin][, host][, time][, interval]) -> None.  Dispatch a value list.
+
+Dispatch this instance to the collectd process. The object has members for each
+of the possible arguments for this method. For a detailed explanation of these
+parameters see the member of the same same.
+
+If you do not submit a parameter the value saved in its member will be
+submitted. If you do provide a parameter it will be used instead, without
+altering the member.
+
+=back
+
+Data descriptors defined here:
+
+=over 4
+
+=item message
+
+Some kind of description of what's going on and why this Notification was
+generated.
+
+=item severity
+
+The severity of this notification. Assign or compare to I<NOTIF_FAILURE>,
+I<NOTIF_WARNING> or I<NOTIF_OKAY>.
+
+=back
+
+=head1 FUNCTIONS
+
+The following functions provide the C-interface to Python-modules.
+
+=over 4
+
+=item B<register_*>(I<callback>[, I<data>][, I<name>]) -> identifier
+
+There are eight different register functions to get callback for eight
+different events. With one exception all of them are called as shown above.
+
+=over 4
+
+=item
+
+I<callback> is a callable object that will be called every time the event is
+triggered.
+
+=item
+
+I<data> is an optional object that will be passed back to the callback function
+every time it is called. If you omit this parameter no object is passed back to
+your callback, not even None.
+
+=item
+
+I<name> is an optional identifier for this callback. The default name is
+B<python>.I<module>. I<module> is taken from the B<__module__> attribute of
+your callback function. Every callback needs a unique identifier, so if you
+want to register the same callback multiple times in the same module you need to
+specify a name here. Otherwise it's safe to ignore this parameter.
+
+=item
+
+I<identifier> is the full identifier assigned to this callback.
+
+=back
+
+These functions are called in the various stages of the daemon (see the section
+L<"WRITING YOUR OWN PLUGINS"> above) and are passed the following arguments:
+
+=over 4
+
+=item register_config
+
+The only argument passed is a I<Config> object. See above for the layout of this
+data type.
+Note that you cannot receive the whole config files this way, only B<Module>
+blocks inside the Python configuration block. Additionally you will only
+receive blocks where your callback identifier matches B<python.>I<blockname>.
+
+=item register_init
+
+The callback will be called without arguments.
+
+=item register_read(callback[, interval][, data][, name]) -> I<identifier>
+
+This function takes an additional parameter: I<interval>. It specifies the
+time between calls to the callback function.
+
+The callback will be called without arguments.
+
+=item register_shutdown
+
+The callback will be called without arguments.
+
+=item register_write
+
+The callback function will be called with one argument passed, which will be a
+I<Values> object. For the layout of I<Values> see above.
+If this callback function throws an exception the next call will be delayed by
+an increasing interval.
+
+=item register_flush
+
+Like B<register_config> is important for this callback because it determines
+what flush requests the plugin will receive.
+
+The arguments passed are I<timeout> and I<identifier>. I<timeout> indicates
+that only data older than I<timeout> seconds is to be flushed. I<identifier>
+specifies which values are to be flushed.
+
+=item register_log
+
+The arguments are I<severity> and I<message>. The severity is an integer and
+small for important messages and high for less important messages. The least
+important level is B<LOG_DEBUG>, the most important level is B<LOG_ERR>. In
+between there are (from least to most important): B<LOG_INFO>, B<LOG_NOTICE>,
+and B<LOG_WARNING>. I<message> is simply a string B<without> a newline at the
+end.
+
+If this callback throws an exception it will B<not> be logged. It will just be
+printed to B<sys.stderr> which usually means silently ignored.
+
+=item register_notification
+
+The only argument passed is a I<Notification> object. See above for the layout of this
+data type.
+
+=back
+
+=item B<unregister_*>(I<identifier>) -> None
+
+Removes a callback or data-set from collectd's internal list of callback
+functions. Every I<register_*> function has an I<unregister_*> function.
+I<identifier> is either the string that was returned by the register function
+or a callback function. The identifier will be constructed in the same way as
+for the register functions.
+
+=item B<get_dataset>(I<name>) -> I<definition>
+
+Returns the definition of a dataset specified by I<name>. I<definition> is a list
+of tuples, each representing one data source. Each tuple has 4 values:
+
+=over 4
+
+=item name
+
+A string, the name of the data source.
+
+=item type
+
+A string that is equal to either of the variables B<DS_TYPE_COUNTER>,
+B<DS_TYPE_GAUGE>, B<DS_TYPE_DERIVE> or B<DS_TYPE_ABSOLUTE>.
+
+=item min
+
+A float or None, the minimum value.
+
+=item max
+
+A float or None, the maximum value.
+
+=back
+
+=item B<flush>(I<plugin>[, I<timeout>][, I<identifier>]) -> None
+
+Flush one or all plugins. I<timeout> and the specified I<identifiers> are
+passed on to the registered flush-callbacks. If omitted, the timeout defaults
+to C<-1>. The identifier defaults to None. If the B<plugin> argument has been
+specified, only named plugin will be flushed.
+
+=item B<error>, B<warning>, B<notice>, B<info>, B<debug>(I<message>)
+
+Log a message with the specified severity.
+
+=back
+
+=head1 EXAMPLES
+
+Any Python module will start similar to:
+
+  import collectd
+
+A very simple read function might look like:
+
+  def read(data=None):
+    vl = collectd.Values(type='gauge')
+    vl.plugin='python.spam'
+    vl.dispatch(values=[random.random() * 100])
+
+A very simple write function might look like:
+
+  def write(vl, data=None):
+    for i in vl.values:
+      print "%s (%s): %f" % (vl.plugin, vl.type, i)
+
+To register those functions with collectd:
+
+  collectd.register_read(read);
+  collectd.register_write(write);
+
+See the section L<"CLASSES"> above for a complete documentation of the data
+types used by the read, write and match functions.
+
+=head1 NOTES
+
+=over 4
+
+=item
+
+Please feel free to send in new plugins to collectd's mailing list at
+E<lt>collectdE<nbsp>atE<nbsp>collectd.orgE<gt> for review and, possibly,
+inclusion in the main distribution. In the latter case, we will take care of
+keeping the plugin up to date and adapting it to new versions of collectd.
+
+Before submitting your plugin, please take a look at
+L<http://collectd.org/dev-info.shtml>.
+
+=back
+
+=head1 CAVEATS
+
+=over 4
+
+=item
+
+collectd is heavily multi-threaded. Each collectd thread accessing the Python
+plugin will be mapped to a Python interpreter thread. Any such thread will be
+created and destroyed transparently and on-the-fly.
+
+Hence, any plugin has to be thread-safe if it provides several entry points
+from collectd (i.E<nbsp>e. if it registers more than one callback or if a
+registered callback may be called more than once in parallel).
+
+=item
+
+The Python thread module is initialized just before calling the init callbacks.
+This means you must not use Python's threading module prior to this point. This
+includes all config and possibly other callback as well.
+
+=item
+
+The python plugin exports the internal API of collectd which is considered
+unstable and subject to change at any time. We try hard to not break backwards
+compatibility in the Python API during the life cycle of one major release.
+However, this cannot be guaranteed at all times. Watch out for warnings
+dispatched by the python plugin after upgrades.
+
+=back
+
+=head1 KNOWN BUGS
+
+=over 4
+
+=item
+
+Not all aspects of the collectd API are accessible from Python. This includes
+but is not limited to filters and data sets.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-perl(5)>,
+L<collectd-exec(5)>,
+L<types.db(5)>,
+L<python(1)>,
+
+=head1 AUTHOR
+
+The C<python plugin> has been written by
+Sven Trenkel E<lt>collectdE<nbsp>atE<nbsp>semidefinite.deE<gt>.
+
+This manpage has been written by Sven Trenkel
+E<lt>collectdE<nbsp>atE<nbsp>semidefinite.deE<gt>.
+It is based on the L<collectd-perl(5)> manual page by
+Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt> and
+Sebastian Harl E<lt>shE<nbsp>atE<nbsp>tokkee.orgE<gt>.
+
+=cut
diff --git a/src/collectd-snmp.5 b/src/collectd-snmp.5
new file mode 100644 (file)
index 0000000..cc7d95c
--- /dev/null
@@ -0,0 +1,400 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-SNMP 5"
+.TH COLLECTD-SNMP 5 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-snmp \- Documentation of collectd's "snmp plugin"
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 10
+\&  LoadPlugin snmp
+\&  # ...
+\&  <Plugin snmp>
+\&    <Data "powerplus_voltge_input">
+\&      Type "voltage"
+\&      Table false
+\&      Instance "input_line1"
+\&      Scale 0.1
+\&      Values "SNMPv2\-SMI::enterprises.6050.5.4.1.1.2.1"
+\&    </Data>
+\&    <Data "hr_users">
+\&      Type "users"
+\&      Table false
+\&      Instance ""
+\&      Shift \-1
+\&      Values "HOST\-RESOURCES\-MIB::hrSystemNumUsers.0"
+\&    </Data>
+\&    <Data "std_traffic">
+\&      Type "if_octets"
+\&      Table true
+\&      Instance "IF\-MIB::ifDescr"
+\&      Values "IF\-MIB::ifInOctets" "IF\-MIB::ifOutOctets"
+\&    </Data>
+\&
+\&    <Host "some.switch.mydomain.org">
+\&      Address "192.168.0.2"
+\&      Version 1
+\&      Community "community_string"
+\&      Collect "std_traffic"
+\&      Interval 120
+\&    </Host>
+\&    <Host "some.server.mydomain.org">
+\&      Address "192.168.0.42"
+\&      Version 2
+\&      Community "another_string"
+\&      Collect "std_traffic" "hr_users"
+\&    </Host>
+\&    <Host "secure.router.mydomain.org">
+\&      Address "192.168.0.7"
+\&      Version 3
+\&      SecurityLevel "authPriv"
+\&      Username "cosmo"
+\&      AuthProtocol "SHA"
+\&      AuthPassphrase "setec_astronomy"
+\&      PrivacyProtocol "AES"
+\&      PrivacyPassphrase "too_many_secrets"
+\&      Collect "std_traffic"
+\&    </Host>
+\&    <Host "some.ups.mydomain.org">
+\&      Address "192.168.0.3"
+\&      Version 1
+\&      Community "more_communities"
+\&      Collect "powerplus_voltge_input"
+\&      Interval 300
+\&    </Host>
+\&  </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \f(CW\*(C`snmp plugin\*(C'\fR queries other hosts using \s-1SNMP,\s0 the simple network
+management protocol, and translates the value it receives to collectd's
+internal format and dispatches them. Depending on the write plugins you have
+loaded they may be written to disk or submitted to another instance or
+whatever you configured.
+.PP
+Because querying a host via \s-1SNMP\s0 may produce a timeout multiple threads are
+used to query hosts in parallel. Depending on the number of hosts between one
+and ten threads are used.
+.SH "CONFIGURATION"
+.IX Header "CONFIGURATION"
+Since the aim of the \f(CW\*(C`snmp plugin\*(C'\fR is to provide a generic interface to \s-1SNMP,\s0
+it's configuration is not trivial and may take some time.
+.PP
+Since the \f(CW\*(C`Net\-SNMP\*(C'\fR library is used you can use all the environment variables
+that are interpreted by that package. See \fIsnmpcmd\fR\|(1) for more details.
+.PP
+There are two types of blocks that can be contained in the
+\&\f(CW\*(C`<Plugin\ snmp>\*(C'\fR block: \fBData\fR and \fBHost\fR:
+.SS "The \fBData\fP block"
+.IX Subsection "The Data block"
+The \fBData\fR block defines a list of values or a table of values that are to be
+queried. The following options can be set:
+.IP "\fBType\fR \fItype\fR" 4
+.IX Item "Type type"
+collectd's type that is to be used, e.\ g. \*(L"if_octets\*(R" for interface
+traffic or \*(L"users\*(R" for a user count. The types are read from the \fBTypesDB\fR
+(see \fIcollectd.conf\fR\|(5)), so you may want to check for which types are
+defined. See \fItypes.db\fR\|(5) for a description of the format of this file.
+.IP "\fBTable\fR \fItrue|false\fR" 4
+.IX Item "Table true|false"
+Define if this is a single list of values or a table of values. The difference
+is the following:
+.Sp
+When \fBTable\fR is set to \fBfalse\fR, the OIDs given to \fBValues\fR (see below) are
+queried using the \f(CW\*(C`GET\*(C'\fR \s-1SNMP\s0 command (see \fIsnmpget\fR\|(1)) and transmitted to
+collectd. \fBOne\fR value list is dispatched and, eventually, one file will be
+written.
+.Sp
+When \fBTable\fR is set to \fBtrue\fR, the OIDs given to \fBValues\fR (see below) are
+queried using the \f(CW\*(C`GETNEXT\*(C'\fR \s-1SNMP\s0 command until the subtree is left. After all
+the lists (think: all columns of the table) have been read \fBseveral\fR values
+sets will be dispatches and, eventually, several files will be written. If you
+configure a \fBType\fR (see above) which needs more than one data source (for
+example \f(CW\*(C`if_octets\*(C'\fR which needs \f(CW\*(C`rx\*(C'\fR and \f(CW\*(C`tx\*(C'\fR) you will need to specify more
+than one (two, in the example case) OIDs with the \fBValues\fR option. This has
+nothing to do with the \fBTable\fR setting.
+.Sp
+For example, if you want to query the number of users on a system, you can use
+\&\f(CW\*(C`HOST\-RESOURCES\-MIB::hrSystemNumUsers.0\*(C'\fR. This is one value and belongs to one
+value list, therefore \fBTable\fR must be set to \fBfalse\fR. Please note that, in
+this case, you have to include the sequence number (zero in this case) in the
+\&\s-1OID.\s0
+.Sp
+Counter example: If you want to query the interface table provided by the
+\&\f(CW\*(C`IF\-MIB\*(C'\fR, e.\ g. the bytes transmitted. There are potentially many
+interfaces, so you will want to set \fBTable\fR to \fBtrue\fR. Because the
+\&\f(CW\*(C`if_octets\*(C'\fR type needs two values, received and transmitted bytes, you need to
+specify two OIDs in the \fBValues\fR setting, in this case likely
+\&\f(CW\*(C`IF\-MIB::ifHCInOctets\*(C'\fR and \f(CW\*(C`IF\-MIB::ifHCOutOctets\*(C'\fR. But, this is because of
+the \fBType\fR setting, not the \fBTable\fR setting.
+.Sp
+Since the semantic of \fBInstance\fR and \fBValues\fR depends on this setting you
+need to set it before setting them. Doing vice verse will result in undefined
+behavior.
+.IP "\fBInstance\fR \fIInstance\fR" 4
+.IX Item "Instance Instance"
+Sets the type-instance of the values that are dispatched. The meaning of this
+setting depends on whether \fBTable\fR is set to \fItrue\fR or \fIfalse\fR:
+.Sp
+If \fBTable\fR is set to \fItrue\fR, \fIInstance\fR is interpreted as an SNMP-prefix
+that will return a list of values. Those values are then used as the actual
+type-instance. An example would be the \f(CW\*(C`IF\-MIB::ifDescr\*(C'\fR subtree.
+\&\fIvariables\fR\|(5) from the \s-1SNMP\s0 distribution describes the format of OIDs.
+.Sp
+If \fBTable\fR is set to \fItrue\fR and \fBInstance\fR is omitted, then \*(L"\s-1SUBID\*(R"\s0 will be
+used as the instance.
+.Sp
+If \fBTable\fR is set to \fIfalse\fR the actual string configured for \fIInstance\fR is
+copied into the value-list. In this case \fIInstance\fR may be empty, i.\ e.
+"".
+.IP "\fBInstancePrefix\fR \fIString\fR" 4
+.IX Item "InstancePrefix String"
+If \fBTable\fR is set to \fItrue\fR, you may feel the need to add something to the
+instance of the files. If set, \fIString\fR is prepended to the instance as
+determined by querying the agent. When \fBTable\fR is set to \fIfalse\fR this option
+has no effect.
+.Sp
+The \f(CW\*(C`UPS\-MIB\*(C'\fR is an example where you need this setting: It has voltages of
+the inlets, outlets and the battery of an \s-1UPS.\s0 However, it doesn't provide a
+descriptive column for these voltages. In this case having 1, 2,\ ... as
+instances is not enough, because the inlet voltages and outlet voltages may
+both have the subids 1, 2,\ ... You can use this setting to distinguish
+between the different voltages.
+.IP "\fBValues\fR \fI\s-1OID\s0\fR [\fI\s-1OID\s0\fR ...]" 4
+.IX Item "Values OID [OID ...]"
+Configures the values to be queried from the \s-1SNMP\s0 host. The meaning slightly
+changes with the \fBTable\fR setting. \fIvariables\fR\|(5) from the \s-1SNMP\s0 distribution
+describes the format of OIDs.
+.Sp
+If \fBTable\fR is set to \fItrue\fR, each \fI\s-1OID\s0\fR must be the prefix of all the
+values to query, e.\ g. \f(CW\*(C`IF\-MIB::ifInOctets\*(C'\fR for all the counters of
+incoming traffic. This subtree is walked (using \f(CW\*(C`GETNEXT\*(C'\fR) until a value from
+outside the subtree is returned.
+.Sp
+If \fBTable\fR is set to \fIfalse\fR, each \fI\s-1OID\s0\fR must be the \s-1OID\s0 of exactly one
+value, e.\ g. \f(CW\*(C`IF\-MIB::ifInOctets.3\*(C'\fR for the third counter of incoming
+traffic.
+.IP "\fBScale\fR \fIValue\fR" 4
+.IX Item "Scale Value"
+The gauge-values returned by the SNMP-agent are multiplied by \fIValue\fR.  This
+is useful when values are transferred as a fixed point real number. For example,
+thermometers may transfer \fB243\fR but actually mean \fB24.3\fR, so you can specify
+a scale value of \fB0.1\fR to correct this. The default value is, of course,
+\&\fB1.0\fR.
+.Sp
+This value is not applied to counter-values.
+.IP "\fBShift\fR \fIValue\fR" 4
+.IX Item "Shift Value"
+\&\fIValue\fR is added to gauge-values returned by the SNMP-agent after they have
+been multiplied by any \fBScale\fR value. If, for example, a thermometer returns
+degrees Kelvin you could specify a shift of \fB273.15\fR here to store values in
+degrees Celsius. The default value is, of course, \fB0.0\fR.
+.Sp
+This value is not applied to counter-values.
+.IP "\fBIgnore\fR \fIValue\fR [, \fIValue\fR ...]" 4
+.IX Item "Ignore Value [, Value ...]"
+The ignore values allows to ignore Instances based on their name and the patterns
+specified by the various values you've entered. The match is a glob-type shell
+matching.
+.IP "\fBInvertMatch\fR \fItrue|false(default)\fR" 4
+.IX Item "InvertMatch true|false(default)"
+The invertmatch value should be use in combination of the Ignore option.
+It changes the behaviour of the Ignore option, from a blacklist behaviour
+when InvertMatch is set to false, to a whitelist when specified to true.
+.SS "The Host block"
+.IX Subsection "The Host block"
+The \fBHost\fR block defines which hosts to query, which \s-1SNMP\s0 community and
+version to use and which of the defined \fBData\fR to query.
+.PP
+The argument passed to the \fBHost\fR block is used as the hostname in the data
+stored by collectd.
+.IP "\fBAddress\fR \fIIP-Address\fR|\fIHostname\fR" 4
+.IX Item "Address IP-Address|Hostname"
+Set the address to connect to.
+.IP "\fBVersion\fR \fB1\fR|\fB2\fR|\fB3\fR" 4
+.IX Item "Version 1|2|3"
+Set the \s-1SNMP\s0 version to use. When giving \fB2\fR version \f(CW\*(C`2c\*(C'\fR is actually used.
+.IP "\fBCommunity\fR \fICommunity\fR" 4
+.IX Item "Community Community"
+Pass \fICommunity\fR to the host. (Ignored for SNMPv3).
+.IP "\fBUsername\fR \fIUsername\fR" 4
+.IX Item "Username Username"
+Sets the \fIUsername\fR to use for SNMPv3 security.
+.IP "\fBSecurityLevel\fR \fIauthPriv\fR|\fIauthNoPriv\fR|\fInoAuthNoPriv\fR" 4
+.IX Item "SecurityLevel authPriv|authNoPriv|noAuthNoPriv"
+Selects the security level for SNMPv3 security.
+.IP "\fBContext\fR \fIContext\fR" 4
+.IX Item "Context Context"
+Sets the \fIContext\fR for SNMPv3 security.
+.IP "\fBAuthProtocol\fR \fI\s-1MD5\s0\fR|\fI\s-1SHA\s0\fR" 4
+.IX Item "AuthProtocol MD5|SHA"
+Selects the authentication protocol for SNMPv3 security.
+.IP "\fBAuthPassphrase\fR \fIPassphrase\fR" 4
+.IX Item "AuthPassphrase Passphrase"
+Sets the authentication passphrase for SNMPv3 security.
+.IP "\fBPrivacyProtocol\fR \fI\s-1AES\s0\fR|\fI\s-1DES\s0\fR" 4
+.IX Item "PrivacyProtocol AES|DES"
+Selects the privacy (encryption) protocol for SNMPv3 security.
+.IP "\fBPrivacyPassphrase\fR \fIPassphrase\fR" 4
+.IX Item "PrivacyPassphrase Passphrase"
+Sets the privacy (encryption) passphrase for SNMPv3 security.
+.IP "\fBCollect\fR \fIData\fR [\fIData\fR ...]" 4
+.IX Item "Collect Data [Data ...]"
+Defines which values to collect. \fIData\fR refers to one of the \fBData\fR block
+above. Since the config file is read top-down you need to define the data
+before using it here.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect data from this host every \fISeconds\fR seconds. This option is meant for
+devices with not much \s-1CPU\s0 power, e.\ g. network equipment such as
+switches, embedded devices, rack monitoring systems and so on. Since the
+\&\fBStep\fR of generated \s-1RRD\s0 files depends on this setting it's wise to select a
+reasonable value once and never change it.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIsnmpget\fR\|(1),
+\&\fIsnmpgetnext\fR\|(1),
+\&\fIvariables\fR\|(5),
+\&\fIunix\fR\|(7)
+.SH "AUTHORS"
+.IX Header "AUTHORS"
+Florian Forster <octo@collectd.org>
+Michael Pilat <mike@mikepilat.com>
diff --git a/src/collectd-snmp.pod b/src/collectd-snmp.pod
new file mode 100644 (file)
index 0000000..65a9b7c
--- /dev/null
@@ -0,0 +1,299 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-snmp - Documentation of collectd's C<snmp plugin>
+
+=head1 SYNOPSIS
+
+  LoadPlugin snmp
+  # ...
+  <Plugin snmp>
+    <Data "powerplus_voltge_input">
+      Type "voltage"
+      Table false
+      Instance "input_line1"
+      Scale 0.1
+      Values "SNMPv2-SMI::enterprises.6050.5.4.1.1.2.1"
+    </Data>
+    <Data "hr_users">
+      Type "users"
+      Table false
+      Instance ""
+      Shift -1
+      Values "HOST-RESOURCES-MIB::hrSystemNumUsers.0"
+    </Data>
+    <Data "std_traffic">
+      Type "if_octets"
+      Table true
+      Instance "IF-MIB::ifDescr"
+      Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
+    </Data>
+
+    <Host "some.switch.mydomain.org">
+      Address "192.168.0.2"
+      Version 1
+      Community "community_string"
+      Collect "std_traffic"
+      Interval 120
+    </Host>
+    <Host "some.server.mydomain.org">
+      Address "192.168.0.42"
+      Version 2
+      Community "another_string"
+      Collect "std_traffic" "hr_users"
+    </Host>
+    <Host "secure.router.mydomain.org">
+      Address "192.168.0.7"
+      Version 3
+      SecurityLevel "authPriv"
+      Username "cosmo"
+      AuthProtocol "SHA"
+      AuthPassphrase "setec_astronomy"
+      PrivacyProtocol "AES"
+      PrivacyPassphrase "too_many_secrets"
+      Collect "std_traffic"
+    </Host>
+    <Host "some.ups.mydomain.org">
+      Address "192.168.0.3"
+      Version 1
+      Community "more_communities"
+      Collect "powerplus_voltge_input"
+      Interval 300
+    </Host>
+  </Plugin>
+
+=head1 DESCRIPTION
+
+The C<snmp plugin> queries other hosts using SNMP, the simple network
+management protocol, and translates the value it receives to collectd's
+internal format and dispatches them. Depending on the write plugins you have
+loaded they may be written to disk or submitted to another instance or
+whatever you configured.
+
+Because querying a host via SNMP may produce a timeout multiple threads are
+used to query hosts in parallel. Depending on the number of hosts between one
+and ten threads are used.
+
+=head1 CONFIGURATION
+
+Since the aim of the C<snmp plugin> is to provide a generic interface to SNMP,
+it's configuration is not trivial and may take some time.
+
+Since the C<Net-SNMP> library is used you can use all the environment variables
+that are interpreted by that package. See L<snmpcmd(1)> for more details.
+
+There are two types of blocks that can be contained in the
+C<E<lt>PluginE<nbsp>snmpE<gt>> block: B<Data> and B<Host>:
+
+=head2 The B<Data> block
+
+The B<Data> block defines a list of values or a table of values that are to be
+queried. The following options can be set:
+
+=over 4
+
+=item B<Type> I<type>
+
+collectd's type that is to be used, e.E<nbsp>g. "if_octets" for interface
+traffic or "users" for a user count. The types are read from the B<TypesDB>
+(see L<collectd.conf(5)>), so you may want to check for which types are
+defined. See L<types.db(5)> for a description of the format of this file.
+
+=item B<Table> I<true|false>
+
+Define if this is a single list of values or a table of values. The difference
+is the following:
+
+When B<Table> is set to B<false>, the OIDs given to B<Values> (see below) are
+queried using the C<GET> SNMP command (see L<snmpget(1)>) and transmitted to
+collectd. B<One> value list is dispatched and, eventually, one file will be
+written.
+
+When B<Table> is set to B<true>, the OIDs given to B<Values> (see below) are
+queried using the C<GETNEXT> SNMP command until the subtree is left. After all
+the lists (think: all columns of the table) have been read B<several> values
+sets will be dispatches and, eventually, several files will be written. If you
+configure a B<Type> (see above) which needs more than one data source (for
+example C<if_octets> which needs C<rx> and C<tx>) you will need to specify more
+than one (two, in the example case) OIDs with the B<Values> option. This has
+nothing to do with the B<Table> setting.
+
+For example, if you want to query the number of users on a system, you can use
+C<HOST-RESOURCES-MIB::hrSystemNumUsers.0>. This is one value and belongs to one
+value list, therefore B<Table> must be set to B<false>. Please note that, in
+this case, you have to include the sequence number (zero in this case) in the
+OID.
+
+Counter example: If you want to query the interface table provided by the
+C<IF-MIB>, e.E<nbsp>g. the bytes transmitted. There are potentially many
+interfaces, so you will want to set B<Table> to B<true>. Because the
+C<if_octets> type needs two values, received and transmitted bytes, you need to
+specify two OIDs in the B<Values> setting, in this case likely
+C<IF-MIB::ifHCInOctets> and C<IF-MIB::ifHCOutOctets>. But, this is because of
+the B<Type> setting, not the B<Table> setting.
+
+Since the semantic of B<Instance> and B<Values> depends on this setting you
+need to set it before setting them. Doing vice verse will result in undefined
+behavior.
+
+=item B<Instance> I<Instance>
+
+Sets the type-instance of the values that are dispatched. The meaning of this
+setting depends on whether B<Table> is set to I<true> or I<false>:
+
+If B<Table> is set to I<true>, I<Instance> is interpreted as an SNMP-prefix
+that will return a list of values. Those values are then used as the actual
+type-instance. An example would be the C<IF-MIB::ifDescr> subtree.
+L<variables(5)> from the SNMP distribution describes the format of OIDs.
+
+If B<Table> is set to I<true> and B<Instance> is omitted, then "SUBID" will be
+used as the instance.
+
+If B<Table> is set to I<false> the actual string configured for I<Instance> is
+copied into the value-list. In this case I<Instance> may be empty, i.E<nbsp>e.
+"".
+
+=item B<InstancePrefix> I<String>
+
+If B<Table> is set to I<true>, you may feel the need to add something to the
+instance of the files. If set, I<String> is prepended to the instance as
+determined by querying the agent. When B<Table> is set to I<false> this option
+has no effect.
+
+The C<UPS-MIB> is an example where you need this setting: It has voltages of
+the inlets, outlets and the battery of an UPS. However, it doesn't provide a
+descriptive column for these voltages. In this case having 1, 2,E<nbsp>... as
+instances is not enough, because the inlet voltages and outlet voltages may
+both have the subids 1, 2,E<nbsp>... You can use this setting to distinguish
+between the different voltages.
+
+=item B<Values> I<OID> [I<OID> ...]
+
+Configures the values to be queried from the SNMP host. The meaning slightly
+changes with the B<Table> setting. L<variables(5)> from the SNMP distribution
+describes the format of OIDs.
+
+If B<Table> is set to I<true>, each I<OID> must be the prefix of all the
+values to query, e.E<nbsp>g. C<IF-MIB::ifInOctets> for all the counters of
+incoming traffic. This subtree is walked (using C<GETNEXT>) until a value from
+outside the subtree is returned.
+
+If B<Table> is set to I<false>, each I<OID> must be the OID of exactly one
+value, e.E<nbsp>g. C<IF-MIB::ifInOctets.3> for the third counter of incoming
+traffic.
+
+=item B<Scale> I<Value>
+
+The gauge-values returned by the SNMP-agent are multiplied by I<Value>.  This
+is useful when values are transferred as a fixed point real number. For example,
+thermometers may transfer B<243> but actually mean B<24.3>, so you can specify
+a scale value of B<0.1> to correct this. The default value is, of course,
+B<1.0>.
+
+This value is not applied to counter-values.
+
+=item B<Shift> I<Value>
+
+I<Value> is added to gauge-values returned by the SNMP-agent after they have
+been multiplied by any B<Scale> value. If, for example, a thermometer returns
+degrees Kelvin you could specify a shift of B<273.15> here to store values in
+degrees Celsius. The default value is, of course, B<0.0>.
+
+This value is not applied to counter-values.
+
+=item B<Ignore> I<Value> [, I<Value> ...]
+
+The ignore values allows to ignore Instances based on their name and the patterns
+specified by the various values you've entered. The match is a glob-type shell
+matching.
+
+=item B<InvertMatch> I<true|false(default)>
+
+The invertmatch value should be use in combination of the Ignore option.
+It changes the behaviour of the Ignore option, from a blacklist behaviour
+when InvertMatch is set to false, to a whitelist when specified to true.
+
+=back
+
+=head2 The Host block
+
+The B<Host> block defines which hosts to query, which SNMP community and
+version to use and which of the defined B<Data> to query.
+
+The argument passed to the B<Host> block is used as the hostname in the data
+stored by collectd.
+
+=over 4
+
+=item B<Address> I<IP-Address>|I<Hostname>
+
+Set the address to connect to.
+
+=item B<Version> B<1>|B<2>|B<3>
+
+Set the SNMP version to use. When giving B<2> version C<2c> is actually used.
+
+=item B<Community> I<Community>
+
+Pass I<Community> to the host. (Ignored for SNMPv3).
+
+=item B<Username> I<Username>
+
+Sets the I<Username> to use for SNMPv3 security.
+
+=item B<SecurityLevel> I<authPriv>|I<authNoPriv>|I<noAuthNoPriv>
+
+Selects the security level for SNMPv3 security.
+
+=item B<Context> I<Context>
+
+Sets the I<Context> for SNMPv3 security.
+
+=item B<AuthProtocol> I<MD5>|I<SHA>
+
+Selects the authentication protocol for SNMPv3 security.
+
+=item B<AuthPassphrase> I<Passphrase>
+
+Sets the authentication passphrase for SNMPv3 security. 
+
+=item B<PrivacyProtocol> I<AES>|I<DES>
+
+Selects the privacy (encryption) protocol for SNMPv3 security.
+
+=item B<PrivacyPassphrase> I<Passphrase>
+
+Sets the privacy (encryption) passphrase for SNMPv3 security. 
+
+=item B<Collect> I<Data> [I<Data> ...]
+
+Defines which values to collect. I<Data> refers to one of the B<Data> block
+above. Since the config file is read top-down you need to define the data
+before using it here.
+
+=item B<Interval> I<Seconds>
+
+Collect data from this host every I<Seconds> seconds. This option is meant for
+devices with not much CPU power, e.E<nbsp>g. network equipment such as
+switches, embedded devices, rack monitoring systems and so on. Since the
+B<Step> of generated RRD files depends on this setting it's wise to select a
+reasonable value once and never change it.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<snmpget(1)>,
+L<snmpgetnext(1)>,
+L<variables(5)>,
+L<unix(7)>
+
+=head1 AUTHORS
+
+Florian Forster E<lt>octo@collectd.orgE<gt>
+Michael Pilat E<lt>mike@mikepilat.comE<gt>
+
+=cut
diff --git a/src/collectd-tg.1 b/src/collectd-tg.1
new file mode 100644 (file)
index 0000000..5cfc2de
--- /dev/null
@@ -0,0 +1,177 @@
+.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.el \{\
+.    de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-TG 1"
+.TH COLLECTD-TG 1 "2014-08-18" "5.4.1.359.g103f05e" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-tg \- Traffic generator for collectd.
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+collectd-tg \fB\-n\fR \fInum_vl\fR \fB\-H\fR \fInum_hosts\fR \fB\-p\fR \fInum_plugins\fR \fB\-i\fR \fIinterval\fR \fB\-d\fR \fIdest\fR \fB\-D\fR \fIdport\fR
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBcollectd-tg\fR generates bogus \fIcollectd\fR network traffic. While host, plugin
+and values are generated randomly, the generated traffic tries to mimic \*(L"real\*(R"
+traffic as closely as possible.
+.SH "ARGUMENTS AND OPTIONS"
+.IX Header "ARGUMENTS AND OPTIONS"
+The following options are understood by \fIcollectd-tg\fR. The order of the
+arguments generally doesn't matter, as long as no argument is passed more than
+once.
+.IP "\fB\-n\fR \fInum_vl\fR" 4
+.IX Item "-n num_vl"
+Sets the number of unique \fIvalue lists\fR (\s-1VL\s0) to generate. Defaults to 10000.
+.IP "\fB\-H\fR \fInum_hosts\fR" 4
+.IX Item "-H num_hosts"
+Sets the number of unique hosts to simulate. Defaults to 1000.
+.IP "\fB\-p\fR \fInum_plugins\fR" 4
+.IX Item "-p num_plugins"
+Sets the number of unique plugins to simulate. Defaults to 20.
+.IP "\fB\-i\fR \fIinterval\fR" 4
+.IX Item "-i interval"
+Sets the interval in which each \fIvalue list\fR is dispatched. Defaults to 10.0
+seconds.
+.IP "\fB\-d\fR \fIdest\fR" 4
+.IX Item "-d dest"
+Sets the destination to which to send the generated network traffic. Defaults
+to the IPv6 multicast address, \f(CW\*(C`ff18::efc0:4a42\*(C'\fR.
+.IP "\fB\-D\fR \fIdport\fR" 4
+.IX Item "-D dport"
+Sets the destination port or service to which to send the generated network
+traffic. Defaults to \fIcollectd's\fR default port, \f(CW25826\fR.
+.IP "\fB\-h\fR" 4
+.IX Item "-h"
+Print usage summary.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo\ at\ collectd.org>
diff --git a/src/collectd-tg.c b/src/collectd-tg.c
new file mode 100644 (file)
index 0000000..45e788c
--- /dev/null
@@ -0,0 +1,440 @@
+/**
+ * collectd-tg - src/collectd-tg.c
+ * Copyright (C) 2010-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef _ISOC99_SOURCE
+# define _ISOC99_SOURCE
+#endif
+
+#ifndef _POSIX_C_SOURCE
+# define _POSIX_C_SOURCE 200809L
+#endif
+
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 700
+#endif
+
+#if !__GNUC__
+# define __attribute__(x) /**/
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "utils_heap.h"
+
+#include "libcollectdclient/collectd/client.h"
+#include "libcollectdclient/collectd/network.h"
+#include "libcollectdclient/collectd/network_buffer.h"
+
+#define DEF_NUM_HOSTS    1000
+#define DEF_NUM_PLUGINS    20
+#define DEF_NUM_VALUES 100000
+#define DEF_INTERVAL       10.0
+
+static int conf_num_hosts = DEF_NUM_HOSTS;
+static int conf_num_plugins = DEF_NUM_PLUGINS;
+static int conf_num_values = DEF_NUM_VALUES;
+static double conf_interval = DEF_INTERVAL;
+static const char *conf_destination = NET_DEFAULT_V6_ADDR;
+static const char *conf_service = NET_DEFAULT_PORT;
+
+static lcc_network_t *net;
+
+static c_heap_t *values_heap = NULL;
+
+static struct sigaction sigint_action;
+static struct sigaction sigterm_action;
+
+static _Bool loop = 1;
+
+__attribute__((noreturn))
+static void exit_usage (int exit_status) /* {{{ */
+{
+  fprintf ((exit_status == EXIT_FAILURE) ? stderr : stdout,
+      "collectd-tg -- collectd traffic generator\n"
+      "\n"
+      "  Usage: collectd-ng [OPTION]\n"
+      "\n"
+      "  Valid options:\n"
+      "    -n <number>    Number of value lists. (Default: %i)\n"
+      "    -H <number>    Number of hosts to emulate. (Default: %i)\n"
+      "    -p <number>    Number of plugins to emulate. (Default: %i)\n"
+      "    -i <seconds>   Interval of each value in seconds. (Default: %.3f)\n"
+      "    -d <dest>      Destination address of the network packets.\n"
+      "                   (Default: %s)\n"
+      "    -D <port>      Destination port of the network packets.\n"
+      "                   (Default: %s)\n"
+      "    -h             Print usage information (this output).\n"
+      "\n"
+      "Copyright (C) 2010-2012  Florian Forster\n"
+      "Licensed under the MIT license.\n",
+      DEF_NUM_VALUES, DEF_NUM_HOSTS, DEF_NUM_PLUGINS,
+      DEF_INTERVAL,
+      NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT);
+  exit (exit_status);
+} /* }}} void exit_usage */
+
+static void signal_handler (int signal) /* {{{ */
+{
+  loop = 0;
+} /* }}} void signal_handler */
+
+static int compare_time (const void *v0, const void *v1) /* {{{ */
+{
+  const lcc_value_list_t *vl0 = v0;
+  const lcc_value_list_t *vl1 = v1;
+
+  if (vl0->time < vl1->time)
+    return (-1);
+  else if (vl0->time > vl1->time)
+    return (1);
+  else
+    return (0);
+} /* }}} int compare_time */
+
+static int get_boundet_random (int min, int max) /* {{{ */
+{
+  int range;
+
+  if (min >= max)
+    return (-1);
+  if (min == (max - 1))
+    return (min);
+
+  range = max - min;
+
+  return (min + ((int) (((double) range) * ((double) random ()) / (((double) RAND_MAX) + 1.0))));
+} /* }}} int get_boundet_random */
+
+static lcc_value_list_t *create_value_list (void) /* {{{ */
+{
+  lcc_value_list_t *vl;
+  int host_num;
+
+  vl = malloc (sizeof (*vl));
+  if (vl == NULL)
+  {
+    fprintf (stderr, "malloc failed.\n");
+    return (NULL);
+  }
+  memset (vl, 0, sizeof (*vl));
+
+  vl->values = calloc (/* nmemb = */ 1, sizeof (*vl->values));
+  if (vl->values == NULL)
+  {
+    fprintf (stderr, "calloc failed.\n");
+    free (vl);
+    return (NULL);
+  }
+
+  vl->values_types = calloc (/* nmemb = */ 1, sizeof (*vl->values_types));
+  if (vl->values_types == NULL)
+  {
+    fprintf (stderr, "calloc failed.\n");
+    free (vl->values);
+    free (vl);
+    return (NULL);
+  }
+
+  vl->values_len = 1;
+
+  host_num = get_boundet_random (0, conf_num_hosts);
+
+  vl->interval = conf_interval;
+  vl->time = 1.0 + time (NULL)
+    + (host_num % (1 + (int) vl->interval));
+
+  if (get_boundet_random (0, 2) == 0)
+    vl->values_types[0] = LCC_TYPE_GAUGE;
+  else
+    vl->values_types[0] = LCC_TYPE_DERIVE;
+
+  snprintf (vl->identifier.host, sizeof (vl->identifier.host),
+      "host%04i", host_num);
+  snprintf (vl->identifier.plugin, sizeof (vl->identifier.plugin),
+      "plugin%03i", get_boundet_random (0, conf_num_plugins));
+  strncpy (vl->identifier.type,
+      (vl->values_types[0] == LCC_TYPE_GAUGE) ? "gauge" : "derive",
+      sizeof (vl->identifier.type));
+  snprintf (vl->identifier.type_instance, sizeof (vl->identifier.type_instance),
+      "ti%li", random ());
+
+  return (vl);
+} /* }}} int create_value_list */
+
+static void destroy_value_list (lcc_value_list_t *vl) /* {{{ */
+{
+  if (vl == NULL)
+    return;
+
+  free (vl->values);
+  free (vl->values_types);
+  free (vl);
+} /* }}} void destroy_value_list */
+
+static int send_value (lcc_value_list_t *vl) /* {{{ */
+{
+  int status;
+
+  if (vl->values_types[0] == LCC_TYPE_GAUGE)
+    vl->values[0].gauge = 100.0 * ((gauge_t) random ()) / (((gauge_t) RAND_MAX) + 1.0);
+  else
+    vl->values[0].derive += get_boundet_random (0, 100);
+
+  status = lcc_network_values_send (net, vl);
+  if (status != 0)
+    fprintf (stderr, "lcc_network_values_send failed with status %i.\n", status);
+
+  vl->time += vl->interval;
+
+  return (0);
+} /* }}} int send_value */
+
+static int get_integer_opt (const char *str, int *ret_value) /* {{{ */
+{
+  char *endptr;
+  int tmp;
+
+  errno = 0;
+  endptr = NULL;
+  tmp = (int) strtol (str, &endptr, /* base = */ 0);
+  if (errno != 0)
+  {
+    fprintf (stderr, "Unable to parse option as a number: \"%s\": %s\n",
+        str, strerror (errno));
+    exit (EXIT_FAILURE);
+  }
+  else if (endptr == str)
+  {
+    fprintf (stderr, "Unable to parse option as a number: \"%s\"\n", str);
+    exit (EXIT_FAILURE);
+  }
+  else if (*endptr != 0)
+  {
+    fprintf (stderr, "Garbage after end of value: \"%s\"\n", str);
+    exit (EXIT_FAILURE);
+  }
+
+  *ret_value = tmp;
+  return (0);
+} /* }}} int get_integer_opt */
+
+static int get_double_opt (const char *str, double *ret_value) /* {{{ */
+{
+  char *endptr;
+  double tmp;
+
+  errno = 0;
+  endptr = NULL;
+  tmp = strtod (str, &endptr);
+  if (errno != 0)
+  {
+    fprintf (stderr, "Unable to parse option as a number: \"%s\": %s\n",
+        str, strerror (errno));
+    exit (EXIT_FAILURE);
+  }
+  else if (endptr == str)
+  {
+    fprintf (stderr, "Unable to parse option as a number: \"%s\"\n", str);
+    exit (EXIT_FAILURE);
+  }
+  else if (*endptr != 0)
+  {
+    fprintf (stderr, "Garbage after end of value: \"%s\"\n", str);
+    exit (EXIT_FAILURE);
+  }
+
+  *ret_value = tmp;
+  return (0);
+} /* }}} int get_double_opt */
+
+static int read_options (int argc, char **argv) /* {{{ */
+{
+  int opt;
+
+  while ((opt = getopt (argc, argv, "n:H:p:i:d:D:h")) != -1)
+  {
+    switch (opt)
+    {
+      case 'n':
+        get_integer_opt (optarg, &conf_num_values);
+        break;
+
+      case 'H':
+        get_integer_opt (optarg, &conf_num_hosts);
+        break;
+
+      case 'p':
+        get_integer_opt (optarg, &conf_num_plugins);
+        break;
+
+      case 'i':
+        get_double_opt (optarg, &conf_interval);
+        break;
+
+      case 'd':
+        conf_destination = optarg;
+        break;
+
+      case 'D':
+        conf_service = optarg;
+        break;
+
+      case 'h':
+        exit_usage (EXIT_SUCCESS);
+
+      default:
+        exit_usage (EXIT_FAILURE);
+    } /* switch (opt) */
+  } /* while (getopt) */
+
+  return (0);
+} /* }}} int read_options */
+
+int main (int argc, char **argv) /* {{{ */
+{
+  int i;
+  time_t last_time;
+  int values_sent = 0;
+
+  read_options (argc, argv);
+
+  sigint_action.sa_handler = signal_handler;
+  sigaction (SIGINT, &sigint_action, /* old = */ NULL);
+
+  sigterm_action.sa_handler = signal_handler;
+  sigaction (SIGTERM, &sigterm_action, /* old = */ NULL);
+
+
+  values_heap = c_heap_create (compare_time);
+  if (values_heap == NULL)
+  {
+    fprintf (stderr, "c_heap_create failed.\n");
+    exit (EXIT_FAILURE);
+  }
+
+  net = lcc_network_create ();
+  if (net == NULL)
+  {
+    fprintf (stderr, "lcc_network_create failed.\n");
+    exit (EXIT_FAILURE);
+  }
+  else
+  {
+    lcc_server_t *srv;
+    
+    srv = lcc_server_create (net, conf_destination, conf_service);
+    if (srv == NULL)
+    {
+      fprintf (stderr, "lcc_server_create failed.\n");
+      exit (EXIT_FAILURE);
+    }
+
+    lcc_server_set_ttl (srv, 42);
+#if 0
+    lcc_server_set_security_level (srv, ENCRYPT,
+        "admin", "password1");
+#endif
+  }
+
+  fprintf (stdout, "Creating %i values ... ", conf_num_values);
+  fflush (stdout);
+  for (i = 0; i < conf_num_values; i++)
+  {
+    lcc_value_list_t *vl;
+
+    vl = create_value_list ();
+    if (vl == NULL)
+    {
+      fprintf (stderr, "create_value_list failed.\n");
+      exit (EXIT_FAILURE);
+    }
+
+    c_heap_insert (values_heap, vl);
+  }
+  fprintf (stdout, "done\n");
+
+  last_time = 0;
+  while (loop)
+  {
+    lcc_value_list_t *vl = c_heap_get_root (values_heap);
+
+    if (vl == NULL)
+      break;
+
+    if (vl->time != last_time)
+    {
+      printf ("%i values have been sent.\n", values_sent);
+
+      /* Check if we need to sleep */
+      time_t now = time (NULL);
+
+      while (now < vl->time)
+      {
+        /* 1 / 100 second */
+        struct timespec ts = { 0, 10000000 };
+        nanosleep (&ts, /* remaining = */ NULL);
+        now = time (NULL);
+
+        if (!loop)
+          break;
+      }
+      last_time = vl->time;
+    }
+
+    send_value (vl);
+    values_sent++;
+
+    c_heap_insert (values_heap, vl);
+  }
+
+  fprintf (stdout, "Shutting down.\n");
+  fflush (stdout);
+
+  while (42)
+  {
+    lcc_value_list_t *vl = c_heap_get_root (values_heap);
+    if (vl == NULL)
+      break;
+    destroy_value_list (vl);
+  }
+  c_heap_destroy (values_heap);
+
+  lcc_network_destroy (net);
+  exit (EXIT_SUCCESS);
+  return (0);
+} /* }}} int main */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/collectd-tg.pod b/src/collectd-tg.pod
new file mode 100644 (file)
index 0000000..97112e7
--- /dev/null
@@ -0,0 +1,67 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-tg - Traffic generator for collectd.
+
+=head1 SYNOPSIS
+
+collectd-tg B<-n> I<num_vl> B<-H> I<num_hosts> B<-p> I<num_plugins> B<-i> I<interval> B<-d> I<dest> B<-D> I<dport>
+
+=head1 DESCRIPTION
+
+B<collectd-tg> generates bogus I<collectd> network traffic. While host, plugin
+and values are generated randomly, the generated traffic tries to mimic "real"
+traffic as closely as possible.
+
+=head1 ARGUMENTS AND OPTIONS
+
+The following options are understood by I<collectd-tg>. The order of the
+arguments generally doesn't matter, as long as no argument is passed more than
+once.
+
+=over 4
+
+=item B<-n> I<num_vl>
+
+Sets the number of unique I<value lists> (VL) to generate. Defaults to 10000.
+
+=item B<-H> I<num_hosts>
+
+Sets the number of unique hosts to simulate. Defaults to 1000.
+
+=item B<-p> I<num_plugins>
+
+Sets the number of unique plugins to simulate. Defaults to 20.
+
+=item B<-i> I<interval>
+
+Sets the interval in which each I<value list> is dispatched. Defaults to 10.0
+seconds.
+
+=item B<-d> I<dest>
+
+Sets the destination to which to send the generated network traffic. Defaults
+to the IPv6 multicast address, C<ff18::efc0:4a42>.
+
+=item B<-D> I<dport>
+
+Sets the destination port or service to which to send the generated network
+traffic. Defaults to I<collectd's> default port, C<25826>.
+
+=item B<-h>
+
+Print usage summary.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt>
+
+=cut
diff --git a/src/collectd-threshold.5 b/src/collectd-threshold.5
new file mode 100644 (file)
index 0000000..94cc46b
--- /dev/null
@@ -0,0 +1,322 @@
+.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.el \{\
+.    de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-THRESHOLD 5"
+.TH COLLECTD-THRESHOLD 5 "2014-08-18" "5.4.1.359.g103f05e" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-threshold \- Documentation of collectd's Threshold plugin
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 11
+\& LoadPlugin "threshold"
+\& <Plugin "threshold">
+\&   <Type "foo">
+\&     WarningMin    0.00
+\&     WarningMax 1000.00
+\&     FailureMin    0.00
+\&     FailureMax 1200.00
+\&     Invert false
+\&     Instance "bar"
+\&   </Type>
+\& </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+Starting with version \f(CW4.3.0\fR \fIcollectd\fR has support for \fBmonitoring\fR. By
+that we mean that the values are not only stored or sent somewhere, but that
+they are judged and, if a problem is recognized, acted upon. The only action
+the \fIThreshold plugin\fR takes itself is to generate and dispatch a
+\&\fInotification\fR. Other plugins can register to receive notifications and
+perform appropriate further actions.
+.PP
+Since systems and what you expect them to do differ a lot, you can configure
+\&\fIthresholds\fR for your values freely. This gives you a lot of flexibility but
+also a lot of responsibility.
+.PP
+Every time a value is out of range, a notification is dispatched. This means
+that the idle percentage of your \s-1CPU\s0 needs to be less then the configured
+threshold only once for a notification to be generated. There's no such thing
+as a moving average or similar \- at least not now.
+.PP
+Also, all values that match a threshold are considered to be relevant or
+\&\*(L"interesting\*(R". As a consequence collectd will issue a notification if they are
+not received for \fBTimeout\fR iterations. The \fBTimeout\fR configuration option is
+explained in section \*(L"\s-1GLOBAL\s0 \s-1OPTIONS\s0\*(R" in \fIcollectd.conf\fR\|(5). If, for example,
+\&\fBTimeout\fR is set to \*(L"2\*(R" (the default) and some hosts sends it's \s-1CPU\s0 statistics
+to the server every 60 seconds, a notification will be dispatched after about
+120 seconds. It may take a little longer because the timeout is checked only
+once each \fBInterval\fR on the server.
+.PP
+When a value comes within range again or is received after it was missing, an
+\&\*(L"OKAY-notification\*(R" is dispatched.
+.SH "CONFIGURATION"
+.IX Header "CONFIGURATION"
+Here is a configuration example to get you started. Read below for more
+information.
+.PP
+.Vb 10
+\& LoadPlugin "threshold"
+\& <Plugin "threshold">
+\&   <Type "foo">
+\&     WarningMin    0.00
+\&     WarningMax 1000.00
+\&     FailureMin    0.00
+\&     FailureMax 1200.00
+\&     Invert false
+\&     Instance "bar"
+\&   </Type>
+\&   
+\&   <Plugin "interface">
+\&     Instance "eth0"
+\&     <Type "if_octets">
+\&       FailureMax 10000000
+\&       DataSource "rx"
+\&     </Type>
+\&   </Plugin>
+\&   
+\&   <Host "hostname">
+\&     <Type "cpu">
+\&       Instance "idle"
+\&       FailureMin 10
+\&     </Type>
+\&   
+\&     <Plugin "memory">
+\&       <Type "memory">
+\&         Instance "cached"
+\&         WarningMin 100000000
+\&       </Type>
+\&     </Plugin>
+\&   
+\&     <Type "load">
+\&        DataSource "midterm"
+\&        FailureMax 4
+\&        Hits 3
+\&        Hysteresis 3
+\&     </Type>
+\&   </Host>
+\& </Plugin>
+.Ve
+.PP
+There are basically two types of configuration statements: The \f(CW\*(C`Host\*(C'\fR,
+\&\f(CW\*(C`Plugin\*(C'\fR, and \f(CW\*(C`Type\*(C'\fR blocks select the value for which a threshold should be
+configured. The \f(CW\*(C`Plugin\*(C'\fR and \f(CW\*(C`Type\*(C'\fR blocks may be specified further using the
+\&\f(CW\*(C`Instance\*(C'\fR option. You can combine the block by nesting the blocks, though
+they must be nested in the above order, i.e. \f(CW\*(C`Host\*(C'\fR may contain either
+\&\f(CW\*(C`Plugin\*(C'\fR and \f(CW\*(C`Type\*(C'\fR blocks, \f(CW\*(C`Plugin\*(C'\fR may only contain \f(CW\*(C`Type\*(C'\fR blocks and
+\&\f(CW\*(C`Type\*(C'\fR may not contain other blocks. If multiple blocks apply to the same
+value the most specific block is used.
+.PP
+The other statements specify the threshold to configure. They \fBmust\fR be
+included in a \f(CW\*(C`Type\*(C'\fR block. Currently the following statements are recognized:
+.IP "\fBFailureMax\fR \fIValue\fR" 4
+.IX Item "FailureMax Value"
+.PD 0
+.IP "\fBWarningMax\fR \fIValue\fR" 4
+.IX Item "WarningMax Value"
+.PD
+Sets the upper bound of acceptable values. If unset defaults to positive
+infinity. If a value is greater than \fBFailureMax\fR a \fB\s-1FAILURE\s0\fR notification
+will be created. If the value is greater than \fBWarningMax\fR but less than (or
+equal to) \fBFailureMax\fR a \fB\s-1WARNING\s0\fR notification will be created.
+.IP "\fBFailureMin\fR \fIValue\fR" 4
+.IX Item "FailureMin Value"
+.PD 0
+.IP "\fBWarningMin\fR \fIValue\fR" 4
+.IX Item "WarningMin Value"
+.PD
+Sets the lower bound of acceptable values. If unset defaults to negative
+infinity. If a value is less than \fBFailureMin\fR a \fB\s-1FAILURE\s0\fR notification will
+be created. If the value is less than \fBWarningMin\fR but greater than (or equal
+to) \fBFailureMin\fR a \fB\s-1WARNING\s0\fR notification will be created.
+.IP "\fBDataSource\fR \fIDSName\fR" 4
+.IX Item "DataSource DSName"
+Some data sets have more than one \*(L"data source\*(R". Interesting examples are the
+\&\f(CW\*(C`if_octets\*(C'\fR data set, which has received (\f(CW\*(C`rx\*(C'\fR) and sent (\f(CW\*(C`tx\*(C'\fR) bytes and
+the \f(CW\*(C`disk_ops\*(C'\fR data set, which holds \f(CW\*(C`read\*(C'\fR and \f(CW\*(C`write\*(C'\fR operations. The
+system load data set, \f(CW\*(C`load\*(C'\fR, even has three data sources: \f(CW\*(C`shortterm\*(C'\fR,
+\&\f(CW\*(C`midterm\*(C'\fR, and \f(CW\*(C`longterm\*(C'\fR.
+.Sp
+Normally, all data sources are checked against a configured threshold. If this
+is undesirable, or if you want to specify different limits for each data
+source, you can use the \fBDataSource\fR option to have a threshold apply only to
+one data source.
+.IP "\fBInvert\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Invert true|false"
+If set to \fBtrue\fR the range of acceptable values is inverted, i.e. values
+between \fBFailureMin\fR and \fBFailureMax\fR (\fBWarningMin\fR and \fBWarningMax\fR) are
+not okay. Defaults to \fBfalse\fR.
+.IP "\fBPersist\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Persist true|false"
+Sets how often notifications are generated. If set to \fBtrue\fR one notification
+will be generated for each value that is out of the acceptable range. If set to
+\&\fBfalse\fR (the default) then a notification is only generated if a value is out
+of range but the previous value was okay.
+.Sp
+This applies to missing values, too: If set to \fBtrue\fR a notification about a
+missing value is generated once every \fBInterval\fR seconds. If set to \fBfalse\fR
+only one such notification is generated until the value appears again.
+.IP "\fBPersistOK\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "PersistOK true|false"
+Sets how \s-1OKAY\s0 notifications act. If set to \fBtrue\fR one notification will be
+generated for each value that is in the acceptable range. If set to \fBfalse\fR
+(the default) then a notification is only generated if a value is in range but
+the previous value was not.
+.IP "\fBPercentage\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Percentage true|false"
+If set to \fBtrue\fR, the minimum and maximum values given are interpreted as
+percentage value, relative to the other data sources. This is helpful for
+example for the \*(L"df\*(R" type, where you may want to issue a warning when less than
+5\ % of the total space is available. Defaults to \fBfalse\fR.
+.IP "\fBHits\fR \fIValue\fR" 4
+.IX Item "Hits Value"
+Sets the number of occurrences which the threshold must be raised before to
+dispatch any notification or, in other words, the number of \fBInterval\fRs
+that the threshold must be match before dispatch any notification.
+.IP "\fBHysteresis\fR \fIValue\fR" 4
+.IX Item "Hysteresis Value"
+Sets the hysteresis value for threshold. The hysteresis is a method to prevent
+flapping between states, until a new received value for a previously matched
+threshold down below the threshold condition (\fBWarningMax\fR, \fBFailureMin\fR or
+everything else) minus the hysteresis value, the failure (respectively warning)
+state will be keep.
+.IP "\fBInteresting\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Interesting true|false"
+If set to \fBtrue\fR (the default), a notification with severity \f(CW\*(C`FAILURE\*(C'\fR will
+be created when a matching value list is no longer updated and purged from the
+internal cache. When this happens depends on the \fIinterval\fR of the value list
+and the global \fBTimeout\fR setting. See the \fBInterval\fR and \fBTimeout\fR settings
+in \fIcollectd.conf\fR\|(5) for details. If set to \fBfalse\fR, this event will be
+ignored.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo\ at\ collectd.org>
diff --git a/src/collectd-threshold.pod b/src/collectd-threshold.pod
new file mode 100644 (file)
index 0000000..35f8a9f
--- /dev/null
@@ -0,0 +1,205 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-threshold - Documentation of collectd's I<Threshold plugin>
+
+=head1 SYNOPSIS
+
+ LoadPlugin "threshold"
+ <Plugin "threshold">
+   <Type "foo">
+     WarningMin    0.00
+     WarningMax 1000.00
+     FailureMin    0.00
+     FailureMax 1200.00
+     Invert false
+     Instance "bar"
+   </Type>
+ </Plugin>
+
+=head1 DESCRIPTION
+
+Starting with version C<4.3.0> I<collectd> has support for B<monitoring>. By
+that we mean that the values are not only stored or sent somewhere, but that
+they are judged and, if a problem is recognized, acted upon. The only action
+the I<Threshold plugin> takes itself is to generate and dispatch a
+I<notification>. Other plugins can register to receive notifications and
+perform appropriate further actions.
+
+Since systems and what you expect them to do differ a lot, you can configure
+I<thresholds> for your values freely. This gives you a lot of flexibility but
+also a lot of responsibility.
+
+Every time a value is out of range, a notification is dispatched. This means
+that the idle percentage of your CPU needs to be less then the configured
+threshold only once for a notification to be generated. There's no such thing
+as a moving average or similar - at least not now.
+
+Also, all values that match a threshold are considered to be relevant or
+"interesting". As a consequence collectd will issue a notification if they are
+not received for B<Timeout> iterations. The B<Timeout> configuration option is
+explained in section L<collectd.conf(5)/"GLOBAL OPTIONS">. If, for example,
+B<Timeout> is set to "2" (the default) and some hosts sends it's CPU statistics
+to the server every 60 seconds, a notification will be dispatched after about
+120 seconds. It may take a little longer because the timeout is checked only
+once each B<Interval> on the server.
+
+When a value comes within range again or is received after it was missing, an
+"OKAY-notification" is dispatched.
+
+=head1 CONFIGURATION
+
+Here is a configuration example to get you started. Read below for more
+information.
+
+ LoadPlugin "threshold"
+ <Plugin "threshold">
+   <Type "foo">
+     WarningMin    0.00
+     WarningMax 1000.00
+     FailureMin    0.00
+     FailureMax 1200.00
+     Invert false
+     Instance "bar"
+   </Type>
+   
+   <Plugin "interface">
+     Instance "eth0"
+     <Type "if_octets">
+       FailureMax 10000000
+       DataSource "rx"
+     </Type>
+   </Plugin>
+   
+   <Host "hostname">
+     <Type "cpu">
+       Instance "idle"
+       FailureMin 10
+     </Type>
+   
+     <Plugin "memory">
+       <Type "memory">
+         Instance "cached"
+         WarningMin 100000000
+       </Type>
+     </Plugin>
+   
+     <Type "load">
+       DataSource "midterm"
+       FailureMax 4
+       Hits 3
+       Hysteresis 3
+     </Type>
+   </Host>
+ </Plugin>
+
+There are basically two types of configuration statements: The C<Host>,
+C<Plugin>, and C<Type> blocks select the value for which a threshold should be
+configured. The C<Plugin> and C<Type> blocks may be specified further using the
+C<Instance> option. You can combine the block by nesting the blocks, though
+they must be nested in the above order, i.e. C<Host> may contain either
+C<Plugin> and C<Type> blocks, C<Plugin> may only contain C<Type> blocks and
+C<Type> may not contain other blocks. If multiple blocks apply to the same
+value the most specific block is used.
+
+The other statements specify the threshold to configure. They B<must> be
+included in a C<Type> block. Currently the following statements are recognized:
+
+=over 4
+
+=item B<FailureMax> I<Value>
+
+=item B<WarningMax> I<Value>
+
+Sets the upper bound of acceptable values. If unset defaults to positive
+infinity. If a value is greater than B<FailureMax> a B<FAILURE> notification
+will be created. If the value is greater than B<WarningMax> but less than (or
+equal to) B<FailureMax> a B<WARNING> notification will be created.
+
+=item B<FailureMin> I<Value>
+
+=item B<WarningMin> I<Value>
+
+Sets the lower bound of acceptable values. If unset defaults to negative
+infinity. If a value is less than B<FailureMin> a B<FAILURE> notification will
+be created. If the value is less than B<WarningMin> but greater than (or equal
+to) B<FailureMin> a B<WARNING> notification will be created.
+
+=item B<DataSource> I<DSName>
+
+Some data sets have more than one "data source". Interesting examples are the
+C<if_octets> data set, which has received (C<rx>) and sent (C<tx>) bytes and
+the C<disk_ops> data set, which holds C<read> and C<write> operations. The
+system load data set, C<load>, even has three data sources: C<shortterm>,
+C<midterm>, and C<longterm>.
+
+Normally, all data sources are checked against a configured threshold. If this
+is undesirable, or if you want to specify different limits for each data
+source, you can use the B<DataSource> option to have a threshold apply only to
+one data source.
+
+=item B<Invert> B<true>|B<false>
+
+If set to B<true> the range of acceptable values is inverted, i.e. values
+between B<FailureMin> and B<FailureMax> (B<WarningMin> and B<WarningMax>) are
+not okay. Defaults to B<false>.
+
+=item B<Persist> B<true>|B<false>
+
+Sets how often notifications are generated. If set to B<true> one notification
+will be generated for each value that is out of the acceptable range. If set to
+B<false> (the default) then a notification is only generated if a value is out
+of range but the previous value was okay.
+
+This applies to missing values, too: If set to B<true> a notification about a
+missing value is generated once every B<Interval> seconds. If set to B<false>
+only one such notification is generated until the value appears again.
+
+=item B<PersistOK> B<true>|B<false>
+
+Sets how OKAY notifications act. If set to B<true> one notification will be
+generated for each value that is in the acceptable range. If set to B<false>
+(the default) then a notification is only generated if a value is in range but
+the previous value was not.
+
+=item B<Percentage> B<true>|B<false>
+
+If set to B<true>, the minimum and maximum values given are interpreted as
+percentage value, relative to the other data sources. This is helpful for
+example for the "df" type, where you may want to issue a warning when less than
+5E<nbsp>% of the total space is available. Defaults to B<false>.
+
+=item B<Hits> I<Value>
+
+Sets the number of occurrences which the threshold must be raised before to
+dispatch any notification or, in other words, the number of B<Interval>s
+that the threshold must be match before dispatch any notification.
+
+=item B<Hysteresis> I<Value>
+
+Sets the hysteresis value for threshold. The hysteresis is a method to prevent
+flapping between states, until a new received value for a previously matched
+threshold down below the threshold condition (B<WarningMax>, B<FailureMin> or
+everything else) minus the hysteresis value, the failure (respectively warning)
+state will be keep.
+
+=item B<Interesting> B<true>|B<false>
+
+If set to B<true> (the default), a notification with severity C<FAILURE> will
+be created when a matching value list is no longer updated and purged from the
+internal cache. When this happens depends on the I<interval> of the value list
+and the global B<Timeout> setting. See the B<Interval> and B<Timeout> settings
+in L<collectd.conf(5)> for details. If set to B<false>, this event will be
+ignored.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt>
diff --git a/src/collectd-unixsock.5 b/src/collectd-unixsock.5
new file mode 100644 (file)
index 0000000..b67dffe
--- /dev/null
@@ -0,0 +1,380 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD-UNIXSOCK 5"
+.TH COLLECTD-UNIXSOCK 5 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd\-unixsock \- Documentation of collectd's "unixsock plugin"
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 9
+\&  # See collectd.conf(5)
+\&  LoadPlugin unixsock
+\&  # ...
+\&  <Plugin unixsock>
+\&    SocketFile "/path/to/socket"
+\&    SocketGroup "collectd"
+\&    SocketPerms "0770"
+\&    DeleteSocket false
+\&  </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \f(CW\*(C`unixsock plugin\*(C'\fR opens an UNIX-socket over which one can interact with
+the daemon. This can be used to use the values collected by collectd in other
+applications, such as monitoring solutions, or submit externally collected
+values to collectd.
+.PP
+For example, this plugin is used by \fIcollectd\-nagios\fR\|(1) to check if some
+value is in a certain range and exit with a Nagios-compatible exit code.
+.SH "COMMANDS"
+.IX Header "COMMANDS"
+Upon start the \f(CW\*(C`unixsock plugin\*(C'\fR opens a UNIX-socket and waits for
+connections. Once a connection is established the client can send commands to
+the daemon which it will answer, if it understand them.
+.PP
+In general the plugin answers with a status line of the following form:
+.PP
+\&\fIStatus\fR \fIMessage\fR
+.PP
+If \fIStatus\fR is greater than or equal to zero the message indicates success,
+if \fIStatus\fR is less than zero the message indicates failure. \fIMessage\fR is a
+human-readable string that further describes the return value.
+.PP
+On success, \fIStatus\fR furthermore indicates the number of subsequent lines of
+output (not including the status line). Each such lines usually contains a
+single return value. See the description of each command for details.
+.PP
+The following commands are implemented:
+.IP "\fB\s-1GETVAL\s0\fR \fIIdentifier\fR" 4
+.IX Item "GETVAL Identifier"
+If the value identified by \fIIdentifier\fR (see below) is found the complete
+value-list is returned. The response is a list of name-value-pairs, each pair
+on its own line (the number of lines is indicated by the status line \- see
+above). Each name-value-pair is of the form \fIname\fR\fB=\fR\fIvalue\fR.
+Counter-values are converted to a rate, e.\ g. bytes per second.
+Undefined values are returned as \fBNaN\fR.
+.Sp
+Example:
+  \-> | \s-1GETVAL\s0 myhost/cpu\-0/cpu\-user
+  <\- | 1 Value found
+  <\- | value=1.260000e+00
+.IP "\fB\s-1LISTVAL\s0\fR" 4
+.IX Item "LISTVAL"
+Returns a list of the values available in the value cache together with the
+time of the last update, so that querying applications can issue a \fB\s-1GETVAL\s0\fR
+command for the values that have changed. Each return value consists of the
+update time as an epoch value and the identifier, separated by a space. The
+update time is the time of the last value, as provided by the collecting
+instance and may be very different from the time the server considers to be
+\&\*(L"now\*(R".
+.Sp
+Example:
+  \-> | \s-1LISTVAL
+ \s0 <\- | 69 Values found
+  <\- | 1182204284 myhost/cpu\-0/cpu\-idle
+  <\- | 1182204284 myhost/cpu\-0/cpu\-nice
+  <\- | 1182204284 myhost/cpu\-0/cpu\-system
+  <\- | 1182204284 myhost/cpu\-0/cpu\-user
+  ...
+.IP "\fB\s-1PUTVAL\s0\fR \fIIdentifier\fR [\fIOptionList\fR] \fIValuelist\fR" 4
+.IX Item "PUTVAL Identifier [OptionList] Valuelist"
+Submits one or more values (identified by \fIIdentifier\fR, see below) to the
+daemon which will dispatch it to all it's write-plugins.
+.Sp
+An \fIIdentifier\fR is of the form
+\&\f(CW\*(C`\f(CIhost\f(CW\f(CB/\f(CW\f(CIplugin\f(CW\f(CB\-\f(CW\f(CIinstance\f(CW\f(CB/\f(CW\f(CItype\f(CW\f(CB\-\f(CW\f(CIinstance\f(CW\*(C'\fR with both
+\&\fIinstance\fR\-parts being optional. If they're omitted the hyphen must be
+omitted, too. \fIplugin\fR and each \fIinstance\fR\-part may be chosen freely as long
+as the tuple (plugin, plugin instance, type instance) uniquely identifies the
+plugin within collectd. \fItype\fR identifies the type and number of values
+(i.\ e. data-set) passed to collectd. A large list of predefined
+data-sets is available in the \fBtypes.db\fR file.
+.Sp
+The \fIOptionList\fR is an optional list of \fIOptions\fR, where each option is a
+key-value-pair. A list of currently understood options can be found below, all
+other options will be ignored. Values that contain spaces must be quoted with
+double quotes.
+.Sp
+\&\fIValuelist\fR is a colon-separated list of the time and the values, each either
+an integer if the data-source is a counter, or a double if the data-source is
+of type \*(L"gauge\*(R". You can submit an undefined gauge-value by using \fBU\fR. When
+submitting \fBU\fR to a counter the behavior is undefined. The time is given as
+epoch (i.\ e. standard \s-1UNIX\s0 time).
+.Sp
+You can mix options and values, but the order is important: Options only
+effect following values, so specifying an option as last field is allowed, but
+useless. Also, an option applies to \fBall\fR following values, so you don't need
+to re-set an option over and over again.
+.Sp
+The currently defined \fBOptions\fR are:
+.RS 4
+.IP "\fBinterval=\fR\fIseconds\fR" 4
+.IX Item "interval=seconds"
+Gives the interval in which the data identified by \fIIdentifier\fR is being
+collected.
+.RE
+.RS 4
+.Sp
+Please note that this is the same format as used in the \fBexec plugin\fR, see
+\&\fIcollectd\-exec\fR\|(5).
+.Sp
+Example:
+  \-> | \s-1PUTVAL\s0 testhost/interface/if_octets\-test0 interval=10 1179574444:123:456
+  <\- | 0 Success
+.RE
+.IP "\fB\s-1PUTNOTIF\s0\fR [\fIOptionList\fR] \fBmessage=\fR\fIMessage\fR" 4
+.IX Item "PUTNOTIF [OptionList] message=Message"
+Submits a notification to the daemon which will then dispatch it to all plugins
+which have registered for receiving notifications.
+.Sp
+The \fB\s-1PUTNOTIF\s0\fR command is followed by a list of options which further describe
+the notification. The \fBmessage\fR option is special in that it will consume the
+rest of the line as its value. The \fBmessage\fR, \fBseverity\fR, and \fBtime\fR options
+are mandatory.
+.Sp
+Valid options are:
+.RS 4
+.IP "\fBmessage=\fR\fIMessage\fR (\fB\s-1REQUIRED\s0\fR)" 4
+.IX Item "message=Message (REQUIRED)"
+Sets the message of the notification. This is the message that will be made
+accessible to the user, so it should contain some useful information. As with
+all options: If the message includes spaces, it must be quoted with double
+quotes. This option is mandatory.
+.IP "\fBseverity=failure\fR|\fBwarning\fR|\fBokay\fR (\fB\s-1REQUIRED\s0\fR)" 4
+.IX Item "severity=failure|warning|okay (REQUIRED)"
+Sets the severity of the notification. This option is mandatory.
+.IP "\fBtime=\fR\fITime\fR (\fB\s-1REQUIRED\s0\fR)" 4
+.IX Item "time=Time (REQUIRED)"
+Sets the time of the notification. The time is given as \*(L"epoch\*(R", i.\ e. as
+seconds since January 1st, 1970, 00:00:00. This option is mandatory.
+.IP "\fBhost=\fR\fIHostname\fR" 4
+.IX Item "host=Hostname"
+.PD 0
+.IP "\fBplugin=\fR\fIPlugin\fR" 4
+.IX Item "plugin=Plugin"
+.IP "\fBplugin_instance=\fR\fIPlugin-Instance\fR" 4
+.IX Item "plugin_instance=Plugin-Instance"
+.IP "\fBtype=\fR\fIType\fR" 4
+.IX Item "type=Type"
+.IP "\fBtype_instance=\fR\fIType-Instance\fR" 4
+.IX Item "type_instance=Type-Instance"
+.PD
+These \*(L"associative\*(R" options establish a relation between this notification and
+collected performance data. This connection is purely informal, i.\ e. the
+daemon itself doesn't do anything with this information. However, websites or
+GUIs may use this information to place notifications near the affected graph or
+table. All the options are optional, but \fBplugin_instance\fR without \fBplugin\fR
+or \fBtype_instance\fR without \fBtype\fR doesn't make much sense and should be
+avoided.
+.IP "\fBtype:key=\fR\fIvalue\fR" 4
+.IX Item "type:key=value"
+Sets user defined meta information. The \fBtype\fR key is a single character
+defining the type of the meta information.
+.Sp
+The current supported types are:
+.RS 4
+.IP "\fBs\fR A string passed as-is." 8
+.IX Item "s A string passed as-is."
+.RE
+.RS 4
+.RE
+.RE
+.RS 4
+.Sp
+Please note that this is the same format as used in the \fBexec plugin\fR, see
+\&\fIcollectd\-exec\fR\|(5).
+.Sp
+Example:
+  \-> | \s-1PUTNOTIF\s0 type=temperature severity=warning time=1201094702 message=The roof is on fire!
+  <\- | 0 Success
+.RE
+.IP "\fB\s-1FLUSH\s0\fR [\fBtimeout=\fR\fITimeout\fR] [\fBplugin=\fR\fIPlugin\fR [...]] [\fBidentifier=\fR\fIIdent\fR [...]]" 4
+.IX Item "FLUSH [timeout=Timeout] [plugin=Plugin [...]] [identifier=Ident [...]]"
+Flushes all cached data older than \fITimeout\fR seconds. If no timeout has been
+specified, it defaults to \-1 which causes all data to be flushed.
+.Sp
+If the \fBplugin\fR option has been specified, only the \fIPlugin\fR plugin will be
+flushed. You can have multiple \fBplugin\fR options to flush multiple plugins in
+one go. If the \fBplugin\fR option is not given all plugins providing a flush
+callback will be flushed.
+.Sp
+If the \fBidentifier\fR option is given only the specified values will be flushed.
+This is meant to be used by graphing or displaying frontends which want to have
+the latest values for a specific graph. Again, you can specify the
+\&\fBidentifier\fR option multiple times to flush several values. If this option is
+not specified at all, all values will be flushed.
+.Sp
+Example:
+  \-> | \s-1FLUSH\s0 plugin=rrdtool identifier=localhost/df/df\-root identifier=localhost/df/df\-var
+  <\- | 0 Done: 2 successful, 0 errors
+.SS "Identifiers"
+.IX Subsection "Identifiers"
+Value or value-lists are identified in a uniform fashion:
+.PP
+\&\fIHostname\fR/\fIPlugin\fR/\fIType\fR
+.PP
+Where \fIPlugin\fR and \fIType\fR are both either of type "\fIName\fR\*(L" or
+\&\*(R"\fIName\fR\-\fIInstance\fR". If the identifier includes spaces, it must be quoted
+using double quotes. This sounds more complicated than it is, so here are
+some examples:
+.PP
+.Vb 5
+\&  myhost/cpu\-0/cpu\-user
+\&  myhost/load/load
+\&  myhost/memory/memory\-used
+\&  myhost/disk\-sda/disk_octets
+\&  "myups/snmp/temperature\-Outlet 1"
+.Ve
+.SH "ABSTRACTION LAYER"
+.IX Header "ABSTRACTION LAYER"
+\&\fBcollectd\fR ships the Perl-Module Collectd::Unixsock which
+provides an abstraction layer over the actual socket connection. It can be
+found in the directory \fIbindings/perl/\fR in the source distribution or
+(usually) somewhere near \fI/usr/share/perl5/\fR if you're using a package. If
+you want to use Perl to communicate with the daemon, you're encouraged to use
+and expand this module.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-nagios\fR\|(1),
+\&\fIunix\fR\|(7)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo@collectd.org>
diff --git a/src/collectd-unixsock.pod b/src/collectd-unixsock.pod
new file mode 100644 (file)
index 0000000..b241a9f
--- /dev/null
@@ -0,0 +1,261 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd-unixsock - Documentation of collectd's C<unixsock plugin>
+
+=head1 SYNOPSIS
+
+  # See collectd.conf(5)
+  LoadPlugin unixsock
+  # ...
+  <Plugin unixsock>
+    SocketFile "/path/to/socket"
+    SocketGroup "collectd"
+    SocketPerms "0770"
+    DeleteSocket false
+  </Plugin>
+
+=head1 DESCRIPTION
+
+The C<unixsock plugin> opens an UNIX-socket over which one can interact with
+the daemon. This can be used to use the values collected by collectd in other
+applications, such as monitoring solutions, or submit externally collected
+values to collectd.
+
+For example, this plugin is used by L<collectd-nagios(1)> to check if some
+value is in a certain range and exit with a Nagios-compatible exit code.
+
+=head1 COMMANDS
+
+Upon start the C<unixsock plugin> opens a UNIX-socket and waits for
+connections. Once a connection is established the client can send commands to
+the daemon which it will answer, if it understand them.
+
+In general the plugin answers with a status line of the following form:
+
+I<Status> I<Message>
+
+If I<Status> is greater than or equal to zero the message indicates success,
+if I<Status> is less than zero the message indicates failure. I<Message> is a
+human-readable string that further describes the return value.
+
+On success, I<Status> furthermore indicates the number of subsequent lines of
+output (not including the status line). Each such lines usually contains a
+single return value. See the description of each command for details.
+
+The following commands are implemented:
+
+=over 4
+
+=item B<GETVAL> I<Identifier>
+
+If the value identified by I<Identifier> (see below) is found the complete
+value-list is returned. The response is a list of name-value-pairs, each pair
+on its own line (the number of lines is indicated by the status line - see
+above). Each name-value-pair is of the form I<name>B<=>I<value>.
+Counter-values are converted to a rate, e.E<nbsp>g. bytes per second.
+Undefined values are returned as B<NaN>.
+
+Example:
+  -> | GETVAL myhost/cpu-0/cpu-user
+  <- | 1 Value found
+  <- | value=1.260000e+00
+
+=item B<LISTVAL>
+
+Returns a list of the values available in the value cache together with the
+time of the last update, so that querying applications can issue a B<GETVAL>
+command for the values that have changed. Each return value consists of the
+update time as an epoch value and the identifier, separated by a space. The
+update time is the time of the last value, as provided by the collecting
+instance and may be very different from the time the server considers to be
+"now".
+
+Example:
+  -> | LISTVAL
+  <- | 69 Values found
+  <- | 1182204284 myhost/cpu-0/cpu-idle
+  <- | 1182204284 myhost/cpu-0/cpu-nice
+  <- | 1182204284 myhost/cpu-0/cpu-system
+  <- | 1182204284 myhost/cpu-0/cpu-user
+  ...
+
+=item B<PUTVAL> I<Identifier> [I<OptionList>] I<Valuelist>
+
+Submits one or more values (identified by I<Identifier>, see below) to the
+daemon which will dispatch it to all it's write-plugins.
+
+An I<Identifier> is of the form
+C<I<host>B</>I<plugin>B<->I<instance>B</>I<type>B<->I<instance>> with both
+I<instance>-parts being optional. If they're omitted the hyphen must be
+omitted, too. I<plugin> and each I<instance>-part may be chosen freely as long
+as the tuple (plugin, plugin instance, type instance) uniquely identifies the
+plugin within collectd. I<type> identifies the type and number of values
+(i.E<nbsp>e. data-set) passed to collectd. A large list of predefined
+data-sets is available in the B<types.db> file.
+
+The I<OptionList> is an optional list of I<Options>, where each option is a
+key-value-pair. A list of currently understood options can be found below, all
+other options will be ignored. Values that contain spaces must be quoted with
+double quotes.
+
+I<Valuelist> is a colon-separated list of the time and the values, each either
+an integer if the data-source is a counter, or a double if the data-source is
+of type "gauge". You can submit an undefined gauge-value by using B<U>. When
+submitting B<U> to a counter the behavior is undefined. The time is given as
+epoch (i.E<nbsp>e. standard UNIX time).
+
+You can mix options and values, but the order is important: Options only
+effect following values, so specifying an option as last field is allowed, but
+useless. Also, an option applies to B<all> following values, so you don't need
+to re-set an option over and over again.
+
+The currently defined B<Options> are:
+
+=over 4
+
+=item B<interval=>I<seconds>
+
+Gives the interval in which the data identified by I<Identifier> is being
+collected.
+
+=back
+
+Please note that this is the same format as used in the B<exec plugin>, see
+L<collectd-exec(5)>.
+
+Example:
+  -> | PUTVAL testhost/interface/if_octets-test0 interval=10 1179574444:123:456
+  <- | 0 Success
+
+=item B<PUTNOTIF> [I<OptionList>] B<message=>I<Message>
+
+Submits a notification to the daemon which will then dispatch it to all plugins
+which have registered for receiving notifications. 
+
+The B<PUTNOTIF> command is followed by a list of options which further describe
+the notification. The B<message> option is special in that it will consume the
+rest of the line as its value. The B<message>, B<severity>, and B<time> options
+are mandatory.
+
+Valid options are:
+
+=over 4
+
+=item B<message=>I<Message> (B<REQUIRED>)
+
+Sets the message of the notification. This is the message that will be made
+accessible to the user, so it should contain some useful information. As with
+all options: If the message includes spaces, it must be quoted with double
+quotes. This option is mandatory.
+
+=item B<severity=failure>|B<warning>|B<okay> (B<REQUIRED>)
+
+Sets the severity of the notification. This option is mandatory.
+
+=item B<time=>I<Time> (B<REQUIRED>)
+
+Sets the time of the notification. The time is given as "epoch", i.E<nbsp>e. as
+seconds since January 1st, 1970, 00:00:00. This option is mandatory.
+
+=item B<host=>I<Hostname>
+
+=item B<plugin=>I<Plugin>
+
+=item B<plugin_instance=>I<Plugin-Instance>
+
+=item B<type=>I<Type>
+
+=item B<type_instance=>I<Type-Instance>
+
+These "associative" options establish a relation between this notification and
+collected performance data. This connection is purely informal, i.E<nbsp>e. the
+daemon itself doesn't do anything with this information. However, websites or
+GUIs may use this information to place notifications near the affected graph or
+table. All the options are optional, but B<plugin_instance> without B<plugin>
+or B<type_instance> without B<type> doesn't make much sense and should be
+avoided.
+
+=item B<type:key=>I<value>
+
+Sets user defined meta information. The B<type> key is a single character
+defining the type of the meta information.
+
+The current supported types are:
+
+=over 8
+
+=item B<s> A string passed as-is.
+
+=back
+
+=back
+
+Please note that this is the same format as used in the B<exec plugin>, see
+L<collectd-exec(5)>.
+
+Example:
+  -> | PUTNOTIF type=temperature severity=warning time=1201094702 message=The roof is on fire!
+  <- | 0 Success
+
+=item B<FLUSH> [B<timeout=>I<Timeout>] [B<plugin=>I<Plugin> [...]] [B<identifier=>I<Ident> [...]]
+
+Flushes all cached data older than I<Timeout> seconds. If no timeout has been
+specified, it defaults to -1 which causes all data to be flushed.
+
+If the B<plugin> option has been specified, only the I<Plugin> plugin will be
+flushed. You can have multiple B<plugin> options to flush multiple plugins in
+one go. If the B<plugin> option is not given all plugins providing a flush
+callback will be flushed.
+
+If the B<identifier> option is given only the specified values will be flushed.
+This is meant to be used by graphing or displaying frontends which want to have
+the latest values for a specific graph. Again, you can specify the
+B<identifier> option multiple times to flush several values. If this option is
+not specified at all, all values will be flushed.
+
+Example:
+  -> | FLUSH plugin=rrdtool identifier=localhost/df/df-root identifier=localhost/df/df-var
+  <- | 0 Done: 2 successful, 0 errors
+
+=back
+
+=head2 Identifiers
+
+Value or value-lists are identified in a uniform fashion:
+
+I<Hostname>/I<Plugin>/I<Type>
+
+Where I<Plugin> and I<Type> are both either of type "I<Name>" or
+"I<Name>-I<Instance>". If the identifier includes spaces, it must be quoted
+using double quotes. This sounds more complicated than it is, so here are
+some examples:
+
+  myhost/cpu-0/cpu-user
+  myhost/load/load
+  myhost/memory/memory-used
+  myhost/disk-sda/disk_octets
+  "myups/snmp/temperature-Outlet 1"
+
+=head1 ABSTRACTION LAYER
+
+B<collectd> ships the Perl-Module L<Collectd::Unixsock> which
+provides an abstraction layer over the actual socket connection. It can be
+found in the directory F<bindings/perl/> in the source distribution or
+(usually) somewhere near F</usr/share/perl5/> if you're using a package. If
+you want to use Perl to communicate with the daemon, you're encouraged to use
+and expand this module.
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-nagios(1)>,
+L<unix(7)>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octo@collectd.orgE<gt>
+
+=cut
diff --git a/src/collectd.1 b/src/collectd.1
new file mode 100644 (file)
index 0000000..91934c0
--- /dev/null
@@ -0,0 +1,251 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD 1"
+.TH COLLECTD 1 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd \- System statistics collection daemon
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+collectd \fI[options]\fR
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+collectd is a daemon that receives system statistics and makes them available
+in a number of ways. The main daemon itself doesn't have any real functionality
+apart from loading, querying and submitting to plugins. For a description of
+available plugins please see \*(L"\s-1PLUGINS\*(R"\s0 below.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+Most of collectd's configuration is done using using a configfile. See
+\&\fIcollectd.conf\fR\|(5) for an in-depth description of all options.
+.IP "\fB\-C\fR \fI<config\-file>\fR" 4
+.IX Item "-C <config-file>"
+Specify an alternative config file. This is the place to go when you wish to
+change \fBcollectd\fR's behavior. The path may be relative to the current working
+directory.
+.IP "\fB\-t\fR" 4
+.IX Item "-t"
+Test the configuration only. The program immediately exits after parsing the
+config file. A return code not equal to zero indicates an error.
+.IP "\fB\-T\fR" 4
+.IX Item "-T"
+Test the plugin read callbacks only. The program immediately exits after invoking
+the read callbacks once. A return code not equal to zero indicates an error.
+.IP "\fB\-P\fR \fI<pid\-file>\fR" 4
+.IX Item "-P <pid-file>"
+Specify an alternative pid file. This overwrites any settings in the config 
+file. This is thought for init-scripts that require the PID-file in a certain
+directory to work correctly. For everyday-usage use the \fBPIDFile\fR
+config-option.
+.IP "\fB\-f\fR" 4
+.IX Item "-f"
+Don't fork to the background. \fIcollectd\fR will also \fBnot\fR close standard file
+descriptors, detach from the session nor write a pid file. This is mainly
+thought for 'supervising' init replacements such as \fIrunit\fR. If using
+\&\fIupstart\fR or \fIsystemd\fR though, starting with version 5.5.0 \fIcollectd\fR is
+able to notify these two init replacements, and \fBdoes\fR require forking to the
+background for process supervision. The \fIcontrib/\fR directory has sample
+\&\fIupstart\fR and \fIsystemd\fR configuration files.
+.IP "\fB\-h\fR" 4
+.IX Item "-h"
+Output usage information and exit.
+.SH "PLUGINS"
+.IX Header "PLUGINS"
+As noted above, the real power of collectd lies within it's plugins. A
+(hopefully complete) list of plugins and short descriptions can be found in the
+\&\fI\s-1README\s0\fR file that is distributed with the sourcecode. If you're using a
+package it's a good bet to search somewhere near \fI/usr/share/doc/collectd\fR.
+.PP
+There are two big groups of plugins, \fBinput\fR and \fBoutput\fR plugins:
+.IP "\(bu" 4
+Input plugins are queried periodically. They somehow acquire the current value
+of whatever they where designed to work with and submit these values back to
+the daemon, i. e. they \*(L"dispatch\*(R" the values. As an example, the \f(CW\*(C`cpu plugin\*(C'\fR
+reads the current cpu-counters of time spent in the various modes (user,
+system, nice, ...) and dispatches these counters to the daemon.
+.IP "\(bu" 4
+Output plugins get the dispatched values from the daemon and does something
+with them. Common applications are writing to RRD-files, CSV-files or sending
+the data over a network link to a remote box.
+.PP
+Of course not all plugins fit neatly into one of the two above categories. The
+\&\f(CW\*(C`network plugin\*(C'\fR, for example, is able to send (i.\ e. \*(L"write\*(R") \fBand\fR
+receive (i.\ e. \*(L"dispatch\*(R") values. Also, it opens a socket upon
+initialization and dispatches the values when it receives them and isn't
+triggered at the same time the input plugins are being read. You can think of
+the network receive part as working asynchronous if it helps.
+.PP
+In addition to the above, there are \*(L"logging plugins\*(R". Right now those are the
+\&\f(CW\*(C`logfile plugin\*(C'\fR and the \f(CW\*(C`syslog plugin\*(C'\fR. With these plugins collectd can
+provide information about issues and significant situations to the user.
+Several loglevels let you suppress uninteresting messages.
+.PP
+Starting with version \f(CW4.3.0\fR collectd has support for \fBmonitoring\fR. This is
+done by checking thresholds defined by the user. If a value is out of range, a
+notification will be dispatched to \*(L"notification plugins\*(R". See
+\&\fIcollectd.conf\fR\|(5) for more detailed information about threshold checking.
+.PP
+Please note that some plugins, that provide other means of communicating with
+the daemon, have manpages of their own to describe their functionality in more
+detail. In particular those are \fIcollectd\-email\fR\|(5), \fIcollectd\-exec\fR\|(5),
+\&\fIcollectd\-perl\fR\|(5), \fIcollectd\-snmp\fR\|(5), and \fIcollectd\-unixsock\fR\|(5)
+.SH "SIGNALS"
+.IX Header "SIGNALS"
+\&\fBcollectd\fR accepts the following signals:
+.IP "\fB\s-1SIGINT\s0\fR, \fB\s-1SIGTERM\s0\fR" 4
+.IX Item "SIGINT, SIGTERM"
+These signals cause \fBcollectd\fR to shut down all plugins and terminate.
+.IP "\fB\s-1SIGUSR1\s0\fR" 4
+.IX Item "SIGUSR1"
+This signal causes \fBcollectd\fR to signal all plugins to flush data from
+internal caches. E.\ g. the \f(CW\*(C`rrdtool plugin\*(C'\fR will write all pending data
+to the \s-1RRD\s0 files. This is the same as using the \f(CW\*(C`FLUSH \-1\*(C'\fR command of the
+\&\f(CW\*(C`unixsock plugin\*(C'\fR.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-email\fR\|(5),
+\&\fIcollectd\-exec\fR\|(5),
+\&\fIcollectd\-perl\fR\|(5),
+\&\fIcollectd\-snmp\fR\|(5),
+\&\fIcollectd\-unixsock\fR\|(5),
+\&\fItypes.db\fR\|(5),
+<http://collectd.org/>
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo@collectd.org>
diff --git a/src/collectd.conf.5 b/src/collectd.conf.5
new file mode 100644 (file)
index 0000000..d4514a1
--- /dev/null
@@ -0,0 +1,7901 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTD.CONF 5"
+.TH COLLECTD.CONF 5 "2015-05-20" "5.4.2.911.g0c88d3b" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectd.conf \- Configuration for the system statistics collection daemon collectd
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 3
+\&  BaseDir "/var/lib/collectd"
+\&  PIDFile "/run/collectd.pid"
+\&  Interval 10.0
+\&
+\&  LoadPlugin cpu
+\&  LoadPlugin load
+\&
+\&  <LoadPlugin df>
+\&    Interval 3600
+\&  </LoadPlugin>
+\&  <Plugin df>
+\&    ValuesPercentage true
+\&  </Plugin>
+\&
+\&  LoadPlugin ping
+\&  <Plugin ping>
+\&    Host "example.org"
+\&    Host "provider.net"
+\&  </Plugin>
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+This config file controls how the system statistics collection daemon
+\&\fBcollectd\fR behaves. The most significant option is \fBLoadPlugin\fR, which
+controls which plugins to load. These plugins ultimately define collectd's
+behavior. If the \fBAutoLoadPlugin\fR option has been enabled, the explicit
+\&\fBLoadPlugin\fR lines may be omitted for all plugins with a configuration block,
+i.e. a \f(CW\*(C`<Plugin\ ...>\*(C'\fR block.
+.PP
+The syntax of this config file is similar to the config file of the famous
+\&\fIApache\fR webserver. Each line contains either an option (a key and a list of
+one or more values) or a section-start or \-end. Empty lines and everything
+after a non-quoted hash-symbol (\f(CW\*(C`#\*(C'\fR) is ignored. \fIKeys\fR are unquoted
+strings, consisting only of alphanumeric characters and the underscore (\f(CW\*(C`_\*(C'\fR)
+character. Keys are handled case insensitive by \fIcollectd\fR itself and all
+plugins included with it. \fIValues\fR can either be an \fIunquoted string\fR, a
+\&\fIquoted string\fR (enclosed in double-quotes) a \fInumber\fR or a \fIboolean\fR
+expression. \fIUnquoted strings\fR consist of only alphanumeric characters and
+underscores (\f(CW\*(C`_\*(C'\fR) and do not need to be quoted. \fIQuoted strings\fR are
+enclosed in double quotes (\f(CW\*(C`"\*(C'\fR). You can use the backslash character (\f(CW\*(C`\e\*(C'\fR)
+to include double quotes as part of the string. \fINumbers\fR can be specified in
+decimal and floating point format (using a dot \f(CW\*(C`.\*(C'\fR as decimal separator),
+hexadecimal when using the \f(CW\*(C`0x\*(C'\fR prefix and octal with a leading zero (\f(CW0\fR).
+\&\fIBoolean\fR values are either \fBtrue\fR or \fBfalse\fR.
+.PP
+Lines may be wrapped by using \f(CW\*(C`\e\*(C'\fR as the last character before the newline.
+This allows long lines to be split into multiple lines. Quoted strings may be
+wrapped as well. However, those are treated special in that whitespace at the
+beginning of the following lines will be ignored, which allows for nicely
+indenting the wrapped lines.
+.PP
+The configuration is read and processed in order, i.e. from top to bottom. So
+the plugins are loaded in the order listed in this config file. It is a good
+idea to load any logging plugins first in order to catch messages from plugins
+during configuration. Also, unless \fBAutoLoadPlugin\fR is enabled, the
+\&\fBLoadPlugin\fR option \fImust\fR occur \fIbefore\fR the appropriate
+\&\f(CW\*(C`<\f(CBPlugin\f(CW ...>\*(C'\fR block.
+.SH "GLOBAL OPTIONS"
+.IX Header "GLOBAL OPTIONS"
+.IP "\fBBaseDir\fR \fIDirectory\fR" 4
+.IX Item "BaseDir Directory"
+Sets the base directory. This is the directory beneath all RRD-files are
+created. Possibly more subdirectories are created. This is also the working
+directory for the daemon.
+.IP "\fBLoadPlugin\fR \fIPlugin\fR" 4
+.IX Item "LoadPlugin Plugin"
+Loads the plugin \fIPlugin\fR. This is required to load plugins, unless the
+\&\fBAutoLoadPlugin\fR option is enabled (see below). Without any loaded plugins,
+\&\fIcollectd\fR will be mostly useless.
+.Sp
+Only the first \fBLoadPlugin\fR statement or block for a given plugin name has any
+effect. This is useful when you want to split up the configuration into smaller
+files and want each file to be \*(L"self contained\*(R", i.e. it contains a \fBPlugin\fR
+block \fIand\fR then appropriate \fBLoadPlugin\fR statement. The downside is that if
+you have multiple conflicting \fBLoadPlugin\fR blocks, e.g. when they specify
+different intervals, only one of them (the first one encountered) will take
+effect and all others will be silently ignored.
+.Sp
+\&\fBLoadPlugin\fR may either be a simple configuration \fIstatement\fR or a \fIblock\fR
+with additional options, affecting the behavior of \fBLoadPlugin\fR. A simple
+statement looks like this:
+.Sp
+.Vb 1
+\& LoadPlugin "cpu"
+.Ve
+.Sp
+Options inside a \fBLoadPlugin\fR block can override default settings and
+influence the way plugins are loaded, e.g.:
+.Sp
+.Vb 3
+\& <LoadPlugin perl>
+\&   Interval 60
+\& </LoadPlugin>
+.Ve
+.Sp
+The following options are valid inside \fBLoadPlugin\fR blocks:
+.RS 4
+.IP "\fBGlobals\fR \fBtrue|false\fR" 4
+.IX Item "Globals true|false"
+If enabled, collectd will export all global symbols of the plugin (and of all
+libraries loaded as dependencies of the plugin) and, thus, makes those symbols
+available for resolving unresolved symbols in subsequently loaded plugins if
+that is supported by your system.
+.Sp
+This is useful (or possibly even required), e.g., when loading a plugin that
+embeds some scripting language into the daemon (e.g. the \fIPerl\fR and
+\&\fIPython plugins\fR). Scripting languages usually provide means to load
+extensions written in C. Those extensions require symbols provided by the
+interpreter, which is loaded as a dependency of the respective collectd plugin.
+See the documentation of those plugins (e.g., \fIcollectd\-perl\fR\|(5) or
+\&\fIcollectd\-python\fR\|(5)) for details.
+.Sp
+By default, this is disabled. As a special exception, if the plugin name is
+either \f(CW\*(C`perl\*(C'\fR or \f(CW\*(C`python\*(C'\fR, the default is changed to enabled in order to keep
+the average user from ever having to deal with this low level linking stuff.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Sets a plugin-specific interval for collecting metrics. This overrides the
+global \fBInterval\fR setting. If a plugin provides own support for specifying an
+interval, that setting will take precedence.
+.RE
+.RS 4
+.RE
+.IP "\fBAutoLoadPlugin\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "AutoLoadPlugin false|true"
+When set to \fBfalse\fR (the default), each plugin needs to be loaded explicitly,
+using the \fBLoadPlugin\fR statement documented above. If a
+\&\fB<Plugin\ ...>\fR block is encountered and no configuration
+handling callback for this plugin has been registered, a warning is logged and
+the block is ignored.
+.Sp
+When set to \fBtrue\fR, explicit \fBLoadPlugin\fR statements are not required. Each
+\&\fB<Plugin\ ...>\fR block acts as if it was immediately preceded by a
+\&\fBLoadPlugin\fR statement. \fBLoadPlugin\fR statements are still required for
+plugins that don't provide any configuration, e.g. the \fILoad plugin\fR.
+.IP "\fBCollectInternalStats\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "CollectInternalStats false|true"
+When set to \fBtrue\fR, various statistics about the \fIcollectd\fR daemon will be
+collected, with \*(L"collectd\*(R" as the \fIplugin name\fR. Defaults to \fBfalse\fR.
+.Sp
+The \*(L"write_queue\*(R" \fIplugin instance\fR reports the number of elements currently
+queued and the number of elements dropped off the queue by the
+\&\fBWriteQueueLimitLow\fR/\fBWriteQueueLimitHigh\fR mechanism.
+.Sp
+The \*(L"cache\*(R" \fIplugin instance\fR reports the number of elements in the value list
+cache (the cache you can interact with using \fIcollectd\-unixsock\fR\|(5)).
+.IP "\fBInclude\fR \fIPath\fR [\fIpattern\fR]" 4
+.IX Item "Include Path [pattern]"
+If \fIPath\fR points to a file, includes that file. If \fIPath\fR points to a
+directory, recursively includes all files within that directory and its
+subdirectories. If the \f(CW\*(C`wordexp\*(C'\fR function is available on your system,
+shell-like wildcards are expanded before files are included. This means you can
+use statements like the following:
+.Sp
+.Vb 1
+\&  Include "/etc/collectd.d/*.conf"
+.Ve
+.Sp
+Starting with version 5.3, this may also be a block in which further options
+affecting the behavior of \fBInclude\fR may be specified. The following option is
+currently allowed:
+.Sp
+.Vb 3
+\&  <Include "/etc/collectd.d">
+\&    Filter "*.conf"
+\&  </Include>
+.Ve
+.RS 4
+.IP "\fBFilter\fR \fIpattern\fR" 4
+.IX Item "Filter pattern"
+If the \f(CW\*(C`fnmatch\*(C'\fR function is available on your system, a shell-like wildcard
+\&\fIpattern\fR may be specified to filter which files to include. This may be used
+in combination with recursively including a directory to easily be able to
+arbitrarily mix configuration files and other documents (e.g. \s-1README\s0 files).
+The given example is similar to the first example above but includes all files
+matching \f(CW\*(C`*.conf\*(C'\fR in any subdirectory of \f(CW\*(C`/etc/collectd.d\*(C'\fR:
+.Sp
+.Vb 1
+\&  Include "/etc/collectd.d" "*.conf"
+.Ve
+.RE
+.RS 4
+.Sp
+If more than one files are included by a single \fBInclude\fR option, the files
+will be included in lexicographical order (as defined by the \f(CW\*(C`strcmp\*(C'\fR
+function). Thus, you can e.\ g. use numbered prefixes to specify the
+order in which the files are loaded.
+.Sp
+To prevent loops and shooting yourself in the foot in interesting ways the
+nesting is limited to a depth of 8\ levels, which should be sufficient for
+most uses. Since symlinks are followed it is still possible to crash the daemon
+by looping symlinks. In our opinion significant stupidity should result in an
+appropriate amount of pain.
+.Sp
+It is no problem to have a block like \f(CW\*(C`<Plugin foo>\*(C'\fR in more than one
+file, but you cannot include files from within blocks.
+.RE
+.IP "\fBPIDFile\fR \fIFile\fR" 4
+.IX Item "PIDFile File"
+Sets where to write the \s-1PID\s0 file to. This file is overwritten when it exists
+and deleted when the program is stopped. Some init-scripts might override this
+setting using the \fB\-P\fR command-line option.
+.IP "\fBPluginDir\fR \fIDirectory\fR" 4
+.IX Item "PluginDir Directory"
+Path to the plugins (shared objects) of collectd.
+.IP "\fBTypesDB\fR \fIFile\fR [\fIFile\fR ...]" 4
+.IX Item "TypesDB File [File ...]"
+Set one or more files that contain the data-set descriptions. See
+\&\fItypes.db\fR\|(5) for a description of the format of this file.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Configures the interval in which to query the read plugins. Obviously smaller
+values lead to a higher system load produced by collectd, while higher values
+lead to more coarse statistics.
+.Sp
+\&\fBWarning:\fR You should set this once and then never touch it again. If you do,
+\&\fIyou will have to delete all your \s-1RRD\s0 files\fR or know some serious RRDtool
+magic! (Assuming you're using the \fIRRDtool\fR or \fIRRDCacheD\fR plugin.)
+.IP "\fBMaxReadInterval\fR \fISeconds\fR" 4
+.IX Item "MaxReadInterval Seconds"
+Read plugin doubles interval between queries after each failed attempt
+to get data.
+.Sp
+This options limits the maximum value of the interval. The default value is
+\&\fB86400\fR.
+.IP "\fBTimeout\fR \fIIterations\fR" 4
+.IX Item "Timeout Iterations"
+Consider a value list \*(L"missing\*(R" when no update has been read or received for
+\&\fIIterations\fR iterations. By default, \fIcollectd\fR considers a value list
+missing when no update has been received for twice the update interval. Since
+this setting uses iterations, the maximum allowed time without update depends
+on the \fIInterval\fR information contained in each value list. This is used in
+the \fIThreshold\fR configuration to dispatch notifications about missing values,
+see \fIcollectd\-threshold\fR\|(5) for details.
+.IP "\fBReadThreads\fR \fINum\fR" 4
+.IX Item "ReadThreads Num"
+Number of threads to start for reading plugins. The default value is \fB5\fR, but
+you may want to increase this if you have more than five plugins that take a
+long time to read. Mostly those are plugins that do network-IO. Setting this to
+a value higher than the number of registered read callbacks is not recommended.
+.IP "\fBWriteThreads\fR \fINum\fR" 4
+.IX Item "WriteThreads Num"
+Number of threads to start for dispatching value lists to write plugins. The
+default value is \fB5\fR, but you may want to increase this if you have more than
+five plugins that may take relatively long to write to.
+.IP "\fBWriteQueueLimitHigh\fR \fIHighNum\fR" 4
+.IX Item "WriteQueueLimitHigh HighNum"
+.PD 0
+.IP "\fBWriteQueueLimitLow\fR \fILowNum\fR" 4
+.IX Item "WriteQueueLimitLow LowNum"
+.PD
+Metrics are read by the \fIread threads\fR and then put into a queue to be handled
+by the \fIwrite threads\fR. If one of the \fIwrite plugins\fR is slow (e.g. network
+timeouts, I/O saturation of the disk) this queue will grow. In order to avoid
+running into memory issues in such a case, you can limit the size of this
+queue.
+.Sp
+By default, there is no limit and memory may grow indefinitely. This is most
+likely not an issue for clients, i.e. instances that only handle the local
+metrics. For servers it is recommended to set this to a non-zero value, though.
+.Sp
+You can set the limits using \fBWriteQueueLimitHigh\fR and \fBWriteQueueLimitLow\fR.
+Each of them takes a numerical argument which is the number of metrics in the
+queue. If there are \fIHighNum\fR metrics in the queue, any new metrics \fIwill\fR be
+dropped. If there are less than \fILowNum\fR metrics in the queue, all new metrics
+\&\fIwill\fR be enqueued. If the number of metrics currently in the queue is between
+\&\fILowNum\fR and \fIHighNum\fR, the metric is dropped with a probability that is
+proportional to the number of metrics in the queue (i.e. it increases linearly
+until it reaches 100%.)
+.Sp
+If \fBWriteQueueLimitHigh\fR is set to non-zero and \fBWriteQueueLimitLow\fR is
+unset, the latter will default to half of \fBWriteQueueLimitHigh\fR.
+.Sp
+If you do not want to randomly drop values when the queue size is between
+\&\fILowNum\fR and \fIHighNum\fR, set \fBWriteQueueLimitHigh\fR and \fBWriteQueueLimitLow\fR
+to the same value.
+.Sp
+Enabling the \fBCollectInternalStats\fR option is of great help to figure out the
+values to set \fBWriteQueueLimitHigh\fR and \fBWriteQueueLimitLow\fR to.
+.IP "\fBHostname\fR \fIName\fR" 4
+.IX Item "Hostname Name"
+Sets the hostname that identifies a host. If you omit this setting, the
+hostname will be determined using the \fIgethostname\fR\|(2) system call.
+.IP "\fBFQDNLookup\fR \fBtrue|false\fR" 4
+.IX Item "FQDNLookup true|false"
+If \fBHostname\fR is determined automatically this setting controls whether or not
+the daemon should try to figure out the \*(L"fully qualified domain name\*(R", \s-1FQDN.\s0
+This is done using a lookup of the name returned by \f(CW\*(C`gethostname\*(C'\fR. This option
+is enabled by default.
+.IP "\fBPreCacheChain\fR \fIChainName\fR" 4
+.IX Item "PreCacheChain ChainName"
+.PD 0
+.IP "\fBPostCacheChain\fR \fIChainName\fR" 4
+.IX Item "PostCacheChain ChainName"
+.PD
+Configure the name of the \*(L"pre-cache chain\*(R" and the \*(L"post-cache chain\*(R". Please
+see \*(L"\s-1FILTER CONFIGURATION\*(R"\s0 below on information on chains and how these
+setting change the daemon's behavior.
+.SH "PLUGIN OPTIONS"
+.IX Header "PLUGIN OPTIONS"
+Some plugins may register own options. These options must be enclosed in a
+\&\f(CW\*(C`Plugin\*(C'\fR\-Section. Which options exist depends on the plugin used. Some plugins
+require external configuration, too. The \f(CW\*(C`apache plugin\*(C'\fR, for example,
+required \f(CW\*(C`mod_status\*(C'\fR to be configured in the webserver you're going to
+collect data from. These plugins are listed below as well, even if they don't
+require any configuration within collectd's configuration file.
+.PP
+A list of all plugins and a short summary for each plugin can be found in the
+\&\fI\s-1README\s0\fR file shipped with the sourcecode and hopefully binary packets as
+well.
+.ie n .SS "Plugin ""aggregation"""
+.el .SS "Plugin \f(CWaggregation\fP"
+.IX Subsection "Plugin aggregation"
+The \fIAggregation plugin\fR makes it possible to aggregate several values into
+one using aggregation functions such as \fIsum\fR, \fIaverage\fR, \fImin\fR and \fImax\fR.
+This can be put to a wide variety of uses, e.g. average and total \s-1CPU\s0
+statistics for your entire fleet.
+.PP
+The grouping is powerful but, as with many powerful tools, may be a bit
+difficult to wrap your head around. The grouping will therefore be
+demonstrated using an example: The average and sum of the \s-1CPU\s0 usage across
+all CPUs of each host is to be calculated.
+.PP
+To select all the affected values for our example, set \f(CW\*(C`Plugin cpu\*(C'\fR and
+\&\f(CW\*(C`Type cpu\*(C'\fR. The other values are left unspecified, meaning \*(L"all values\*(R". The
+\&\fIHost\fR, \fIPlugin\fR, \fIPluginInstance\fR, \fIType\fR and \fITypeInstance\fR options
+work as if they were specified in the \f(CW\*(C`WHERE\*(C'\fR clause of an \f(CW\*(C`SELECT\*(C'\fR \s-1SQL\s0
+statement.
+.PP
+.Vb 2
+\&  Plugin "cpu"
+\&  Type "cpu"
+.Ve
+.PP
+Although the \fIHost\fR, \fIPluginInstance\fR (\s-1CPU\s0 number, i.e. 0, 1, 2, ...)  and
+\&\fITypeInstance\fR (idle, user, system, ...) fields are left unspecified in the
+example, the intention is to have a new value for each host / type instance
+pair. This is achieved by \*(L"grouping\*(R" the values using the \f(CW\*(C`GroupBy\*(C'\fR option.
+It can be specified multiple times to group by more than one field.
+.PP
+.Vb 2
+\&  GroupBy "Host"
+\&  GroupBy "TypeInstance"
+.Ve
+.PP
+We do neither specify nor group by \fIplugin instance\fR (the \s-1CPU\s0 number), so all
+metrics that differ in the \s-1CPU\s0 number only will be aggregated. Each
+aggregation needs \fIat least one\fR such field, otherwise no aggregation would
+take place.
+.PP
+The full example configuration looks like this:
+.PP
+.Vb 4
+\& <Plugin "aggregation">
+\&   <Aggregation>
+\&     Plugin "cpu"
+\&     Type "cpu"
+\&
+\&     GroupBy "Host"
+\&     GroupBy "TypeInstance"
+\&
+\&     CalculateSum true
+\&     CalculateAverage true
+\&   </Aggregation>
+\& </Plugin>
+.Ve
+.PP
+There are a couple of limitations you should be aware of:
+.IP "\(bu" 4
+The \fIType\fR cannot be left unspecified, because it is not reasonable to add
+apples to oranges. Also, the internal lookup structure won't work if you try
+to group by type.
+.IP "\(bu" 4
+There must be at least one unspecified, ungrouped field. Otherwise nothing
+will be aggregated.
+.PP
+As you can see in the example above, each aggregation has its own
+\&\fBAggregation\fR block. You can have multiple aggregation blocks and aggregation
+blocks may match the same values, i.e. one value list can update multiple
+aggregations. The following options are valid inside \fBAggregation\fR blocks:
+.IP "\fBHost\fR \fIHost\fR" 4
+.IX Item "Host Host"
+.PD 0
+.IP "\fBPlugin\fR \fIPlugin\fR" 4
+.IX Item "Plugin Plugin"
+.IP "\fBPluginInstance\fR \fIPluginInstance\fR" 4
+.IX Item "PluginInstance PluginInstance"
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+.IP "\fBTypeInstance\fR \fITypeInstance\fR" 4
+.IX Item "TypeInstance TypeInstance"
+.PD
+Selects the value lists to be added to this aggregation. \fBType\fR must be a
+valid data set name, see \fItypes.db\fR\|(5) for details.
+.Sp
+If the string starts with and ends with a slash (\f(CW\*(C`/\*(C'\fR), the string is
+interpreted as a \fIregular expression\fR. The regex flavor used are \s-1POSIX\s0
+extended regular expressions as described in \fIregex\fR\|(7). Example usage:
+.Sp
+.Vb 1
+\& Host "/^db[0\-9]\e\e.example\e\e.com$/"
+.Ve
+.IP "\fBGroupBy\fR \fBHost\fR|\fBPlugin\fR|\fBPluginInstance\fR|\fBTypeInstance\fR" 4
+.IX Item "GroupBy Host|Plugin|PluginInstance|TypeInstance"
+Group valued by the specified field. The \fBGroupBy\fR option may be repeated to
+group by multiple fields.
+.IP "\fBSetHost\fR \fIHost\fR" 4
+.IX Item "SetHost Host"
+.PD 0
+.IP "\fBSetPlugin\fR \fIPlugin\fR" 4
+.IX Item "SetPlugin Plugin"
+.IP "\fBSetPluginInstance\fR \fIPluginInstance\fR" 4
+.IX Item "SetPluginInstance PluginInstance"
+.IP "\fBSetTypeInstance\fR \fITypeInstance\fR" 4
+.IX Item "SetTypeInstance TypeInstance"
+.PD
+Sets the appropriate part of the identifier to the provided string.
+.Sp
+The \fIPluginInstance\fR should include the placeholder \f(CW\*(C`%{aggregation}\*(C'\fR which
+will be replaced with the aggregation function, e.g. \*(L"average\*(R". Not including
+the placeholder will result in duplication warnings and/or messed up values if
+more than one aggregation function are enabled.
+.Sp
+The following example calculates the average usage of all \*(L"even\*(R" CPUs:
+.Sp
+.Vb 5
+\& <Plugin "aggregation">
+\&   <Aggregation>
+\&     Plugin "cpu"
+\&     PluginInstance "/[0,2,4,6,8]$/"
+\&     Type "cpu"
+\&
+\&     SetPlugin "cpu"
+\&     SetPluginInstance "even\-%{aggregation}"
+\&
+\&     GroupBy "Host"
+\&     GroupBy "TypeInstance"
+\&
+\&     CalculateAverage true
+\&   </Aggregation>
+\& </Plugin>
+.Ve
+.Sp
+This will create the files:
+.RS 4
+.IP "\(bu" 4
+foo.example.com/cpu\-even\-average/cpu\-idle
+.IP "\(bu" 4
+foo.example.com/cpu\-even\-average/cpu\-system
+.IP "\(bu" 4
+foo.example.com/cpu\-even\-average/cpu\-user
+.IP "\(bu" 4
+\&...
+.RE
+.RS 4
+.RE
+.IP "\fBCalculateNum\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CalculateNum true|false"
+.PD 0
+.IP "\fBCalculateSum\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CalculateSum true|false"
+.IP "\fBCalculateAverage\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CalculateAverage true|false"
+.IP "\fBCalculateMinimum\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CalculateMinimum true|false"
+.IP "\fBCalculateMaximum\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CalculateMaximum true|false"
+.IP "\fBCalculateStddev\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CalculateStddev true|false"
+.PD
+Boolean options for enabling calculation of the number of value lists, their
+sum, average, minimum, maximum and\ / or standard deviation. All options
+are disabled by default.
+.ie n .SS "Plugin ""amqp"""
+.el .SS "Plugin \f(CWamqp\fP"
+.IX Subsection "Plugin amqp"
+The \fI\s-1AMQMP\s0 plugin\fR can be used to communicate with other instances of
+\&\fIcollectd\fR or third party applications using an \s-1AMQP\s0 message broker. Values
+are sent to or received from the broker, which handles routing, queueing and
+possibly filtering or messages.
+.PP
+.Vb 10
+\& <Plugin "amqp">
+\&   # Send values to an AMQP broker
+\&   <Publish "some_name">
+\&     Host "localhost"
+\&     Port "5672"
+\&     VHost "/"
+\&     User "guest"
+\&     Password "guest"
+\&     Exchange "amq.fanout"
+\& #   ExchangeType "fanout"
+\& #   RoutingKey "collectd"
+\& #   Persistent false
+\& #   ConnectionRetryDelay 0
+\& #   Format "command"
+\& #   StoreRates false
+\& #   GraphitePrefix "collectd."
+\& #   GraphiteEscapeChar "_"
+\& #   GraphiteSeparateInstances false
+\& #   GraphiteAlwaysAppendDS false
+\&   </Publish>
+\&
+\&   # Receive values from an AMQP broker
+\&   <Subscribe "some_name">
+\&     Host "localhost"
+\&     Port "5672"
+\&     VHost "/"
+\&     User "guest"
+\&     Password "guest"
+\&     Exchange "amq.fanout"
+\& #   ExchangeType "fanout"
+\& #   Queue "queue_name"
+\& #   QueueDurable false
+\& #   QueueAutoDelete true
+\& #   RoutingKey "collectd.#"
+\& #   ConnectionRetryDelay 0
+\&   </Subscribe>
+\& </Plugin>
+.Ve
+.PP
+The plugin's configuration consists of a number of \fIPublish\fR and \fISubscribe\fR
+blocks, which configure sending and receiving of values respectively. The two
+blocks are very similar, so unless otherwise noted, an option can be used in
+either block. The name given in the blocks starting tag is only used for
+reporting messages, but may be used to support \fIflushing\fR of certain
+\&\fIPublish\fR blocks in the future.
+.IP "\fBHost\fR \fIHost\fR" 4
+.IX Item "Host Host"
+Hostname or IP-address of the \s-1AMQP\s0 broker. Defaults to the default behavior of
+the underlying communications library, \fIrabbitmq-c\fR, which is \*(L"localhost\*(R".
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+Service name or port number on which the \s-1AMQP\s0 broker accepts connections. This
+argument must be a string, even if the numeric form is used. Defaults to
+\&\*(L"5672\*(R".
+.IP "\fBVHost\fR \fIVHost\fR" 4
+.IX Item "VHost VHost"
+Name of the \fIvirtual host\fR on the \s-1AMQP\s0 broker to use. Defaults to \*(L"/\*(R".
+.IP "\fBUser\fR \fIUser\fR" 4
+.IX Item "User User"
+.PD 0
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+.PD
+Credentials used to authenticate to the \s-1AMQP\s0 broker. By default \*(L"guest\*(R"/\*(L"guest\*(R"
+is used.
+.IP "\fBExchange\fR \fIExchange\fR" 4
+.IX Item "Exchange Exchange"
+In \fIPublish\fR blocks, this option specifies the \fIexchange\fR to send values to.
+By default, \*(L"amq.fanout\*(R" will be used.
+.Sp
+In \fISubscribe\fR blocks this option is optional. If given, a \fIbinding\fR between
+the given exchange and the \fIqueue\fR is created, using the \fIrouting key\fR if
+configured. See the \fBQueue\fR and \fBRoutingKey\fR options below.
+.IP "\fBExchangeType\fR \fIType\fR" 4
+.IX Item "ExchangeType Type"
+If given, the plugin will try to create the configured \fIexchange\fR with this
+\&\fItype\fR after connecting. When in a \fISubscribe\fR block, the \fIqueue\fR will then
+be bound to this exchange.
+.IP "\fBQueue\fR \fIQueue\fR (Subscribe only)" 4
+.IX Item "Queue Queue (Subscribe only)"
+Configures the \fIqueue\fR name to subscribe to. If no queue name was configured
+explicitly, a unique queue name will be created by the broker.
+.IP "\fBQueueDurable\fR \fBtrue\fR|\fBfalse\fR (Subscribe only)" 4
+.IX Item "QueueDurable true|false (Subscribe only)"
+Defines if the \fIqueue\fR subscribed to is durable (saved to persistent storage)
+or transient (will disappear if the \s-1AMQP\s0 broker is restarted). Defaults to
+\&\*(L"false\*(R".
+.Sp
+This option should be used in conjunction with the \fIPersistent\fR option on the
+publish side.
+.IP "\fBQueueAutoDelete\fR \fBtrue\fR|\fBfalse\fR (Subscribe only)" 4
+.IX Item "QueueAutoDelete true|false (Subscribe only)"
+Defines if the \fIqueue\fR subscribed to will be deleted once the last consumer
+unsubscribes. Defaults to \*(L"true\*(R".
+.IP "\fBRoutingKey\fR \fIKey\fR" 4
+.IX Item "RoutingKey Key"
+In \fIPublish\fR blocks, this configures the routing key to set on all outgoing
+messages. If not given, the routing key will be computed from the \fIidentifier\fR
+of the value. The host, plugin, type and the two instances are concatenated
+together using dots as the separator and all containing dots replaced with
+slashes. For example \*(L"collectd.host/example/com.cpu.0.cpu.user\*(R". This makes it
+possible to receive only specific values using a \*(L"topic\*(R" exchange.
+.Sp
+In \fISubscribe\fR blocks, configures the \fIrouting key\fR used when creating a
+\&\fIbinding\fR between an \fIexchange\fR and the \fIqueue\fR. The usual wildcards can be
+used to filter messages when using a \*(L"topic\*(R" exchange. If you're only
+interested in \s-1CPU\s0 statistics, you could use the routing key \*(L"collectd.*.cpu.#\*(R"
+for example.
+.IP "\fBPersistent\fR \fBtrue\fR|\fBfalse\fR (Publish only)" 4
+.IX Item "Persistent true|false (Publish only)"
+Selects the \fIdelivery method\fR to use. If set to \fBtrue\fR, the \fIpersistent\fR
+mode will be used, i.e. delivery is guaranteed. If set to \fBfalse\fR (the
+default), the \fItransient\fR delivery mode will be used, i.e. messages may be
+lost due to high load, overflowing queues or similar issues.
+.IP "\fBConnectionRetryDelay\fR \fIDelay\fR" 4
+.IX Item "ConnectionRetryDelay Delay"
+When the connection to the \s-1AMQP\s0 broker is lost, defines the time in seconds to
+wait before attempting to reconnect. Defaults to 0, which implies collectd will
+attempt to reconnect at each read interval (in Subscribe mode) or each time
+values are ready for submission (in Publish mode).
+.IP "\fBFormat\fR \fBCommand\fR|\fB\s-1JSON\s0\fR|\fBGraphite\fR (Publish only)" 4
+.IX Item "Format Command|JSON|Graphite (Publish only)"
+Selects the format in which messages are sent to the broker. If set to
+\&\fBCommand\fR (the default), values are sent as \f(CW\*(C`PUTVAL\*(C'\fR commands which are
+identical to the syntax used by the \fIExec\fR and \fIUnixSock plugins\fR. In this
+case, the \f(CW\*(C`Content\-Type\*(C'\fR header field will be set to \f(CW\*(C`text/collectd\*(C'\fR.
+.Sp
+If set to \fB\s-1JSON\s0\fR, the values are encoded in the \fIJavaScript Object Notation\fR,
+an easy and straight forward exchange format. The \f(CW\*(C`Content\-Type\*(C'\fR header field
+will be set to \f(CW\*(C`application/json\*(C'\fR.
+.Sp
+If set to \fBGraphite\fR, values are encoded in the \fIGraphite\fR format, which is
+\&\*(L"<metric> <value> <timestamp>\en\*(R". The \f(CW\*(C`Content\-Type\*(C'\fR header field will be set to
+\&\f(CW\*(C`text/graphite\*(C'\fR.
+.Sp
+A subscribing client \fIshould\fR use the \f(CW\*(C`Content\-Type\*(C'\fR header field to
+determine how to decode the values. Currently, the \fI\s-1AMQP\s0 plugin\fR itself can
+only decode the \fBCommand\fR format.
+.IP "\fBStoreRates\fR \fBtrue\fR|\fBfalse\fR (Publish only)" 4
+.IX Item "StoreRates true|false (Publish only)"
+Determines whether or not \f(CW\*(C`COUNTER\*(C'\fR, \f(CW\*(C`DERIVE\*(C'\fR and \f(CW\*(C`ABSOLUTE\*(C'\fR data sources
+are converted to a \fIrate\fR (i.e. a \f(CW\*(C`GAUGE\*(C'\fR value). If set to \fBfalse\fR (the
+default), no conversion is performed. Otherwise the conversion is performed
+using the internal value cache.
+.Sp
+Please note that currently this option is only used if the \fBFormat\fR option has
+been set to \fB\s-1JSON\s0\fR.
+.IP "\fBGraphitePrefix\fR (Publish and \fBFormat\fR=\fIGraphite\fR only)" 4
+.IX Item "GraphitePrefix (Publish and Format=Graphite only)"
+A prefix can be added in the metric name when outputting in the \fIGraphite\fR format.
+It's added before the \fIHost\fR name.
+Metric name will be \*(L"<prefix><host><postfix><plugin><type><name>\*(R"
+.IP "\fBGraphitePostfix\fR (Publish and \fBFormat\fR=\fIGraphite\fR only)" 4
+.IX Item "GraphitePostfix (Publish and Format=Graphite only)"
+A postfix can be added in the metric name when outputting in the \fIGraphite\fR format.
+It's added after the \fIHost\fR name.
+Metric name will be \*(L"<prefix><host><postfix><plugin><type><name>\*(R"
+.IP "\fBGraphiteEscapeChar\fR (Publish and \fBFormat\fR=\fIGraphite\fR only)" 4
+.IX Item "GraphiteEscapeChar (Publish and Format=Graphite only)"
+Specify a character to replace dots (.) in the host part of the metric name.
+In \fIGraphite\fR metric name, dots are used as separators between different
+metric parts (host, plugin, type).
+Default is \*(L"_\*(R" (\fIUnderscore\fR).
+.IP "\fBGraphiteSeparateInstances\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GraphiteSeparateInstances true|false"
+If set to \fBtrue\fR, the plugin instance and type instance will be in their own
+path component, for example \f(CW\*(C`host.cpu.0.cpu.idle\*(C'\fR. If set to \fBfalse\fR (the
+default), the plugin and plugin instance (and likewise the type and type
+instance) are put into one component, for example \f(CW\*(C`host.cpu\-0.cpu\-idle\*(C'\fR.
+.IP "\fBGraphiteAlwaysAppendDS\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GraphiteAlwaysAppendDS true|false"
+If set to \fBtrue\fR, append the name of the \fIData Source\fR (\s-1DS\s0) to the \*(L"metric\*(R"
+identifier. If set to \fBfalse\fR (the default), this is only done when there is
+more than one \s-1DS.\s0
+.ie n .SS "Plugin ""apache"""
+.el .SS "Plugin \f(CWapache\fP"
+.IX Subsection "Plugin apache"
+To configure the \f(CW\*(C`apache\*(C'\fR\-plugin you first need to configure the Apache
+webserver correctly. The Apache-plugin \f(CW\*(C`mod_status\*(C'\fR needs to be loaded and
+working and the \f(CW\*(C`ExtendedStatus\*(C'\fR directive needs to be \fBenabled\fR. You can use
+the following snipped to base your Apache config upon:
+.PP
+.Vb 6
+\&  ExtendedStatus on
+\&  <IfModule mod_status.c>
+\&    <Location /mod_status>
+\&      SetHandler server\-status
+\&    </Location>
+\&  </IfModule>
+.Ve
+.PP
+Since its \f(CW\*(C`mod_status\*(C'\fR module is very similar to Apache's, \fBlighttpd\fR is
+also supported. It introduces a new field, called \f(CW\*(C`BusyServers\*(C'\fR, to count the
+number of currently connected clients. This field is also supported.
+.PP
+The configuration of the \fIApache\fR plugin consists of one or more
+\&\f(CW\*(C`<Instance\ />\*(C'\fR blocks. Each block requires one string argument
+as the instance name. For example:
+.PP
+.Vb 8
+\& <Plugin "apache">
+\&   <Instance "www1">
+\&     URL "http://www1.example.com/mod_status?auto"
+\&   </Instance>
+\&   <Instance "www2">
+\&     URL "http://www2.example.com/mod_status?auto"
+\&   </Instance>
+\& </Plugin>
+.Ve
+.PP
+The instance name will be used as the \fIplugin instance\fR. To emulate the old
+(version\ 4) behavior, you can use an empty string (""). In order for the
+plugin to work correctly, each instance name must be unique. This is not
+enforced by the plugin and it is your responsibility to ensure it.
+.PP
+The following options are accepted within each \fIInstance\fR block:
+.IP "\fB\s-1URL\s0\fR \fIhttp://host/mod_status?auto\fR" 4
+.IX Item "URL http://host/mod_status?auto"
+Sets the \s-1URL\s0 of the \f(CW\*(C`mod_status\*(C'\fR output. This needs to be the output generated
+by \f(CW\*(C`ExtendedStatus on\*(C'\fR and it needs to be the machine readable output
+generated by appending the \f(CW\*(C`?auto\*(C'\fR argument. This option is \fImandatory\fR.
+.IP "\fBUser\fR \fIUsername\fR" 4
+.IX Item "User Username"
+Optional user name needed for authentication.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Optional password needed for authentication.
+.IP "\fBVerifyPeer\fR \fBtrue|false\fR" 4
+.IX Item "VerifyPeer true|false"
+Enable or disable peer \s-1SSL\s0 certificate verification. See
+<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+.IP "\fBVerifyHost\fR \fBtrue|false\fR" 4
+.IX Item "VerifyHost true|false"
+Enable or disable peer host name verification. If enabled, the plugin checks
+if the \f(CW\*(C`Common Name\*(C'\fR or a \f(CW\*(C`Subject Alternate Name\*(C'\fR field of the \s-1SSL\s0
+certificate matches the host name provided by the \fB\s-1URL\s0\fR option. If this
+identity check fails, the connection is aborted. Obviously, only works when
+connecting to a \s-1SSL\s0 enabled server. Enabled by default.
+.IP "\fBCACert\fR \fIFile\fR" 4
+.IX Item "CACert File"
+File that holds one or more \s-1SSL\s0 certificates. If you want to use \s-1HTTPS\s0 you will
+possibly need this option. What \s-1CA\s0 certificates come bundled with \f(CW\*(C`libcurl\*(C'\fR
+and are checked by default depends on the distribution you use.
+.IP "\fBSSLCiphers\fR \fIlist of ciphers\fR" 4
+.IX Item "SSLCiphers list of ciphers"
+Specifies which ciphers to use in the connection. The list of ciphers
+must specify valid ciphers. See
+<http://www.openssl.org/docs/apps/ciphers.html> for details.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+The \fBTimeout\fR option sets the overall timeout for \s-1HTTP\s0 requests to \fB\s-1URL\s0\fR, in
+milliseconds. By default, the configured \fBInterval\fR is used to set the
+timeout.
+.ie n .SS "Plugin ""apcups"""
+.el .SS "Plugin \f(CWapcups\fP"
+.IX Subsection "Plugin apcups"
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+Hostname of the host running \fBapcupsd\fR. Defaults to \fBlocalhost\fR. Please note
+that IPv6 support has been disabled unless someone can confirm or decline that
+\&\fBapcupsd\fR can handle it.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+TCP-Port to connect to. Defaults to \fB3551\fR.
+.IP "\fBReportSeconds\fR \fBtrue|false\fR" 4
+.IX Item "ReportSeconds true|false"
+If set to \fBtrue\fR, the time reported in the \f(CW\*(C`timeleft\*(C'\fR metric will be
+converted to seconds. This is the recommended setting. If set to \fBfalse\fR, the
+default for backwards compatibility, the time will be reported in minutes.
+.ie n .SS "Plugin ""aquaero"""
+.el .SS "Plugin \f(CWaquaero\fP"
+.IX Subsection "Plugin aquaero"
+This plugin collects the value of the available sensors in an
+\&\fIAquaero\ 5\fR board. Aquaero\ 5 is a water-cooling controller board,
+manufactured by Aqua Computer GmbH <http://www.aquacomputer.de/>, with a \s-1USB2\s0
+connection for monitoring and configuration. The board can handle multiple
+temperature sensors, fans, water pumps and water level sensors and adjust the
+output settings such as fan voltage or power used by the water pump based on
+the available inputs using a configurable controller included in the board.
+This plugin collects all the available inputs as well as some of the output
+values chosen by this controller. The plugin is based on the \fIlibaquaero5\fR
+library provided by \fIaquatools-ng\fR.
+.IP "\fBDevice\fR \fIDevicePath\fR" 4
+.IX Item "Device DevicePath"
+Device path of the Aquaero\ 5's \s-1USB HID \s0(human interface device), usually
+in the form \f(CW\*(C`/dev/usb/hiddevX\*(C'\fR. If this option is no set the plugin will try
+to auto-detect the Aquaero 5 \s-1USB\s0 device based on vendor-ID and product-ID.
+.ie n .SS "Plugin ""ascent"""
+.el .SS "Plugin \f(CWascent\fP"
+.IX Subsection "Plugin ascent"
+This plugin collects information about an Ascent server, a free server for the
+\&\*(L"World of Warcraft\*(R" game. This plugin gathers the information by fetching the
+\&\s-1XML\s0 status page using \f(CW\*(C`libcurl\*(C'\fR and parses it using \f(CW\*(C`libxml2\*(C'\fR.
+.PP
+The configuration options are the same as for the \f(CW\*(C`apache\*(C'\fR plugin above:
+.IP "\fB\s-1URL\s0\fR \fIhttp://localhost/ascent/status/\fR" 4
+.IX Item "URL http://localhost/ascent/status/"
+Sets the \s-1URL\s0 of the \s-1XML\s0 status output.
+.IP "\fBUser\fR \fIUsername\fR" 4
+.IX Item "User Username"
+Optional user name needed for authentication.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Optional password needed for authentication.
+.IP "\fBVerifyPeer\fR \fBtrue|false\fR" 4
+.IX Item "VerifyPeer true|false"
+Enable or disable peer \s-1SSL\s0 certificate verification. See
+<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+.IP "\fBVerifyHost\fR \fBtrue|false\fR" 4
+.IX Item "VerifyHost true|false"
+Enable or disable peer host name verification. If enabled, the plugin checks
+if the \f(CW\*(C`Common Name\*(C'\fR or a \f(CW\*(C`Subject Alternate Name\*(C'\fR field of the \s-1SSL\s0
+certificate matches the host name provided by the \fB\s-1URL\s0\fR option. If this
+identity check fails, the connection is aborted. Obviously, only works when
+connecting to a \s-1SSL\s0 enabled server. Enabled by default.
+.IP "\fBCACert\fR \fIFile\fR" 4
+.IX Item "CACert File"
+File that holds one or more \s-1SSL\s0 certificates. If you want to use \s-1HTTPS\s0 you will
+possibly need this option. What \s-1CA\s0 certificates come bundled with \f(CW\*(C`libcurl\*(C'\fR
+and are checked by default depends on the distribution you use.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+The \fBTimeout\fR option sets the overall timeout for \s-1HTTP\s0 requests to \fB\s-1URL\s0\fR, in
+milliseconds. By default, the configured \fBInterval\fR is used to set the
+timeout.
+.ie n .SS "Plugin ""barometer"""
+.el .SS "Plugin \f(CWbarometer\fP"
+.IX Subsection "Plugin barometer"
+This plugin reads absolute air pressure using digital barometer sensor on a I2C
+bus. Supported sensors are:
+.IP "\fI\s-1MPL115A2\s0\fR from Freescale, see <http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL115A>." 5
+.IX Item "MPL115A2 from Freescale, see <http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL115A>."
+.PD 0
+.IP "\fI\s-1MPL3115\s0\fR from Freescale see <http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL3115A2>." 5
+.IX Item "MPL3115 from Freescale see <http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL3115A2>."
+.IP "\fI\s-1BMP085\s0\fR from Bosch Sensortec" 5
+.IX Item "BMP085 from Bosch Sensortec"
+.PD
+.PP
+The sensor type \- one of the above \- is detected automatically by the plugin
+and indicated in the plugin_instance (you will see subdirectory
+\&\*(L"barometer\-mpl115\*(R" or \*(L"barometer\-mpl3115\*(R", or \*(L"barometer\-bmp085\*(R"). The order of
+detection is \s-1BMP085 \-\s0> \s-1MPL3115 \-\s0> \s-1MPL115A2,\s0 the first one found will be used
+(only one sensor can be used by the plugin).
+.PP
+The plugin provides absolute barometric pressure, air pressure reduced to sea
+level (several possible approximations) and as an auxiliary value also internal
+sensor temperature. It uses (expects/provides) typical metric units \- pressure
+in [hPa], temperature in [C], altitude in [m].
+.PP
+It was developed and tested under Linux only. The only platform dependency is
+the standard Linux i2c\-dev interface (the particular bus driver has to
+support the \s-1SM\s0 Bus command subset).
+.PP
+The reduction or normalization to mean sea level pressure requires (depending
+on selected method/approximation) also altitude and reference to temperature
+sensor(s).  When multiple temperature sensors are configured the minumum of
+their values is always used (expecting that the warmer ones are affected by
+e.g. direct sun light at that moment).
+.PP
+Synopsis:
+.PP
+.Vb 9
+\&  <Plugin "barometer">
+\&     Device            "/dev/i2c\-0";
+\&     Oversampling      512
+\&     PressureOffset    0.0
+\&     TemperatureOffset 0.0
+\&     Normalization     2
+\&     Altitude          238.0
+\&     TemperatureSensor "myserver/onewire\-F10FCA000800/temperature"
+\&  </Plugin>
+.Ve
+.IP "\fBDevice\fR \fIdevice\fR" 4
+.IX Item "Device device"
+The only mandatory configuration parameter.
+.Sp
+Device name of the I2C bus to which the sensor is connected. Note that
+typically you need to have loaded the i2c\-dev module.
+Using i2c\-tools you can check/list i2c buses available on your system by:
+.Sp
+.Vb 1
+\&  i2cdetect \-l
+.Ve
+.Sp
+Then you can scan for devices on given bus. E.g. to scan the whole bus 0 use:
+.Sp
+.Vb 1
+\&  i2cdetect \-y \-a 0
+.Ve
+.Sp
+This way you should be able to verify that the pressure sensor (either type) is
+connected and detected on address 0x60.
+.IP "\fBOversampling\fR \fIvalue\fR" 4
+.IX Item "Oversampling value"
+Optional parameter controlling the oversampling/accuracy. Default value
+is 1 providing fastest and least accurate reading.
+.Sp
+For \fI\s-1MPL115\s0\fR this is the size of the averaging window. To filter out sensor
+noise a simple averaging using floating window of this configurable size is
+used. The plugin will use average of the last \f(CW\*(C`value\*(C'\fR measurements (value of 1
+means no averaging).  Minimal size is 1, maximal 1024.
+.Sp
+For \fI\s-1MPL3115\s0\fR this is the oversampling value. The actual oversampling is
+performed by the sensor and the higher value the higher accuracy and longer
+conversion time (although nothing to worry about in the collectd context).
+Supported values are: 1, 2, 4, 8, 16, 32, 64 and 128. Any other value is
+adjusted by the plugin to the closest supported one.
+.Sp
+For \fI\s-1BMP085\s0\fR this is the oversampling value. The actual oversampling is
+performed by the sensor and the higher value the higher accuracy and longer
+conversion time (although nothing to worry about in the collectd context).
+Supported values are: 1, 2, 4, 8. Any other value is adjusted by the plugin to
+the closest supported one.
+.IP "\fBPressureOffset\fR \fIoffset\fR" 4
+.IX Item "PressureOffset offset"
+Optional parameter for \s-1MPL3115\s0 only.
+.Sp
+You can further calibrate the sensor by supplying pressure and/or temperature
+offsets.  This is added to the measured/caclulated value (i.e. if the measured
+value is too high then use negative offset).
+In hPa, default is 0.0.
+.IP "\fBTemperatureOffset\fR \fIoffset\fR" 4
+.IX Item "TemperatureOffset offset"
+Optional parameter for \s-1MPL3115\s0 only.
+.Sp
+You can further calibrate the sensor by supplying pressure and/or temperature
+offsets.  This is added to the measured/caclulated value (i.e. if the measured
+value is too high then use negative offset).
+In C, default is 0.0.
+.IP "\fBNormalization\fR \fImethod\fR" 4
+.IX Item "Normalization method"
+Optional parameter, default value is 0.
+.Sp
+Normalization method \- what approximation/model is used to compute the mean sea
+level pressure from the air absolute pressure.
+.Sp
+Supported values of the \f(CW\*(C`method\*(C'\fR (integer between from 0 to 2) are:
+.RS 4
+.ie n .IP "\fB0\fR \- no conversion, absolute pressure is simply copied over. For this method you do not need to configure ""Altitude"" or ""TemperatureSensor""." 5
+.el .IP "\fB0\fR \- no conversion, absolute pressure is simply copied over. For this method you do not need to configure \f(CWAltitude\fR or \f(CWTemperatureSensor\fR." 5
+.IX Item "0 - no conversion, absolute pressure is simply copied over. For this method you do not need to configure Altitude or TemperatureSensor."
+.PD 0
+.ie n .IP "\fB1\fR \- international formula for conversion , See <http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation>. For this method you have to configure ""Altitude"" but do not need ""TemperatureSensor"" (uses fixed global temperature average instead)." 5
+.el .IP "\fB1\fR \- international formula for conversion , See <http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation>. For this method you have to configure \f(CWAltitude\fR but do not need \f(CWTemperatureSensor\fR (uses fixed global temperature average instead)." 5
+.IX Item "1 - international formula for conversion , See <http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation>. For this method you have to configure Altitude but do not need TemperatureSensor (uses fixed global temperature average instead)."
+.ie n .IP "\fB2\fR \- formula as recommended by the Deutsche Wetterdienst (German Meteorological Service). See <http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie> For this method you have to configure both  ""Altitude"" and ""TemperatureSensor""." 5
+.el .IP "\fB2\fR \- formula as recommended by the Deutsche Wetterdienst (German Meteorological Service). See <http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie> For this method you have to configure both  \f(CWAltitude\fR and \f(CWTemperatureSensor\fR." 5
+.IX Item "2 - formula as recommended by the Deutsche Wetterdienst (German Meteorological Service). See <http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie> For this method you have to configure both Altitude and TemperatureSensor."
+.RE
+.RS 4
+.RE
+.IP "\fBAltitude\fR \fIaltitude\fR" 4
+.IX Item "Altitude altitude"
+.PD
+The altitude (in meters) of the location where you meassure the pressure.
+.IP "\fBTemperatureSensor\fR \fIreference\fR" 4
+.IX Item "TemperatureSensor reference"
+Temperature sensor(s) which should be used as a reference when normalizing the
+pressure using \f(CW\*(C`Normalization\*(C'\fR method 2.
+When specified more sensors a minumum is found and used each time.  The
+temperature reading directly from this pressure sensor/plugin is typically not
+suitable as the pressure sensor will be probably inside while we want outside
+temperature.  The collectd reference name is something like
+<hostname>/<plugin_name>\-<plugin_instance>/<type>\-<type_instance>
+(<type_instance> is usually omitted when there is just single value type). Or
+you can figure it out from the path of the output data files.
+.ie n .SS "Plugin ""battery"""
+.el .SS "Plugin \f(CWbattery\fP"
+.IX Subsection "Plugin battery"
+The \fIbattery plugin\fR reports the remaining capacity, power and voltage of
+laptop batteries.
+.IP "\fBValuesPercentage\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ValuesPercentage false|true"
+When enabled, remaining capacity is reported as a percentage, e.g. \*(L"42%
+capacity remaining\*(R". Otherwise the capacity is stored as reported by the
+battery, most likely in \*(L"Wh\*(R". This option does not work with all input methods,
+in particular when only \f(CW\*(C`/proc/pmu\*(C'\fR is available on an old Linux system.
+Defaults to \fBfalse\fR.
+.IP "\fBReportDegraded\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ReportDegraded false|true"
+Typical laptop batteries degrade over time, meaning the capacity decreases with
+recharge cycles. The maximum charge of the previous charge cycle is tracked as
+\&\*(L"last full capacity\*(R" and used to determine that a battery is \*(L"fully charged\*(R".
+.Sp
+When this option is set to \fBfalse\fR, the default, the \fIbattery plugin\fR will
+only report the remaining capacity. If the \fBValuesPercentage\fR option is
+enabled, the relative remaining capacity is calculated as the ratio of the
+\&\*(L"remaining capacity\*(R" and the \*(L"last full capacity\*(R". This is what most tools,
+such as the status bar of desktop environments, also do.
+.Sp
+When set to \fBtrue\fR, the battery plugin will report three values: \fBcharged\fR
+(remaining capacity), \fBdischarged\fR (difference between \*(L"last full capacity\*(R"
+and \*(L"remaining capacity\*(R") and \fBdegraded\fR (difference between \*(L"design capacity\*(R"
+and \*(L"last full capacity\*(R").
+.ie n .SS "Plugin ""bind"""
+.el .SS "Plugin \f(CWbind\fP"
+.IX Subsection "Plugin bind"
+Starting with \s-1BIND 9.5.0,\s0 the most widely used \s-1DNS\s0 server software provides
+extensive statistics about queries, responses and lots of other information.
+The bind plugin retrieves this information that's encoded in \s-1XML\s0 and provided
+via \s-1HTTP\s0 and submits the values to collectd.
+.PP
+To use this plugin, you first need to tell \s-1BIND\s0 to make this information
+available. This is done with the \f(CW\*(C`statistics\-channels\*(C'\fR configuration option:
+.PP
+.Vb 3
+\& statistics\-channels {
+\&   inet localhost port 8053;
+\& };
+.Ve
+.PP
+The configuration follows the grouping that can be seen when looking at the
+data with an \s-1XSLT\s0 compatible viewer, such as a modern web browser. It's
+probably a good idea to make yourself familiar with the provided values, so you
+can understand what the collected statistics actually mean.
+.PP
+Synopsis:
+.PP
+.Vb 5
+\& <Plugin "bind">
+\&   URL "http://localhost:8053/"
+\&   ParseTime       false
+\&   OpCodes         true
+\&   QTypes          true
+\&
+\&   ServerStats     true
+\&   ZoneMaintStats  true
+\&   ResolverStats   false
+\&   MemoryStats     true
+\&
+\&   <View "_default">
+\&     QTypes        true
+\&     ResolverStats true
+\&     CacheRRSets   true
+\&
+\&     Zone "127.in\-addr.arpa/IN"
+\&   </View>
+\& </Plugin>
+.Ve
+.PP
+The bind plugin accepts the following configuration options:
+.IP "\fB\s-1URL\s0\fR \fI\s-1URL\s0\fR" 4
+.IX Item "URL URL"
+\&\s-1URL\s0 from which to retrieve the \s-1XML\s0 data. If not specified,
+\&\f(CW\*(C`http://localhost:8053/\*(C'\fR will be used.
+.IP "\fBParseTime\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ParseTime true|false"
+When set to \fBtrue\fR, the time provided by \s-1BIND\s0 will be parsed and used to
+dispatch the values. When set to \fBfalse\fR, the local time source is queried.
+.Sp
+This setting is set to \fBtrue\fR by default for backwards compatibility; setting
+this to \fBfalse\fR is \fIrecommended\fR to avoid problems with timezones and
+localization.
+.IP "\fBOpCodes\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "OpCodes true|false"
+When enabled, statistics about the \fI\*(L"OpCodes\*(R"\fR, for example the number of
+\&\f(CW\*(C`QUERY\*(C'\fR packets, are collected.
+.Sp
+Default: Enabled.
+.IP "\fBQTypes\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "QTypes true|false"
+When enabled, the number of \fIincoming\fR queries by query types (for example
+\&\f(CW\*(C`A\*(C'\fR, \f(CW\*(C`MX\*(C'\fR, \f(CW\*(C`AAAA\*(C'\fR) is collected.
+.Sp
+Default: Enabled.
+.IP "\fBServerStats\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ServerStats true|false"
+Collect global server statistics, such as requests received over IPv4 and IPv6,
+successful queries, and failed updates.
+.Sp
+Default: Enabled.
+.IP "\fBZoneMaintStats\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ZoneMaintStats true|false"
+Collect zone maintenance statistics, mostly information about notifications
+(zone updates) and zone transfers.
+.Sp
+Default: Enabled.
+.IP "\fBResolverStats\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ResolverStats true|false"
+Collect resolver statistics, i.\ e. statistics about outgoing requests
+(e.\ g. queries over IPv4, lame servers). Since the global resolver
+counters apparently were removed in \s-1BIND 9.5.1\s0 and 9.6.0, this is disabled by
+default. Use the \fBResolverStats\fR option within a \fBView \*(L"_default\*(R"\fR block
+instead for the same functionality.
+.Sp
+Default: Disabled.
+.IP "\fBMemoryStats\fR" 4
+.IX Item "MemoryStats"
+Collect global memory statistics.
+.Sp
+Default: Enabled.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+The \fBTimeout\fR option sets the overall timeout for \s-1HTTP\s0 requests to \fB\s-1URL\s0\fR, in
+milliseconds. By default, the configured \fBInterval\fR is used to set the
+timeout.
+.IP "\fBView\fR \fIName\fR" 4
+.IX Item "View Name"
+Collect statistics about a specific \fI\*(L"view\*(R"\fR. \s-1BIND\s0 can behave different,
+mostly depending on the source IP-address of the request. These different
+configurations are called \*(L"views\*(R". If you don't use this feature, you most
+likely are only interested in the \f(CW\*(C`_default\*(C'\fR view.
+.Sp
+Within a <\fBView\fR\ \fIname\fR> block, you can specify which
+information you want to collect about a view. If no \fBView\fR block is
+configured, no detailed view statistics will be collected.
+.RS 4
+.IP "\fBQTypes\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "QTypes true|false"
+If enabled, the number of \fIoutgoing\fR queries by query type (e.\ g. \f(CW\*(C`A\*(C'\fR,
+\&\f(CW\*(C`MX\*(C'\fR) is collected.
+.Sp
+Default: Enabled.
+.IP "\fBResolverStats\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ResolverStats true|false"
+Collect resolver statistics, i.\ e. statistics about outgoing requests
+(e.\ g. queries over IPv4, lame servers).
+.Sp
+Default: Enabled.
+.IP "\fBCacheRRSets\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CacheRRSets true|false"
+If enabled, the number of entries (\fI\*(L"\s-1RR\s0 sets\*(R"\fR) in the view's cache by query
+type is collected. Negative entries (queries which resulted in an error, for
+example names that do not exist) are reported with a leading exclamation mark,
+e.\ g. \*(L"!A\*(R".
+.Sp
+Default: Enabled.
+.IP "\fBZone\fR \fIName\fR" 4
+.IX Item "Zone Name"
+When given, collect detailed information about the given zone in the view. The
+information collected if very similar to the global \fBServerStats\fR information
+(see above).
+.Sp
+You can repeat this option to collect detailed information about multiple
+zones.
+.Sp
+By default no detailed zone information is collected.
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""ceph"""
+.el .SS "Plugin \f(CWceph\fP"
+.IX Subsection "Plugin ceph"
+The ceph plugin collects values from \s-1JSON\s0 data to be parsed by \fBlibyajl\fR
+(<https://lloyd.github.io/yajl/>) retrieved from ceph daemon admin sockets.
+.PP
+A separate \fBDaemon\fR block must be configured for each ceph daemon to be
+monitored. The following example will read daemon statistics from four
+separate ceph daemons running on the same device (two OSDs, one \s-1MON,\s0 one \s-1MDS\s0) :
+.PP
+.Vb 10
+\&  <Plugin ceph>
+\&    LongRunAvgLatency false
+\&    ConvertSpecialMetricTypes true
+\&    <Daemon "osd.0">
+\&      SocketPath "/var/run/ceph/ceph\-osd.0.asok"
+\&    </Daemon>
+\&    <Daemon "osd.1">
+\&      SocketPath "/var/run/ceph/ceph\-osd.1.asok"
+\&    </Daemon>
+\&    <Daemon "mon.a">
+\&      SocketPath "/var/run/ceph/ceph\-mon.ceph1.asok"
+\&    </Daemon>
+\&    <Daemon "mds.a">
+\&      SocketPath "/var/run/ceph/ceph\-mds.ceph1.asok"
+\&    </Daemon>
+\&  </Plugin>
+.Ve
+.PP
+The ceph plugin accepts the following configuration options:
+.IP "\fBLongRunAvgLatency\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "LongRunAvgLatency true|false"
+If enabled, latency values(sum,count pairs) are calculated as the long run
+average \- average since the ceph daemon was started = (sum / count).
+When disabled, latency values are calculated as the average since the last
+collection = (sum_now \- sum_last) / (count_now \- count_last).
+.Sp
+Default: Disabled
+.IP "\fBConvertSpecialMetricTypes\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ConvertSpecialMetricTypes true|false"
+If enabled, special metrics (metrics that differ in type from similar counters)
+are converted to the type of those similar counters. This currently only
+applies to filestore.journal_wr_bytes which is a counter for \s-1OSD\s0 daemons. The
+ceph schema reports this metric type as a sum,count pair while similar counters
+are treated as derive types. When converted, the sum is used as the counter
+value and is treated as a derive type.
+When disabled, all metrics are treated as the types received from the ceph schema.
+.Sp
+Default: Enabled
+.PP
+Each \fBDaemon\fR block must have a string argument for the plugin instance name.
+A \fBSocketPath\fR is also required for each \fBDaemon\fR block:
+.IP "\fBDaemon\fR \fIDaemonName\fR" 4
+.IX Item "Daemon DaemonName"
+Name to be used as the instance name for this daemon.
+.IP "\fBSocketPath\fR \fISocketPath\fR" 4
+.IX Item "SocketPath SocketPath"
+Specifies the path to the \s-1UNIX\s0 admin socket of the ceph daemon.
+.ie n .SS "Plugin ""cgroups"""
+.el .SS "Plugin \f(CWcgroups\fP"
+.IX Subsection "Plugin cgroups"
+This plugin collects the \s-1CPU\s0 user/system time for each \fIcgroup\fR by reading the
+\&\fIcpuacct.stat\fR files in the first cpuacct-mountpoint (typically
+\&\fI/sys/fs/cgroup/cpu.cpuacct\fR on machines using systemd).
+.IP "\fBCGroup\fR \fIDirectory\fR" 4
+.IX Item "CGroup Directory"
+Select \fIcgroup\fR based on the name. Whether only matching \fIcgroups\fR are
+collected or if they are ignored is controlled by the \fBIgnoreSelected\fR option;
+see below.
+.IP "\fBIgnoreSelected\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+Invert the selection: If set to true, all cgroups \fIexcept\fR the ones that
+match any one of the criteria are collected. By default only selected
+cgroups are collected if a selection is made. If no selection is configured
+at all, \fBall\fR cgroups are selected.
+.ie n .SS "Plugin ""conntrack"""
+.el .SS "Plugin \f(CWconntrack\fP"
+.IX Subsection "Plugin conntrack"
+This plugin collects \s-1IP\s0 conntrack statistics.
+.IP "\fBOldFiles\fR" 4
+.IX Item "OldFiles"
+Assume the \fBconntrack_count\fR and \fBconntrack_max\fR files to be found in
+\&\fI/proc/sys/net/ipv4/netfilter\fR instead of \fI/proc/sys/net/netfilter/\fR.
+.ie n .SS "Plugin ""cpu"""
+.el .SS "Plugin \f(CWcpu\fP"
+.IX Subsection "Plugin cpu"
+The \fI\s-1CPU\s0 plugin\fR collects \s-1CPU\s0 usage metrics. By default, \s-1CPU\s0 usage is reported
+as Jiffies, using the \f(CW\*(C`cpu\*(C'\fR type. Two aggregations are available:
+.IP "\(bu" 4
+Sum, per-state, over all CPUs installed in the system; and
+.IP "\(bu" 4
+Sum, per-CPU, over all non-idle states of a \s-1CPU,\s0 creating an \*(L"active\*(R" state.
+.PP
+The two aggregations can be combined, leading to \fIcollectd\fR only emitting a
+single \*(L"active\*(R" metric for the entire system. As soon as one of these
+aggregations (or both) is enabled, the \fIcpu plugin\fR will report a percentage,
+rather than Jiffies. In addition, you can request individual, per-state,
+per-CPU metrics to be reported as percentage.
+.PP
+The following configuration options are available:
+.IP "\fBReportByState\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ReportByState true|false"
+When set to \fBtrue\fR, the default, reports per-state metrics, e.g. \*(L"system\*(R",
+\&\*(L"user\*(R" and \*(L"idle\*(R".
+When set to \fBfalse\fR, aggregates (sums) all \fInon-idle\fR states into one
+\&\*(L"active\*(R" metric.
+.IP "\fBReportByCpu\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ReportByCpu true|false"
+When set to \fBtrue\fR, the default, reports per-CPU (per-core) metrics.
+When set to \fBfalse\fR, instead of reporting metrics for individual CPUs, only a
+global sum of \s-1CPU\s0 states is emitted.
+.IP "\fBValuesPercentage\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ValuesPercentage false|true"
+This option is only considered when both, \fBReportByCpu\fR and \fBReportByState\fR
+are set to \fBtrue\fR. In this case, by default, metrics will be reported as
+Jiffies. By setting this option to \fBtrue\fR, you can request percentage values
+in the un-aggregated (per-CPU, per-state) mode as well.
+.ie n .SS "Plugin ""cpufreq"""
+.el .SS "Plugin \f(CWcpufreq\fP"
+.IX Subsection "Plugin cpufreq"
+This plugin doesn't have any options. It reads
+\&\fI/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq\fR (for the first \s-1CPU\s0
+installed) to get the current \s-1CPU\s0 frequency. If this file does not exist make
+sure \fBcpufreqd\fR (<http://cpufreqd.sourceforge.net/>) or a similar tool is
+installed and an \*(L"cpu governor\*(R" (that's a kernel module) is loaded.
+.ie n .SS "Plugin ""csv"""
+.el .SS "Plugin \f(CWcsv\fP"
+.IX Subsection "Plugin csv"
+.IP "\fBDataDir\fR \fIDirectory\fR" 4
+.IX Item "DataDir Directory"
+Set the directory to store CSV-files under. Per default CSV-files are generated
+beneath the daemon's working directory, i.\ e. the \fBBaseDir\fR.
+The special strings \fBstdout\fR and \fBstderr\fR can be used to write to the standard
+output and standard error channels, respectively. This, of course, only makes
+much sense when collectd is running in foreground\- or non-daemon-mode.
+.IP "\fBStoreRates\fR \fBtrue|false\fR" 4
+.IX Item "StoreRates true|false"
+If set to \fBtrue\fR, convert counter values to rates. If set to \fBfalse\fR (the
+default) counter values are stored as is, i.\ e. as an increasing integer
+number.
+.ie n .SS "Plugin ""curl"""
+.el .SS "Plugin \f(CWcurl\fP"
+.IX Subsection "Plugin curl"
+The curl plugin uses the \fBlibcurl\fR (<http://curl.haxx.se/>) to read web pages
+and the match infrastructure (the same code used by the tail plugin) to use
+regular expressions with the received data.
+.PP
+The following example will read the current value of \s-1AMD\s0 stock from Google's
+finance page and dispatch the value to collectd.
+.PP
+.Vb 11
+\&  <Plugin curl>
+\&    <Page "stock_quotes">
+\&      URL "http://finance.google.com/finance?q=NYSE%3AAMD"
+\&      User "foo"
+\&      Password "bar"
+\&      Digest false
+\&      VerifyPeer true
+\&      VerifyHost true
+\&      CACert "/path/to/ca.crt"
+\&      Header "X\-Custom\-Header: foobar"
+\&      Post "foo=bar"
+\&
+\&      MeasureResponseTime false
+\&      MeasureResponseCode false
+\&
+\&      <Match>
+\&        Regex "<span +class=\e"pr\e"[^>]*> *([0\-9]*\e\e.[0\-9]+) *</span>"
+\&        DSType "GaugeAverage"
+\&        # Note: \`stock_value\*(Aq is not a standard type.
+\&        Type "stock_value"
+\&        Instance "AMD"
+\&      </Match>
+\&    </Page>
+\&  </Plugin>
+.Ve
+.PP
+In the \fBPlugin\fR block, there may be one or more \fBPage\fR blocks, each defining
+a web page and one or more \*(L"matches\*(R" to be performed on the returned data. The
+string argument to the \fBPage\fR block is used as plugin instance.
+.PP
+The following options are valid within \fBPage\fR blocks:
+.IP "\fB\s-1URL\s0\fR \fI\s-1URL\s0\fR" 4
+.IX Item "URL URL"
+\&\s-1URL\s0 of the web site to retrieve. Since a regular expression will be used to
+extract information from this data, non-binary data is a big plus here ;)
+.IP "\fBUser\fR \fIName\fR" 4
+.IX Item "User Name"
+Username to use if authorization is required to read the page.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Password to use if authorization is required to read the page.
+.IP "\fBDigest\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Digest true|false"
+Enable \s-1HTTP\s0 digest authentication.
+.IP "\fBVerifyPeer\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "VerifyPeer true|false"
+Enable or disable peer \s-1SSL\s0 certificate verification. See
+<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+.IP "\fBVerifyHost\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "VerifyHost true|false"
+Enable or disable peer host name verification. If enabled, the plugin checks if
+the \f(CW\*(C`Common Name\*(C'\fR or a \f(CW\*(C`Subject Alternate Name\*(C'\fR field of the \s-1SSL\s0 certificate
+matches the host name provided by the \fB\s-1URL\s0\fR option. If this identity check
+fails, the connection is aborted. Obviously, only works when connecting to a
+\&\s-1SSL\s0 enabled server. Enabled by default.
+.IP "\fBCACert\fR \fIfile\fR" 4
+.IX Item "CACert file"
+File that holds one or more \s-1SSL\s0 certificates. If you want to use \s-1HTTPS\s0 you will
+possibly need this option. What \s-1CA\s0 certificates come bundled with \f(CW\*(C`libcurl\*(C'\fR
+and are checked by default depends on the distribution you use.
+.IP "\fBHeader\fR \fIHeader\fR" 4
+.IX Item "Header Header"
+A \s-1HTTP\s0 header to add to the request. Multiple headers are added if this option
+is specified more than once.
+.IP "\fBPost\fR \fIBody\fR" 4
+.IX Item "Post Body"
+Specifies that the \s-1HTTP\s0 operation should be a \s-1POST\s0 instead of a \s-1GET.\s0 The
+complete data to be posted is given as the argument.  This option will usually
+need to be accompanied by a \fBHeader\fR option to set an appropriate
+\&\f(CW\*(C`Content\-Type\*(C'\fR for the post body (e.g. to
+\&\f(CW\*(C`application/x\-www\-form\-urlencoded\*(C'\fR).
+.IP "\fBMeasureResponseTime\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "MeasureResponseTime true|false"
+Measure response time for the request. If this setting is enabled, \fBMatch\fR
+blocks (see below) are optional. Disabled by default.
+.Sp
+Beware that requests will get aborted if they take too long to complete. Adjust
+\&\fBTimeout\fR accordingly if you expect \fBMeasureResponseTime\fR to report such slow
+requests.
+.IP "\fBMeasureResponseCode\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "MeasureResponseCode true|false"
+Measure response code for the request. If this setting is enabled, \fBMatch\fR
+blocks (see below) are optional. Disabled by default.
+.IP "\fB<Match>\fR" 4
+.IX Item "<Match>"
+One or more \fBMatch\fR blocks that define how to match information in the data
+returned by \f(CW\*(C`libcurl\*(C'\fR. The \f(CW\*(C`curl\*(C'\fR plugin uses the same infrastructure that's
+used by the \f(CW\*(C`tail\*(C'\fR plugin, so please see the documentation of the \f(CW\*(C`tail\*(C'\fR
+plugin below on how matches are defined. If the \fBMeasureResponseTime\fR or
+\&\fBMeasureResponseCode\fR options are set to \fBtrue\fR, \fBMatch\fR blocks are
+optional.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+The \fBTimeout\fR option sets the overall timeout for \s-1HTTP\s0 requests to \fB\s-1URL\s0\fR, in
+milliseconds. By default, the configured \fBInterval\fR is used to set the
+timeout. Prior to version 5.5.0, there was no timeout and requests could hang
+indefinitely. This legacy behaviour can be achieved by setting the value of
+\&\fBTimeout\fR to 0.
+.Sp
+If \fBTimeout\fR is 0 or bigger than the \fBInterval\fR, keep in mind that each slow
+network connection will stall one read thread. Adjust the \fBReadThreads\fR global
+setting accordingly to prevent this from blocking other plugins.
+.ie n .SS "Plugin ""curl_json"""
+.el .SS "Plugin \f(CWcurl_json\fP"
+.IX Subsection "Plugin curl_json"
+The \fBcurl_json plugin\fR collects values from \s-1JSON\s0 data to be parsed by
+\&\fBlibyajl\fR (<http://www.lloydforge.org/projects/yajl/>) retrieved via
+either \fBlibcurl\fR (<http://curl.haxx.se/>) or read directly from a
+unix socket. The former can be used, for example, to collect values
+from CouchDB documents (which are stored \s-1JSON\s0 notation), and the
+latter to collect values from a uWSGI stats socket.
+.PP
+The following example will collect several values from the built-in
+\&\f(CW\*(C`_stats\*(C'\fR runtime statistics module of \fICouchDB\fR
+(<http://wiki.apache.org/couchdb/Runtime_Statistics>).
+.PP
+.Vb 6
+\&  <Plugin curl_json>
+\&    <URL "http://localhost:5984/_stats">
+\&      Instance "httpd"
+\&      <Key "httpd/requests/count">
+\&        Type "http_requests"
+\&      </Key>
+\&
+\&      <Key "httpd_request_methods/*/count">
+\&        Type "http_request_methods"
+\&      </Key>
+\&
+\&      <Key "httpd_status_codes/*/count">
+\&        Type "http_response_codes"
+\&      </Key>
+\&    </URL>
+\&  </Plugin>
+.Ve
+.PP
+This example will collect data directly from a \fIuWSGI\fR \*(L"Stats Server\*(R" socket.
+.PP
+.Vb 6
+\&  <Plugin curl_json>
+\&    <Sock "/var/run/uwsgi.stats.sock">
+\&      Instance "uwsgi"
+\&      <Key "workers/*/requests">
+\&        Type "http_requests"
+\&      </Key>
+\&
+\&      <Key "workers/*/apps/*/requests">
+\&        Type "http_requests"
+\&      </Key>
+\&    </Sock>
+\&  </Plugin>
+.Ve
+.PP
+In the \fBPlugin\fR block, there may be one or more \fB\s-1URL\s0\fR blocks, each
+defining a \s-1URL\s0 to be fetched via \s-1HTTP \s0(using libcurl) or \fBSock\fR
+blocks defining a unix socket to read \s-1JSON\s0 from directly.  Each of
+these blocks may have one or more \fBKey\fR blocks.
+.PP
+The \fBKey\fR string argument must be in a path format. Each component is
+used to match the key from a \s-1JSON\s0 map or the index of an \s-1JSON\s0
+array. If a path component of a \fBKey\fR is a \fI*\fR\ wildcard, the
+values for all map keys or array indices will be collectd.
+.PP
+The following options are valid within \fB\s-1URL\s0\fR blocks:
+.IP "\fBInstance\fR \fIInstance\fR" 4
+.IX Item "Instance Instance"
+Sets the plugin instance to \fIInstance\fR.
+.IP "\fBInterval\fR \fIInterval\fR" 4
+.IX Item "Interval Interval"
+Sets the interval (in seconds) in which the values will be collected from this
+\&\s-1URL.\s0 By default the global \fBInterval\fR setting will be used.
+.IP "\fBUser\fR \fIName\fR" 4
+.IX Item "User Name"
+.PD 0
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+.IP "\fBDigest\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Digest true|false"
+.IP "\fBVerifyPeer\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "VerifyPeer true|false"
+.IP "\fBVerifyHost\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "VerifyHost true|false"
+.IP "\fBCACert\fR \fIfile\fR" 4
+.IX Item "CACert file"
+.IP "\fBHeader\fR \fIHeader\fR" 4
+.IX Item "Header Header"
+.IP "\fBPost\fR \fIBody\fR" 4
+.IX Item "Post Body"
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+.PD
+These options behave exactly equivalent to the appropriate options of the
+\&\fIcURL\fR plugin. Please see there for a detailed description.
+.PP
+The following options are valid within \fBKey\fR blocks:
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+Sets the type used to dispatch the values to the daemon. Detailed information
+about types and their configuration can be found in \fItypes.db\fR\|(5). This
+option is mandatory.
+.IP "\fBInstance\fR \fIInstance\fR" 4
+.IX Item "Instance Instance"
+Type-instance to use. Defaults to the current map key or current string array element value.
+.ie n .SS "Plugin ""curl_xml"""
+.el .SS "Plugin \f(CWcurl_xml\fP"
+.IX Subsection "Plugin curl_xml"
+The \fBcurl_xml plugin\fR uses \fBlibcurl\fR (<http://curl.haxx.se/>) and \fBlibxml2\fR
+(<http://xmlsoft.org/>) to retrieve \s-1XML\s0 data via cURL.
+.PP
+.Vb 11
+\& <Plugin "curl_xml">
+\&   <URL "http://localhost/stats.xml">
+\&     Host "my_host"
+\&     Instance "some_instance"
+\&     User "collectd"
+\&     Password "thaiNg0I"
+\&     VerifyPeer true
+\&     VerifyHost true
+\&     CACert "/path/to/ca.crt"
+\&     Header "X\-Custom\-Header: foobar"
+\&     Post "foo=bar"
+\&
+\&     <XPath "table[@id=\e"magic_level\e"]/tr">
+\&       Type "magic_level"
+\&       #InstancePrefix "prefix\-"
+\&       InstanceFrom "td[1]"
+\&       ValuesFrom "td[2]/span[@class=\e"level\e"]"
+\&     </XPath>
+\&   </URL>
+\& </Plugin>
+.Ve
+.PP
+In the \fBPlugin\fR block, there may be one or more \fB\s-1URL\s0\fR blocks, each defining a
+\&\s-1URL\s0 to be fetched using libcurl. Within each \fB\s-1URL\s0\fR block there are
+options which specify the connection parameters, for example authentication
+information, and one or more \fBXPath\fR blocks.
+.PP
+Each \fBXPath\fR block specifies how to get one type of information. The
+string argument must be a valid XPath expression which returns a list
+of \*(L"base elements\*(R". One value is dispatched for each \*(L"base element\*(R". The
+\&\fItype instance\fR and values are looked up using further \fIXPath\fR expressions
+that should be relative to the base element.
+.PP
+Within the \fB\s-1URL\s0\fR block the following options are accepted:
+.IP "\fBHost\fR \fIName\fR" 4
+.IX Item "Host Name"
+Use \fIName\fR as the host name when submitting values. Defaults to the global
+host name setting.
+.IP "\fBInstance\fR \fIInstance\fR" 4
+.IX Item "Instance Instance"
+Use \fIInstance\fR as the plugin instance when submitting values. Defaults to an
+empty string (no plugin instance).
+.IP "\fBNamespace\fR \fIPrefix\fR \fI\s-1URL\s0\fR" 4
+.IX Item "Namespace Prefix URL"
+If an XPath expression references namespaces, they must be specified
+with this option. \fIPrefix\fR is the \*(L"namespace prefix\*(R" used in the \s-1XML\s0 document.
+\&\fI\s-1URL\s0\fR is the \*(L"namespace name\*(R", an \s-1URI\s0 reference uniquely identifying the
+namespace. The option can be repeated to register multiple namespaces.
+.Sp
+Examples:
+.Sp
+.Vb 2
+\&  Namespace "s" "http://schemas.xmlsoap.org/soap/envelope/"
+\&  Namespace "m" "http://www.w3.org/1998/Math/MathML"
+.Ve
+.IP "\fBUser\fR \fIUser\fR" 4
+.IX Item "User User"
+.PD 0
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+.IP "\fBDigest\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Digest true|false"
+.IP "\fBVerifyPeer\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "VerifyPeer true|false"
+.IP "\fBVerifyHost\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "VerifyHost true|false"
+.IP "\fBCACert\fR \fI\s-1CA\s0 Cert File\fR" 4
+.IX Item "CACert CA Cert File"
+.IP "\fBHeader\fR \fIHeader\fR" 4
+.IX Item "Header Header"
+.IP "\fBPost\fR \fIBody\fR" 4
+.IX Item "Post Body"
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+.PD
+These options behave exactly equivalent to the appropriate options of the
+\&\fIcURL plugin\fR. Please see there for a detailed description.
+.IP "<\fBXPath\fR \fIXPath-expression\fR>" 4
+.IX Item "<XPath XPath-expression>"
+Within each \fB\s-1URL\s0\fR block, there must be one or more \fBXPath\fR blocks. Each
+\&\fBXPath\fR block specifies how to get one type of information. The string
+argument must be a valid XPath expression which returns a list of \*(L"base
+elements\*(R". One value is dispatched for each \*(L"base element\*(R".
+.Sp
+Within the \fBXPath\fR block the following options are accepted:
+.RS 4
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+Specifies the \fIType\fR used for submitting patches. This determines the number
+of values that are required / expected and whether the strings are parsed as
+signed or unsigned integer or as double values. See \fItypes.db\fR\|(5) for details.
+This option is required.
+.IP "\fBInstancePrefix\fR \fIInstancePrefix\fR" 4
+.IX Item "InstancePrefix InstancePrefix"
+Prefix the \fItype instance\fR with \fIInstancePrefix\fR. The values are simply
+concatenated together without any separator.
+This option is optional.
+.IP "\fBInstanceFrom\fR \fIInstanceFrom\fR" 4
+.IX Item "InstanceFrom InstanceFrom"
+Specifies a XPath expression to use for determining the \fItype instance\fR. The
+XPath expression must return exactly one element. The element's value is then
+used as \fItype instance\fR, possibly prefixed with \fIInstancePrefix\fR (see above).
+.Sp
+This value is required. As a special exception, if the \*(L"base XPath expression\*(R"
+(the argument to the \fBXPath\fR block) returns exactly one argument, then this
+option may be omitted.
+.IP "\fBValuesFrom\fR \fIValuesFrom\fR [\fIValuesFrom\fR ...]" 4
+.IX Item "ValuesFrom ValuesFrom [ValuesFrom ...]"
+Specifies one or more XPath expression to use for reading the values. The
+number of XPath expressions must match the number of data sources in the
+\&\fItype\fR specified with \fBType\fR (see above). Each XPath expression must return
+exactly one element. The element's value is then parsed as a number and used as
+value for the appropriate value in the value list dispatched to the daemon.
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""dbi"""
+.el .SS "Plugin \f(CWdbi\fP"
+.IX Subsection "Plugin dbi"
+This plugin uses the \fBdbi\fR library (<http://libdbi.sourceforge.net/>) to
+connect to various databases, execute \fI\s-1SQL\s0\fR statements and read back the
+results. \fIdbi\fR is an acronym for \*(L"database interface\*(R" in case you were
+wondering about the name. You can configure how each column is to be
+interpreted and the plugin will generate one or more data sets from each row
+returned according to these rules.
+.PP
+Because the plugin is very generic, the configuration is a little more complex
+than those of other plugins. It usually looks something like this:
+.PP
+.Vb 10
+\&  <Plugin dbi>
+\&    <Query "out_of_stock">
+\&      Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category"
+\&      # Use with MySQL 5.0.0 or later
+\&      MinVersion 50000
+\&      <Result>
+\&        Type "gauge"
+\&        InstancePrefix "out_of_stock"
+\&        InstancesFrom "category"
+\&        ValuesFrom "value"
+\&      </Result>
+\&    </Query>
+\&    <Database "product_information">
+\&      Driver "mysql"
+\&      DriverOption "host" "localhost"
+\&      DriverOption "username" "collectd"
+\&      DriverOption "password" "aZo6daiw"
+\&      DriverOption "dbname" "prod_info"
+\&      SelectDB "prod_info"
+\&      Query "out_of_stock"
+\&    </Database>
+\&  </Plugin>
+.Ve
+.PP
+The configuration above defines one query with one result and one database. The
+query is then linked to the database with the \fBQuery\fR option \fIwithin\fR the
+\&\fB<Database>\fR block. You can have any number of queries and databases
+and you can also use the \fBInclude\fR statement to split up the configuration
+file in multiple, smaller files. However, the \fB<Query>\fR block \fImust\fR
+precede the \fB<Database>\fR blocks, because the file is interpreted from
+top to bottom!
+.PP
+The following is a complete list of options:
+.PP
+\fI\f(BIQuery\fI blocks\fR
+.IX Subsection "Query blocks"
+.PP
+Query blocks define \fI\s-1SQL\s0\fR statements and how the returned data should be
+interpreted. They are identified by the name that is given in the opening line
+of the block. Thus the name needs to be unique. Other than that, the name is
+not used in collectd.
+.PP
+In each \fBQuery\fR block, there is one or more \fBResult\fR blocks. \fBResult\fR blocks
+define which column holds which value or instance information. You can use
+multiple \fBResult\fR blocks to create multiple values from one returned row. This
+is especially useful, when queries take a long time and sending almost the same
+query again and again is not desirable.
+.PP
+Example:
+.PP
+.Vb 10
+\&  <Query "environment">
+\&    Statement "select station, temperature, humidity from environment"
+\&    <Result>
+\&      Type "temperature"
+\&      # InstancePrefix "foo"
+\&      InstancesFrom "station"
+\&      ValuesFrom "temperature"
+\&    </Result>
+\&    <Result>
+\&      Type "humidity"
+\&      InstancesFrom "station"
+\&      ValuesFrom "humidity"
+\&    </Result>
+\&  </Query>
+.Ve
+.PP
+The following options are accepted:
+.IP "\fBStatement\fR \fI\s-1SQL\s0\fR" 4
+.IX Item "Statement SQL"
+Sets the statement that should be executed on the server. This is \fBnot\fR
+interpreted by collectd, but simply passed to the database server. Therefore,
+the \s-1SQL\s0 dialect that's used depends on the server collectd is connected to.
+.Sp
+The query has to return at least two columns, one for the instance and one
+value. You cannot omit the instance, even if the statement is guaranteed to
+always return exactly one line. In that case, you can usually specify something
+like this:
+.Sp
+.Vb 1
+\&  Statement "SELECT \e"instance\e", COUNT(*) AS value FROM table"
+.Ve
+.Sp
+(That works with MySQL but may not be valid \s-1SQL\s0 according to the spec. If you
+use a more strict database server, you may have to select from a dummy table or
+something.)
+.Sp
+Please note that some databases, for example \fBOracle\fR, will fail if you
+include a semicolon at the end of the statement.
+.IP "\fBMinVersion\fR \fIVersion\fR" 4
+.IX Item "MinVersion Version"
+.PD 0
+.IP "\fBMaxVersion\fR \fIValue\fR" 4
+.IX Item "MaxVersion Value"
+.PD
+Only use this query for the specified database version. You can use these
+options to provide multiple queries with the same name but with a slightly
+different syntax. The plugin will use only those queries, where the specified
+minimum and maximum versions fit the version of the database in use.
+.Sp
+The database version is determined by \f(CW\*(C`dbi_conn_get_engine_version\*(C'\fR, see the
+libdbi documentation <http://libdbi.sourceforge.net/docs/programmers-guide/reference-conn.html#DBI-CONN-GET-ENGINE-VERSION>
+for details. Basically, each part of the version is assumed to be in the range
+from \fB00\fR to \fB99\fR and all dots are removed. So version \*(L"4.1.2\*(R" becomes
+\&\*(L"40102\*(R", version \*(L"5.0.42\*(R" becomes \*(L"50042\*(R".
+.Sp
+\&\fBWarning:\fR The plugin will use \fBall\fR matching queries, so if you specify
+multiple queries with the same name and \fBoverlapping\fR ranges, weird stuff will
+happen. Don't to it! A valid example would be something along these lines:
+.Sp
+.Vb 8
+\&  MinVersion 40000
+\&  MaxVersion 49999
+\&  ...
+\&  MinVersion 50000
+\&  MaxVersion 50099
+\&  ...
+\&  MinVersion 50100
+\&  # No maximum
+.Ve
+.Sp
+In the above example, there are three ranges that don't overlap. The last one
+goes from version \*(L"5.1.0\*(R" to infinity, meaning \*(L"all later versions\*(R". Versions
+before \*(L"4.0.0\*(R" are not specified.
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+The \fBtype\fR that's used for each line returned. See \fItypes.db\fR\|(5) for more
+details on how types are defined. In short: A type is a predefined layout of
+data and the number of values and type of values has to match the type
+definition.
+.Sp
+If you specify \*(L"temperature\*(R" here, you need exactly one gauge column. If you
+specify \*(L"if_octets\*(R", you will need two counter columns. See the \fBValuesFrom\fR
+setting below.
+.Sp
+There must be exactly one \fBType\fR option inside each \fBResult\fR block.
+.IP "\fBInstancePrefix\fR \fIprefix\fR" 4
+.IX Item "InstancePrefix prefix"
+Prepends \fIprefix\fR to the type instance. If \fBInstancesFrom\fR (see below) is not
+given, the string is simply copied. If \fBInstancesFrom\fR is given, \fIprefix\fR and
+all strings returned in the appropriate columns are concatenated together,
+separated by dashes \fI(\*(L"\-\*(R")\fR.
+.IP "\fBInstancesFrom\fR \fIcolumn0\fR [\fIcolumn1\fR ...]" 4
+.IX Item "InstancesFrom column0 [column1 ...]"
+Specifies the columns whose values will be used to create the \*(L"type-instance\*(R"
+for each row. If you specify more than one column, the value of all columns
+will be joined together with dashes \fI(\*(L"\-\*(R")\fR as separation characters.
+.Sp
+The plugin itself does not check whether or not all built instances are
+different. It's your responsibility to assure that each is unique. This is
+especially true, if you do not specify \fBInstancesFrom\fR: \fBYou\fR have to make
+sure that only one row is returned in this case.
+.Sp
+If neither \fBInstancePrefix\fR nor \fBInstancesFrom\fR is given, the type-instance
+will be empty.
+.IP "\fBValuesFrom\fR \fIcolumn0\fR [\fIcolumn1\fR ...]" 4
+.IX Item "ValuesFrom column0 [column1 ...]"
+Names the columns whose content is used as the actual data for the data sets
+that are dispatched to the daemon. How many such columns you need is determined
+by the \fBType\fR setting above. If you specify too many or not enough columns,
+the plugin will complain about that and no data will be submitted to the
+daemon.
+.Sp
+The actual data type in the columns is not that important. The plugin will
+automatically cast the values to the right type if it know how to do that. So
+it should be able to handle integer an floating point types, as well as strings
+(if they include a number at the beginning).
+.Sp
+There must be at least one \fBValuesFrom\fR option inside each \fBResult\fR block.
+.IP "\fBMetadataFrom\fR [\fIcolumn0\fR \fIcolumn1\fR ...]" 4
+.IX Item "MetadataFrom [column0 column1 ...]"
+Names the columns whose content is used as metadata for the data sets
+that are dispatched to the daemon.
+.Sp
+The actual data type in the columns is not that important. The plugin will
+automatically cast the values to the right type if it know how to do that. So
+it should be able to handle integer an floating point types, as well as strings
+(if they include a number at the beginning).
+.PP
+\fI\f(BIDatabase\fI blocks\fR
+.IX Subsection "Database blocks"
+.PP
+Database blocks define a connection to a database and which queries should be
+sent to that database. Since the used \*(L"dbi\*(R" library can handle a wide variety
+of databases, the configuration is very generic. If in doubt, refer to libdbi's
+documentation\ \- we stick as close to the terminology used there.
+.PP
+Each database needs a \*(L"name\*(R" as string argument in the starting tag of the
+block. This name will be used as \*(L"PluginInstance\*(R" in the values submitted to
+the daemon. Other than that, that name is not used.
+.IP "\fBDriver\fR \fIDriver\fR" 4
+.IX Item "Driver Driver"
+Specifies the driver to use to connect to the database. In many cases those
+drivers are named after the database they can connect to, but this is not a
+technical necessity. These drivers are sometimes referred to as \*(L"\s-1DBD\*(R",
+\&\s0\fBD\fRata\fBB\fRase \fBD\fRriver, and some distributions ship them in separate
+packages. Drivers for the \*(L"dbi\*(R" library are developed by the \fBlibdbi-drivers\fR
+project at <http://libdbi\-drivers.sourceforge.net/>.
+.Sp
+You need to give the driver name as expected by the \*(L"dbi\*(R" library here. You
+should be able to find that in the documentation for each driver. If you
+mistype the driver name, the plugin will dump a list of all known driver names
+to the log.
+.IP "\fBDriverOption\fR \fIKey\fR \fIValue\fR" 4
+.IX Item "DriverOption Key Value"
+Sets driver-specific options. What option a driver supports can be found in the
+documentation for each driver, somewhere at
+<http://libdbi\-drivers.sourceforge.net/>. However, the options \*(L"host\*(R",
+\&\*(L"username\*(R", \*(L"password\*(R", and \*(L"dbname\*(R" seem to be de\ facto standards.
+.Sp
+DBDs can register two types of options: String options and numeric options. The
+plugin will use the \f(CW\*(C`dbi_conn_set_option\*(C'\fR function when the configuration
+provides a string and the \f(CW\*(C`dbi_conn_require_option_numeric\*(C'\fR function when the
+configuration provides a number. So these two lines will actually result in
+different calls being used:
+.Sp
+.Vb 2
+\&  DriverOption "Port" 1234      # numeric
+\&  DriverOption "Port" "1234"    # string
+.Ve
+.Sp
+Unfortunately, drivers are not too keen to report errors when an unknown option
+is passed to them, so invalid settings here may go unnoticed. This is not the
+plugin's fault, it will report errors if it gets them from the library\ /
+the driver. If a driver complains about an option, the plugin will dump a
+complete list of all options understood by that driver to the log. There is no
+way to programatically find out if an option expects a string or a numeric
+argument, so you will have to refer to the appropriate \s-1DBD\s0's documentation to
+find this out. Sorry.
+.IP "\fBSelectDB\fR \fIDatabase\fR" 4
+.IX Item "SelectDB Database"
+In some cases, the database name you connect with is not the database name you
+want to use for querying data. If this option is set, the plugin will \*(L"select\*(R"
+(switch to) that database after the connection is established.
+.IP "\fBQuery\fR \fIQueryName\fR" 4
+.IX Item "Query QueryName"
+Associates the query named \fIQueryName\fR with this database connection. The
+query needs to be defined \fIbefore\fR this statement, i.\ e. all query
+blocks you want to refer to must be placed above the database block you want to
+refer to them from.
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+Sets the \fBhost\fR field of \fIvalue lists\fR to \fIHostname\fR when dispatching
+values. Defaults to the global hostname setting.
+.ie n .SS "Plugin ""df"""
+.el .SS "Plugin \f(CWdf\fP"
+.IX Subsection "Plugin df"
+.IP "\fBDevice\fR \fIDevice\fR" 4
+.IX Item "Device Device"
+Select partitions based on the devicename.
+.IP "\fBMountPoint\fR \fIDirectory\fR" 4
+.IX Item "MountPoint Directory"
+Select partitions based on the mountpoint.
+.IP "\fBFSType\fR \fIFSType\fR" 4
+.IX Item "FSType FSType"
+Select partitions based on the filesystem type.
+.IP "\fBIgnoreSelected\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+Invert the selection: If set to true, all partitions \fBexcept\fR the ones that
+match any one of the criteria are collected. By default only selected
+partitions are collected if a selection is made. If no selection is configured
+at all, \fBall\fR partitions are selected.
+.IP "\fBReportByDevice\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ReportByDevice true|false"
+Report using the device name rather than the mountpoint. i.e. with this \fIfalse\fR,
+(the default), it will report a disk as \*(L"root\*(R", but with it \fItrue\fR, it will be
+\&\*(L"sda1\*(R" (or whichever).
+.IP "\fBReportInodes\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ReportInodes true|false"
+Enables or disables reporting of free, reserved and used inodes. Defaults to
+inode collection being disabled.
+.Sp
+Enable this option if inodes are a scarce resource for you, usually because
+many small files are stored on the disk. This is a usual scenario for mail
+transfer agents and web caches.
+.IP "\fBValuesAbsolute\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ValuesAbsolute true|false"
+Enables or disables reporting of free and used disk space in 1K\-blocks.
+Defaults to \fBtrue\fR.
+.IP "\fBValuesPercentage\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ValuesPercentage false|true"
+Enables or disables reporting of free and used disk space in percentage.
+Defaults to \fBfalse\fR.
+.Sp
+This is useful for deploying \fIcollectd\fR on the cloud, where machines with
+different disk size may exist. Then it is more practical to configure
+thresholds based on relative disk size.
+.ie n .SS "Plugin ""disk"""
+.el .SS "Plugin \f(CWdisk\fP"
+.IX Subsection "Plugin disk"
+The \f(CW\*(C`disk\*(C'\fR plugin collects information about the usage of physical disks and
+logical disks (partitions). Values collected are the number of octets written
+to and read from a disk or partition, the number of read/write operations
+issued to the disk and a rather complex \*(L"time\*(R" it took for these commands to be
+issued.
+.PP
+Using the following two options you can ignore some disks or configure the
+collection only of specific disks.
+.IP "\fBDisk\fR \fIName\fR" 4
+.IX Item "Disk Name"
+Select the disk \fIName\fR. Whether it is collected or ignored depends on the
+\&\fBIgnoreSelected\fR setting, see below. As with other plugins that use the
+daemon's ignorelist functionality, a string that starts and ends with a slash
+is interpreted as a regular expression. Examples:
+.Sp
+.Vb 2
+\&  Disk "sdd"
+\&  Disk "/hda[34]/"
+.Ve
+.IP "\fBIgnoreSelected\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+Sets whether selected disks, i.\ e. the ones matches by any of the \fBDisk\fR
+statements, are ignored or if all other disks are ignored. The behavior
+(hopefully) is intuitive: If no \fBDisk\fR option is configured, all disks are
+collected. If at least one \fBDisk\fR option is given and no \fBIgnoreSelected\fR or
+set to \fBfalse\fR, \fBonly\fR matching disks will be collected. If \fBIgnoreSelected\fR
+is set to \fBtrue\fR, all disks are collected \fBexcept\fR the ones matched.
+.IP "\fBUseBSDName\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "UseBSDName true|false"
+Whether to use the device's \*(L"\s-1BSD\s0 Name\*(R", on Mac\ \s-1OS\s0\ X, instead of the
+default major/minor numbers. Requires collectd to be built with Apple's
+IOKitLib support.
+.IP "\fBUdevNameAttr\fR \fIAttribute\fR" 4
+.IX Item "UdevNameAttr Attribute"
+Attempt to override disk instance name with the value of a specified udev
+attribute when built with \fBlibudev\fR.  If the attribute is not defined for the
+given device, the default name is used. Example:
+.Sp
+.Vb 1
+\&  UdevNameAttr "DM_NAME"
+.Ve
+.ie n .SS "Plugin ""dns"""
+.el .SS "Plugin \f(CWdns\fP"
+.IX Subsection "Plugin dns"
+.IP "\fBInterface\fR \fIInterface\fR" 4
+.IX Item "Interface Interface"
+The dns plugin uses \fBlibpcap\fR to capture dns traffic and analyzes it. This
+option sets the interface that should be used. If this option is not set, or
+set to \*(L"any\*(R", the plugin will try to get packets from \fBall\fR interfaces. This
+may not work on certain platforms, such as Mac\ \s-1OS\s0\ X.
+.IP "\fBIgnoreSource\fR \fIIP-address\fR" 4
+.IX Item "IgnoreSource IP-address"
+Ignore packets that originate from this address.
+.IP "\fBSelectNumericQueryTypes\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "SelectNumericQueryTypes true|false"
+Enabled by default, collects unknown (and thus presented as numeric only) query types.
+.ie n .SS "Plugin ""email"""
+.el .SS "Plugin \f(CWemail\fP"
+.IX Subsection "Plugin email"
+.IP "\fBSocketFile\fR \fIPath\fR" 4
+.IX Item "SocketFile Path"
+Sets the socket-file which is to be created.
+.IP "\fBSocketGroup\fR \fIGroup\fR" 4
+.IX Item "SocketGroup Group"
+If running as root change the group of the UNIX-socket after it has been
+created. Defaults to \fBcollectd\fR.
+.IP "\fBSocketPerms\fR \fIPermissions\fR" 4
+.IX Item "SocketPerms Permissions"
+Change the file permissions of the UNIX-socket after it has been created. The
+permissions must be given as a numeric, octal value as you would pass to
+\&\fIchmod\fR\|(1). Defaults to \fB0770\fR.
+.IP "\fBMaxConns\fR \fINumber\fR" 4
+.IX Item "MaxConns Number"
+Sets the maximum number of connections that can be handled in parallel. Since
+this many threads will be started immediately setting this to a very high
+value will waste valuable resources. Defaults to \fB5\fR and will be forced to be
+at most \fB16384\fR to prevent typos and dumb mistakes.
+.ie n .SS "Plugin ""ethstat"""
+.el .SS "Plugin \f(CWethstat\fP"
+.IX Subsection "Plugin ethstat"
+The \fIethstat plugin\fR collects information about network interface cards (NICs)
+by talking directly with the underlying kernel driver using \fIioctl\fR\|(2).
+.PP
+\&\fBSynopsis:\fR
+.PP
+.Vb 5
+\& <Plugin "ethstat">
+\&   Interface "eth0"
+\&   Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
+\&   Map "multicast" "if_multicast"
+\& </Plugin>
+.Ve
+.PP
+\&\fBOptions:\fR
+.IP "\fBInterface\fR \fIName\fR" 4
+.IX Item "Interface Name"
+Collect statistical information about interface \fIName\fR.
+.IP "\fBMap\fR \fIName\fR \fIType\fR [\fITypeInstance\fR]" 4
+.IX Item "Map Name Type [TypeInstance]"
+By default, the plugin will submit values as type \f(CW\*(C`derive\*(C'\fR and \fItype
+instance\fR set to \fIName\fR, the name of the metric as reported by the driver. If
+an appropriate \fBMap\fR option exists, the given \fIType\fR and, optionally,
+\&\fITypeInstance\fR will be used.
+.IP "\fBMappedOnly\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "MappedOnly true|false"
+When set to \fBtrue\fR, only metrics that can be mapped to to a \fItype\fR will be
+collected, all other metrics will be ignored. Defaults to \fBfalse\fR.
+.ie n .SS "Plugin ""exec"""
+.el .SS "Plugin \f(CWexec\fP"
+.IX Subsection "Plugin exec"
+Please make sure to read \fIcollectd\-exec\fR\|(5) before using this plugin. It
+contains valuable information on when the executable is executed and the
+output that is expected from it.
+.IP "\fBExec\fR \fIUser\fR[:[\fIGroup\fR]] \fIExecutable\fR [\fI<arg>\fR [\fI<arg>\fR ...]]" 4
+.IX Item "Exec User[:[Group]] Executable [<arg> [<arg> ...]]"
+.PD 0
+.IP "\fBNotificationExec\fR \fIUser\fR[:[\fIGroup\fR]] \fIExecutable\fR [\fI<arg>\fR [\fI<arg>\fR ...]]" 4
+.IX Item "NotificationExec User[:[Group]] Executable [<arg> [<arg> ...]]"
+.PD
+Execute the executable \fIExecutable\fR as user \fIUser\fR. If the user name is
+followed by a colon and a group name, the effective group is set to that group.
+The real group and saved-set group will be set to the default group of that
+user. If no group is given the effective group \s-1ID\s0 will be the same as the real
+group \s-1ID.\s0
+.Sp
+Please note that in order to change the user and/or group the daemon needs
+superuser privileges. If the daemon is run as an unprivileged user you must
+specify the same user/group here. If the daemon is run with superuser
+privileges, you must supply a non-root user here.
+.Sp
+The executable may be followed by optional arguments that are passed to the
+program. Please note that due to the configuration parsing numbers and boolean
+values may be changed. If you want to be absolutely sure that something is
+passed as-is please enclose it in quotes.
+.Sp
+The \fBExec\fR and \fBNotificationExec\fR statements change the semantics of the
+programs executed, i.\ e. the data passed to them and the response
+expected from them. This is documented in great detail in \fIcollectd\-exec\fR\|(5).
+.ie n .SS "Plugin ""fhcount"""
+.el .SS "Plugin \f(CWfhcount\fP"
+.IX Subsection "Plugin fhcount"
+The \f(CW\*(C`fhcount\*(C'\fR plugin provides statistics about used, unused and total number of
+file handles.
+.PP
+The \fIfhcount plugin\fR provides the following configuration options:
+.IP "\fBValuesAbsolute\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ValuesAbsolute true|false"
+Enables or disables reporting of file handles usage in absolute numbers,
+e.g. file handles used. Defaults to \fBtrue\fR.
+.IP "\fBValuesPercentage\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ValuesPercentage false|true"
+Enables or disables reporting of file handles usage in percentages, e.g.
+percent of file handles used. Defaults to \fBfalse\fR.
+.ie n .SS "Plugin ""filecount"""
+.el .SS "Plugin \f(CWfilecount\fP"
+.IX Subsection "Plugin filecount"
+The \f(CW\*(C`filecount\*(C'\fR plugin counts the number of files in a certain directory (and
+its subdirectories) and their combined size. The configuration is very straight
+forward:
+.PP
+.Vb 12
+\&  <Plugin "filecount">
+\&    <Directory "/var/qmail/queue/mess">
+\&      Instance "qmail\-message"
+\&    </Directory>
+\&    <Directory "/var/qmail/queue/todo">
+\&      Instance "qmail\-todo"
+\&    </Directory>
+\&    <Directory "/var/lib/php5">
+\&      Instance "php5\-sessions"
+\&      Name "sess_*"
+\&    </Directory>
+\&  </Plugin>
+.Ve
+.PP
+The example above counts the number of files in QMail's queue directories and
+the number of \s-1PHP5\s0 sessions. Jfiy: The \*(L"todo\*(R" queue holds the messages that
+QMail has not yet looked at, the \*(L"message\*(R" queue holds the messages that were
+classified into \*(L"local\*(R" and \*(L"remote\*(R".
+.PP
+As you can see, the configuration consists of one or more \f(CW\*(C`Directory\*(C'\fR blocks,
+each of which specifies a directory in which to count the files. Within those
+blocks, the following options are recognized:
+.IP "\fBInstance\fR \fIInstance\fR" 4
+.IX Item "Instance Instance"
+Sets the plugin instance to \fIInstance\fR. That instance name must be unique, but
+it's your responsibility, the plugin doesn't check for that. If not given, the
+instance is set to the directory name with all slashes replaced by underscores
+and all leading underscores removed.
+.IP "\fBName\fR \fIPattern\fR" 4
+.IX Item "Name Pattern"
+Only count files that match \fIPattern\fR, where \fIPattern\fR is a shell-like
+wildcard as understood by \fIfnmatch\fR\|(3). Only the \fBfilename\fR is checked
+against the pattern, not the entire path. In case this makes it easier for you:
+This option has been named after the \fB\-name\fR parameter to \fIfind\fR\|(1).
+.IP "\fBMTime\fR \fIAge\fR" 4
+.IX Item "MTime Age"
+Count only files of a specific age: If \fIAge\fR is greater than zero, only files
+that haven't been touched in the last \fIAge\fR seconds are counted. If \fIAge\fR is
+a negative number, this is inversed. For example, if \fB\-60\fR is specified, only
+files that have been modified in the last minute will be counted.
+.Sp
+The number can also be followed by a \*(L"multiplier\*(R" to easily specify a larger
+timespan. When given in this notation, the argument must in quoted, i.\ e.
+must be passed as string. So the \fB\-60\fR could also be written as \fB\*(L"\-1m\*(R"\fR (one
+minute). Valid multipliers are \f(CW\*(C`s\*(C'\fR (second), \f(CW\*(C`m\*(C'\fR (minute), \f(CW\*(C`h\*(C'\fR (hour), \f(CW\*(C`d\*(C'\fR
+(day), \f(CW\*(C`w\*(C'\fR (week), and \f(CW\*(C`y\*(C'\fR (year). There is no \*(L"month\*(R" multiplier. You can
+also specify fractional numbers, e.\ g. \fB\*(L"0.5d\*(R"\fR is identical to
+\&\fB\*(L"12h\*(R"\fR.
+.IP "\fBSize\fR \fISize\fR" 4
+.IX Item "Size Size"
+Count only files of a specific size. When \fISize\fR is a positive number, only
+files that are at least this big are counted. If \fISize\fR is a negative number,
+this is inversed, i.\ e. only files smaller than the absolute value of
+\&\fISize\fR are counted.
+.Sp
+As with the \fBMTime\fR option, a \*(L"multiplier\*(R" may be added. For a detailed
+description see above. Valid multipliers here are \f(CW\*(C`b\*(C'\fR (byte), \f(CW\*(C`k\*(C'\fR (kilobyte),
+\&\f(CW\*(C`m\*(C'\fR (megabyte), \f(CW\*(C`g\*(C'\fR (gigabyte), \f(CW\*(C`t\*(C'\fR (terabyte), and \f(CW\*(C`p\*(C'\fR (petabyte). Please
+note that there are 1000 bytes in a kilobyte, not 1024.
+.IP "\fBRecursive\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "Recursive true|false"
+Controls whether or not to recurse into subdirectories. Enabled by default.
+.IP "\fBIncludeHidden\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "IncludeHidden true|false"
+Controls whether or not to include \*(L"hidden\*(R" files and directories in the count.
+\&\*(L"Hidden\*(R" files and directories are those, whose name begins with a dot.
+Defaults to \fIfalse\fR, i.e. by default hidden files and directories are ignored.
+.ie n .SS "Plugin ""GenericJMX"""
+.el .SS "Plugin \f(CWGenericJMX\fP"
+.IX Subsection "Plugin GenericJMX"
+The \fIGenericJMX plugin\fR is written in \fIJava\fR and therefore documented in
+\&\fIcollectd\-java\fR\|(5).
+.ie n .SS "Plugin ""gmond"""
+.el .SS "Plugin \f(CWgmond\fP"
+.IX Subsection "Plugin gmond"
+The \fIgmond\fR plugin received the multicast traffic sent by \fBgmond\fR, the
+statistics collection daemon of Ganglia. Mappings for the standard \*(L"metrics\*(R"
+are built-in, custom mappings may be added via \fBMetric\fR blocks, see below.
+.PP
+Synopsis:
+.PP
+.Vb 10
+\& <Plugin "gmond">
+\&   MCReceiveFrom "239.2.11.71" "8649"
+\&   <Metric "swap_total">
+\&     Type "swap"
+\&     TypeInstance "total"
+\&     DataSource "value"
+\&   </Metric>
+\&   <Metric "swap_free">
+\&     Type "swap"
+\&     TypeInstance "free"
+\&     DataSource "value"
+\&   </Metric>
+\& </Plugin>
+.Ve
+.PP
+The following metrics are built-in:
+.IP "\(bu" 4
+load_one, load_five, load_fifteen
+.IP "\(bu" 4
+cpu_user, cpu_system, cpu_idle, cpu_nice, cpu_wio
+.IP "\(bu" 4
+mem_free, mem_shared, mem_buffers, mem_cached, mem_total
+.IP "\(bu" 4
+bytes_in, bytes_out
+.IP "\(bu" 4
+pkts_in, pkts_out
+.PP
+Available configuration options:
+.IP "\fBMCReceiveFrom\fR \fIMCGroup\fR [\fIPort\fR]" 4
+.IX Item "MCReceiveFrom MCGroup [Port]"
+Sets sets the multicast group and \s-1UDP\s0 port to which to subscribe.
+.Sp
+Default: \fB239.2.11.71\fR\ /\ \fB8649\fR
+.IP "<\fBMetric\fR \fIName\fR>" 4
+.IX Item "<Metric Name>"
+These blocks add a new metric conversion to the internal table. \fIName\fR, the
+string argument to the \fBMetric\fR block, is the metric name as used by Ganglia.
+.RS 4
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+Type to map this metric to. Required.
+.IP "\fBTypeInstance\fR \fIInstance\fR" 4
+.IX Item "TypeInstance Instance"
+Type-instance to use. Optional.
+.IP "\fBDataSource\fR \fIName\fR" 4
+.IX Item "DataSource Name"
+Data source to map this metric to. If the configured type has exactly one data
+source, this is optional. Otherwise the option is required.
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""hddtemp"""
+.el .SS "Plugin \f(CWhddtemp\fP"
+.IX Subsection "Plugin hddtemp"
+To get values from \fBhddtemp\fR collectd connects to \fBlocalhost\fR (127.0.0.1),
+port \fB7634/tcp\fR. The \fBHost\fR and \fBPort\fR options can be used to change these
+default values, see below. \f(CW\*(C`hddtemp\*(C'\fR has to be running to work correctly. If
+\&\f(CW\*(C`hddtemp\*(C'\fR is not running timeouts may appear which may interfere with other
+statistics..
+.PP
+The \fBhddtemp\fR homepage can be found at
+<http://www.guzu.net/linux/hddtemp.php>.
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+Hostname to connect to. Defaults to \fB127.0.0.1\fR.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+TCP-Port to connect to. Defaults to \fB7634\fR.
+.ie n .SS "Plugin ""interface"""
+.el .SS "Plugin \f(CWinterface\fP"
+.IX Subsection "Plugin interface"
+.IP "\fBInterface\fR \fIInterface\fR" 4
+.IX Item "Interface Interface"
+Select this interface. By default these interfaces will then be collected. For
+a more detailed description see \fBIgnoreSelected\fR below.
+.IP "\fBIgnoreSelected\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+If no configuration if given, the \fBtraffic\fR\-plugin will collect data from
+all interfaces. This may not be practical, especially for loopback\- and
+similar interfaces. Thus, you can use the \fBInterface\fR\-option to pick the
+interfaces you're interested in. Sometimes, however, it's easier/preferred
+to collect all interfaces \fIexcept\fR a few ones. This option enables you to
+do that: By setting \fBIgnoreSelected\fR to \fItrue\fR the effect of
+\&\fBInterface\fR is inverted: All selected interfaces are ignored and all
+other interfaces are collected.
+.ie n .SS "Plugin ""ipmi"""
+.el .SS "Plugin \f(CWipmi\fP"
+.IX Subsection "Plugin ipmi"
+.IP "\fBSensor\fR \fISensor\fR" 4
+.IX Item "Sensor Sensor"
+Selects sensors to collect or to ignore, depending on \fBIgnoreSelected\fR.
+.IP "\fBIgnoreSelected\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+If no configuration if given, the \fBipmi\fR plugin will collect data from all
+sensors found of type \*(L"temperature\*(R", \*(L"voltage\*(R", \*(L"current\*(R" and \*(L"fanspeed\*(R".
+This option enables you to do that: By setting \fBIgnoreSelected\fR to \fItrue\fR
+the effect of \fBSensor\fR is inverted: All selected sensors are ignored and
+all other sensors are collected.
+.IP "\fBNotifySensorAdd\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "NotifySensorAdd true|false"
+If a sensor appears after initialization time of a minute a notification
+is sent.
+.IP "\fBNotifySensorRemove\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "NotifySensorRemove true|false"
+If a sensor disappears a notification is sent.
+.IP "\fBNotifySensorNotPresent\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "NotifySensorNotPresent true|false"
+If you have for example dual power supply and one of them is (un)plugged then
+a notification is sent.
+.ie n .SS "Plugin ""iptables"""
+.el .SS "Plugin \f(CWiptables\fP"
+.IX Subsection "Plugin iptables"
+.IP "\fBChain\fR \fITable\fR \fIChain\fR [\fIComment|Number\fR [\fIName\fR]]" 4
+.IX Item "Chain Table Chain [Comment|Number [Name]]"
+Select the rules to count. If only \fITable\fR and \fIChain\fR are given, this plugin
+will collect the counters of all rules which have a comment-match. The comment
+is then used as type-instance.
+.Sp
+If \fIComment\fR or \fINumber\fR is given, only the rule with the matching comment or
+the \fIn\fRth rule will be collected. Again, the comment (or the number) will be
+used as the type-instance.
+.Sp
+If \fIName\fR is supplied, it will be used as the type-instance instead of the
+comment or the number.
+.ie n .SS "Plugin ""irq"""
+.el .SS "Plugin \f(CWirq\fP"
+.IX Subsection "Plugin irq"
+.IP "\fBIrq\fR \fIIrq\fR" 4
+.IX Item "Irq Irq"
+Select this irq. By default these irqs will then be collected. For a more
+detailed description see \fBIgnoreSelected\fR below.
+.IP "\fBIgnoreSelected\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+If no configuration if given, the \fBirq\fR\-plugin will collect data from all
+irqs. This may not be practical, especially if no interrupts happen. Thus, you
+can use the \fBIrq\fR\-option to pick the interrupt you're interested in.
+Sometimes, however, it's easier/preferred to collect all interrupts \fIexcept\fR a
+few ones. This option enables you to do that: By setting \fBIgnoreSelected\fR to
+\&\fItrue\fR the effect of \fBIrq\fR is inverted: All selected interrupts are ignored
+and all other interrupts are collected.
+.ie n .SS "Plugin ""java"""
+.el .SS "Plugin \f(CWjava\fP"
+.IX Subsection "Plugin java"
+The \fIJava\fR plugin makes it possible to write extensions for collectd in Java.
+This section only discusses the syntax and semantic of the configuration
+options. For more in-depth information on the \fIJava\fR plugin, please read
+\&\fIcollectd\-java\fR\|(5).
+.PP
+Synopsis:
+.PP
+.Vb 8
+\& <Plugin "java">
+\&   JVMArg "\-verbose:jni"
+\&   JVMArg "\-Djava.class.path=/opt/collectd/lib/collectd/bindings/java"
+\&   LoadPlugin "org.collectd.java.Foobar"
+\&   <Plugin "org.collectd.java.Foobar">
+\&     # To be parsed by the plugin
+\&   </Plugin>
+\& </Plugin>
+.Ve
+.PP
+Available configuration options:
+.IP "\fBJVMArg\fR \fIArgument\fR" 4
+.IX Item "JVMArg Argument"
+Argument that is to be passed to the \fIJava Virtual Machine\fR (\s-1JVM\s0). This works
+exactly the way the arguments to the \fIjava\fR binary on the command line work.
+Execute \f(CW\*(C`java\ \-\-help\*(C'\fR for details.
+.Sp
+Please note that \fBall\fR these options must appear \fBbefore\fR (i.\ e. above)
+any other options! When another option is found, the \s-1JVM\s0 will be started and
+later options will have to be ignored!
+.IP "\fBLoadPlugin\fR \fIJavaClass\fR" 4
+.IX Item "LoadPlugin JavaClass"
+Instantiates a new \fIJavaClass\fR object. The constructor of this object very
+likely then registers one or more callback methods with the server.
+.Sp
+See \fIcollectd\-java\fR\|(5) for details.
+.Sp
+When the first such option is found, the virtual machine (\s-1JVM\s0) is created. This
+means that all \fBJVMArg\fR options must appear before (i.\ e. above) all
+\&\fBLoadPlugin\fR options!
+.IP "\fBPlugin\fR \fIName\fR" 4
+.IX Item "Plugin Name"
+The entire block is passed to the Java plugin as an
+\&\fIorg.collectd.api.OConfigItem\fR object.
+.Sp
+For this to work, the plugin has to register a configuration callback first,
+see \*(L"config callback\*(R" in \fIcollectd\-java\fR\|(5). This means, that the \fBPlugin\fR block
+must appear after the appropriate \fBLoadPlugin\fR block. Also note, that \fIName\fR
+depends on the (Java) plugin registering the callback and is completely
+independent from the \fIJavaClass\fR argument passed to \fBLoadPlugin\fR.
+.ie n .SS "Plugin ""load"""
+.el .SS "Plugin \f(CWload\fP"
+.IX Subsection "Plugin load"
+The \fILoad plugin\fR collects the system load. These numbers give a rough overview
+over the utilization of a machine. The system load is defined as the number of
+runnable tasks in the run-queue and is provided by many operating systems as a
+one, five or fifteen minute average.
+.PP
+The following configuration options are available:
+.IP "\fBReportRelative\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ReportRelative false|true"
+When enabled, system load divided by number of available \s-1CPU\s0 cores is reported
+for intervals 1 min, 5 min and 15 min. Defaults to false.
+.ie n .SS "Plugin ""logfile"""
+.el .SS "Plugin \f(CWlogfile\fP"
+.IX Subsection "Plugin logfile"
+.IP "\fBLogLevel\fR \fBdebug|info|notice|warning|err\fR" 4
+.IX Item "LogLevel debug|info|notice|warning|err"
+Sets the log-level. If, for example, set to \fBnotice\fR, then all events with
+severity \fBnotice\fR, \fBwarning\fR, or \fBerr\fR will be written to the logfile.
+.Sp
+Please note that \fBdebug\fR is only available if collectd has been compiled with
+debugging support.
+.IP "\fBFile\fR \fIFile\fR" 4
+.IX Item "File File"
+Sets the file to write log messages to. The special strings \fBstdout\fR and
+\&\fBstderr\fR can be used to write to the standard output and standard error
+channels, respectively. This, of course, only makes much sense when \fIcollectd\fR
+is running in foreground\- or non-daemon-mode.
+.IP "\fBTimestamp\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Timestamp true|false"
+Prefix all lines printed by the current time. Defaults to \fBtrue\fR.
+.IP "\fBPrintSeverity\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "PrintSeverity true|false"
+When enabled, all lines are prefixed by the severity of the log message, for
+example \*(L"warning\*(R". Defaults to \fBfalse\fR.
+.PP
+\&\fBNote\fR: There is no need to notify the daemon after moving or removing the
+log file (e.\ g. when rotating the logs). The plugin reopens the file
+for each line it writes.
+.ie n .SS "Plugin ""log_logstash"""
+.el .SS "Plugin \f(CWlog_logstash\fP"
+.IX Subsection "Plugin log_logstash"
+The \fIlog logstash plugin\fR behaves like the logfile plugin but formats
+messages as \s-1JSON\s0 events for logstash to parse and input.
+.IP "\fBLogLevel\fR \fBdebug|info|notice|warning|err\fR" 4
+.IX Item "LogLevel debug|info|notice|warning|err"
+Sets the log-level. If, for example, set to \fBnotice\fR, then all events with
+severity \fBnotice\fR, \fBwarning\fR, or \fBerr\fR will be written to the logfile.
+.Sp
+Please note that \fBdebug\fR is only available if collectd has been compiled with
+debugging support.
+.IP "\fBFile\fR \fIFile\fR" 4
+.IX Item "File File"
+Sets the file to write log messages to. The special strings \fBstdout\fR and
+\&\fBstderr\fR can be used to write to the standard output and standard error
+channels, respectively. This, of course, only makes much sense when \fIcollectd\fR
+is running in foreground\- or non-daemon-mode.
+.PP
+\&\fBNote\fR: There is no need to notify the daemon after moving or removing the
+log file (e.\ g. when rotating the logs). The plugin reopens the file
+for each line it writes.
+.ie n .SS "Plugin ""lpar"""
+.el .SS "Plugin \f(CWlpar\fP"
+.IX Subsection "Plugin lpar"
+The \fI\s-1LPAR\s0 plugin\fR reads \s-1CPU\s0 statistics of \fILogical Partitions\fR, a
+virtualization technique for \s-1IBM POWER\s0 processors. It takes into account \s-1CPU\s0
+time stolen from or donated to a partition, in addition to the usual user,
+system, I/O statistics.
+.PP
+The following configuration options are available:
+.IP "\fBCpuPoolStats\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "CpuPoolStats false|true"
+When enabled, statistics about the processor pool are read, too. The partition
+needs to have pool authority in order to be able to acquire this information.
+Defaults to false.
+.IP "\fBReportBySerial\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ReportBySerial false|true"
+If enabled, the serial of the physical machine the partition is currently
+running on is reported as \fIhostname\fR and the logical hostname of the machine
+is reported in the \fIplugin instance\fR. Otherwise, the logical hostname will be
+used (just like other plugins) and the \fIplugin instance\fR will be empty.
+Defaults to false.
+.ie n .SS "Plugin ""mbmon"""
+.el .SS "Plugin \f(CWmbmon\fP"
+.IX Subsection "Plugin mbmon"
+The \f(CW\*(C`mbmon plugin\*(C'\fR uses mbmon to retrieve temperature, voltage, etc.
+.PP
+Be default collectd connects to \fBlocalhost\fR (127.0.0.1), port \fB411/tcp\fR. The
+\&\fBHost\fR and \fBPort\fR options can be used to change these values, see below.
+\&\f(CW\*(C`mbmon\*(C'\fR has to be running to work correctly. If \f(CW\*(C`mbmon\*(C'\fR is not running
+timeouts may appear which may interfere with other statistics..
+.PP
+\&\f(CW\*(C`mbmon\*(C'\fR must be run with the \-r option (\*(L"print \s-1TAG\s0 and Value format\*(R");
+Debian's \fI/etc/init.d/mbmon\fR script already does this, other people
+will need to ensure that this is the case.
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+Hostname to connect to. Defaults to \fB127.0.0.1\fR.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+TCP-Port to connect to. Defaults to \fB411\fR.
+.ie n .SS "Plugin ""md"""
+.el .SS "Plugin \f(CWmd\fP"
+.IX Subsection "Plugin md"
+The \f(CW\*(C`md plugin\*(C'\fR collects information from Linux Software-RAID devices (md).
+.PP
+All reported values are of the type \f(CW\*(C`md_disks\*(C'\fR. Reported type instances are
+\&\fIactive\fR, \fIfailed\fR (present but not operational), \fIspare\fR (hot stand-by) and
+\&\fImissing\fR (physically absent) disks.
+.IP "\fBDevice\fR \fIDevice\fR" 4
+.IX Item "Device Device"
+Select md devices based on device name. The \fIdevice name\fR is the basename of
+the device, i.e. the name of the block device without the leading \f(CW\*(C`/dev/\*(C'\fR.
+See \fBIgnoreSelected\fR for more details.
+.IP "\fBIgnoreSelected\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+Invert device selection: If set to \fBtrue\fR, all md devices \fBexcept\fR those
+listed using \fBDevice\fR are collected. If \fBfalse\fR (the default), only those
+listed are collected. If no configuration is given, the \fBmd\fR plugin will
+collect data from all md devices.
+.ie n .SS "Plugin ""memcachec"""
+.el .SS "Plugin \f(CWmemcachec\fP"
+.IX Subsection "Plugin memcachec"
+The \f(CW\*(C`memcachec plugin\*(C'\fR connects to a memcached server, queries one or more
+given \fIpages\fR and parses the returned data according to user specification.
+The \fImatches\fR used are the same as the matches used in the \f(CW\*(C`curl\*(C'\fR and \f(CW\*(C`tail\*(C'\fR
+plugins.
+.PP
+In order to talk to the memcached server, this plugin uses the \fIlibmemcached\fR
+library. Please note that there is another library with a very similar name,
+libmemcache (notice the missing `d'), which is not applicable.
+.PP
+Synopsis of the configuration:
+.PP
+.Vb 12
+\& <Plugin "memcachec">
+\&   <Page "plugin_instance">
+\&     Server "localhost"
+\&     Key "page_key"
+\&     <Match>
+\&       Regex "(\e\ed+) bytes sent"
+\&       DSType CounterAdd
+\&       Type "ipt_octets"
+\&       Instance "type_instance"
+\&     </Match>
+\&   </Page>
+\& </Plugin>
+.Ve
+.PP
+The configuration options are:
+.IP "<\fBPage\fR \fIName\fR>" 4
+.IX Item "<Page Name>"
+Each \fBPage\fR block defines one \fIpage\fR to be queried from the memcached server.
+The block requires one string argument which is used as \fIplugin instance\fR.
+.IP "\fBServer\fR \fIAddress\fR" 4
+.IX Item "Server Address"
+Sets the server address to connect to when querying the page. Must be inside a
+\&\fBPage\fR block.
+.IP "\fBKey\fR \fIKey\fR" 4
+.IX Item "Key Key"
+When connected to the memcached server, asks for the page \fIKey\fR.
+.IP "<\fBMatch\fR>" 4
+.IX Item "<Match>"
+Match blocks define which strings to look for and how matches substrings are
+interpreted. For a description of match blocks, please see \*(L"Plugin tail\*(R".
+.ie n .SS "Plugin ""memcached"""
+.el .SS "Plugin \f(CWmemcached\fP"
+.IX Subsection "Plugin memcached"
+The \fBmemcached plugin\fR connects to a memcached server and queries statistics
+about cache utilization, memory and bandwidth used.
+<http://www.danga.com/memcached/>
+.PP
+.Vb 6
+\& <Plugin "memcached">
+\&   <Instance "name">
+\&     Host "memcache.example.com"
+\&     Port 11211
+\&   </Instance>
+\& </Plugin>
+.Ve
+.PP
+The plugin configuration consists of one or more \fBInstance\fR blocks which
+specify one \fImemcached\fR connection each. Within the \fBInstance\fR blocks, the
+following options are allowed:
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+Hostname to connect to. Defaults to \fB127.0.0.1\fR.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+TCP-Port to connect to. Defaults to \fB11211\fR.
+.IP "\fBSocket\fR \fIPath\fR" 4
+.IX Item "Socket Path"
+Connect to \fImemcached\fR using the \s-1UNIX\s0 domain socket at \fIPath\fR. If this
+setting is given, the \fBHost\fR and \fBPort\fR settings are ignored.
+.ie n .SS "Plugin ""mic"""
+.el .SS "Plugin \f(CWmic\fP"
+.IX Subsection "Plugin mic"
+The \fBmic plugin\fR gathers \s-1CPU\s0 statistics, memory usage and temperatures from
+Intel's Many Integrated Core (\s-1MIC\s0) systems.
+.PP
+\&\fBSynopsis:\fR
+.PP
+.Vb 4
+\& <Plugin mic>
+\&   ShowCPU true
+\&   ShowCPUCores true
+\&   ShowMemory true
+\&
+\&   ShowTemperatures true
+\&   Temperature vddg
+\&   Temperature vddq
+\&   IgnoreSelectedTemperature true
+\&
+\&   ShowPower true
+\&   Power total0
+\&   Power total1
+\&   IgnoreSelectedPower true
+\& </Plugin>
+.Ve
+.PP
+The following options are valid inside the \fBPlugin\ mic\fR block:
+.IP "\fBShowCPU\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ShowCPU true|false"
+If enabled (the default) a sum of the \s-1CPU\s0 usage across all cores is reported.
+.IP "\fBShowCPUCores\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ShowCPUCores true|false"
+If enabled (the default) per-core \s-1CPU\s0 usage is reported.
+.IP "\fBShowMemory\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ShowMemory true|false"
+If enabled (the default) the physical memory usage of the \s-1MIC\s0 system is
+reported.
+.IP "\fBShowTemperatures\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ShowTemperatures true|false"
+If enabled (the default) various temperatures of the \s-1MIC\s0 system are reported.
+.IP "\fBTemperature\fR \fIName\fR" 4
+.IX Item "Temperature Name"
+This option controls which temperatures are being reported. Whether matching
+temperatures are being ignored or \fIonly\fR matching temperatures are reported
+depends on the \fBIgnoreSelectedTemperature\fR setting below. By default \fIall\fR
+temperatures are reported.
+.IP "\fBIgnoreSelectedTemperature\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "IgnoreSelectedTemperature false|true"
+Controls the behavior of the \fBTemperature\fR setting above. If set to \fBfalse\fR
+(the default) only temperatures matching a \fBTemperature\fR option are reported
+or, if no \fBTemperature\fR option is specified, all temperatures are reported. If
+set to \fBtrue\fR, matching temperatures are \fIignored\fR and all other temperatures
+are reported.
+.Sp
+Known temperature names are:
+.RS 4
+.IP "die" 4
+.IX Item "die"
+Die of the \s-1CPU\s0
+.IP "devmem" 4
+.IX Item "devmem"
+Device Memory
+.IP "fin" 4
+.IX Item "fin"
+Fan In
+.IP "fout" 4
+.IX Item "fout"
+Fan Out
+.IP "vccp" 4
+.IX Item "vccp"
+Voltage ccp
+.IP "vddg" 4
+.IX Item "vddg"
+Voltage ddg
+.IP "vddq" 4
+.IX Item "vddq"
+Voltage ddq
+.RE
+.RS 4
+.RE
+.IP "\fBShowPower\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ShowPower true|false"
+If enabled (the default) various temperatures of the \s-1MIC\s0 system are reported.
+.IP "\fBPower\fR \fIName\fR" 4
+.IX Item "Power Name"
+This option controls which power readings are being reported. Whether matching
+power readings are being ignored or \fIonly\fR matching power readings are reported
+depends on the \fBIgnoreSelectedPower\fR setting below. By default \fIall\fR
+power readings are reported.
+.IP "\fBIgnoreSelectedPower\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "IgnoreSelectedPower false|true"
+Controls the behavior of the \fBPower\fR setting above. If set to \fBfalse\fR
+(the default) only power readings matching a \fBPower\fR option are reported
+or, if no \fBPower\fR option is specified, all power readings are reported. If
+set to \fBtrue\fR, matching power readings are \fIignored\fR and all other power readings
+are reported.
+.Sp
+Known power names are:
+.RS 4
+.IP "total0" 4
+.IX Item "total0"
+Total power utilization averaged over Time Window 0 (uWatts).
+.IP "total1" 4
+.IX Item "total1"
+Total power utilization averaged over Time Window 0 (uWatts).
+.IP "inst" 4
+.IX Item "inst"
+Instantaneous power (uWatts).
+.IP "imax" 4
+.IX Item "imax"
+Max instantaneous power (uWatts).
+.IP "pcie" 4
+.IX Item "pcie"
+PCI-E connector power (uWatts).
+.IP "c2x3" 4
+.IX Item "c2x3"
+2x3 connector power (uWatts).
+.IP "c2x4" 4
+.IX Item "c2x4"
+2x4 connector power (uWatts).
+.IP "vccp" 4
+.IX Item "vccp"
+Core rail (uVolts).
+.IP "vddg" 4
+.IX Item "vddg"
+Uncore rail (uVolts).
+.IP "vddq" 4
+.IX Item "vddq"
+Memory subsystem rail (uVolts).
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""memory"""
+.el .SS "Plugin \f(CWmemory\fP"
+.IX Subsection "Plugin memory"
+The \fImemory plugin\fR provides the following configuration options:
+.IP "\fBValuesAbsolute\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ValuesAbsolute true|false"
+Enables or disables reporting of physical memory usage in absolute numbers,
+i.e. bytes. Defaults to \fBtrue\fR.
+.IP "\fBValuesPercentage\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ValuesPercentage false|true"
+Enables or disables reporting of physical memory usage in percentages, e.g.
+percent of physical memory used. Defaults to \fBfalse\fR.
+.Sp
+This is useful for deploying \fIcollectd\fR in a heterogeneous environment in
+which the sizes of physical memory vary.
+.ie n .SS "Plugin ""modbus"""
+.el .SS "Plugin \f(CWmodbus\fP"
+.IX Subsection "Plugin modbus"
+The \fBmodbus plugin\fR connects to a Modbus \*(L"slave\*(R" via Modbus/TCP or Modbus/RTU and
+reads register values. It supports reading single registers (unsigned 16\ bit
+values), large integer values (unsigned 32\ bit values) and floating point
+values (two registers interpreted as \s-1IEEE\s0 floats in big endian notation).
+.PP
+\&\fBSynopsis:\fR
+.PP
+.Vb 7
+\& <Data "voltage\-input\-1">
+\&   RegisterBase 0
+\&   RegisterType float
+\&   RegisterCmd ReadHolding
+\&   Type voltage
+\&   Instance "input\-1"
+\& </Data>
+\&
+\& <Data "voltage\-input\-2">
+\&   RegisterBase 2
+\&   RegisterType float
+\&   RegisterCmd ReadHolding
+\&   Type voltage
+\&   Instance "input\-2"
+\& </Data>
+\&
+\& <Data "supply\-temperature\-1">
+\&   RegisterBase 0
+\&   RegisterType Int16
+\&   RegisterCmd ReadHolding
+\&   Type temperature
+\&   Instance "temp\-1"
+\& </Data>
+\&
+\& <Host "modbus.example.com">
+\&   Address "192.168.0.42"
+\&   Port    "502"
+\&   Interval 60
+\&
+\&   <Slave 1>
+\&     Instance "power\-supply"
+\&     Collect  "voltage\-input\-1"
+\&     Collect  "voltage\-input\-2"
+\&   </Slave>
+\& </Host>
+\&
+\& <Host "localhost">
+\&   Device "/dev/ttyUSB0"
+\&   Baudrate 38400
+\&   Interval 20
+\&
+\&   <Slave 1>
+\&     Instance "temperature"
+\&     Collect  "supply\-temperature\-1"
+\&   </Slave>
+\& </Host>
+.Ve
+.IP "<\fBData\fR \fIName\fR> blocks" 4
+.IX Item "<Data Name> blocks"
+Data blocks define a mapping between register numbers and the \*(L"types\*(R" used by
+\&\fIcollectd\fR.
+.Sp
+Within <Data\ /> blocks, the following options are allowed:
+.RS 4
+.IP "\fBRegisterBase\fR \fINumber\fR" 4
+.IX Item "RegisterBase Number"
+Configures the base register to read from the device. If the option
+\&\fBRegisterType\fR has been set to \fBUint32\fR or \fBFloat\fR, this and the next
+register will be read (the register number is increased by one).
+.IP "\fBRegisterType\fR \fBInt16\fR|\fBInt32\fR|\fBUint16\fR|\fBUint32\fR|\fBFloat\fR" 4
+.IX Item "RegisterType Int16|Int32|Uint16|Uint32|Float"
+Specifies what kind of data is returned by the device. If the type is \fBInt32\fR,
+\&\fBUint32\fR or \fBFloat\fR, two 16\ bit registers will be read and the data is
+combined into one value. Defaults to \fBUint16\fR.
+.IP "\fBRegisterCmd\fR \fBReadHolding\fR|\fBReadInput\fR" 4
+.IX Item "RegisterCmd ReadHolding|ReadInput"
+Specifies register type to be collected from device. Works only with libmodbus
+2.9.2 or higher. Defaults to \fBReadHolding\fR.
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+Specifies the \*(L"type\*(R" (data set) to use when dispatching the value to
+\&\fIcollectd\fR. Currently, only data sets with exactly one data source are
+supported.
+.IP "\fBInstance\fR \fIInstance\fR" 4
+.IX Item "Instance Instance"
+Sets the type instance to use when dispatching the value to \fIcollectd\fR. If
+unset, an empty string (no type instance) is used.
+.RE
+.RS 4
+.RE
+.IP "<\fBHost\fR \fIName\fR> blocks" 4
+.IX Item "<Host Name> blocks"
+Host blocks are used to specify to which hosts to connect and what data to read
+from their \*(L"slaves\*(R". The string argument \fIName\fR is used as hostname when
+dispatching the values to \fIcollectd\fR.
+.Sp
+Within <Host\ /> blocks, the following options are allowed:
+.RS 4
+.IP "\fBAddress\fR \fIHostname\fR" 4
+.IX Item "Address Hostname"
+For Modbus/TCP, specifies the node name (the actual network address) used to
+connect to the host. This may be an \s-1IP\s0 address or a hostname. Please note that
+the used \fIlibmodbus\fR library only supports IPv4 at the moment.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+for Modbus/TCP, specifies the port used to connect to the host. The port can
+either be given as a number or as a service name. Please note that the
+\&\fIService\fR argument must be a string, even if ports are given in their numerical
+form. Defaults to \*(L"502\*(R".
+.IP "\fBDevice\fR \fIDevicenode\fR" 4
+.IX Item "Device Devicenode"
+For Modbus/RTU, specifies the path to the serial device being used.
+.IP "\fBBaudrate\fR \fIBaudrate\fR" 4
+.IX Item "Baudrate Baudrate"
+For Modbus/RTU, specifies the baud rate of the serial device.
+Note, connections currently support only 8/N/1.
+.IP "\fBInterval\fR \fIInterval\fR" 4
+.IX Item "Interval Interval"
+Sets the interval (in seconds) in which the values will be collected from this
+host. By default the global \fBInterval\fR setting will be used.
+.IP "<\fBSlave\fR \fI\s-1ID\s0\fR>" 4
+.IX Item "<Slave ID>"
+Over each connection, multiple Modbus devices may be reached. The slave \s-1ID\s0
+is used to specify which device should be addressed. For each device you want
+to query, one \fBSlave\fR block must be given.
+.Sp
+Within <Slave\ /> blocks, the following options are allowed:
+.RS 4
+.IP "\fBInstance\fR \fIInstance\fR" 4
+.IX Item "Instance Instance"
+Specify the plugin instance to use when dispatching the values to \fIcollectd\fR.
+By default "slave_\fI\s-1ID\s0\fR" is used.
+.IP "\fBCollect\fR \fIDataName\fR" 4
+.IX Item "Collect DataName"
+Specifies which data to retrieve from the device. \fIDataName\fR must be the same
+string as the \fIName\fR argument passed to a \fBData\fR block. You can specify this
+option multiple times to collect more than one value from a slave. At least one
+\&\fBCollect\fR option is mandatory.
+.RE
+.RS 4
+.RE
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""mysql"""
+.el .SS "Plugin \f(CWmysql\fP"
+.IX Subsection "Plugin mysql"
+The \f(CW\*(C`mysql plugin\*(C'\fR requires \fBmysqlclient\fR to be installed. It connects to
+one or more databases when started and keeps the connection up as long as
+possible. When the connection is interrupted for whatever reason it will try
+to re-connect. The plugin will complain loudly in case anything goes wrong.
+.PP
+This plugin issues the MySQL \f(CW\*(C`SHOW STATUS\*(C'\fR / \f(CW\*(C`SHOW GLOBAL STATUS\*(C'\fR command
+and collects information about MySQL network traffic, executed statements,
+requests, the query cache and threads by evaluating the
+\&\f(CW\*(C`Bytes_{received,sent}\*(C'\fR, \f(CW\*(C`Com_*\*(C'\fR, \f(CW\*(C`Handler_*\*(C'\fR, \f(CW\*(C`Qcache_*\*(C'\fR and \f(CW\*(C`Threads_*\*(C'\fR
+return values. Please refer to the \fBMySQL reference manual\fR, \fI5.1.6. Server
+Status Variables\fR for an explanation of these values.
+.PP
+Optionally, master and slave statistics may be collected in a MySQL
+replication setup. In that case, information about the synchronization state
+of the nodes are collected by evaluating the \f(CW\*(C`Position\*(C'\fR return value of the
+\&\f(CW\*(C`SHOW MASTER STATUS\*(C'\fR command and the \f(CW\*(C`Seconds_Behind_Master\*(C'\fR,
+\&\f(CW\*(C`Read_Master_Log_Pos\*(C'\fR and \f(CW\*(C`Exec_Master_Log_Pos\*(C'\fR return values of the
+\&\f(CW\*(C`SHOW SLAVE STATUS\*(C'\fR command. See the \fBMySQL reference manual\fR,
+\&\fI12.5.5.21 \s-1SHOW MASTER STATUS\s0 Syntax\fR and
+\&\fI12.5.5.31 \s-1SHOW SLAVE STATUS\s0 Syntax\fR for details.
+.PP
+Synopsis:
+.PP
+.Vb 9
+\&  <Plugin mysql>
+\&    <Database foo>
+\&      Host "hostname"
+\&      User "username"
+\&      Password "password"
+\&      Port "3306"
+\&      MasterStats true
+\&      ConnectTimeout 10
+\&    </Database>
+\&
+\&    <Database bar>
+\&      Alias "squeeze"
+\&      Host "localhost"
+\&      Socket "/var/run/mysql/mysqld.sock"
+\&      SlaveStats true
+\&      SlaveNotifications true
+\&    </Database>
+\&  </Plugin>
+.Ve
+.PP
+A \fBDatabase\fR block defines one connection to a MySQL database. It accepts a
+single argument which specifies the name of the database. None of the other
+options are required. MySQL will use default values as documented in the
+section \*(L"\fImysql_real_connect()\fR\*(R" in the \fBMySQL reference manual\fR.
+.IP "\fBAlias\fR \fIAlias\fR" 4
+.IX Item "Alias Alias"
+Alias to use as sender instead of hostname when reporting. This may be useful
+when having cryptic hostnames.
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+Hostname of the database server. Defaults to \fBlocalhost\fR.
+.IP "\fBUser\fR \fIUsername\fR" 4
+.IX Item "User Username"
+Username to use when connecting to the database. The user does not have to be
+granted any privileges (which is synonym to granting the \f(CW\*(C`USAGE\*(C'\fR privilege),
+unless you want to collectd replication statistics (see \fBMasterStats\fR and
+\&\fBSlaveStats\fR below). In this case, the user needs the \f(CW\*(C`REPLICATION CLIENT\*(C'\fR
+(or \f(CW\*(C`SUPER\*(C'\fR) privileges. Else, any existing MySQL user will do.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Password needed to log into the database.
+.IP "\fBDatabase\fR \fIDatabase\fR" 4
+.IX Item "Database Database"
+Select this database. Defaults to \fIno database\fR which is a perfectly reasonable
+option for what this plugin does.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+TCP-port to connect to. The port must be specified in its numeric form, but it
+must be passed as a string nonetheless. For example:
+.Sp
+.Vb 1
+\&  Port "3306"
+.Ve
+.Sp
+If \fBHost\fR is set to \fBlocalhost\fR (the default), this setting has no effect.
+See the documentation for the \f(CW\*(C`mysql_real_connect\*(C'\fR function for details.
+.IP "\fBSocket\fR \fISocket\fR" 4
+.IX Item "Socket Socket"
+Specifies the path to the \s-1UNIX\s0 domain socket of the MySQL server. This option
+only has any effect, if \fBHost\fR is set to \fBlocalhost\fR (the default).
+Otherwise, use the \fBPort\fR option above. See the documentation for the
+\&\f(CW\*(C`mysql_real_connect\*(C'\fR function for details.
+.IP "\fBInnodbStats\fR \fItrue|false\fR" 4
+.IX Item "InnodbStats true|false"
+If enabled, metrics about the InnoDB storage engine are collected.
+Disabled by default.
+.IP "\fBMasterStats\fR \fItrue|false\fR" 4
+.IX Item "MasterStats true|false"
+.PD 0
+.IP "\fBSlaveStats\fR \fItrue|false\fR" 4
+.IX Item "SlaveStats true|false"
+.PD
+Enable the collection of master / slave statistics in a replication setup. In
+order to be able to get access to these statistics, the user needs special
+privileges. See the \fBUser\fR documentation above. Defaults to \fBfalse\fR.
+.IP "\fBSlaveNotifications\fR \fItrue|false\fR" 4
+.IX Item "SlaveNotifications true|false"
+If enabled, the plugin sends a notification if the replication slave I/O and /
+or \s-1SQL\s0 threads are not running. Defaults to \fBfalse\fR.
+.IP "\fBConnectTimeout\fR \fISeconds\fR" 4
+.IX Item "ConnectTimeout Seconds"
+Sets the connect timeout for the MySQL client.
+.ie n .SS "Plugin ""netapp"""
+.el .SS "Plugin \f(CWnetapp\fP"
+.IX Subsection "Plugin netapp"
+The netapp plugin can collect various performance and capacity information
+from a NetApp filer using the NetApp \s-1API.\s0
+.PP
+Please note that NetApp has a wide line of products and a lot of different
+software versions for each of these products. This plugin was developed for a
+NetApp \s-1FAS3040\s0 running OnTap 7.2.3P8 and tested on \s-1FAS2050 7.3.1.1L1,
+FAS3140 7.2.5.1\s0 and \s-1FAS3020 7.2.4P9.\s0 It \fIshould\fR work for most combinations of
+model and software version but it is very hard to test this.
+If you have used this plugin with other models and/or software version, feel
+free to send us a mail to tell us about the results, even if it's just a short
+\&\*(L"It works\*(R".
+.PP
+To collect these data collectd will log in to the NetApp via \s-1HTTP\s0(S) and \s-1HTTP\s0
+basic authentication.
+.PP
+\&\fBDo not use a regular user for this!\fR Create a special collectd user with just
+the minimum of capabilities needed. The user only needs the \*(L"login-http-admin\*(R"
+capability as well as a few more depending on which data will be collected.
+Required capabilities are documented below.
+.PP
+\fISynopsis\fR
+.IX Subsection "Synopsis"
+.PP
+.Vb 8
+\& <Plugin "netapp">
+\&   <Host "netapp1.example.com">
+\&    Protocol      "https"
+\&    Address       "10.0.0.1"
+\&    Port          443
+\&    User          "username"
+\&    Password      "aef4Aebe"
+\&    Interval      30
+\&
+\&    <WAFL>
+\&      Interval 30
+\&      GetNameCache   true
+\&      GetDirCache    true
+\&      GetBufferCache true
+\&      GetInodeCache  true
+\&    </WAFL>
+\&
+\&    <Disks>
+\&      Interval 30
+\&      GetBusy true
+\&    </Disks>
+\&
+\&    <VolumePerf>
+\&      Interval 30
+\&      GetIO      "volume0"
+\&      IgnoreSelectedIO      false
+\&      GetOps     "volume0"
+\&      IgnoreSelectedOps     false
+\&      GetLatency "volume0"
+\&      IgnoreSelectedLatency false
+\&    </VolumePerf>
+\&
+\&    <VolumeUsage>
+\&      Interval 30
+\&      GetCapacity "vol0"
+\&      GetCapacity "vol1"
+\&      IgnoreSelectedCapacity false
+\&      GetSnapshot "vol1"
+\&      GetSnapshot "vol3"
+\&      IgnoreSelectedSnapshot false
+\&    </VolumeUsage>
+\&
+\&    <Quota>
+\&      Interval 60
+\&    </Quota>
+\&
+\&    <Snapvault>
+\&      Interval 30
+\&    </Snapvault>
+\&
+\&    <System>
+\&      Interval 30
+\&      GetCPULoad     true
+\&      GetInterfaces  true
+\&      GetDiskOps     true
+\&      GetDiskIO      true
+\&    </System>
+\&
+\&    <VFiler vfilerA>
+\&      Interval 60
+\&
+\&      SnapVault true
+\&      # ...
+\&    </VFiler>
+\&   </Host>
+\& </Plugin>
+.Ve
+.PP
+The netapp plugin accepts the following configuration options:
+.IP "\fBHost\fR \fIName\fR" 4
+.IX Item "Host Name"
+A host block defines one NetApp filer. It will appear in collectd with the name
+you specify here which does not have to be its real name nor its hostname (see
+the \fBAddress\fR option below).
+.IP "\fBVFiler\fR \fIName\fR" 4
+.IX Item "VFiler Name"
+A \fBVFiler\fR block may only be used inside a host block. It accepts all the
+same options as the \fBHost\fR block (except for cascaded \fBVFiler\fR blocks) and
+will execute all NetApp \s-1API\s0 commands in the context of the specified
+VFiler(R). It will appear in collectd with the name you specify here which
+does not have to be its real name. The VFiler name may be specified using the
+\&\fBVFilerName\fR option. If this is not specified, it will default to the name
+you specify here.
+.Sp
+The VFiler block inherits all connection related settings from the surrounding
+\&\fBHost\fR block (which appear before the \fBVFiler\fR block) but they may be
+overwritten inside the \fBVFiler\fR block.
+.Sp
+This feature is useful, for example, when using a VFiler as SnapVault target
+(supported since OnTap 8.1). In that case, the SnapVault statistics are not
+available in the host filer (vfiler0) but only in the respective VFiler
+context.
+.IP "\fBProtocol\fR \fBhttpd\fR|\fBhttp\fR" 4
+.IX Item "Protocol httpd|http"
+The protocol collectd will use to query this host.
+.Sp
+Optional
+.Sp
+Type: string
+.Sp
+Default: https
+.Sp
+Valid options: http, https
+.IP "\fBAddress\fR \fIAddress\fR" 4
+.IX Item "Address Address"
+The hostname or \s-1IP\s0 address of the host.
+.Sp
+Optional
+.Sp
+Type: string
+.Sp
+Default: The \*(L"host\*(R" block's name.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+The \s-1TCP\s0 port to connect to on the host.
+.Sp
+Optional
+.Sp
+Type: integer
+.Sp
+Default: 80 for protocol \*(L"http\*(R", 443 for protocol \*(L"https\*(R"
+.IP "\fBUser\fR \fIUser\fR" 4
+.IX Item "User User"
+.PD 0
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+.PD
+The username and password to use to login to the NetApp.
+.Sp
+Mandatory
+.Sp
+Type: string
+.IP "\fBVFilerName\fR \fIName\fR" 4
+.IX Item "VFilerName Name"
+The name of the VFiler in which context to execute \s-1API\s0 commands. If not
+specified, the name provided to the \fBVFiler\fR block will be used instead.
+.Sp
+Optional
+.Sp
+Type: string
+.Sp
+Default: name of the \fBVFiler\fR block
+.Sp
+\&\fBNote:\fR This option may only be used inside \fBVFiler\fR blocks.
+.IP "\fBInterval\fR \fIInterval\fR" 4
+.IX Item "Interval Interval"
+\&\fB\s-1TODO\s0\fR
+.PP
+The following options decide what kind of data will be collected. You can
+either use them as a block and fine tune various parameters inside this block,
+use them as a single statement to just accept all default values, or omit it to
+not collect any data.
+.PP
+The following options are valid inside all blocks:
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect the respective statistics every \fISeconds\fR seconds. Defaults to the
+host specific setting.
+.PP
+\fIThe System block\fR
+.IX Subsection "The System block"
+.PP
+This will collect various performance data about the whole system.
+.PP
+\&\fBNote:\fR To get this data the collectd user needs the
+\&\*(L"api-perf-object-get-instances\*(R" capability.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect disk statistics every \fISeconds\fR seconds.
+.IP "\fBGetCPULoad\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetCPULoad true|false"
+If you set this option to true the current \s-1CPU\s0 usage will be read. This will be
+the average usage between all CPUs in your NetApp without any information about
+individual CPUs.
+.Sp
+\&\fBNote:\fR These are the same values that the NetApp \s-1CLI\s0 command \*(L"sysstat\*(R"
+returns in the \*(L"\s-1CPU\*(R"\s0 field.
+.Sp
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: Two value lists of type \*(L"cpu\*(R", and type instances \*(L"idle\*(R" and \*(L"system\*(R".
+.IP "\fBGetInterfaces\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetInterfaces true|false"
+If you set this option to true the current traffic of the network interfaces
+will be read. This will be the total traffic over all interfaces of your NetApp
+without any information about individual interfaces.
+.Sp
+\&\fBNote:\fR This is the same values that the NetApp \s-1CLI\s0 command \*(L"sysstat\*(R" returns
+in the \*(L"Net kB/s\*(R" field.
+.Sp
+\&\fBOr is it?\fR
+.Sp
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: One value list of type \*(L"if_octects\*(R".
+.IP "\fBGetDiskIO\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetDiskIO true|false"
+If you set this option to true the current \s-1IO\s0 throughput will be read. This
+will be the total \s-1IO\s0 of your NetApp without any information about individual
+disks, volumes or aggregates.
+.Sp
+\&\fBNote:\fR This is the same values that the NetApp \s-1CLI\s0 command \*(L"sysstat\*(R" returns
+in the \*(L"Disk\ kB/s\*(R" field.
+.Sp
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: One value list of type \*(L"disk_octets\*(R".
+.IP "\fBGetDiskOps\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetDiskOps true|false"
+If you set this option to true the current number of \s-1HTTP, NFS, CIFS, FCP,\s0
+iSCSI, etc. operations will be read. This will be the total number of
+operations on your NetApp without any information about individual volumes or
+aggregates.
+.Sp
+\&\fBNote:\fR These are the same values that the NetApp \s-1CLI\s0 command \*(L"sysstat\*(R"
+returns in the \*(L"\s-1NFS\*(R", \*(L"CIFS\*(R", \*(L"HTTP\*(R", \*(L"FCP\*(R"\s0 and \*(L"iSCSI\*(R" fields.
+.Sp
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: A variable number of value lists of type \*(L"disk_ops_complex\*(R". Each type
+of operation will result in one value list with the name of the operation as
+type instance.
+.PP
+\fIThe \s-1WAFL\s0 block\fR
+.IX Subsection "The WAFL block"
+.PP
+This will collect various performance data about the \s-1WAFL\s0 file system. At the
+moment this just means cache performance.
+.PP
+\&\fBNote:\fR To get this data the collectd user needs the
+\&\*(L"api-perf-object-get-instances\*(R" capability.
+.PP
+\&\fBNote:\fR The interface to get these values is classified as \*(L"Diagnostics\*(R" by
+NetApp. This means that it is not guaranteed to be stable even between minor
+releases.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect disk statistics every \fISeconds\fR seconds.
+.IP "\fBGetNameCache\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetNameCache true|false"
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: One value list of type \*(L"cache_ratio\*(R" and type instance
+\&\*(L"name_cache_hit\*(R".
+.IP "\fBGetDirCache\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetDirCache true|false"
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: One value list of type \*(L"cache_ratio\*(R" and type instance \*(L"find_dir_hit\*(R".
+.IP "\fBGetInodeCache\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetInodeCache true|false"
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: One value list of type \*(L"cache_ratio\*(R" and type instance
+\&\*(L"inode_cache_hit\*(R".
+.IP "\fBGetBufferCache\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetBufferCache true|false"
+\&\fBNote:\fR This is the same value that the NetApp \s-1CLI\s0 command \*(L"sysstat\*(R" returns
+in the \*(L"Cache hit\*(R" field.
+.Sp
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: One value list of type \*(L"cache_ratio\*(R" and type instance \*(L"buf_hash_hit\*(R".
+.PP
+\fIThe Disks block\fR
+.IX Subsection "The Disks block"
+.PP
+This will collect performance data about the individual disks in the NetApp.
+.PP
+\&\fBNote:\fR To get this data the collectd user needs the
+\&\*(L"api-perf-object-get-instances\*(R" capability.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect disk statistics every \fISeconds\fR seconds.
+.IP "\fBGetBusy\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "GetBusy true|false"
+If you set this option to true the busy time of all disks will be calculated
+and the value of the busiest disk in the system will be written.
+.Sp
+\&\fBNote:\fR This is the same values that the NetApp \s-1CLI\s0 command \*(L"sysstat\*(R" returns
+in the \*(L"Disk util\*(R" field. Probably.
+.Sp
+Optional
+.Sp
+Type: boolean
+.Sp
+Default: true
+.Sp
+Result: One value list of type \*(L"percent\*(R" and type instance \*(L"disk_busy\*(R".
+.PP
+\fIThe VolumePerf block\fR
+.IX Subsection "The VolumePerf block"
+.PP
+This will collect various performance data about the individual volumes.
+.PP
+You can select which data to collect about which volume using the following
+options. They follow the standard ignorelist semantic.
+.PP
+\&\fBNote:\fR To get this data the collectd user needs the
+\&\fIapi-perf-object-get-instances\fR capability.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect volume performance data every \fISeconds\fR seconds.
+.IP "\fBGetIO\fR \fIVolume\fR" 4
+.IX Item "GetIO Volume"
+.PD 0
+.IP "\fBGetOps\fR \fIVolume\fR" 4
+.IX Item "GetOps Volume"
+.IP "\fBGetLatency\fR \fIVolume\fR" 4
+.IX Item "GetLatency Volume"
+.PD
+Select the given volume for \s-1IO,\s0 operations or latency statistics collection.
+The argument is the name of the volume without the \f(CW\*(C`/vol/\*(C'\fR prefix.
+.Sp
+Since the standard ignorelist functionality is used here, you can use a string
+starting and ending with a slash to specify regular expression matching: To
+match the volumes \*(L"vol0\*(R", \*(L"vol2\*(R" and \*(L"vol7\*(R", you can use this regular
+expression:
+.Sp
+.Vb 1
+\&  GetIO "/^vol[027]$/"
+.Ve
+.Sp
+If no regular expression is specified, an exact match is required. Both,
+regular and exact matching are case sensitive.
+.Sp
+If no volume was specified at all for either of the three options, that data
+will be collected for all available volumes.
+.IP "\fBIgnoreSelectedIO\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelectedIO true|false"
+.PD 0
+.IP "\fBIgnoreSelectedOps\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelectedOps true|false"
+.IP "\fBIgnoreSelectedLatency\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelectedLatency true|false"
+.PD
+When set to \fBtrue\fR, the volumes selected for \s-1IO,\s0 operations or latency
+statistics collection will be ignored and the data will be collected for all
+other volumes.
+.Sp
+When set to \fBfalse\fR, data will only be collected for the specified volumes and
+all other volumes will be ignored.
+.Sp
+If no volumes have been specified with the above \fBGet*\fR options, all volumes
+will be collected regardless of the \fBIgnoreSelected*\fR option.
+.Sp
+Defaults to \fBfalse\fR
+.PP
+\fIThe VolumeUsage block\fR
+.IX Subsection "The VolumeUsage block"
+.PP
+This will collect capacity data about the individual volumes.
+.PP
+\&\fBNote:\fR To get this data the collectd user needs the \fIapi-volume-list-info\fR
+capability.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect volume usage statistics every \fISeconds\fR seconds.
+.IP "\fBGetCapacity\fR \fIVolumeName\fR" 4
+.IX Item "GetCapacity VolumeName"
+The current capacity of the volume will be collected. This will result in two
+to four value lists, depending on the configuration of the volume. All data
+sources are of type \*(L"df_complex\*(R" with the name of the volume as
+plugin_instance.
+.Sp
+There will be type_instances \*(L"used\*(R" and \*(L"free\*(R" for the number of used and
+available bytes on the volume.  If the volume has some space reserved for
+snapshots, a type_instance \*(L"snap_reserved\*(R" will be available.  If the volume
+has \s-1SIS\s0 enabled, a type_instance \*(L"sis_saved\*(R" will be available. This is the
+number of bytes saved by the \s-1SIS\s0 feature.
+.Sp
+\&\fBNote:\fR The current NetApp \s-1API\s0 has a bug that results in this value being
+reported as a 32\ bit number. This plugin tries to guess the correct
+number which works most of the time.  If you see strange values here, bug
+NetApp support to fix this.
+.Sp
+Repeat this option to specify multiple volumes.
+.IP "\fBIgnoreSelectedCapacity\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelectedCapacity true|false"
+Specify whether to collect only the volumes selected by the \fBGetCapacity\fR
+option or to ignore those volumes. \fBIgnoreSelectedCapacity\fR defaults to
+\&\fBfalse\fR. However, if no \fBGetCapacity\fR option is specified at all, all
+capacities will be selected anyway.
+.IP "\fBGetSnapshot\fR \fIVolumeName\fR" 4
+.IX Item "GetSnapshot VolumeName"
+Select volumes from which to collect snapshot information.
+.Sp
+Usually, the space used for snapshots is included in the space reported as
+\&\*(L"used\*(R". If snapshot information is collected as well, the space used for
+snapshots is subtracted from the used space.
+.Sp
+To make things even more interesting, it is possible to reserve space to be
+used for snapshots. If the space required for snapshots is less than that
+reserved space, there is \*(L"reserved free\*(R" and \*(L"reserved used\*(R" space in addition
+to \*(L"free\*(R" and \*(L"used\*(R". If the space required for snapshots exceeds the reserved
+space, that part allocated in the normal space is subtracted from the \*(L"used\*(R"
+space again.
+.Sp
+Repeat this option to specify multiple volumes.
+.IP "\fBIgnoreSelectedSnapshot\fR" 4
+.IX Item "IgnoreSelectedSnapshot"
+Specify whether to collect only the volumes selected by the \fBGetSnapshot\fR
+option or to ignore those volumes. \fBIgnoreSelectedSnapshot\fR defaults to
+\&\fBfalse\fR. However, if no \fBGetSnapshot\fR option is specified at all, all
+capacities will be selected anyway.
+.PP
+\fIThe Quota block\fR
+.IX Subsection "The Quota block"
+.PP
+This will collect (tree) quota statistics (used disk space and number of used
+files). This mechanism is useful to get usage information for single qtrees.
+In case the quotas are not used for any other purpose, an entry similar to the
+following in \f(CW\*(C`/etc/quotas\*(C'\fR would be sufficient:
+.PP
+.Vb 1
+\&  /vol/volA/some_qtree tree \- \- \- \- \-
+.Ve
+.PP
+After adding the entry, issue \f(CW\*(C`quota on \-w volA\*(C'\fR on the NetApp filer.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect SnapVault(R) statistics every \fISeconds\fR seconds.
+.PP
+\fIThe SnapVault block\fR
+.IX Subsection "The SnapVault block"
+.PP
+This will collect statistics about the time and traffic of SnapVault(R)
+transfers.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Collect SnapVault(R) statistics every \fISeconds\fR seconds.
+.ie n .SS "Plugin ""netlink"""
+.el .SS "Plugin \f(CWnetlink\fP"
+.IX Subsection "Plugin netlink"
+The \f(CW\*(C`netlink\*(C'\fR plugin uses a netlink socket to query the Linux kernel about
+statistics of various interface and routing aspects.
+.IP "\fBInterface\fR \fIInterface\fR" 4
+.IX Item "Interface Interface"
+.PD 0
+.IP "\fBVerboseInterface\fR \fIInterface\fR" 4
+.IX Item "VerboseInterface Interface"
+.PD
+Instruct the plugin to collect interface statistics. This is basically the same
+as the statistics provided by the \f(CW\*(C`interface\*(C'\fR plugin (see above) but
+potentially much more detailed.
+.Sp
+When configuring with \fBInterface\fR only the basic statistics will be collected,
+namely octets, packets, and errors. These statistics are collected by
+the \f(CW\*(C`interface\*(C'\fR plugin, too, so using both at the same time is no benefit.
+.Sp
+When configured with \fBVerboseInterface\fR all counters \fBexcept\fR the basic ones,
+so that no data needs to be collected twice if you use the \f(CW\*(C`interface\*(C'\fR plugin.
+This includes dropped packets, received multicast packets, collisions and a
+whole zoo of differentiated \s-1RX\s0 and \s-1TX\s0 errors. You can try the following command
+to get an idea of what awaits you:
+.Sp
+.Vb 1
+\&  ip \-s \-s link list
+.Ve
+.Sp
+If \fIInterface\fR is \fBAll\fR, all interfaces will be selected.
+.IP "\fBQDisc\fR \fIInterface\fR [\fIQDisc\fR]" 4
+.IX Item "QDisc Interface [QDisc]"
+.PD 0
+.IP "\fBClass\fR \fIInterface\fR [\fIClass\fR]" 4
+.IX Item "Class Interface [Class]"
+.IP "\fBFilter\fR \fIInterface\fR [\fIFilter\fR]" 4
+.IX Item "Filter Interface [Filter]"
+.PD
+Collect the octets and packets that pass a certain qdisc, class or filter.
+.Sp
+QDiscs and classes are identified by their type and handle (or classid).
+Filters don't necessarily have a handle, therefore the parent's handle is used.
+The notation used in collectd differs from that used in \fItc\fR\|(1) in that it
+doesn't skip the major or minor number if it's zero and doesn't print special
+ids by their name. So, for example, a qdisc may be identified by
+\&\f(CW\*(C`pfifo_fast\-1:0\*(C'\fR even though the minor number of \fBall\fR qdiscs is zero and
+thus not displayed by \fItc\fR\|(1).
+.Sp
+If \fBQDisc\fR, \fBClass\fR, or \fBFilter\fR is given without the second argument,
+i.\ .e. without an identifier, all qdiscs, classes, or filters that are
+associated with that interface will be collected.
+.Sp
+Since a filter itself doesn't necessarily have a handle, the parent's handle is
+used. This may lead to problems when more than one filter is attached to a
+qdisc or class. This isn't nice, but we don't know how this could be done any
+better. If you have a idea, please don't hesitate to tell us.
+.Sp
+As with the \fBInterface\fR option you can specify \fBAll\fR as the interface,
+meaning all interfaces.
+.Sp
+Here are some examples to help you understand the above text more easily:
+.Sp
+.Vb 7
+\&  <Plugin netlink>
+\&    VerboseInterface "All"
+\&    QDisc "eth0" "pfifo_fast\-1:0"
+\&    QDisc "ppp0"
+\&    Class "ppp0" "htb\-1:10"
+\&    Filter "ppp0" "u32\-1:0"
+\&  </Plugin>
+.Ve
+.IP "\fBIgnoreSelected\fR" 4
+.IX Item "IgnoreSelected"
+The behavior is the same as with all other similar plugins: If nothing is
+selected at all, everything is collected. If some things are selected using the
+options described above, only these statistics are collected. If you set
+\&\fBIgnoreSelected\fR to \fBtrue\fR, this behavior is inverted, i.\ e. the
+specified statistics will not be collected.
+.ie n .SS "Plugin ""network"""
+.el .SS "Plugin \f(CWnetwork\fP"
+.IX Subsection "Plugin network"
+The Network plugin sends data to a remote instance of collectd, receives data
+from a remote instance, or both at the same time. Data which has been received
+from the network is usually not transmitted again, but this can be activated, see
+the \fBForward\fR option below.
+.PP
+The default IPv6 multicast group is \f(CW\*(C`ff18::efc0:4a42\*(C'\fR. The default IPv4
+multicast group is \f(CW239.192.74.66\fR. The default \fI\s-1UDP\s0\fR port is \fB25826\fR.
+.PP
+Both, \fBServer\fR and \fBListen\fR can be used as single option or as block. When
+used as block, given options are valid for this socket only. The following
+example will export the metrics twice: Once to an \*(L"internal\*(R" server (without
+encryption and signing) and one to an external server (with cryptographic
+signature):
+.PP
+.Vb 4
+\& <Plugin "network">
+\&   # Export to an internal server
+\&   # (demonstrates usage without additional options)
+\&   Server "collectd.internal.tld"
+\&
+\&   # Export to an external server
+\&   # (demonstrates usage with signature options)
+\&   <Server "collectd.external.tld">
+\&     SecurityLevel "sign"
+\&     Username "myhostname"
+\&     Password "ohl0eQue"
+\&   </Server>
+\& </Plugin>
+.Ve
+.IP "\fB<Server\fR \fIHost\fR [\fIPort\fR]\fB>\fR" 4
+.IX Item "<Server Host [Port]>"
+The \fBServer\fR statement/block sets the server to send datagrams to. The
+statement may occur multiple times to send each datagram to multiple
+destinations.
+.Sp
+The argument \fIHost\fR may be a hostname, an IPv4 address or an IPv6 address. The
+optional second argument specifies a port number or a service name. If not
+given, the default, \fB25826\fR, is used.
+.Sp
+The following options are recognized within \fBServer\fR blocks:
+.RS 4
+.IP "\fBSecurityLevel\fR \fBEncrypt\fR|\fBSign\fR|\fBNone\fR" 4
+.IX Item "SecurityLevel Encrypt|Sign|None"
+Set the security you require for network communication. When the security level
+has been set to \fBEncrypt\fR, data sent over the network will be encrypted using
+\&\fI\s-1AES\-256\s0\fR. The integrity of encrypted packets is ensured using \fI\s-1SHA\-1\s0\fR. When
+set to \fBSign\fR, transmitted data is signed using the \fI\s-1HMAC\-SHA\-256\s0\fR message
+authentication code. When set to \fBNone\fR, data is sent without any security.
+.Sp
+This feature is only available if the \fInetwork\fR plugin was linked with
+\&\fIlibgcrypt\fR.
+.IP "\fBUsername\fR \fIUsername\fR" 4
+.IX Item "Username Username"
+Sets the username to transmit. This is used by the server to lookup the
+password. See \fBAuthFile\fR below. All security levels except \fBNone\fR require
+this setting.
+.Sp
+This feature is only available if the \fInetwork\fR plugin was linked with
+\&\fIlibgcrypt\fR.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Sets a password (shared secret) for this socket. All security levels except
+\&\fBNone\fR require this setting.
+.Sp
+This feature is only available if the \fInetwork\fR plugin was linked with
+\&\fIlibgcrypt\fR.
+.IP "\fBInterface\fR \fIInterface name\fR" 4
+.IX Item "Interface Interface name"
+Set the outgoing interface for \s-1IP\s0 packets. This applies at least
+to IPv6 packets and if possible to IPv4. If this option is not applicable,
+undefined or a non-existent interface name is specified, the default
+behavior is to let the kernel choose the appropriate interface. Be warned
+that the manual selection of an interface for unicast traffic is only
+necessary in rare cases.
+.IP "\fBResolveInterval\fR \fISeconds\fR" 4
+.IX Item "ResolveInterval Seconds"
+Sets the interval at which to re-resolve the \s-1DNS\s0 for the \fIHost\fR. This is
+useful to force a regular \s-1DNS\s0 lookup to support a high availability setup. If
+not specified, re-resolves are never attempted.
+.RE
+.RS 4
+.RE
+.IP "\fB<Listen\fR \fIHost\fR [\fIPort\fR]\fB>\fR" 4
+.IX Item "<Listen Host [Port]>"
+The \fBListen\fR statement sets the interfaces to bind to. When multiple
+statements are found the daemon will bind to multiple interfaces.
+.Sp
+The argument \fIHost\fR may be a hostname, an IPv4 address or an IPv6 address. If
+the argument is a multicast address the daemon will join that multicast group.
+The optional second argument specifies a port number or a service name. If not
+given, the default, \fB25826\fR, is used.
+.Sp
+The following options are recognized within \f(CW\*(C`<Listen>\*(C'\fR blocks:
+.RS 4
+.IP "\fBSecurityLevel\fR \fBEncrypt\fR|\fBSign\fR|\fBNone\fR" 4
+.IX Item "SecurityLevel Encrypt|Sign|None"
+Set the security you require for network communication. When the security level
+has been set to \fBEncrypt\fR, only encrypted data will be accepted. The integrity
+of encrypted packets is ensured using \fI\s-1SHA\-1\s0\fR. When set to \fBSign\fR, only
+signed and encrypted data is accepted. When set to \fBNone\fR, all data will be
+accepted. If an \fBAuthFile\fR option was given (see below), encrypted data is
+decrypted if possible.
+.Sp
+This feature is only available if the \fInetwork\fR plugin was linked with
+\&\fIlibgcrypt\fR.
+.IP "\fBAuthFile\fR \fIFilename\fR" 4
+.IX Item "AuthFile Filename"
+Sets a file in which usernames are mapped to passwords. These passwords are
+used to verify signatures and to decrypt encrypted network packets. If
+\&\fBSecurityLevel\fR is set to \fBNone\fR, this is optional. If given, signed data is
+verified and encrypted packets are decrypted. Otherwise, signed data is
+accepted without checking the signature and encrypted data cannot be decrypted.
+For the other security levels this option is mandatory.
+.Sp
+The file format is very simple: Each line consists of a username followed by a
+colon and any number of spaces followed by the password. To demonstrate, an
+example file could look like this:
+.Sp
+.Vb 2
+\&  user0: foo
+\&  user1: bar
+.Ve
+.Sp
+Each time a packet is received, the modification time of the file is checked
+using \fIstat\fR\|(2). If the file has been changed, the contents is re-read. While
+the file is being read, it is locked using \fIfcntl\fR\|(2).
+.IP "\fBInterface\fR \fIInterface name\fR" 4
+.IX Item "Interface Interface name"
+Set the incoming interface for \s-1IP\s0 packets explicitly. This applies at least
+to IPv6 packets and if possible to IPv4. If this option is not applicable,
+undefined or a non-existent interface name is specified, the default
+behavior is, to let the kernel choose the appropriate interface. Thus incoming
+traffic gets only accepted, if it arrives on the given interface.
+.RE
+.RS 4
+.RE
+.IP "\fBTimeToLive\fR \fI1\-255\fR" 4
+.IX Item "TimeToLive 1-255"
+Set the time-to-live of sent packets. This applies to all, unicast and
+multicast, and IPv4 and IPv6 packets. The default is to not change this value.
+That means that multicast packets will be sent with a \s-1TTL\s0 of \f(CW1\fR (one) on most
+operating systems.
+.IP "\fBMaxPacketSize\fR \fI1024\-65535\fR" 4
+.IX Item "MaxPacketSize 1024-65535"
+Set the maximum size for datagrams received over the network. Packets larger
+than this will be truncated. Defaults to 1452\ bytes, which is the maximum
+payload size that can be transmitted in one Ethernet frame using IPv6\ /
+\&\s-1UDP.\s0
+.Sp
+On the server side, this limit should be set to the largest value used on
+\&\fIany\fR client. Likewise, the value on the client must not be larger than the
+value on the server, or data will be lost.
+.Sp
+\&\fBCompatibility:\fR Versions prior to \fIversion\ 4.8\fR used a fixed sized
+buffer of 1024\ bytes. Versions \fI4.8\fR, \fI4.9\fR and \fI4.10\fR used a default
+value of 1024\ bytes to avoid problems when sending data to an older
+server.
+.IP "\fBForward\fR \fItrue|false\fR" 4
+.IX Item "Forward true|false"
+If set to \fItrue\fR, write packets that were received via the network plugin to
+the sending sockets. This should only be activated when the \fBListen\fR\- and
+\&\fBServer\fR\-statements differ. Otherwise packets may be send multiple times to
+the same multicast group. While this results in more network traffic than
+necessary it's not a huge problem since the plugin has a duplicate detection,
+so the values will not loop.
+.IP "\fBReportStats\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ReportStats true|false"
+The network plugin cannot only receive and send statistics, it can also create
+statistics about itself. Collected data included the number of received and
+sent octets and packets, the length of the receive queue and the number of
+values handled. When set to \fBtrue\fR, the \fINetwork plugin\fR will make these
+statistics available. Defaults to \fBfalse\fR.
+.ie n .SS "Plugin ""nginx"""
+.el .SS "Plugin \f(CWnginx\fP"
+.IX Subsection "Plugin nginx"
+This plugin collects the number of connections and requests handled by the
+\&\f(CW\*(C`nginx daemon\*(C'\fR (speak: engine\ X), a \s-1HTTP\s0 and mail server/proxy. It
+queries the page provided by the \f(CW\*(C`ngx_http_stub_status_module\*(C'\fR module, which
+isn't compiled by default. Please refer to
+<http://wiki.codemongers.com/NginxStubStatusModule> for more information on
+how to compile and configure nginx and this module.
+.PP
+The following options are accepted by the \f(CW\*(C`nginx plugin\*(C'\fR:
+.IP "\fB\s-1URL\s0\fR \fIhttp://host/nginx_status\fR" 4
+.IX Item "URL http://host/nginx_status"
+Sets the \s-1URL\s0 of the \f(CW\*(C`ngx_http_stub_status_module\*(C'\fR output.
+.IP "\fBUser\fR \fIUsername\fR" 4
+.IX Item "User Username"
+Optional user name needed for authentication.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Optional password needed for authentication.
+.IP "\fBVerifyPeer\fR \fBtrue|false\fR" 4
+.IX Item "VerifyPeer true|false"
+Enable or disable peer \s-1SSL\s0 certificate verification. See
+<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+.IP "\fBVerifyHost\fR \fBtrue|false\fR" 4
+.IX Item "VerifyHost true|false"
+Enable or disable peer host name verification. If enabled, the plugin checks
+if the \f(CW\*(C`Common Name\*(C'\fR or a \f(CW\*(C`Subject Alternate Name\*(C'\fR field of the \s-1SSL\s0
+certificate matches the host name provided by the \fB\s-1URL\s0\fR option. If this
+identity check fails, the connection is aborted. Obviously, only works when
+connecting to a \s-1SSL\s0 enabled server. Enabled by default.
+.IP "\fBCACert\fR \fIFile\fR" 4
+.IX Item "CACert File"
+File that holds one or more \s-1SSL\s0 certificates. If you want to use \s-1HTTPS\s0 you will
+possibly need this option. What \s-1CA\s0 certificates come bundled with \f(CW\*(C`libcurl\*(C'\fR
+and are checked by default depends on the distribution you use.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+The \fBTimeout\fR option sets the overall timeout for \s-1HTTP\s0 requests to \fB\s-1URL\s0\fR, in
+milliseconds. By default, the configured \fBInterval\fR is used to set the
+timeout.
+.ie n .SS "Plugin ""notify_desktop"""
+.el .SS "Plugin \f(CWnotify_desktop\fP"
+.IX Subsection "Plugin notify_desktop"
+This plugin sends a desktop notification to a notification daemon, as defined
+in the Desktop Notification Specification. To actually display the
+notifications, \fBnotification-daemon\fR is required and \fBcollectd\fR has to be
+able to access the X server (i.\ e., the \f(CW\*(C`DISPLAY\*(C'\fR and \f(CW\*(C`XAUTHORITY\*(C'\fR
+environment variables have to be set correctly) and the D\-Bus message bus.
+.PP
+The Desktop Notification Specification can be found at
+<http://www.galago\-project.org/specs/notification/>.
+.IP "\fBOkayTimeout\fR \fItimeout\fR" 4
+.IX Item "OkayTimeout timeout"
+.PD 0
+.IP "\fBWarningTimeout\fR \fItimeout\fR" 4
+.IX Item "WarningTimeout timeout"
+.IP "\fBFailureTimeout\fR \fItimeout\fR" 4
+.IX Item "FailureTimeout timeout"
+.PD
+Set the \fItimeout\fR, in milliseconds, after which to expire the notification
+for \f(CW\*(C`OKAY\*(C'\fR, \f(CW\*(C`WARNING\*(C'\fR and \f(CW\*(C`FAILURE\*(C'\fR severities respectively. If zero has
+been specified, the displayed notification will not be closed at all \- the
+user has to do so herself. These options default to 5000. If a negative number
+has been specified, the default is used as well.
+.ie n .SS "Plugin ""notify_email"""
+.el .SS "Plugin \f(CWnotify_email\fP"
+.IX Subsection "Plugin notify_email"
+The \fInotify_email\fR plugin uses the \fI\s-1ESMTP\s0\fR library to send notifications to a
+configured email address.
+.PP
+\&\fIlibESMTP\fR is available from <http://www.stafford.uklinux.net/libesmtp/>.
+.PP
+Available configuration options:
+.IP "\fBFrom\fR \fIAddress\fR" 4
+.IX Item "From Address"
+Email address from which the emails should appear to come from.
+.Sp
+Default: \f(CW\*(C`root@localhost\*(C'\fR
+.IP "\fBRecipient\fR \fIAddress\fR" 4
+.IX Item "Recipient Address"
+Configures the email address(es) to which the notifications should be mailed.
+May be repeated to send notifications to multiple addresses.
+.Sp
+At least one \fBRecipient\fR must be present for the plugin to work correctly.
+.IP "\fBSMTPServer\fR \fIHostname\fR" 4
+.IX Item "SMTPServer Hostname"
+Hostname of the \s-1SMTP\s0 server to connect to.
+.Sp
+Default: \f(CW\*(C`localhost\*(C'\fR
+.IP "\fBSMTPPort\fR \fIPort\fR" 4
+.IX Item "SMTPPort Port"
+\&\s-1TCP\s0 port to connect to.
+.Sp
+Default: \f(CW25\fR
+.IP "\fBSMTPUser\fR \fIUsername\fR" 4
+.IX Item "SMTPUser Username"
+Username for \s-1ASMTP\s0 authentication. Optional.
+.IP "\fBSMTPPassword\fR \fIPassword\fR" 4
+.IX Item "SMTPPassword Password"
+Password for \s-1ASMTP\s0 authentication. Optional.
+.IP "\fBSubject\fR \fISubject\fR" 4
+.IX Item "Subject Subject"
+Subject-template to use when sending emails. There must be exactly two
+string-placeholders in the subject, given in the standard \fI\fIprintf\fI\|(3)\fR syntax,
+i.\ e. \f(CW%s\fR. The first will be replaced with the severity, the second
+with the hostname.
+.Sp
+Default: \f(CW\*(C`Collectd notify: %s@%s\*(C'\fR
+.ie n .SS "Plugin ""ntpd"""
+.el .SS "Plugin \f(CWntpd\fP"
+.IX Subsection "Plugin ntpd"
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+Hostname of the host running \fBntpd\fR. Defaults to \fBlocalhost\fR.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+UDP-Port to connect to. Defaults to \fB123\fR.
+.IP "\fBReverseLookups\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ReverseLookups true|false"
+Sets whether or not to perform reverse lookups on peers. Since the name or
+IP-address may be used in a filename it is recommended to disable reverse
+lookups. The default is to do reverse lookups to preserve backwards
+compatibility, though.
+.IP "\fBIncludeUnitID\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IncludeUnitID true|false"
+When a peer is a refclock, include the unit \s-1ID\s0 in the \fItype instance\fR.
+Defaults to \fBfalse\fR for backward compatibility.
+.Sp
+If two refclock peers use the same driver and this is \fBfalse\fR, the plugin will
+try to write simultaneous measurements from both to the same type instance.
+This will result in error messages in the log and only one set of measurements
+making it through.
+.ie n .SS "Plugin ""nut"""
+.el .SS "Plugin \f(CWnut\fP"
+.IX Subsection "Plugin nut"
+.IP "\fB\s-1UPS\s0\fR \fIupsname\fR\fB@\fR\fIhostname\fR[\fB:\fR\fIport\fR]" 4
+.IX Item "UPS upsname@hostname[:port]"
+Add a \s-1UPS\s0 to collect data from. The format is identical to the one accepted by
+\&\fIupsc\fR\|(8).
+.ie n .SS "Plugin ""olsrd"""
+.el .SS "Plugin \f(CWolsrd\fP"
+.IX Subsection "Plugin olsrd"
+The \fIolsrd\fR plugin connects to the \s-1TCP\s0 port opened by the \fItxtinfo\fR plugin of
+the Optimized Link State Routing daemon and reads information about the current
+state of the meshed network.
+.PP
+The following configuration options are understood:
+.IP "\fBHost\fR \fIHost\fR" 4
+.IX Item "Host Host"
+Connect to \fIHost\fR. Defaults to \fB\*(L"localhost\*(R"\fR.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+Specifies the port to connect to. This must be a string, even if you give the
+port as a number rather than a service name. Defaults to \fB\*(L"2006\*(R"\fR.
+.IP "\fBCollectLinks\fR \fBNo\fR|\fBSummary\fR|\fBDetail\fR" 4
+.IX Item "CollectLinks No|Summary|Detail"
+Specifies what information to collect about links, i.\ e. direct
+connections of the daemon queried. If set to \fBNo\fR, no information is
+collected. If set to \fBSummary\fR, the number of links and the average of all
+\&\fIlink quality\fR (\s-1LQ\s0) and \fIneighbor link quality\fR (\s-1NLQ\s0) values is calculated.
+If set to \fBDetail\fR \s-1LQ\s0 and \s-1NLQ\s0 are collected per link.
+.Sp
+Defaults to \fBDetail\fR.
+.IP "\fBCollectRoutes\fR \fBNo\fR|\fBSummary\fR|\fBDetail\fR" 4
+.IX Item "CollectRoutes No|Summary|Detail"
+Specifies what information to collect about routes of the daemon queried. If
+set to \fBNo\fR, no information is collected. If set to \fBSummary\fR, the number of
+routes and the average \fImetric\fR and \fI\s-1ETX\s0\fR is calculated. If set to \fBDetail\fR
+metric and \s-1ETX\s0 are collected per route.
+.Sp
+Defaults to \fBSummary\fR.
+.IP "\fBCollectTopology\fR \fBNo\fR|\fBSummary\fR|\fBDetail\fR" 4
+.IX Item "CollectTopology No|Summary|Detail"
+Specifies what information to collect about the global topology. If set to
+\&\fBNo\fR, no information is collected. If set to \fBSummary\fR, the number of links
+in the entire topology and the average \fIlink quality\fR (\s-1LQ\s0) is calculated.
+If set to \fBDetail\fR \s-1LQ\s0 and \s-1NLQ\s0 are collected for each link in the entire topology.
+.Sp
+Defaults to \fBSummary\fR.
+.ie n .SS "Plugin ""onewire"""
+.el .SS "Plugin \f(CWonewire\fP"
+.IX Subsection "Plugin onewire"
+\&\fB\s-1EXPERIMENTAL\s0!\fR See notes below.
+.PP
+The \f(CW\*(C`onewire\*(C'\fR plugin uses the \fBowcapi\fR library from the \fBowfs\fR project
+<http://owfs.org/> to read sensors connected via the onewire bus.
+.PP
+It can be used in two possible modes \- standard or advanced.
+.PP
+In the standard mode only temperature sensors (sensors with the family code
+\&\f(CW10\fR, \f(CW22\fR and \f(CW28\fR \- e.g. \s-1DS1820, DS18S20, DS1920\s0) can be read. If you have
+other sensors you would like to have included, please send a sort request to
+the mailing list. You can select sensors to be read or to be ignored depending
+on the option \fBIgnoreSelected\fR). When no list is provided the whole bus is
+walked and all sensors are read.
+.PP
+Hubs (the \s-1DS2409\s0 chips) are working, but read the note, why this plugin is
+experimental, below.
+.PP
+In the advanced mode you can configure any sensor to be read (only numerical
+value) using full \s-1OWFS\s0 path (e.g. \*(L"/uncached/10.F10FCA000800/temperature\*(R").
+In this mode you have to list all the sensors. Neither default bus walk nor
+\&\fBIgnoreSelected\fR are used here. Address and type (file) is extracted from
+the path automatically and should produce compatible structure with the \*(L"standard\*(R"
+mode (basically the path is expected as for example
+\&\*(L"/uncached/10.F10FCA000800/temperature\*(R" where it would extract address part
+\&\*(L"F10FCA000800\*(R" and the rest after the slash is considered the type \- here
+\&\*(L"temperature\*(R").
+There are two advantages to this mode \- you can access virtually any sensor
+(not just temperature), select whether to use cached or directly read values
+and it is slighlty faster. The downside is more complex configuration.
+.PP
+The two modes are distinguished automatically by the format of the address.
+It is not possible to mix the two modes. Once a full path is detected in any
+\&\fBSensor\fR then the whole addressing (all sensors) is considered to be this way
+(and as standard addresses will fail parsing they will be ignored).
+.IP "\fBDevice\fR \fIDevice\fR" 4
+.IX Item "Device Device"
+Sets the device to read the values from. This can either be a \*(L"real\*(R" hardware
+device, such as a serial port or an \s-1USB\s0 port, or the address of the
+\&\fIowserver\fR\|(1) socket, usually \fBlocalhost:4304\fR.
+.Sp
+Though the documentation claims to automatically recognize the given address
+format, with version\ 2.7p4 we had to specify the type explicitly. So
+with that version, the following configuration worked for us:
+.Sp
+.Vb 3
+\&  <Plugin onewire>
+\&    Device "\-s localhost:4304"
+\&  </Plugin>
+.Ve
+.Sp
+This directive is \fBrequired\fR and does not have a default value.
+.IP "\fBSensor\fR \fISensor\fR" 4
+.IX Item "Sensor Sensor"
+In the standard mode selects sensors to collect or to ignore
+(depending on \fBIgnoreSelected\fR, see below). Sensors are specified without
+the family byte at the beginning, so you have to use for example \f(CW\*(C`F10FCA000800\*(C'\fR,
+and \fBnot\fR include the leading \f(CW10.\fR family byte and point.
+When no \fBSensor\fR is configured the whole Onewire bus is walked and all supported
+sensors (see above) are read.
+.Sp
+In the advanced mode the \fBSensor\fR specifies full \s-1OWFS\s0 path \- e.g.
+\&\f(CW\*(C`/uncached/10.F10FCA000800/temperature\*(C'\fR (or when cached values are \s-1OK
+\&\s0\f(CW\*(C`/10.F10FCA000800/temperature\*(C'\fR). \fBIgnoreSelected\fR is not used.
+.Sp
+As there can be multiple devices on the bus you can list multiple sensor (use
+multiple \fBSensor\fR elements).
+.IP "\fBIgnoreSelected\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+If no configuration is given, the \fBonewire\fR plugin will collect data from all
+sensors found. This may not be practical, especially if sensors are added and
+removed regularly. Sometimes, however, it's easier/preferred to collect only
+specific sensors or all sensors \fIexcept\fR a few specified ones. This option
+enables you to do that: By setting \fBIgnoreSelected\fR to \fItrue\fR the effect of
+\&\fBSensor\fR is inverted: All selected interfaces are ignored and all other
+interfaces are collected.
+.Sp
+Used only in the standard mode \- see above.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Sets the interval in which all sensors should be read. If not specified, the
+global \fBInterval\fR setting is used.
+.PP
+\&\fB\s-1EXPERIMENTAL\s0!\fR The \f(CW\*(C`onewire\*(C'\fR plugin is experimental, because it doesn't yet
+work with big setups. It works with one sensor being attached to one
+controller, but as soon as you throw in a couple more senors and maybe a hub
+or two, reading all values will take more than ten seconds (the default
+interval). We will probably add some separate thread for reading the sensors
+and some cache or something like that, but it's not done yet. We will try to
+maintain backwards compatibility in the future, but we can't promise. So in
+short: If it works for you: Great! But keep in mind that the config \fImight\fR
+change, though this is unlikely. Oh, and if you want to help improving this
+plugin, just send a short notice to the mailing list. Thanks\ :)
+.ie n .SS "Plugin ""openldap"""
+.el .SS "Plugin \f(CWopenldap\fP"
+.IX Subsection "Plugin openldap"
+To use the \f(CW\*(C`openldap\*(C'\fR plugin you first need to configure the \fIOpenLDAP\fR
+server correctly. The backend database \f(CW\*(C`monitor\*(C'\fR needs to be loaded and
+working. See \fIslapd\-monitor\fR\|(5) for the details.
+.PP
+The configuration of the \f(CW\*(C`openldap\*(C'\fR plugin consists of one or more \fBInstance\fR
+blocks. Each block requires one string argument as the instance name. For
+example:
+.PP
+.Vb 8
+\& <Plugin "openldap">
+\&   <Instance "foo">
+\&     URL "ldap://localhost/"
+\&   </Instance>
+\&   <Instance "bar">
+\&     URL "ldaps://localhost/"
+\&   </Instance>
+\& </Plugin>
+.Ve
+.PP
+The instance name will be used as the \fIplugin instance\fR. To emulate the old
+(version\ 4) behavior, you can use an empty string (""). In order for the
+plugin to work correctly, each instance name must be unique. This is not
+enforced by the plugin and it is your responsibility to ensure it is.
+.PP
+The following options are accepted within each \fBInstance\fR block:
+.IP "\fB\s-1URL\s0\fR \fIldap://host/binddn\fR" 4
+.IX Item "URL ldap://host/binddn"
+Sets the \s-1URL\s0 to use to connect to the \fIOpenLDAP\fR server. This option is
+\&\fImandatory\fR.
+.IP "\fBStartTLS\fR \fBtrue|false\fR" 4
+.IX Item "StartTLS true|false"
+Defines whether \s-1TLS\s0 must be used when connecting to the \fIOpenLDAP\fR server.
+Disabled by default.
+.IP "\fBVerifyHost\fR \fBtrue|false\fR" 4
+.IX Item "VerifyHost true|false"
+Enables or disables peer host name verification. If enabled, the plugin checks
+if the \f(CW\*(C`Common Name\*(C'\fR or a \f(CW\*(C`Subject Alternate Name\*(C'\fR field of the \s-1SSL\s0
+certificate matches the host name provided by the \fB\s-1URL\s0\fR option. If this
+identity check fails, the connection is aborted. Enabled by default.
+.IP "\fBCACert\fR \fIFile\fR" 4
+.IX Item "CACert File"
+File that holds one or more \s-1SSL\s0 certificates. If you want to use \s-1TLS/SSL\s0 you
+may possibly need this option. What \s-1CA\s0 certificates are checked by default
+depends on the distribution you use and can be changed with the usual ldap
+client configuration mechanisms. See \fIldap.conf\fR\|(5) for the details.
+.IP "\fBTimeout\fR \fISeconds\fR" 4
+.IX Item "Timeout Seconds"
+Sets the timeout value for ldap operations. Defaults to \fB\-1\fR which results in
+an infinite timeout.
+.IP "\fBVersion\fR \fIVersion\fR" 4
+.IX Item "Version Version"
+An integer which sets the \s-1LDAP\s0 protocol version number to use when connecting
+to the \fIOpenLDAP\fR server. Defaults to \fB3\fR for using \fILDAPv3\fR.
+.ie n .SS "Plugin ""openvpn"""
+.el .SS "Plugin \f(CWopenvpn\fP"
+.IX Subsection "Plugin openvpn"
+The OpenVPN plugin reads a status file maintained by OpenVPN and gathers
+traffic statistics about connected clients.
+.PP
+To set up OpenVPN to write to the status file periodically, use the
+\&\fB\-\-status\fR option of OpenVPN. Since OpenVPN can write two different formats,
+you need to set the required format, too. This is done by setting
+\&\fB\-\-status\-version\fR to \fB2\fR.
+.PP
+So, in a nutshell you need:
+.PP
+.Vb 3
+\&  openvpn $OTHER_OPTIONS \e
+\&    \-\-status "/var/run/openvpn\-status" 10 \e
+\&    \-\-status\-version 2
+.Ve
+.PP
+Available options:
+.IP "\fBStatusFile\fR \fIFile\fR" 4
+.IX Item "StatusFile File"
+Specifies the location of the status file.
+.IP "\fBImprovedNamingSchema\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ImprovedNamingSchema true|false"
+When enabled, the filename of the status file will be used as plugin instance
+and the client's \*(L"common name\*(R" will be used as type instance. This is required
+when reading multiple status files. Enabling this option is recommended, but to
+maintain backwards compatibility this option is disabled by default.
+.IP "\fBCollectCompression\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectCompression true|false"
+Sets whether or not statistics about the compression used by OpenVPN should be
+collected. This information is only available in \fIsingle\fR mode. Enabled by
+default.
+.IP "\fBCollectIndividualUsers\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectIndividualUsers true|false"
+Sets whether or not traffic information is collected for each connected client
+individually. If set to false, currently no traffic data is collected at all
+because aggregating this data in a save manner is tricky. Defaults to \fBtrue\fR.
+.IP "\fBCollectUserCount\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectUserCount true|false"
+When enabled, the number of currently connected clients or users is collected.
+This is especially interesting when \fBCollectIndividualUsers\fR is disabled, but
+can be configured independently from that option. Defaults to \fBfalse\fR.
+.ie n .SS "Plugin ""oracle"""
+.el .SS "Plugin \f(CWoracle\fP"
+.IX Subsection "Plugin oracle"
+The \*(L"oracle\*(R" plugin uses the OracleX Call Interface \fI(\s-1OCI\s0)\fR to connect to an
+OracleX Database and lets you execute \s-1SQL\s0 statements there. It is very similar
+to the \*(L"dbi\*(R" plugin, because it was written around the same time. See the \*(L"dbi\*(R"
+plugin's documentation above for details.
+.PP
+.Vb 10
+\&  <Plugin oracle>
+\&    <Query "out_of_stock">
+\&      Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category"
+\&      <Result>
+\&        Type "gauge"
+\&        # InstancePrefix "foo"
+\&        InstancesFrom "category"
+\&        ValuesFrom "value"
+\&      </Result>
+\&    </Query>
+\&    <Database "product_information">
+\&      ConnectID "db01"
+\&      Username "oracle"
+\&      Password "secret"
+\&      Query "out_of_stock"
+\&    </Database>
+\&  </Plugin>
+.Ve
+.PP
+\fI\f(BIQuery\fI blocks\fR
+.IX Subsection "Query blocks"
+.PP
+The Query blocks are handled identically to the Query blocks of the \*(L"dbi\*(R"
+plugin. Please see its documentation above for details on how to specify
+queries.
+.PP
+\fI\f(BIDatabase\fI blocks\fR
+.IX Subsection "Database blocks"
+.PP
+Database blocks define a connection to a database and which queries should be
+sent to that database. Each database needs a \*(L"name\*(R" as string argument in the
+starting tag of the block. This name will be used as \*(L"PluginInstance\*(R" in the
+values submitted to the daemon. Other than that, that name is not used.
+.IP "\fBConnectID\fR \fI\s-1ID\s0\fR" 4
+.IX Item "ConnectID ID"
+Defines the \*(L"database alias\*(R" or \*(L"service name\*(R" to connect to. Usually, these
+names are defined in the file named \f(CW\*(C`$ORACLE_HOME/network/admin/tnsnames.ora\*(C'\fR.
+.IP "\fBHost\fR \fIHost\fR" 4
+.IX Item "Host Host"
+Hostname to use when dispatching values for this database. Defaults to using
+the global hostname of the \fIcollectd\fR instance.
+.IP "\fBUsername\fR \fIUsername\fR" 4
+.IX Item "Username Username"
+Username used for authentication.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Password used for authentication.
+.IP "\fBQuery\fR \fIQueryName\fR" 4
+.IX Item "Query QueryName"
+Associates the query named \fIQueryName\fR with this database connection. The
+query needs to be defined \fIbefore\fR this statement, i.\ e. all query
+blocks you want to refer to must be placed above the database block you want to
+refer to them from.
+.ie n .SS "Plugin ""perl"""
+.el .SS "Plugin \f(CWperl\fP"
+.IX Subsection "Plugin perl"
+This plugin embeds a Perl-interpreter into collectd and provides an interface
+to collectd's plugin system. See \fIcollectd\-perl\fR\|(5) for its documentation.
+.ie n .SS "Plugin ""pinba"""
+.el .SS "Plugin \f(CWpinba\fP"
+.IX Subsection "Plugin pinba"
+The \fIPinba plugin\fR receives profiling information from \fIPinba\fR, an extension
+for the \fI\s-1PHP\s0\fR interpreter. At the end of executing a script, i.e. after a
+PHP-based webpage has been delivered, the extension will send a \s-1UDP\s0 packet
+containing timing information, peak memory usage and so on. The plugin will
+wait for such packets, parse them and account the provided information, which
+is then dispatched to the daemon once per interval.
+.PP
+Synopsis:
+.PP
+.Vb 10
+\& <Plugin pinba>
+\&   Address "::0"
+\&   Port "30002"
+\&   # Overall statistics for the website.
+\&   <View "www\-total">
+\&     Server "www.example.com"
+\&   </View>
+\&   # Statistics for www\-a only
+\&   <View "www\-a">
+\&     Host "www\-a.example.com"
+\&     Server "www.example.com"
+\&   </View>
+\&   # Statistics for www\-b only
+\&   <View "www\-b">
+\&     Host "www\-b.example.com"
+\&     Server "www.example.com"
+\&   </View>
+\& </Plugin>
+.Ve
+.PP
+The plugin provides the following configuration options:
+.IP "\fBAddress\fR \fINode\fR" 4
+.IX Item "Address Node"
+Configures the address used to open a listening socket. By default, plugin will
+bind to the \fIany\fR address \f(CW\*(C`::0\*(C'\fR.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+Configures the port (service) to bind to. By default the default Pinba port
+\&\*(L"30002\*(R" will be used. The option accepts service names in addition to port
+numbers and thus requires a \fIstring\fR argument.
+.IP "<\fBView\fR \fIName\fR> block" 4
+.IX Item "<View Name> block"
+The packets sent by the Pinba extension include the hostname of the server, the
+server name (the name of the virtual host) and the script that was executed.
+Using \fBView\fR blocks it is possible to separate the data into multiple groups
+to get more meaningful statistics. Each packet is added to all matching groups,
+so that a packet may be accounted for more than once.
+.RS 4
+.IP "\fBHost\fR \fIHost\fR" 4
+.IX Item "Host Host"
+Matches the hostname of the system the webserver / script is running on. This
+will contain the result of the \fIgethostname\fR\|(2) system call. If not
+configured, all hostnames will be accepted.
+.IP "\fBServer\fR \fIServer\fR" 4
+.IX Item "Server Server"
+Matches the name of the \fIvirtual host\fR, i.e. the contents of the
+\&\f(CW$_SERVER["SERVER_NAME"]\fR variable when within \s-1PHP.\s0 If not configured, all
+server names will be accepted.
+.IP "\fBScript\fR \fIScript\fR" 4
+.IX Item "Script Script"
+Matches the name of the \fIscript name\fR, i.e. the contents of the
+\&\f(CW$_SERVER["SCRIPT_NAME"]\fR variable when within \s-1PHP.\s0 If not configured, all
+script names will be accepted.
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""ping"""
+.el .SS "Plugin \f(CWping\fP"
+.IX Subsection "Plugin ping"
+The \fIPing\fR plugin starts a new thread which sends \s-1ICMP \s0\*(L"ping\*(R" packets to the
+configured hosts periodically and measures the network latency. Whenever the
+\&\f(CW\*(C`read\*(C'\fR function of the plugin is called, it submits the average latency, the
+standard deviation and the drop rate for each host.
+.PP
+Available configuration options:
+.IP "\fBHost\fR \fIIP-address\fR" 4
+.IX Item "Host IP-address"
+Host to ping periodically. This option may be repeated several times to ping
+multiple hosts.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Sets the interval in which to send \s-1ICMP\s0 echo packets to the configured hosts.
+This is \fBnot\fR the interval in which statistics are queries from the plugin but
+the interval in which the hosts are \*(L"pinged\*(R". Therefore, the setting here
+should be smaller than or equal to the global \fBInterval\fR setting. Fractional
+times, such as \*(L"1.24\*(R" are allowed.
+.Sp
+Default: \fB1.0\fR
+.IP "\fBTimeout\fR \fISeconds\fR" 4
+.IX Item "Timeout Seconds"
+Time to wait for a response from the host to which an \s-1ICMP\s0 packet had been
+sent. If a reply was not received after \fISeconds\fR seconds, the host is assumed
+to be down or the packet to be dropped. This setting must be smaller than the
+\&\fBInterval\fR setting above for the plugin to work correctly. Fractional
+arguments are accepted.
+.Sp
+Default: \fB0.9\fR
+.IP "\fB\s-1TTL\s0\fR \fI0\-255\fR" 4
+.IX Item "TTL 0-255"
+Sets the Time-To-Live of generated \s-1ICMP\s0 packets.
+.IP "\fBSourceAddress\fR \fIhost\fR" 4
+.IX Item "SourceAddress host"
+Sets the source address to use. \fIhost\fR may either be a numerical network
+address or a network hostname.
+.IP "\fBDevice\fR \fIname\fR" 4
+.IX Item "Device name"
+Sets the outgoing network device to be used. \fIname\fR has to specify an
+interface name (e.\ g. \f(CW\*(C`eth0\*(C'\fR). This might not be supported by all
+operating systems.
+.IP "\fBMaxMissed\fR \fIPackets\fR" 4
+.IX Item "MaxMissed Packets"
+Trigger a \s-1DNS\s0 resolve after the host has not replied to \fIPackets\fR packets. This
+enables the use of dynamic \s-1DNS\s0 services (like dyndns.org) with the ping plugin.
+.Sp
+Default: \fB\-1\fR (disabled)
+.ie n .SS "Plugin ""postgresql"""
+.el .SS "Plugin \f(CWpostgresql\fP"
+.IX Subsection "Plugin postgresql"
+The \f(CW\*(C`postgresql\*(C'\fR plugin queries statistics from PostgreSQL databases. It
+keeps a persistent connection to all configured databases and tries to
+reconnect if the connection has been interrupted. A database is configured by
+specifying a \fBDatabase\fR block as described below. The default statistics are
+collected from PostgreSQL's \fBstatistics collector\fR which thus has to be
+enabled for this plugin to work correctly. This should usually be the case by
+default. See the section \*(L"The Statistics Collector\*(R" of the \fBPostgreSQL
+Documentation\fR for details.
+.PP
+By specifying custom database queries using a \fBQuery\fR block as described
+below, you may collect any data that is available from some PostgreSQL
+database. This way, you are able to access statistics of external daemons
+which are available in a PostgreSQL database or use future or special
+statistics provided by PostgreSQL without the need to upgrade your collectd
+installation.
+.PP
+Starting with version 5.2, the \f(CW\*(C`postgresql\*(C'\fR plugin supports writing data to
+PostgreSQL databases as well. This has been implemented in a generic way. You
+need to specify an \s-1SQL\s0 statement which will then be executed by collectd in
+order to write the data (see below for details). The benefit of that approach
+is that there is no fixed database layout. Rather, the layout may be optimized
+for the current setup.
+.PP
+The \fBPostgreSQL Documentation\fR manual can be found at
+<http://www.postgresql.org/docs/manuals/>.
+.PP
+.Vb 10
+\&  <Plugin postgresql>
+\&    <Query magic>
+\&      Statement "SELECT magic FROM wizard WHERE host = $1;"
+\&      Param hostname
+\&      <Result>
+\&        Type gauge
+\&        InstancePrefix "magic"
+\&        ValuesFrom magic
+\&      </Result>
+\&    </Query>
+\&
+\&    <Query rt36_tickets>
+\&      Statement "SELECT COUNT(type) AS count, type \e
+\&                        FROM (SELECT CASE \e
+\&                                     WHEN resolved = \*(Aqepoch\*(Aq THEN \*(Aqopen\*(Aq \e
+\&                                     ELSE \*(Aqresolved\*(Aq END AS type \e
+\&                                     FROM tickets) type \e
+\&                        GROUP BY type;"
+\&      <Result>
+\&        Type counter
+\&        InstancePrefix "rt36_tickets"
+\&        InstancesFrom "type"
+\&        ValuesFrom "count"
+\&      </Result>
+\&    </Query>
+\&
+\&    <Writer sqlstore>
+\&      Statement "SELECT collectd_insert($1, $2, $3, $4, $5, $6, $7, $8, $9);"
+\&      StoreRates true
+\&    </Writer>
+\&
+\&    <Database foo>
+\&      Host "hostname"
+\&      Port "5432"
+\&      User "username"
+\&      Password "secret"
+\&      SSLMode "prefer"
+\&      KRBSrvName "kerberos_service_name"
+\&      Query magic
+\&    </Database>
+\&
+\&    <Database bar>
+\&      Interval 300
+\&      Service "service_name"
+\&      Query backend # predefined
+\&      Query rt36_tickets
+\&    </Database>
+\&
+\&    <Database qux>
+\&      # ...
+\&      Writer sqlstore
+\&      CommitInterval 10
+\&    </Database>
+\&  </Plugin>
+.Ve
+.PP
+The \fBQuery\fR block defines one database query which may later be used by a
+database definition. It accepts a single mandatory argument which specifies
+the name of the query. The names of all queries have to be unique (see the
+\&\fBMinVersion\fR and \fBMaxVersion\fR options below for an exception to this
+rule). The following configuration options are available to define the query:
+.PP
+In each \fBQuery\fR block, there is one or more \fBResult\fR blocks. \fBResult\fR
+blocks define how to handle the values returned from the query. They define
+which column holds which value and how to dispatch that value to the daemon.
+Multiple \fBResult\fR blocks may be used to extract multiple values from a single
+query.
+.IP "\fBStatement\fR \fIsql query statement\fR" 4
+.IX Item "Statement sql query statement"
+Specify the \fIsql query statement\fR which the plugin should execute. The string
+may contain the tokens \fB\f(CB$1\fB\fR, \fB\f(CB$2\fB\fR, etc. which are used to reference the
+first, second, etc. parameter. The value of the parameters is specified by the
+\&\fBParam\fR configuration option \- see below for details. To include a literal
+\&\fB$\fR character followed by a number, surround it with single quotes (\fB'\fR).
+.Sp
+Any \s-1SQL\s0 command which may return data (such as \f(CW\*(C`SELECT\*(C'\fR or \f(CW\*(C`SHOW\*(C'\fR) is
+allowed. Note, however, that only a single command may be used. Semicolons are
+allowed as long as a single non-empty command has been specified only.
+.Sp
+The returned lines will be handled separately one after another.
+.IP "\fBParam\fR \fIhostname\fR|\fIdatabase\fR|\fIusername\fR|\fIinterval\fR" 4
+.IX Item "Param hostname|database|username|interval"
+Specify the parameters which should be passed to the \s-1SQL\s0 query. The parameters
+are referred to in the \s-1SQL\s0 query as \fB\f(CB$1\fB\fR, \fB\f(CB$2\fB\fR, etc. in the same order as
+they appear in the configuration file. The value of the parameter is
+determined depending on the value of the \fBParam\fR option as follows:
+.RS 4
+.IP "\fIhostname\fR" 4
+.IX Item "hostname"
+The configured hostname of the database connection. If a \s-1UNIX\s0 domain socket is
+used, the parameter expands to \*(L"localhost\*(R".
+.IP "\fIdatabase\fR" 4
+.IX Item "database"
+The name of the database of the current connection.
+.IP "\fIinstance\fR" 4
+.IX Item "instance"
+The name of the database plugin instance. See the \fBInstance\fR option of the
+database specification below for details.
+.IP "\fIusername\fR" 4
+.IX Item "username"
+The username used to connect to the database.
+.IP "\fIinterval\fR" 4
+.IX Item "interval"
+The interval with which this database is queried (as specified by the database
+specific or global \fBInterval\fR options).
+.RE
+.RS 4
+.Sp
+Please note that parameters are only supported by PostgreSQL's protocol
+version 3 and above which was introduced in version 7.4 of PostgreSQL.
+.RE
+.IP "\fBType\fR \fItype\fR" 4
+.IX Item "Type type"
+The \fItype\fR name to be used when dispatching the values. The type describes
+how to handle the data and where to store it. See \fItypes.db\fR\|(5) for more
+details on types and their configuration. The number and type of values (as
+selected by the \fBValuesFrom\fR option) has to match the type of the given name.
+.Sp
+This option is required inside a \fBResult\fR block.
+.IP "\fBInstancePrefix\fR \fIprefix\fR" 4
+.IX Item "InstancePrefix prefix"
+.PD 0
+.IP "\fBInstancesFrom\fR \fIcolumn0\fR [\fIcolumn1\fR ...]" 4
+.IX Item "InstancesFrom column0 [column1 ...]"
+.PD
+Specify how to create the \*(L"TypeInstance\*(R" for each data set (i.\ e. line).
+\&\fBInstancePrefix\fR defines a static prefix that will be prepended to all type
+instances. \fBInstancesFrom\fR defines the column names whose values will be used
+to create the type instance. Multiple values will be joined together using the
+hyphen (\f(CW\*(C`\-\*(C'\fR) as separation character.
+.Sp
+The plugin itself does not check whether or not all built instances are
+different. It is your responsibility to assure that each is unique.
+.Sp
+Both options are optional. If none is specified, the type instance will be
+empty.
+.IP "\fBValuesFrom\fR \fIcolumn0\fR [\fIcolumn1\fR ...]" 4
+.IX Item "ValuesFrom column0 [column1 ...]"
+Names the columns whose content is used as the actual data for the data sets
+that are dispatched to the daemon. How many such columns you need is
+determined by the \fBType\fR setting as explained above. If you specify too many
+or not enough columns, the plugin will complain about that and no data will be
+submitted to the daemon.
+.Sp
+The actual data type, as seen by PostgreSQL, is not that important as long as
+it represents numbers. The plugin will automatically cast the values to the
+right type if it know how to do that. For that, it uses the \fIstrtoll\fR\|(3) and
+\&\fIstrtod\fR\|(3) functions, so anything supported by those functions is supported
+by the plugin as well.
+.Sp
+This option is required inside a \fBResult\fR block and may be specified multiple
+times. If multiple \fBValuesFrom\fR options are specified, the columns are read
+in the given order.
+.IP "\fBMinVersion\fR \fIversion\fR" 4
+.IX Item "MinVersion version"
+.PD 0
+.IP "\fBMaxVersion\fR \fIversion\fR" 4
+.IX Item "MaxVersion version"
+.PD
+Specify the minimum or maximum version of PostgreSQL that this query should be
+used with. Some statistics might only be available with certain versions of
+PostgreSQL. This allows you to specify multiple queries with the same name but
+which apply to different versions, thus allowing you to use the same
+configuration in a heterogeneous environment.
+.Sp
+The \fIversion\fR has to be specified as the concatenation of the major, minor
+and patch-level versions, each represented as two-decimal-digit numbers. For
+example, version 8.2.3 will become 80203.
+.PP
+The following predefined queries are available (the definitions can be found
+in the \fIpostgresql_default.conf\fR file which, by default, is available at
+\&\f(CW\*(C`\f(CIprefix\f(CW/share/collectd/\*(C'\fR):
+.IP "\fBbackends\fR" 4
+.IX Item "backends"
+This query collects the number of backends, i.\ e. the number of
+connected clients.
+.IP "\fBtransactions\fR" 4
+.IX Item "transactions"
+This query collects the numbers of committed and rolled-back transactions of
+the user tables.
+.IP "\fBqueries\fR" 4
+.IX Item "queries"
+This query collects the numbers of various table modifications (i.\ e.
+insertions, updates, deletions) of the user tables.
+.IP "\fBquery_plans\fR" 4
+.IX Item "query_plans"
+This query collects the numbers of various table scans and returned tuples of
+the user tables.
+.IP "\fBtable_states\fR" 4
+.IX Item "table_states"
+This query collects the numbers of live and dead rows in the user tables.
+.IP "\fBdisk_io\fR" 4
+.IX Item "disk_io"
+This query collects disk block access counts for user tables.
+.IP "\fBdisk_usage\fR" 4
+.IX Item "disk_usage"
+This query collects the on-disk size of the database in bytes.
+.PP
+In addition, the following detailed queries are available by default. Please
+note that each of those queries collects information \fBby table\fR, thus,
+potentially producing \fBa lot\fR of data. For details see the description of the
+non\-by_table queries above.
+.IP "\fBqueries_by_table\fR" 4
+.IX Item "queries_by_table"
+.PD 0
+.IP "\fBquery_plans_by_table\fR" 4
+.IX Item "query_plans_by_table"
+.IP "\fBtable_states_by_table\fR" 4
+.IX Item "table_states_by_table"
+.IP "\fBdisk_io_by_table\fR" 4
+.IX Item "disk_io_by_table"
+.PD
+.PP
+The \fBWriter\fR block defines a PostgreSQL writer backend. It accepts a single
+mandatory argument specifying the name of the writer. This will then be used
+in the \fBDatabase\fR specification in order to activate the writer instance. The
+names of all writers have to be unique. The following options may be
+specified:
+.IP "\fBStatement\fR \fIsql statement\fR" 4
+.IX Item "Statement sql statement"
+This mandatory option specifies the \s-1SQL\s0 statement that will be executed for
+each submitted value. A single \s-1SQL\s0 statement is allowed only. Anything after
+the first semicolon will be ignored.
+.Sp
+Nine parameters will be passed to the statement and should be specified as
+tokens \fB\f(CB$1\fB\fR, \fB\f(CB$2\fB\fR, through \fB\f(CB$9\fB\fR in the statement string. The following
+values are made available through those parameters:
+.RS 4
+.ie n .IP "\fB\fB$1\fB\fR" 4
+.el .IP "\fB\f(CB$1\fB\fR" 4
+.IX Item "$1"
+The timestamp of the queried value as a floating point number.
+.ie n .IP "\fB\fB$2\fB\fR" 4
+.el .IP "\fB\f(CB$2\fB\fR" 4
+.IX Item "$2"
+The hostname of the queried value.
+.ie n .IP "\fB\fB$3\fB\fR" 4
+.el .IP "\fB\f(CB$3\fB\fR" 4
+.IX Item "$3"
+The plugin name of the queried value.
+.ie n .IP "\fB\fB$4\fB\fR" 4
+.el .IP "\fB\f(CB$4\fB\fR" 4
+.IX Item "$4"
+The plugin instance of the queried value. This value may be \fB\s-1NULL\s0\fR if there
+is no plugin instance.
+.ie n .IP "\fB\fB$5\fB\fR" 4
+.el .IP "\fB\f(CB$5\fB\fR" 4
+.IX Item "$5"
+The type of the queried value (cf. \fItypes.db\fR\|(5)).
+.ie n .IP "\fB\fB$6\fB\fR" 4
+.el .IP "\fB\f(CB$6\fB\fR" 4
+.IX Item "$6"
+The type instance of the queried value. This value may be \fB\s-1NULL\s0\fR if there is
+no type instance.
+.ie n .IP "\fB\fB$7\fB\fR" 4
+.el .IP "\fB\f(CB$7\fB\fR" 4
+.IX Item "$7"
+An array of names for the submitted values (i.\ e., the name of the data
+sources of the submitted value-list).
+.ie n .IP "\fB\fB$8\fB\fR" 4
+.el .IP "\fB\f(CB$8\fB\fR" 4
+.IX Item "$8"
+An array of types for the submitted values (i.\ e., the type of the data
+sources of the submitted value-list; \f(CW\*(C`counter\*(C'\fR, \f(CW\*(C`gauge\*(C'\fR, ...). Note, that if
+\&\fBStoreRates\fR is enabled (which is the default, see below), all types will be
+\&\f(CW\*(C`gauge\*(C'\fR.
+.ie n .IP "\fB\fB$9\fB\fR" 4
+.el .IP "\fB\f(CB$9\fB\fR" 4
+.IX Item "$9"
+An array of the submitted values. The dimensions of the value name and value
+arrays match.
+.RE
+.RS 4
+.Sp
+In general, it is advisable to create and call a custom function in the
+PostgreSQL database for this purpose. Any procedural language supported by
+PostgreSQL will do (see chapter \*(L"Server Programming\*(R" in the PostgreSQL manual
+for details).
+.RE
+.IP "\fBStoreRates\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "StoreRates false|true"
+If set to \fBtrue\fR (the default), convert counter values to rates. If set to
+\&\fBfalse\fR counter values are stored as is, i.\ e. as an increasing integer
+number.
+.PP
+The \fBDatabase\fR block defines one PostgreSQL database for which to collect
+statistics. It accepts a single mandatory argument which specifies the
+database name. None of the other options are required. PostgreSQL will use
+default values as documented in the section \*(L"\s-1CONNECTING TO A DATABASE\*(R"\s0 in the
+\&\fIpsql\fR\|(1) manpage. However, be aware that those defaults may be influenced by
+the user collectd is run as and special environment variables. See the manpage
+for details.
+.IP "\fBInterval\fR \fIseconds\fR" 4
+.IX Item "Interval seconds"
+Specify the interval with which the database should be queried. The default is
+to use the global \fBInterval\fR setting.
+.IP "\fBCommitInterval\fR \fIseconds\fR" 4
+.IX Item "CommitInterval seconds"
+This option may be used for database connections which have \*(L"writers\*(R" assigned
+(see above). If specified, it causes a writer to put several updates into a
+single transaction. This transaction will last for the specified amount of
+time. By default, each update will be executed in a separate transaction. Each
+transaction generates a fair amount of overhead which can, thus, be reduced by
+activating this option. The draw-back is, that data covering the specified
+amount of time will be lost, for example, if a single statement within the
+transaction fails or if the database server crashes.
+.IP "\fBInstance\fR \fIname\fR" 4
+.IX Item "Instance name"
+Specify the plugin instance name that should be used instead of the database
+name (which is the default, if this option has not been specified). This
+allows to query multiple databases of the same name on the same host (e.g.
+when running multiple database server versions in parallel).
+.IP "\fBHost\fR \fIhostname\fR" 4
+.IX Item "Host hostname"
+Specify the hostname or \s-1IP\s0 of the PostgreSQL server to connect to. If the
+value begins with a slash, it is interpreted as the directory name in which to
+look for the \s-1UNIX\s0 domain socket.
+.Sp
+This option is also used to determine the hostname that is associated with a
+collected data set. If it has been omitted or either begins with with a slash
+or equals \fBlocalhost\fR it will be replaced with the global hostname definition
+of collectd. Any other value will be passed literally to collectd when
+dispatching values. Also see the global \fBHostname\fR and \fBFQDNLookup\fR options.
+.IP "\fBPort\fR \fIport\fR" 4
+.IX Item "Port port"
+Specify the \s-1TCP\s0 port or the local \s-1UNIX\s0 domain socket file extension of the
+server.
+.IP "\fBUser\fR \fIusername\fR" 4
+.IX Item "User username"
+Specify the username to be used when connecting to the server.
+.IP "\fBPassword\fR \fIpassword\fR" 4
+.IX Item "Password password"
+Specify the password to be used when connecting to the server.
+.IP "\fBExpireDelay\fR \fIdelay\fR" 4
+.IX Item "ExpireDelay delay"
+Skip expired values in query output.
+.IP "\fBSSLMode\fR \fIdisable\fR|\fIallow\fR|\fIprefer\fR|\fIrequire\fR" 4
+.IX Item "SSLMode disable|allow|prefer|require"
+Specify whether to use an \s-1SSL\s0 connection when contacting the server. The
+following modes are supported:
+.RS 4
+.IP "\fIdisable\fR" 4
+.IX Item "disable"
+Do not use \s-1SSL\s0 at all.
+.IP "\fIallow\fR" 4
+.IX Item "allow"
+First, try to connect without using \s-1SSL.\s0 If that fails, try using \s-1SSL.\s0
+.IP "\fIprefer\fR (default)" 4
+.IX Item "prefer (default)"
+First, try to connect using \s-1SSL.\s0 If that fails, try without using \s-1SSL.\s0
+.IP "\fIrequire\fR" 4
+.IX Item "require"
+Use \s-1SSL\s0 only.
+.RE
+.RS 4
+.RE
+.IP "\fBInstance\fR \fIname\fR" 4
+.IX Item "Instance name"
+Specify the plugin instance name that should be used instead of the database
+name (which is the default, if this option has not been specified). This
+allows to query multiple databases of the same name on the same host (e.g.
+when running multiple database server versions in parallel).
+.IP "\fBKRBSrvName\fR \fIkerberos_service_name\fR" 4
+.IX Item "KRBSrvName kerberos_service_name"
+Specify the Kerberos service name to use when authenticating with Kerberos 5
+or \s-1GSSAPI.\s0 See the sections \*(L"Kerberos authentication\*(R" and \*(L"\s-1GSSAPI\*(R"\s0 of the
+\&\fBPostgreSQL Documentation\fR for details.
+.IP "\fBService\fR \fIservice_name\fR" 4
+.IX Item "Service service_name"
+Specify the PostgreSQL service name to use for additional parameters. That
+service has to be defined in \fIpg_service.conf\fR and holds additional
+connection parameters. See the section \*(L"The Connection Service File\*(R" in the
+\&\fBPostgreSQL Documentation\fR for details.
+.IP "\fBQuery\fR \fIquery\fR" 4
+.IX Item "Query query"
+Specifies a \fIquery\fR which should be executed in the context of the database
+connection. This may be any of the predefined or user-defined queries. If no
+such option is given, it defaults to \*(L"backends\*(R", \*(L"transactions\*(R", \*(L"queries\*(R",
+\&\*(L"query_plans\*(R", \*(L"table_states\*(R", \*(L"disk_io\*(R" and \*(L"disk_usage\*(R" (unless a \fBWriter\fR
+has been specified). Else, the specified queries are used only.
+.IP "\fBWriter\fR \fIwriter\fR" 4
+.IX Item "Writer writer"
+Assigns the specified \fIwriter\fR backend to the database connection. This
+causes all collected data to be send to the database using the settings
+defined in the writer configuration (see the section \*(L"\s-1FILTER CONFIGURATION\*(R"\s0
+below for details on how to selectively send data to certain plugins).
+.Sp
+Each writer will register a flush callback which may be used when having long
+transactions enabled (see the \fBCommitInterval\fR option above). When issuing
+the \fB\s-1FLUSH\s0\fR command (see \fIcollectd\-unixsock\fR\|(5) for details) the current
+transaction will be committed right away. Two different kinds of flush
+callbacks are available with the \f(CW\*(C`postgresql\*(C'\fR plugin:
+.RS 4
+.IP "\fBpostgresql\fR" 4
+.IX Item "postgresql"
+Flush all writer backends.
+.IP "\fBpostgresql\-\fR\fIdatabase\fR" 4
+.IX Item "postgresql-database"
+Flush all writers of the specified \fIdatabase\fR only.
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""powerdns"""
+.el .SS "Plugin \f(CWpowerdns\fP"
+.IX Subsection "Plugin powerdns"
+The \f(CW\*(C`powerdns\*(C'\fR plugin queries statistics from an authoritative PowerDNS
+nameserver and/or a PowerDNS recursor. Since both offer a wide variety of
+values, many of which are probably meaningless to most users, but may be useful
+for some. So you may chose which values to collect, but if you don't, some
+reasonable defaults will be collected.
+.PP
+.Vb 10
+\&  <Plugin "powerdns">
+\&    <Server "server_name">
+\&      Collect "latency"
+\&      Collect "udp\-answers" "udp\-queries"
+\&      Socket "/var/run/pdns.controlsocket"
+\&    </Server>
+\&    <Recursor "recursor_name">
+\&      Collect "questions"
+\&      Collect "cache\-hits" "cache\-misses"
+\&      Socket "/var/run/pdns_recursor.controlsocket"
+\&    </Recursor>
+\&    LocalSocket "/opt/collectd/var/run/collectd\-powerdns"
+\&  </Plugin>
+.Ve
+.IP "\fBServer\fR and \fBRecursor\fR block" 4
+.IX Item "Server and Recursor block"
+The \fBServer\fR block defines one authoritative server to query, the \fBRecursor\fR
+does the same for an recursing server. The possible options in both blocks are
+the same, though. The argument defines a name for the server\ / recursor
+and is required.
+.RS 4
+.IP "\fBCollect\fR \fIField\fR" 4
+.IX Item "Collect Field"
+Using the \fBCollect\fR statement you can select which values to collect. Here,
+you specify the name of the values as used by the PowerDNS servers, e.\ g.
+\&\f(CW\*(C`dlg\-only\-drops\*(C'\fR, \f(CW\*(C`answers10\-100\*(C'\fR.
+.Sp
+The method of getting the values differs for \fBServer\fR and \fBRecursor\fR blocks:
+When querying the server a \f(CW\*(C`SHOW *\*(C'\fR command is issued in any case, because
+that's the only way of getting multiple values out of the server at once.
+collectd then picks out the values you have selected. When querying the
+recursor, a command is generated to query exactly these values. So if you
+specify invalid fields when querying the recursor, a syntax error may be
+returned by the daemon and collectd may not collect any values at all.
+.Sp
+If no \fBCollect\fR statement is given, the following \fBServer\fR values will be
+collected:
+.RS 4
+.IP "latency" 4
+.IX Item "latency"
+.PD 0
+.IP "packetcache-hit" 4
+.IX Item "packetcache-hit"
+.IP "packetcache-miss" 4
+.IX Item "packetcache-miss"
+.IP "packetcache-size" 4
+.IX Item "packetcache-size"
+.IP "query-cache-hit" 4
+.IX Item "query-cache-hit"
+.IP "query-cache-miss" 4
+.IX Item "query-cache-miss"
+.IP "recursing-answers" 4
+.IX Item "recursing-answers"
+.IP "recursing-questions" 4
+.IX Item "recursing-questions"
+.IP "tcp-answers" 4
+.IX Item "tcp-answers"
+.IP "tcp-queries" 4
+.IX Item "tcp-queries"
+.IP "udp-answers" 4
+.IX Item "udp-answers"
+.IP "udp-queries" 4
+.IX Item "udp-queries"
+.RE
+.RS 4
+.PD
+.Sp
+The following \fBRecursor\fR values will be collected by default:
+.IP "noerror-answers" 4
+.IX Item "noerror-answers"
+.PD 0
+.IP "nxdomain-answers" 4
+.IX Item "nxdomain-answers"
+.IP "servfail-answers" 4
+.IX Item "servfail-answers"
+.IP "sys-msec" 4
+.IX Item "sys-msec"
+.IP "user-msec" 4
+.IX Item "user-msec"
+.IP "qa-latency" 4
+.IX Item "qa-latency"
+.IP "cache-entries" 4
+.IX Item "cache-entries"
+.IP "cache-hits" 4
+.IX Item "cache-hits"
+.IP "cache-misses" 4
+.IX Item "cache-misses"
+.IP "questions" 4
+.IX Item "questions"
+.RE
+.RS 4
+.PD
+.Sp
+Please note that up to that point collectd doesn't know what values are
+available on the server and values that are added do not need a change of the
+mechanism so far. However, the values must be mapped to collectd's naming
+scheme, which is done using a lookup table that lists all known values. If
+values are added in the future and collectd does not know about them, you will
+get an error much like this:
+.Sp
+.Vb 1
+\&  powerdns plugin: submit: Not found in lookup table: foobar = 42
+.Ve
+.Sp
+In this case please file a bug report with the collectd team.
+.RE
+.IP "\fBSocket\fR \fIPath\fR" 4
+.IX Item "Socket Path"
+Configures the path to the \s-1UNIX\s0 domain socket to be used when connecting to the
+daemon. By default \f(CW\*(C`${localstatedir}/run/pdns.controlsocket\*(C'\fR will be used for
+an authoritative server and \f(CW\*(C`${localstatedir}/run/pdns_recursor.controlsocket\*(C'\fR
+will be used for the recursor.
+.RE
+.RS 4
+.RE
+.IP "\fBLocalSocket\fR \fIPath\fR" 4
+.IX Item "LocalSocket Path"
+Querying the recursor is done using \s-1UDP.\s0 When using \s-1UDP\s0 over \s-1UNIX\s0 domain
+sockets, the client socket needs a name in the file system, too. You can set
+this local name to \fIPath\fR using the \fBLocalSocket\fR option. The default is
+\&\f(CW\*(C`\f(CIprefix\f(CW/var/run/collectd\-powerdns\*(C'\fR.
+.ie n .SS "Plugin ""processes"""
+.el .SS "Plugin \f(CWprocesses\fP"
+.IX Subsection "Plugin processes"
+.IP "\fBProcess\fR \fIName\fR" 4
+.IX Item "Process Name"
+Select more detailed statistics of processes matching this name. The statistics
+collected for these selected processes are size of the resident segment size
+(\s-1RSS\s0), user\- and system-time used, number of processes and number of threads,
+io data (where available) and minor and major pagefaults.
+.IP "\fBProcessMatch\fR \fIname\fR \fIregex\fR" 4
+.IX Item "ProcessMatch name regex"
+Similar to the \fBProcess\fR option this allows to select more detailed
+statistics of processes matching the specified \fIregex\fR (see \fIregex\fR\|(7) for
+details). The statistics of all matching processes are summed up and
+dispatched to the daemon using the specified \fIname\fR as an identifier. This
+allows to \*(L"group\*(R" several processes together. \fIname\fR must not contain
+slashes.
+.ie n .SS "Plugin ""protocols"""
+.el .SS "Plugin \f(CWprotocols\fP"
+.IX Subsection "Plugin protocols"
+Collects a lot of information about various network protocols, such as \fI\s-1IP\s0\fR,
+\&\fI\s-1TCP\s0\fR, \fI\s-1UDP\s0\fR, etc.
+.PP
+Available configuration options:
+.IP "\fBValue\fR \fISelector\fR" 4
+.IX Item "Value Selector"
+Selects whether or not to select a specific value. The string being matched is
+of the form "\fIProtocol\fR:\fIValueName\fR", where \fIProtocol\fR will be used as the
+plugin instance and \fIValueName\fR will be used as type instance. An example of
+the string being used would be \f(CW\*(C`Tcp:RetransSegs\*(C'\fR.
+.Sp
+You can use regular expressions to match a large number of values with just one
+configuration option. To select all \*(L"extended\*(R" \fI\s-1TCP\s0\fR values, you could use the
+following statement:
+.Sp
+.Vb 1
+\&  Value "/^TcpExt:/"
+.Ve
+.Sp
+Whether only matched values are selected or all matched values are ignored
+depends on the \fBIgnoreSelected\fR. By default, only matched values are selected.
+If no value is configured at all, all values will be selected.
+.IP "\fBIgnoreSelected\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+If set to \fBtrue\fR, inverts the selection made by \fBValue\fR, i.\ e. all
+matching values will be ignored.
+.ie n .SS "Plugin ""python"""
+.el .SS "Plugin \f(CWpython\fP"
+.IX Subsection "Plugin python"
+This plugin embeds a Python-interpreter into collectd and provides an interface
+to collectd's plugin system. See \fIcollectd\-python\fR\|(5) for its documentation.
+.ie n .SS "Plugin ""routeros"""
+.el .SS "Plugin \f(CWrouteros\fP"
+.IX Subsection "Plugin routeros"
+The \f(CW\*(C`routeros\*(C'\fR plugin connects to a device running \fIRouterOS\fR, the
+Linux-based operating system for routers by \fIMikroTik\fR. The plugin uses
+\&\fIlibrouteros\fR to connect and reads information about the interfaces and
+wireless connections of the device. The configuration supports querying
+multiple routers:
+.PP
+.Vb 10
+\&  <Plugin "routeros">
+\&    <Router>
+\&      Host "router0.example.com"
+\&      User "collectd"
+\&      Password "secr3t"
+\&      CollectInterface true
+\&      CollectCPULoad true
+\&      CollectMemory true
+\&    </Router>
+\&    <Router>
+\&      Host "router1.example.com"
+\&      User "collectd"
+\&      Password "5ecret"
+\&      CollectInterface true
+\&      CollectRegistrationTable true
+\&      CollectDF true
+\&      CollectDisk true
+\&    </Router>
+\&  </Plugin>
+.Ve
+.PP
+As you can see above, the configuration of the \fIrouteros\fR plugin consists of
+one or more \fB<Router>\fR blocks. Within each block, the following
+options are understood:
+.IP "\fBHost\fR \fIHost\fR" 4
+.IX Item "Host Host"
+Hostname or IP-address of the router to connect to.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+Port name or port number used when connecting. If left unspecified, the default
+will be chosen by \fIlibrouteros\fR, currently \*(L"8728\*(R". This option expects a
+string argument, even when a numeric port number is given.
+.IP "\fBUser\fR \fIUser\fR" 4
+.IX Item "User User"
+Use the user name \fIUser\fR to authenticate. Defaults to \*(L"admin\*(R".
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Set the password used to authenticate.
+.IP "\fBCollectInterface\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectInterface true|false"
+When set to \fBtrue\fR, interface statistics will be collected for all interfaces
+present on the device. Defaults to \fBfalse\fR.
+.IP "\fBCollectRegistrationTable\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectRegistrationTable true|false"
+When set to \fBtrue\fR, information about wireless \s-1LAN\s0 connections will be
+collected. Defaults to \fBfalse\fR.
+.IP "\fBCollectCPULoad\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectCPULoad true|false"
+When set to \fBtrue\fR, information about the \s-1CPU\s0 usage will be collected. The
+number is a dimensionless value where zero indicates no \s-1CPU\s0 usage at all.
+Defaults to \fBfalse\fR.
+.IP "\fBCollectMemory\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectMemory true|false"
+When enabled, the amount of used and free memory will be collected. How used
+memory is calculated is unknown, for example whether or not caches are counted
+as used space.
+Defaults to \fBfalse\fR.
+.IP "\fBCollectDF\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectDF true|false"
+When enabled, the amount of used and free disk space will be collected.
+Defaults to \fBfalse\fR.
+.IP "\fBCollectDisk\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectDisk true|false"
+When enabled, the number of sectors written and bad blocks will be collected.
+Defaults to \fBfalse\fR.
+.ie n .SS "Plugin ""redis"""
+.el .SS "Plugin \f(CWredis\fP"
+.IX Subsection "Plugin redis"
+The \fIRedis plugin\fR connects to one or more Redis servers and gathers
+information about each server's state. For each server there is a \fINode\fR block
+which configures the connection parameters for this node.
+.PP
+.Vb 11
+\&  <Plugin redis>
+\&    <Node "example">
+\&        Host "localhost"
+\&        Port "6379"
+\&        Timeout 2000
+\&        <Query "LLEN myqueue">
+\&          Type "queue_length"
+\&          Instance "myqueue"
+\&        <Query>
+\&    </Node>
+\&  </Plugin>
+.Ve
+.PP
+The information shown in the synopsis above is the \fIdefault configuration\fR
+which is used by the plugin if no configuration is present.
+.IP "\fBNode\fR \fINodename\fR" 4
+.IX Item "Node Nodename"
+The \fBNode\fR block identifies a new Redis node, that is a new Redis instance
+running in an specified host and port. The name for node is a canonical
+identifier which is used as \fIplugin instance\fR. It is limited to
+64\ characters in length.
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+The \fBHost\fR option is the hostname or IP-address where the Redis instance is
+running on.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+The \fBPort\fR option is the \s-1TCP\s0 port on which the Redis instance accepts
+connections. Either a service name of a port number may be given. Please note
+that numerical port numbers must be given as a string, too.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Use \fIPassword\fR to authenticate when connecting to \fIRedis\fR.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+The \fBTimeout\fR option set the socket timeout for node response. Since the Redis
+read function is blocking, you should keep this value as low as possible. Keep
+in mind that the sum of all \fBTimeout\fR values for all \fBNodes\fR should be lower
+than \fBInterval\fR defined globally.
+.IP "\fBQuery\fR \fIQuerystring\fR" 4
+.IX Item "Query Querystring"
+The \fBQuery\fR block identifies a query to execute against the redis server.
+There may be an arbitrary number of queries to execute.
+.IP "\fBType\fR \fICollectd type\fR" 4
+.IX Item "Type Collectd type"
+Within a query definition, a valid collectd type to use as when submitting
+the result of the query. When not supplied, will default to \fBgauge\fR.
+.IP "\fBInstance\fR \fIType instance\fR" 4
+.IX Item "Instance Type instance"
+Within a query definition, an optional type instance to use when submitting
+the result of the query. When not supplied will default to the escaped
+command, up to 64 chars.
+.ie n .SS "Plugin ""rrdcached"""
+.el .SS "Plugin \f(CWrrdcached\fP"
+.IX Subsection "Plugin rrdcached"
+The \f(CW\*(C`rrdcached\*(C'\fR plugin uses the RRDtool accelerator daemon, \fIrrdcached\fR\|(1),
+to store values to \s-1RRD\s0 files in an efficient manner. The combination of the
+\&\f(CW\*(C`rrdcached\*(C'\fR \fBplugin\fR and the \f(CW\*(C`rrdcached\*(C'\fR \fBdaemon\fR is very similar to the
+way the \f(CW\*(C`rrdtool\*(C'\fR plugin works (see below). The added abstraction layer
+provides a number of benefits, though: Because the cache is not within
+\&\f(CW\*(C`collectd\*(C'\fR anymore, it does not need to be flushed when \f(CW\*(C`collectd\*(C'\fR is to be
+restarted. This results in much shorter (if any) gaps in graphs, especially
+under heavy load. Also, the \f(CW\*(C`rrdtool\*(C'\fR command line utility is aware of the
+daemon so that it can flush values to disk automatically when needed. This
+allows to integrate automated flushing of values into graphing solutions much
+more easily.
+.PP
+There are disadvantages, though: The daemon may reside on a different host, so
+it may not be possible for \f(CW\*(C`collectd\*(C'\fR to create the appropriate \s-1RRD\s0 files
+anymore. And even if \f(CW\*(C`rrdcached\*(C'\fR runs on the same host, it may run in a
+different base directory, so relative paths may do weird stuff if you're not
+careful.
+.PP
+So the \fBrecommended configuration\fR is to let \f(CW\*(C`collectd\*(C'\fR and \f(CW\*(C`rrdcached\*(C'\fR run
+on the same host, communicating via a \s-1UNIX\s0 domain socket. The \fBDataDir\fR
+setting should be set to an absolute path, so that a changed base directory
+does not result in \s-1RRD\s0 files being created\ / expected in the wrong place.
+.IP "\fBDaemonAddress\fR \fIAddress\fR" 4
+.IX Item "DaemonAddress Address"
+Address of the daemon as understood by the \f(CW\*(C`rrdc_connect\*(C'\fR function of the \s-1RRD\s0
+library. See \fIrrdcached\fR\|(1) for details. Example:
+.Sp
+.Vb 3
+\&  <Plugin "rrdcached">
+\&    DaemonAddress "unix:/var/run/rrdcached.sock"
+\&  </Plugin>
+.Ve
+.IP "\fBDataDir\fR \fIDirectory\fR" 4
+.IX Item "DataDir Directory"
+Set the base directory in which the \s-1RRD\s0 files reside. If this is a relative
+path, it is relative to the working base directory of the \f(CW\*(C`rrdcached\*(C'\fR daemon!
+Use of an absolute path is recommended.
+.IP "\fBCreateFiles\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CreateFiles true|false"
+Enables or disables the creation of \s-1RRD\s0 files. If the daemon is not running
+locally, or \fBDataDir\fR is set to a relative path, this will not work as
+expected. Default is \fBtrue\fR.
+.IP "\fBCreateFilesAsync\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "CreateFilesAsync false|true"
+When enabled, new \s-1RRD\s0 files are enabled asynchronously, using a separate thread
+that runs in the background. This prevents writes to block, which is a problem
+especially when many hundreds of files need to be created at once. However,
+since the purpose of creating the files asynchronously is \fInot\fR to block until
+the file is available, values before the file is available will be discarded.
+When disabled (the default) files are created synchronously, blocking for a
+short while, while the file is being written.
+.IP "\fBStepSize\fR \fISeconds\fR" 4
+.IX Item "StepSize Seconds"
+\&\fBForce\fR the stepsize of newly created RRD-files. Ideally (and per default)
+this setting is unset and the stepsize is set to the interval in which the data
+is collected. Do not use this option unless you absolutely have to for some
+reason. Setting this option may cause problems with the \f(CW\*(C`snmp plugin\*(C'\fR, the
+\&\f(CW\*(C`exec plugin\*(C'\fR or when the daemon is set up to receive data from other hosts.
+.IP "\fBHeartBeat\fR \fISeconds\fR" 4
+.IX Item "HeartBeat Seconds"
+\&\fBForce\fR the heartbeat of newly created RRD-files. This setting should be unset
+in which case the heartbeat is set to twice the \fBStepSize\fR which should equal
+the interval in which data is collected. Do not set this option unless you have
+a very good reason to do so.
+.IP "\fBRRARows\fR \fINumRows\fR" 4
+.IX Item "RRARows NumRows"
+The \f(CW\*(C`rrdtool plugin\*(C'\fR calculates the number of PDPs per \s-1CDP\s0 based on the
+\&\fBStepSize\fR, this setting and a timespan. This plugin creates RRD-files with
+three times five RRAs, i. e. five RRAs with the CFs \fB\s-1MIN\s0\fR, \fB\s-1AVERAGE\s0\fR, and
+\&\fB\s-1MAX\s0\fR. The five RRAs are optimized for graphs covering one hour, one day, one
+week, one month, and one year.
+.Sp
+So for each timespan, it calculates how many PDPs need to be consolidated into
+one \s-1CDP\s0 by calculating:
+  number of PDPs = timespan / (stepsize * rrarows)
+.Sp
+Bottom line is, set this no smaller than the width of you graphs in pixels. The
+default is 1200.
+.IP "\fBRRATimespan\fR \fISeconds\fR" 4
+.IX Item "RRATimespan Seconds"
+Adds an RRA-timespan, given in seconds. Use this option multiple times to have
+more then one \s-1RRA.\s0 If this option is never used, the built-in default of (3600,
+86400, 604800, 2678400, 31622400) is used.
+.Sp
+For more information on how RRA-sizes are calculated see \fBRRARows\fR above.
+.IP "\fB\s-1XFF\s0\fR \fIFactor\fR" 4
+.IX Item "XFF Factor"
+Set the \*(L"XFiles Factor\*(R". The default is 0.1. If unsure, don't set this option.
+\&\fIFactor\fR must be in the range \f(CW\*(C`[0.0\-1.0)\*(C'\fR, i.e. between zero (inclusive) and
+one (exclusive).
+.IP "\fBCollectStatistics\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "CollectStatistics false|true"
+When set to \fBtrue\fR, various statistics about the \fIrrdcached\fR daemon will be
+collected, with \*(L"rrdcached\*(R" as the \fIplugin name\fR. Defaults to \fBfalse\fR.
+.Sp
+Statistics are read via \fIrrdcached\fRs socket using the \s-1STATS\s0 command.
+See \fIrrdcached\fR\|(1) for details.
+.ie n .SS "Plugin ""rrdtool"""
+.el .SS "Plugin \f(CWrrdtool\fP"
+.IX Subsection "Plugin rrdtool"
+You can use the settings \fBStepSize\fR, \fBHeartBeat\fR, \fBRRARows\fR, and \fB\s-1XFF\s0\fR to
+fine-tune your RRD-files. Please read \fIrrdcreate\fR\|(1) if you encounter problems
+using these settings. If you don't want to dive into the depths of RRDtool, you
+can safely ignore these settings.
+.IP "\fBDataDir\fR \fIDirectory\fR" 4
+.IX Item "DataDir Directory"
+Set the directory to store \s-1RRD\s0 files under. By default \s-1RRD\s0 files are generated
+beneath the daemon's working directory, i.e. the \fBBaseDir\fR.
+.IP "\fBCreateFilesAsync\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "CreateFilesAsync false|true"
+When enabled, new \s-1RRD\s0 files are enabled asynchronously, using a separate thread
+that runs in the background. This prevents writes to block, which is a problem
+especially when many hundreds of files need to be created at once. However,
+since the purpose of creating the files asynchronously is \fInot\fR to block until
+the file is available, values before the file is available will be discarded.
+When disabled (the default) files are created synchronously, blocking for a
+short while, while the file is being written.
+.IP "\fBStepSize\fR \fISeconds\fR" 4
+.IX Item "StepSize Seconds"
+\&\fBForce\fR the stepsize of newly created RRD-files. Ideally (and per default)
+this setting is unset and the stepsize is set to the interval in which the data
+is collected. Do not use this option unless you absolutely have to for some
+reason. Setting this option may cause problems with the \f(CW\*(C`snmp plugin\*(C'\fR, the
+\&\f(CW\*(C`exec plugin\*(C'\fR or when the daemon is set up to receive data from other hosts.
+.IP "\fBHeartBeat\fR \fISeconds\fR" 4
+.IX Item "HeartBeat Seconds"
+\&\fBForce\fR the heartbeat of newly created RRD-files. This setting should be unset
+in which case the heartbeat is set to twice the \fBStepSize\fR which should equal
+the interval in which data is collected. Do not set this option unless you have
+a very good reason to do so.
+.IP "\fBRRARows\fR \fINumRows\fR" 4
+.IX Item "RRARows NumRows"
+The \f(CW\*(C`rrdtool plugin\*(C'\fR calculates the number of PDPs per \s-1CDP\s0 based on the
+\&\fBStepSize\fR, this setting and a timespan. This plugin creates RRD-files with
+three times five RRAs, i.e. five RRAs with the CFs \fB\s-1MIN\s0\fR, \fB\s-1AVERAGE\s0\fR, and
+\&\fB\s-1MAX\s0\fR. The five RRAs are optimized for graphs covering one hour, one day, one
+week, one month, and one year.
+.Sp
+So for each timespan, it calculates how many PDPs need to be consolidated into
+one \s-1CDP\s0 by calculating:
+  number of PDPs = timespan / (stepsize * rrarows)
+.Sp
+Bottom line is, set this no smaller than the width of you graphs in pixels. The
+default is 1200.
+.IP "\fBRRATimespan\fR \fISeconds\fR" 4
+.IX Item "RRATimespan Seconds"
+Adds an RRA-timespan, given in seconds. Use this option multiple times to have
+more then one \s-1RRA.\s0 If this option is never used, the built-in default of (3600,
+86400, 604800, 2678400, 31622400) is used.
+.Sp
+For more information on how RRA-sizes are calculated see \fBRRARows\fR above.
+.IP "\fB\s-1XFF\s0\fR \fIFactor\fR" 4
+.IX Item "XFF Factor"
+Set the \*(L"XFiles Factor\*(R". The default is 0.1. If unsure, don't set this option.
+\&\fIFactor\fR must be in the range \f(CW\*(C`[0.0\-1.0)\*(C'\fR, i.e. between zero (inclusive) and
+one (exclusive).
+.IP "\fBCacheFlush\fR \fISeconds\fR" 4
+.IX Item "CacheFlush Seconds"
+When the \f(CW\*(C`rrdtool\*(C'\fR plugin uses a cache (by setting \fBCacheTimeout\fR, see below)
+it writes all values for a certain RRD-file if the oldest value is older than
+(or equal to) the number of seconds specified. If some RRD-file is not updated
+anymore for some reason (the computer was shut down, the network is broken,
+etc.) some values may still be in the cache. If \fBCacheFlush\fR is set, then the
+entire cache is searched for entries older than \fBCacheTimeout\fR seconds and
+written to disk every \fISeconds\fR seconds. Since this is kind of expensive and
+does nothing under normal circumstances, this value should not be too small.
+900 seconds might be a good value, though setting this to 7200 seconds doesn't
+normally do much harm either.
+.IP "\fBCacheTimeout\fR \fISeconds\fR" 4
+.IX Item "CacheTimeout Seconds"
+If this option is set to a value greater than zero, the \f(CW\*(C`rrdtool plugin\*(C'\fR will
+save values in a cache, as described above. Writing multiple values at once
+reduces IO-operations and thus lessens the load produced by updating the files.
+The trade off is that the graphs kind of \*(L"drag behind\*(R" and that more memory is
+used.
+.IP "\fBWritesPerSecond\fR \fIUpdates\fR" 4
+.IX Item "WritesPerSecond Updates"
+When collecting many statistics with collectd and the \f(CW\*(C`rrdtool\*(C'\fR plugin, you
+will run serious performance problems. The \fBCacheFlush\fR setting and the
+internal update queue assert that collectd continues to work just fine even
+under heavy load, but the system may become very unresponsive and slow. This is
+a problem especially if you create graphs from the \s-1RRD\s0 files on the same
+machine, for example using the \f(CW\*(C`graph.cgi\*(C'\fR script included in the
+\&\f(CW\*(C`contrib/collection3/\*(C'\fR directory.
+.Sp
+This setting is designed for very large setups. Setting this option to a value
+between 25 and 80 updates per second, depending on your hardware, will leave
+the server responsive enough to draw graphs even while all the cached values
+are written to disk. Flushed values, i.\ e. values that are forced to disk
+by the \fB\s-1FLUSH\s0\fR command, are \fBnot\fR effected by this limit. They are still
+written as fast as possible, so that web frontends have up to date data when
+generating graphs.
+.Sp
+For example: If you have 100,000 \s-1RRD\s0 files and set \fBWritesPerSecond\fR to 30
+updates per second, writing all values to disk will take approximately
+56\ minutes. Together with the flushing ability that's integrated into
+\&\*(L"collection3\*(R" you'll end up with a responsive and fast system, up to date
+graphs and basically a \*(L"backup\*(R" of your values every hour.
+.IP "\fBRandomTimeout\fR \fISeconds\fR" 4
+.IX Item "RandomTimeout Seconds"
+When set, the actual timeout for each value is chosen randomly between
+\&\fICacheTimeout\fR\-\fIRandomTimeout\fR and \fICacheTimeout\fR+\fIRandomTimeout\fR. The
+intention is to avoid high load situations that appear when many values timeout
+at the same time. This is especially a problem shortly after the daemon starts,
+because all values were added to the internal cache at roughly the same time.
+.ie n .SS "Plugin ""sensors"""
+.el .SS "Plugin \f(CWsensors\fP"
+.IX Subsection "Plugin sensors"
+The \fISensors plugin\fR uses \fBlm_sensors\fR to retrieve sensor-values. This means
+that all the needed modules have to be loaded and lm_sensors has to be
+configured (most likely by editing \fI/etc/sensors.conf\fR. Read
+\&\fIsensors.conf\fR\|(5) for details.
+.PP
+The \fBlm_sensors\fR homepage can be found at
+<http://secure.netroedge.com/~lm78/>.
+.IP "\fBSensorConfigFile\fR \fIFile\fR" 4
+.IX Item "SensorConfigFile File"
+Read the \fIlm_sensors\fR configuration from \fIFile\fR. When unset (recommended),
+the library's default will be used.
+.IP "\fBSensor\fR \fIchip\-bus\-address/type\-feature\fR" 4
+.IX Item "Sensor chip-bus-address/type-feature"
+Selects the name of the sensor which you want to collect or ignore, depending
+on the \fBIgnoreSelected\fR below. For example, the option "\fBSensor\fR
+\&\fIit8712\-isa\-0290/voltage\-in1\fR" will cause collectd to gather data for the
+voltage sensor \fIin1\fR of the \fIit8712\fR on the isa bus at the address 0290.
+.IP "\fBIgnoreSelected\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+If no configuration if given, the \fBsensors\fR\-plugin will collect data from all
+sensors. This may not be practical, especially for uninteresting sensors.
+Thus, you can use the \fBSensor\fR\-option to pick the sensors you're interested
+in. Sometimes, however, it's easier/preferred to collect all sensors \fIexcept\fR a
+few ones. This option enables you to do that: By setting \fBIgnoreSelected\fR to
+\&\fItrue\fR the effect of \fBSensor\fR is inverted: All selected sensors are ignored
+and all other sensors are collected.
+.ie n .SS "Plugin ""sigrok"""
+.el .SS "Plugin \f(CWsigrok\fP"
+.IX Subsection "Plugin sigrok"
+The \fIsigrok plugin\fR uses \fIlibsigrok\fR to retrieve measurements from any device
+supported by the sigrok <http://sigrok.org/> project.
+.PP
+\&\fBSynopsis\fR
+.PP
+.Vb 12
+\& <Plugin sigrok>
+\&   LogLevel 3
+\&   <Device "AC Voltage">
+\&      Driver "fluke\-dmm"
+\&      MinimumInterval 10
+\&      Conn "/dev/ttyUSB2"
+\&   </Device>
+\&   <Device "Sound Level">
+\&      Driver "cem\-dt\-885x"
+\&      Conn "/dev/ttyUSB1"
+\&   </Device>
+\& </Plugin>
+.Ve
+.IP "\fBLogLevel\fR \fB0\-5\fR" 4
+.IX Item "LogLevel 0-5"
+The \fIsigrok\fR logging level to pass on to the \fIcollectd\fR log, as a number
+between \fB0\fR and \fB5\fR (inclusive). These levels correspond to \f(CW\*(C`None\*(C'\fR,
+\&\f(CW\*(C`Errors\*(C'\fR, \f(CW\*(C`Warnings\*(C'\fR, \f(CW\*(C`Informational\*(C'\fR, \f(CW\*(C`Debug \*(C'\fRand \f(CW\*(C`Spew\*(C'\fR, respectively.
+The default is \fB2\fR (\f(CW\*(C`Warnings\*(C'\fR). The \fIsigrok\fR log messages, regardless of
+their level, are always submitted to \fIcollectd\fR at its \s-1INFO\s0 log level.
+.IP "<\fBDevice\fR \fIName\fR>" 4
+.IX Item "<Device Name>"
+A sigrok-supported device, uniquely identified by this section's options. The
+\&\fIName\fR is passed to \fIcollectd\fR as the \fIplugin instance\fR.
+.IP "\fBDriver\fR \fIDriverName\fR" 4
+.IX Item "Driver DriverName"
+The sigrok driver to use for this device.
+.IP "\fBConn\fR \fIConnectionSpec\fR" 4
+.IX Item "Conn ConnectionSpec"
+If the device cannot be auto-discovered, or more than one might be discovered
+by the driver, \fIConnectionSpec\fR specifies the connection string to the device.
+It can be of the form of a device path (e.g.\ \f(CW\*(C`/dev/ttyUSB2\*(C'\fR), or, in
+case of a non-serial USB-connected device, the \s-1USB \s0\fIVendorID\fR\fB.\fR\fIProductID\fR
+separated by a period (e.g.\ \f(CW0403.6001\fR). A \s-1USB\s0 device can also be
+specified as \fIBus\fR\fB.\fR\fIAddress\fR (e.g.\ \f(CW1.41\fR).
+.IP "\fBSerialComm\fR \fISerialSpec\fR" 4
+.IX Item "SerialComm SerialSpec"
+For serial devices with non-standard port settings, this option can be used
+to specify them in a form understood by \fIsigrok\fR, e.g.\ \f(CW\*(C`9600/8n1\*(C'\fR.
+This should not be necessary; drivers know how to communicate with devices they
+support.
+.IP "\fBMinimumInterval\fR \fISeconds\fR" 4
+.IX Item "MinimumInterval Seconds"
+Specifies the minimum time between measurement dispatches to \fIcollectd\fR, in
+seconds. Since some \fIsigrok\fR supported devices can acquire measurements many
+times per second, it may be necessary to throttle these. For example, the
+\&\fI\s-1RRD\s0 plugin\fR cannot process writes more than once per second.
+.Sp
+The default \fBMinimumInterval\fR is \fB0\fR, meaning measurements received from the
+device are always dispatched to \fIcollectd\fR. When throttled, unused
+measurements are discarded.
+.ie n .SS "Plugin ""smart"""
+.el .SS "Plugin \f(CWsmart\fP"
+.IX Subsection "Plugin smart"
+The \f(CW\*(C`smart\*(C'\fR plugin collects \s-1SMART\s0 information from physical
+disks. Values collectd include temperature, power cycle count, poweron
+time and bad sectors. Also, all \s-1SMART\s0 attributes are collected along
+with the normalized current value, the worst value, the threshold and
+a human readable value.
+.PP
+Using the following two options you can ignore some disks or configure the
+collection only of specific disks.
+.IP "\fBDisk\fR \fIName\fR" 4
+.IX Item "Disk Name"
+Select the disk \fIName\fR. Whether it is collected or ignored depends on the
+\&\fBIgnoreSelected\fR setting, see below. As with other plugins that use the
+daemon's ignorelist functionality, a string that starts and ends with a slash
+is interpreted as a regular expression. Examples:
+.Sp
+.Vb 2
+\&  Disk "sdd"
+\&  Disk "/hda[34]/"
+.Ve
+.IP "\fBIgnoreSelected\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+Sets whether selected disks, i.\ e. the ones matches by any of the \fBDisk\fR
+statements, are ignored or if all other disks are ignored. The behavior
+(hopefully) is intuitive: If no \fBDisk\fR option is configured, all disks are
+collected. If at least one \fBDisk\fR option is given and no \fBIgnoreSelected\fR or
+set to \fBfalse\fR, \fBonly\fR matching disks will be collected. If \fBIgnoreSelected\fR
+is set to \fBtrue\fR, all disks are collected \fBexcept\fR the ones matched.
+.ie n .SS "Plugin ""snmp"""
+.el .SS "Plugin \f(CWsnmp\fP"
+.IX Subsection "Plugin snmp"
+Since the configuration of the \f(CW\*(C`snmp plugin\*(C'\fR is a little more complicated than
+other plugins, its documentation has been moved to an own manpage,
+\&\fIcollectd\-snmp\fR\|(5). Please see there for details.
+.ie n .SS "Plugin ""statsd"""
+.el .SS "Plugin \f(CWstatsd\fP"
+.IX Subsection "Plugin statsd"
+The \fIstatsd plugin\fR listens to a \s-1UDP\s0 socket, reads \*(L"events\*(R" in the statsd
+protocol and dispatches rates or other aggregates of these numbers
+periodically.
+.PP
+The plugin implements the \fICounter\fR, \fITimer\fR, \fIGauge\fR and \fISet\fR types which
+are dispatched as the \fIcollectd\fR types \f(CW\*(C`derive\*(C'\fR, \f(CW\*(C`latency\*(C'\fR, \f(CW\*(C`gauge\*(C'\fR and
+\&\f(CW\*(C`objects\*(C'\fR respectively.
+.PP
+The following configuration options are valid:
+.IP "\fBHost\fR \fIHost\fR" 4
+.IX Item "Host Host"
+Bind to the hostname / address \fIHost\fR. By default, the plugin will bind to the
+\&\*(L"any\*(R" address, i.e. accept packets sent to any of the hosts addresses.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+\&\s-1UDP\s0 port to listen to. This can be either a service name or a port number.
+Defaults to \f(CW8125\fR.
+.IP "\fBDeleteCounters\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "DeleteCounters false|true"
+.PD 0
+.IP "\fBDeleteTimers\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "DeleteTimers false|true"
+.IP "\fBDeleteGauges\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "DeleteGauges false|true"
+.IP "\fBDeleteSets\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "DeleteSets false|true"
+.PD
+These options control what happens if metrics are not updated in an interval.
+If set to \fBFalse\fR, the default, metrics are dispatched unchanged, i.e. the
+rate of counters and size of sets will be zero, timers report \f(CW\*(C`NaN\*(C'\fR and gauges
+are unchanged. If set to \fBTrue\fR, the such metrics are not dispatched and
+removed from the internal cache.
+.IP "\fBTimerPercentile\fR \fIPercent\fR" 4
+.IX Item "TimerPercentile Percent"
+Calculate and dispatch the configured percentile, i.e. compute the latency, so
+that \fIPercent\fR of all reported timers are smaller than or equal to the
+computed latency. This is useful for cutting off the long tail latency, as it's
+often done in \fIService Level Agreements\fR (SLAs).
+.Sp
+Different percentiles can be calculated by setting this option several times.
+If none are specified, no percentiles are calculated / dispatched.
+.IP "\fBTimerLower\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "TimerLower false|true"
+.PD 0
+.IP "\fBTimerUpper\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "TimerUpper false|true"
+.IP "\fBTimerSum\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "TimerSum false|true"
+.IP "\fBTimerCount\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "TimerCount false|true"
+.PD
+Calculate and dispatch various values out of \fITimer\fR metrics received during
+an interval. If set to \fBFalse\fR, the default, these values aren't calculated /
+dispatched.
+.ie n .SS "Plugin ""swap"""
+.el .SS "Plugin \f(CWswap\fP"
+.IX Subsection "Plugin swap"
+The \fISwap plugin\fR collects information about used and available swap space. On
+\&\fILinux\fR and \fISolaris\fR, the following options are available:
+.IP "\fBReportByDevice\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ReportByDevice false|true"
+Configures how to report physical swap devices. If set to \fBfalse\fR (the
+default), the summary over all swap devices is reported only, i.e. the globally
+used and available space over all devices. If \fBtrue\fR is configured, the used
+and available space of each device will be reported separately.
+.Sp
+This option is only available if the \fISwap plugin\fR can read \f(CW\*(C`/proc/swaps\*(C'\fR
+(under Linux) or use the \fIswapctl\fR\|(2) mechanism (under \fISolaris\fR).
+.IP "\fBReportBytes\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ReportBytes false|true"
+When enabled, the \fIswap I/O\fR is reported in bytes. When disabled, the default,
+\&\fIswap I/O\fR is reported in pages. This option is available under Linux only.
+.IP "\fBValuesAbsolute\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "ValuesAbsolute true|false"
+Enables or disables reporting of absolute swap metrics, i.e. number of \fIbytes\fR
+available and used. Defaults to \fBtrue\fR.
+.IP "\fBValuesPercentage\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "ValuesPercentage false|true"
+Enables or disables reporting of relative swap metrics, i.e. \fIpercent\fR
+available and free. Defaults to \fBfalse\fR.
+.Sp
+This is useful for deploying \fIcollectd\fR in a heterogeneous environment, where
+swap sizes differ and you want to specify generic thresholds or similar.
+.ie n .SS "Plugin ""syslog"""
+.el .SS "Plugin \f(CWsyslog\fP"
+.IX Subsection "Plugin syslog"
+.IP "\fBLogLevel\fR \fBdebug|info|notice|warning|err\fR" 4
+.IX Item "LogLevel debug|info|notice|warning|err"
+Sets the log-level. If, for example, set to \fBnotice\fR, then all events with
+severity \fBnotice\fR, \fBwarning\fR, or \fBerr\fR will be submitted to the
+syslog-daemon.
+.Sp
+Please note that \fBdebug\fR is only available if collectd has been compiled with
+debugging support.
+.IP "\fBNotifyLevel\fR \fB\s-1OKAY\s0\fR|\fB\s-1WARNING\s0\fR|\fB\s-1FAILURE\s0\fR" 4
+.IX Item "NotifyLevel OKAY|WARNING|FAILURE"
+Controls which notifications should be sent to syslog. The default behaviour is
+not to send any. Less severe notifications always imply logging more severe
+notifications: Setting this to \fB\s-1OKAY\s0\fR means all notifications will be sent to
+syslog, setting this to \fB\s-1WARNING\s0\fR will send \fB\s-1WARNING\s0\fR and \fB\s-1FAILURE\s0\fR
+notifications but will dismiss \fB\s-1OKAY\s0\fR notifications. Setting this option to
+\&\fB\s-1FAILURE\s0\fR will only send failures to syslog.
+.ie n .SS "Plugin ""table"""
+.el .SS "Plugin \f(CWtable\fP"
+.IX Subsection "Plugin table"
+The \f(CW\*(C`table plugin\*(C'\fR provides generic means to parse tabular data and dispatch
+user specified values. Values are selected based on column numbers. For
+example, this plugin may be used to get values from the Linux \fIproc\fR\|(5)
+filesystem or \s-1CSV \s0(comma separated values) files.
+.PP
+.Vb 10
+\&  <Plugin table>
+\&    <Table "/proc/slabinfo">
+\&      Instance "slabinfo"
+\&      Separator " "
+\&      <Result>
+\&        Type gauge
+\&        InstancePrefix "active_objs"
+\&        InstancesFrom 0
+\&        ValuesFrom 1
+\&      </Result>
+\&      <Result>
+\&        Type gauge
+\&        InstancePrefix "objperslab"
+\&        InstancesFrom 0
+\&        ValuesFrom 4
+\&      </Result>
+\&    </Table>
+\&  </Plugin>
+.Ve
+.PP
+The configuration consists of one or more \fBTable\fR blocks, each of which
+configures one file to parse. Within each \fBTable\fR block, there are one or
+more \fBResult\fR blocks, which configure which data to select and how to
+interpret it.
+.PP
+The following options are available inside a \fBTable\fR block:
+.IP "\fBInstance\fR \fIinstance\fR" 4
+.IX Item "Instance instance"
+If specified, \fIinstance\fR is used as the plugin instance. So, in the above
+example, the plugin name \f(CW\*(C`table\-slabinfo\*(C'\fR would be used. If omitted, the
+filename of the table is used instead, with all special characters replaced
+with an underscore (\f(CW\*(C`_\*(C'\fR).
+.IP "\fBSeparator\fR \fIstring\fR" 4
+.IX Item "Separator string"
+Any character of \fIstring\fR is interpreted as a delimiter between the different
+columns of the table. A sequence of two or more contiguous delimiters in the
+table is considered to be a single delimiter, i.\ e. there cannot be any
+empty columns. The plugin uses the \fIstrtok_r\fR\|(3) function to parse the lines
+of a table \- see its documentation for more details. This option is mandatory.
+.Sp
+A horizontal tab, newline and carriage return may be specified by \f(CW\*(C`\e\et\*(C'\fR,
+\&\f(CW\*(C`\e\en\*(C'\fR and \f(CW\*(C`\e\er\*(C'\fR respectively. Please note that the double backslashes are
+required because of collectd's config parsing.
+.PP
+The following options are available inside a \fBResult\fR block:
+.IP "\fBType\fR \fItype\fR" 4
+.IX Item "Type type"
+Sets the type used to dispatch the values to the daemon. Detailed information
+about types and their configuration can be found in \fItypes.db\fR\|(5). This
+option is mandatory.
+.IP "\fBInstancePrefix\fR \fIprefix\fR" 4
+.IX Item "InstancePrefix prefix"
+If specified, prepend \fIprefix\fR to the type instance. If omitted, only the
+\&\fBInstancesFrom\fR option is considered for the type instance.
+.IP "\fBInstancesFrom\fR \fIcolumn0\fR [\fIcolumn1\fR ...]" 4
+.IX Item "InstancesFrom column0 [column1 ...]"
+If specified, the content of the given columns (identified by the column
+number starting at zero) will be used to create the type instance for each
+row. Multiple values (and the instance prefix) will be joined together with
+dashes (\fI\-\fR) as separation character. If omitted, only the \fBInstancePrefix\fR
+option is considered for the type instance.
+.Sp
+The plugin itself does not check whether or not all built instances are
+different. ItXs your responsibility to assure that each is unique. This is
+especially true, if you do not specify \fBInstancesFrom\fR: \fBYou\fR have to make
+sure that the table only contains one row.
+.Sp
+If neither \fBInstancePrefix\fR nor \fBInstancesFrom\fR is given, the type instance
+will be empty.
+.IP "\fBValuesFrom\fR \fIcolumn0\fR [\fIcolumn1\fR ...]" 4
+.IX Item "ValuesFrom column0 [column1 ...]"
+Specifies the columns (identified by the column numbers starting at zero)
+whose content is used as the actual data for the data sets that are dispatched
+to the daemon. How many such columns you need is determined by the \fBType\fR
+setting above. If you specify too many or not enough columns, the plugin will
+complain about that and no data will be submitted to the daemon. The plugin
+uses \fIstrtoll\fR\|(3) and \fIstrtod\fR\|(3) to parse counter and gauge values
+respectively, so anything supported by those functions is supported by the
+plugin as well. This option is mandatory.
+.ie n .SS "Plugin ""tail"""
+.el .SS "Plugin \f(CWtail\fP"
+.IX Subsection "Plugin tail"
+The \f(CW\*(C`tail plugin\*(C'\fR follows logfiles, just like \fItail\fR\|(1) does, parses
+each line and dispatches found values. What is matched can be configured by the
+user using (extended) regular expressions, as described in \fIregex\fR\|(7).
+.PP
+.Vb 10
+\&  <Plugin "tail">
+\&    <File "/var/log/exim4/mainlog">
+\&      Instance "exim"
+\&      Interval 60
+\&      <Match>
+\&        Regex "S=([1\-9][0\-9]*)"
+\&        DSType "CounterAdd"
+\&        Type "ipt_bytes"
+\&        Instance "total"
+\&      </Match>
+\&      <Match>
+\&        Regex "\e\e<R=local_user\e\e>"
+\&        ExcludeRegex "\e\e<R=local_user\e\e>.*mail_spool defer"
+\&        DSType "CounterInc"
+\&        Type "counter"
+\&        Instance "local_user"
+\&      </Match>
+\&    </File>
+\&  </Plugin>
+.Ve
+.PP
+The config consists of one or more \fBFile\fR blocks, each of which configures one
+logfile to parse. Within each \fBFile\fR block, there are one or more \fBMatch\fR
+blocks, which configure a regular expression to search for.
+.PP
+The \fBInstance\fR option in the \fBFile\fR block may be used to set the plugin
+instance. So in the above example the plugin name \f(CW\*(C`tail\-foo\*(C'\fR would be used.
+This plugin instance is for all \fBMatch\fR blocks that \fBfollow\fR it, until the
+next \fBInstance\fR option. This way you can extract several plugin instances from
+one logfile, handy when parsing syslog and the like.
+.PP
+The \fBInterval\fR option allows you to define the length of time between reads. If
+this is not set, the default Interval will be used.
+.PP
+Each \fBMatch\fR block has the following options to describe how the match should
+be performed:
+.IP "\fBRegex\fR \fIregex\fR" 4
+.IX Item "Regex regex"
+Sets the regular expression to use for matching against a line. The first
+subexpression has to match something that can be turned into a number by
+\&\fIstrtoll\fR\|(3) or \fIstrtod\fR\|(3), depending on the value of \f(CW\*(C`CounterAdd\*(C'\fR, see
+below. Because \fBextended\fR regular expressions are used, you do not need to use
+backslashes for subexpressions! If in doubt, please consult \fIregex\fR\|(7). Due to
+collectd's config parsing you need to escape backslashes, though. So if you
+want to match literal parentheses you need to do the following:
+.Sp
+.Vb 1
+\&  Regex "SPAM \e\e(Score: (\-?[0\-9]+\e\e.[0\-9]+)\e\e)"
+.Ve
+.IP "\fBExcludeRegex\fR \fIregex\fR" 4
+.IX Item "ExcludeRegex regex"
+Sets an optional regular expression to use for excluding lines from the match.
+An example which excludes all connections from localhost from the match:
+.Sp
+.Vb 1
+\&  ExcludeRegex "127\e\e.0\e\e.0\e\e.1"
+.Ve
+.IP "\fBDSType\fR \fIType\fR" 4
+.IX Item "DSType Type"
+Sets how the values are cumulated. \fIType\fR is one of:
+.RS 4
+.IP "\fBGaugeAverage\fR" 4
+.IX Item "GaugeAverage"
+Calculate the average.
+.IP "\fBGaugeMin\fR" 4
+.IX Item "GaugeMin"
+Use the smallest number only.
+.IP "\fBGaugeMax\fR" 4
+.IX Item "GaugeMax"
+Use the greatest number only.
+.IP "\fBGaugeLast\fR" 4
+.IX Item "GaugeLast"
+Use the last number found.
+.IP "\fBCounterSet\fR" 4
+.IX Item "CounterSet"
+.PD 0
+.IP "\fBDeriveSet\fR" 4
+.IX Item "DeriveSet"
+.IP "\fBAbsoluteSet\fR" 4
+.IX Item "AbsoluteSet"
+.PD
+The matched number is a counter. Simply \fIsets\fR the internal counter to this
+value. Variants exist for \f(CW\*(C`COUNTER\*(C'\fR, \f(CW\*(C`DERIVE\*(C'\fR, and \f(CW\*(C`ABSOLUTE\*(C'\fR data sources.
+.IP "\fBGaugeAdd\fR" 4
+.IX Item "GaugeAdd"
+.PD 0
+.IP "\fBCounterAdd\fR" 4
+.IX Item "CounterAdd"
+.IP "\fBDeriveAdd\fR" 4
+.IX Item "DeriveAdd"
+.PD
+Add the matched value to the internal counter. In case of \fBDeriveAdd\fR, the
+matched number may be negative, which will effectively subtract from the
+internal counter.
+.IP "\fBGaugeInc\fR" 4
+.IX Item "GaugeInc"
+.PD 0
+.IP "\fBCounterInc\fR" 4
+.IX Item "CounterInc"
+.IP "\fBDeriveInc\fR" 4
+.IX Item "DeriveInc"
+.PD
+Increase the internal counter by one. These \fBDSType\fR are the only ones that do
+not use the matched subexpression, but simply count the number of matched
+lines. Thus, you may use a regular expression without submatch in this case.
+.RE
+.RS 4
+.Sp
+As you'd expect the \fBGauge*\fR types interpret the submatch as a floating point
+number, using \fIstrtod\fR\|(3). The \fBCounter*\fR and \fBAbsoluteSet\fR types interpret
+the submatch as an unsigned integer using \fIstrtoull\fR\|(3). The \fBDerive*\fR types
+interpret the submatch as a signed integer using \fIstrtoll\fR\|(3). \fBCounterInc\fR
+and \fBDeriveInc\fR do not use the submatch at all and it may be omitted in this
+case.
+.RE
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+Sets the type used to dispatch this value. Detailed information about types and
+their configuration can be found in \fItypes.db\fR\|(5).
+.IP "\fBInstance\fR \fITypeInstance\fR" 4
+.IX Item "Instance TypeInstance"
+This optional setting sets the type instance to use.
+.ie n .SS "Plugin ""tail_csv"""
+.el .SS "Plugin \f(CWtail_csv\fP"
+.IX Subsection "Plugin tail_csv"
+The \fItail_csv plugin\fR reads files in the \s-1CSV\s0 format, e.g. the statistics file
+written by \fISnort\fR.
+.PP
+\&\fBSynopsis:\fR
+.PP
+.Vb 12
+\& <Plugin "tail_csv">
+\&   <Metric "snort\-dropped">
+\&       Type "percent"
+\&       Instance "dropped"
+\&       Index 1
+\&   </Metric>
+\&   <File "/var/log/snort/snort.stats">
+\&       Instance "snort\-eth0"
+\&       Interval 600
+\&       Collect "snort\-dropped"
+\&   </File>
+\& </Plugin>
+.Ve
+.PP
+The configuration consists of one or more \fBMetric\fR blocks that define an index
+into the line of the \s-1CSV\s0 file and how this value is mapped to \fIcollectd's\fR
+internal representation. These are followed by one or more \fBInstance\fR blocks
+which configure which file to read, in which interval and which metrics to
+extract.
+.IP "<\fBMetric\fR \fIName\fR>" 4
+.IX Item "<Metric Name>"
+The \fBMetric\fR block configures a new metric to be extracted from the statistics
+file and how it is mapped on \fIcollectd's\fR data model. The string \fIName\fR is
+only used inside the \fBInstance\fR blocks to refer to this block, so you can use
+one \fBMetric\fR block for multiple \s-1CSV\s0 files.
+.RS 4
+.IP "\fBType\fR \fIType\fR" 4
+.IX Item "Type Type"
+Configures which \fIType\fR to use when dispatching this metric. Types are defined
+in the \fItypes.db\fR\|(5) file, see the appropriate manual page for more
+information on specifying types. Only types with a single \fIdata source\fR are
+supported by the \fItail_csv plugin\fR. The information whether the value is an
+absolute value (i.e. a \f(CW\*(C`GAUGE\*(C'\fR) or a rate (i.e. a \f(CW\*(C`DERIVE\*(C'\fR) is taken from the
+\&\fIType's\fR definition.
+.IP "\fBInstance\fR \fITypeInstance\fR" 4
+.IX Item "Instance TypeInstance"
+If set, \fITypeInstance\fR is used to populate the type instance field of the
+created value lists. Otherwise, no type instance is used.
+.IP "\fBValueFrom\fR \fIIndex\fR" 4
+.IX Item "ValueFrom Index"
+Configure to read the value from the field with the zero-based index \fIIndex\fR.
+If the value is parsed as signed integer, unsigned integer or double depends on
+the \fBType\fR setting, see above.
+.RE
+.RS 4
+.RE
+.IP "<\fBFile\fR \fIPath\fR>" 4
+.IX Item "<File Path>"
+Each \fBFile\fR block represents one \s-1CSV\s0 file to read. There must be at least one
+\&\fIFile\fR block but there can be multiple if you have multiple \s-1CSV\s0 files.
+.RS 4
+.IP "\fBInstance\fR \fIPluginInstance\fR" 4
+.IX Item "Instance PluginInstance"
+Sets the \fIplugin instance\fR used when dispatching the values.
+.IP "\fBCollect\fR \fIMetric\fR" 4
+.IX Item "Collect Metric"
+Specifies which \fIMetric\fR to collect. This option must be specified at least
+once, and you can use this option multiple times to specify more than one
+metric to be extracted from this statistic file.
+.IP "\fBInterval\fR \fISeconds\fR" 4
+.IX Item "Interval Seconds"
+Configures the interval in which to read values from this instance / file.
+Defaults to the plugin's default interval.
+.IP "\fBTimeFrom\fR \fIIndex\fR" 4
+.IX Item "TimeFrom Index"
+Rather than using the local time when dispatching a value, read the timestamp
+from the field with the zero-based index \fIIndex\fR. The value is interpreted as
+seconds since epoch. The value is parsed as a double and may be factional.
+.RE
+.RS 4
+.RE
+.ie n .SS "Plugin ""teamspeak2"""
+.el .SS "Plugin \f(CWteamspeak2\fP"
+.IX Subsection "Plugin teamspeak2"
+The \f(CW\*(C`teamspeak2 plugin\*(C'\fR connects to the query port of a teamspeak2 server and
+polls interesting global and virtual server data. The plugin can query only one
+physical server but unlimited virtual servers. You can use the following
+options to configure it:
+.IP "\fBHost\fR \fIhostname/ip\fR" 4
+.IX Item "Host hostname/ip"
+The hostname or ip which identifies the physical server.
+Default: 127.0.0.1
+.IP "\fBPort\fR \fIport\fR" 4
+.IX Item "Port port"
+The query port of the physical server. This needs to be a string.
+Default: \*(L"51234\*(R"
+.IP "\fBServer\fR \fIport\fR" 4
+.IX Item "Server port"
+This option has to be added once for every virtual server the plugin should
+query. If you want to query the virtual server on port 8767 this is what the
+option would look like:
+.Sp
+.Vb 1
+\&  Server "8767"
+.Ve
+.Sp
+This option, although numeric, needs to be a string, i.\ e. you \fBmust\fR
+use quotes around it! If no such statement is given only global information
+will be collected.
+.ie n .SS "Plugin ""ted"""
+.el .SS "Plugin \f(CWted\fP"
+.IX Subsection "Plugin ted"
+The \fI\s-1TED\s0\fR plugin connects to a device of \*(L"The Energy Detective\*(R", a device to
+measure power consumption. These devices are usually connected to a serial
+(\s-1RS232\s0) or \s-1USB\s0 port. The plugin opens a configured device and tries to read the
+current energy readings. For more information on \s-1TED,\s0 visit
+<http://www.theenergydetective.com/>.
+.PP
+Available configuration options:
+.IP "\fBDevice\fR \fIPath\fR" 4
+.IX Item "Device Path"
+Path to the device on which \s-1TED\s0 is connected. collectd will need read and write
+permissions on that file.
+.Sp
+Default: \fB/dev/ttyUSB0\fR
+.IP "\fBRetries\fR \fINum\fR" 4
+.IX Item "Retries Num"
+Apparently reading from \s-1TED\s0 is not that reliable. You can therefore configure a
+number of retries here. You only configure the \fIretries\fR here, to if you
+specify zero, one reading will be performed (but no retries if that fails); if
+you specify three, a maximum of four readings are performed. Negative values
+are illegal.
+.Sp
+Default: \fB0\fR
+.ie n .SS "Plugin ""tcpconns"""
+.el .SS "Plugin \f(CWtcpconns\fP"
+.IX Subsection "Plugin tcpconns"
+The \f(CW\*(C`tcpconns plugin\*(C'\fR counts the number of currently established \s-1TCP\s0
+connections based on the local port and/or the remote port. Since there may be
+a lot of connections the default if to count all connections with a local port,
+for which a listening socket is opened. You can use the following options to
+fine-tune the ports you are interested in:
+.IP "\fBListeningPorts\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "ListeningPorts true|false"
+If this option is set to \fItrue\fR, statistics for all local ports for which a
+listening socket exists are collected. The default depends on \fBLocalPort\fR and
+\&\fBRemotePort\fR (see below): If no port at all is specifically selected, the
+default is to collect listening ports. If specific ports (no matter if local or
+remote ports) are selected, this option defaults to \fIfalse\fR, i.\ e. only
+the selected ports will be collected unless this option is set to \fItrue\fR
+specifically.
+.IP "\fBLocalPort\fR \fIPort\fR" 4
+.IX Item "LocalPort Port"
+Count the connections to a specific local port. This can be used to see how
+many connections are handled by a specific daemon, e.\ g. the mailserver.
+You have to specify the port in numeric form, so for the mailserver example
+you'd need to set \fB25\fR.
+.IP "\fBRemotePort\fR \fIPort\fR" 4
+.IX Item "RemotePort Port"
+Count the connections to a specific remote port. This is useful to see how
+much a remote service is used. This is most useful if you want to know how many
+connections a local service has opened to remote services, e.\ g. how many
+connections a mail server or news server has to other mail or news servers, or
+how many connections a web proxy holds to web servers. You have to give the
+port in numeric form.
+.IP "\fBAllPortsSummary\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "AllPortsSummary true|false"
+If this option is set to \fItrue\fR a summary of statistics from all connections
+are collectd. This option defaults to \fIfalse\fR.
+.ie n .SS "Plugin ""thermal"""
+.el .SS "Plugin \f(CWthermal\fP"
+.IX Subsection "Plugin thermal"
+.IP "\fBForceUseProcfs\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "ForceUseProcfs true|false"
+By default, the \fIThermal plugin\fR tries to read the statistics from the Linux
+\&\f(CW\*(C`sysfs\*(C'\fR interface. If that is not available, the plugin falls back to the
+\&\f(CW\*(C`procfs\*(C'\fR interface. By setting this option to \fItrue\fR, you can force the
+plugin to use the latter. This option defaults to \fIfalse\fR.
+.IP "\fBDevice\fR \fIDevice\fR" 4
+.IX Item "Device Device"
+Selects the name of the thermal device that you want to collect or ignore,
+depending on the value of the \fBIgnoreSelected\fR option. This option may be
+used multiple times to specify a list of devices.
+.IP "\fBIgnoreSelected\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+Invert the selection: If set to true, all devices \fBexcept\fR the ones that
+match the device names specified by the \fBDevice\fR option are collected. By
+default only selected devices are collected if a selection is made. If no
+selection is configured at all, \fBall\fR devices are selected.
+.ie n .SS "Plugin ""threshold"""
+.el .SS "Plugin \f(CWthreshold\fP"
+.IX Subsection "Plugin threshold"
+The \fIThreshold plugin\fR checks values collected or received by \fIcollectd\fR
+against a configurable \fIthreshold\fR and issues \fInotifications\fR if values are
+out of bounds.
+.PP
+Documentation for this plugin is available in the \fIcollectd\-threshold\fR\|(5)
+manual page.
+.ie n .SS "Plugin ""tokyotyrant"""
+.el .SS "Plugin \f(CWtokyotyrant\fP"
+.IX Subsection "Plugin tokyotyrant"
+The \fITokyoTyrant plugin\fR connects to a TokyoTyrant server and collects a
+couple metrics: number of records, and database size on disk.
+.IP "\fBHost\fR \fIHostname/IP\fR" 4
+.IX Item "Host Hostname/IP"
+The hostname or ip which identifies the server.
+Default: \fB127.0.0.1\fR
+.IP "\fBPort\fR \fIService/Port\fR" 4
+.IX Item "Port Service/Port"
+The query port of the server. This needs to be a string, even if the port is
+given in its numeric form.
+Default: \fB1978\fR
+.ie n .SS "Plugin ""turbostat"""
+.el .SS "Plugin \f(CWturbostat\fP"
+.IX Subsection "Plugin turbostat"
+The \fITurbostat plugin\fR reads \s-1CPU\s0 frequency and C\-state residency on modern
+Intel processors by using the new Model Specific Registers.
+.IP "\fBCoreCstates\fR \fIBitmask(Integer)\fR" 4
+.IX Item "CoreCstates Bitmask(Integer)"
+Bitmask of the list of core C states supported by the processor.
+This option should only be used if the automated detection fails.
+Default value extracted from the cpu model and family.
+.Sp
+Currently supported C\-states (by this plugin): 3, 6, 7
+.Sp
+Example: (1<<3)+(1<<6)+(1<<7) = 392 for all states
+.IP "\fBPackageCstates\fR \fIBitmask(Integer)\fR" 4
+.IX Item "PackageCstates Bitmask(Integer)"
+Bitmask of the list of pacages C states supported by the processor.
+This option should only be used if the automated detection fails.
+Default value extracted from the cpu model and family.
+.Sp
+Currently supported C\-states (by this plugin): 2, 3, 6, 7, 8, 9, 10
+.Sp
+Example: (1<<2)+(1<<3)+(1<<6)+(1<<7) = 396 for states 2, 3, 6 and 7
+.IP "\fBSystemManagementInterrupt\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "SystemManagementInterrupt true|false"
+Boolean enabling the collection of the I/O System-Management Interrupt
+counter'. This option should only be used if the automated detection
+fails or if you want to disable this feature.
+.IP "\fBDigitalTemperatureSensor\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "DigitalTemperatureSensor true|false"
+Boolean enabling the collection of the temperature of each core.
+This option should only be used if the automated detectionfails or 
+if you want to disable this feature.
+.IP "\fBDigitalTemperatureSensor\fR \fItrue\fR|\fIfalse\fR" 4
+.IX Item "DigitalTemperatureSensor true|false"
+Boolean enabling the collection of the temperature of each package.
+This option should only be used if the automated detectionfails or 
+if you want to disable this feature.
+.IP "\fBTCCActivationTemp\fR \fITemperature\fR" 4
+.IX Item "TCCActivationTemp Temperature"
+Thermal Control Circuit Activation Temperature of the installed
+\&\s-1CPU.\s0 This temperature is used when collecting the temperature of
+cores or packages. This option should only be used if the automated
+detection fails. Default value extracted from \fB\s-1MSR_IA32_TEMPERATURE_TARGET\s0\fR
+.IP "\fBRunningAveragePowerLimit\fR \fIBitmask(Integer)\fR" 4
+.IX Item "RunningAveragePowerLimit Bitmask(Integer)"
+Bitmask of the list of elements to be thermally monitored. This option
+should only be used if the automated detection fails or if you want to
+disable some collections. The different bits of this bitmask accepted
+by this plugin are:
+.RS 4
+.IP "0 ('1'): Package" 4
+.IX Item "0 ('1'): Package"
+.PD 0
+.IP "1 ('2'): \s-1DRAM\s0" 4
+.IX Item "1 ('2'): DRAM"
+.IP "2 ('4'): Cores" 4
+.IX Item "2 ('4'): Cores"
+.IP "3 ('8'): Embedded graphic device" 4
+.IX Item "3 ('8'): Embedded graphic device"
+.RE
+.RS 4
+.RE
+.PD
+.ie n .SS "Plugin ""unixsock"""
+.el .SS "Plugin \f(CWunixsock\fP"
+.IX Subsection "Plugin unixsock"
+.IP "\fBSocketFile\fR \fIPath\fR" 4
+.IX Item "SocketFile Path"
+Sets the socket-file which is to be created.
+.IP "\fBSocketGroup\fR \fIGroup\fR" 4
+.IX Item "SocketGroup Group"
+If running as root change the group of the UNIX-socket after it has been
+created. Defaults to \fBcollectd\fR.
+.IP "\fBSocketPerms\fR \fIPermissions\fR" 4
+.IX Item "SocketPerms Permissions"
+Change the file permissions of the UNIX-socket after it has been created. The
+permissions must be given as a numeric, octal value as you would pass to
+\&\fIchmod\fR\|(1). Defaults to \fB0770\fR.
+.IP "\fBDeleteSocket\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "DeleteSocket false|true"
+If set to \fBtrue\fR, delete the socket file before calling \fIbind\fR\|(2), if a file
+with the given name already exists. If \fIcollectd\fR crashes a socket file may be
+left over, preventing the daemon from opening a new socket when restarted.
+Since this is potentially dangerous, this defaults to \fBfalse\fR.
+.ie n .SS "Plugin ""uuid"""
+.el .SS "Plugin \f(CWuuid\fP"
+.IX Subsection "Plugin uuid"
+This plugin, if loaded, causes the Hostname to be taken from the machine's
+\&\s-1UUID.\s0 The \s-1UUID\s0 is a universally unique designation for the machine, usually
+taken from the machine's \s-1BIOS.\s0 This is most useful if the machine is running in
+a virtual environment such as Xen, in which case the \s-1UUID\s0 is preserved across
+shutdowns and migration.
+.PP
+The following methods are used to find the machine's \s-1UUID,\s0 in order:
+.IP "\(bu" 4
+Check \fI/etc/uuid\fR (or \fIUUIDFile\fR).
+.IP "\(bu" 4
+Check for \s-1UUID\s0 from \s-1HAL \s0(<http://www.freedesktop.org/wiki/Software/hal>) if
+present.
+.IP "\(bu" 4
+Check for \s-1UUID\s0 from \f(CW\*(C`dmidecode\*(C'\fR / \s-1SMBIOS.\s0
+.IP "\(bu" 4
+Check for \s-1UUID\s0 from Xen hypervisor.
+.PP
+If no \s-1UUID\s0 can be found then the hostname is not modified.
+.IP "\fBUUIDFile\fR \fIPath\fR" 4
+.IX Item "UUIDFile Path"
+Take the \s-1UUID\s0 from the given file (default \fI/etc/uuid\fR).
+.ie n .SS "Plugin ""varnish"""
+.el .SS "Plugin \f(CWvarnish\fP"
+.IX Subsection "Plugin varnish"
+The \fIvarnish plugin\fR collects information about Varnish, an \s-1HTTP\s0 accelerator.
+It collects a subset of the values displayed by \fIvarnishstat\fR\|(1), and
+organizes them in categories which can be enabled or disabled. Currently only
+metrics shown in \fIvarnishstat\fR\|(1)'s \fI\s-1MAIN\s0\fR section are collected. The exact
+meaning of each metric can be found in \fIvarnish\-counters\fR\|(7).
+.PP
+Synopsis:
+.PP
+.Vb 10
+\& <Plugin "varnish">
+\&   <Instance "example">
+\&     CollectBackend     true
+\&     CollectBan         false
+\&     CollectCache       true
+\&     CollectConnections true
+\&     CollectDirectorDNS false
+\&     CollectESI         false
+\&     CollectFetch       false
+\&     CollectHCB         false
+\&     CollectObjects     false
+\&     CollectPurge       false
+\&     CollectSession     false
+\&     CollectSHM         true
+\&     CollectSMA         false
+\&     CollectSMS         false
+\&     CollectSM          false
+\&     CollectStruct      false
+\&     CollectTotals      false
+\&     CollectUptime      false
+\&     CollectVCL         false
+\&     CollectVSM         false
+\&     CollectWorkers     false
+\&   </Instance>
+\& </Plugin>
+.Ve
+.PP
+The configuration consists of one or more <\fBInstance\fR\ \fIName\fR>
+blocks. \fIName\fR is the parameter passed to \*(L"varnishd \-n\*(R". If left empty, it
+will collectd statistics from the default \*(L"varnishd\*(R" instance (this should work
+fine in most cases).
+.PP
+Inside each <\fBInstance\fR> blocks, the following options are recognized:
+.IP "\fBCollectBackend\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectBackend true|false"
+Back-end connection statistics, such as successful, reused,
+and closed connections. True by default.
+.IP "\fBCollectBan\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectBan true|false"
+Statistics about ban operations, such as number of bans added, retired, and
+number of objects tested against ban operations. Only available with Varnish
+3.x and above. False by default.
+.IP "\fBCollectCache\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectCache true|false"
+Cache hits and misses. True by default.
+.IP "\fBCollectConnections\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectConnections true|false"
+Number of client connections received, accepted and dropped. True by default.
+.IP "\fBCollectDirectorDNS\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectDirectorDNS true|false"
+\&\s-1DNS\s0 director lookup cache statistics. Only available with Varnish 3.x. False by
+default.
+.IP "\fBCollectESI\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectESI true|false"
+Edge Side Includes (\s-1ESI\s0) parse statistics. False by default.
+.IP "\fBCollectFetch\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectFetch true|false"
+Statistics about fetches (\s-1HTTP\s0 requests sent to the backend). False by default.
+.IP "\fBCollectHCB\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectHCB true|false"
+Inserts and look-ups in the crit bit tree based hash. Look-ups are
+divided into locked and unlocked look-ups. False by default.
+.IP "\fBCollectObjects\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectObjects true|false"
+Statistics on cached objects: number of objects expired, nuked (prematurely
+expired), saved, moved, etc. False by default.
+.IP "\fBCollectPurge\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectPurge true|false"
+Statistics about purge operations, such as number of purges added, retired, and
+number of objects tested against purge operations. Only available with Varnish
+2.x. False by default.
+.IP "\fBCollectSession\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectSession true|false"
+Client session statistics. Number of past and current sessions, session herd and
+linger counters, etc. False by default. Note that if using Varnish 4.x, some
+metrics found in the Connections and Threads sections with previous versions of
+Varnish have been moved here.
+.IP "\fBCollectSHM\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectSHM true|false"
+Statistics about the shared memory log, a memory region to store
+log messages which is flushed to disk when full. True by default.
+.IP "\fBCollectSMA\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectSMA true|false"
+malloc or umem (umem_alloc(3MALLOC) based) storage statistics. The umem storage
+component is Solaris specific. Only available with Varnish 2.x. False by
+default.
+.IP "\fBCollectSMS\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectSMS true|false"
+synth (synthetic content) storage statistics. This storage
+component is used internally only. False by default.
+.IP "\fBCollectSM\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectSM true|false"
+file (memory mapped file) storage statistics. Only available with Varnish 2.x.
+False by default.
+.IP "\fBCollectStruct\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectStruct true|false"
+Current varnish internal state statistics. Number of current sessions, objects
+in cache store, open connections to backends (with Varnish 2.x), etc. False by
+default.
+.IP "\fBCollectTotals\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectTotals true|false"
+Collects overview counters, such as the number of sessions created,
+the number of requests and bytes transferred. False by default.
+.IP "\fBCollectUptime\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectUptime true|false"
+Varnish uptime. Only available with Varnish 3.x and above. False by default.
+.IP "\fBCollectVCL\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectVCL true|false"
+Number of total (available + discarded) \s-1VCL \s0(config files). False by default.
+.IP "\fBCollectVSM\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectVSM true|false"
+Collect statistics about Varnish's shared memory usage (used by the logging and
+statistics subsystems). Only available with Varnish 4.x. False by default.
+.IP "\fBCollectWorkers\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "CollectWorkers true|false"
+Collect statistics about worker threads. False by default.
+.ie n .SS "Plugin ""virt"""
+.el .SS "Plugin \f(CWvirt\fP"
+.IX Subsection "Plugin virt"
+This plugin allows \s-1CPU,\s0 disk and network load to be collected for virtualized
+guests on the machine. This means that these metrics can be collected for guest
+systems without installing any software on them \- \fIcollectd\fR only runs on the
+host system. The statistics are collected through libvirt
+(<http://libvirt.org/>).
+.PP
+Only \fIConnection\fR is required.
+.IP "\fBConnection\fR \fIuri\fR" 4
+.IX Item "Connection uri"
+Connect to the hypervisor given by \fIuri\fR. For example if using Xen use:
+.Sp
+.Vb 1
+\& Connection "xen:///"
+.Ve
+.Sp
+Details which URIs allowed are given at <http://libvirt.org/uri.html>.
+.IP "\fBRefreshInterval\fR \fIseconds\fR" 4
+.IX Item "RefreshInterval seconds"
+Refresh the list of domains and devices every \fIseconds\fR. The default is 60
+seconds. Setting this to be the same or smaller than the \fIInterval\fR will cause
+the list of domains and devices to be refreshed on every iteration.
+.Sp
+Refreshing the devices in particular is quite a costly operation, so if your
+virtualization setup is static you might consider increasing this. If this
+option is set to 0, refreshing is disabled completely.
+.IP "\fBDomain\fR \fIname\fR" 4
+.IX Item "Domain name"
+.PD 0
+.IP "\fBBlockDevice\fR \fIname:dev\fR" 4
+.IX Item "BlockDevice name:dev"
+.IP "\fBInterfaceDevice\fR \fIname:dev\fR" 4
+.IX Item "InterfaceDevice name:dev"
+.IP "\fBIgnoreSelected\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "IgnoreSelected true|false"
+.PD
+Select which domains and devices are collected.
+.Sp
+If \fIIgnoreSelected\fR is not given or \fBfalse\fR then only the listed domains and
+disk/network devices are collected.
+.Sp
+If \fIIgnoreSelected\fR is \fBtrue\fR then the test is reversed and the listed
+domains and disk/network devices are ignored, while the rest are collected.
+.Sp
+The domain name and device names may use a regular expression, if the name is
+surrounded by \fI/.../\fR and collectd was compiled with support for regexps.
+.Sp
+The default is to collect statistics for all domains and all their devices.
+.Sp
+Example:
+.Sp
+.Vb 2
+\& BlockDevice "/:hdb/"
+\& IgnoreSelected "true"
+.Ve
+.Sp
+Ignore all \fIhdb\fR devices on any domain, but other block devices (eg. \fIhda\fR)
+will be collected.
+.IP "\fBHostnameFormat\fR \fBname|uuid|hostname|...\fR" 4
+.IX Item "HostnameFormat name|uuid|hostname|..."
+When the virt plugin logs data, it sets the hostname of the collected data
+according to this setting. The default is to use the guest name as provided by
+the hypervisor, which is equal to setting \fBname\fR.
+.Sp
+\&\fBuuid\fR means use the guest's \s-1UUID.\s0 This is useful if you want to track the
+same guest across migrations.
+.Sp
+\&\fBhostname\fR means to use the global \fBHostname\fR setting, which is probably not
+useful on its own because all guests will appear to have the same name.
+.Sp
+You can also specify combinations of these fields. For example \fBname uuid\fR
+means to concatenate the guest name and \s-1UUID \s0(with a literal colon character
+between, thus \fI\*(L"foo:1234\-1234\-1234\-1234\*(R"\fR).
+.IP "\fBInterfaceFormat\fR \fBname\fR|\fBaddress\fR" 4
+.IX Item "InterfaceFormat name|address"
+When the virt plugin logs interface data, it sets the name of the collected
+data according to this setting. The default is to use the path as provided by
+the hypervisor (the \*(L"dev\*(R" property of the target node), which is equal to
+setting \fBname\fR.
+.Sp
+\&\fBaddress\fR means use the interface's mac address. This is useful since the
+interface path might change between reboots of a guest or across migrations.
+.IP "\fBPluginInstanceFormat\fR \fBname|uuid\fR" 4
+.IX Item "PluginInstanceFormat name|uuid"
+When the virt plugin logs data, it sets the plugin_instance of the collected
+data according to this setting. The default is to use the guest name as provided
+by the hypervisor, which is equal to setting \fBname\fR.
+.Sp
+\&\fBuuid\fR means use the guest's \s-1UUID.\s0
+.ie n .SS "Plugin ""vmem"""
+.el .SS "Plugin \f(CWvmem\fP"
+.IX Subsection "Plugin vmem"
+The \f(CW\*(C`vmem\*(C'\fR plugin collects information about the usage of virtual memory.
+Since the statistics provided by the Linux kernel are very detailed, they are
+collected very detailed. However, to get all the details, you have to switch
+them on manually. Most people just want an overview over, such as the number of
+pages read from swap space.
+.IP "\fBVerbose\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Verbose true|false"
+Enables verbose collection of information. This will start collecting page
+\&\*(L"actions\*(R", e.\ g. page allocations, (de)activations, steals and so on.
+Part of these statistics are collected on a \*(L"per zone\*(R" basis.
+.ie n .SS "Plugin ""vserver"""
+.el .SS "Plugin \f(CWvserver\fP"
+.IX Subsection "Plugin vserver"
+This plugin doesn't have any options. \fBVServer\fR support is only available for
+Linux. It cannot yet be found in a vanilla kernel, though. To make use of this
+plugin you need a kernel that has \fBVServer\fR support built in, i.\ e. you
+need to apply the patches and compile your own kernel, which will then provide
+the \fI/proc/virtual\fR filesystem that is required by this plugin.
+.PP
+The \fBVServer\fR homepage can be found at <http://linux\-vserver.org/>.
+.PP
+\&\fBNote\fR: The traffic collected by this plugin accounts for the amount of
+traffic passing a socket which might be a lot less than the actual on-wire
+traffic (e.\ g. due to headers and retransmission). If you want to
+collect on-wire traffic you could, for example, use the logging facilities of
+iptables to feed data for the guest IPs into the iptables plugin.
+.ie n .SS "Plugin ""write_graphite"""
+.el .SS "Plugin \f(CWwrite_graphite\fP"
+.IX Subsection "Plugin write_graphite"
+The \f(CW\*(C`write_graphite\*(C'\fR plugin writes data to \fIGraphite\fR, an open-source metrics
+storage and graphing project. The plugin connects to \fICarbon\fR, the data layer
+of \fIGraphite\fR, via \fI\s-1TCP\s0\fR or \fI\s-1UDP\s0\fR and sends data via the \*(L"line based\*(R"
+protocol (per default using port\ 2003). The data will be sent in blocks
+of at most 1428 bytes to minimize the number of network packets.
+.PP
+Synopsis:
+.PP
+.Vb 9
+\& <Plugin write_graphite>
+\&   <Node "example">
+\&     Host "localhost"
+\&     Port "2003"
+\&     Protocol "tcp"
+\&     LogSendErrors true
+\&     Prefix "collectd"
+\&   </Node>
+\& </Plugin>
+.Ve
+.PP
+The configuration consists of one or more <\fBNode\fR\ \fIName\fR>
+blocks. Inside the \fBNode\fR blocks, the following options are recognized:
+.IP "\fBHost\fR \fIAddress\fR" 4
+.IX Item "Host Address"
+Hostname or address to connect to. Defaults to \f(CW\*(C`localhost\*(C'\fR.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+Service name or port number to connect to. Defaults to \f(CW2003\fR.
+.IP "\fBProtocol\fR \fIString\fR" 4
+.IX Item "Protocol String"
+Protocol to use when connecting to \fIGraphite\fR. Defaults to \f(CW\*(C`tcp\*(C'\fR.
+.IP "\fBLogSendErrors\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "LogSendErrors false|true"
+If set to \fBtrue\fR (the default), logs errors when sending data to \fIGraphite\fR.
+If set to \fBfalse\fR, it will not log the errors. This is especially useful when
+using Protocol \s-1UDP\s0 since many times we want to use the \*(L"fire-and-forget\*(R"
+approach and logging errors fills syslog with unneeded messages.
+.IP "\fBPrefix\fR \fIString\fR" 4
+.IX Item "Prefix String"
+When set, \fIString\fR is added in front of the host name. Dots and whitespace are
+\&\fInot\fR escaped in this string (see \fBEscapeCharacter\fR below).
+.IP "\fBPostfix\fR \fIString\fR" 4
+.IX Item "Postfix String"
+When set, \fIString\fR is appended to the host name. Dots and whitespace are
+\&\fInot\fR escaped in this string (see \fBEscapeCharacter\fR below).
+.IP "\fBEscapeCharacter\fR \fIChar\fR" 4
+.IX Item "EscapeCharacter Char"
+\&\fICarbon\fR uses the dot (\f(CW\*(C`.\*(C'\fR) as escape character and doesn't allow whitespace
+in the identifier. The \fBEscapeCharacter\fR option determines which character
+dots, whitespace and control characters are replaced with. Defaults to
+underscore (\f(CW\*(C`_\*(C'\fR).
+.IP "\fBStoreRates\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "StoreRates false|true"
+If set to \fBtrue\fR (the default), convert counter values to rates. If set to
+\&\fBfalse\fR counter values are stored as is, i.\ e. as an increasing integer
+number.
+.IP "\fBSeparateInstances\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "SeparateInstances false|true"
+If set to \fBtrue\fR, the plugin instance and type instance will be in their own
+path component, for example \f(CW\*(C`host.cpu.0.cpu.idle\*(C'\fR. If set to \fBfalse\fR (the
+default), the plugin and plugin instance (and likewise the type and type
+instance) are put into one component, for example \f(CW\*(C`host.cpu\-0.cpu\-idle\*(C'\fR.
+.IP "\fBAlwaysAppendDS\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "AlwaysAppendDS false|true"
+If set to \fBtrue\fR, append the name of the \fIData Source\fR (\s-1DS\s0) to the \*(L"metric\*(R"
+identifier. If set to \fBfalse\fR (the default), this is only done when there is
+more than one \s-1DS.\s0
+.ie n .SS "Plugin ""write_tsdb"""
+.el .SS "Plugin \f(CWwrite_tsdb\fP"
+.IX Subsection "Plugin write_tsdb"
+The \f(CW\*(C`write_tsdb\*(C'\fR plugin writes data to \fIOpenTSDB\fR, a scalable open-source
+time series database. The plugin connects to a \fI\s-1TSD\s0\fR, a masterless, no shared
+state daemon that ingests metrics and stores them in HBase. The plugin uses
+\&\fI\s-1TCP\s0\fR over the \*(L"line based\*(R" protocol with a default port 4242. The data will
+be sent in blocks of at most 1428 bytes to minimize the number of network
+packets.
+.PP
+Synopsis:
+.PP
+.Vb 7
+\& <Plugin write_tsdb>
+\&   <Node "example">
+\&     Host "tsd\-1.my.domain"
+\&     Port "4242"
+\&     HostTags "status=production"
+\&   </Node>
+\& </Plugin>
+.Ve
+.PP
+The configuration consists of one or more <\fBNode\fR\ \fIName\fR>
+blocks. Inside the \fBNode\fR blocks, the following options are recognized:
+.IP "\fBHost\fR \fIAddress\fR" 4
+.IX Item "Host Address"
+Hostname or address to connect to. Defaults to \f(CW\*(C`localhost\*(C'\fR.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+Service name or port number to connect to. Defaults to \f(CW4242\fR.
+.IP "\fBHostTags\fR \fIString\fR" 4
+.IX Item "HostTags String"
+When set, \fIHostTags\fR is added to the end of the metric. It is intended to be
+used for name=value pairs that the \s-1TSD\s0 will tag the metric with. Dots and
+whitespace are \fInot\fR escaped in this string.
+.IP "\fBStoreRates\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "StoreRates false|true"
+If set to \fBtrue\fR, convert counter values to rates. If set to \fBfalse\fR
+(the default) counter values are stored as is, as an increasing
+integer number.
+.IP "\fBAlwaysAppendDS\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "AlwaysAppendDS false|true"
+If set the \fBtrue\fR, append the name of the \fIData Source\fR (\s-1DS\s0) to the \*(L"metric\*(R"
+identifier. If set to \fBfalse\fR (the default), this is only done when there is
+more than one \s-1DS.\s0
+.ie n .SS "Plugin ""write_mongodb"""
+.el .SS "Plugin \f(CWwrite_mongodb\fP"
+.IX Subsection "Plugin write_mongodb"
+The \fIwrite_mongodb plugin\fR will send values to \fIMongoDB\fR, a schema-less
+NoSQL database.
+.PP
+\&\fBSynopsis:\fR
+.PP
+.Vb 8
+\& <Plugin "write_mongodb">
+\&   <Node "default">
+\&     Host "localhost"
+\&     Port "27017"
+\&     Timeout 1000
+\&     StoreRates true
+\&   </Node>
+\& </Plugin>
+.Ve
+.PP
+The plugin can send values to multiple instances of \fIMongoDB\fR by specifying
+one \fBNode\fR block for each instance. Within the \fBNode\fR blocks, the following
+options are available:
+.IP "\fBHost\fR \fIAddress\fR" 4
+.IX Item "Host Address"
+Hostname or address to connect to. Defaults to \f(CW\*(C`localhost\*(C'\fR.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+Service name or port number to connect to. Defaults to \f(CW27017\fR.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+Set the timeout for each operation on \fIMongoDB\fR to \fITimeout\fR milliseconds.
+Setting this option to zero means no timeout, which is the default.
+.IP "\fBStoreRates\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "StoreRates false|true"
+If set to \fBtrue\fR (the default), convert counter values to rates. If set to
+\&\fBfalse\fR counter values are stored as is, i.e. as an increasing integer
+number.
+.IP "\fBDatabase\fR \fIDatabase\fR" 4
+.IX Item "Database Database"
+.PD 0
+.IP "\fBUser\fR \fIUser\fR" 4
+.IX Item "User User"
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+.PD
+Sets the information used when authenticating to a \fIMongoDB\fR database. The
+fields are optional (in which case no authentication is attempted), but if you
+want to use authentication all three fields must be set.
+.ie n .SS "Plugin ""write_http"""
+.el .SS "Plugin \f(CWwrite_http\fP"
+.IX Subsection "Plugin write_http"
+This output plugin submits values to an \s-1HTTP\s0 server using \s-1POST\s0 requests and
+encoding metrics with \s-1JSON\s0 or using the \f(CW\*(C`PUTVAL\*(C'\fR command described in
+\&\fIcollectd\-unixsock\fR\|(5).
+.PP
+Synopsis:
+.PP
+.Vb 8
+\& <Plugin "write_http">
+\&   <Node "example">
+\&     URL "http://example.com/post\-collectd"
+\&     User "collectd"
+\&     Password "weCh3ik0"
+\&     Format JSON
+\&   </Node>
+\& </Plugin>
+.Ve
+.PP
+The plugin can send values to multiple \s-1HTTP\s0 servers by specifying one
+<\fBNode\fR\ \fIName\fR> block for each server. Within each \fBNode\fR
+block, the following options are available:
+.IP "\fB\s-1URL\s0\fR \fI\s-1URL\s0\fR" 4
+.IX Item "URL URL"
+\&\s-1URL\s0 to which the values are submitted to. Mandatory.
+.IP "\fBUser\fR \fIUsername\fR" 4
+.IX Item "User Username"
+Optional user name needed for authentication.
+.IP "\fBPassword\fR \fIPassword\fR" 4
+.IX Item "Password Password"
+Optional password needed for authentication.
+.IP "\fBVerifyPeer\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "VerifyPeer true|false"
+Enable or disable peer \s-1SSL\s0 certificate verification. See
+<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+.IP "\fBVerifyHost\fR \fBtrue|false\fR" 4
+.IX Item "VerifyHost true|false"
+Enable or disable peer host name verification. If enabled, the plugin checks if
+the \f(CW\*(C`Common Name\*(C'\fR or a \f(CW\*(C`Subject Alternate Name\*(C'\fR field of the \s-1SSL\s0 certificate
+matches the host name provided by the \fB\s-1URL\s0\fR option. If this identity check
+fails, the connection is aborted. Obviously, only works when connecting to a
+\&\s-1SSL\s0 enabled server. Enabled by default.
+.IP "\fBCACert\fR \fIFile\fR" 4
+.IX Item "CACert File"
+File that holds one or more \s-1SSL\s0 certificates. If you want to use \s-1HTTPS\s0 you will
+possibly need this option. What \s-1CA\s0 certificates come bundled with \f(CW\*(C`libcurl\*(C'\fR
+and are checked by default depends on the distribution you use.
+.IP "\fBCAPath\fR \fIDirectory\fR" 4
+.IX Item "CAPath Directory"
+Directory holding one or more \s-1CA\s0 certificate files. You can use this if for
+some reason all the needed \s-1CA\s0 certificates aren't in the same file and can't be
+pointed to using the \fBCACert\fR option. Requires \f(CW\*(C`libcurl\*(C'\fR to be built against
+OpenSSL.
+.IP "\fBClientKey\fR \fIFile\fR" 4
+.IX Item "ClientKey File"
+File that holds the private key in \s-1PEM\s0 format to be used for certificate-based
+authentication.
+.IP "\fBClientCert\fR \fIFile\fR" 4
+.IX Item "ClientCert File"
+File that holds the \s-1SSL\s0 certificate to be used for certificate-based
+authentication.
+.IP "\fBClientKeyPass\fR \fIPassword\fR" 4
+.IX Item "ClientKeyPass Password"
+Password required to load the private key in \fBClientKey\fR.
+.IP "\fBSSLVersion\fR \fBSSLv2\fR|\fBSSLv3\fR|\fBTLSv1\fR|\fBTLSv1_0\fR|\fBTLSv1_1\fR|\fBTLSv1_2\fR" 4
+.IX Item "SSLVersion SSLv2|SSLv3|TLSv1|TLSv1_0|TLSv1_1|TLSv1_2"
+Define which \s-1SSL\s0 protocol version must be used. By default \f(CW\*(C`libcurl\*(C'\fR will
+attempt to figure out the remote \s-1SSL\s0 protocol version. See
+\&\fIcurl_easy_setopt\fR\|(3) for more details.
+.IP "\fBFormat\fR \fBCommand\fR|\fB\s-1JSON\s0\fR" 4
+.IX Item "Format Command|JSON"
+Format of the output to generate. If set to \fBCommand\fR, will create output that
+is understood by the \fIExec\fR and \fIUnixSock\fR plugins. When set to \fB\s-1JSON\s0\fR, will
+create output in the \fIJavaScript Object Notation\fR (\s-1JSON\s0).
+.Sp
+Defaults to \fBCommand\fR.
+.IP "\fBStoreRates\fR \fBtrue|false\fR" 4
+.IX Item "StoreRates true|false"
+If set to \fBtrue\fR, convert counter values to rates. If set to \fBfalse\fR (the
+default) counter values are stored as is, i.e. as an increasing integer number.
+.IP "\fBBufferSize\fR \fIBytes\fR" 4
+.IX Item "BufferSize Bytes"
+Sets the send buffer size to \fIBytes\fR. By increasing this buffer, less \s-1HTTP\s0
+requests will be generated, but more metrics will be batched / metrics are
+cached for longer before being sent, introducing additional delay until they
+are available on the server side. \fIBytes\fR must be at least 1024 and cannot
+exceed the size of an \f(CW\*(C`int\*(C'\fR, i.e. 2\ GByte.
+Defaults to \f(CW4096\fR.
+.IP "\fBLowSpeedLimit\fR \fIBytes per Second\fR" 4
+.IX Item "LowSpeedLimit Bytes per Second"
+Sets the minimal transfer rate in \fIBytes per Second\fR below which the
+connection with the \s-1HTTP\s0 server will be considered too slow and aborted. All
+the data submitted over this connection will probably be lost. Defaults to 0,
+which means no minimum transfer rate is enforced.
+.IP "\fBTimeout\fR \fITimeout\fR" 4
+.IX Item "Timeout Timeout"
+Sets the maximum time in milliseconds given for \s-1HTTP POST\s0 operations to
+complete. When this limit is reached, the \s-1POST\s0 operation will be aborted, and
+all the data in the current send buffer will probably be lost. Defaults to 0,
+which means the connection never times out.
+.Sp
+The \f(CW\*(C`write_http\*(C'\fR plugin regularly submits the collected values to the \s-1HTTP\s0
+server. How frequently this happens depends on how much data you are collecting
+and the size of \fBBufferSize\fR. The optimal value to set \fBTimeout\fR to is
+slightly below this interval, which you can estimate by monitoring the network
+traffic between collectd and the \s-1HTTP\s0 server.
+.ie n .SS "Plugin ""write_kafka"""
+.el .SS "Plugin \f(CWwrite_kafka\fP"
+.IX Subsection "Plugin write_kafka"
+The \fIwrite_kafka plugin\fR will send values to a \fIKafka\fR topic, a distributed
+queue.
+Synopsis:
+.PP
+.Vb 6
+\& <Plugin "write_kafka">
+\&   Property "metadata.broker.list" "broker1:9092,broker2:9092"
+\&   <Topic "collectd">
+\&     Format JSON
+\&   </Topic>
+\& </Plugin>
+.Ve
+.PP
+The following options are understood by the \fIwrite_kafka plugin\fR:
+.IP "<\fBTopic\fR \fIName\fR>" 4
+.IX Item "<Topic Name>"
+The plugin's configuration consists of one or more \fBTopic\fR blocks. Each block
+is given a unique \fIName\fR and specifies one kafka producer.
+Inside the \fBTopic\fR block, the following per-topic options are
+understood:
+.RS 4
+.IP "\fBProperty\fR \fIString\fR \fIString\fR" 4
+.IX Item "Property String String"
+Configure the named property for the current topic. Properties are
+forwarded to the kafka producer library \fBlibrdkafka\fR.
+.IP "\fBKey\fR \fIString\fR" 4
+.IX Item "Key String"
+Use the specified string as a partioning key for the topic. Kafka breaks
+topic into partitions and guarantees that for a given topology, the same
+consumer will be used for a specific key. The special (case insensitive)
+string \fBRandom\fR can be used to specify that an arbitrary partition should
+be used.
+.IP "\fBFormat\fR \fBCommand\fR|\fB\s-1JSON\s0\fR|\fBGraphite\fR" 4
+.IX Item "Format Command|JSON|Graphite"
+Selects the format in which messages are sent to the broker. If set to
+\&\fBCommand\fR (the default), values are sent as \f(CW\*(C`PUTVAL\*(C'\fR commands which are
+identical to the syntax used by the \fIExec\fR and \fIUnixSock plugins\fR.
+.Sp
+If set to \fB\s-1JSON\s0\fR, the values are encoded in the \fIJavaScript Object Notation\fR,
+an easy and straight forward exchange format.
+.Sp
+If set to \fBGraphite\fR, values are encoded in the \fIGraphite\fR format, which is
+\&\f(CW\*(C`<metric> <value> <timestamp>\en\*(C'\fR.
+.IP "\fBStoreRates\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "StoreRates true|false"
+Determines whether or not \f(CW\*(C`COUNTER\*(C'\fR, \f(CW\*(C`DERIVE\*(C'\fR and \f(CW\*(C`ABSOLUTE\*(C'\fR data sources
+are converted to a \fIrate\fR (i.e. a \f(CW\*(C`GAUGE\*(C'\fR value). If set to \fBfalse\fR (the
+default), no conversion is performed. Otherwise the conversion is performed
+using the internal value cache.
+.Sp
+Please note that currently this option is only used if the \fBFormat\fR option has
+been set to \fB\s-1JSON\s0\fR.
+.IP "\fBGraphitePrefix\fR (\fBFormat\fR=\fIGraphite\fR only)" 4
+.IX Item "GraphitePrefix (Format=Graphite only)"
+A prefix can be added in the metric name when outputting in the \fIGraphite\fR
+format. It's added before the \fIHost\fR name.
+Metric name will be
+\&\f(CW\*(C`<prefix><host><postfix><plugin><type><name>\*(C'\fR
+.IP "\fBGraphitePostfix\fR (\fBFormat\fR=\fIGraphite\fR only)" 4
+.IX Item "GraphitePostfix (Format=Graphite only)"
+A postfix can be added in the metric name when outputting in the \fIGraphite\fR
+format. It's added after the \fIHost\fR name.
+Metric name will be
+\&\f(CW\*(C`<prefix><host><postfix><plugin><type><name>\*(C'\fR
+.IP "\fBGraphiteEscapeChar\fR (\fBFormat\fR=\fIGraphite\fR only)" 4
+.IX Item "GraphiteEscapeChar (Format=Graphite only)"
+Specify a character to replace dots (.) in the host part of the metric name.
+In \fIGraphite\fR metric name, dots are used as separators between different
+metric parts (host, plugin, type).
+Default is \f(CW\*(C`_\*(C'\fR (\fIUnderscore\fR).
+.IP "\fBGraphiteSeparateInstances\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "GraphiteSeparateInstances false|true"
+If set to \fBtrue\fR, the plugin instance and type instance will be in their own
+path component, for example \f(CW\*(C`host.cpu.0.cpu.idle\*(C'\fR. If set to \fBfalse\fR (the
+default), the plugin and plugin instance (and likewise the type and type
+instance) are put into one component, for example \f(CW\*(C`host.cpu\-0.cpu\-idle\*(C'\fR.
+.IP "\fBStoreRates\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "StoreRates true|false"
+If set to \fBtrue\fR (the default), convert counter values to rates. If set to
+\&\fBfalse\fR counter values are stored as is, i.e. as an increasing integer number.
+.Sp
+This will be reflected in the \f(CW\*(C`ds_type\*(C'\fR tag: If \fBStoreRates\fR is enabled,
+converted values will have \*(L"rate\*(R" appended to the data source type, e.g.
+\&\f(CW\*(C`ds_type:derive:rate\*(C'\fR.
+.RE
+.RS 4
+.RE
+.IP "\fBProperty\fR \fIString\fR \fIString\fR" 4
+.IX Item "Property String String"
+Configure the kafka producer through properties, you almost always will
+want to set \fBmetadata.broker.list\fR to your Kafka broker list.
+.ie n .SS "Plugin ""write_redis"""
+.el .SS "Plugin \f(CWwrite_redis\fP"
+.IX Subsection "Plugin write_redis"
+The \fIwrite_redis plugin\fR submits values to \fIRedis\fR, a data structure server.
+.PP
+Synopsis:
+.PP
+.Vb 7
+\&  <Plugin "write_redis">
+\&    <Node "example">
+\&        Host "localhost"
+\&        Port "6379"
+\&        Timeout 1000
+\&    </Node>
+\&  </Plugin>
+.Ve
+.PP
+Values are submitted to \fISorted Sets\fR, using the metric name as the key, and
+the timestamp as the score. Retrieving a date range can then be done using the
+\&\f(CW\*(C`ZRANGEBYSCORE\*(C'\fR \fIRedis\fR command. Additionnally, all the identifiers of these
+\&\fISorted Sets\fR are kept in a \fISet\fR called \f(CW\*(C`collectd/values\*(C'\fR and can be
+retrieved using the \f(CW\*(C`SMEMBERS\*(C'\fR \fIRedis\fR command. See
+<http://redis.io/commands#sorted_set> and <http://redis.io/commands#set> for
+details.
+.PP
+The information shown in the synopsis above is the \fIdefault configuration\fR
+which is used by the plugin if no configuration is present.
+.PP
+The plugin can send values to multiple instances of \fIRedis\fR by specifying
+one \fBNode\fR block for each instance. Within the \fBNode\fR blocks, the following
+options are available:
+.IP "\fBNode\fR \fINodename\fR" 4
+.IX Item "Node Nodename"
+The \fBNode\fR block identifies a new \fIRedis\fR node, that is a new \fIRedis\fR
+instance running in an specified host and port. The name for node is a
+canonical identifier which is used as \fIplugin instance\fR. It is limited to
+64\ characters in length.
+.IP "\fBHost\fR \fIHostname\fR" 4
+.IX Item "Host Hostname"
+The \fBHost\fR option is the hostname or IP-address where the \fIRedis\fR instance is
+running on.
+.IP "\fBPort\fR \fIPort\fR" 4
+.IX Item "Port Port"
+The \fBPort\fR option is the \s-1TCP\s0 port on which the Redis instance accepts
+connections. Either a service name of a port number may be given. Please note
+that numerical port numbers must be given as a string, too.
+.IP "\fBTimeout\fR \fIMilliseconds\fR" 4
+.IX Item "Timeout Milliseconds"
+The \fBTimeout\fR option sets the socket connection timeout, in milliseconds.
+.ie n .SS "Plugin ""write_riemann"""
+.el .SS "Plugin \f(CWwrite_riemann\fP"
+.IX Subsection "Plugin write_riemann"
+The \fIwrite_riemann plugin\fR will send values to \fIRiemann\fR, a powerful stream
+aggregation and monitoring system. The plugin sends \fIProtobuf\fR encoded data to
+\&\fIRiemann\fR using \s-1UDP\s0 packets.
+.PP
+Synopsis:
+.PP
+.Vb 12
+\& <Plugin "write_riemann">
+\&   <Node "example">
+\&     Host "localhost"
+\&     Port "5555"
+\&     Protocol UDP
+\&     StoreRates true
+\&     AlwaysAppendDS false
+\&     TTLFactor 2.0
+\&   </Node>
+\&   Tag "foobar"
+\&   Attribute "foo" "bar"
+\& </Plugin>
+.Ve
+.PP
+The following options are understood by the \fIwrite_riemann plugin\fR:
+.IP "<\fBNode\fR \fIName\fR>" 4
+.IX Item "<Node Name>"
+The plugin's configuration consists of one or more \fBNode\fR blocks. Each block
+is given a unique \fIName\fR and specifies one connection to an instance of
+\&\fIRiemann\fR. Indise the \fBNode\fR block, the following per-connection options are
+understood:
+.RS 4
+.IP "\fBHost\fR \fIAddress\fR" 4
+.IX Item "Host Address"
+Hostname or address to connect to. Defaults to \f(CW\*(C`localhost\*(C'\fR.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+Service name or port number to connect to. Defaults to \f(CW5555\fR.
+.IP "\fBProtocol\fR \fB\s-1UDP\s0\fR|\fB\s-1TCP\s0\fR" 4
+.IX Item "Protocol UDP|TCP"
+Specify the protocol to use when communicating with \fIRiemann\fR. Defaults to
+\&\fB\s-1TCP\s0\fR.
+.IP "\fBBatch\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Batch true|false"
+If set to \fBtrue\fR and \fBProtocol\fR is set to \fB\s-1TCP\s0\fR,
+events will be batched in memory and flushed at
+regular intervals or when \fBBatchMaxSize\fR is exceeded.
+.Sp
+Notifications are not batched and sent as soon as possible.
+.Sp
+When enabled, it can occur that events get processed by the Riemann server
+close to or after their expiration time. Tune the \fBTTLFactor\fR and
+\&\fBBatchMaxSize\fR settings according to the amount of values collected, if this
+is an issue.
+.Sp
+Defaults to true
+.IP "\fBBatchMaxSize\fR \fIsize\fR" 4
+.IX Item "BatchMaxSize size"
+Maximum payload size for a riemann packet. Defaults to 8192
+.IP "\fBStoreRates\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "StoreRates true|false"
+If set to \fBtrue\fR (the default), convert counter values to rates. If set to
+\&\fBfalse\fR counter values are stored as is, i.e. as an increasing integer number.
+.Sp
+This will be reflected in the \f(CW\*(C`ds_type\*(C'\fR tag: If \fBStoreRates\fR is enabled,
+converted values will have \*(L"rate\*(R" appended to the data source type, e.g.
+\&\f(CW\*(C`ds_type:derive:rate\*(C'\fR.
+.IP "\fBAlwaysAppendDS\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "AlwaysAppendDS false|true"
+If set the \fBtrue\fR, append the name of the \fIData Source\fR (\s-1DS\s0) to the
+\&\*(L"service\*(R", i.e. the field that, together with the \*(L"host\*(R" field, uniquely
+identifies a metric in \fIRiemann\fR. If set to \fBfalse\fR (the default), this is
+only done when there is more than one \s-1DS.\s0
+.IP "\fBTTLFactor\fR \fIFactor\fR" 4
+.IX Item "TTLFactor Factor"
+\&\fIRiemann\fR events have a \fITime to Live\fR (\s-1TTL\s0) which specifies how long each
+event is considered active. \fIcollectd\fR populates this field based on the
+metrics interval setting. This setting controls the factor with which the
+interval is multiplied to set the \s-1TTL.\s0 The default value is \fB2.0\fR. Unless you
+know exactly what you're doing, you should only increase this setting from its
+default value.
+.IP "\fBNotifications\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "Notifications false|true"
+If set to \fBtrue\fR, create riemann events for notifications. This is \fBtrue\fR
+by default. When processing thresholds from write_riemann, it might prove
+useful to avoid getting notification events.
+.IP "\fBCheckThresholds\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "CheckThresholds false|true"
+If set to \fBtrue\fR, attach state to events based on thresholds defined
+in the \fBThreshold\fR plugin. Defaults to \fBfalse\fR.
+.IP "\fBEventServicePrefix\fR \fIString\fR" 4
+.IX Item "EventServicePrefix String"
+Add the given string as a prefix to the event service name.
+If \fBEventServicePrefix\fR not set or set to an empty string (""),
+no prefix will be used.
+.RE
+.RS 4
+.RE
+.IP "\fBTag\fR \fIString\fR" 4
+.IX Item "Tag String"
+Add the given string as an additional tag to the metric being sent to
+\&\fIRiemann\fR.
+.IP "\fBAttribute\fR \fIString\fR \fIString\fR" 4
+.IX Item "Attribute String String"
+Consider the two given strings to be the key and value of an additional
+attribute for each metric being sent out to \fIRiemann\fR.
+.ie n .SS "Plugin ""write_sensu"""
+.el .SS "Plugin \f(CWwrite_sensu\fP"
+.IX Subsection "Plugin write_sensu"
+The \fIwrite_sensu plugin\fR will send values to \fISensu\fR, a powerful stream
+aggregation and monitoring system. The plugin sends \fI\s-1JSON\s0\fR encoded data to
+a local \fISensu\fR client using a \s-1TCP\s0 socket.
+.PP
+At the moment, the \fIwrite_sensu plugin\fR does not send over a collectd_host
+parameter so it is not possible to use one collectd instance as a gateway for
+others. Each collectd host must pair with one \fISensu\fR client.
+.PP
+Synopsis:
+.PP
+.Vb 10
+\& <Plugin "write_sensu">
+\&   <Node "example">
+\&     Host "localhost"
+\&     Port "3030"
+\&     StoreRates true
+\&     AlwaysAppendDS false
+\&     MetricHandler "influx"
+\&     MetricHandler "default"
+\&     NotificationHandler "flapjack"
+\&     NotificationHandler "howling_monkey"
+\&     Notifications true
+\&   </Node>
+\&   Tag "foobar"
+\&   Attribute "foo" "bar"
+\& </Plugin>
+.Ve
+.PP
+The following options are understood by the \fIwrite_sensu plugin\fR:
+.IP "<\fBNode\fR \fIName\fR>" 4
+.IX Item "<Node Name>"
+The plugin's configuration consists of one or more \fBNode\fR blocks. Each block
+is given a unique \fIName\fR and specifies one connection to an instance of
+\&\fISensu\fR. Inside the \fBNode\fR block, the following per-connection options are
+understood:
+.RS 4
+.IP "\fBHost\fR \fIAddress\fR" 4
+.IX Item "Host Address"
+Hostname or address to connect to. Defaults to \f(CW\*(C`localhost\*(C'\fR.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+Service name or port number to connect to. Defaults to \f(CW3030\fR.
+.IP "\fBStoreRates\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "StoreRates true|false"
+If set to \fBtrue\fR (the default), convert counter values to rates. If set to
+\&\fBfalse\fR counter values are stored as is, i.e. as an increasing integer number.
+.Sp
+This will be reflected in the \f(CW\*(C`collectd_data_source_type\*(C'\fR tag: If
+\&\fBStoreRates\fR is enabled, converted values will have \*(L"rate\*(R" appended to the
+data source type, e.g.  \f(CW\*(C`collectd_data_source_type:derive:rate\*(C'\fR.
+.IP "\fBAlwaysAppendDS\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "AlwaysAppendDS false|true"
+If set the \fBtrue\fR, append the name of the \fIData Source\fR (\s-1DS\s0) to the
+\&\*(L"service\*(R", i.e. the field that, together with the \*(L"host\*(R" field, uniquely
+identifies a metric in \fISensu\fR. If set to \fBfalse\fR (the default), this is
+only done when there is more than one \s-1DS.\s0
+.IP "\fBNotifications\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "Notifications false|true"
+If set to \fBtrue\fR, create \fISensu\fR events for notifications. This is \fBfalse\fR
+by default. At least one of \fBNotifications\fR or \fBMetrics\fR should be enabled.
+.IP "\fBMetrics\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "Metrics false|true"
+If set to \fBtrue\fR, create \fISensu\fR events for metrics. This is \fBfalse\fR
+by default. At least one of \fBNotifications\fR or \fBMetrics\fR should be enabled.
+.IP "\fBSeparator\fR \fIString\fR" 4
+.IX Item "Separator String"
+Sets the separator for \fISensu\fR metrics name or checks. Defaults to \*(L"/\*(R".
+.IP "\fBMetricHandler\fR \fIString\fR" 4
+.IX Item "MetricHandler String"
+Add a handler that will be set when metrics are sent to \fISensu\fR. You can add
+several of them, one per line. Defaults to no handler.
+.IP "\fBNotificationHandler\fR \fIString\fR" 4
+.IX Item "NotificationHandler String"
+Add a handler that will be set when notifications are sent to \fISensu\fR. You can
+add several of them, one per line. Defaults to no handler.
+.IP "\fBEventServicePrefix\fR \fIString\fR" 4
+.IX Item "EventServicePrefix String"
+Add the given string as a prefix to the event service name.
+If \fBEventServicePrefix\fR not set or set to an empty string (""),
+no prefix will be used.
+.RE
+.RS 4
+.RE
+.IP "\fBTag\fR \fIString\fR" 4
+.IX Item "Tag String"
+Add the given string as an additional tag to the metric being sent to
+\&\fISensu\fR.
+.IP "\fBAttribute\fR \fIString\fR \fIString\fR" 4
+.IX Item "Attribute String String"
+Consider the two given strings to be the key and value of an additional
+attribute for each metric being sent out to \fISensu\fR.
+.ie n .SS "Plugin ""zookeeper"""
+.el .SS "Plugin \f(CWzookeeper\fP"
+.IX Subsection "Plugin zookeeper"
+The \fIzookeeper plugin\fR will collect statistics from a \fIZookeeper\fR server
+using the mntr command.  It requires Zookeeper 3.4.0+ and access to the
+client port.
+.PP
+\&\fBSynopsis:\fR
+.PP
+.Vb 4
+\& <Plugin "zookeeper">
+\&   Host "127.0.0.1"
+\&   Port "2181"
+\& </Plugin>
+.Ve
+.IP "\fBHost\fR \fIAddress\fR" 4
+.IX Item "Host Address"
+Hostname or address to connect to. Defaults to \f(CW\*(C`localhost\*(C'\fR.
+.IP "\fBPort\fR \fIService\fR" 4
+.IX Item "Port Service"
+Service name or port number to connect to. Defaults to \f(CW2181\fR.
+.SH "THRESHOLD CONFIGURATION"
+.IX Header "THRESHOLD CONFIGURATION"
+Starting with version \f(CW4.3.0\fR collectd has support for \fBmonitoring\fR. By that
+we mean that the values are not only stored or sent somewhere, but that they
+are judged and, if a problem is recognized, acted upon. The only action
+collectd takes itself is to generate and dispatch a \*(L"notification\*(R". Plugins can
+register to receive notifications and perform appropriate further actions.
+.PP
+Since systems and what you expect them to do differ a lot, you can configure
+\&\fBthresholds\fR for your values freely. This gives you a lot of flexibility but
+also a lot of responsibility.
+.PP
+Every time a value is out of range a notification is dispatched. This means
+that the idle percentage of your \s-1CPU\s0 needs to be less then the configured
+threshold only once for a notification to be generated. There's no such thing
+as a moving average or similar \- at least not now.
+.PP
+Also, all values that match a threshold are considered to be relevant or
+\&\*(L"interesting\*(R". As a consequence collectd will issue a notification if they are
+not received for \fBTimeout\fR iterations. The \fBTimeout\fR configuration option is
+explained in section \*(L"\s-1GLOBAL OPTIONS\*(R"\s0. If, for example, \fBTimeout\fR is set to
+\&\*(L"2\*(R" (the default) and some hosts sends it's \s-1CPU\s0 statistics to the server every
+60 seconds, a notification will be dispatched after about 120 seconds. It may
+take a little longer because the timeout is checked only once each \fBInterval\fR
+on the server.
+.PP
+When a value comes within range again or is received after it was missing, an
+\&\*(L"OKAY-notification\*(R" is dispatched.
+.PP
+Here is a configuration example to get you started. Read below for more
+information.
+.PP
+.Vb 9
+\& <Plugin threshold>
+\&   <Type "foo">
+\&     WarningMin    0.00
+\&     WarningMax 1000.00
+\&     FailureMin    0.00
+\&     FailureMax 1200.00
+\&     Invert false
+\&     Instance "bar"
+\&   </Type>
+\&
+\&   <Plugin "interface">
+\&     Instance "eth0"
+\&     <Type "if_octets">
+\&       FailureMax 10000000
+\&       DataSource "rx"
+\&     </Type>
+\&   </Plugin>
+\&
+\&   <Host "hostname">
+\&     <Type "cpu">
+\&       Instance "idle"
+\&       FailureMin 10
+\&     </Type>
+\&
+\&     <Plugin "memory">
+\&       <Type "memory">
+\&         Instance "cached"
+\&         WarningMin 100000000
+\&       </Type>
+\&     </Plugin>
+\&   </Host>
+\& </Plugin>
+.Ve
+.PP
+There are basically two types of configuration statements: The \f(CW\*(C`Host\*(C'\fR,
+\&\f(CW\*(C`Plugin\*(C'\fR, and \f(CW\*(C`Type\*(C'\fR blocks select the value for which a threshold should be
+configured. The \f(CW\*(C`Plugin\*(C'\fR and \f(CW\*(C`Type\*(C'\fR blocks may be specified further using the
+\&\f(CW\*(C`Instance\*(C'\fR option. You can combine the block by nesting the blocks, though
+they must be nested in the above order, i.\ e. \f(CW\*(C`Host\*(C'\fR may contain either
+\&\f(CW\*(C`Plugin\*(C'\fR and \f(CW\*(C`Type\*(C'\fR blocks, \f(CW\*(C`Plugin\*(C'\fR may only contain \f(CW\*(C`Type\*(C'\fR blocks and
+\&\f(CW\*(C`Type\*(C'\fR may not contain other blocks. If multiple blocks apply to the same
+value the most specific block is used.
+.PP
+The other statements specify the threshold to configure. They \fBmust\fR be
+included in a \f(CW\*(C`Type\*(C'\fR block. Currently the following statements are recognized:
+.IP "\fBFailureMax\fR \fIValue\fR" 4
+.IX Item "FailureMax Value"
+.PD 0
+.IP "\fBWarningMax\fR \fIValue\fR" 4
+.IX Item "WarningMax Value"
+.PD
+Sets the upper bound of acceptable values. If unset defaults to positive
+infinity. If a value is greater than \fBFailureMax\fR a \fB\s-1FAILURE\s0\fR notification
+will be created. If the value is greater than \fBWarningMax\fR but less than (or
+equal to) \fBFailureMax\fR a \fB\s-1WARNING\s0\fR notification will be created.
+.IP "\fBFailureMin\fR \fIValue\fR" 4
+.IX Item "FailureMin Value"
+.PD 0
+.IP "\fBWarningMin\fR \fIValue\fR" 4
+.IX Item "WarningMin Value"
+.PD
+Sets the lower bound of acceptable values. If unset defaults to negative
+infinity. If a value is less than \fBFailureMin\fR a \fB\s-1FAILURE\s0\fR notification will
+be created. If the value is less than \fBWarningMin\fR but greater than (or equal
+to) \fBFailureMin\fR a \fB\s-1WARNING\s0\fR notification will be created.
+.IP "\fBDataSource\fR \fIDSName\fR" 4
+.IX Item "DataSource DSName"
+Some data sets have more than one \*(L"data source\*(R". Interesting examples are the
+\&\f(CW\*(C`if_octets\*(C'\fR data set, which has received (\f(CW\*(C`rx\*(C'\fR) and sent (\f(CW\*(C`tx\*(C'\fR) bytes and
+the \f(CW\*(C`disk_ops\*(C'\fR data set, which holds \f(CW\*(C`read\*(C'\fR and \f(CW\*(C`write\*(C'\fR operations. The
+system load data set, \f(CW\*(C`load\*(C'\fR, even has three data sources: \f(CW\*(C`shortterm\*(C'\fR,
+\&\f(CW\*(C`midterm\*(C'\fR, and \f(CW\*(C`longterm\*(C'\fR.
+.Sp
+Normally, all data sources are checked against a configured threshold. If this
+is undesirable, or if you want to specify different limits for each data
+source, you can use the \fBDataSource\fR option to have a threshold apply only to
+one data source.
+.IP "\fBInvert\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Invert true|false"
+If set to \fBtrue\fR the range of acceptable values is inverted, i.\ e.
+values between \fBFailureMin\fR and \fBFailureMax\fR (\fBWarningMin\fR and
+\&\fBWarningMax\fR) are not okay. Defaults to \fBfalse\fR.
+.IP "\fBPersist\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Persist true|false"
+Sets how often notifications are generated. If set to \fBtrue\fR one notification
+will be generated for each value that is out of the acceptable range. If set to
+\&\fBfalse\fR (the default) then a notification is only generated if a value is out
+of range but the previous value was okay.
+.Sp
+This applies to missing values, too: If set to \fBtrue\fR a notification about a
+missing value is generated once every \fBInterval\fR seconds. If set to \fBfalse\fR
+only one such notification is generated until the value appears again.
+.IP "\fBPercentage\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Percentage true|false"
+If set to \fBtrue\fR, the minimum and maximum values given are interpreted as
+percentage value, relative to the other data sources. This is helpful for
+example for the \*(L"df\*(R" type, where you may want to issue a warning when less than
+5\ % of the total space is available. Defaults to \fBfalse\fR.
+.IP "\fBHits\fR \fINumber\fR" 4
+.IX Item "Hits Number"
+Delay creating the notification until the threshold has been passed \fINumber\fR
+times. When a notification has been generated, or when a subsequent value is
+inside the threshold, the counter is reset. If, for example, a value is
+collected once every 10\ seconds and \fBHits\fR is set to 3, a notification
+will be dispatched at most once every 30\ seconds.
+.Sp
+This is useful when short bursts are not a problem. If, for example, 100% \s-1CPU\s0
+usage for up to a minute is normal (and data is collected every
+10\ seconds), you could set \fBHits\fR to \fB6\fR to account for this.
+.IP "\fBHysteresis\fR \fINumber\fR" 4
+.IX Item "Hysteresis Number"
+When set to non-zero, a hysteresis value is applied when checking minimum and
+maximum bounds. This is useful for values that increase slowly and fluctuate a
+bit while doing so. When these values come close to the threshold, they may
+\&\*(L"flap\*(R", i.e. switch between failure / warning case and okay case repeatedly.
+.Sp
+If, for example, the threshold is configures as
+.Sp
+.Vb 2
+\&  WarningMax 100.0
+\&  Hysteresis 1.0
+.Ve
+.Sp
+then a \fIWarning\fR notification is created when the value exceeds \fI101\fR and the
+corresponding \fIOkay\fR notification is only created once the value falls below
+\&\fI99\fR, thus avoiding the \*(L"flapping\*(R".
+.SH "FILTER CONFIGURATION"
+.IX Header "FILTER CONFIGURATION"
+Starting with collectd 4.6 there is a powerful filtering infrastructure
+implemented in the daemon. The concept has mostly been copied from
+\&\fIip_tables\fR, the packet filter infrastructure for Linux. We'll use a similar
+terminology, so that users that are familiar with iptables feel right at home.
+.SS "Terminology"
+.IX Subsection "Terminology"
+The following are the terms used in the remainder of the filter configuration
+documentation. For an ASCII-art schema of the mechanism, see
+\&\*(L"General structure\*(R" below.
+.IP "\fBMatch\fR" 4
+.IX Item "Match"
+A \fImatch\fR is a criteria to select specific values. Examples are, of course, the
+name of the value or it's current value.
+.Sp
+Matches are implemented in plugins which you have to load prior to using the
+match. The name of such plugins starts with the \*(L"match_\*(R" prefix.
+.IP "\fBTarget\fR" 4
+.IX Item "Target"
+A \fItarget\fR is some action that is to be performed with data. Such actions
+could, for example, be to change part of the value's identifier or to ignore
+the value completely.
+.Sp
+Some of these targets are built into the daemon, see \*(L"Built-in targets\*(R"
+below. Other targets are implemented in plugins which you have to load prior to
+using the target. The name of such plugins starts with the \*(L"target_\*(R" prefix.
+.IP "\fBRule\fR" 4
+.IX Item "Rule"
+The combination of any number of matches and at least one target is called a
+\&\fIrule\fR. The target actions will be performed for all values for which \fBall\fR
+matches apply. If the rule does not have any matches associated with it, the
+target action will be performed for all values.
+.IP "\fBChain\fR" 4
+.IX Item "Chain"
+A \fIchain\fR is a list of rules and possibly default targets. The rules are tried
+in order and if one matches, the associated target will be called. If a value
+is handled by a rule, it depends on the target whether or not any subsequent
+rules are considered or if traversal of the chain is aborted, see
+\&\*(L"Flow control\*(R" below. After all rules have been checked, the default targets
+will be executed.
+.SS "General structure"
+.IX Subsection "General structure"
+The following shows the resulting structure:
+.PP
+.Vb 10
+\& +\-\-\-\-\-\-\-\-\-+
+\& ! Chain   !
+\& +\-\-\-\-\-\-\-\-\-+
+\&      !
+\&      V
+\& +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+
+\& ! Rule    !\->! Match   !\->! Match   !\->! Target  !
+\& +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+
+\&      !
+\&      V
+\& +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+
+\& ! Rule    !\->! Target  !\->! Target  !
+\& +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+
+\&      !
+\&      V
+\&      :
+\&      :
+\&      !
+\&      V
+\& +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+
+\& ! Rule    !\->! Match   !\->! Target  !
+\& +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+  +\-\-\-\-\-\-\-\-\-+
+\&      !
+\&      V
+\& +\-\-\-\-\-\-\-\-\-+
+\& ! Default !
+\& ! Target  !
+\& +\-\-\-\-\-\-\-\-\-+
+.Ve
+.SS "Flow control"
+.IX Subsection "Flow control"
+There are four ways to control which way a value takes through the filter
+mechanism:
+.IP "\fBjump\fR" 4
+.IX Item "jump"
+The built-in \fBjump\fR target can be used to \*(L"call\*(R" another chain, i.\ e.
+process the value with another chain. When the called chain finishes, usually
+the next target or rule after the jump is executed.
+.IP "\fBstop\fR" 4
+.IX Item "stop"
+The stop condition, signaled for example by the built-in target \fBstop\fR, causes
+all processing of the value to be stopped immediately.
+.IP "\fBreturn\fR" 4
+.IX Item "return"
+Causes processing in the current chain to be aborted, but processing of the
+value generally will continue. This means that if the chain was called via
+\&\fBJump\fR, the next target or rule after the jump will be executed. If the chain
+was not called by another chain, control will be returned to the daemon and it
+may pass the value to another chain.
+.IP "\fBcontinue\fR" 4
+.IX Item "continue"
+Most targets will signal the \fBcontinue\fR condition, meaning that processing
+should continue normally. There is no special built-in target for this
+condition.
+.SS "Synopsis"
+.IX Subsection "Synopsis"
+The configuration reflects this structure directly:
+.PP
+.Vb 10
+\& PostCacheChain "PostCache"
+\& <Chain "PostCache">
+\&   <Rule "ignore_mysql_show">
+\&     <Match "regex">
+\&       Plugin "^mysql$"
+\&       Type "^mysql_command$"
+\&       TypeInstance "^show_"
+\&     </Match>
+\&     <Target "stop">
+\&     </Target>
+\&   </Rule>
+\&   <Target "write">
+\&     Plugin "rrdtool"
+\&   </Target>
+\& </Chain>
+.Ve
+.PP
+The above configuration example will ignore all values where the plugin field
+is \*(L"mysql\*(R", the type is \*(L"mysql_command\*(R" and the type instance begins with
+\&\*(L"show_\*(R". All other values will be sent to the \f(CW\*(C`rrdtool\*(C'\fR write plugin via the
+default target of the chain. Since this chain is run after the value has been
+added to the cache, the MySQL \f(CW\*(C`show_*\*(C'\fR command statistics will be available
+via the \f(CW\*(C`unixsock\*(C'\fR plugin.
+.SS "List of configuration options"
+.IX Subsection "List of configuration options"
+.IP "\fBPreCacheChain\fR \fIChainName\fR" 4
+.IX Item "PreCacheChain ChainName"
+.PD 0
+.IP "\fBPostCacheChain\fR \fIChainName\fR" 4
+.IX Item "PostCacheChain ChainName"
+.PD
+Configure the name of the \*(L"pre-cache chain\*(R" and the \*(L"post-cache chain\*(R". The
+argument is the name of a \fIchain\fR that should be executed before and/or after
+the values have been added to the cache.
+.Sp
+To understand the implications, it's important you know what is going on inside
+\&\fIcollectd\fR. The following diagram shows how values are passed from the
+read-plugins to the write-plugins:
+.Sp
+.Vb 10
+\&   +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+\&   !  Read\-Plugin  !
+\&   +\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+
+\&           !
+\& + \- \- \- \- V \- \- \- \- +
+\& : +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ :
+\& : !   Pre\-Cache   ! :
+\& : !     Chain     ! :
+\& : +\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+ :
+\& :         !         :
+\& :         V         :
+\& : +\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+ :  +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+\& : !     Cache     !\-\-\->!  Value Cache  !
+\& : !     insert    ! :  +\-\-\-+\-\-\-+\-\-\-\-\-\-\-+
+\& : +\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+ :      !   !
+\& :         !   ,\-\-\-\-\-\-\-\-\-\-\-\-\*(Aq   !
+\& :         V   V     :          V
+\& : +\-\-\-\-\-\-\-+\-\-\-+\-\-\-+ :  +\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+
+\& : !  Post\-Cache   +\-\-\->! Write\-Plugins !
+\& : !     Chain     ! :  +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+\& : +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ :
+\& :                   :
+\& :  dispatch values  :
+\& + \- \- \- \- \- \- \- \- \- +
+.Ve
+.Sp
+After the values are passed from the \*(L"read\*(R" plugins to the dispatch functions,
+the pre-cache chain is run first. The values are added to the internal cache
+afterwards. The post-cache chain is run after the values have been added to the
+cache. So why is it such a huge deal if chains are run before or after the
+values have been added to this cache?
+.Sp
+Targets that change the identifier of a value list should be executed before
+the values are added to the cache, so that the name in the cache matches the
+name that is used in the \*(L"write\*(R" plugins. The \f(CW\*(C`unixsock\*(C'\fR plugin, too, uses
+this cache to receive a list of all available values. If you change the
+identifier after the value list has been added to the cache, this may easily
+lead to confusion, but it's not forbidden of course.
+.Sp
+The cache is also used to convert counter values to rates. These rates are, for
+example, used by the \f(CW\*(C`value\*(C'\fR match (see below). If you use the rate stored in
+the cache \fBbefore\fR the new value is added, you will use the old, \fBprevious\fR
+rate. Write plugins may use this rate, too, see the \f(CW\*(C`csv\*(C'\fR plugin, for example.
+The \f(CW\*(C`unixsock\*(C'\fR plugin uses these rates too, to implement the \f(CW\*(C`GETVAL\*(C'\fR
+command.
+.Sp
+Last but not last, the \fBstop\fR target makes a difference: If the pre-cache
+chain returns the stop condition, the value will not be added to the cache and
+the post-cache chain will not be run.
+.IP "\fBChain\fR \fIName\fR" 4
+.IX Item "Chain Name"
+Adds a new chain with a certain name. This name can be used to refer to a
+specific chain, for example to jump to it.
+.Sp
+Within the \fBChain\fR block, there can be \fBRule\fR blocks and \fBTarget\fR blocks.
+.IP "\fBRule\fR [\fIName\fR]" 4
+.IX Item "Rule [Name]"
+Adds a new rule to the current chain. The name of the rule is optional and
+currently has no meaning for the daemon.
+.Sp
+Within the \fBRule\fR block, there may be any number of \fBMatch\fR blocks and there
+must be at least one \fBTarget\fR block.
+.IP "\fBMatch\fR \fIName\fR" 4
+.IX Item "Match Name"
+Adds a match to a \fBRule\fR block. The name specifies what kind of match should
+be performed. Available matches depend on the plugins that have been loaded.
+.Sp
+The arguments inside the \fBMatch\fR block are passed to the plugin implementing
+the match, so which arguments are valid here depends on the plugin being used.
+If you do not need any to pass any arguments to a match, you can use the
+shorter syntax:
+.Sp
+.Vb 1
+\& Match "foobar"
+.Ve
+.Sp
+Which is equivalent to:
+.Sp
+.Vb 2
+\& <Match "foobar">
+\& </Match>
+.Ve
+.IP "\fBTarget\fR \fIName\fR" 4
+.IX Item "Target Name"
+Add a target to a rule or a default target to a chain. The name specifies what
+kind of target is to be added. Which targets are available depends on the
+plugins being loaded.
+.Sp
+The arguments inside the \fBTarget\fR block are passed to the plugin implementing
+the target, so which arguments are valid here depends on the plugin being used.
+If you do not need any to pass any arguments to a target, you can use the
+shorter syntax:
+.Sp
+.Vb 1
+\& Target "stop"
+.Ve
+.Sp
+This is the same as writing:
+.Sp
+.Vb 2
+\& <Target "stop">
+\& </Target>
+.Ve
+.SS "Built-in targets"
+.IX Subsection "Built-in targets"
+The following targets are built into the core daemon and therefore need no
+plugins to be loaded:
+.IP "\fBreturn\fR" 4
+.IX Item "return"
+Signals the \*(L"return\*(R" condition, see the \*(L"Flow control\*(R" section above. This
+causes the current chain to stop processing the value and returns control to
+the calling chain. The calling chain will continue processing targets and rules
+just after the \fBjump\fR target (see below). This is very similar to the
+\&\fB\s-1RETURN\s0\fR target of iptables, see \fIiptables\fR\|(8).
+.Sp
+This target does not have any options.
+.Sp
+Example:
+.Sp
+.Vb 1
+\& Target "return"
+.Ve
+.IP "\fBstop\fR" 4
+.IX Item "stop"
+Signals the \*(L"stop\*(R" condition, see the \*(L"Flow control\*(R" section above. This
+causes processing of the value to be aborted immediately. This is similar to
+the \fB\s-1DROP\s0\fR target of iptables, see \fIiptables\fR\|(8).
+.Sp
+This target does not have any options.
+.Sp
+Example:
+.Sp
+.Vb 1
+\& Target "stop"
+.Ve
+.IP "\fBwrite\fR" 4
+.IX Item "write"
+Sends the value to \*(L"write\*(R" plugins.
+.Sp
+Available options:
+.RS 4
+.IP "\fBPlugin\fR \fIName\fR" 4
+.IX Item "Plugin Name"
+Name of the write plugin to which the data should be sent. This option may be
+given multiple times to send the data to more than one write plugin. If the
+plugin supports multiple instances, the plugin's instance(s) must also be
+specified.
+.RE
+.RS 4
+.Sp
+If no plugin is explicitly specified, the values will be sent to all available
+write plugins.
+.Sp
+Single-instance plugin example:
+.Sp
+.Vb 3
+\& <Target "write">
+\&   Plugin "rrdtool"
+\& </Target>
+.Ve
+.Sp
+Multi-instance plugin example:
+.Sp
+.Vb 12
+\& <Plugin "write_graphite">
+\&   <Node "foo">
+\&   ...
+\&   </Node>
+\&   <Node "bar">
+\&   ...
+\&   </Node>
+\& </Plugin>
+\&  ...
+\& <Target "write">
+\&   Plugin "write_graphite/foo"
+\& </Target>
+.Ve
+.RE
+.IP "\fBjump\fR" 4
+.IX Item "jump"
+Starts processing the rules of another chain, see \*(L"Flow control\*(R" above. If
+the end of that chain is reached, or a stop condition is encountered,
+processing will continue right after the \fBjump\fR target, i.\ e. with the
+next target or the next rule. This is similar to the \fB\-j\fR command line option
+of iptables, see \fIiptables\fR\|(8).
+.Sp
+Available options:
+.RS 4
+.IP "\fBChain\fR \fIName\fR" 4
+.IX Item "Chain Name"
+Jumps to the chain \fIName\fR. This argument is required and may appear only once.
+.RE
+.RS 4
+.Sp
+Example:
+.Sp
+.Vb 3
+\& <Target "jump">
+\&   Chain "foobar"
+\& </Target>
+.Ve
+.RE
+.SS "Available matches"
+.IX Subsection "Available matches"
+.IP "\fBregex\fR" 4
+.IX Item "regex"
+Matches a value using regular expressions.
+.Sp
+Available options:
+.RS 4
+.IP "\fBHost\fR \fIRegex\fR" 4
+.IX Item "Host Regex"
+.PD 0
+.IP "\fBPlugin\fR \fIRegex\fR" 4
+.IX Item "Plugin Regex"
+.IP "\fBPluginInstance\fR \fIRegex\fR" 4
+.IX Item "PluginInstance Regex"
+.IP "\fBType\fR \fIRegex\fR" 4
+.IX Item "Type Regex"
+.IP "\fBTypeInstance\fR \fIRegex\fR" 4
+.IX Item "TypeInstance Regex"
+.PD
+Match values where the given regular expressions match the various fields of
+the identifier of a value. If multiple regular expressions are given, \fBall\fR
+regexen must match for a value to match.
+.IP "\fBInvert\fR \fBfalse\fR|\fBtrue\fR" 4
+.IX Item "Invert false|true"
+When set to \fBtrue\fR, the result of the match is inverted, i.e. all value lists
+where all regular expressions apply are not matched, all other value lists are
+matched. Defaults to \fBfalse\fR.
+.RE
+.RS 4
+.Sp
+Example:
+.Sp
+.Vb 4
+\& <Match "regex">
+\&   Host "customer[0\-9]+"
+\&   Plugin "^foobar$"
+\& </Match>
+.Ve
+.RE
+.IP "\fBtimediff\fR" 4
+.IX Item "timediff"
+Matches values that have a time which differs from the time on the server.
+.Sp
+This match is mainly intended for servers that receive values over the
+\&\f(CW\*(C`network\*(C'\fR plugin and write them to disk using the \f(CW\*(C`rrdtool\*(C'\fR plugin. RRDtool
+is very sensitive to the timestamp used when updating the \s-1RRD\s0 files. In
+particular, the time must be ever increasing. If a misbehaving client sends one
+packet with a timestamp far in the future, all further packets with a correct
+time will be ignored because of that one packet. What's worse, such corrupted
+\&\s-1RRD\s0 files are hard to fix.
+.Sp
+This match lets one match all values \fBoutside\fR a specified time range
+(relative to the server's time), so you can use the \fBstop\fR target (see below)
+to ignore the value, for example.
+.Sp
+Available options:
+.RS 4
+.IP "\fBFuture\fR \fISeconds\fR" 4
+.IX Item "Future Seconds"
+Matches all values that are \fIahead\fR of the server's time by \fISeconds\fR or more
+seconds. Set to zero for no limit. Either \fBFuture\fR or \fBPast\fR must be
+non-zero.
+.IP "\fBPast\fR \fISeconds\fR" 4
+.IX Item "Past Seconds"
+Matches all values that are \fIbehind\fR of the server's time by \fISeconds\fR or
+more seconds. Set to zero for no limit. Either \fBFuture\fR or \fBPast\fR must be
+non-zero.
+.RE
+.RS 4
+.Sp
+Example:
+.Sp
+.Vb 4
+\& <Match "timediff">
+\&   Future  300
+\&   Past   3600
+\& </Match>
+.Ve
+.Sp
+This example matches all values that are five minutes or more ahead of the
+server or one hour (or more) lagging behind.
+.RE
+.IP "\fBvalue\fR" 4
+.IX Item "value"
+Matches the actual value of data sources against given minimum\ / maximum
+values. If a data-set consists of more than one data-source, all data-sources
+must match the specified ranges for a positive match.
+.Sp
+Available options:
+.RS 4
+.IP "\fBMin\fR \fIValue\fR" 4
+.IX Item "Min Value"
+Sets the smallest value which still results in a match. If unset, behaves like
+negative infinity.
+.IP "\fBMax\fR \fIValue\fR" 4
+.IX Item "Max Value"
+Sets the largest value which still results in a match. If unset, behaves like
+positive infinity.
+.IP "\fBInvert\fR \fBtrue\fR|\fBfalse\fR" 4
+.IX Item "Invert true|false"
+Inverts the selection. If the \fBMin\fR and \fBMax\fR settings result in a match,
+no-match is returned and vice versa. Please note that the \fBInvert\fR setting
+only effects how \fBMin\fR and \fBMax\fR are applied to a specific value. Especially
+the \fBDataSource\fR and \fBSatisfy\fR settings (see below) are not inverted.
+.IP "\fBDataSource\fR \fIDSName\fR [\fIDSName\fR ...]" 4
+.IX Item "DataSource DSName [DSName ...]"
+Select one or more of the data sources. If no data source is configured, all
+data sources will be checked. If the type handled by the match does not have a
+data source of the specified name(s), this will always result in no match
+(independent of the \fBInvert\fR setting).
+.IP "\fBSatisfy\fR \fBAny\fR|\fBAll\fR" 4
+.IX Item "Satisfy Any|All"
+Specifies how checking with several data sources is performed. If set to
+\&\fBAny\fR, the match succeeds if one of the data sources is in the configured
+range. If set to \fBAll\fR the match only succeeds if all data sources are within
+the configured range. Default is \fBAll\fR.
+.Sp
+Usually \fBAll\fR is used for positive matches, \fBAny\fR is used for negative
+matches. This means that with \fBAll\fR you usually check that all values are in a
+\&\*(L"good\*(R" range, while with \fBAny\fR you check if any value is within a \*(L"bad\*(R" range
+(or outside the \*(L"good\*(R" range).
+.RE
+.RS 4
+.Sp
+Either \fBMin\fR or \fBMax\fR, but not both, may be unset.
+.Sp
+Example:
+.Sp
+.Vb 6
+\& # Match all values smaller than or equal to 100. Matches only if all data
+\& # sources are below 100.
+\& <Match "value">
+\&   Max 100
+\&   Satisfy "All"
+\& </Match>
+\&
+\& # Match if the value of any data source is outside the range of 0 \- 100.
+\& <Match "value">
+\&   Min   0
+\&   Max 100
+\&   Invert true
+\&   Satisfy "Any"
+\& </Match>
+.Ve
+.RE
+.IP "\fBempty_counter\fR" 4
+.IX Item "empty_counter"
+Matches all values with one or more data sources of type \fB\s-1COUNTER\s0\fR and where
+all counter values are zero. These counters usually \fInever\fR increased since
+they started existing (and are therefore uninteresting), or got reset recently
+or overflowed and you had really, \fIreally\fR bad luck.
+.Sp
+Please keep in mind that ignoring such counters can result in confusing
+behavior: Counters which hardly ever increase will be zero for long periods of
+time. If the counter is reset for some reason (machine or service restarted,
+usually), the graph will be empty (\s-1NAN\s0) for a long time. People may not
+understand why.
+.IP "\fBhashed\fR" 4
+.IX Item "hashed"
+Calculates a hash value of the host name and matches values according to that
+hash value. This makes it possible to divide all hosts into groups and match
+only values that are in a specific group. The intended use is in load
+balancing, where you want to handle only part of all data and leave the rest
+for other servers.
+.Sp
+The hashing function used tries to distribute the hosts evenly. First, it
+calculates a 32\ bit hash value using the characters of the hostname:
+.Sp
+.Vb 3
+\&  hash_value = 0;
+\&  for (i = 0; host[i] != 0; i++)
+\&    hash_value = (hash_value * 251) + host[i];
+.Ve
+.Sp
+The constant 251 is a prime number which is supposed to make this hash value
+more random. The code then checks the group for this host according to the
+\&\fITotal\fR and \fIMatch\fR arguments:
+.Sp
+.Vb 4
+\&  if ((hash_value % Total) == Match)
+\&    matches;
+\&  else
+\&    does not match;
+.Ve
+.Sp
+Please note that when you set \fITotal\fR to two (i.\ e. you have only two
+groups), then the least significant bit of the hash value will be the \s-1XOR\s0 of
+all least significant bits in the host name. One consequence is that when you
+have two hosts, \*(L"server0.example.com\*(R" and \*(L"server1.example.com\*(R", where the host
+name differs in one digit only and the digits differ by one, those hosts will
+never end up in the same group.
+.Sp
+Available options:
+.RS 4
+.IP "\fBMatch\fR \fIMatch\fR \fITotal\fR" 4
+.IX Item "Match Match Total"
+Divide the data into \fITotal\fR groups and match all hosts in group \fIMatch\fR as
+described above. The groups are numbered from zero, i.\ e. \fIMatch\fR must
+be smaller than \fITotal\fR. \fITotal\fR must be at least one, although only values
+greater than one really do make any sense.
+.Sp
+You can repeat this option to match multiple groups, for example:
+.Sp
+.Vb 2
+\&  Match 3 7
+\&  Match 5 7
+.Ve
+.Sp
+The above config will divide the data into seven groups and match groups three
+and five. One use would be to keep every value on two hosts so that if one
+fails the missing data can later be reconstructed from the second host.
+.RE
+.RS 4
+.Sp
+Example:
+.Sp
+.Vb 10
+\& # Operate on the pre\-cache chain, so that ignored values are not even in the
+\& # global cache.
+\& <Chain "PreCache">
+\&   <Rule>
+\&     <Match "hashed">
+\&       # Divide all received hosts in seven groups and accept all hosts in
+\&       # group three.
+\&       Match 3 7
+\&     </Match>
+\&     # If matched: Return and continue.
+\&     Target "return"
+\&   </Rule>
+\&   # If not matched: Return and stop.
+\&   Target "stop"
+\& </Chain>
+.Ve
+.RE
+.SS "Available targets"
+.IX Subsection "Available targets"
+.IP "\fBnotification\fR" 4
+.IX Item "notification"
+Creates and dispatches a notification.
+.Sp
+Available options:
+.RS 4
+.IP "\fBMessage\fR \fIString\fR" 4
+.IX Item "Message String"
+This required option sets the message of the notification. The following
+placeholders will be replaced by an appropriate value:
+.RS 4
+.IP "\fB%{host}\fR" 4
+.IX Item "%{host}"
+.PD 0
+.IP "\fB%{plugin}\fR" 4
+.IX Item "%{plugin}"
+.IP "\fB%{plugin_instance}\fR" 4
+.IX Item "%{plugin_instance}"
+.IP "\fB%{type}\fR" 4
+.IX Item "%{type}"
+.IP "\fB%{type_instance}\fR" 4
+.IX Item "%{type_instance}"
+.PD
+These placeholders are replaced by the identifier field of the same name.
+.IP "\fB%{ds:\fR\fIname\fR\fB}\fR" 4
+.IX Item "%{ds:name}"
+These placeholders are replaced by a (hopefully) human readable representation
+of the current rate of this data source. If you changed the instance name
+(using the \fBset\fR or \fBreplace\fR targets, see below), it may not be possible to
+convert counter values to rates.
+.RE
+.RS 4
+.Sp
+Please note that these placeholders are \fBcase sensitive\fR!
+.RE
+.ie n .IP "\fBSeverity\fR \fB""\s-1FAILURE""\s0\fR|\fB""\s-1WARNING""\s0\fR|\fB""\s-1OKAY""\s0\fR" 4
+.el .IP "\fBSeverity\fR \fB``\s-1FAILURE''\s0\fR|\fB``\s-1WARNING''\s0\fR|\fB``\s-1OKAY''\s0\fR" 4
+.IX Item "Severity FAILURE|WARNING|OKAY"
+Sets the severity of the message. If omitted, the severity \fB\*(L"\s-1WARNING\*(R"\s0\fR is
+used.
+.RE
+.RS 4
+.Sp
+Example:
+.Sp
+.Vb 4
+\&  <Target "notification">
+\&    Message "Oops, the %{type_instance} temperature is currently %{ds:value}!"
+\&    Severity "WARNING"
+\&  </Target>
+.Ve
+.RE
+.IP "\fBreplace\fR" 4
+.IX Item "replace"
+Replaces parts of the identifier using regular expressions.
+.Sp
+Available options:
+.RS 4
+.IP "\fBHost\fR \fIRegex\fR \fIReplacement\fR" 4
+.IX Item "Host Regex Replacement"
+.PD 0
+.IP "\fBPlugin\fR \fIRegex\fR \fIReplacement\fR" 4
+.IX Item "Plugin Regex Replacement"
+.IP "\fBPluginInstance\fR \fIRegex\fR \fIReplacement\fR" 4
+.IX Item "PluginInstance Regex Replacement"
+.IP "\fBTypeInstance\fR \fIRegex\fR \fIReplacement\fR" 4
+.IX Item "TypeInstance Regex Replacement"
+.PD
+Match the appropriate field with the given regular expression \fIRegex\fR. If the
+regular expression matches, that part that matches is replaced with
+\&\fIReplacement\fR. If multiple places of the input buffer match a given regular
+expression, only the first occurrence will be replaced.
+.Sp
+You can specify each option multiple times to use multiple regular expressions
+one after another.
+.RE
+.RS 4
+.Sp
+Example:
+.Sp
+.Vb 3
+\& <Target "replace">
+\&   # Replace "example.net" with "example.com"
+\&   Host "\e\e<example.net\e\e>" "example.com"
+\&
+\&   # Strip "www." from hostnames
+\&   Host "\e\e<www\e\e." ""
+\& </Target>
+.Ve
+.RE
+.IP "\fBset\fR" 4
+.IX Item "set"
+Sets part of the identifier of a value to a given string.
+.Sp
+Available options:
+.RS 4
+.IP "\fBHost\fR \fIString\fR" 4
+.IX Item "Host String"
+.PD 0
+.IP "\fBPlugin\fR \fIString\fR" 4
+.IX Item "Plugin String"
+.IP "\fBPluginInstance\fR \fIString\fR" 4
+.IX Item "PluginInstance String"
+.IP "\fBTypeInstance\fR \fIString\fR" 4
+.IX Item "TypeInstance String"
+.PD
+Set the appropriate field to the given string. The strings for plugin instance
+and type instance may be empty, the strings for host and plugin may not be
+empty. It's currently not possible to set the type of a value this way.
+.RE
+.RS 4
+.Sp
+Example:
+.Sp
+.Vb 4
+\& <Target "set">
+\&   PluginInstance "coretemp"
+\&   TypeInstance "core3"
+\& </Target>
+.Ve
+.RE
+.SS "Backwards compatibility"
+.IX Subsection "Backwards compatibility"
+If you use collectd with an old configuration, i.\ e. one without a
+\&\fBChain\fR block, it will behave as it used to. This is equivalent to the
+following configuration:
+.PP
+.Vb 3
+\& <Chain "PostCache">
+\&   Target "write"
+\& </Chain>
+.Ve
+.PP
+If you specify a \fBPostCacheChain\fR, the \fBwrite\fR target will not be added
+anywhere and you will have to make sure that it is called where appropriate. We
+suggest to add the above snippet as default target to your \*(L"PostCache\*(R" chain.
+.SS "Examples"
+.IX Subsection "Examples"
+Ignore all values, where the hostname does not contain a dot, i.\ e. can't
+be an \s-1FQDN.\s0
+.PP
+.Vb 9
+\& <Chain "PreCache">
+\&   <Rule "no_fqdn">
+\&     <Match "regex">
+\&       Host "^[^\e.]*$"
+\&     </Match>
+\&     Target "stop"
+\&   </Rule>
+\&   Target "write"
+\& </Chain>
+.Ve
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd\-exec\fR\|(5),
+\&\fIcollectd\-perl\fR\|(5),
+\&\fIcollectd\-unixsock\fR\|(5),
+\&\fItypes.db\fR\|(5),
+\&\fIhddtemp\fR\|(8),
+\&\fIiptables\fR\|(8),
+kstat(3KSTAT),
+\&\fImbmon\fR\|(1),
+\&\fIpsql\fR\|(1),
+\&\fIregex\fR\|(7),
+\&\fIrrdtool\fR\|(1),
+\&\fIsensors\fR\|(1)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Florian Forster <octo@collectd.org>
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
new file mode 100644 (file)
index 0000000..5132cb4
--- /dev/null
@@ -0,0 +1,1499 @@
+#
+# Config file for collectd(1).
+# Please read collectd.conf(5) for a list of options.
+# http://collectd.org/
+#
+
+##############################################################################
+# Global                                                                     #
+#----------------------------------------------------------------------------#
+# Global settings for the daemon.                                            #
+##############################################################################
+
+#Hostname    "localhost"
+#FQDNLookup   true
+#BaseDir     "@localstatedir@/lib/@PACKAGE_NAME@"
+#PIDFile     "@localstatedir@/run/@PACKAGE_NAME@.pid"
+#PluginDir   "@libdir@/@PACKAGE_NAME@"
+#TypesDB     "@prefix@/share/@PACKAGE_NAME@/types.db"
+
+#----------------------------------------------------------------------------#
+# When enabled, plugins are loaded automatically with the default options    #
+# when an appropriate <Plugin ...> block is encountered.                     #
+# Disabled by default.                                                       #
+#----------------------------------------------------------------------------#
+#AutoLoadPlugin false
+
+#----------------------------------------------------------------------------#
+# When enabled, internal statistics are collected, using "collectd" as the   #
+# plugin name.                                                               #
+# Disabled by default.                                                       #
+#----------------------------------------------------------------------------#
+#CollectInternalStats false
+
+#----------------------------------------------------------------------------#
+# Interval at which to query values. This may be overwritten on a per-plugin #
+# base by using the 'Interval' option of the LoadPlugin block:               #
+#   <LoadPlugin foo>                                                         #
+#       Interval 60                                                          #
+#   </LoadPlugin>                                                            #
+#----------------------------------------------------------------------------#
+#Interval     10
+
+#MaxReadInterval 86400
+#Timeout         2
+#ReadThreads     5
+#WriteThreads    5
+
+# Limit the size of the write queue. Default is no limit. Setting up a limit is
+# recommended for servers handling a high volume of traffic.
+#WriteQueueLimitHigh 1000000
+#WriteQueueLimitLow   800000
+
+##############################################################################
+# Logging                                                                    #
+#----------------------------------------------------------------------------#
+# Plugins which provide logging functions should be loaded first, so log     #
+# messages generated when loading or configuring other plugins can be        #
+# accessed.                                                                  #
+##############################################################################
+
+@LOAD_PLUGIN_SYSLOG@LoadPlugin syslog
+@LOAD_PLUGIN_LOGFILE@LoadPlugin logfile
+@LOAD_PLUGIN_LOG_LOGSTASH@LoadPlugin log_logstash
+
+#<Plugin logfile>
+#      LogLevel @DEFAULT_LOG_LEVEL@
+#      File STDOUT
+#      Timestamp true
+#      PrintSeverity false
+#</Plugin>
+
+#<Plugin log_logstash>
+#      LogLevel @DEFAULT_LOG_LEVEL@
+#      File "@localstatedir@/log/@PACKAGE_NAME@.json.log"
+#</Plugin>
+
+#<Plugin syslog>
+#      LogLevel @DEFAULT_LOG_LEVEL@
+#</Plugin>
+
+##############################################################################
+# LoadPlugin section                                                         #
+#----------------------------------------------------------------------------#
+# Lines beginning with a single `#' belong to plugins which have been built  #
+# but are disabled by default.                                               #
+#                                                                            #
+# Lines begnning with `##' belong to plugins which have not been built due   #
+# to missing dependencies or because they have been deactivated explicitly.  #
+##############################################################################
+
+#@BUILD_PLUGIN_AGGREGATION_TRUE@LoadPlugin aggregation
+#@BUILD_PLUGIN_AMQP_TRUE@LoadPlugin amqp
+#@BUILD_PLUGIN_APACHE_TRUE@LoadPlugin apache
+#@BUILD_PLUGIN_APCUPS_TRUE@LoadPlugin apcups
+#@BUILD_PLUGIN_APPLE_SENSORS_TRUE@LoadPlugin apple_sensors
+#@BUILD_PLUGIN_AQUAERO_TRUE@LoadPlugin aquaero
+#@BUILD_PLUGIN_ASCENT_TRUE@LoadPlugin ascent
+#@BUILD_PLUGIN_BAROMETER_TRUE@LoadPlugin barometer
+#@BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery
+#@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
+#@BUILD_PLUGIN_CEPH_TRUE@LoadPlugin ceph
+#@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
+#@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
+#@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
+@BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
+#@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
+@LOAD_PLUGIN_CSV@LoadPlugin csv
+#@BUILD_PLUGIN_CURL_TRUE@LoadPlugin curl
+#@BUILD_PLUGIN_CURL_JSON_TRUE@LoadPlugin curl_json
+#@BUILD_PLUGIN_CURL_XML_TRUE@LoadPlugin curl_xml
+#@BUILD_PLUGIN_DBI_TRUE@LoadPlugin dbi
+#@BUILD_PLUGIN_DF_TRUE@LoadPlugin df
+#@BUILD_PLUGIN_DISK_TRUE@LoadPlugin disk
+#@BUILD_PLUGIN_DNS_TRUE@LoadPlugin dns
+#@BUILD_PLUGIN_DRBD_TRUE@LoadPlugin drbd
+#@BUILD_PLUGIN_EMAIL_TRUE@LoadPlugin email
+#@BUILD_PLUGIN_ENTROPY_TRUE@LoadPlugin entropy
+#@BUILD_PLUGIN_ETHSTAT_TRUE@LoadPlugin ethstat
+#@BUILD_PLUGIN_EXEC_TRUE@LoadPlugin exec
+#@BUILD_PLUGIN_FHCOUNT_TRUE@LoadPlugin fhcount
+#@BUILD_PLUGIN_FILECOUNT_TRUE@LoadPlugin filecount
+#@BUILD_PLUGIN_FSCACHE_TRUE@LoadPlugin fscache
+#@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
+#@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
+@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
+#@BUILD_PLUGIN_IPC_TRUE@@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
+#@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
+#@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
+#@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs
+#@BUILD_PLUGIN_IRQ_TRUE@LoadPlugin irq
+#@BUILD_PLUGIN_JAVA_TRUE@LoadPlugin java
+@BUILD_PLUGIN_LOAD_TRUE@@BUILD_PLUGIN_LOAD_TRUE@LoadPlugin load
+#@BUILD_PLUGIN_LPAR_TRUE@LoadPlugin lpar
+#@BUILD_PLUGIN_LVM_TRUE@LoadPlugin lvm
+#@BUILD_PLUGIN_MADWIFI_TRUE@LoadPlugin madwifi
+#@BUILD_PLUGIN_MBMON_TRUE@LoadPlugin mbmon
+#@BUILD_PLUGIN_MD_TRUE@LoadPlugin md
+#@BUILD_PLUGIN_MEMCACHEC_TRUE@LoadPlugin memcachec
+#@BUILD_PLUGIN_MEMCACHED_TRUE@LoadPlugin memcached
+@BUILD_PLUGIN_MEMORY_TRUE@@BUILD_PLUGIN_MEMORY_TRUE@LoadPlugin memory
+#@BUILD_PLUGIN_MODBUS_TRUE@LoadPlugin modbus
+#@BUILD_PLUGIN_MULTIMETER_TRUE@LoadPlugin multimeter
+#@BUILD_PLUGIN_MYSQL_TRUE@LoadPlugin mysql
+#@BUILD_PLUGIN_NETAPP_TRUE@LoadPlugin netapp
+#@BUILD_PLUGIN_NETLINK_TRUE@LoadPlugin netlink
+@LOAD_PLUGIN_NETWORK@LoadPlugin network
+#@BUILD_PLUGIN_NFS_TRUE@LoadPlugin nfs
+#@BUILD_PLUGIN_NGINX_TRUE@LoadPlugin nginx
+#@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@LoadPlugin notify_desktop
+#@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
+#@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
+#@BUILD_PLUGIN_NUMA_TRUE@LoadPlugin numa
+#@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
+#@BUILD_PLUGIN_OLSRD_TRUE@LoadPlugin olsrd
+#@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
+#@BUILD_PLUGIN_OPENLDAP_TRUE@LoadPlugin openldap
+#@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
+#@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
+#@BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl
+#@BUILD_PLUGIN_PINBA_TRUE@LoadPlugin pinba
+#@BUILD_PLUGIN_PING_TRUE@LoadPlugin ping
+#@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
+#@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
+#@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
+#@BUILD_PLUGIN_PROTOCOLS_TRUE@LoadPlugin protocols
+#@BUILD_PLUGIN_PYTHON_TRUE@LoadPlugin python
+#@BUILD_PLUGIN_REDIS_TRUE@LoadPlugin redis
+#@BUILD_PLUGIN_ROUTEROS_TRUE@LoadPlugin routeros
+#@BUILD_PLUGIN_RRDCACHED_TRUE@LoadPlugin rrdcached
+@LOAD_PLUGIN_RRDTOOL@LoadPlugin rrdtool
+#@BUILD_PLUGIN_SENSORS_TRUE@LoadPlugin sensors
+#@BUILD_PLUGIN_SERIAL_TRUE@LoadPlugin serial
+#@BUILD_PLUGIN_SIGROK_TRUE@LoadPlugin sigrok
+#@BUILD_PLUGIN_SMART_TRUE@LoadPlugin smart
+#@BUILD_PLUGIN_SNMP_TRUE@LoadPlugin snmp
+#@BUILD_PLUGIN_STATSD_TRUE@LoadPlugin statsd
+#@BUILD_PLUGIN_SWAP_TRUE@LoadPlugin swap
+#@BUILD_PLUGIN_TABLE_TRUE@LoadPlugin table
+#@BUILD_PLUGIN_TAIL_TRUE@LoadPlugin tail
+#@BUILD_PLUGIN_TAIL_CSV_TRUE@LoadPlugin tail_csv
+#@BUILD_PLUGIN_TAPE_TRUE@LoadPlugin tape
+#@BUILD_PLUGIN_TCPCONNS_TRUE@LoadPlugin tcpconns
+#@BUILD_PLUGIN_TEAMSPEAK2_TRUE@LoadPlugin teamspeak2
+#@BUILD_PLUGIN_TED_TRUE@LoadPlugin ted
+#@BUILD_PLUGIN_THERMAL_TRUE@LoadPlugin thermal
+#@BUILD_PLUGIN_TOKYOTYRANT_TRUE@LoadPlugin tokyotyrant
+#@BUILD_PLUGIN_TURBOSTAT_TRUE@LoadPlugin turbostat
+#@BUILD_PLUGIN_UNIXSOCK_TRUE@LoadPlugin unixsock
+#@BUILD_PLUGIN_UPTIME_TRUE@LoadPlugin uptime
+#@BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
+#@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
+#@BUILD_PLUGIN_VARNISH_TRUE@LoadPlugin varnish
+#@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
+#@BUILD_PLUGIN_VIRT_TRUE@LoadPlugin virt
+#@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
+#@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
+#@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
+#@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@LoadPlugin write_graphite
+#@BUILD_PLUGIN_WRITE_HTTP_TRUE@LoadPlugin write_http
+#@BUILD_PLUGIN_WRITE_KAFKA_TRUE@LoadPlugin write_kafka
+#@BUILD_PLUGIN_WRITE_LOG_TRUE@LoadPlugin write_log
+#@BUILD_PLUGIN_WRITE_MONGODB_TRUE@LoadPlugin write_mongodb
+#@BUILD_PLUGIN_WRITE_REDIS_TRUE@LoadPlugin write_redis
+#@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@LoadPlugin write_riemann
+#@BUILD_PLUGIN_WRITE_SENSU_TRUE@LoadPlugin write_sensu
+#@BUILD_PLUGIN_WRITE_TSDB_TRUE@LoadPlugin write_tsdb
+#@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
+#@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
+#@BUILD_PLUGIN_ZOOKEEPER_TRUE@LoadPlugin zookeeper
+
+##############################################################################
+# Plugin configuration                                                       #
+#----------------------------------------------------------------------------#
+# In this section configuration stubs for each plugin are provided. A desc-  #
+# ription of those options is available in the collectd.conf(5) manual page. #
+##############################################################################
+
+#<Plugin aggregation>
+#  <Aggregation>
+#    #Host "unspecified"
+#    Plugin "cpu"
+#    #PluginInstance "unspecified"
+#    Type "cpu"
+#    #TypeInstance "unspecified"
+#
+#    GroupBy "Host"
+#    GroupBy "TypeInstance"
+#
+#    CalculateNum false
+#    CalculateSum false
+#    CalculateAverage true
+#    CalculateMinimum false
+#    CalculateMaximum false
+#    CalculateStddev false
+#  </Aggregation>
+#</Plugin>
+
+#<Plugin amqp>
+#  <Publish "name">
+#    Host "localhost"
+#    Port "5672"
+#    VHost "/"
+#    User "guest"
+#    Password "guest"
+#    Exchange "amq.fanout"
+#    RoutingKey "collectd"
+#    Persistent false
+#    StoreRates false
+#    ConnectionRetryDelay 0
+#  </Publish>
+#</Plugin>
+
+#<Plugin apache>
+#  <Instance "local">
+#    URL "http://localhost/status?auto"
+#    User "www-user"
+#    Password "secret"
+#    CACert "/etc/ssl/ca.crt"
+#  </Instance>
+#</Plugin>
+
+#<Plugin apcups>
+#      Host "localhost"
+#      Port "3551"
+#      ReportSeconds true
+#</Plugin>
+
+#<Plugin aquaero>
+#      Device ""
+#</Plugin>
+
+#<Plugin ascent>
+#      URL "http://localhost/ascent/status/"
+#      User "www-user"
+#      Password "secret"
+#      CACert "/etc/ssl/ca.crt"
+#</Plugin>
+
+#<Plugin "barometer">
+#   Device            "/dev/i2c-0";
+#   Oversampling      512
+#   PressureOffset    0.0
+#   TemperatureOffset 0.0
+#   Normalization     2
+#   Altitude          238.0
+#   TemperatureSensor "myserver/onewire-F10FCA000800/temperature"
+#</Plugin>
+
+#<Plugin "battery">
+#  ValuesPercentage false
+#  ReportDegraded
+#</Plugin>
+
+#<Plugin "bind">
+#  URL "http://localhost:8053/"
+#  ParseTime       false
+#  OpCodes         true
+#  QTypes          true
+#
+#  ServerStats     true
+#  ZoneMaintStats  true
+#  ResolverStats   false
+#  MemoryStats     true
+#
+#  <View "_default">
+#    QTypes        true
+#    ResolverStats true
+#    CacheRRSets   true
+#
+#    Zone "127.in-addr.arpa/IN"
+#  </View>
+#</Plugin>
+
+#<Plugin ceph>
+#  LongRunAvgLatency false
+#  ConvertSpecialMetricTypes true
+#  <Daemon "osd.0">
+#    SocketPath "/var/run/ceph/ceph-osd.0.asok"
+#  </Daemon>
+#  <Daemon "osd.1">
+#    SocketPath "/var/run/ceph/ceph-osd.1.asok"
+#  </Daemon>
+#  <Daemon "mon.a">
+#    SocketPath "/var/run/ceph/ceph-mon.ceph1.asok"
+#  </Daemon>
+#  <Daemon "mds.a">
+#    SocketPath "/var/run/ceph/ceph-mds.ceph1.asok"
+#  </Daemon>
+#</Plugin>
+
+#<Plugin cgroups>
+#  CGroup "libvirt"
+#  IgnoreSelected false
+#</Plugin>
+
+#<Plugin cpu>
+#  ReportByCpu true
+#  ReportByState true
+#  ValuesPercentage false
+#</Plugin>
+#
+#<Plugin csv>
+#      DataDir "@localstatedir@/lib/@PACKAGE_NAME@/csv"
+#      StoreRates false
+#</Plugin>
+
+#<Plugin curl>
+#  <Page "stock_quotes">
+#    URL "http://finance.google.com/finance?q=NYSE%3AAMD"
+#    User "foo"
+#    Password "bar"
+#    Digest false
+#    VerifyPeer true
+#    VerifyHost true
+#    CACert "/path/to/ca.crt"
+#    Header "X-Custom-Header: foobar"
+#    Post "foo=bar"
+#
+#    MeasureResponseTime false
+#    MeasureResponseCode false
+#    <Match>
+#      Regex "<span +class=\"pr\"[^>]*> *([0-9]*\\.[0-9]+) *</span>"
+#      DSType "GaugeAverage"
+#      Type "stock_value"
+#      Instance "AMD"
+#    </Match>
+#  </Page>
+#</Plugin>
+
+#<Plugin curl_json>
+#  <URL "http://localhost:80/test.json">
+#    Instance "test_http_json"
+#    <Key "testArray/0">
+#      Type "gauge"
+#      # Expect: 1
+#    </Key>
+#    <Key "testArray/1">
+#      Type "gauge"
+#      # Expect: 2
+#    </Key>
+#    <Key "testArrayInbetween/0/blarg">
+#      Type "gauge"
+#      # Expect: 3
+#    </Key>
+#    <Key "testArrayInbetween/1/blub">
+#      Type "gauge"
+#      # Expect: 4
+#    </Key>
+#    <Key "testDirectHit">
+#      Type "gauge"
+#      # Expect: 5
+#    </Key>
+#    <Key "testSubLevelHit/oneMoreLevel">
+#      Type "gauge"
+#      # Expect: 6
+#    </Key>
+#  </URL>
+# put this as test.json on your webserver, the above config demonstraces
+# how to match them.
+# {
+#  "testArray":[1,2],
+#  "testArrayInbetween":[{"blarg":3},{"blub":4}],
+#  "testDirectHit":5,
+#  "testSubLevelHit":{"oneMoreLevel":6}
+# }
+## See: http://wiki.apache.org/couchdb/Runtime_Statistics
+#  <URL "http://localhost:5984/_stats">
+#    Instance "httpd"
+#    <Key "httpd/requests/count">
+#      Type "http_requests"
+#    </Key>
+#
+#    <Key "httpd_request_methods/*/count">
+#      Type "http_request_methods"
+#    </Key>
+#
+#    <Key "httpd_status_codes/*/count">
+#      Type "http_response_codes"
+#    </Key>
+#  </URL>
+## Database status metrics:
+#  <URL "http://localhost:5984/_all_dbs">
+#    Instance "dbs"
+#    <Key "*/doc_count">
+#      Type "gauge"
+#    </Key>
+#    <Key "*/doc_del_count">
+#      Type "counter"
+#    </Key>
+#    <Key "*/disk_size">
+#      Type "bytes"
+#    </Key>
+#  </URL>
+#</Plugin>
+
+#<Plugin curl_xml>
+#  <URL "http://localhost/stats.xml">
+#    Host "my_host"
+#    Instance "some_instance"
+#    User "collectd"
+#    Password "thaiNg0I"
+#    Digest false
+#    VerifyPeer true
+#    VerifyHost true
+#    CACert "/path/to/ca.crt"
+#    Header "X-Custom-Header: foobar"
+#    Post "foo=bar"
+#
+#    <XPath "table[@id=\"magic_level\"]/tr">
+#      Type "magic_level"
+#      #InstancePrefix "prefix-"
+#      InstanceFrom "td[1]"
+#      ValuesFrom "td[2]/span[@class=\"level\"]"
+#    </XPath>
+#  </URL>
+#</Plugin>
+
+#<Plugin dbi>
+#      <Query "num_of_customers">
+#              Statement "SELECT 'customers' AS c_key, COUNT(*) AS c_value FROM customers_tbl"
+#              <Result>
+#                      Type "gauge"
+#                      InstancesFrom "c_key"
+#                      ValuesFrom "c_value"
+#              </Result>
+#      </Query>
+#      <Database "customers_db">
+#              Driver "mysql"
+#              DriverOption "host" "localhost"
+#              DriverOption "username" "collectd"
+#              DriverOption "password" "AeXohy0O"
+#              DriverOption "dbname" "custdb0"
+#              #SelectDB "custdb0"
+#              Query "num_of_customers"
+#              #Query "..."
+#              #Host "..."
+#      </Database>
+#</Plugin>
+
+#<Plugin df>
+#      Device "/dev/hda1"
+#      Device "192.168.0.2:/mnt/nfs"
+#      MountPoint "/home"
+#      FSType "ext3"
+#      IgnoreSelected false
+#      ReportByDevice false
+#      ReportReserved false
+#      ReportInodes false
+#      ValuesAbsolute true
+#      ValuesPercentage false
+#</Plugin>
+
+#<Plugin disk>
+#      Disk "/^[hs]d[a-f][0-9]?$/"
+#      IgnoreSelected false
+#      UseBSDName false
+#      UdevNameAttr "DEVNAME"
+#</Plugin>
+
+#<Plugin dns>
+#      Interface "eth0"
+#      IgnoreSource "192.168.0.1"
+#      SelectNumericQueryTypes true
+#</Plugin>
+
+#<Plugin email>
+#      SocketFile "@localstatedir@/run/@PACKAGE_NAME@-email"
+#      SocketGroup "collectd"
+#      SocketPerms "0770"
+#      MaxConns 5
+#</Plugin>
+
+#<Plugin ethstat>
+#      Interface "eth0"
+#      Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
+#      Map "multicast" "if_multicast"
+#      MappedOnly false
+#</Plugin>
+
+#<Plugin exec>
+#      Exec "user:group" "/path/to/exec"
+#      NotificationExec "user:group" "/path/to/exec"
+#</Plugin>
+
+#<Plugin fhcount>
+#      ValuesAbsolute true
+#      ValuesPercentage false
+#</Plugin>
+
+#<Plugin filecount>
+#      <Directory "/path/to/dir">
+#              Instance "foodir"
+#              Name "*.conf"
+#              MTime "-5m"
+#              Size "+10k"
+#              Recursive true
+#              IncludeHidden false
+#      </Directory>
+#</Plugin>
+
+#<Plugin gmond>
+#  MCReceiveFrom "239.2.11.71" "8649"
+#  <Metric "swap_total">
+#    Type "swap"
+#    TypeInstance "total"
+#    DataSource "value"
+#  </Metric>
+#  <Metric "swap_free">
+#    Type "swap"
+#    TypeInstance "free"
+#    DataSource "value"
+#  </Metric>
+#</Plugin>
+
+#<Plugin hddtemp>
+#  Host "127.0.0.1"
+#  Port "7634"
+#</Plugin>
+
+#<Plugin interface>
+#      Interface "eth0"
+#      IgnoreSelected false
+#</Plugin>
+
+#<Plugin ipmi>
+#      Sensor "some_sensor"
+#      Sensor "another_one"
+#      IgnoreSelected false
+#      NotifySensorAdd false
+#      NotifySensorRemove true
+#      NotifySensorNotPresent false
+#</Plugin>
+
+#<Plugin iptables>
+#      Chain table chain
+#</Plugin>
+
+#<Plugin irq>
+#      Irq 7
+#      Irq 8
+#      Irq 9
+#      IgnoreSelected true
+#</Plugin>
+
+#<Plugin java>
+#      JVMArg "-verbose:jni"
+#      JVMArg "-Djava.class.path=@prefix@/share/collectd/java/collectd-api.jar"
+#
+#      LoadPlugin "org.collectd.java.Foobar"
+#      <Plugin "org.collectd.java.Foobar">
+#        # To be parsed by the plugin
+#      </Plugin>
+#</Plugin>
+
+#<Plugin load>
+#        ReportRelative true
+#</Plugin>
+
+#<Plugin lpar>
+#      CpuPoolStats   false
+#      ReportBySerial false
+#</Plugin>
+
+#<Plugin madwifi>
+#      Interface "wlan0"
+#      IgnoreSelected false
+#      Source "SysFS"
+#      WatchSet "None"
+#      WatchAdd "node_octets"
+#      WatchAdd "node_rssi"
+#      WatchAdd "is_rx_acl"
+#      WatchAdd "is_scan_active"
+#</Plugin>
+
+#<Plugin mbmon>
+#      Host "127.0.0.1"
+#      Port "411"
+#</Plugin>
+
+#<Plugin md>
+#      Device "/dev/md0"
+#      IgnoreSelected false
+#</Plugin>
+
+#<Plugin memcachec>
+#      <Page "plugin_instance">
+#              Server "localhost"
+#              Key "page_key"
+#              <Match>
+#                      Regex "(\\d+) bytes sent"
+#                      ExcludeRegex "<lines to be excluded>"
+#                      DSType CounterAdd
+#                      Type "ipt_octets"
+#                      Instance "type_instance"
+#              </Match>
+#      </Page>
+#</Plugin>
+
+#<Plugin memcached>
+#      <Instance "local">
+#              Host "127.0.0.1"
+#              Port "11211"
+#      </Instance>
+#</Plugin>
+
+#<Plugin memory>
+#      ValuesAbsolute true
+#      ValuesPercentage false
+#</Plugin>
+
+#<Plugin modbus>
+#      <Data "data_name">
+#              RegisterBase 1234
+#              RegisterCmd ReadHolding
+#              RegisterType float
+#              Type gauge
+#              Instance "..."
+#      </Data>
+#
+#      <Host "name">
+#              Address "addr"
+#              Port "1234"
+#              Interval 60
+#
+#              <Slave 1>
+#                      Instance "foobar" # optional
+#                      Collect "data_name"
+#              </Slave>
+#      </Host>
+#</Plugin>
+
+#<Plugin mysql>
+#      <Database db_name>
+#              Host "database.serv.er"
+#              User "db_user"
+#              Password "secret"
+#              Database "db_name"
+#              MasterStats true
+#              ConnectTimeout 10
+#              InnodbStats true
+#      </Database>
+#
+#      <Database db_name2>
+#              Alias "squeeze"
+#              Host "localhost"
+#              Socket "/var/run/mysql/mysqld.sock"
+#              SlaveStats true
+#              SlaveNotifications true
+#      </Database>
+#</Plugin>
+
+#<Plugin netapp>
+#      <Host "netapp1.example.com">
+#              Protocol      "https"
+#              Address       "10.0.0.1"
+#              Port          443
+#              User          "username"
+#              Password      "aef4Aebe"
+#              Interval      30
+#
+#              <WAFL>
+#                      Interval 30
+#                      GetNameCache   true
+#                      GetDirCache    true
+#                      GetBufferCache true
+#                      GetInodeCache  true
+#              </WAFL>
+#
+#              <Disks>
+#                      Interval 30
+#                      GetBusy true
+#              </Disks>
+#
+#              <VolumePerf>
+#                      Interval 30
+#                      GetIO      "volume0"
+#                      IgnoreSelectedIO      false
+#                      GetOps     "volume0"
+#                      IgnoreSelectedOps     false
+#                      GetLatency "volume0"
+#                      IgnoreSelectedLatency false
+#              </VolumePerf>
+#
+#              <VolumeUsage>
+#                      Interval 30
+#                      GetCapacity "vol0"
+#                      GetCapacity "vol1"
+#                      IgnoreSelectedCapacity false
+#                      GetSnapshot "vol1"
+#                      GetSnapshot "vol3"
+#                      IgnoreSelectedSnapshot false
+#              </VolumeUsage>
+#
+#              <System>
+#                      Interval 30
+#                      GetCPULoad     true
+#                      GetInterfaces  true
+#                      GetDiskOps     true
+#                      GetDiskIO      true
+#              </System>
+#      </Host>
+#</Plugin>
+
+#<Plugin netlink>
+#      Interface "All"
+#      VerboseInterface "All"
+#      QDisc "eth0" "pfifo_fast-1:0"
+#      Class "ppp0" "htb-1:10"
+#      Filter "ppp0" "u32-1:0"
+#      IgnoreSelected false
+#</Plugin>
+
+@LOAD_PLUGIN_NETWORK@<Plugin network>
+#      # client setup:
+@LOAD_PLUGIN_NETWORK@  Server "ff18::efc0:4a42" "25826"
+@LOAD_PLUGIN_NETWORK@  <Server "239.192.74.66" "25826">
+#              SecurityLevel Encrypt
+#              Username "user"
+#              Password "secret"
+#              Interface "eth0"
+#              ResolveInterval 14400
+@LOAD_PLUGIN_NETWORK@  </Server>
+#      TimeToLive 128
+#
+#      # server setup:
+#      Listen "ff18::efc0:4a42" "25826"
+#      <Listen "239.192.74.66" "25826">
+#              SecurityLevel Sign
+#              AuthFile "/etc/collectd/passwd"
+#              Interface "eth0"
+#      </Listen>
+#      MaxPacketSize 1452
+#
+#      # proxy setup (client and server as above):
+#      Forward true
+#
+#      # statistics about the network plugin itself
+#      ReportStats false
+#
+#      # "garbage collection"
+#      CacheFlush 1800
+@LOAD_PLUGIN_NETWORK@</Plugin>
+
+#<Plugin nginx>
+#      URL "http://localhost/status?auto"
+#      User "www-user"
+#      Password "secret"
+#      CACert "/etc/ssl/ca.crt"
+#</Plugin>
+
+#<Plugin notify_desktop>
+#      OkayTimeout 1000
+#      WarningTimeout 5000
+#      FailureTimeout 0
+#</Plugin>
+
+#<Plugin notify_email>
+#       SMTPServer "localhost"
+#      SMTPPort 25
+#      SMTPUser "my-username"
+#      SMTPPassword "my-password"
+#      From "collectd@main0server.com"
+#      # <WARNING/FAILURE/OK> on <hostname>. beware! do not use not more than two %s in this string!!!
+#      Subject "Aaaaaa!! %s on %s!!!!!"
+#      Recipient "email1@domain1.net"
+#      Recipient "email2@domain2.com"
+#</Plugin>
+
+#<Plugin ntpd>
+#      Host "localhost"
+#      Port 123
+#      ReverseLookups false
+#      IncludeUnitID true
+#</Plugin>
+
+#<Plugin nut>
+#      UPS "upsname@hostname:port"
+#</Plugin>
+
+#<Plugin olsrd>
+#      Host "127.0.0.1"
+#      Port "2006"
+#      CollectLinks "Summary"
+#      CollectRoutes "Summary"
+#      CollectTopology "Summary"
+#</Plugin>
+
+#<Plugin onewire>
+#      Device "-s localhost:4304"
+#      Sensor "F10FCA000800"
+#      IgnoreSelected false
+#</Plugin>
+
+#<Plugin openldap>
+#  <Instance "localhost">
+#    URL "ldap://localhost:389"
+#    StartTLS false
+#    VerifyHost true
+#    CACert "/path/to/ca.crt"
+#    Timeout -1
+#    Version 3
+#  </Instance>
+#</Plugin>
+
+#<Plugin openvpn>
+#      StatusFile "/etc/openvpn/openvpn-status.log"
+#      ImprovedNamingSchema false
+#      CollectCompression true
+#      CollectIndividualUsers true
+#      CollectUserCount false
+#</Plugin>
+
+#<Plugin oracle>
+#  <Query "out_of_stock">
+#    Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category"
+#    <Result>
+#      Type "gauge"
+#      InstancesFrom "category"
+#      ValuesFrom "value"
+#    </Result>
+#  </Query>
+#  <Database "product_information">
+#    ConnectID "db01"
+#    Username "oracle"
+#    Password "secret"
+#    Query "out_of_stock"
+#  </Database>
+#</Plugin>
+
+#<Plugin perl>
+#      IncludeDir "/my/include/path"
+#      BaseName "Collectd::Plugins"
+#      EnableDebugger ""
+#      LoadPlugin Monitorus
+#      LoadPlugin OpenVZ
+#
+#      <Plugin foo>
+#              Foo "Bar"
+#              Qux "Baz"
+#      </Plugin>
+#</Plugin>
+
+#<Plugin pinba>
+#      Address "::0"
+#      Port "30002"
+#      <View "name">
+#              Host "host name"
+#              Server "server name"
+#              Script "script name"
+#      </View>
+#</Plugin>
+
+#<Plugin ping>
+#      Host "host.foo.bar"
+#      Interval 1.0
+#      Timeout 0.9
+#      TTL 255
+#      SourceAddress "1.2.3.4"
+#      Device "eth0"
+#      MaxMissed -1
+#</Plugin>
+
+#<Plugin postgresql>
+#      <Query magic>
+#              Statement "SELECT magic FROM wizard WHERE host = $1;"
+#              Param hostname
+#              <Result>
+#                      Type gauge
+#                      InstancePrefix "magic"
+#                      ValuesFrom magic
+#              </Result>
+#      </Query>
+#      <Query rt36_tickets>
+#              Statement "SELECT COUNT(type) AS count, type \
+#                                FROM (SELECT CASE \
+#                                             WHEN resolved = 'epoch' THEN 'open' \
+#                                             ELSE 'resolved' END AS type \
+#                                             FROM tickets) type \
+#                                GROUP BY type;"
+#              <Result>
+#                      Type counter
+#                      InstancePrefix "rt36_tickets"
+#                      InstancesFrom "type"
+#                      ValuesFrom "count"
+#              </Result>
+#      </Query>
+#      <Writer sqlstore>
+#              # See contrib/postgresql/collectd_insert.sql for details
+#              Statement "SELECT collectd_insert($1, $2, $3, $4, $5, $6, $7, $8, $9);"
+#              StoreRates true
+#      </Writer>
+#      <Database foo>
+#              Host "hostname"
+#              Port "5432"
+#              User "username"
+#              Password "secret"
+#              SSLMode "prefer"
+#              KRBSrvName "kerberos_service_name"
+#              Query magic
+#      </Database>
+#      <Database bar>
+#              Interval 60
+#              Service "service_name"
+#              Query backend # predefined
+#              Query rt36_tickets
+#      </Database>
+#      <Database qux>
+#              Service "collectd_store"
+#              Writer sqlstore
+#              # see collectd.conf(5) for details
+#              CommitInterval 30
+#      </Database>
+#</Plugin>
+
+#<Plugin powerdns>
+#  <Server "server_name">
+#    Collect "latency"
+#    Collect "udp-answers" "udp-queries"
+#    Socket "/var/run/pdns.controlsocket"
+#  </Server>
+#  <Recursor "recursor_name">
+#    Collect "questions"
+#    Collect "cache-hits" "cache-misses"
+#    Socket "/var/run/pdns_recursor.controlsocket"
+#  </Recursor>
+#  LocalSocket "/opt/collectd/var/run/collectd-powerdns"
+#</Plugin>
+
+#<Plugin processes>
+#      Process "name"
+#</Plugin>
+
+#<Plugin protocols>
+#      Value "/^Tcp:/"
+#      IgnoreSelected false
+#</Plugin>
+
+#<Plugin python>
+#      ModulePath "/path/to/your/python/modules"
+#      LogTraces true
+#      Interactive true
+#      Import "spam"
+#
+#      <Module spam>
+#              spam "wonderful" "lovely"
+#      </Module>
+#</Plugin>
+
+#<Plugin redis>
+#   <Node example>
+#      Host "redis.example.com"
+#      Port "6379"
+#      Timeout 2000
+#   </Node>
+#</Plugin>
+
+#<Plugin routeros>
+#      <Router>
+#              Host "router.example.com"
+#              Port "8728"
+#              User "admin"
+#              Password "dozaiTh4"
+#              CollectInterface true
+#              CollectRegistrationTable true
+#              CollectCPULoad true
+#              CollectMemory true
+#              CollectDF true
+#              CollectDisk true
+#      </Router>
+#</Plugin>
+
+#<Plugin rrdcached>
+#      DaemonAddress "unix:/tmp/rrdcached.sock"
+#      DataDir "@localstatedir@/lib/@PACKAGE_NAME@/rrd"
+#      CreateFiles true
+#      CreateFilesAsync false
+#      CollectStatistics true
+#</Plugin>
+
+#<Plugin rrdtool>
+#      DataDir "@localstatedir@/lib/@PACKAGE_NAME@/rrd"
+#      CreateFilesAsync false
+#      CacheTimeout 120
+#      CacheFlush   900
+#      WritesPerSecond 50
+#</Plugin>
+
+#<Plugin sensors>
+#      SensorConfigFile "/etc/sensors.conf"
+#      Sensor "it8712-isa-0290/temperature-temp1"
+#      Sensor "it8712-isa-0290/fanspeed-fan3"
+#      Sensor "it8712-isa-0290/voltage-in8"
+#      IgnoreSelected false
+#</Plugin>
+
+#<Plugin sigrok>
+#  LogLevel 3
+#  <Device "AC Voltage">
+#    Driver "fluke-dmm"
+#    MinimumInterval 10
+#    Conn "/dev/ttyUSB2"
+#  </Device>
+#  <Device "Sound Level">
+#    Driver "cem-dt-885x"
+#    Conn "/dev/ttyUSB1"
+#  </Device>
+#</Plugin>
+
+#<Plugin smart>
+#  Disk "/^[hs]d[a-f][0-9]?$/"
+#  IgnoreSelected false
+#</Plugin>
+
+#<Plugin snmp>
+#   <Data "powerplus_voltge_input">
+#       Type "voltage"
+#       Table false
+#       Instance "input_line1"
+#       Values "SNMPv2-SMI::enterprises.6050.5.4.1.1.2.1"
+#   </Data>
+#   <Data "hr_users">
+#       Type "users"
+#       Table false
+#       Instance ""
+#       Values "HOST-RESOURCES-MIB::hrSystemNumUsers.0"
+#   </Data>
+#   <Data "std_traffic">
+#       Type "if_octets"
+#       Table true
+#       Instance "IF-MIB::ifDescr"
+#       Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets"
+#   </Data>
+#
+#   <Host "some.switch.mydomain.org">
+#       Address "192.168.0.2"
+#       Version 1
+#       Community "community_string"
+#       Collect "std_traffic"
+#       Interval 120
+#   </Host>
+#   <Host "some.server.mydomain.org">
+#       Address "192.168.0.42"
+#       Version 2
+#       Community "another_string"
+#       Collect "std_traffic" "hr_users"
+#   </Host>
+#   <Host "some.ups.mydomain.org">
+#       Address "192.168.0.3"
+#       Version 1
+#       Community "more_communities"
+#       Collect "powerplus_voltge_input"
+#       Interval 300
+#   </Host>
+#</Plugin>
+
+#<Plugin statsd>
+#  Host "::"
+#  Port "8125"
+#  DeleteCounters false
+#  DeleteTimers   false
+#  DeleteGauges   false
+#  DeleteSets     false
+#  TimerPercentile 90.0
+#  TimerPercentile 95.0
+#  TimerPercentile 99.0
+#  TimerLower     false
+#  TimerUpper     false
+#  TimerSum       false
+#  TimerCount     false
+#</Plugin>
+
+#<Plugin swap>
+#      ReportByDevice false
+#      ReportBytes true
+#      ValuesAbsolute true
+#      ValuesPercentage false
+#</Plugin>
+
+#<Plugin table>
+#      <Table "/proc/slabinfo">
+#              Instance "slabinfo"
+#              Separator " "
+#              <Result>
+#                      Type gauge
+#                      InstancePrefix "active_objs"
+#                      InstancesFrom 0
+#                      ValuesFrom 1
+#              </Result>
+#              <Result>
+#                      Type gauge
+#                      InstancePrefix "objperslab"
+#                      InstancesFrom 0
+#                      ValuesFrom 4
+#              </Result>
+#      </Table>
+#</Plugin>
+
+#<Plugin tail>
+#  <File "/var/log/exim4/mainlog">
+#    Instance "exim"
+#    Interval 60
+#    <Match>
+#      Regex "S=([1-9][0-9]*)"
+#      DSType "CounterAdd"
+#      Type "ipt_bytes"
+#      Instance "total"
+#    </Match>
+#    <Match>
+#      Regex "\\<R=local_user\\>"
+#      ExcludeRegex "\\<R=local_user\\>.*mail_spool defer"
+#      DSType "CounterInc"
+#      Type "counter"
+#      Instance "local_user"
+#    </Match>
+#  </File>
+#</Plugin>
+
+#<Plugin tail_csv>
+#   <Metric "dropped">
+#       Type "percent"
+#       Instance "dropped"
+#       ValueFrom 1
+#   </Metric>
+#   <Metric "mbps">
+#       Type "bytes"
+#       Instance "wire-realtime"
+#       ValueFrom 2
+#   </Metric>
+#   <Metric "alerts">
+#       Type "alerts_per_second"
+#       ValueFrom 3
+#   </Metric>
+#   <Metric "kpps">
+#       Type "kpackets_wire_per_sec.realtime"
+#       ValueFrom 4
+#   </Metric>
+#   <File "/var/log/snort/snort.stats">
+#       Instance "snort-eth0"
+#       Interval 600
+#       Collect "dropped" "mbps" "alerts" "kpps"
+#       TimeFrom 0
+#   </File>
+#</Plugin>
+
+#<Plugin tcpconns>
+#      ListeningPorts false
+#      AllPortsSummary false
+#      LocalPort "25"
+#      RemotePort "25"
+#</Plugin>
+
+#<Plugin teamspeak2>
+#      Host "127.0.0.1"
+#      Port "51234"
+#      Server "8767"
+#</Plugin>
+
+#<Plugin ted>
+#      Device "/dev/ttyUSB0"
+#      Retries 0
+#</Plugin>
+
+#<Plugin thermal>
+#      ForceUseProcfs false
+#      Device "THRM"
+#      IgnoreSelected false
+#</Plugin>
+
+#<Plugin tokyotyrant>
+#      Host "localhost"
+#      Port "1978"
+#</Plugin>
+
+#<Plugin turbostat>
+##     None of the following option should be set manually
+##     This plugin automatically detect most optimal options
+##     Only set values here if:
+##     - The module ask you to
+##     - You want to disable the collection of some data
+##     - Your (intel) CPU is not supported (yet) by the module
+##     - The module generate a lot of errors 'MSR offset 0x... read failed'
+##     In the last two cases, please open a bug request
+#
+#      TCCActivationTemp "100"
+#      CoreCstates "392"
+#      PackageCstates "396"
+#      SystemManagementInterrupt true
+#      DigitalTemperatureSensor true
+#      PackageThermalManagement true
+#      RunningAveragePowerLimit "7"    
+#</Plugin>
+
+#<Plugin unixsock>
+#      SocketFile "@prefix@/var/run/@PACKAGE_NAME@-unixsock"
+#      SocketGroup "collectd"
+#      SocketPerms "0660"
+#      DeleteSocket false
+#</Plugin>
+
+#<Plugin uuid>
+#      UUIDFile "/etc/uuid"
+#</Plugin>
+
+#<Plugin mic>
+#   ShowCPU true
+#   ShowCPUCores true
+#   ShowMemory true
+#   ShowTemperatures true
+##  Temperature Sensors can be ignored/shown by repeated #Temperature lines, and
+##  then inverted with a IgnoreSelectedTemperature.
+##  Known Temperature sensors: die, devmem, fin, fout, vccp, vddg, vddq
+#   Temperature vddg
+#   IgnoreSelectedTemperature true
+#   ShowPower true
+##  Power Sensors can be ignored/shown by repeated #Power lines, and
+##  then inverted with a IgnoreSelectedTemperature.
+##  Known Temperature sensors: total0, total1, inst, imax, pci3, c2x3, c2x4, vccp, vddg, vddq
+#   Power total1
+#   IgnoreSelectedPower true
+#</Plugin>
+
+#<Plugin varnish>
+#   This tag support an argument if you want to
+#   monitor the local instance just use </Instance>
+#   If you prefer defining another instance you can do
+#   so by using <Instance "myinstance">
+#   <Instance>
+#      CollectBackend true
+#      CollectBan false           # Varnish 3 and above
+#      CollectCache true
+#      CollectConnections true
+#      CollectDirectorDNS false   # Varnish 3 only
+#      CollectESI false
+#      CollectFetch false
+#      CollectHCB false
+#      CollectObjects false
+#      CollectPurge false         # Varnish 2 only
+#      CollectSession false
+#      CollectSHM true
+#      CollectSMA false           # Varnish 2 only
+#      CollectSMS false
+#      CollectSM false            # Varnish 2 only
+#      CollectStruct false
+#      CollectTotals false
+#      CollectUptime false        # Varnish 3 and above
+#      CollectVCL false
+#      CollectVSM false           # Varnish 4 only
+#      CollectWorkers false
+#   </Instance>
+#</Plugin>
+
+#<Plugin virt>
+#      Connection "xen:///"
+#      RefreshInterval 60
+#      Domain "name"
+#      BlockDevice "name:device"
+#      InterfaceDevice "name:device"
+#      IgnoreSelected false
+#      HostnameFormat name
+#      InterfaceFormat name
+#      PluginInstanceFormat name
+#</Plugin>
+
+#<Plugin vmem>
+#      Verbose false
+#</Plugin>
+
+#<Plugin write_graphite>
+#  <Node "example">
+#    Host "localhost"
+#    Port "2003"
+#    Protocol "tcp"
+#    LogSendErrors true
+#    Prefix "collectd"
+#    Postfix "collectd"
+#    StoreRates true
+#    AlwaysAppendDS false
+#    EscapeCharacter "_"
+#  </Node>
+#</Plugin>
+
+#<Plugin write_http>
+#      <Node "example">
+#              URL "http://example.com/collectd-post"
+#              User "collectd"
+#              Password "weCh3ik0"
+#              VerifyPeer true
+#              VerifyHost true
+#              CACert "/etc/ssl/ca.crt"
+#              CAPath "/etc/ssl/certs/"
+#              ClientKey "/etc/ssl/client.pem"
+#              ClientCert "/etc/ssl/client.crt"
+#              ClientKeyPass "secret"
+#              SSLVersion "TLSv1"
+#              Format "Command"
+#              StoreRates false
+#              BufferSize 4096
+#              LowSpeedLimit 0
+#              Timeout 0
+#      </Node>
+#</Plugin>
+
+#<Plugin write_kafka>
+#  Property "metadata.broker.list" "localhost:9092"
+#  <Topic "collectd">
+#    Format JSON
+#  </Topic>
+#</Plugin>
+
+#<Plugin write_mongodb>
+#      <Node "example">
+#              Host "localhost"
+#              Port "27017"
+#              Timeout 1000
+#              StoreRates false
+#              Database "auth_db"
+#              User "auth_user"
+#              Password "auth_passwd"
+#      </Node>
+#</Plugin>
+
+#<Plugin write_redis>
+#      <Node "example">
+#              Host "localhost"
+#              Port "6379"
+#              Timeout 1000
+#      </Node>
+#</Plugin>
+
+#<Plugin write_riemann>
+#      <Node "example">
+#              Host "localhost"
+#              Port 5555
+#              Protocol TCP
+#              Batch true
+#              BatchMaxSize 8192
+#              StoreRates true
+#              AlwaysAppendDS false
+#              TTLFactor 2.0
+#              Notifications true
+#              CheckThresholds false
+#              EventServicePrefix ""
+#      </Node>
+#      Tag "foobar"
+#      Attribute "foo" "bar"
+#</Plugin>
+
+#<Plugin write_sensu>
+#      <Node "example">
+#              Host "localhost"
+#              Port 3030
+#              StoreRates true
+#              AlwaysAppendDS false
+#              Notifications true
+#              Metrics true
+#              EventServicePrefix ""
+#              MetricHandler "influx"
+#              MetricHandler "default"
+#              NotificationHandler "flapjack"
+#              NotificationHandler "howling_monkey"
+#      </Node>
+#      Tag "foobar"
+#      Attribute "foo" "bar"
+#</Plugin>
+
+#<Plugin write_tsdb>
+#      <Node>
+#              Host "localhost"
+#              Port "4242"
+#              HostTags "status=production"
+#              StoreRates false
+#              AlwaysAppendDS false
+#      </Node>
+#</Plugin>
+
+#<Plugin zookeeper>
+#    Host "localhost"
+#    Port "2181"
+#</Plugin>
+
+##############################################################################
+# Filter configuration                                                       #
+#----------------------------------------------------------------------------#
+# The following configures collectd's filtering mechanism. Before changing   #
+# anything in this section, please read the `FILTER CONFIGURATION' section   #
+# in the collectd.conf(5) manual page.                                       #
+##############################################################################
+
+# Load required matches:
+#@BUILD_PLUGIN_MATCH_EMPTY_COUNTER_TRUE@LoadPlugin match_empty_counter
+#@BUILD_PLUGIN_MATCH_HASHED_TRUE@LoadPlugin match_hashed
+#@BUILD_PLUGIN_MATCH_REGEX_TRUE@LoadPlugin match_regex
+#@BUILD_PLUGIN_MATCH_VALUE_TRUE@LoadPlugin match_value
+#@BUILD_PLUGIN_MATCH_TIMEDIFF_TRUE@LoadPlugin match_timediff
+
+# Load required targets:
+#@BUILD_PLUGIN_TARGET_NOTIFICATION_TRUE@LoadPlugin target_notification
+#@BUILD_PLUGIN_TARGET_REPLACE_TRUE@LoadPlugin target_replace
+#@BUILD_PLUGIN_TARGET_SCALE_TRUE@LoadPlugin target_scale
+#@BUILD_PLUGIN_TARGET_SET_TRUE@LoadPlugin target_set
+#@BUILD_PLUGIN_TARGET_V5UPGRADE_TRUE@LoadPlugin target_v5upgrade
+
+#----------------------------------------------------------------------------#
+# The following block demonstrates the default behavior if no filtering is   #
+# configured at all: All values will be sent to all available write plugins. #
+#----------------------------------------------------------------------------#
+
+#<Chain "PostCache">
+#  Target "write"
+#</Chain>
+
+##############################################################################
+# Threshold configuration                                                    #
+#----------------------------------------------------------------------------#
+# The following outlines how to configure collectd's threshold checking      #
+# plugin. The plugin and possible configuration options are documented in    #
+# the collectd-threshold(5) manual page.                                     #
+##############################################################################
+
+#@BUILD_PLUGIN_THRESHOLD_TRUE@LoadPlugin "threshold"
+#<Plugin threshold>
+#  <Type "foo">
+#    WarningMin    0.00
+#    WarningMax 1000.00
+#    FailureMin    0.00
+#    FailureMax 1200.00
+#    Invert false
+#    Instance "bar"
+#  </Type>
+#
+#  <Plugin "interface">
+#    Instance "eth0"
+#    <Type "if_octets">
+#      FailureMax 10000000
+#      DataSource "rx"
+#    </Type>
+#  </Plugin>
+#
+#  <Host "hostname">
+#    <Type "cpu">
+#      Instance "idle"
+#      FailureMin 10
+#    </Type>
+#
+#    <Plugin "memory">
+#      <Type "memory">
+#        Instance "cached"
+#        WarningMin 100000000
+#      </Type>
+#    </Plugin>
+#
+#    <Type "load">
+#      DataSource "midterm"
+#      FailureMax 4
+#      Hits 3
+#      Hysteresis 3
+#    </Type>
+#  </Host>
+#</Plugin>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
new file mode 100644 (file)
index 0000000..0c8e1e2
--- /dev/null
@@ -0,0 +1,8701 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd.conf - Configuration for the system statistics collection daemon B<collectd>
+
+=head1 SYNOPSIS
+
+  BaseDir "/var/lib/collectd"
+  PIDFile "/run/collectd.pid"
+  Interval 10.0
+
+  LoadPlugin cpu
+  LoadPlugin load
+
+  <LoadPlugin df>
+    Interval 3600
+  </LoadPlugin>
+  <Plugin df>
+    ValuesPercentage true
+  </Plugin>
+
+  LoadPlugin ping
+  <Plugin ping>
+    Host "example.org"
+    Host "provider.net"
+  </Plugin>
+
+=head1 DESCRIPTION
+
+This config file controls how the system statistics collection daemon
+B<collectd> behaves. The most significant option is B<LoadPlugin>, which
+controls which plugins to load. These plugins ultimately define collectd's
+behavior. If the B<AutoLoadPlugin> option has been enabled, the explicit
+B<LoadPlugin> lines may be omitted for all plugins with a configuration block,
+i.e. a C<E<lt>PluginE<nbsp>...E<gt>> block.
+
+The syntax of this config file is similar to the config file of the famous
+I<Apache> webserver. Each line contains either an option (a key and a list of
+one or more values) or a section-start or -end. Empty lines and everything
+after a non-quoted hash-symbol (C<#>) is ignored. I<Keys> are unquoted
+strings, consisting only of alphanumeric characters and the underscore (C<_>)
+character. Keys are handled case insensitive by I<collectd> itself and all
+plugins included with it. I<Values> can either be an I<unquoted string>, a
+I<quoted string> (enclosed in double-quotes) a I<number> or a I<boolean>
+expression. I<Unquoted strings> consist of only alphanumeric characters and
+underscores (C<_>) and do not need to be quoted. I<Quoted strings> are
+enclosed in double quotes (C<">). You can use the backslash character (C<\>)
+to include double quotes as part of the string. I<Numbers> can be specified in
+decimal and floating point format (using a dot C<.> as decimal separator),
+hexadecimal when using the C<0x> prefix and octal with a leading zero (C<0>).
+I<Boolean> values are either B<true> or B<false>.
+
+Lines may be wrapped by using C<\> as the last character before the newline.
+This allows long lines to be split into multiple lines. Quoted strings may be
+wrapped as well. However, those are treated special in that whitespace at the
+beginning of the following lines will be ignored, which allows for nicely
+indenting the wrapped lines.
+
+The configuration is read and processed in order, i.e. from top to bottom. So
+the plugins are loaded in the order listed in this config file. It is a good
+idea to load any logging plugins first in order to catch messages from plugins
+during configuration. Also, unless B<AutoLoadPlugin> is enabled, the
+B<LoadPlugin> option I<must> occur I<before> the appropriate
+C<E<lt>B<Plugin> ...E<gt>> block.
+
+=head1 GLOBAL OPTIONS
+
+=over 4
+
+=item B<BaseDir> I<Directory>
+
+Sets the base directory. This is the directory beneath all RRD-files are
+created. Possibly more subdirectories are created. This is also the working
+directory for the daemon.
+
+=item B<LoadPlugin> I<Plugin>
+
+Loads the plugin I<Plugin>. This is required to load plugins, unless the
+B<AutoLoadPlugin> option is enabled (see below). Without any loaded plugins,
+I<collectd> will be mostly useless.
+
+Only the first B<LoadPlugin> statement or block for a given plugin name has any
+effect. This is useful when you want to split up the configuration into smaller
+files and want each file to be "self contained", i.e. it contains a B<Plugin>
+block I<and> then appropriate B<LoadPlugin> statement. The downside is that if
+you have multiple conflicting B<LoadPlugin> blocks, e.g. when they specify
+different intervals, only one of them (the first one encountered) will take
+effect and all others will be silently ignored.
+
+B<LoadPlugin> may either be a simple configuration I<statement> or a I<block>
+with additional options, affecting the behavior of B<LoadPlugin>. A simple
+statement looks like this:
+
+ LoadPlugin "cpu"
+
+Options inside a B<LoadPlugin> block can override default settings and
+influence the way plugins are loaded, e.g.:
+
+ <LoadPlugin perl>
+   Interval 60
+ </LoadPlugin>
+
+The following options are valid inside B<LoadPlugin> blocks:
+
+=over 4
+
+=item B<Globals> B<true|false>
+
+If enabled, collectd will export all global symbols of the plugin (and of all
+libraries loaded as dependencies of the plugin) and, thus, makes those symbols
+available for resolving unresolved symbols in subsequently loaded plugins if
+that is supported by your system.
+
+This is useful (or possibly even required), e.g., when loading a plugin that
+embeds some scripting language into the daemon (e.g. the I<Perl> and
+I<Python plugins>). Scripting languages usually provide means to load
+extensions written in C. Those extensions require symbols provided by the
+interpreter, which is loaded as a dependency of the respective collectd plugin.
+See the documentation of those plugins (e.g., L<collectd-perl(5)> or
+L<collectd-python(5)>) for details.
+
+By default, this is disabled. As a special exception, if the plugin name is
+either C<perl> or C<python>, the default is changed to enabled in order to keep
+the average user from ever having to deal with this low level linking stuff.
+
+=item B<Interval> I<Seconds>
+
+Sets a plugin-specific interval for collecting metrics. This overrides the
+global B<Interval> setting. If a plugin provides own support for specifying an
+interval, that setting will take precedence.
+
+=back
+
+=item B<AutoLoadPlugin> B<false>|B<true>
+
+When set to B<false> (the default), each plugin needs to be loaded explicitly,
+using the B<LoadPlugin> statement documented above. If a
+B<E<lt>PluginE<nbsp>...E<gt>> block is encountered and no configuration
+handling callback for this plugin has been registered, a warning is logged and
+the block is ignored.
+
+When set to B<true>, explicit B<LoadPlugin> statements are not required. Each
+B<E<lt>PluginE<nbsp>...E<gt>> block acts as if it was immediately preceded by a
+B<LoadPlugin> statement. B<LoadPlugin> statements are still required for
+plugins that don't provide any configuration, e.g. the I<Load plugin>.
+
+=item B<CollectInternalStats> B<false>|B<true>
+
+When set to B<true>, various statistics about the I<collectd> daemon will be
+collected, with "collectd" as the I<plugin name>. Defaults to B<false>.
+
+The "write_queue" I<plugin instance> reports the number of elements currently
+queued and the number of elements dropped off the queue by the
+B<WriteQueueLimitLow>/B<WriteQueueLimitHigh> mechanism.
+
+The "cache" I<plugin instance> reports the number of elements in the value list
+cache (the cache you can interact with using L<collectd-unixsock(5)>).
+
+=item B<Include> I<Path> [I<pattern>]
+
+If I<Path> points to a file, includes that file. If I<Path> points to a
+directory, recursively includes all files within that directory and its
+subdirectories. If the C<wordexp> function is available on your system,
+shell-like wildcards are expanded before files are included. This means you can
+use statements like the following:
+
+  Include "/etc/collectd.d/*.conf"
+
+Starting with version 5.3, this may also be a block in which further options
+affecting the behavior of B<Include> may be specified. The following option is
+currently allowed:
+
+  <Include "/etc/collectd.d">
+    Filter "*.conf"
+  </Include>
+
+=over 4
+
+=item B<Filter> I<pattern>
+
+If the C<fnmatch> function is available on your system, a shell-like wildcard
+I<pattern> may be specified to filter which files to include. This may be used
+in combination with recursively including a directory to easily be able to
+arbitrarily mix configuration files and other documents (e.g. README files).
+The given example is similar to the first example above but includes all files
+matching C<*.conf> in any subdirectory of C</etc/collectd.d>:
+
+  Include "/etc/collectd.d" "*.conf"
+
+=back
+
+If more than one files are included by a single B<Include> option, the files
+will be included in lexicographical order (as defined by the C<strcmp>
+function). Thus, you can e.E<nbsp>g. use numbered prefixes to specify the
+order in which the files are loaded.
+
+To prevent loops and shooting yourself in the foot in interesting ways the
+nesting is limited to a depth of 8E<nbsp>levels, which should be sufficient for
+most uses. Since symlinks are followed it is still possible to crash the daemon
+by looping symlinks. In our opinion significant stupidity should result in an
+appropriate amount of pain.
+
+It is no problem to have a block like C<E<lt>Plugin fooE<gt>> in more than one
+file, but you cannot include files from within blocks.
+
+=item B<PIDFile> I<File>
+
+Sets where to write the PID file to. This file is overwritten when it exists
+and deleted when the program is stopped. Some init-scripts might override this
+setting using the B<-P> command-line option.
+
+=item B<PluginDir> I<Directory>
+
+Path to the plugins (shared objects) of collectd.
+
+=item B<TypesDB> I<File> [I<File> ...]
+
+Set one or more files that contain the data-set descriptions. See
+L<types.db(5)> for a description of the format of this file.
+
+=item B<Interval> I<Seconds>
+
+Configures the interval in which to query the read plugins. Obviously smaller
+values lead to a higher system load produced by collectd, while higher values
+lead to more coarse statistics.
+
+B<Warning:> You should set this once and then never touch it again. If you do,
+I<you will have to delete all your RRD files> or know some serious RRDtool
+magic! (Assuming you're using the I<RRDtool> or I<RRDCacheD> plugin.)
+
+=item B<MaxReadInterval> I<Seconds>
+
+Read plugin doubles interval between queries after each failed attempt
+to get data.
+
+This options limits the maximum value of the interval. The default value is
+B<86400>.
+
+=item B<Timeout> I<Iterations>
+
+Consider a value list "missing" when no update has been read or received for
+I<Iterations> iterations. By default, I<collectd> considers a value list
+missing when no update has been received for twice the update interval. Since
+this setting uses iterations, the maximum allowed time without update depends
+on the I<Interval> information contained in each value list. This is used in
+the I<Threshold> configuration to dispatch notifications about missing values,
+see L<collectd-threshold(5)> for details.
+
+=item B<ReadThreads> I<Num>
+
+Number of threads to start for reading plugins. The default value is B<5>, but
+you may want to increase this if you have more than five plugins that take a
+long time to read. Mostly those are plugins that do network-IO. Setting this to
+a value higher than the number of registered read callbacks is not recommended.
+
+=item B<WriteThreads> I<Num>
+
+Number of threads to start for dispatching value lists to write plugins. The
+default value is B<5>, but you may want to increase this if you have more than
+five plugins that may take relatively long to write to.
+
+=item B<WriteQueueLimitHigh> I<HighNum>
+
+=item B<WriteQueueLimitLow> I<LowNum>
+
+Metrics are read by the I<read threads> and then put into a queue to be handled
+by the I<write threads>. If one of the I<write plugins> is slow (e.g. network
+timeouts, I/O saturation of the disk) this queue will grow. In order to avoid
+running into memory issues in such a case, you can limit the size of this
+queue.
+
+By default, there is no limit and memory may grow indefinitely. This is most
+likely not an issue for clients, i.e. instances that only handle the local
+metrics. For servers it is recommended to set this to a non-zero value, though.
+
+You can set the limits using B<WriteQueueLimitHigh> and B<WriteQueueLimitLow>.
+Each of them takes a numerical argument which is the number of metrics in the
+queue. If there are I<HighNum> metrics in the queue, any new metrics I<will> be
+dropped. If there are less than I<LowNum> metrics in the queue, all new metrics
+I<will> be enqueued. If the number of metrics currently in the queue is between
+I<LowNum> and I<HighNum>, the metric is dropped with a probability that is
+proportional to the number of metrics in the queue (i.e. it increases linearly
+until it reaches 100%.)
+
+If B<WriteQueueLimitHigh> is set to non-zero and B<WriteQueueLimitLow> is
+unset, the latter will default to half of B<WriteQueueLimitHigh>.
+
+If you do not want to randomly drop values when the queue size is between
+I<LowNum> and I<HighNum>, set B<WriteQueueLimitHigh> and B<WriteQueueLimitLow>
+to the same value.
+
+Enabling the B<CollectInternalStats> option is of great help to figure out the
+values to set B<WriteQueueLimitHigh> and B<WriteQueueLimitLow> to.
+
+=item B<Hostname> I<Name>
+
+Sets the hostname that identifies a host. If you omit this setting, the
+hostname will be determined using the L<gethostname(2)> system call.
+
+=item B<FQDNLookup> B<true|false>
+
+If B<Hostname> is determined automatically this setting controls whether or not
+the daemon should try to figure out the "fully qualified domain name", FQDN.
+This is done using a lookup of the name returned by C<gethostname>. This option
+is enabled by default.
+
+=item B<PreCacheChain> I<ChainName>
+
+=item B<PostCacheChain> I<ChainName>
+
+Configure the name of the "pre-cache chain" and the "post-cache chain". Please
+see L<FILTER CONFIGURATION> below on information on chains and how these
+setting change the daemon's behavior.
+
+=back
+
+=head1 PLUGIN OPTIONS
+
+Some plugins may register own options. These options must be enclosed in a
+C<Plugin>-Section. Which options exist depends on the plugin used. Some plugins
+require external configuration, too. The C<apache plugin>, for example,
+required C<mod_status> to be configured in the webserver you're going to
+collect data from. These plugins are listed below as well, even if they don't
+require any configuration within collectd's configuration file.
+
+A list of all plugins and a short summary for each plugin can be found in the
+F<README> file shipped with the sourcecode and hopefully binary packets as
+well.
+
+=head2 Plugin C<aggregation>
+
+The I<Aggregation plugin> makes it possible to aggregate several values into
+one using aggregation functions such as I<sum>, I<average>, I<min> and I<max>.
+This can be put to a wide variety of uses, e.g. average and total CPU
+statistics for your entire fleet.
+
+The grouping is powerful but, as with many powerful tools, may be a bit
+difficult to wrap your head around. The grouping will therefore be
+demonstrated using an example: The average and sum of the CPU usage across
+all CPUs of each host is to be calculated.
+
+To select all the affected values for our example, set C<Plugin cpu> and
+C<Type cpu>. The other values are left unspecified, meaning "all values". The
+I<Host>, I<Plugin>, I<PluginInstance>, I<Type> and I<TypeInstance> options
+work as if they were specified in the C<WHERE> clause of an C<SELECT> SQL
+statement.
+
+  Plugin "cpu"
+  Type "cpu"
+
+Although the I<Host>, I<PluginInstance> (CPU number, i.e. 0, 1, 2, ...)  and
+I<TypeInstance> (idle, user, system, ...) fields are left unspecified in the
+example, the intention is to have a new value for each host / type instance
+pair. This is achieved by "grouping" the values using the C<GroupBy> option.
+It can be specified multiple times to group by more than one field.
+
+  GroupBy "Host"
+  GroupBy "TypeInstance"
+
+We do neither specify nor group by I<plugin instance> (the CPU number), so all
+metrics that differ in the CPU number only will be aggregated. Each
+aggregation needs I<at least one> such field, otherwise no aggregation would
+take place.
+
+The full example configuration looks like this:
+
+ <Plugin "aggregation">
+   <Aggregation>
+     Plugin "cpu"
+     Type "cpu"
+
+     GroupBy "Host"
+     GroupBy "TypeInstance"
+
+     CalculateSum true
+     CalculateAverage true
+   </Aggregation>
+ </Plugin>
+
+There are a couple of limitations you should be aware of:
+
+=over 4
+
+=item
+
+The I<Type> cannot be left unspecified, because it is not reasonable to add
+apples to oranges. Also, the internal lookup structure won't work if you try
+to group by type.
+
+=item
+
+There must be at least one unspecified, ungrouped field. Otherwise nothing
+will be aggregated.
+
+=back
+
+As you can see in the example above, each aggregation has its own
+B<Aggregation> block. You can have multiple aggregation blocks and aggregation
+blocks may match the same values, i.e. one value list can update multiple
+aggregations. The following options are valid inside B<Aggregation> blocks:
+
+=over 4
+
+=item B<Host> I<Host>
+
+=item B<Plugin> I<Plugin>
+
+=item B<PluginInstance> I<PluginInstance>
+
+=item B<Type> I<Type>
+
+=item B<TypeInstance> I<TypeInstance>
+
+Selects the value lists to be added to this aggregation. B<Type> must be a
+valid data set name, see L<types.db(5)> for details.
+
+If the string starts with and ends with a slash (C</>), the string is
+interpreted as a I<regular expression>. The regex flavor used are POSIX
+extended regular expressions as described in L<regex(7)>. Example usage:
+
+ Host "/^db[0-9]\\.example\\.com$/"
+
+=item B<GroupBy> B<Host>|B<Plugin>|B<PluginInstance>|B<TypeInstance>
+
+Group valued by the specified field. The B<GroupBy> option may be repeated to
+group by multiple fields.
+
+=item B<SetHost> I<Host>
+
+=item B<SetPlugin> I<Plugin>
+
+=item B<SetPluginInstance> I<PluginInstance>
+
+=item B<SetTypeInstance> I<TypeInstance>
+
+Sets the appropriate part of the identifier to the provided string.
+
+The I<PluginInstance> should include the placeholder C<%{aggregation}> which
+will be replaced with the aggregation function, e.g. "average". Not including
+the placeholder will result in duplication warnings and/or messed up values if
+more than one aggregation function are enabled.
+
+The following example calculates the average usage of all "even" CPUs:
+
+ <Plugin "aggregation">
+   <Aggregation>
+     Plugin "cpu"
+     PluginInstance "/[0,2,4,6,8]$/"
+     Type "cpu"
+
+     SetPlugin "cpu"
+     SetPluginInstance "even-%{aggregation}"
+
+     GroupBy "Host"
+     GroupBy "TypeInstance"
+
+     CalculateAverage true
+   </Aggregation>
+ </Plugin>
+
+This will create the files:
+
+=over 4
+
+=item
+
+foo.example.com/cpu-even-average/cpu-idle
+
+=item
+
+foo.example.com/cpu-even-average/cpu-system
+
+=item
+
+foo.example.com/cpu-even-average/cpu-user
+
+=item
+
+...
+
+=back
+
+=item B<CalculateNum> B<true>|B<false>
+
+=item B<CalculateSum> B<true>|B<false>
+
+=item B<CalculateAverage> B<true>|B<false>
+
+=item B<CalculateMinimum> B<true>|B<false>
+
+=item B<CalculateMaximum> B<true>|B<false>
+
+=item B<CalculateStddev> B<true>|B<false>
+
+Boolean options for enabling calculation of the number of value lists, their
+sum, average, minimum, maximum andE<nbsp>/ or standard deviation. All options
+are disabled by default.
+
+=back
+
+=head2 Plugin C<amqp>
+
+The I<AMQMP plugin> can be used to communicate with other instances of
+I<collectd> or third party applications using an AMQP message broker. Values
+are sent to or received from the broker, which handles routing, queueing and
+possibly filtering or messages.
+
+ <Plugin "amqp">
+   # Send values to an AMQP broker
+   <Publish "some_name">
+     Host "localhost"
+     Port "5672"
+     VHost "/"
+     User "guest"
+     Password "guest"
+     Exchange "amq.fanout"
+ #   ExchangeType "fanout"
+ #   RoutingKey "collectd"
+ #   Persistent false
+ #   ConnectionRetryDelay 0
+ #   Format "command"
+ #   StoreRates false
+ #   GraphitePrefix "collectd."
+ #   GraphiteEscapeChar "_"
+ #   GraphiteSeparateInstances false
+ #   GraphiteAlwaysAppendDS false
+   </Publish>
+
+   # Receive values from an AMQP broker
+   <Subscribe "some_name">
+     Host "localhost"
+     Port "5672"
+     VHost "/"
+     User "guest"
+     Password "guest"
+     Exchange "amq.fanout"
+ #   ExchangeType "fanout"
+ #   Queue "queue_name"
+ #   QueueDurable false
+ #   QueueAutoDelete true
+ #   RoutingKey "collectd.#"
+ #   ConnectionRetryDelay 0
+   </Subscribe>
+ </Plugin>
+
+The plugin's configuration consists of a number of I<Publish> and I<Subscribe>
+blocks, which configure sending and receiving of values respectively. The two
+blocks are very similar, so unless otherwise noted, an option can be used in
+either block. The name given in the blocks starting tag is only used for
+reporting messages, but may be used to support I<flushing> of certain
+I<Publish> blocks in the future.
+
+=over 4
+
+=item B<Host> I<Host>
+
+Hostname or IP-address of the AMQP broker. Defaults to the default behavior of
+the underlying communications library, I<rabbitmq-c>, which is "localhost".
+
+=item B<Port> I<Port>
+
+Service name or port number on which the AMQP broker accepts connections. This
+argument must be a string, even if the numeric form is used. Defaults to
+"5672".
+
+=item B<VHost> I<VHost>
+
+Name of the I<virtual host> on the AMQP broker to use. Defaults to "/".
+
+=item B<User> I<User>
+
+=item B<Password> I<Password>
+
+Credentials used to authenticate to the AMQP broker. By default "guest"/"guest"
+is used.
+
+=item B<Exchange> I<Exchange>
+
+In I<Publish> blocks, this option specifies the I<exchange> to send values to.
+By default, "amq.fanout" will be used.
+
+In I<Subscribe> blocks this option is optional. If given, a I<binding> between
+the given exchange and the I<queue> is created, using the I<routing key> if
+configured. See the B<Queue> and B<RoutingKey> options below.
+
+=item B<ExchangeType> I<Type>
+
+If given, the plugin will try to create the configured I<exchange> with this
+I<type> after connecting. When in a I<Subscribe> block, the I<queue> will then
+be bound to this exchange.
+
+=item B<Queue> I<Queue> (Subscribe only)
+
+Configures the I<queue> name to subscribe to. If no queue name was configured
+explicitly, a unique queue name will be created by the broker.
+
+=item B<QueueDurable> B<true>|B<false> (Subscribe only)
+
+Defines if the I<queue> subscribed to is durable (saved to persistent storage)
+or transient (will disappear if the AMQP broker is restarted). Defaults to
+"false".
+
+This option should be used in conjunction with the I<Persistent> option on the
+publish side.
+
+=item B<QueueAutoDelete> B<true>|B<false> (Subscribe only)
+
+Defines if the I<queue> subscribed to will be deleted once the last consumer
+unsubscribes. Defaults to "true".
+
+=item B<RoutingKey> I<Key>
+
+In I<Publish> blocks, this configures the routing key to set on all outgoing
+messages. If not given, the routing key will be computed from the I<identifier>
+of the value. The host, plugin, type and the two instances are concatenated
+together using dots as the separator and all containing dots replaced with
+slashes. For example "collectd.host/example/com.cpu.0.cpu.user". This makes it
+possible to receive only specific values using a "topic" exchange.
+
+In I<Subscribe> blocks, configures the I<routing key> used when creating a
+I<binding> between an I<exchange> and the I<queue>. The usual wildcards can be
+used to filter messages when using a "topic" exchange. If you're only
+interested in CPU statistics, you could use the routing key "collectd.*.cpu.#"
+for example.
+
+=item B<Persistent> B<true>|B<false> (Publish only)
+
+Selects the I<delivery method> to use. If set to B<true>, the I<persistent>
+mode will be used, i.e. delivery is guaranteed. If set to B<false> (the
+default), the I<transient> delivery mode will be used, i.e. messages may be
+lost due to high load, overflowing queues or similar issues.
+
+=item B<ConnectionRetryDelay> I<Delay>
+
+When the connection to the AMQP broker is lost, defines the time in seconds to
+wait before attempting to reconnect. Defaults to 0, which implies collectd will
+attempt to reconnect at each read interval (in Subscribe mode) or each time
+values are ready for submission (in Publish mode).
+
+=item B<Format> B<Command>|B<JSON>|B<Graphite> (Publish only)
+
+Selects the format in which messages are sent to the broker. If set to
+B<Command> (the default), values are sent as C<PUTVAL> commands which are
+identical to the syntax used by the I<Exec> and I<UnixSock plugins>. In this
+case, the C<Content-Type> header field will be set to C<text/collectd>.
+
+If set to B<JSON>, the values are encoded in the I<JavaScript Object Notation>,
+an easy and straight forward exchange format. The C<Content-Type> header field
+will be set to C<application/json>.
+
+If set to B<Graphite>, values are encoded in the I<Graphite> format, which is
+"<metric> <value> <timestamp>\n". The C<Content-Type> header field will be set to
+C<text/graphite>.
+
+A subscribing client I<should> use the C<Content-Type> header field to
+determine how to decode the values. Currently, the I<AMQP plugin> itself can
+only decode the B<Command> format.
+
+=item B<StoreRates> B<true>|B<false> (Publish only)
+
+Determines whether or not C<COUNTER>, C<DERIVE> and C<ABSOLUTE> data sources
+are converted to a I<rate> (i.e. a C<GAUGE> value). If set to B<false> (the
+default), no conversion is performed. Otherwise the conversion is performed
+using the internal value cache.
+
+Please note that currently this option is only used if the B<Format> option has
+been set to B<JSON>.
+
+=item B<GraphitePrefix> (Publish and B<Format>=I<Graphite> only)
+
+A prefix can be added in the metric name when outputting in the I<Graphite> format.
+It's added before the I<Host> name.
+Metric name will be "<prefix><host><postfix><plugin><type><name>"
+
+=item B<GraphitePostfix> (Publish and B<Format>=I<Graphite> only)
+
+A postfix can be added in the metric name when outputting in the I<Graphite> format.
+It's added after the I<Host> name.
+Metric name will be "<prefix><host><postfix><plugin><type><name>"
+
+=item B<GraphiteEscapeChar> (Publish and B<Format>=I<Graphite> only)
+
+Specify a character to replace dots (.) in the host part of the metric name.
+In I<Graphite> metric name, dots are used as separators between different
+metric parts (host, plugin, type).
+Default is "_" (I<Underscore>).
+
+=item B<GraphiteSeparateInstances> B<true>|B<false>
+
+If set to B<true>, the plugin instance and type instance will be in their own
+path component, for example C<host.cpu.0.cpu.idle>. If set to B<false> (the
+default), the plugin and plugin instance (and likewise the type and type
+instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
+
+=item B<GraphiteAlwaysAppendDS> B<true>|B<false>
+
+If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
+identifier. If set to B<false> (the default), this is only done when there is
+more than one DS.
+
+=back
+
+=head2 Plugin C<apache>
+
+To configure the C<apache>-plugin you first need to configure the Apache
+webserver correctly. The Apache-plugin C<mod_status> needs to be loaded and
+working and the C<ExtendedStatus> directive needs to be B<enabled>. You can use
+the following snipped to base your Apache config upon:
+
+  ExtendedStatus on
+  <IfModule mod_status.c>
+    <Location /mod_status>
+      SetHandler server-status
+    </Location>
+  </IfModule>
+
+Since its C<mod_status> module is very similar to Apache's, B<lighttpd> is
+also supported. It introduces a new field, called C<BusyServers>, to count the
+number of currently connected clients. This field is also supported.
+
+The configuration of the I<Apache> plugin consists of one or more
+C<E<lt>InstanceE<nbsp>/E<gt>> blocks. Each block requires one string argument
+as the instance name. For example:
+
+ <Plugin "apache">
+   <Instance "www1">
+     URL "http://www1.example.com/mod_status?auto"
+   </Instance>
+   <Instance "www2">
+     URL "http://www2.example.com/mod_status?auto"
+   </Instance>
+ </Plugin>
+
+The instance name will be used as the I<plugin instance>. To emulate the old
+(versionE<nbsp>4) behavior, you can use an empty string (""). In order for the
+plugin to work correctly, each instance name must be unique. This is not
+enforced by the plugin and it is your responsibility to ensure it.
+
+The following options are accepted within each I<Instance> block:
+
+=over 4
+
+=item B<URL> I<http://host/mod_status?auto>
+
+Sets the URL of the C<mod_status> output. This needs to be the output generated
+by C<ExtendedStatus on> and it needs to be the machine readable output
+generated by appending the C<?auto> argument. This option is I<mandatory>.
+
+=item B<User> I<Username>
+
+Optional user name needed for authentication.
+
+=item B<Password> I<Password>
+
+Optional password needed for authentication.
+
+=item B<VerifyPeer> B<true|false>
+
+Enable or disable peer SSL certificate verification. See
+L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enable or disable peer host name verification. If enabled, the plugin checks
+if the C<Common Name> or a C<Subject Alternate Name> field of the SSL
+certificate matches the host name provided by the B<URL> option. If this
+identity check fails, the connection is aborted. Obviously, only works when
+connecting to a SSL enabled server. Enabled by default.
+
+=item B<CACert> I<File>
+
+File that holds one or more SSL certificates. If you want to use HTTPS you will
+possibly need this option. What CA certificates come bundled with C<libcurl>
+and are checked by default depends on the distribution you use.
+
+=item B<SSLCiphers> I<list of ciphers>
+
+Specifies which ciphers to use in the connection. The list of ciphers
+must specify valid ciphers. See
+L<http://www.openssl.org/docs/apps/ciphers.html> for details.
+
+=item B<Timeout> I<Milliseconds>
+
+The B<Timeout> option sets the overall timeout for HTTP requests to B<URL>, in
+milliseconds. By default, the configured B<Interval> is used to set the
+timeout.
+
+=back
+
+=head2 Plugin C<apcups>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the host running B<apcupsd>. Defaults to B<localhost>. Please note
+that IPv6 support has been disabled unless someone can confirm or decline that
+B<apcupsd> can handle it.
+
+=item B<Port> I<Port>
+
+TCP-Port to connect to. Defaults to B<3551>.
+
+=item B<ReportSeconds> B<true|false>
+
+If set to B<true>, the time reported in the C<timeleft> metric will be
+converted to seconds. This is the recommended setting. If set to B<false>, the
+default for backwards compatibility, the time will be reported in minutes.
+
+=back
+
+=head2 Plugin C<aquaero>
+
+This plugin collects the value of the available sensors in an
+I<AquaeroE<nbsp>5> board. AquaeroE<nbsp>5 is a water-cooling controller board,
+manufactured by Aqua Computer GmbH L<http://www.aquacomputer.de/>, with a USB2
+connection for monitoring and configuration. The board can handle multiple
+temperature sensors, fans, water pumps and water level sensors and adjust the
+output settings such as fan voltage or power used by the water pump based on
+the available inputs using a configurable controller included in the board.
+This plugin collects all the available inputs as well as some of the output
+values chosen by this controller. The plugin is based on the I<libaquaero5>
+library provided by I<aquatools-ng>.
+
+=over 4
+
+=item B<Device> I<DevicePath>
+
+Device path of the AquaeroE<nbsp>5's USB HID (human interface device), usually
+in the form C</dev/usb/hiddevX>. If this option is no set the plugin will try
+to auto-detect the Aquaero 5 USB device based on vendor-ID and product-ID.
+
+=back
+
+=head2 Plugin C<ascent>
+
+This plugin collects information about an Ascent server, a free server for the
+"World of Warcraft" game. This plugin gathers the information by fetching the
+XML status page using C<libcurl> and parses it using C<libxml2>.
+
+The configuration options are the same as for the C<apache> plugin above:
+
+=over 4
+
+=item B<URL> I<http://localhost/ascent/status/>
+
+Sets the URL of the XML status output.
+
+=item B<User> I<Username>
+
+Optional user name needed for authentication.
+
+=item B<Password> I<Password>
+
+Optional password needed for authentication.
+
+=item B<VerifyPeer> B<true|false>
+
+Enable or disable peer SSL certificate verification. See
+L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enable or disable peer host name verification. If enabled, the plugin checks
+if the C<Common Name> or a C<Subject Alternate Name> field of the SSL
+certificate matches the host name provided by the B<URL> option. If this
+identity check fails, the connection is aborted. Obviously, only works when
+connecting to a SSL enabled server. Enabled by default.
+
+=item B<CACert> I<File>
+
+File that holds one or more SSL certificates. If you want to use HTTPS you will
+possibly need this option. What CA certificates come bundled with C<libcurl>
+and are checked by default depends on the distribution you use.
+
+=item B<Timeout> I<Milliseconds>
+
+The B<Timeout> option sets the overall timeout for HTTP requests to B<URL>, in
+milliseconds. By default, the configured B<Interval> is used to set the
+timeout.
+
+=back
+
+=head2 Plugin C<barometer>
+
+This plugin reads absolute air pressure using digital barometer sensor on a I2C
+bus. Supported sensors are:
+
+=over 5
+
+=item I<MPL115A2> from Freescale,
+see L<http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL115A>.
+
+
+=item I<MPL3115> from Freescale
+see L<http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL3115A2>.
+
+
+=item I<BMP085> from Bosch Sensortec
+
+=back
+
+The sensor type - one of the above - is detected automatically by the plugin
+and indicated in the plugin_instance (you will see subdirectory
+"barometer-mpl115" or "barometer-mpl3115", or "barometer-bmp085"). The order of
+detection is BMP085 -> MPL3115 -> MPL115A2, the first one found will be used
+(only one sensor can be used by the plugin).
+
+The plugin provides absolute barometric pressure, air pressure reduced to sea
+level (several possible approximations) and as an auxiliary value also internal
+sensor temperature. It uses (expects/provides) typical metric units - pressure
+in [hPa], temperature in [C], altitude in [m].
+
+It was developed and tested under Linux only. The only platform dependency is
+the standard Linux i2c-dev interface (the particular bus driver has to
+support the SM Bus command subset).
+
+The reduction or normalization to mean sea level pressure requires (depending
+on selected method/approximation) also altitude and reference to temperature
+sensor(s).  When multiple temperature sensors are configured the minumum of
+their values is always used (expecting that the warmer ones are affected by
+e.g. direct sun light at that moment).
+
+Synopsis:
+
+  <Plugin "barometer">
+     Device            "/dev/i2c-0";
+     Oversampling      512
+     PressureOffset    0.0
+     TemperatureOffset 0.0
+     Normalization     2
+     Altitude          238.0
+     TemperatureSensor "myserver/onewire-F10FCA000800/temperature"
+  </Plugin>
+
+=over 4
+
+=item B<Device> I<device>
+
+The only mandatory configuration parameter.
+
+Device name of the I2C bus to which the sensor is connected. Note that
+typically you need to have loaded the i2c-dev module.
+Using i2c-tools you can check/list i2c buses available on your system by:
+
+  i2cdetect -l
+
+Then you can scan for devices on given bus. E.g. to scan the whole bus 0 use:
+
+  i2cdetect -y -a 0
+
+This way you should be able to verify that the pressure sensor (either type) is
+connected and detected on address 0x60.
+
+=item B<Oversampling> I<value>
+
+Optional parameter controlling the oversampling/accuracy. Default value
+is 1 providing fastest and least accurate reading.
+
+For I<MPL115> this is the size of the averaging window. To filter out sensor
+noise a simple averaging using floating window of this configurable size is
+used. The plugin will use average of the last C<value> measurements (value of 1
+means no averaging).  Minimal size is 1, maximal 1024.
+
+For I<MPL3115> this is the oversampling value. The actual oversampling is
+performed by the sensor and the higher value the higher accuracy and longer
+conversion time (although nothing to worry about in the collectd context).
+Supported values are: 1, 2, 4, 8, 16, 32, 64 and 128. Any other value is
+adjusted by the plugin to the closest supported one.
+
+For I<BMP085> this is the oversampling value. The actual oversampling is
+performed by the sensor and the higher value the higher accuracy and longer
+conversion time (although nothing to worry about in the collectd context).
+Supported values are: 1, 2, 4, 8. Any other value is adjusted by the plugin to
+the closest supported one.
+
+=item B<PressureOffset> I<offset>
+
+Optional parameter for MPL3115 only.
+
+You can further calibrate the sensor by supplying pressure and/or temperature
+offsets.  This is added to the measured/caclulated value (i.e. if the measured
+value is too high then use negative offset).
+In hPa, default is 0.0.
+
+=item B<TemperatureOffset> I<offset>
+
+Optional parameter for MPL3115 only.
+
+You can further calibrate the sensor by supplying pressure and/or temperature
+offsets.  This is added to the measured/caclulated value (i.e. if the measured
+value is too high then use negative offset).
+In C, default is 0.0.
+
+=item B<Normalization> I<method>
+
+Optional parameter, default value is 0.
+
+Normalization method - what approximation/model is used to compute the mean sea
+level pressure from the air absolute pressure.
+
+Supported values of the C<method> (integer between from 0 to 2) are:
+
+=over 5
+
+=item B<0> - no conversion, absolute pressure is simply copied over. For this method you
+       do not need to configure C<Altitude> or C<TemperatureSensor>.
+
+=item B<1> - international formula for conversion ,
+See
+L<http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation>.
+For this method you have to configure C<Altitude> but do not need
+C<TemperatureSensor> (uses fixed global temperature average instead).
+
+=item B<2> - formula as recommended by the Deutsche Wetterdienst (German
+Meteorological Service).
+See L<http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie>
+For this method you have to configure both  C<Altitude> and
+C<TemperatureSensor>.
+
+=back
+
+
+=item B<Altitude> I<altitude>
+
+The altitude (in meters) of the location where you meassure the pressure.
+
+=item B<TemperatureSensor> I<reference>
+
+Temperature sensor(s) which should be used as a reference when normalizing the
+pressure using C<Normalization> method 2.
+When specified more sensors a minumum is found and used each time.  The
+temperature reading directly from this pressure sensor/plugin is typically not
+suitable as the pressure sensor will be probably inside while we want outside
+temperature.  The collectd reference name is something like
+<hostname>/<plugin_name>-<plugin_instance>/<type>-<type_instance>
+(<type_instance> is usually omitted when there is just single value type). Or
+you can figure it out from the path of the output data files.
+
+=back
+
+=head2 Plugin C<battery>
+
+The I<battery plugin> reports the remaining capacity, power and voltage of
+laptop batteries.
+
+=over 4
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+When enabled, remaining capacity is reported as a percentage, e.g. "42%
+capacity remaining". Otherwise the capacity is stored as reported by the
+battery, most likely in "Wh". This option does not work with all input methods,
+in particular when only C</proc/pmu> is available on an old Linux system.
+Defaults to B<false>.
+
+=item B<ReportDegraded> B<false>|B<true>
+
+Typical laptop batteries degrade over time, meaning the capacity decreases with
+recharge cycles. The maximum charge of the previous charge cycle is tracked as
+"last full capacity" and used to determine that a battery is "fully charged".
+
+When this option is set to B<false>, the default, the I<battery plugin> will
+only report the remaining capacity. If the B<ValuesPercentage> option is
+enabled, the relative remaining capacity is calculated as the ratio of the
+"remaining capacity" and the "last full capacity". This is what most tools,
+such as the status bar of desktop environments, also do.
+
+When set to B<true>, the battery plugin will report three values: B<charged>
+(remaining capacity), B<discharged> (difference between "last full capacity"
+and "remaining capacity") and B<degraded> (difference between "design capacity"
+and "last full capacity").
+
+=back
+
+=head2 Plugin C<bind>
+
+Starting with BIND 9.5.0, the most widely used DNS server software provides
+extensive statistics about queries, responses and lots of other information.
+The bind plugin retrieves this information that's encoded in XML and provided
+via HTTP and submits the values to collectd.
+
+To use this plugin, you first need to tell BIND to make this information
+available. This is done with the C<statistics-channels> configuration option:
+
+ statistics-channels {
+   inet localhost port 8053;
+ };
+
+The configuration follows the grouping that can be seen when looking at the
+data with an XSLT compatible viewer, such as a modern web browser. It's
+probably a good idea to make yourself familiar with the provided values, so you
+can understand what the collected statistics actually mean.
+
+Synopsis:
+
+ <Plugin "bind">
+   URL "http://localhost:8053/"
+   ParseTime       false
+   OpCodes         true
+   QTypes          true
+
+   ServerStats     true
+   ZoneMaintStats  true
+   ResolverStats   false
+   MemoryStats     true
+
+   <View "_default">
+     QTypes        true
+     ResolverStats true
+     CacheRRSets   true
+
+     Zone "127.in-addr.arpa/IN"
+   </View>
+ </Plugin>
+
+The bind plugin accepts the following configuration options:
+
+=over 4
+
+=item B<URL> I<URL>
+
+URL from which to retrieve the XML data. If not specified,
+C<http://localhost:8053/> will be used.
+
+=item B<ParseTime> B<true>|B<false>
+
+When set to B<true>, the time provided by BIND will be parsed and used to
+dispatch the values. When set to B<false>, the local time source is queried.
+
+This setting is set to B<true> by default for backwards compatibility; setting
+this to B<false> is I<recommended> to avoid problems with timezones and
+localization.
+
+=item B<OpCodes> B<true>|B<false>
+
+When enabled, statistics about the I<"OpCodes">, for example the number of
+C<QUERY> packets, are collected.
+
+Default: Enabled.
+
+=item B<QTypes> B<true>|B<false>
+
+When enabled, the number of I<incoming> queries by query types (for example
+C<A>, C<MX>, C<AAAA>) is collected.
+
+Default: Enabled.
+
+=item B<ServerStats> B<true>|B<false>
+
+Collect global server statistics, such as requests received over IPv4 and IPv6,
+successful queries, and failed updates.
+
+Default: Enabled.
+
+=item B<ZoneMaintStats> B<true>|B<false>
+
+Collect zone maintenance statistics, mostly information about notifications
+(zone updates) and zone transfers.
+
+Default: Enabled.
+
+=item B<ResolverStats> B<true>|B<false>
+
+Collect resolver statistics, i.E<nbsp>e. statistics about outgoing requests
+(e.E<nbsp>g. queries over IPv4, lame servers). Since the global resolver
+counters apparently were removed in BIND 9.5.1 and 9.6.0, this is disabled by
+default. Use the B<ResolverStats> option within a B<View "_default"> block
+instead for the same functionality.
+
+Default: Disabled.
+
+=item B<MemoryStats>
+
+Collect global memory statistics.
+
+Default: Enabled.
+
+=item B<Timeout> I<Milliseconds>
+
+The B<Timeout> option sets the overall timeout for HTTP requests to B<URL>, in
+milliseconds. By default, the configured B<Interval> is used to set the
+timeout.
+
+=item B<View> I<Name>
+
+Collect statistics about a specific I<"view">. BIND can behave different,
+mostly depending on the source IP-address of the request. These different
+configurations are called "views". If you don't use this feature, you most
+likely are only interested in the C<_default> view.
+
+Within a E<lt>B<View>E<nbsp>I<name>E<gt> block, you can specify which
+information you want to collect about a view. If no B<View> block is
+configured, no detailed view statistics will be collected.
+
+=over 4
+
+=item B<QTypes> B<true>|B<false>
+
+If enabled, the number of I<outgoing> queries by query type (e.E<nbsp>g. C<A>,
+C<MX>) is collected.
+
+Default: Enabled.
+
+=item B<ResolverStats> B<true>|B<false>
+
+Collect resolver statistics, i.E<nbsp>e. statistics about outgoing requests
+(e.E<nbsp>g. queries over IPv4, lame servers).
+
+Default: Enabled.
+
+=item B<CacheRRSets> B<true>|B<false>
+
+If enabled, the number of entries (I<"RR sets">) in the view's cache by query
+type is collected. Negative entries (queries which resulted in an error, for
+example names that do not exist) are reported with a leading exclamation mark,
+e.E<nbsp>g. "!A".
+
+Default: Enabled.
+
+=item B<Zone> I<Name>
+
+When given, collect detailed information about the given zone in the view. The
+information collected if very similar to the global B<ServerStats> information
+(see above).
+
+You can repeat this option to collect detailed information about multiple
+zones.
+
+By default no detailed zone information is collected.
+
+=back
+
+=back
+
+=head2 Plugin C<ceph>
+
+The ceph plugin collects values from JSON data to be parsed by B<libyajl>
+(L<https://lloyd.github.io/yajl/>) retrieved from ceph daemon admin sockets.
+
+A separate B<Daemon> block must be configured for each ceph daemon to be
+monitored. The following example will read daemon statistics from four
+separate ceph daemons running on the same device (two OSDs, one MON, one MDS) :
+
+  <Plugin ceph>
+    LongRunAvgLatency false
+    ConvertSpecialMetricTypes true
+    <Daemon "osd.0">
+      SocketPath "/var/run/ceph/ceph-osd.0.asok"
+    </Daemon>
+    <Daemon "osd.1">
+      SocketPath "/var/run/ceph/ceph-osd.1.asok"
+    </Daemon>
+    <Daemon "mon.a">
+      SocketPath "/var/run/ceph/ceph-mon.ceph1.asok"
+    </Daemon>
+    <Daemon "mds.a">
+      SocketPath "/var/run/ceph/ceph-mds.ceph1.asok"
+    </Daemon>
+  </Plugin>
+
+The ceph plugin accepts the following configuration options:
+
+=over 4
+
+=item B<LongRunAvgLatency> B<true>|B<false>
+
+If enabled, latency values(sum,count pairs) are calculated as the long run
+average - average since the ceph daemon was started = (sum / count).
+When disabled, latency values are calculated as the average since the last
+collection = (sum_now - sum_last) / (count_now - count_last).
+
+Default: Disabled
+
+=item B<ConvertSpecialMetricTypes> B<true>|B<false>
+
+If enabled, special metrics (metrics that differ in type from similar counters)
+are converted to the type of those similar counters. This currently only
+applies to filestore.journal_wr_bytes which is a counter for OSD daemons. The
+ceph schema reports this metric type as a sum,count pair while similar counters
+are treated as derive types. When converted, the sum is used as the counter
+value and is treated as a derive type.
+When disabled, all metrics are treated as the types received from the ceph schema.
+
+Default: Enabled
+
+=back
+
+Each B<Daemon> block must have a string argument for the plugin instance name.
+A B<SocketPath> is also required for each B<Daemon> block:
+
+=over 4
+
+=item B<Daemon> I<DaemonName>
+
+Name to be used as the instance name for this daemon.
+
+=item B<SocketPath> I<SocketPath>
+
+Specifies the path to the UNIX admin socket of the ceph daemon.
+
+=back
+
+=head2 Plugin C<cgroups>
+
+This plugin collects the CPU user/system time for each I<cgroup> by reading the
+F<cpuacct.stat> files in the first cpuacct-mountpoint (typically
+F</sys/fs/cgroup/cpu.cpuacct> on machines using systemd).
+
+=over 4
+
+=item B<CGroup> I<Directory>
+
+Select I<cgroup> based on the name. Whether only matching I<cgroups> are
+collected or if they are ignored is controlled by the B<IgnoreSelected> option;
+see below.
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Invert the selection: If set to true, all cgroups I<except> the ones that
+match any one of the criteria are collected. By default only selected
+cgroups are collected if a selection is made. If no selection is configured
+at all, B<all> cgroups are selected.
+
+=back
+
+=head2 Plugin C<conntrack>
+
+This plugin collects IP conntrack statistics.
+
+=over 4
+
+=item B<OldFiles>
+
+Assume the B<conntrack_count> and B<conntrack_max> files to be found in
+F</proc/sys/net/ipv4/netfilter> instead of F</proc/sys/net/netfilter/>.
+
+=back
+
+=head2 Plugin C<cpu>
+
+The I<CPU plugin> collects CPU usage metrics. By default, CPU usage is reported
+as Jiffies, using the C<cpu> type. Two aggregations are available:
+
+=over 4
+
+=item
+
+Sum, per-state, over all CPUs installed in the system; and
+
+=item
+
+Sum, per-CPU, over all non-idle states of a CPU, creating an "active" state.
+
+=back
+
+The two aggregations can be combined, leading to I<collectd> only emitting a
+single "active" metric for the entire system. As soon as one of these
+aggregations (or both) is enabled, the I<cpu plugin> will report a percentage,
+rather than Jiffies. In addition, you can request individual, per-state,
+per-CPU metrics to be reported as percentage.
+
+The following configuration options are available:
+
+=over 4
+
+=item B<ReportByState> B<true>|B<false>
+
+When set to B<true>, the default, reports per-state metrics, e.g. "system",
+"user" and "idle".
+When set to B<false>, aggregates (sums) all I<non-idle> states into one
+"active" metric.
+
+=item B<ReportByCpu> B<true>|B<false>
+
+When set to B<true>, the default, reports per-CPU (per-core) metrics.
+When set to B<false>, instead of reporting metrics for individual CPUs, only a
+global sum of CPU states is emitted.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+This option is only considered when both, B<ReportByCpu> and B<ReportByState>
+are set to B<true>. In this case, by default, metrics will be reported as
+Jiffies. By setting this option to B<true>, you can request percentage values
+in the un-aggregated (per-CPU, per-state) mode as well.
+
+=back
+
+=head2 Plugin C<cpufreq>
+
+This plugin doesn't have any options. It reads
+F</sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq> (for the first CPU
+installed) to get the current CPU frequency. If this file does not exist make
+sure B<cpufreqd> (L<http://cpufreqd.sourceforge.net/>) or a similar tool is
+installed and an "cpu governor" (that's a kernel module) is loaded.
+
+=head2 Plugin C<csv>
+
+=over 4
+
+=item B<DataDir> I<Directory>
+
+Set the directory to store CSV-files under. Per default CSV-files are generated
+beneath the daemon's working directory, i.E<nbsp>e. the B<BaseDir>.
+The special strings B<stdout> and B<stderr> can be used to write to the standard
+output and standard error channels, respectively. This, of course, only makes
+much sense when collectd is running in foreground- or non-daemon-mode.
+
+=item B<StoreRates> B<true|false>
+
+If set to B<true>, convert counter values to rates. If set to B<false> (the
+default) counter values are stored as is, i.E<nbsp>e. as an increasing integer
+number.
+
+=back
+
+=head2 Plugin C<curl>
+
+The curl plugin uses the B<libcurl> (L<http://curl.haxx.se/>) to read web pages
+and the match infrastructure (the same code used by the tail plugin) to use
+regular expressions with the received data.
+
+The following example will read the current value of AMD stock from Google's
+finance page and dispatch the value to collectd.
+
+  <Plugin curl>
+    <Page "stock_quotes">
+      URL "http://finance.google.com/finance?q=NYSE%3AAMD"
+      User "foo"
+      Password "bar"
+      Digest false
+      VerifyPeer true
+      VerifyHost true
+      CACert "/path/to/ca.crt"
+      Header "X-Custom-Header: foobar"
+      Post "foo=bar"
+
+      MeasureResponseTime false
+      MeasureResponseCode false
+
+      <Match>
+        Regex "<span +class=\"pr\"[^>]*> *([0-9]*\\.[0-9]+) *</span>"
+        DSType "GaugeAverage"
+        # Note: `stock_value' is not a standard type.
+        Type "stock_value"
+        Instance "AMD"
+      </Match>
+    </Page>
+  </Plugin>
+
+In the B<Plugin> block, there may be one or more B<Page> blocks, each defining
+a web page and one or more "matches" to be performed on the returned data. The
+string argument to the B<Page> block is used as plugin instance.
+
+The following options are valid within B<Page> blocks:
+
+=over 4
+
+=item B<URL> I<URL>
+
+URL of the web site to retrieve. Since a regular expression will be used to
+extract information from this data, non-binary data is a big plus here ;)
+
+=item B<User> I<Name>
+
+Username to use if authorization is required to read the page.
+
+=item B<Password> I<Password>
+
+Password to use if authorization is required to read the page.
+
+=item B<Digest> B<true>|B<false>
+
+Enable HTTP digest authentication.
+
+=item B<VerifyPeer> B<true>|B<false>
+
+Enable or disable peer SSL certificate verification. See
+L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+
+=item B<VerifyHost> B<true>|B<false>
+
+Enable or disable peer host name verification. If enabled, the plugin checks if
+the C<Common Name> or a C<Subject Alternate Name> field of the SSL certificate
+matches the host name provided by the B<URL> option. If this identity check
+fails, the connection is aborted. Obviously, only works when connecting to a
+SSL enabled server. Enabled by default.
+
+=item B<CACert> I<file>
+
+File that holds one or more SSL certificates. If you want to use HTTPS you will
+possibly need this option. What CA certificates come bundled with C<libcurl>
+and are checked by default depends on the distribution you use.
+
+=item B<Header> I<Header>
+
+A HTTP header to add to the request. Multiple headers are added if this option
+is specified more than once.
+
+=item B<Post> I<Body>
+
+Specifies that the HTTP operation should be a POST instead of a GET. The
+complete data to be posted is given as the argument.  This option will usually
+need to be accompanied by a B<Header> option to set an appropriate
+C<Content-Type> for the post body (e.g. to
+C<application/x-www-form-urlencoded>).
+
+=item B<MeasureResponseTime> B<true>|B<false>
+
+Measure response time for the request. If this setting is enabled, B<Match>
+blocks (see below) are optional. Disabled by default.
+
+Beware that requests will get aborted if they take too long to complete. Adjust
+B<Timeout> accordingly if you expect B<MeasureResponseTime> to report such slow
+requests.
+
+=item B<MeasureResponseCode> B<true>|B<false>
+
+Measure response code for the request. If this setting is enabled, B<Match>
+blocks (see below) are optional. Disabled by default.
+
+=item B<E<lt>MatchE<gt>>
+
+One or more B<Match> blocks that define how to match information in the data
+returned by C<libcurl>. The C<curl> plugin uses the same infrastructure that's
+used by the C<tail> plugin, so please see the documentation of the C<tail>
+plugin below on how matches are defined. If the B<MeasureResponseTime> or
+B<MeasureResponseCode> options are set to B<true>, B<Match> blocks are
+optional.
+
+=item B<Timeout> I<Milliseconds>
+
+The B<Timeout> option sets the overall timeout for HTTP requests to B<URL>, in
+milliseconds. By default, the configured B<Interval> is used to set the
+timeout. Prior to version 5.5.0, there was no timeout and requests could hang
+indefinitely. This legacy behaviour can be achieved by setting the value of
+B<Timeout> to 0.
+
+If B<Timeout> is 0 or bigger than the B<Interval>, keep in mind that each slow
+network connection will stall one read thread. Adjust the B<ReadThreads> global
+setting accordingly to prevent this from blocking other plugins.
+
+=back
+
+=head2 Plugin C<curl_json>
+
+The B<curl_json plugin> collects values from JSON data to be parsed by
+B<libyajl> (L<http://www.lloydforge.org/projects/yajl/>) retrieved via
+either B<libcurl> (L<http://curl.haxx.se/>) or read directly from a
+unix socket. The former can be used, for example, to collect values
+from CouchDB documents (which are stored JSON notation), and the
+latter to collect values from a uWSGI stats socket.
+
+The following example will collect several values from the built-in
+C<_stats> runtime statistics module of I<CouchDB>
+(L<http://wiki.apache.org/couchdb/Runtime_Statistics>).
+
+  <Plugin curl_json>
+    <URL "http://localhost:5984/_stats">
+      Instance "httpd"
+      <Key "httpd/requests/count">
+        Type "http_requests"
+      </Key>
+
+      <Key "httpd_request_methods/*/count">
+        Type "http_request_methods"
+      </Key>
+
+      <Key "httpd_status_codes/*/count">
+        Type "http_response_codes"
+      </Key>
+    </URL>
+  </Plugin>
+
+This example will collect data directly from a I<uWSGI> "Stats Server" socket.
+
+  <Plugin curl_json>
+    <Sock "/var/run/uwsgi.stats.sock">
+      Instance "uwsgi"
+      <Key "workers/*/requests">
+        Type "http_requests"
+      </Key>
+
+      <Key "workers/*/apps/*/requests">
+        Type "http_requests"
+      </Key>
+    </Sock>
+  </Plugin>
+
+In the B<Plugin> block, there may be one or more B<URL> blocks, each
+defining a URL to be fetched via HTTP (using libcurl) or B<Sock>
+blocks defining a unix socket to read JSON from directly.  Each of
+these blocks may have one or more B<Key> blocks.
+
+The B<Key> string argument must be in a path format. Each component is
+used to match the key from a JSON map or the index of an JSON
+array. If a path component of a B<Key> is a I<*>E<nbsp>wildcard, the
+values for all map keys or array indices will be collectd.
+
+The following options are valid within B<URL> blocks:
+
+=over 4
+
+=item B<Instance> I<Instance>
+
+Sets the plugin instance to I<Instance>.
+
+=item B<Interval> I<Interval>
+
+Sets the interval (in seconds) in which the values will be collected from this
+URL. By default the global B<Interval> setting will be used.
+
+=item B<User> I<Name>
+
+=item B<Password> I<Password>
+
+=item B<Digest> B<true>|B<false>
+
+=item B<VerifyPeer> B<true>|B<false>
+
+=item B<VerifyHost> B<true>|B<false>
+
+=item B<CACert> I<file>
+
+=item B<Header> I<Header>
+
+=item B<Post> I<Body>
+
+=item B<Timeout> I<Milliseconds>
+
+These options behave exactly equivalent to the appropriate options of the
+I<cURL> plugin. Please see there for a detailed description.
+
+=back
+
+The following options are valid within B<Key> blocks:
+
+=over 4
+
+=item B<Type> I<Type>
+
+Sets the type used to dispatch the values to the daemon. Detailed information
+about types and their configuration can be found in L<types.db(5)>. This
+option is mandatory.
+
+=item B<Instance> I<Instance>
+
+Type-instance to use. Defaults to the current map key or current string array element value.
+
+=back
+
+=head2 Plugin C<curl_xml>
+
+The B<curl_xml plugin> uses B<libcurl> (L<http://curl.haxx.se/>) and B<libxml2>
+(L<http://xmlsoft.org/>) to retrieve XML data via cURL.
+
+ <Plugin "curl_xml">
+   <URL "http://localhost/stats.xml">
+     Host "my_host"
+     Instance "some_instance"
+     User "collectd"
+     Password "thaiNg0I"
+     VerifyPeer true
+     VerifyHost true
+     CACert "/path/to/ca.crt"
+     Header "X-Custom-Header: foobar"
+     Post "foo=bar"
+
+     <XPath "table[@id=\"magic_level\"]/tr">
+       Type "magic_level"
+       #InstancePrefix "prefix-"
+       InstanceFrom "td[1]"
+       ValuesFrom "td[2]/span[@class=\"level\"]"
+     </XPath>
+   </URL>
+ </Plugin>
+
+In the B<Plugin> block, there may be one or more B<URL> blocks, each defining a
+URL to be fetched using libcurl. Within each B<URL> block there are
+options which specify the connection parameters, for example authentication
+information, and one or more B<XPath> blocks.
+
+Each B<XPath> block specifies how to get one type of information. The
+string argument must be a valid XPath expression which returns a list
+of "base elements". One value is dispatched for each "base element". The
+I<type instance> and values are looked up using further I<XPath> expressions
+that should be relative to the base element.
+
+Within the B<URL> block the following options are accepted:
+
+=over 4
+
+=item B<Host> I<Name>
+
+Use I<Name> as the host name when submitting values. Defaults to the global
+host name setting.
+
+=item B<Instance> I<Instance>
+
+Use I<Instance> as the plugin instance when submitting values. Defaults to an
+empty string (no plugin instance).
+
+=item B<Namespace> I<Prefix> I<URL>
+
+If an XPath expression references namespaces, they must be specified
+with this option. I<Prefix> is the "namespace prefix" used in the XML document.
+I<URL> is the "namespace name", an URI reference uniquely identifying the
+namespace. The option can be repeated to register multiple namespaces.
+
+Examples:
+
+  Namespace "s" "http://schemas.xmlsoap.org/soap/envelope/"
+  Namespace "m" "http://www.w3.org/1998/Math/MathML"
+
+=item B<User> I<User>
+
+=item B<Password> I<Password>
+
+=item B<Digest> B<true>|B<false>
+
+=item B<VerifyPeer> B<true>|B<false>
+
+=item B<VerifyHost> B<true>|B<false>
+
+=item B<CACert> I<CA Cert File>
+
+=item B<Header> I<Header>
+
+=item B<Post> I<Body>
+
+=item B<Timeout> I<Milliseconds>
+
+These options behave exactly equivalent to the appropriate options of the
+I<cURL plugin>. Please see there for a detailed description.
+
+=item E<lt>B<XPath> I<XPath-expression>E<gt>
+
+Within each B<URL> block, there must be one or more B<XPath> blocks. Each
+B<XPath> block specifies how to get one type of information. The string
+argument must be a valid XPath expression which returns a list of "base
+elements". One value is dispatched for each "base element".
+
+Within the B<XPath> block the following options are accepted:
+
+=over 4
+
+=item B<Type> I<Type>
+
+Specifies the I<Type> used for submitting patches. This determines the number
+of values that are required / expected and whether the strings are parsed as
+signed or unsigned integer or as double values. See L<types.db(5)> for details.
+This option is required.
+
+=item B<InstancePrefix> I<InstancePrefix>
+
+Prefix the I<type instance> with I<InstancePrefix>. The values are simply
+concatenated together without any separator.
+This option is optional.
+
+=item B<InstanceFrom> I<InstanceFrom>
+
+Specifies a XPath expression to use for determining the I<type instance>. The
+XPath expression must return exactly one element. The element's value is then
+used as I<type instance>, possibly prefixed with I<InstancePrefix> (see above).
+
+This value is required. As a special exception, if the "base XPath expression"
+(the argument to the B<XPath> block) returns exactly one argument, then this
+option may be omitted.
+
+=item B<ValuesFrom> I<ValuesFrom> [I<ValuesFrom> ...]
+
+Specifies one or more XPath expression to use for reading the values. The
+number of XPath expressions must match the number of data sources in the
+I<type> specified with B<Type> (see above). Each XPath expression must return
+exactly one element. The element's value is then parsed as a number and used as
+value for the appropriate value in the value list dispatched to the daemon.
+
+=back
+
+=back
+
+=head2 Plugin C<dbi>
+
+This plugin uses the B<dbi> library (L<http://libdbi.sourceforge.net/>) to
+connect to various databases, execute I<SQL> statements and read back the
+results. I<dbi> is an acronym for "database interface" in case you were
+wondering about the name. You can configure how each column is to be
+interpreted and the plugin will generate one or more data sets from each row
+returned according to these rules.
+
+Because the plugin is very generic, the configuration is a little more complex
+than those of other plugins. It usually looks something like this:
+
+  <Plugin dbi>
+    <Query "out_of_stock">
+      Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category"
+      # Use with MySQL 5.0.0 or later
+      MinVersion 50000
+      <Result>
+        Type "gauge"
+        InstancePrefix "out_of_stock"
+        InstancesFrom "category"
+        ValuesFrom "value"
+      </Result>
+    </Query>
+    <Database "product_information">
+      Driver "mysql"
+      DriverOption "host" "localhost"
+      DriverOption "username" "collectd"
+      DriverOption "password" "aZo6daiw"
+      DriverOption "dbname" "prod_info"
+      SelectDB "prod_info"
+      Query "out_of_stock"
+    </Database>
+  </Plugin>
+
+The configuration above defines one query with one result and one database. The
+query is then linked to the database with the B<Query> option I<within> the
+B<E<lt>DatabaseE<gt>> block. You can have any number of queries and databases
+and you can also use the B<Include> statement to split up the configuration
+file in multiple, smaller files. However, the B<E<lt>QueryE<gt>> block I<must>
+precede the B<E<lt>DatabaseE<gt>> blocks, because the file is interpreted from
+top to bottom!
+
+The following is a complete list of options:
+
+=head3 B<Query> blocks
+
+Query blocks define I<SQL> statements and how the returned data should be
+interpreted. They are identified by the name that is given in the opening line
+of the block. Thus the name needs to be unique. Other than that, the name is
+not used in collectd.
+
+In each B<Query> block, there is one or more B<Result> blocks. B<Result> blocks
+define which column holds which value or instance information. You can use
+multiple B<Result> blocks to create multiple values from one returned row. This
+is especially useful, when queries take a long time and sending almost the same
+query again and again is not desirable.
+
+Example:
+
+  <Query "environment">
+    Statement "select station, temperature, humidity from environment"
+    <Result>
+      Type "temperature"
+      # InstancePrefix "foo"
+      InstancesFrom "station"
+      ValuesFrom "temperature"
+    </Result>
+    <Result>
+      Type "humidity"
+      InstancesFrom "station"
+      ValuesFrom "humidity"
+    </Result>
+  </Query>
+
+The following options are accepted:
+
+=over 4
+
+=item B<Statement> I<SQL>
+
+Sets the statement that should be executed on the server. This is B<not>
+interpreted by collectd, but simply passed to the database server. Therefore,
+the SQL dialect that's used depends on the server collectd is connected to.
+
+The query has to return at least two columns, one for the instance and one
+value. You cannot omit the instance, even if the statement is guaranteed to
+always return exactly one line. In that case, you can usually specify something
+like this:
+
+  Statement "SELECT \"instance\", COUNT(*) AS value FROM table"
+
+(That works with MySQL but may not be valid SQL according to the spec. If you
+use a more strict database server, you may have to select from a dummy table or
+something.)
+
+Please note that some databases, for example B<Oracle>, will fail if you
+include a semicolon at the end of the statement.
+
+=item B<MinVersion> I<Version>
+
+=item B<MaxVersion> I<Value>
+
+Only use this query for the specified database version. You can use these
+options to provide multiple queries with the same name but with a slightly
+different syntax. The plugin will use only those queries, where the specified
+minimum and maximum versions fit the version of the database in use.
+
+The database version is determined by C<dbi_conn_get_engine_version>, see the
+L<libdbi documentation|http://libdbi.sourceforge.net/docs/programmers-guide/reference-conn.html#DBI-CONN-GET-ENGINE-VERSION>
+for details. Basically, each part of the version is assumed to be in the range
+from B<00> to B<99> and all dots are removed. So version "4.1.2" becomes
+"40102", version "5.0.42" becomes "50042".
+
+B<Warning:> The plugin will use B<all> matching queries, so if you specify
+multiple queries with the same name and B<overlapping> ranges, weird stuff will
+happen. Don't to it! A valid example would be something along these lines:
+
+  MinVersion 40000
+  MaxVersion 49999
+  ...
+  MinVersion 50000
+  MaxVersion 50099
+  ...
+  MinVersion 50100
+  # No maximum
+
+In the above example, there are three ranges that don't overlap. The last one
+goes from version "5.1.0" to infinity, meaning "all later versions". Versions
+before "4.0.0" are not specified.
+
+=item B<Type> I<Type>
+
+The B<type> that's used for each line returned. See L<types.db(5)> for more
+details on how types are defined. In short: A type is a predefined layout of
+data and the number of values and type of values has to match the type
+definition.
+
+If you specify "temperature" here, you need exactly one gauge column. If you
+specify "if_octets", you will need two counter columns. See the B<ValuesFrom>
+setting below.
+
+There must be exactly one B<Type> option inside each B<Result> block.
+
+=item B<InstancePrefix> I<prefix>
+
+Prepends I<prefix> to the type instance. If B<InstancesFrom> (see below) is not
+given, the string is simply copied. If B<InstancesFrom> is given, I<prefix> and
+all strings returned in the appropriate columns are concatenated together,
+separated by dashes I<("-")>.
+
+=item B<InstancesFrom> I<column0> [I<column1> ...]
+
+Specifies the columns whose values will be used to create the "type-instance"
+for each row. If you specify more than one column, the value of all columns
+will be joined together with dashes I<("-")> as separation characters.
+
+The plugin itself does not check whether or not all built instances are
+different. It's your responsibility to assure that each is unique. This is
+especially true, if you do not specify B<InstancesFrom>: B<You> have to make
+sure that only one row is returned in this case.
+
+If neither B<InstancePrefix> nor B<InstancesFrom> is given, the type-instance
+will be empty.
+
+=item B<ValuesFrom> I<column0> [I<column1> ...]
+
+Names the columns whose content is used as the actual data for the data sets
+that are dispatched to the daemon. How many such columns you need is determined
+by the B<Type> setting above. If you specify too many or not enough columns,
+the plugin will complain about that and no data will be submitted to the
+daemon.
+
+The actual data type in the columns is not that important. The plugin will
+automatically cast the values to the right type if it know how to do that. So
+it should be able to handle integer an floating point types, as well as strings
+(if they include a number at the beginning).
+
+There must be at least one B<ValuesFrom> option inside each B<Result> block.
+
+=item B<MetadataFrom> [I<column0> I<column1> ...]
+
+Names the columns whose content is used as metadata for the data sets
+that are dispatched to the daemon.
+
+The actual data type in the columns is not that important. The plugin will
+automatically cast the values to the right type if it know how to do that. So
+it should be able to handle integer an floating point types, as well as strings
+(if they include a number at the beginning).
+
+=back
+
+=head3 B<Database> blocks
+
+Database blocks define a connection to a database and which queries should be
+sent to that database. Since the used "dbi" library can handle a wide variety
+of databases, the configuration is very generic. If in doubt, refer to libdbi's
+documentationE<nbsp>- we stick as close to the terminology used there.
+
+Each database needs a "name" as string argument in the starting tag of the
+block. This name will be used as "PluginInstance" in the values submitted to
+the daemon. Other than that, that name is not used.
+
+=over 4
+
+=item B<Driver> I<Driver>
+
+Specifies the driver to use to connect to the database. In many cases those
+drivers are named after the database they can connect to, but this is not a
+technical necessity. These drivers are sometimes referred to as "DBD",
+B<D>ataB<B>ase B<D>river, and some distributions ship them in separate
+packages. Drivers for the "dbi" library are developed by the B<libdbi-drivers>
+project at L<http://libdbi-drivers.sourceforge.net/>.
+
+You need to give the driver name as expected by the "dbi" library here. You
+should be able to find that in the documentation for each driver. If you
+mistype the driver name, the plugin will dump a list of all known driver names
+to the log.
+
+=item B<DriverOption> I<Key> I<Value>
+
+Sets driver-specific options. What option a driver supports can be found in the
+documentation for each driver, somewhere at
+L<http://libdbi-drivers.sourceforge.net/>. However, the options "host",
+"username", "password", and "dbname" seem to be deE<nbsp>facto standards.
+
+DBDs can register two types of options: String options and numeric options. The
+plugin will use the C<dbi_conn_set_option> function when the configuration
+provides a string and the C<dbi_conn_require_option_numeric> function when the
+configuration provides a number. So these two lines will actually result in
+different calls being used:
+
+  DriverOption "Port" 1234      # numeric
+  DriverOption "Port" "1234"    # string
+
+Unfortunately, drivers are not too keen to report errors when an unknown option
+is passed to them, so invalid settings here may go unnoticed. This is not the
+plugin's fault, it will report errors if it gets them from the libraryE<nbsp>/
+the driver. If a driver complains about an option, the plugin will dump a
+complete list of all options understood by that driver to the log. There is no
+way to programatically find out if an option expects a string or a numeric
+argument, so you will have to refer to the appropriate DBD's documentation to
+find this out. Sorry.
+
+=item B<SelectDB> I<Database>
+
+In some cases, the database name you connect with is not the database name you
+want to use for querying data. If this option is set, the plugin will "select"
+(switch to) that database after the connection is established.
+
+=item B<Query> I<QueryName>
+
+Associates the query named I<QueryName> with this database connection. The
+query needs to be defined I<before> this statement, i.E<nbsp>e. all query
+blocks you want to refer to must be placed above the database block you want to
+refer to them from.
+
+=item B<Host> I<Hostname>
+
+Sets the B<host> field of I<value lists> to I<Hostname> when dispatching
+values. Defaults to the global hostname setting.
+
+=back
+
+=head2 Plugin C<df>
+
+=over 4
+
+=item B<Device> I<Device>
+
+Select partitions based on the devicename.
+
+=item B<MountPoint> I<Directory>
+
+Select partitions based on the mountpoint.
+
+=item B<FSType> I<FSType>
+
+Select partitions based on the filesystem type.
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Invert the selection: If set to true, all partitions B<except> the ones that
+match any one of the criteria are collected. By default only selected
+partitions are collected if a selection is made. If no selection is configured
+at all, B<all> partitions are selected.
+
+=item B<ReportByDevice> B<true>|B<false>
+
+Report using the device name rather than the mountpoint. i.e. with this I<false>,
+(the default), it will report a disk as "root", but with it I<true>, it will be
+"sda1" (or whichever).
+
+=item B<ReportInodes> B<true>|B<false>
+
+Enables or disables reporting of free, reserved and used inodes. Defaults to
+inode collection being disabled.
+
+Enable this option if inodes are a scarce resource for you, usually because
+many small files are stored on the disk. This is a usual scenario for mail
+transfer agents and web caches.
+
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of free and used disk space in 1K-blocks.
+Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of free and used disk space in percentage.
+Defaults to B<false>.
+
+This is useful for deploying I<collectd> on the cloud, where machines with
+different disk size may exist. Then it is more practical to configure
+thresholds based on relative disk size.
+
+=back
+
+=head2 Plugin C<disk>
+
+The C<disk> plugin collects information about the usage of physical disks and
+logical disks (partitions). Values collected are the number of octets written
+to and read from a disk or partition, the number of read/write operations
+issued to the disk and a rather complex "time" it took for these commands to be
+issued.
+
+Using the following two options you can ignore some disks or configure the
+collection only of specific disks.
+
+=over 4
+
+=item B<Disk> I<Name>
+
+Select the disk I<Name>. Whether it is collected or ignored depends on the
+B<IgnoreSelected> setting, see below. As with other plugins that use the
+daemon's ignorelist functionality, a string that starts and ends with a slash
+is interpreted as a regular expression. Examples:
+
+  Disk "sdd"
+  Disk "/hda[34]/"
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Sets whether selected disks, i.E<nbsp>e. the ones matches by any of the B<Disk>
+statements, are ignored or if all other disks are ignored. The behavior
+(hopefully) is intuitive: If no B<Disk> option is configured, all disks are
+collected. If at least one B<Disk> option is given and no B<IgnoreSelected> or
+set to B<false>, B<only> matching disks will be collected. If B<IgnoreSelected>
+is set to B<true>, all disks are collected B<except> the ones matched.
+
+=item B<UseBSDName> B<true>|B<false>
+
+Whether to use the device's "BSD Name", on MacE<nbsp>OSE<nbsp>X, instead of the
+default major/minor numbers. Requires collectd to be built with Apple's
+IOKitLib support.
+
+=item B<UdevNameAttr> I<Attribute>
+
+Attempt to override disk instance name with the value of a specified udev
+attribute when built with B<libudev>.  If the attribute is not defined for the
+given device, the default name is used. Example:
+
+  UdevNameAttr "DM_NAME"
+
+=back
+
+=head2 Plugin C<dns>
+
+=over 4
+
+=item B<Interface> I<Interface>
+
+The dns plugin uses B<libpcap> to capture dns traffic and analyzes it. This
+option sets the interface that should be used. If this option is not set, or
+set to "any", the plugin will try to get packets from B<all> interfaces. This
+may not work on certain platforms, such as MacE<nbsp>OSE<nbsp>X.
+
+=item B<IgnoreSource> I<IP-address>
+
+Ignore packets that originate from this address.
+
+=item B<SelectNumericQueryTypes> B<true>|B<false>
+
+Enabled by default, collects unknown (and thus presented as numeric only) query types.
+
+=back
+
+=head2 Plugin C<email>
+
+=over 4
+
+=item B<SocketFile> I<Path>
+
+Sets the socket-file which is to be created.
+
+=item B<SocketGroup> I<Group>
+
+If running as root change the group of the UNIX-socket after it has been
+created. Defaults to B<collectd>.
+
+=item B<SocketPerms> I<Permissions>
+
+Change the file permissions of the UNIX-socket after it has been created. The
+permissions must be given as a numeric, octal value as you would pass to
+L<chmod(1)>. Defaults to B<0770>.
+
+=item B<MaxConns> I<Number>
+
+Sets the maximum number of connections that can be handled in parallel. Since
+this many threads will be started immediately setting this to a very high
+value will waste valuable resources. Defaults to B<5> and will be forced to be
+at most B<16384> to prevent typos and dumb mistakes.
+
+=back
+
+=head2 Plugin C<ethstat>
+
+The I<ethstat plugin> collects information about network interface cards (NICs)
+by talking directly with the underlying kernel driver using L<ioctl(2)>.
+
+B<Synopsis:>
+
+ <Plugin "ethstat">
+   Interface "eth0"
+   Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
+   Map "multicast" "if_multicast"
+ </Plugin>
+
+B<Options:>
+
+=over 4
+
+=item B<Interface> I<Name>
+
+Collect statistical information about interface I<Name>.
+
+=item B<Map> I<Name> I<Type> [I<TypeInstance>]
+
+By default, the plugin will submit values as type C<derive> and I<type
+instance> set to I<Name>, the name of the metric as reported by the driver. If
+an appropriate B<Map> option exists, the given I<Type> and, optionally,
+I<TypeInstance> will be used.
+
+=item B<MappedOnly> B<true>|B<false>
+
+When set to B<true>, only metrics that can be mapped to to a I<type> will be
+collected, all other metrics will be ignored. Defaults to B<false>.
+
+=back
+
+=head2 Plugin C<exec>
+
+Please make sure to read L<collectd-exec(5)> before using this plugin. It
+contains valuable information on when the executable is executed and the
+output that is expected from it.
+
+=over 4
+
+=item B<Exec> I<User>[:[I<Group>]] I<Executable> [I<E<lt>argE<gt>> [I<E<lt>argE<gt>> ...]]
+
+=item B<NotificationExec> I<User>[:[I<Group>]] I<Executable> [I<E<lt>argE<gt>> [I<E<lt>argE<gt>> ...]]
+
+Execute the executable I<Executable> as user I<User>. If the user name is
+followed by a colon and a group name, the effective group is set to that group.
+The real group and saved-set group will be set to the default group of that
+user. If no group is given the effective group ID will be the same as the real
+group ID.
+
+Please note that in order to change the user and/or group the daemon needs
+superuser privileges. If the daemon is run as an unprivileged user you must
+specify the same user/group here. If the daemon is run with superuser
+privileges, you must supply a non-root user here.
+
+The executable may be followed by optional arguments that are passed to the
+program. Please note that due to the configuration parsing numbers and boolean
+values may be changed. If you want to be absolutely sure that something is
+passed as-is please enclose it in quotes.
+
+The B<Exec> and B<NotificationExec> statements change the semantics of the
+programs executed, i.E<nbsp>e. the data passed to them and the response
+expected from them. This is documented in great detail in L<collectd-exec(5)>.
+
+=back
+
+=head2 Plugin C<fhcount>
+
+The C<fhcount> plugin provides statistics about used, unused and total number of
+file handles.
+
+The I<fhcount plugin> provides the following configuration options:
+
+=over 4
+
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of file handles usage in absolute numbers,
+e.g. file handles used. Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of file handles usage in percentages, e.g.
+percent of file handles used. Defaults to B<false>.
+
+=back
+
+=head2 Plugin C<filecount>
+
+The C<filecount> plugin counts the number of files in a certain directory (and
+its subdirectories) and their combined size. The configuration is very straight
+forward:
+
+  <Plugin "filecount">
+    <Directory "/var/qmail/queue/mess">
+      Instance "qmail-message"
+    </Directory>
+    <Directory "/var/qmail/queue/todo">
+      Instance "qmail-todo"
+    </Directory>
+    <Directory "/var/lib/php5">
+      Instance "php5-sessions"
+      Name "sess_*"
+    </Directory>
+  </Plugin>
+
+The example above counts the number of files in QMail's queue directories and
+the number of PHP5 sessions. Jfiy: The "todo" queue holds the messages that
+QMail has not yet looked at, the "message" queue holds the messages that were
+classified into "local" and "remote".
+
+As you can see, the configuration consists of one or more C<Directory> blocks,
+each of which specifies a directory in which to count the files. Within those
+blocks, the following options are recognized:
+
+=over 4
+
+=item B<Instance> I<Instance>
+
+Sets the plugin instance to I<Instance>. That instance name must be unique, but
+it's your responsibility, the plugin doesn't check for that. If not given, the
+instance is set to the directory name with all slashes replaced by underscores
+and all leading underscores removed.
+
+=item B<Name> I<Pattern>
+
+Only count files that match I<Pattern>, where I<Pattern> is a shell-like
+wildcard as understood by L<fnmatch(3)>. Only the B<filename> is checked
+against the pattern, not the entire path. In case this makes it easier for you:
+This option has been named after the B<-name> parameter to L<find(1)>.
+
+=item B<MTime> I<Age>
+
+Count only files of a specific age: If I<Age> is greater than zero, only files
+that haven't been touched in the last I<Age> seconds are counted. If I<Age> is
+a negative number, this is inversed. For example, if B<-60> is specified, only
+files that have been modified in the last minute will be counted.
+
+The number can also be followed by a "multiplier" to easily specify a larger
+timespan. When given in this notation, the argument must in quoted, i.E<nbsp>e.
+must be passed as string. So the B<-60> could also be written as B<"-1m"> (one
+minute). Valid multipliers are C<s> (second), C<m> (minute), C<h> (hour), C<d>
+(day), C<w> (week), and C<y> (year). There is no "month" multiplier. You can
+also specify fractional numbers, e.E<nbsp>g. B<"0.5d"> is identical to
+B<"12h">.
+
+=item B<Size> I<Size>
+
+Count only files of a specific size. When I<Size> is a positive number, only
+files that are at least this big are counted. If I<Size> is a negative number,
+this is inversed, i.E<nbsp>e. only files smaller than the absolute value of
+I<Size> are counted.
+
+As with the B<MTime> option, a "multiplier" may be added. For a detailed
+description see above. Valid multipliers here are C<b> (byte), C<k> (kilobyte),
+C<m> (megabyte), C<g> (gigabyte), C<t> (terabyte), and C<p> (petabyte). Please
+note that there are 1000 bytes in a kilobyte, not 1024.
+
+=item B<Recursive> I<true>|I<false>
+
+Controls whether or not to recurse into subdirectories. Enabled by default.
+
+=item B<IncludeHidden> I<true>|I<false>
+
+Controls whether or not to include "hidden" files and directories in the count.
+"Hidden" files and directories are those, whose name begins with a dot.
+Defaults to I<false>, i.e. by default hidden files and directories are ignored.
+
+=back
+
+=head2 Plugin C<GenericJMX>
+
+The I<GenericJMX plugin> is written in I<Java> and therefore documented in
+L<collectd-java(5)>.
+
+=head2 Plugin C<gmond>
+
+The I<gmond> plugin received the multicast traffic sent by B<gmond>, the
+statistics collection daemon of Ganglia. Mappings for the standard "metrics"
+are built-in, custom mappings may be added via B<Metric> blocks, see below.
+
+Synopsis:
+
+ <Plugin "gmond">
+   MCReceiveFrom "239.2.11.71" "8649"
+   <Metric "swap_total">
+     Type "swap"
+     TypeInstance "total"
+     DataSource "value"
+   </Metric>
+   <Metric "swap_free">
+     Type "swap"
+     TypeInstance "free"
+     DataSource "value"
+   </Metric>
+ </Plugin>
+
+The following metrics are built-in:
+
+=over 4
+
+=item *
+
+load_one, load_five, load_fifteen
+
+=item *
+
+cpu_user, cpu_system, cpu_idle, cpu_nice, cpu_wio
+
+=item *
+
+mem_free, mem_shared, mem_buffers, mem_cached, mem_total
+
+=item *
+
+bytes_in, bytes_out
+
+=item *
+
+pkts_in, pkts_out
+
+=back
+
+Available configuration options:
+
+=over 4
+
+=item B<MCReceiveFrom> I<MCGroup> [I<Port>]
+
+Sets sets the multicast group and UDP port to which to subscribe.
+
+Default: B<239.2.11.71>E<nbsp>/E<nbsp>B<8649>
+
+=item E<lt>B<Metric> I<Name>E<gt>
+
+These blocks add a new metric conversion to the internal table. I<Name>, the
+string argument to the B<Metric> block, is the metric name as used by Ganglia.
+
+=over 4
+
+=item B<Type> I<Type>
+
+Type to map this metric to. Required.
+
+=item B<TypeInstance> I<Instance>
+
+Type-instance to use. Optional.
+
+=item B<DataSource> I<Name>
+
+Data source to map this metric to. If the configured type has exactly one data
+source, this is optional. Otherwise the option is required.
+
+=back
+
+=back
+
+=head2 Plugin C<hddtemp>
+
+To get values from B<hddtemp> collectd connects to B<localhost> (127.0.0.1),
+port B<7634/tcp>. The B<Host> and B<Port> options can be used to change these
+default values, see below. C<hddtemp> has to be running to work correctly. If
+C<hddtemp> is not running timeouts may appear which may interfere with other
+statistics..
+
+The B<hddtemp> homepage can be found at
+L<http://www.guzu.net/linux/hddtemp.php>.
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname to connect to. Defaults to B<127.0.0.1>.
+
+=item B<Port> I<Port>
+
+TCP-Port to connect to. Defaults to B<7634>.
+
+=back
+
+=head2 Plugin C<interface>
+
+=over 4
+
+=item B<Interface> I<Interface>
+
+Select this interface. By default these interfaces will then be collected. For
+a more detailed description see B<IgnoreSelected> below.
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+If no configuration if given, the B<traffic>-plugin will collect data from
+all interfaces. This may not be practical, especially for loopback- and
+similar interfaces. Thus, you can use the B<Interface>-option to pick the
+interfaces you're interested in. Sometimes, however, it's easier/preferred
+to collect all interfaces I<except> a few ones. This option enables you to
+do that: By setting B<IgnoreSelected> to I<true> the effect of
+B<Interface> is inverted: All selected interfaces are ignored and all
+other interfaces are collected.
+
+=back
+
+=head2 Plugin C<ipmi>
+
+=over 4
+
+=item B<Sensor> I<Sensor>
+
+Selects sensors to collect or to ignore, depending on B<IgnoreSelected>.
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+If no configuration if given, the B<ipmi> plugin will collect data from all
+sensors found of type "temperature", "voltage", "current" and "fanspeed".
+This option enables you to do that: By setting B<IgnoreSelected> to I<true>
+the effect of B<Sensor> is inverted: All selected sensors are ignored and
+all other sensors are collected.
+
+=item B<NotifySensorAdd> I<true>|I<false>
+
+If a sensor appears after initialization time of a minute a notification
+is sent.
+
+=item B<NotifySensorRemove> I<true>|I<false>
+
+If a sensor disappears a notification is sent.
+
+=item B<NotifySensorNotPresent> I<true>|I<false>
+
+If you have for example dual power supply and one of them is (un)plugged then
+a notification is sent.
+
+=back
+
+=head2 Plugin C<iptables>
+
+=over 4
+
+=item B<Chain> I<Table> I<Chain> [I<Comment|Number> [I<Name>]]
+
+Select the rules to count. If only I<Table> and I<Chain> are given, this plugin
+will collect the counters of all rules which have a comment-match. The comment
+is then used as type-instance.
+
+If I<Comment> or I<Number> is given, only the rule with the matching comment or
+the I<n>th rule will be collected. Again, the comment (or the number) will be
+used as the type-instance.
+
+If I<Name> is supplied, it will be used as the type-instance instead of the
+comment or the number.
+
+=back
+
+=head2 Plugin C<irq>
+
+=over 4
+
+=item B<Irq> I<Irq>
+
+Select this irq. By default these irqs will then be collected. For a more
+detailed description see B<IgnoreSelected> below.
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+If no configuration if given, the B<irq>-plugin will collect data from all
+irqs. This may not be practical, especially if no interrupts happen. Thus, you
+can use the B<Irq>-option to pick the interrupt you're interested in.
+Sometimes, however, it's easier/preferred to collect all interrupts I<except> a
+few ones. This option enables you to do that: By setting B<IgnoreSelected> to
+I<true> the effect of B<Irq> is inverted: All selected interrupts are ignored
+and all other interrupts are collected.
+
+=back
+
+=head2 Plugin C<java>
+
+The I<Java> plugin makes it possible to write extensions for collectd in Java.
+This section only discusses the syntax and semantic of the configuration
+options. For more in-depth information on the I<Java> plugin, please read
+L<collectd-java(5)>.
+
+Synopsis:
+
+ <Plugin "java">
+   JVMArg "-verbose:jni"
+   JVMArg "-Djava.class.path=/opt/collectd/lib/collectd/bindings/java"
+   LoadPlugin "org.collectd.java.Foobar"
+   <Plugin "org.collectd.java.Foobar">
+     # To be parsed by the plugin
+   </Plugin>
+ </Plugin>
+
+Available configuration options:
+
+=over 4
+
+=item B<JVMArg> I<Argument>
+
+Argument that is to be passed to the I<Java Virtual Machine> (JVM). This works
+exactly the way the arguments to the I<java> binary on the command line work.
+Execute C<javaE<nbsp>--help> for details.
+
+Please note that B<all> these options must appear B<before> (i.E<nbsp>e. above)
+any other options! When another option is found, the JVM will be started and
+later options will have to be ignored!
+
+=item B<LoadPlugin> I<JavaClass>
+
+Instantiates a new I<JavaClass> object. The constructor of this object very
+likely then registers one or more callback methods with the server.
+
+See L<collectd-java(5)> for details.
+
+When the first such option is found, the virtual machine (JVM) is created. This
+means that all B<JVMArg> options must appear before (i.E<nbsp>e. above) all
+B<LoadPlugin> options!
+
+=item B<Plugin> I<Name>
+
+The entire block is passed to the Java plugin as an
+I<org.collectd.api.OConfigItem> object.
+
+For this to work, the plugin has to register a configuration callback first,
+see L<collectd-java(5)/"config callback">. This means, that the B<Plugin> block
+must appear after the appropriate B<LoadPlugin> block. Also note, that I<Name>
+depends on the (Java) plugin registering the callback and is completely
+independent from the I<JavaClass> argument passed to B<LoadPlugin>.
+
+=back
+
+=head2 Plugin C<load>
+
+The I<Load plugin> collects the system load. These numbers give a rough overview
+over the utilization of a machine. The system load is defined as the number of
+runnable tasks in the run-queue and is provided by many operating systems as a
+one, five or fifteen minute average.
+
+The following configuration options are available:
+
+=over 4
+
+=item B<ReportRelative> B<false>|B<true>
+
+When enabled, system load divided by number of available CPU cores is reported
+for intervals 1 min, 5 min and 15 min. Defaults to false.
+
+=back
+
+
+=head2 Plugin C<logfile>
+
+=over 4
+
+=item B<LogLevel> B<debug|info|notice|warning|err>
+
+Sets the log-level. If, for example, set to B<notice>, then all events with
+severity B<notice>, B<warning>, or B<err> will be written to the logfile.
+
+Please note that B<debug> is only available if collectd has been compiled with
+debugging support.
+
+=item B<File> I<File>
+
+Sets the file to write log messages to. The special strings B<stdout> and
+B<stderr> can be used to write to the standard output and standard error
+channels, respectively. This, of course, only makes much sense when I<collectd>
+is running in foreground- or non-daemon-mode.
+
+=item B<Timestamp> B<true>|B<false>
+
+Prefix all lines printed by the current time. Defaults to B<true>.
+
+=item B<PrintSeverity> B<true>|B<false>
+
+When enabled, all lines are prefixed by the severity of the log message, for
+example "warning". Defaults to B<false>.
+
+=back
+
+B<Note>: There is no need to notify the daemon after moving or removing the
+log file (e.E<nbsp>g. when rotating the logs). The plugin reopens the file
+for each line it writes.
+
+=head2 Plugin C<log_logstash>
+
+The I<log logstash plugin> behaves like the logfile plugin but formats
+messages as JSON events for logstash to parse and input.
+
+=over 4
+
+=item B<LogLevel> B<debug|info|notice|warning|err>
+
+Sets the log-level. If, for example, set to B<notice>, then all events with
+severity B<notice>, B<warning>, or B<err> will be written to the logfile.
+
+Please note that B<debug> is only available if collectd has been compiled with
+debugging support.
+
+=item B<File> I<File>
+
+Sets the file to write log messages to. The special strings B<stdout> and
+B<stderr> can be used to write to the standard output and standard error
+channels, respectively. This, of course, only makes much sense when I<collectd>
+is running in foreground- or non-daemon-mode.
+
+=back
+
+B<Note>: There is no need to notify the daemon after moving or removing the
+log file (e.E<nbsp>g. when rotating the logs). The plugin reopens the file
+for each line it writes.
+
+=head2 Plugin C<lpar>
+
+The I<LPAR plugin> reads CPU statistics of I<Logical Partitions>, a
+virtualization technique for IBM POWER processors. It takes into account CPU
+time stolen from or donated to a partition, in addition to the usual user,
+system, I/O statistics.
+
+The following configuration options are available:
+
+=over 4
+
+=item B<CpuPoolStats> B<false>|B<true>
+
+When enabled, statistics about the processor pool are read, too. The partition
+needs to have pool authority in order to be able to acquire this information.
+Defaults to false.
+
+=item B<ReportBySerial> B<false>|B<true>
+
+If enabled, the serial of the physical machine the partition is currently
+running on is reported as I<hostname> and the logical hostname of the machine
+is reported in the I<plugin instance>. Otherwise, the logical hostname will be
+used (just like other plugins) and the I<plugin instance> will be empty.
+Defaults to false.
+
+=back
+
+=head2 Plugin C<mbmon>
+
+The C<mbmon plugin> uses mbmon to retrieve temperature, voltage, etc.
+
+Be default collectd connects to B<localhost> (127.0.0.1), port B<411/tcp>. The
+B<Host> and B<Port> options can be used to change these values, see below.
+C<mbmon> has to be running to work correctly. If C<mbmon> is not running
+timeouts may appear which may interfere with other statistics..
+
+C<mbmon> must be run with the -r option ("print TAG and Value format");
+Debian's F</etc/init.d/mbmon> script already does this, other people
+will need to ensure that this is the case.
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname to connect to. Defaults to B<127.0.0.1>.
+
+=item B<Port> I<Port>
+
+TCP-Port to connect to. Defaults to B<411>.
+
+=back
+
+=head2 Plugin C<md>
+
+The C<md plugin> collects information from Linux Software-RAID devices (md).
+
+All reported values are of the type C<md_disks>. Reported type instances are
+I<active>, I<failed> (present but not operational), I<spare> (hot stand-by) and
+I<missing> (physically absent) disks.
+
+=over 4
+
+=item B<Device> I<Device>
+
+Select md devices based on device name. The I<device name> is the basename of
+the device, i.e. the name of the block device without the leading C</dev/>.
+See B<IgnoreSelected> for more details.
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Invert device selection: If set to B<true>, all md devices B<except> those
+listed using B<Device> are collected. If B<false> (the default), only those
+listed are collected. If no configuration is given, the B<md> plugin will
+collect data from all md devices.
+
+=back
+
+=head2 Plugin C<memcachec>
+
+The C<memcachec plugin> connects to a memcached server, queries one or more
+given I<pages> and parses the returned data according to user specification.
+The I<matches> used are the same as the matches used in the C<curl> and C<tail>
+plugins.
+
+In order to talk to the memcached server, this plugin uses the I<libmemcached>
+library. Please note that there is another library with a very similar name,
+libmemcache (notice the missing `d'), which is not applicable.
+
+Synopsis of the configuration:
+
+ <Plugin "memcachec">
+   <Page "plugin_instance">
+     Server "localhost"
+     Key "page_key"
+     <Match>
+       Regex "(\\d+) bytes sent"
+       DSType CounterAdd
+       Type "ipt_octets"
+       Instance "type_instance"
+     </Match>
+   </Page>
+ </Plugin>
+
+The configuration options are:
+
+=over 4
+
+=item E<lt>B<Page> I<Name>E<gt>
+
+Each B<Page> block defines one I<page> to be queried from the memcached server.
+The block requires one string argument which is used as I<plugin instance>.
+
+=item B<Server> I<Address>
+
+Sets the server address to connect to when querying the page. Must be inside a
+B<Page> block.
+
+=item B<Key> I<Key>
+
+When connected to the memcached server, asks for the page I<Key>.
+
+=item E<lt>B<Match>E<gt>
+
+Match blocks define which strings to look for and how matches substrings are
+interpreted. For a description of match blocks, please see L<"Plugin tail">.
+
+=back
+
+=head2 Plugin C<memcached>
+
+The B<memcached plugin> connects to a memcached server and queries statistics
+about cache utilization, memory and bandwidth used.
+L<http://www.danga.com/memcached/>
+
+ <Plugin "memcached">
+   <Instance "name">
+     Host "memcache.example.com"
+     Port 11211
+   </Instance>
+ </Plugin>
+
+The plugin configuration consists of one or more B<Instance> blocks which
+specify one I<memcached> connection each. Within the B<Instance> blocks, the
+following options are allowed:
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname to connect to. Defaults to B<127.0.0.1>.
+
+=item B<Port> I<Port>
+
+TCP-Port to connect to. Defaults to B<11211>.
+
+=item B<Socket> I<Path>
+
+Connect to I<memcached> using the UNIX domain socket at I<Path>. If this
+setting is given, the B<Host> and B<Port> settings are ignored.
+
+=back
+
+=head2 Plugin C<mic>
+
+The B<mic plugin> gathers CPU statistics, memory usage and temperatures from
+Intel's Many Integrated Core (MIC) systems.
+
+B<Synopsis:>
+
+ <Plugin mic>
+   ShowCPU true
+   ShowCPUCores true
+   ShowMemory true
+
+   ShowTemperatures true
+   Temperature vddg
+   Temperature vddq
+   IgnoreSelectedTemperature true
+
+   ShowPower true
+   Power total0
+   Power total1
+   IgnoreSelectedPower true
+ </Plugin>
+
+The following options are valid inside the B<PluginE<nbsp>mic> block:
+
+=over 4
+
+=item B<ShowCPU> B<true>|B<false>
+
+If enabled (the default) a sum of the CPU usage across all cores is reported.
+
+=item B<ShowCPUCores> B<true>|B<false>
+
+If enabled (the default) per-core CPU usage is reported.
+
+=item B<ShowMemory> B<true>|B<false>
+
+If enabled (the default) the physical memory usage of the MIC system is
+reported.
+
+=item B<ShowTemperatures> B<true>|B<false>
+
+If enabled (the default) various temperatures of the MIC system are reported.
+
+=item B<Temperature> I<Name>
+
+This option controls which temperatures are being reported. Whether matching
+temperatures are being ignored or I<only> matching temperatures are reported
+depends on the B<IgnoreSelectedTemperature> setting below. By default I<all>
+temperatures are reported.
+
+=item B<IgnoreSelectedTemperature> B<false>|B<true>
+
+Controls the behavior of the B<Temperature> setting above. If set to B<false>
+(the default) only temperatures matching a B<Temperature> option are reported
+or, if no B<Temperature> option is specified, all temperatures are reported. If
+set to B<true>, matching temperatures are I<ignored> and all other temperatures
+are reported.
+
+Known temperature names are:
+
+=over 4
+
+=item die
+
+Die of the CPU
+
+=item devmem
+
+Device Memory
+
+=item fin
+
+Fan In
+
+=item fout
+
+Fan Out
+
+=item vccp
+
+Voltage ccp
+
+=item vddg
+
+Voltage ddg
+
+=item vddq
+
+Voltage ddq
+
+=back
+
+=item B<ShowPower> B<true>|B<false>
+
+If enabled (the default) various temperatures of the MIC system are reported.
+
+=item B<Power> I<Name>
+
+This option controls which power readings are being reported. Whether matching
+power readings are being ignored or I<only> matching power readings are reported
+depends on the B<IgnoreSelectedPower> setting below. By default I<all>
+power readings are reported.
+
+=item B<IgnoreSelectedPower> B<false>|B<true>
+
+Controls the behavior of the B<Power> setting above. If set to B<false>
+(the default) only power readings matching a B<Power> option are reported
+or, if no B<Power> option is specified, all power readings are reported. If
+set to B<true>, matching power readings are I<ignored> and all other power readings
+are reported.
+
+Known power names are:
+
+=over 4
+
+=item total0
+
+Total power utilization averaged over Time Window 0 (uWatts).
+
+=item total1
+
+Total power utilization averaged over Time Window 0 (uWatts).
+
+=item inst
+
+Instantaneous power (uWatts).
+
+=item imax
+
+Max instantaneous power (uWatts).
+
+=item pcie
+
+PCI-E connector power (uWatts).
+
+=item c2x3
+
+2x3 connector power (uWatts).
+
+=item c2x4
+
+2x4 connector power (uWatts).
+
+=item vccp
+
+Core rail (uVolts).
+
+=item vddg
+
+Uncore rail (uVolts).
+
+=item vddq
+
+Memory subsystem rail (uVolts).
+
+=back
+
+=back
+
+=head2 Plugin C<memory>
+
+The I<memory plugin> provides the following configuration options:
+
+=over 4
+
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of physical memory usage in absolute numbers,
+i.e. bytes. Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of physical memory usage in percentages, e.g.
+percent of physical memory used. Defaults to B<false>.
+
+This is useful for deploying I<collectd> in a heterogeneous environment in
+which the sizes of physical memory vary.
+
+=back
+
+=head2 Plugin C<modbus>
+
+The B<modbus plugin> connects to a Modbus "slave" via Modbus/TCP or Modbus/RTU and
+reads register values. It supports reading single registers (unsigned 16E<nbsp>bit
+values), large integer values (unsigned 32E<nbsp>bit values) and floating point
+values (two registers interpreted as IEEE floats in big endian notation).
+
+B<Synopsis:>
+
+ <Data "voltage-input-1">
+   RegisterBase 0
+   RegisterType float
+   RegisterCmd ReadHolding
+   Type voltage
+   Instance "input-1"
+ </Data>
+
+ <Data "voltage-input-2">
+   RegisterBase 2
+   RegisterType float
+   RegisterCmd ReadHolding
+   Type voltage
+   Instance "input-2"
+ </Data>
+
+ <Data "supply-temperature-1">
+   RegisterBase 0
+   RegisterType Int16
+   RegisterCmd ReadHolding
+   Type temperature
+   Instance "temp-1"
+ </Data>
+
+ <Host "modbus.example.com">
+   Address "192.168.0.42"
+   Port    "502"
+   Interval 60
+
+   <Slave 1>
+     Instance "power-supply"
+     Collect  "voltage-input-1"
+     Collect  "voltage-input-2"
+   </Slave>
+ </Host>
+
+ <Host "localhost">
+   Device "/dev/ttyUSB0"
+   Baudrate 38400
+   Interval 20
+
+   <Slave 1>
+     Instance "temperature"
+     Collect  "supply-temperature-1"
+   </Slave>
+ </Host>
+
+=over 4
+
+=item E<lt>B<Data> I<Name>E<gt> blocks
+
+Data blocks define a mapping between register numbers and the "types" used by
+I<collectd>.
+
+Within E<lt>DataE<nbsp>/E<gt> blocks, the following options are allowed:
+
+=over 4
+
+=item B<RegisterBase> I<Number>
+
+Configures the base register to read from the device. If the option
+B<RegisterType> has been set to B<Uint32> or B<Float>, this and the next
+register will be read (the register number is increased by one).
+
+=item B<RegisterType> B<Int16>|B<Int32>|B<Uint16>|B<Uint32>|B<Float>
+
+Specifies what kind of data is returned by the device. If the type is B<Int32>,
+B<Uint32> or B<Float>, two 16E<nbsp>bit registers will be read and the data is
+combined into one value. Defaults to B<Uint16>.
+
+=item B<RegisterCmd> B<ReadHolding>|B<ReadInput>
+
+Specifies register type to be collected from device. Works only with libmodbus
+2.9.2 or higher. Defaults to B<ReadHolding>.
+
+=item B<Type> I<Type>
+
+Specifies the "type" (data set) to use when dispatching the value to
+I<collectd>. Currently, only data sets with exactly one data source are
+supported.
+
+=item B<Instance> I<Instance>
+
+Sets the type instance to use when dispatching the value to I<collectd>. If
+unset, an empty string (no type instance) is used.
+
+=back
+
+=item E<lt>B<Host> I<Name>E<gt> blocks
+
+Host blocks are used to specify to which hosts to connect and what data to read
+from their "slaves". The string argument I<Name> is used as hostname when
+dispatching the values to I<collectd>.
+
+Within E<lt>HostE<nbsp>/E<gt> blocks, the following options are allowed:
+
+=over 4
+
+=item B<Address> I<Hostname>
+
+For Modbus/TCP, specifies the node name (the actual network address) used to
+connect to the host. This may be an IP address or a hostname. Please note that
+the used I<libmodbus> library only supports IPv4 at the moment.
+
+=item B<Port> I<Service>
+
+for Modbus/TCP, specifies the port used to connect to the host. The port can
+either be given as a number or as a service name. Please note that the
+I<Service> argument must be a string, even if ports are given in their numerical
+form. Defaults to "502".
+
+=item B<Device> I<Devicenode>
+
+For Modbus/RTU, specifies the path to the serial device being used.
+
+=item B<Baudrate> I<Baudrate>
+
+For Modbus/RTU, specifies the baud rate of the serial device.
+Note, connections currently support only 8/N/1.
+
+=item B<Interval> I<Interval>
+
+Sets the interval (in seconds) in which the values will be collected from this
+host. By default the global B<Interval> setting will be used.
+
+=item E<lt>B<Slave> I<ID>E<gt>
+
+Over each connection, multiple Modbus devices may be reached. The slave ID
+is used to specify which device should be addressed. For each device you want
+to query, one B<Slave> block must be given.
+
+Within E<lt>SlaveE<nbsp>/E<gt> blocks, the following options are allowed:
+
+=over 4
+
+=item B<Instance> I<Instance>
+
+Specify the plugin instance to use when dispatching the values to I<collectd>.
+By default "slave_I<ID>" is used.
+
+=item B<Collect> I<DataName>
+
+Specifies which data to retrieve from the device. I<DataName> must be the same
+string as the I<Name> argument passed to a B<Data> block. You can specify this
+option multiple times to collect more than one value from a slave. At least one
+B<Collect> option is mandatory.
+
+=back
+
+=back
+
+=back
+
+=head2 Plugin C<mysql>
+
+The C<mysql plugin> requires B<mysqlclient> to be installed. It connects to
+one or more databases when started and keeps the connection up as long as
+possible. When the connection is interrupted for whatever reason it will try
+to re-connect. The plugin will complain loudly in case anything goes wrong.
+
+This plugin issues the MySQL C<SHOW STATUS> / C<SHOW GLOBAL STATUS> command
+and collects information about MySQL network traffic, executed statements,
+requests, the query cache and threads by evaluating the
+C<Bytes_{received,sent}>, C<Com_*>, C<Handler_*>, C<Qcache_*> and C<Threads_*>
+return values. Please refer to the B<MySQL reference manual>, I<5.1.6. Server
+Status Variables> for an explanation of these values.
+
+Optionally, master and slave statistics may be collected in a MySQL
+replication setup. In that case, information about the synchronization state
+of the nodes are collected by evaluating the C<Position> return value of the
+C<SHOW MASTER STATUS> command and the C<Seconds_Behind_Master>,
+C<Read_Master_Log_Pos> and C<Exec_Master_Log_Pos> return values of the
+C<SHOW SLAVE STATUS> command. See the B<MySQL reference manual>,
+I<12.5.5.21 SHOW MASTER STATUS Syntax> and
+I<12.5.5.31 SHOW SLAVE STATUS Syntax> for details.
+
+Synopsis:
+
+  <Plugin mysql>
+    <Database foo>
+      Host "hostname"
+      User "username"
+      Password "password"
+      Port "3306"
+      MasterStats true
+      ConnectTimeout 10
+    </Database>
+
+    <Database bar>
+      Alias "squeeze"
+      Host "localhost"
+      Socket "/var/run/mysql/mysqld.sock"
+      SlaveStats true
+      SlaveNotifications true
+    </Database>
+  </Plugin>
+
+A B<Database> block defines one connection to a MySQL database. It accepts a
+single argument which specifies the name of the database. None of the other
+options are required. MySQL will use default values as documented in the
+section "mysql_real_connect()" in the B<MySQL reference manual>.
+
+=over 4
+
+=item B<Alias> I<Alias>
+
+Alias to use as sender instead of hostname when reporting. This may be useful
+when having cryptic hostnames.
+
+=item B<Host> I<Hostname>
+
+Hostname of the database server. Defaults to B<localhost>.
+
+=item B<User> I<Username>
+
+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
+B<SlaveStats> below). In this case, the user needs the C<REPLICATION CLIENT>
+(or C<SUPER>) privileges. Else, any existing MySQL user will do.
+
+=item B<Password> I<Password>
+
+Password needed to log into the database.
+
+=item B<Database> I<Database>
+
+Select this database. Defaults to I<no database> which is a perfectly reasonable
+option for what this plugin does.
+
+=item B<Port> I<Port>
+
+TCP-port to connect to. The port must be specified in its numeric form, but it
+must be passed as a string nonetheless. For example:
+
+  Port "3306"
+
+If B<Host> is set to B<localhost> (the default), this setting has no effect.
+See the documentation for the C<mysql_real_connect> function for details.
+
+=item B<Socket> I<Socket>
+
+Specifies the path to the UNIX domain socket of the MySQL server. This option
+only has any effect, if B<Host> is set to B<localhost> (the default).
+Otherwise, use the B<Port> option above. See the documentation for the
+C<mysql_real_connect> function for details.
+
+=item B<InnodbStats> I<true|false>
+
+If enabled, metrics about the InnoDB storage engine are collected.
+Disabled by default.
+
+=item B<MasterStats> I<true|false>
+
+=item B<SlaveStats> I<true|false>
+
+Enable the collection of master / slave statistics in a replication setup. In
+order to be able to get access to these statistics, the user needs special
+privileges. See the B<User> documentation above. Defaults to B<false>.
+
+=item B<SlaveNotifications> I<true|false>
+
+If enabled, the plugin sends a notification if the replication slave I/O and /
+or SQL threads are not running. Defaults to B<false>.
+
+=item B<ConnectTimeout> I<Seconds>
+
+Sets the connect timeout for the MySQL client.
+
+=back
+
+=head2 Plugin C<netapp>
+
+The netapp plugin can collect various performance and capacity information
+from a NetApp filer using the NetApp API.
+
+Please note that NetApp has a wide line of products and a lot of different
+software versions for each of these products. This plugin was developed for a
+NetApp FAS3040 running OnTap 7.2.3P8 and tested on FAS2050 7.3.1.1L1,
+FAS3140 7.2.5.1 and FAS3020 7.2.4P9. It I<should> work for most combinations of
+model and software version but it is very hard to test this.
+If you have used this plugin with other models and/or software version, feel
+free to send us a mail to tell us about the results, even if it's just a short
+"It works".
+
+To collect these data collectd will log in to the NetApp via HTTP(S) and HTTP
+basic authentication.
+
+B<Do not use a regular user for this!> Create a special collectd user with just
+the minimum of capabilities needed. The user only needs the "login-http-admin"
+capability as well as a few more depending on which data will be collected.
+Required capabilities are documented below.
+
+=head3 Synopsis
+
+ <Plugin "netapp">
+   <Host "netapp1.example.com">
+    Protocol      "https"
+    Address       "10.0.0.1"
+    Port          443
+    User          "username"
+    Password      "aef4Aebe"
+    Interval      30
+
+    <WAFL>
+      Interval 30
+      GetNameCache   true
+      GetDirCache    true
+      GetBufferCache true
+      GetInodeCache  true
+    </WAFL>
+
+    <Disks>
+      Interval 30
+      GetBusy true
+    </Disks>
+
+    <VolumePerf>
+      Interval 30
+      GetIO      "volume0"
+      IgnoreSelectedIO      false
+      GetOps     "volume0"
+      IgnoreSelectedOps     false
+      GetLatency "volume0"
+      IgnoreSelectedLatency false
+    </VolumePerf>
+
+    <VolumeUsage>
+      Interval 30
+      GetCapacity "vol0"
+      GetCapacity "vol1"
+      IgnoreSelectedCapacity false
+      GetSnapshot "vol1"
+      GetSnapshot "vol3"
+      IgnoreSelectedSnapshot false
+    </VolumeUsage>
+
+    <Quota>
+      Interval 60
+    </Quota>
+
+    <Snapvault>
+      Interval 30
+    </Snapvault>
+
+    <System>
+      Interval 30
+      GetCPULoad     true
+      GetInterfaces  true
+      GetDiskOps     true
+      GetDiskIO      true
+    </System>
+
+    <VFiler vfilerA>
+      Interval 60
+
+      SnapVault true
+      # ...
+    </VFiler>
+   </Host>
+ </Plugin>
+
+The netapp plugin accepts the following configuration options:
+
+=over 4
+
+=item B<Host> I<Name>
+
+A host block defines one NetApp filer. It will appear in collectd with the name
+you specify here which does not have to be its real name nor its hostname (see
+the B<Address> option below).
+
+=item B<VFiler> I<Name>
+
+A B<VFiler> block may only be used inside a host block. It accepts all the
+same options as the B<Host> block (except for cascaded B<VFiler> blocks) and
+will execute all NetApp API commands in the context of the specified
+VFiler(R). It will appear in collectd with the name you specify here which
+does not have to be its real name. The VFiler name may be specified using the
+B<VFilerName> option. If this is not specified, it will default to the name
+you specify here.
+
+The VFiler block inherits all connection related settings from the surrounding
+B<Host> block (which appear before the B<VFiler> block) but they may be
+overwritten inside the B<VFiler> block.
+
+This feature is useful, for example, when using a VFiler as SnapVault target
+(supported since OnTap 8.1). In that case, the SnapVault statistics are not
+available in the host filer (vfiler0) but only in the respective VFiler
+context.
+
+=item B<Protocol> B<httpd>|B<http>
+
+The protocol collectd will use to query this host.
+
+Optional
+
+Type: string
+
+Default: https
+
+Valid options: http, https
+
+=item B<Address> I<Address>
+
+The hostname or IP address of the host.
+
+Optional
+
+Type: string
+
+Default: The "host" block's name.
+
+=item B<Port> I<Port>
+
+The TCP port to connect to on the host.
+
+Optional
+
+Type: integer
+
+Default: 80 for protocol "http", 443 for protocol "https"
+
+=item B<User> I<User>
+
+=item B<Password> I<Password>
+
+The username and password to use to login to the NetApp.
+
+Mandatory
+
+Type: string
+
+=item B<VFilerName> I<Name>
+
+The name of the VFiler in which context to execute API commands. If not
+specified, the name provided to the B<VFiler> block will be used instead.
+
+Optional
+
+Type: string
+
+Default: name of the B<VFiler> block
+
+B<Note:> This option may only be used inside B<VFiler> blocks.
+
+=item B<Interval> I<Interval>
+
+B<TODO>
+
+=back
+
+The following options decide what kind of data will be collected. You can
+either use them as a block and fine tune various parameters inside this block,
+use them as a single statement to just accept all default values, or omit it to
+not collect any data.
+
+The following options are valid inside all blocks:
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect the respective statistics every I<Seconds> seconds. Defaults to the
+host specific setting.
+
+=back
+
+=head3 The System block
+
+This will collect various performance data about the whole system.
+
+B<Note:> To get this data the collectd user needs the
+"api-perf-object-get-instances" capability.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect disk statistics every I<Seconds> seconds.
+
+=item B<GetCPULoad> B<true>|B<false>
+
+If you set this option to true the current CPU usage will be read. This will be
+the average usage between all CPUs in your NetApp without any information about
+individual CPUs.
+
+B<Note:> These are the same values that the NetApp CLI command "sysstat"
+returns in the "CPU" field.
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: Two value lists of type "cpu", and type instances "idle" and "system".
+
+=item B<GetInterfaces> B<true>|B<false>
+
+If you set this option to true the current traffic of the network interfaces
+will be read. This will be the total traffic over all interfaces of your NetApp
+without any information about individual interfaces.
+
+B<Note:> This is the same values that the NetApp CLI command "sysstat" returns
+in the "Net kB/s" field.
+
+B<Or is it?>
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: One value list of type "if_octects".
+
+=item B<GetDiskIO> B<true>|B<false>
+
+If you set this option to true the current IO throughput will be read. This
+will be the total IO of your NetApp without any information about individual
+disks, volumes or aggregates.
+
+B<Note:> This is the same values that the NetApp CLI command "sysstat" returns
+in the "DiskE<nbsp>kB/s" field.
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: One value list of type "disk_octets".
+
+=item B<GetDiskOps> B<true>|B<false>
+
+If you set this option to true the current number of HTTP, NFS, CIFS, FCP,
+iSCSI, etc. operations will be read. This will be the total number of
+operations on your NetApp without any information about individual volumes or
+aggregates.
+
+B<Note:> These are the same values that the NetApp CLI command "sysstat"
+returns in the "NFS", "CIFS", "HTTP", "FCP" and "iSCSI" fields.
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: A variable number of value lists of type "disk_ops_complex". Each type
+of operation will result in one value list with the name of the operation as
+type instance.
+
+=back
+
+=head3 The WAFL block
+
+This will collect various performance data about the WAFL file system. At the
+moment this just means cache performance.
+
+B<Note:> To get this data the collectd user needs the
+"api-perf-object-get-instances" capability.
+
+B<Note:> The interface to get these values is classified as "Diagnostics" by
+NetApp. This means that it is not guaranteed to be stable even between minor
+releases.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect disk statistics every I<Seconds> seconds.
+
+=item B<GetNameCache> B<true>|B<false>
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: One value list of type "cache_ratio" and type instance
+"name_cache_hit".
+
+=item B<GetDirCache> B<true>|B<false>
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: One value list of type "cache_ratio" and type instance "find_dir_hit".
+
+=item B<GetInodeCache> B<true>|B<false>
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: One value list of type "cache_ratio" and type instance
+"inode_cache_hit".
+
+=item B<GetBufferCache> B<true>|B<false>
+
+B<Note:> This is the same value that the NetApp CLI command "sysstat" returns
+in the "Cache hit" field.
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: One value list of type "cache_ratio" and type instance "buf_hash_hit".
+
+=back
+
+=head3 The Disks block
+
+This will collect performance data about the individual disks in the NetApp.
+
+B<Note:> To get this data the collectd user needs the
+"api-perf-object-get-instances" capability.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect disk statistics every I<Seconds> seconds.
+
+=item B<GetBusy> B<true>|B<false>
+
+If you set this option to true the busy time of all disks will be calculated
+and the value of the busiest disk in the system will be written.
+
+B<Note:> This is the same values that the NetApp CLI command "sysstat" returns
+in the "Disk util" field. Probably.
+
+Optional
+
+Type: boolean
+
+Default: true
+
+Result: One value list of type "percent" and type instance "disk_busy".
+
+=back
+
+=head3 The VolumePerf block
+
+This will collect various performance data about the individual volumes.
+
+You can select which data to collect about which volume using the following
+options. They follow the standard ignorelist semantic.
+
+B<Note:> To get this data the collectd user needs the
+I<api-perf-object-get-instances> capability.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect volume performance data every I<Seconds> seconds.
+
+=item B<GetIO> I<Volume>
+
+=item B<GetOps> I<Volume>
+
+=item B<GetLatency> I<Volume>
+
+Select the given volume for IO, operations or latency statistics collection.
+The argument is the name of the volume without the C</vol/> prefix.
+
+Since the standard ignorelist functionality is used here, you can use a string
+starting and ending with a slash to specify regular expression matching: To
+match the volumes "vol0", "vol2" and "vol7", you can use this regular
+expression:
+
+  GetIO "/^vol[027]$/"
+
+If no regular expression is specified, an exact match is required. Both,
+regular and exact matching are case sensitive.
+
+If no volume was specified at all for either of the three options, that data
+will be collected for all available volumes.
+
+=item B<IgnoreSelectedIO> B<true>|B<false>
+
+=item B<IgnoreSelectedOps> B<true>|B<false>
+
+=item B<IgnoreSelectedLatency> B<true>|B<false>
+
+When set to B<true>, the volumes selected for IO, operations or latency
+statistics collection will be ignored and the data will be collected for all
+other volumes.
+
+When set to B<false>, data will only be collected for the specified volumes and
+all other volumes will be ignored.
+
+If no volumes have been specified with the above B<Get*> options, all volumes
+will be collected regardless of the B<IgnoreSelected*> option.
+
+Defaults to B<false>
+
+=back
+
+=head3 The VolumeUsage block
+
+This will collect capacity data about the individual volumes.
+
+B<Note:> To get this data the collectd user needs the I<api-volume-list-info>
+capability.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect volume usage statistics every I<Seconds> seconds.
+
+=item B<GetCapacity> I<VolumeName>
+
+The current capacity of the volume will be collected. This will result in two
+to four value lists, depending on the configuration of the volume. All data
+sources are of type "df_complex" with the name of the volume as
+plugin_instance.
+
+There will be type_instances "used" and "free" for the number of used and
+available bytes on the volume.  If the volume has some space reserved for
+snapshots, a type_instance "snap_reserved" will be available.  If the volume
+has SIS enabled, a type_instance "sis_saved" will be available. This is the
+number of bytes saved by the SIS feature.
+
+B<Note:> The current NetApp API has a bug that results in this value being
+reported as a 32E<nbsp>bit number. This plugin tries to guess the correct
+number which works most of the time.  If you see strange values here, bug
+NetApp support to fix this.
+
+Repeat this option to specify multiple volumes.
+
+=item B<IgnoreSelectedCapacity> B<true>|B<false>
+
+Specify whether to collect only the volumes selected by the B<GetCapacity>
+option or to ignore those volumes. B<IgnoreSelectedCapacity> defaults to
+B<false>. However, if no B<GetCapacity> option is specified at all, all
+capacities will be selected anyway.
+
+=item B<GetSnapshot> I<VolumeName>
+
+Select volumes from which to collect snapshot information.
+
+Usually, the space used for snapshots is included in the space reported as
+"used". If snapshot information is collected as well, the space used for
+snapshots is subtracted from the used space.
+
+To make things even more interesting, it is possible to reserve space to be
+used for snapshots. If the space required for snapshots is less than that
+reserved space, there is "reserved free" and "reserved used" space in addition
+to "free" and "used". If the space required for snapshots exceeds the reserved
+space, that part allocated in the normal space is subtracted from the "used"
+space again.
+
+Repeat this option to specify multiple volumes.
+
+=item B<IgnoreSelectedSnapshot>
+
+Specify whether to collect only the volumes selected by the B<GetSnapshot>
+option or to ignore those volumes. B<IgnoreSelectedSnapshot> defaults to
+B<false>. However, if no B<GetSnapshot> option is specified at all, all
+capacities will be selected anyway.
+
+=back
+
+=head3 The Quota block
+
+This will collect (tree) quota statistics (used disk space and number of used
+files). This mechanism is useful to get usage information for single qtrees.
+In case the quotas are not used for any other purpose, an entry similar to the
+following in C</etc/quotas> would be sufficient:
+
+  /vol/volA/some_qtree tree - - - - -
+
+After adding the entry, issue C<quota on -w volA> on the NetApp filer.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect SnapVault(R) statistics every I<Seconds> seconds.
+
+=back
+
+=head3 The SnapVault block
+
+This will collect statistics about the time and traffic of SnapVault(R)
+transfers.
+
+=over 4
+
+=item B<Interval> I<Seconds>
+
+Collect SnapVault(R) statistics every I<Seconds> seconds.
+
+=back
+
+=head2 Plugin C<netlink>
+
+The C<netlink> plugin uses a netlink socket to query the Linux kernel about
+statistics of various interface and routing aspects.
+
+=over 4
+
+=item B<Interface> I<Interface>
+
+=item B<VerboseInterface> I<Interface>
+
+Instruct the plugin to collect interface statistics. This is basically the same
+as the statistics provided by the C<interface> plugin (see above) but
+potentially much more detailed.
+
+When configuring with B<Interface> only the basic statistics will be collected,
+namely octets, packets, and errors. These statistics are collected by
+the C<interface> plugin, too, so using both at the same time is no benefit.
+
+When configured with B<VerboseInterface> all counters B<except> the basic ones,
+so that no data needs to be collected twice if you use the C<interface> plugin.
+This includes dropped packets, received multicast packets, collisions and a
+whole zoo of differentiated RX and TX errors. You can try the following command
+to get an idea of what awaits you:
+
+  ip -s -s link list
+
+If I<Interface> is B<All>, all interfaces will be selected.
+
+=item B<QDisc> I<Interface> [I<QDisc>]
+
+=item B<Class> I<Interface> [I<Class>]
+
+=item B<Filter> I<Interface> [I<Filter>]
+
+Collect the octets and packets that pass a certain qdisc, class or filter.
+
+QDiscs and classes are identified by their type and handle (or classid).
+Filters don't necessarily have a handle, therefore the parent's handle is used.
+The notation used in collectd differs from that used in tc(1) in that it
+doesn't skip the major or minor number if it's zero and doesn't print special
+ids by their name. So, for example, a qdisc may be identified by
+C<pfifo_fast-1:0> even though the minor number of B<all> qdiscs is zero and
+thus not displayed by tc(1).
+
+If B<QDisc>, B<Class>, or B<Filter> is given without the second argument,
+i.E<nbsp>.e. without an identifier, all qdiscs, classes, or filters that are
+associated with that interface will be collected.
+
+Since a filter itself doesn't necessarily have a handle, the parent's handle is
+used. This may lead to problems when more than one filter is attached to a
+qdisc or class. This isn't nice, but we don't know how this could be done any
+better. If you have a idea, please don't hesitate to tell us.
+
+As with the B<Interface> option you can specify B<All> as the interface,
+meaning all interfaces.
+
+Here are some examples to help you understand the above text more easily:
+
+  <Plugin netlink>
+    VerboseInterface "All"
+    QDisc "eth0" "pfifo_fast-1:0"
+    QDisc "ppp0"
+    Class "ppp0" "htb-1:10"
+    Filter "ppp0" "u32-1:0"
+  </Plugin>
+
+=item B<IgnoreSelected>
+
+The behavior is the same as with all other similar plugins: If nothing is
+selected at all, everything is collected. If some things are selected using the
+options described above, only these statistics are collected. If you set
+B<IgnoreSelected> to B<true>, this behavior is inverted, i.E<nbsp>e. the
+specified statistics will not be collected.
+
+=back
+
+=head2 Plugin C<network>
+
+The Network plugin sends data to a remote instance of collectd, receives data
+from a remote instance, or both at the same time. Data which has been received
+from the network is usually not transmitted again, but this can be activated, see
+the B<Forward> option below.
+
+The default IPv6 multicast group is C<ff18::efc0:4a42>. The default IPv4
+multicast group is C<239.192.74.66>. The default I<UDP> port is B<25826>.
+
+Both, B<Server> and B<Listen> can be used as single option or as block. When
+used as block, given options are valid for this socket only. The following
+example will export the metrics twice: Once to an "internal" server (without
+encryption and signing) and one to an external server (with cryptographic
+signature):
+
+ <Plugin "network">
+   # Export to an internal server
+   # (demonstrates usage without additional options)
+   Server "collectd.internal.tld"
+
+   # Export to an external server
+   # (demonstrates usage with signature options)
+   <Server "collectd.external.tld">
+     SecurityLevel "sign"
+     Username "myhostname"
+     Password "ohl0eQue"
+   </Server>
+ </Plugin>
+
+=over 4
+
+=item B<E<lt>Server> I<Host> [I<Port>]B<E<gt>>
+
+The B<Server> statement/block sets the server to send datagrams to. The
+statement may occur multiple times to send each datagram to multiple
+destinations.
+
+The argument I<Host> may be a hostname, an IPv4 address or an IPv6 address. The
+optional second argument specifies a port number or a service name. If not
+given, the default, B<25826>, is used.
+
+The following options are recognized within B<Server> blocks:
+
+=over 4
+
+=item B<SecurityLevel> B<Encrypt>|B<Sign>|B<None>
+
+Set the security you require for network communication. When the security level
+has been set to B<Encrypt>, data sent over the network will be encrypted using
+I<AES-256>. The integrity of encrypted packets is ensured using I<SHA-1>. When
+set to B<Sign>, transmitted data is signed using the I<HMAC-SHA-256> message
+authentication code. When set to B<None>, data is sent without any security.
+
+This feature is only available if the I<network> plugin was linked with
+I<libgcrypt>.
+
+=item B<Username> I<Username>
+
+Sets the username to transmit. This is used by the server to lookup the
+password. See B<AuthFile> below. All security levels except B<None> require
+this setting.
+
+This feature is only available if the I<network> plugin was linked with
+I<libgcrypt>.
+
+=item B<Password> I<Password>
+
+Sets a password (shared secret) for this socket. All security levels except
+B<None> require this setting.
+
+This feature is only available if the I<network> plugin was linked with
+I<libgcrypt>.
+
+=item B<Interface> I<Interface name>
+
+Set the outgoing interface for IP packets. This applies at least
+to IPv6 packets and if possible to IPv4. If this option is not applicable,
+undefined or a non-existent interface name is specified, the default
+behavior is to let the kernel choose the appropriate interface. Be warned
+that the manual selection of an interface for unicast traffic is only
+necessary in rare cases.
+
+=item B<ResolveInterval> I<Seconds>
+
+Sets the interval at which to re-resolve the DNS for the I<Host>. This is
+useful to force a regular DNS lookup to support a high availability setup. If
+not specified, re-resolves are never attempted.
+
+=back
+
+=item B<E<lt>Listen> I<Host> [I<Port>]B<E<gt>>
+
+The B<Listen> statement sets the interfaces to bind to. When multiple
+statements are found the daemon will bind to multiple interfaces.
+
+The argument I<Host> may be a hostname, an IPv4 address or an IPv6 address. If
+the argument is a multicast address the daemon will join that multicast group.
+The optional second argument specifies a port number or a service name. If not
+given, the default, B<25826>, is used.
+
+The following options are recognized within C<E<lt>ListenE<gt>> blocks:
+
+=over 4
+
+=item B<SecurityLevel> B<Encrypt>|B<Sign>|B<None>
+
+Set the security you require for network communication. When the security level
+has been set to B<Encrypt>, only encrypted data will be accepted. The integrity
+of encrypted packets is ensured using I<SHA-1>. When set to B<Sign>, only
+signed and encrypted data is accepted. When set to B<None>, all data will be
+accepted. If an B<AuthFile> option was given (see below), encrypted data is
+decrypted if possible.
+
+This feature is only available if the I<network> plugin was linked with
+I<libgcrypt>.
+
+=item B<AuthFile> I<Filename>
+
+Sets a file in which usernames are mapped to passwords. These passwords are
+used to verify signatures and to decrypt encrypted network packets. If
+B<SecurityLevel> is set to B<None>, this is optional. If given, signed data is
+verified and encrypted packets are decrypted. Otherwise, signed data is
+accepted without checking the signature and encrypted data cannot be decrypted.
+For the other security levels this option is mandatory.
+
+The file format is very simple: Each line consists of a username followed by a
+colon and any number of spaces followed by the password. To demonstrate, an
+example file could look like this:
+
+  user0: foo
+  user1: bar
+
+Each time a packet is received, the modification time of the file is checked
+using L<stat(2)>. If the file has been changed, the contents is re-read. While
+the file is being read, it is locked using L<fcntl(2)>.
+
+=item B<Interface> I<Interface name>
+
+Set the incoming interface for IP packets explicitly. This applies at least
+to IPv6 packets and if possible to IPv4. If this option is not applicable,
+undefined or a non-existent interface name is specified, the default
+behavior is, to let the kernel choose the appropriate interface. Thus incoming
+traffic gets only accepted, if it arrives on the given interface.
+
+=back
+
+=item B<TimeToLive> I<1-255>
+
+Set the time-to-live of sent packets. This applies to all, unicast and
+multicast, and IPv4 and IPv6 packets. The default is to not change this value.
+That means that multicast packets will be sent with a TTL of C<1> (one) on most
+operating systems.
+
+=item B<MaxPacketSize> I<1024-65535>
+
+Set the maximum size for datagrams received over the network. Packets larger
+than this will be truncated. Defaults to 1452E<nbsp>bytes, which is the maximum
+payload size that can be transmitted in one Ethernet frame using IPv6E<nbsp>/
+UDP.
+
+On the server side, this limit should be set to the largest value used on
+I<any> client. Likewise, the value on the client must not be larger than the
+value on the server, or data will be lost.
+
+B<Compatibility:> Versions prior to I<versionE<nbsp>4.8> used a fixed sized
+buffer of 1024E<nbsp>bytes. Versions I<4.8>, I<4.9> and I<4.10> used a default
+value of 1024E<nbsp>bytes to avoid problems when sending data to an older
+server.
+
+=item B<Forward> I<true|false>
+
+If set to I<true>, write packets that were received via the network plugin to
+the sending sockets. This should only be activated when the B<Listen>- and
+B<Server>-statements differ. Otherwise packets may be send multiple times to
+the same multicast group. While this results in more network traffic than
+necessary it's not a huge problem since the plugin has a duplicate detection,
+so the values will not loop.
+
+=item B<ReportStats> B<true>|B<false>
+
+The network plugin cannot only receive and send statistics, it can also create
+statistics about itself. Collected data included the number of received and
+sent octets and packets, the length of the receive queue and the number of
+values handled. When set to B<true>, the I<Network plugin> will make these
+statistics available. Defaults to B<false>.
+
+=back
+
+=head2 Plugin C<nginx>
+
+This plugin collects the number of connections and requests handled by the
+C<nginx daemon> (speak: engineE<nbsp>X), a HTTP and mail server/proxy. It
+queries the page provided by the C<ngx_http_stub_status_module> module, which
+isn't compiled by default. Please refer to
+L<http://wiki.codemongers.com/NginxStubStatusModule> for more information on
+how to compile and configure nginx and this module.
+
+The following options are accepted by the C<nginx plugin>:
+
+=over 4
+
+=item B<URL> I<http://host/nginx_status>
+
+Sets the URL of the C<ngx_http_stub_status_module> output.
+
+=item B<User> I<Username>
+
+Optional user name needed for authentication.
+
+=item B<Password> I<Password>
+
+Optional password needed for authentication.
+
+=item B<VerifyPeer> B<true|false>
+
+Enable or disable peer SSL certificate verification. See
+L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enable or disable peer host name verification. If enabled, the plugin checks
+if the C<Common Name> or a C<Subject Alternate Name> field of the SSL
+certificate matches the host name provided by the B<URL> option. If this
+identity check fails, the connection is aborted. Obviously, only works when
+connecting to a SSL enabled server. Enabled by default.
+
+=item B<CACert> I<File>
+
+File that holds one or more SSL certificates. If you want to use HTTPS you will
+possibly need this option. What CA certificates come bundled with C<libcurl>
+and are checked by default depends on the distribution you use.
+
+=item B<Timeout> I<Milliseconds>
+
+The B<Timeout> option sets the overall timeout for HTTP requests to B<URL>, in
+milliseconds. By default, the configured B<Interval> is used to set the
+timeout.
+
+=back
+
+=head2 Plugin C<notify_desktop>
+
+This plugin sends a desktop notification to a notification daemon, as defined
+in the Desktop Notification Specification. To actually display the
+notifications, B<notification-daemon> is required and B<collectd> has to be
+able to access the X server (i.E<nbsp>e., the C<DISPLAY> and C<XAUTHORITY>
+environment variables have to be set correctly) and the D-Bus message bus.
+
+The Desktop Notification Specification can be found at
+L<http://www.galago-project.org/specs/notification/>.
+
+=over 4
+
+=item B<OkayTimeout> I<timeout>
+
+=item B<WarningTimeout> I<timeout>
+
+=item B<FailureTimeout> I<timeout>
+
+Set the I<timeout>, in milliseconds, after which to expire the notification
+for C<OKAY>, C<WARNING> and C<FAILURE> severities respectively. If zero has
+been specified, the displayed notification will not be closed at all - the
+user has to do so herself. These options default to 5000. If a negative number
+has been specified, the default is used as well.
+
+=back
+
+=head2 Plugin C<notify_email>
+
+The I<notify_email> plugin uses the I<ESMTP> library to send notifications to a
+configured email address.
+
+I<libESMTP> is available from L<http://www.stafford.uklinux.net/libesmtp/>.
+
+Available configuration options:
+
+=over 4
+
+=item B<From> I<Address>
+
+Email address from which the emails should appear to come from.
+
+Default: C<root@localhost>
+
+=item B<Recipient> I<Address>
+
+Configures the email address(es) to which the notifications should be mailed.
+May be repeated to send notifications to multiple addresses.
+
+At least one B<Recipient> must be present for the plugin to work correctly.
+
+=item B<SMTPServer> I<Hostname>
+
+Hostname of the SMTP server to connect to.
+
+Default: C<localhost>
+
+=item B<SMTPPort> I<Port>
+
+TCP port to connect to.
+
+Default: C<25>
+
+=item B<SMTPUser> I<Username>
+
+Username for ASMTP authentication. Optional.
+
+=item B<SMTPPassword> I<Password>
+
+Password for ASMTP authentication. Optional.
+
+=item B<Subject> I<Subject>
+
+Subject-template to use when sending emails. There must be exactly two
+string-placeholders in the subject, given in the standard I<printf(3)> syntax,
+i.E<nbsp>e. C<%s>. The first will be replaced with the severity, the second
+with the hostname.
+
+Default: C<Collectd notify: %s@%s>
+
+=back
+
+=head2 Plugin C<ntpd>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the host running B<ntpd>. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+UDP-Port to connect to. Defaults to B<123>.
+
+=item B<ReverseLookups> B<true>|B<false>
+
+Sets whether or not to perform reverse lookups on peers. Since the name or
+IP-address may be used in a filename it is recommended to disable reverse
+lookups. The default is to do reverse lookups to preserve backwards
+compatibility, though.
+
+=item B<IncludeUnitID> B<true>|B<false>
+
+When a peer is a refclock, include the unit ID in the I<type instance>.
+Defaults to B<false> for backward compatibility.
+
+If two refclock peers use the same driver and this is B<false>, the plugin will
+try to write simultaneous measurements from both to the same type instance.
+This will result in error messages in the log and only one set of measurements
+making it through.
+
+=back
+
+=head2 Plugin C<nut>
+
+=over 4
+
+=item B<UPS> I<upsname>B<@>I<hostname>[B<:>I<port>]
+
+Add a UPS to collect data from. The format is identical to the one accepted by
+L<upsc(8)>.
+
+=back
+
+=head2 Plugin C<olsrd>
+
+The I<olsrd> plugin connects to the TCP port opened by the I<txtinfo> plugin of
+the Optimized Link State Routing daemon and reads information about the current
+state of the meshed network.
+
+The following configuration options are understood:
+
+=over 4
+
+=item B<Host> I<Host>
+
+Connect to I<Host>. Defaults to B<"localhost">.
+
+=item B<Port> I<Port>
+
+Specifies the port to connect to. This must be a string, even if you give the
+port as a number rather than a service name. Defaults to B<"2006">.
+
+=item B<CollectLinks> B<No>|B<Summary>|B<Detail>
+
+Specifies what information to collect about links, i.E<nbsp>e. direct
+connections of the daemon queried. If set to B<No>, no information is
+collected. If set to B<Summary>, the number of links and the average of all
+I<link quality> (LQ) and I<neighbor link quality> (NLQ) values is calculated.
+If set to B<Detail> LQ and NLQ are collected per link.
+
+Defaults to B<Detail>.
+
+=item B<CollectRoutes> B<No>|B<Summary>|B<Detail>
+
+Specifies what information to collect about routes of the daemon queried. If
+set to B<No>, no information is collected. If set to B<Summary>, the number of
+routes and the average I<metric> and I<ETX> is calculated. If set to B<Detail>
+metric and ETX are collected per route.
+
+Defaults to B<Summary>.
+
+=item B<CollectTopology> B<No>|B<Summary>|B<Detail>
+
+Specifies what information to collect about the global topology. If set to
+B<No>, no information is collected. If set to B<Summary>, the number of links
+in the entire topology and the average I<link quality> (LQ) is calculated.
+If set to B<Detail> LQ and NLQ are collected for each link in the entire topology.
+
+Defaults to B<Summary>.
+
+=back
+
+=head2 Plugin C<onewire>
+
+B<EXPERIMENTAL!> See notes below.
+
+The C<onewire> plugin uses the B<owcapi> library from the B<owfs> project
+L<http://owfs.org/> to read sensors connected via the onewire bus.
+
+It can be used in two possible modes - standard or advanced.
+
+In the standard mode only temperature sensors (sensors with the family code
+C<10>, C<22> and C<28> - e.g. DS1820, DS18S20, DS1920) can be read. If you have
+other sensors you would like to have included, please send a sort request to
+the mailing list. You can select sensors to be read or to be ignored depending
+on the option B<IgnoreSelected>). When no list is provided the whole bus is
+walked and all sensors are read.
+
+Hubs (the DS2409 chips) are working, but read the note, why this plugin is
+experimental, below.
+
+In the advanced mode you can configure any sensor to be read (only numerical
+value) using full OWFS path (e.g. "/uncached/10.F10FCA000800/temperature").
+In this mode you have to list all the sensors. Neither default bus walk nor
+B<IgnoreSelected> are used here. Address and type (file) is extracted from
+the path automatically and should produce compatible structure with the "standard"
+mode (basically the path is expected as for example
+"/uncached/10.F10FCA000800/temperature" where it would extract address part
+"F10FCA000800" and the rest after the slash is considered the type - here
+"temperature").
+There are two advantages to this mode - you can access virtually any sensor
+(not just temperature), select whether to use cached or directly read values
+and it is slighlty faster. The downside is more complex configuration.
+
+The two modes are distinguished automatically by the format of the address.
+It is not possible to mix the two modes. Once a full path is detected in any
+B<Sensor> then the whole addressing (all sensors) is considered to be this way
+(and as standard addresses will fail parsing they will be ignored).
+
+=over 4
+
+=item B<Device> I<Device>
+
+Sets the device to read the values from. This can either be a "real" hardware
+device, such as a serial port or an USB port, or the address of the
+L<owserver(1)> socket, usually B<localhost:4304>.
+
+Though the documentation claims to automatically recognize the given address
+format, with versionE<nbsp>2.7p4 we had to specify the type explicitly. So
+with that version, the following configuration worked for us:
+
+  <Plugin onewire>
+    Device "-s localhost:4304"
+  </Plugin>
+
+This directive is B<required> and does not have a default value.
+
+=item B<Sensor> I<Sensor>
+
+In the standard mode selects sensors to collect or to ignore
+(depending on B<IgnoreSelected>, see below). Sensors are specified without
+the family byte at the beginning, so you have to use for example C<F10FCA000800>,
+and B<not> include the leading C<10.> family byte and point.
+When no B<Sensor> is configured the whole Onewire bus is walked and all supported
+sensors (see above) are read.
+
+In the advanced mode the B<Sensor> specifies full OWFS path - e.g.
+C</uncached/10.F10FCA000800/temperature> (or when cached values are OK
+C</10.F10FCA000800/temperature>). B<IgnoreSelected> is not used.
+
+As there can be multiple devices on the bus you can list multiple sensor (use
+multiple B<Sensor> elements).
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+If no configuration is given, the B<onewire> plugin will collect data from all
+sensors found. This may not be practical, especially if sensors are added and
+removed regularly. Sometimes, however, it's easier/preferred to collect only
+specific sensors or all sensors I<except> a few specified ones. This option
+enables you to do that: By setting B<IgnoreSelected> to I<true> the effect of
+B<Sensor> is inverted: All selected interfaces are ignored and all other
+interfaces are collected.
+
+Used only in the standard mode - see above.
+
+=item B<Interval> I<Seconds>
+
+Sets the interval in which all sensors should be read. If not specified, the
+global B<Interval> setting is used.
+
+=back
+
+B<EXPERIMENTAL!> The C<onewire> plugin is experimental, because it doesn't yet
+work with big setups. It works with one sensor being attached to one
+controller, but as soon as you throw in a couple more senors and maybe a hub
+or two, reading all values will take more than ten seconds (the default
+interval). We will probably add some separate thread for reading the sensors
+and some cache or something like that, but it's not done yet. We will try to
+maintain backwards compatibility in the future, but we can't promise. So in
+short: If it works for you: Great! But keep in mind that the config I<might>
+change, though this is unlikely. Oh, and if you want to help improving this
+plugin, just send a short notice to the mailing list. ThanksE<nbsp>:)
+
+=head2 Plugin C<openldap>
+
+To use the C<openldap> plugin you first need to configure the I<OpenLDAP>
+server correctly. The backend database C<monitor> needs to be loaded and
+working. See slapd-monitor(5) for the details.
+
+The configuration of the C<openldap> plugin consists of one or more B<Instance>
+blocks. Each block requires one string argument as the instance name. For
+example:
+
+ <Plugin "openldap">
+   <Instance "foo">
+     URL "ldap://localhost/"
+   </Instance>
+   <Instance "bar">
+     URL "ldaps://localhost/"
+   </Instance>
+ </Plugin>
+
+The instance name will be used as the I<plugin instance>. To emulate the old
+(versionE<nbsp>4) behavior, you can use an empty string (""). In order for the
+plugin to work correctly, each instance name must be unique. This is not
+enforced by the plugin and it is your responsibility to ensure it is.
+
+The following options are accepted within each B<Instance> block:
+
+=over 4
+
+=item B<URL> I<ldap://host/binddn>
+
+Sets the URL to use to connect to the I<OpenLDAP> server. This option is
+I<mandatory>.
+
+=item B<StartTLS> B<true|false>
+
+Defines whether TLS must be used when connecting to the I<OpenLDAP> server.
+Disabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enables or disables peer host name verification. If enabled, the plugin checks
+if the C<Common Name> or a C<Subject Alternate Name> field of the SSL
+certificate matches the host name provided by the B<URL> option. If this
+identity check fails, the connection is aborted. Enabled by default.
+
+=item B<CACert> I<File>
+
+File that holds one or more SSL certificates. If you want to use TLS/SSL you
+may possibly need this option. What CA certificates are checked by default
+depends on the distribution you use and can be changed with the usual ldap
+client configuration mechanisms. See ldap.conf(5) for the details.
+
+=item B<Timeout> I<Seconds>
+
+Sets the timeout value for ldap operations. Defaults to B<-1> which results in
+an infinite timeout.
+
+=item B<Version> I<Version>
+
+An integer which sets the LDAP protocol version number to use when connecting
+to the I<OpenLDAP> server. Defaults to B<3> for using I<LDAPv3>.
+
+=back
+
+=head2 Plugin C<openvpn>
+
+The OpenVPN plugin reads a status file maintained by OpenVPN and gathers
+traffic statistics about connected clients.
+
+To set up OpenVPN to write to the status file periodically, use the
+B<--status> option of OpenVPN. Since OpenVPN can write two different formats,
+you need to set the required format, too. This is done by setting
+B<--status-version> to B<2>.
+
+So, in a nutshell you need:
+
+  openvpn $OTHER_OPTIONS \
+    --status "/var/run/openvpn-status" 10 \
+    --status-version 2
+
+Available options:
+
+=over 4
+
+=item B<StatusFile> I<File>
+
+Specifies the location of the status file.
+
+=item B<ImprovedNamingSchema> B<true>|B<false>
+
+When enabled, the filename of the status file will be used as plugin instance
+and the client's "common name" will be used as type instance. This is required
+when reading multiple status files. Enabling this option is recommended, but to
+maintain backwards compatibility this option is disabled by default.
+
+=item B<CollectCompression> B<true>|B<false>
+
+Sets whether or not statistics about the compression used by OpenVPN should be
+collected. This information is only available in I<single> mode. Enabled by
+default.
+
+=item B<CollectIndividualUsers> B<true>|B<false>
+
+Sets whether or not traffic information is collected for each connected client
+individually. If set to false, currently no traffic data is collected at all
+because aggregating this data in a save manner is tricky. Defaults to B<true>.
+
+=item B<CollectUserCount> B<true>|B<false>
+
+When enabled, the number of currently connected clients or users is collected.
+This is especially interesting when B<CollectIndividualUsers> is disabled, but
+can be configured independently from that option. Defaults to B<false>.
+
+=back
+
+=head2 Plugin C<oracle>
+
+The "oracle" plugin uses the Oracle® Call Interface I<(OCI)> to connect to an
+Oracle® Database and lets you execute SQL statements there. It is very similar
+to the "dbi" plugin, because it was written around the same time. See the "dbi"
+plugin's documentation above for details.
+
+  <Plugin oracle>
+    <Query "out_of_stock">
+      Statement "SELECT category, COUNT(*) AS value FROM products WHERE in_stock = 0 GROUP BY category"
+      <Result>
+        Type "gauge"
+        # InstancePrefix "foo"
+        InstancesFrom "category"
+        ValuesFrom "value"
+      </Result>
+    </Query>
+    <Database "product_information">
+      ConnectID "db01"
+      Username "oracle"
+      Password "secret"
+      Query "out_of_stock"
+    </Database>
+  </Plugin>
+
+=head3 B<Query> blocks
+
+The Query blocks are handled identically to the Query blocks of the "dbi"
+plugin. Please see its documentation above for details on how to specify
+queries.
+
+=head3 B<Database> blocks
+
+Database blocks define a connection to a database and which queries should be
+sent to that database. Each database needs a "name" as string argument in the
+starting tag of the block. This name will be used as "PluginInstance" in the
+values submitted to the daemon. Other than that, that name is not used.
+
+=over 4
+
+=item B<ConnectID> I<ID>
+
+Defines the "database alias" or "service name" to connect to. Usually, these
+names are defined in the file named C<$ORACLE_HOME/network/admin/tnsnames.ora>.
+
+=item B<Host> I<Host>
+
+Hostname to use when dispatching values for this database. Defaults to using
+the global hostname of the I<collectd> instance.
+
+=item B<Username> I<Username>
+
+Username used for authentication.
+
+=item B<Password> I<Password>
+
+Password used for authentication.
+
+=item B<Query> I<QueryName>
+
+Associates the query named I<QueryName> with this database connection. The
+query needs to be defined I<before> this statement, i.E<nbsp>e. all query
+blocks you want to refer to must be placed above the database block you want to
+refer to them from.
+
+=back
+
+=head2 Plugin C<perl>
+
+This plugin embeds a Perl-interpreter into collectd and provides an interface
+to collectd's plugin system. See L<collectd-perl(5)> for its documentation.
+
+=head2 Plugin C<pinba>
+
+The I<Pinba plugin> receives profiling information from I<Pinba>, an extension
+for the I<PHP> interpreter. At the end of executing a script, i.e. after a
+PHP-based webpage has been delivered, the extension will send a UDP packet
+containing timing information, peak memory usage and so on. The plugin will
+wait for such packets, parse them and account the provided information, which
+is then dispatched to the daemon once per interval.
+
+Synopsis:
+
+ <Plugin pinba>
+   Address "::0"
+   Port "30002"
+   # Overall statistics for the website.
+   <View "www-total">
+     Server "www.example.com"
+   </View>
+   # Statistics for www-a only
+   <View "www-a">
+     Host "www-a.example.com"
+     Server "www.example.com"
+   </View>
+   # Statistics for www-b only
+   <View "www-b">
+     Host "www-b.example.com"
+     Server "www.example.com"
+   </View>
+ </Plugin>
+
+The plugin provides the following configuration options:
+
+=over 4
+
+=item B<Address> I<Node>
+
+Configures the address used to open a listening socket. By default, plugin will
+bind to the I<any> address C<::0>.
+
+=item B<Port> I<Service>
+
+Configures the port (service) to bind to. By default the default Pinba port
+"30002" will be used. The option accepts service names in addition to port
+numbers and thus requires a I<string> argument.
+
+=item E<lt>B<View> I<Name>E<gt> block
+
+The packets sent by the Pinba extension include the hostname of the server, the
+server name (the name of the virtual host) and the script that was executed.
+Using B<View> blocks it is possible to separate the data into multiple groups
+to get more meaningful statistics. Each packet is added to all matching groups,
+so that a packet may be accounted for more than once.
+
+=over 4
+
+=item B<Host> I<Host>
+
+Matches the hostname of the system the webserver / script is running on. This
+will contain the result of the L<gethostname(2)> system call. If not
+configured, all hostnames will be accepted.
+
+=item B<Server> I<Server>
+
+Matches the name of the I<virtual host>, i.e. the contents of the
+C<$_SERVER["SERVER_NAME"]> variable when within PHP. If not configured, all
+server names will be accepted.
+
+=item B<Script> I<Script>
+
+Matches the name of the I<script name>, i.e. the contents of the
+C<$_SERVER["SCRIPT_NAME"]> variable when within PHP. If not configured, all
+script names will be accepted.
+
+=back
+
+=back
+
+=head2 Plugin C<ping>
+
+The I<Ping> plugin starts a new thread which sends ICMP "ping" packets to the
+configured hosts periodically and measures the network latency. Whenever the
+C<read> function of the plugin is called, it submits the average latency, the
+standard deviation and the drop rate for each host.
+
+Available configuration options:
+
+=over 4
+
+=item B<Host> I<IP-address>
+
+Host to ping periodically. This option may be repeated several times to ping
+multiple hosts.
+
+=item B<Interval> I<Seconds>
+
+Sets the interval in which to send ICMP echo packets to the configured hosts.
+This is B<not> the interval in which statistics are queries from the plugin but
+the interval in which the hosts are "pinged". Therefore, the setting here
+should be smaller than or equal to the global B<Interval> setting. Fractional
+times, such as "1.24" are allowed.
+
+Default: B<1.0>
+
+=item B<Timeout> I<Seconds>
+
+Time to wait for a response from the host to which an ICMP packet had been
+sent. If a reply was not received after I<Seconds> seconds, the host is assumed
+to be down or the packet to be dropped. This setting must be smaller than the
+B<Interval> setting above for the plugin to work correctly. Fractional
+arguments are accepted.
+
+Default: B<0.9>
+
+=item B<TTL> I<0-255>
+
+Sets the Time-To-Live of generated ICMP packets.
+
+=item B<SourceAddress> I<host>
+
+Sets the source address to use. I<host> may either be a numerical network
+address or a network hostname.
+
+=item B<Device> I<name>
+
+Sets the outgoing network device to be used. I<name> has to specify an
+interface name (e.E<nbsp>g. C<eth0>). This might not be supported by all
+operating systems.
+
+=item B<MaxMissed> I<Packets>
+
+Trigger a DNS resolve after the host has not replied to I<Packets> packets. This
+enables the use of dynamic DNS services (like dyndns.org) with the ping plugin.
+
+Default: B<-1> (disabled)
+
+=back
+
+=head2 Plugin C<postgresql>
+
+The C<postgresql> plugin queries statistics from PostgreSQL databases. It
+keeps a persistent connection to all configured databases and tries to
+reconnect if the connection has been interrupted. A database is configured by
+specifying a B<Database> block as described below. The default statistics are
+collected from PostgreSQL's B<statistics collector> which thus has to be
+enabled for this plugin to work correctly. This should usually be the case by
+default. See the section "The Statistics Collector" of the B<PostgreSQL
+Documentation> for details.
+
+By specifying custom database queries using a B<Query> block as described
+below, you may collect any data that is available from some PostgreSQL
+database. This way, you are able to access statistics of external daemons
+which are available in a PostgreSQL database or use future or special
+statistics provided by PostgreSQL without the need to upgrade your collectd
+installation.
+
+Starting with version 5.2, the C<postgresql> plugin supports writing data to
+PostgreSQL databases as well. This has been implemented in a generic way. You
+need to specify an SQL statement which will then be executed by collectd in
+order to write the data (see below for details). The benefit of that approach
+is that there is no fixed database layout. Rather, the layout may be optimized
+for the current setup.
+
+The B<PostgreSQL Documentation> manual can be found at
+L<http://www.postgresql.org/docs/manuals/>.
+
+  <Plugin postgresql>
+    <Query magic>
+      Statement "SELECT magic FROM wizard WHERE host = $1;"
+      Param hostname
+      <Result>
+        Type gauge
+        InstancePrefix "magic"
+        ValuesFrom magic
+      </Result>
+    </Query>
+
+    <Query rt36_tickets>
+      Statement "SELECT COUNT(type) AS count, type \
+                        FROM (SELECT CASE \
+                                     WHEN resolved = 'epoch' THEN 'open' \
+                                     ELSE 'resolved' END AS type \
+                                     FROM tickets) type \
+                        GROUP BY type;"
+      <Result>
+        Type counter
+        InstancePrefix "rt36_tickets"
+        InstancesFrom "type"
+        ValuesFrom "count"
+      </Result>
+    </Query>
+
+    <Writer sqlstore>
+      Statement "SELECT collectd_insert($1, $2, $3, $4, $5, $6, $7, $8, $9);"
+      StoreRates true
+    </Writer>
+
+    <Database foo>
+      Host "hostname"
+      Port "5432"
+      User "username"
+      Password "secret"
+      SSLMode "prefer"
+      KRBSrvName "kerberos_service_name"
+      Query magic
+    </Database>
+
+    <Database bar>
+      Interval 300
+      Service "service_name"
+      Query backend # predefined
+      Query rt36_tickets
+    </Database>
+
+    <Database qux>
+      # ...
+      Writer sqlstore
+      CommitInterval 10
+    </Database>
+  </Plugin>
+
+The B<Query> block defines one database query which may later be used by a
+database definition. It accepts a single mandatory argument which specifies
+the name of the query. The names of all queries have to be unique (see the
+B<MinVersion> and B<MaxVersion> options below for an exception to this
+rule). The following configuration options are available to define the query:
+
+In each B<Query> block, there is one or more B<Result> blocks. B<Result>
+blocks define how to handle the values returned from the query. They define
+which column holds which value and how to dispatch that value to the daemon.
+Multiple B<Result> blocks may be used to extract multiple values from a single
+query.
+
+=over 4
+
+=item B<Statement> I<sql query statement>
+
+Specify the I<sql query statement> which the plugin should execute. The string
+may contain the tokens B<$1>, B<$2>, etc. which are used to reference the
+first, second, etc. parameter. The value of the parameters is specified by the
+B<Param> configuration option - see below for details. To include a literal
+B<$> character followed by a number, surround it with single quotes (B<'>).
+
+Any SQL command which may return data (such as C<SELECT> or C<SHOW>) is
+allowed. Note, however, that only a single command may be used. Semicolons are
+allowed as long as a single non-empty command has been specified only.
+
+The returned lines will be handled separately one after another.
+
+=item B<Param> I<hostname>|I<database>|I<username>|I<interval>
+
+Specify the parameters which should be passed to the SQL query. The parameters
+are referred to in the SQL query as B<$1>, B<$2>, etc. in the same order as
+they appear in the configuration file. The value of the parameter is
+determined depending on the value of the B<Param> option as follows:
+
+=over 4
+
+=item I<hostname>
+
+The configured hostname of the database connection. If a UNIX domain socket is
+used, the parameter expands to "localhost".
+
+=item I<database>
+
+The name of the database of the current connection.
+
+=item I<instance>
+
+The name of the database plugin instance. See the B<Instance> option of the
+database specification below for details.
+
+=item I<username>
+
+The username used to connect to the database.
+
+=item I<interval>
+
+The interval with which this database is queried (as specified by the database
+specific or global B<Interval> options).
+
+=back
+
+Please note that parameters are only supported by PostgreSQL's protocol
+version 3 and above which was introduced in version 7.4 of PostgreSQL.
+
+=item B<Type> I<type>
+
+The I<type> name to be used when dispatching the values. The type describes
+how to handle the data and where to store it. See L<types.db(5)> for more
+details on types and their configuration. The number and type of values (as
+selected by the B<ValuesFrom> option) has to match the type of the given name.
+
+This option is required inside a B<Result> block.
+
+=item B<InstancePrefix> I<prefix>
+
+=item B<InstancesFrom> I<column0> [I<column1> ...]
+
+Specify how to create the "TypeInstance" for each data set (i.E<nbsp>e. line).
+B<InstancePrefix> defines a static prefix that will be prepended to all type
+instances. B<InstancesFrom> defines the column names whose values will be used
+to create the type instance. Multiple values will be joined together using the
+hyphen (C<->) as separation character.
+
+The plugin itself does not check whether or not all built instances are
+different. It is your responsibility to assure that each is unique.
+
+Both options are optional. If none is specified, the type instance will be
+empty.
+
+=item B<ValuesFrom> I<column0> [I<column1> ...]
+
+Names the columns whose content is used as the actual data for the data sets
+that are dispatched to the daemon. How many such columns you need is
+determined by the B<Type> setting as explained above. If you specify too many
+or not enough columns, the plugin will complain about that and no data will be
+submitted to the daemon.
+
+The actual data type, as seen by PostgreSQL, is not that important as long as
+it represents numbers. The plugin will automatically cast the values to the
+right type if it know how to do that. For that, it uses the L<strtoll(3)> and
+L<strtod(3)> functions, so anything supported by those functions is supported
+by the plugin as well.
+
+This option is required inside a B<Result> block and may be specified multiple
+times. If multiple B<ValuesFrom> options are specified, the columns are read
+in the given order.
+
+=item B<MinVersion> I<version>
+
+=item B<MaxVersion> I<version>
+
+Specify the minimum or maximum version of PostgreSQL that this query should be
+used with. Some statistics might only be available with certain versions of
+PostgreSQL. This allows you to specify multiple queries with the same name but
+which apply to different versions, thus allowing you to use the same
+configuration in a heterogeneous environment.
+
+The I<version> has to be specified as the concatenation of the major, minor
+and patch-level versions, each represented as two-decimal-digit numbers. For
+example, version 8.2.3 will become 80203.
+
+=back
+
+The following predefined queries are available (the definitions can be found
+in the F<postgresql_default.conf> file which, by default, is available at
+C<I<prefix>/share/collectd/>):
+
+=over 4
+
+=item B<backends>
+
+This query collects the number of backends, i.E<nbsp>e. the number of
+connected clients.
+
+=item B<transactions>
+
+This query collects the numbers of committed and rolled-back transactions of
+the user tables.
+
+=item B<queries>
+
+This query collects the numbers of various table modifications (i.E<nbsp>e.
+insertions, updates, deletions) of the user tables.
+
+=item B<query_plans>
+
+This query collects the numbers of various table scans and returned tuples of
+the user tables.
+
+=item B<table_states>
+
+This query collects the numbers of live and dead rows in the user tables.
+
+=item B<disk_io>
+
+This query collects disk block access counts for user tables.
+
+=item B<disk_usage>
+
+This query collects the on-disk size of the database in bytes.
+
+=back
+
+In addition, the following detailed queries are available by default. Please
+note that each of those queries collects information B<by table>, thus,
+potentially producing B<a lot> of data. For details see the description of the
+non-by_table queries above.
+
+=over 4
+
+=item B<queries_by_table>
+
+=item B<query_plans_by_table>
+
+=item B<table_states_by_table>
+
+=item B<disk_io_by_table>
+
+=back
+
+The B<Writer> block defines a PostgreSQL writer backend. It accepts a single
+mandatory argument specifying the name of the writer. This will then be used
+in the B<Database> specification in order to activate the writer instance. The
+names of all writers have to be unique. The following options may be
+specified:
+
+=over 4
+
+=item B<Statement> I<sql statement>
+
+This mandatory option specifies the SQL statement that will be executed for
+each submitted value. A single SQL statement is allowed only. Anything after
+the first semicolon will be ignored.
+
+Nine parameters will be passed to the statement and should be specified as
+tokens B<$1>, B<$2>, through B<$9> in the statement string. The following
+values are made available through those parameters:
+
+=over 4
+
+=item B<$1>
+
+The timestamp of the queried value as a floating point number.
+
+=item B<$2>
+
+The hostname of the queried value.
+
+=item B<$3>
+
+The plugin name of the queried value.
+
+=item B<$4>
+
+The plugin instance of the queried value. This value may be B<NULL> if there
+is no plugin instance.
+
+=item B<$5>
+
+The type of the queried value (cf. L<types.db(5)>).
+
+=item B<$6>
+
+The type instance of the queried value. This value may be B<NULL> if there is
+no type instance.
+
+=item B<$7>
+
+An array of names for the submitted values (i.E<nbsp>e., the name of the data
+sources of the submitted value-list).
+
+=item B<$8>
+
+An array of types for the submitted values (i.E<nbsp>e., the type of the data
+sources of the submitted value-list; C<counter>, C<gauge>, ...). Note, that if
+B<StoreRates> is enabled (which is the default, see below), all types will be
+C<gauge>.
+
+=item B<$9>
+
+An array of the submitted values. The dimensions of the value name and value
+arrays match.
+
+=back
+
+In general, it is advisable to create and call a custom function in the
+PostgreSQL database for this purpose. Any procedural language supported by
+PostgreSQL will do (see chapter "Server Programming" in the PostgreSQL manual
+for details).
+
+=item B<StoreRates> B<false>|B<true>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.E<nbsp>e. as an increasing integer
+number.
+
+=back
+
+The B<Database> block defines one PostgreSQL database for which to collect
+statistics. It accepts a single mandatory argument which specifies the
+database name. None of the other options are required. PostgreSQL will use
+default values as documented in the section "CONNECTING TO A DATABASE" in the
+L<psql(1)> manpage. However, be aware that those defaults may be influenced by
+the user collectd is run as and special environment variables. See the manpage
+for details.
+
+=over 4
+
+=item B<Interval> I<seconds>
+
+Specify the interval with which the database should be queried. The default is
+to use the global B<Interval> setting.
+
+=item B<CommitInterval> I<seconds>
+
+This option may be used for database connections which have "writers" assigned
+(see above). If specified, it causes a writer to put several updates into a
+single transaction. This transaction will last for the specified amount of
+time. By default, each update will be executed in a separate transaction. Each
+transaction generates a fair amount of overhead which can, thus, be reduced by
+activating this option. The draw-back is, that data covering the specified
+amount of time will be lost, for example, if a single statement within the
+transaction fails or if the database server crashes.
+
+=item B<Instance> I<name>
+
+Specify the plugin instance name that should be used instead of the database
+name (which is the default, if this option has not been specified). This
+allows to query multiple databases of the same name on the same host (e.g.
+when running multiple database server versions in parallel).
+
+=item B<Host> I<hostname>
+
+Specify the hostname or IP of the PostgreSQL server to connect to. If the
+value begins with a slash, it is interpreted as the directory name in which to
+look for the UNIX domain socket.
+
+This option is also used to determine the hostname that is associated with a
+collected data set. If it has been omitted or either begins with with a slash
+or equals B<localhost> it will be replaced with the global hostname definition
+of collectd. Any other value will be passed literally to collectd when
+dispatching values. Also see the global B<Hostname> and B<FQDNLookup> options.
+
+=item B<Port> I<port>
+
+Specify the TCP port or the local UNIX domain socket file extension of the
+server.
+
+=item B<User> I<username>
+
+Specify the username to be used when connecting to the server.
+
+=item B<Password> I<password>
+
+Specify the password to be used when connecting to the server.
+
+=item B<ExpireDelay> I<delay>
+
+Skip expired values in query output.
+
+=item B<SSLMode> I<disable>|I<allow>|I<prefer>|I<require>
+
+Specify whether to use an SSL connection when contacting the server. The
+following modes are supported:
+
+=over 4
+
+=item I<disable>
+
+Do not use SSL at all.
+
+=item I<allow>
+
+First, try to connect without using SSL. If that fails, try using SSL.
+
+=item I<prefer> (default)
+
+First, try to connect using SSL. If that fails, try without using SSL.
+
+=item I<require>
+
+Use SSL only.
+
+=back
+
+=item B<Instance> I<name>
+
+Specify the plugin instance name that should be used instead of the database
+name (which is the default, if this option has not been specified). This
+allows to query multiple databases of the same name on the same host (e.g.
+when running multiple database server versions in parallel).
+
+=item B<KRBSrvName> I<kerberos_service_name>
+
+Specify the Kerberos service name to use when authenticating with Kerberos 5
+or GSSAPI. See the sections "Kerberos authentication" and "GSSAPI" of the
+B<PostgreSQL Documentation> for details.
+
+=item B<Service> I<service_name>
+
+Specify the PostgreSQL service name to use for additional parameters. That
+service has to be defined in F<pg_service.conf> and holds additional
+connection parameters. See the section "The Connection Service File" in the
+B<PostgreSQL Documentation> for details.
+
+=item B<Query> I<query>
+
+Specifies a I<query> which should be executed in the context of the database
+connection. This may be any of the predefined or user-defined queries. If no
+such option is given, it defaults to "backends", "transactions", "queries",
+"query_plans", "table_states", "disk_io" and "disk_usage" (unless a B<Writer>
+has been specified). Else, the specified queries are used only.
+
+=item B<Writer> I<writer>
+
+Assigns the specified I<writer> backend to the database connection. This
+causes all collected data to be send to the database using the settings
+defined in the writer configuration (see the section "FILTER CONFIGURATION"
+below for details on how to selectively send data to certain plugins).
+
+Each writer will register a flush callback which may be used when having long
+transactions enabled (see the B<CommitInterval> option above). When issuing
+the B<FLUSH> command (see L<collectd-unixsock(5)> for details) the current
+transaction will be committed right away. Two different kinds of flush
+callbacks are available with the C<postgresql> plugin:
+
+=over 4
+
+=item B<postgresql>
+
+Flush all writer backends.
+
+=item B<postgresql->I<database>
+
+Flush all writers of the specified I<database> only.
+
+=back
+
+=back
+
+=head2 Plugin C<powerdns>
+
+The C<powerdns> plugin queries statistics from an authoritative PowerDNS
+nameserver and/or a PowerDNS recursor. Since both offer a wide variety of
+values, many of which are probably meaningless to most users, but may be useful
+for some. So you may chose which values to collect, but if you don't, some
+reasonable defaults will be collected.
+
+  <Plugin "powerdns">
+    <Server "server_name">
+      Collect "latency"
+      Collect "udp-answers" "udp-queries"
+      Socket "/var/run/pdns.controlsocket"
+    </Server>
+    <Recursor "recursor_name">
+      Collect "questions"
+      Collect "cache-hits" "cache-misses"
+      Socket "/var/run/pdns_recursor.controlsocket"
+    </Recursor>
+    LocalSocket "/opt/collectd/var/run/collectd-powerdns"
+  </Plugin>
+
+=over 4
+
+=item B<Server> and B<Recursor> block
+
+The B<Server> block defines one authoritative server to query, the B<Recursor>
+does the same for an recursing server. The possible options in both blocks are
+the same, though. The argument defines a name for the serverE<nbsp>/ recursor
+and is required.
+
+=over 4
+
+=item B<Collect> I<Field>
+
+Using the B<Collect> statement you can select which values to collect. Here,
+you specify the name of the values as used by the PowerDNS servers, e.E<nbsp>g.
+C<dlg-only-drops>, C<answers10-100>.
+
+The method of getting the values differs for B<Server> and B<Recursor> blocks:
+When querying the server a C<SHOW *> command is issued in any case, because
+that's the only way of getting multiple values out of the server at once.
+collectd then picks out the values you have selected. When querying the
+recursor, a command is generated to query exactly these values. So if you
+specify invalid fields when querying the recursor, a syntax error may be
+returned by the daemon and collectd may not collect any values at all.
+
+If no B<Collect> statement is given, the following B<Server> values will be
+collected:
+
+=over 4
+
+=item latency
+
+=item packetcache-hit
+
+=item packetcache-miss
+
+=item packetcache-size
+
+=item query-cache-hit
+
+=item query-cache-miss
+
+=item recursing-answers
+
+=item recursing-questions
+
+=item tcp-answers
+
+=item tcp-queries
+
+=item udp-answers
+
+=item udp-queries
+
+=back
+
+The following B<Recursor> values will be collected by default:
+
+=over 4
+
+=item noerror-answers
+
+=item nxdomain-answers
+
+=item servfail-answers
+
+=item sys-msec
+
+=item user-msec
+
+=item qa-latency
+
+=item cache-entries
+
+=item cache-hits
+
+=item cache-misses
+
+=item questions
+
+=back
+
+Please note that up to that point collectd doesn't know what values are
+available on the server and values that are added do not need a change of the
+mechanism so far. However, the values must be mapped to collectd's naming
+scheme, which is done using a lookup table that lists all known values. If
+values are added in the future and collectd does not know about them, you will
+get an error much like this:
+
+  powerdns plugin: submit: Not found in lookup table: foobar = 42
+
+In this case please file a bug report with the collectd team.
+
+=item B<Socket> I<Path>
+
+Configures the path to the UNIX domain socket to be used when connecting to the
+daemon. By default C<${localstatedir}/run/pdns.controlsocket> will be used for
+an authoritative server and C<${localstatedir}/run/pdns_recursor.controlsocket>
+will be used for the recursor.
+
+=back
+
+=item B<LocalSocket> I<Path>
+
+Querying the recursor is done using UDP. When using UDP over UNIX domain
+sockets, the client socket needs a name in the file system, too. You can set
+this local name to I<Path> using the B<LocalSocket> option. The default is
+C<I<prefix>/var/run/collectd-powerdns>.
+
+=back
+
+=head2 Plugin C<processes>
+
+=over 4
+
+=item B<Process> I<Name>
+
+Select more detailed statistics of processes matching this name. The statistics
+collected for these selected processes are size of the resident segment size
+(RSS), user- and system-time used, number of processes and number of threads,
+io data (where available) and minor and major pagefaults.
+
+=item B<ProcessMatch> I<name> I<regex>
+
+Similar to the B<Process> option this allows to select more detailed
+statistics of processes matching the specified I<regex> (see L<regex(7)> for
+details). The statistics of all matching processes are summed up and
+dispatched to the daemon using the specified I<name> as an identifier. This
+allows to "group" several processes together. I<name> must not contain
+slashes.
+
+=back
+
+=head2 Plugin C<protocols>
+
+Collects a lot of information about various network protocols, such as I<IP>,
+I<TCP>, I<UDP>, etc.
+
+Available configuration options:
+
+=over 4
+
+=item B<Value> I<Selector>
+
+Selects whether or not to select a specific value. The string being matched is
+of the form "I<Protocol>:I<ValueName>", where I<Protocol> will be used as the
+plugin instance and I<ValueName> will be used as type instance. An example of
+the string being used would be C<Tcp:RetransSegs>.
+
+You can use regular expressions to match a large number of values with just one
+configuration option. To select all "extended" I<TCP> values, you could use the
+following statement:
+
+  Value "/^TcpExt:/"
+
+Whether only matched values are selected or all matched values are ignored
+depends on the B<IgnoreSelected>. By default, only matched values are selected.
+If no value is configured at all, all values will be selected.
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+If set to B<true>, inverts the selection made by B<Value>, i.E<nbsp>e. all
+matching values will be ignored.
+
+=back
+
+=head2 Plugin C<python>
+
+This plugin embeds a Python-interpreter into collectd and provides an interface
+to collectd's plugin system. See L<collectd-python(5)> for its documentation.
+
+=head2 Plugin C<routeros>
+
+The C<routeros> plugin connects to a device running I<RouterOS>, the
+Linux-based operating system for routers by I<MikroTik>. The plugin uses
+I<librouteros> to connect and reads information about the interfaces and
+wireless connections of the device. The configuration supports querying
+multiple routers:
+
+  <Plugin "routeros">
+    <Router>
+      Host "router0.example.com"
+      User "collectd"
+      Password "secr3t"
+      CollectInterface true
+      CollectCPULoad true
+      CollectMemory true
+    </Router>
+    <Router>
+      Host "router1.example.com"
+      User "collectd"
+      Password "5ecret"
+      CollectInterface true
+      CollectRegistrationTable true
+      CollectDF true
+      CollectDisk true
+    </Router>
+  </Plugin>
+
+As you can see above, the configuration of the I<routeros> plugin consists of
+one or more B<E<lt>RouterE<gt>> blocks. Within each block, the following
+options are understood:
+
+=over 4
+
+=item B<Host> I<Host>
+
+Hostname or IP-address of the router to connect to.
+
+=item B<Port> I<Port>
+
+Port name or port number used when connecting. If left unspecified, the default
+will be chosen by I<librouteros>, currently "8728". This option expects a
+string argument, even when a numeric port number is given.
+
+=item B<User> I<User>
+
+Use the user name I<User> to authenticate. Defaults to "admin".
+
+=item B<Password> I<Password>
+
+Set the password used to authenticate.
+
+=item B<CollectInterface> B<true>|B<false>
+
+When set to B<true>, interface statistics will be collected for all interfaces
+present on the device. Defaults to B<false>.
+
+=item B<CollectRegistrationTable> B<true>|B<false>
+
+When set to B<true>, information about wireless LAN connections will be
+collected. Defaults to B<false>.
+
+=item B<CollectCPULoad> B<true>|B<false>
+
+When set to B<true>, information about the CPU usage will be collected. The
+number is a dimensionless value where zero indicates no CPU usage at all.
+Defaults to B<false>.
+
+=item B<CollectMemory> B<true>|B<false>
+
+When enabled, the amount of used and free memory will be collected. How used
+memory is calculated is unknown, for example whether or not caches are counted
+as used space.
+Defaults to B<false>.
+
+=item B<CollectDF> B<true>|B<false>
+
+When enabled, the amount of used and free disk space will be collected.
+Defaults to B<false>.
+
+=item B<CollectDisk> B<true>|B<false>
+
+When enabled, the number of sectors written and bad blocks will be collected.
+Defaults to B<false>.
+
+=back
+
+=head2 Plugin C<redis>
+
+The I<Redis plugin> connects to one or more Redis servers and gathers
+information about each server's state. For each server there is a I<Node> block
+which configures the connection parameters for this node.
+
+  <Plugin redis>
+    <Node "example">
+        Host "localhost"
+        Port "6379"
+        Timeout 2000
+        <Query "LLEN myqueue">
+          Type "queue_length"
+          Instance "myqueue"
+        <Query>
+    </Node>
+  </Plugin>
+
+The information shown in the synopsis above is the I<default configuration>
+which is used by the plugin if no configuration is present.
+
+=over 4
+
+=item B<Node> I<Nodename>
+
+The B<Node> block identifies a new Redis node, that is a new Redis instance
+running in an specified host and port. The name for node is a canonical
+identifier which is used as I<plugin instance>. It is limited to
+64E<nbsp>characters in length.
+
+=item B<Host> I<Hostname>
+
+The B<Host> option is the hostname or IP-address where the Redis instance is
+running on.
+
+=item B<Port> I<Port>
+
+The B<Port> option is the TCP port on which the Redis instance accepts
+connections. Either a service name of a port number may be given. Please note
+that numerical port numbers must be given as a string, too.
+
+=item B<Password> I<Password>
+
+Use I<Password> to authenticate when connecting to I<Redis>.
+
+=item B<Timeout> I<Milliseconds>
+
+The B<Timeout> option set the socket timeout for node response. Since the Redis
+read function is blocking, you should keep this value as low as possible. Keep
+in mind that the sum of all B<Timeout> values for all B<Nodes> should be lower
+than B<Interval> defined globally.
+
+=item B<Query> I<Querystring>
+
+The B<Query> block identifies a query to execute against the redis server.
+There may be an arbitrary number of queries to execute.
+
+=item B<Type> I<Collectd type>
+
+Within a query definition, a valid collectd type to use as when submitting
+the result of the query. When not supplied, will default to B<gauge>.
+
+=item B<Instance> I<Type instance>
+
+Within a query definition, an optional type instance to use when submitting
+the result of the query. When not supplied will default to the escaped
+command, up to 64 chars.
+
+=back
+
+=head2 Plugin C<rrdcached>
+
+The C<rrdcached> plugin uses the RRDtool accelerator daemon, L<rrdcached(1)>,
+to store values to RRD files in an efficient manner. The combination of the
+C<rrdcached> B<plugin> and the C<rrdcached> B<daemon> is very similar to the
+way the C<rrdtool> plugin works (see below). The added abstraction layer
+provides a number of benefits, though: Because the cache is not within
+C<collectd> anymore, it does not need to be flushed when C<collectd> is to be
+restarted. This results in much shorter (if any) gaps in graphs, especially
+under heavy load. Also, the C<rrdtool> command line utility is aware of the
+daemon so that it can flush values to disk automatically when needed. This
+allows to integrate automated flushing of values into graphing solutions much
+more easily.
+
+There are disadvantages, though: The daemon may reside on a different host, so
+it may not be possible for C<collectd> to create the appropriate RRD files
+anymore. And even if C<rrdcached> runs on the same host, it may run in a
+different base directory, so relative paths may do weird stuff if you're not
+careful.
+
+So the B<recommended configuration> is to let C<collectd> and C<rrdcached> run
+on the same host, communicating via a UNIX domain socket. The B<DataDir>
+setting should be set to an absolute path, so that a changed base directory
+does not result in RRD files being createdE<nbsp>/ expected in the wrong place.
+
+=over 4
+
+=item B<DaemonAddress> I<Address>
+
+Address of the daemon as understood by the C<rrdc_connect> function of the RRD
+library. See L<rrdcached(1)> for details. Example:
+
+  <Plugin "rrdcached">
+    DaemonAddress "unix:/var/run/rrdcached.sock"
+  </Plugin>
+
+=item B<DataDir> I<Directory>
+
+Set the base directory in which the RRD files reside. If this is a relative
+path, it is relative to the working base directory of the C<rrdcached> daemon!
+Use of an absolute path is recommended.
+
+=item B<CreateFiles> B<true>|B<false>
+
+Enables or disables the creation of RRD files. If the daemon is not running
+locally, or B<DataDir> is set to a relative path, this will not work as
+expected. Default is B<true>.
+
+=item B<CreateFilesAsync> B<false>|B<true>
+
+When enabled, new RRD files are enabled asynchronously, using a separate thread
+that runs in the background. This prevents writes to block, which is a problem
+especially when many hundreds of files need to be created at once. However,
+since the purpose of creating the files asynchronously is I<not> to block until
+the file is available, values before the file is available will be discarded.
+When disabled (the default) files are created synchronously, blocking for a
+short while, while the file is being written.
+
+=item B<StepSize> I<Seconds>
+
+B<Force> the stepsize of newly created RRD-files. Ideally (and per default)
+this setting is unset and the stepsize is set to the interval in which the data
+is collected. Do not use this option unless you absolutely have to for some
+reason. Setting this option may cause problems with the C<snmp plugin>, the
+C<exec plugin> or when the daemon is set up to receive data from other hosts.
+
+=item B<HeartBeat> I<Seconds>
+
+B<Force> the heartbeat of newly created RRD-files. This setting should be unset
+in which case the heartbeat is set to twice the B<StepSize> which should equal
+the interval in which data is collected. Do not set this option unless you have
+a very good reason to do so.
+
+=item B<RRARows> I<NumRows>
+
+The C<rrdtool plugin> calculates the number of PDPs per CDP based on the
+B<StepSize>, this setting and a timespan. This plugin creates RRD-files with
+three times five RRAs, i. e. five RRAs with the CFs B<MIN>, B<AVERAGE>, and
+B<MAX>. The five RRAs are optimized for graphs covering one hour, one day, one
+week, one month, and one year.
+
+So for each timespan, it calculates how many PDPs need to be consolidated into
+one CDP by calculating:
+  number of PDPs = timespan / (stepsize * rrarows)
+
+Bottom line is, set this no smaller than the width of you graphs in pixels. The
+default is 1200.
+
+=item B<RRATimespan> I<Seconds>
+
+Adds an RRA-timespan, given in seconds. Use this option multiple times to have
+more then one RRA. If this option is never used, the built-in default of (3600,
+86400, 604800, 2678400, 31622400) is used.
+
+For more information on how RRA-sizes are calculated see B<RRARows> above.
+
+=item B<XFF> I<Factor>
+
+Set the "XFiles Factor". The default is 0.1. If unsure, don't set this option.
+I<Factor> must be in the range C<[0.0-1.0)>, i.e. between zero (inclusive) and
+one (exclusive).
+
+=item B<CollectStatistics> B<false>|B<true>
+
+When set to B<true>, various statistics about the I<rrdcached> daemon will be
+collected, with "rrdcached" as the I<plugin name>. Defaults to B<false>.
+
+Statistics are read via I<rrdcached>s socket using the STATS command.
+See L<rrdcached(1)> for details.
+
+=back
+
+=head2 Plugin C<rrdtool>
+
+You can use the settings B<StepSize>, B<HeartBeat>, B<RRARows>, and B<XFF> to
+fine-tune your RRD-files. Please read L<rrdcreate(1)> if you encounter problems
+using these settings. If you don't want to dive into the depths of RRDtool, you
+can safely ignore these settings.
+
+=over 4
+
+=item B<DataDir> I<Directory>
+
+Set the directory to store RRD files under. By default RRD files are generated
+beneath the daemon's working directory, i.e. the B<BaseDir>.
+
+=item B<CreateFilesAsync> B<false>|B<true>
+
+When enabled, new RRD files are enabled asynchronously, using a separate thread
+that runs in the background. This prevents writes to block, which is a problem
+especially when many hundreds of files need to be created at once. However,
+since the purpose of creating the files asynchronously is I<not> to block until
+the file is available, values before the file is available will be discarded.
+When disabled (the default) files are created synchronously, blocking for a
+short while, while the file is being written.
+
+=item B<StepSize> I<Seconds>
+
+B<Force> the stepsize of newly created RRD-files. Ideally (and per default)
+this setting is unset and the stepsize is set to the interval in which the data
+is collected. Do not use this option unless you absolutely have to for some
+reason. Setting this option may cause problems with the C<snmp plugin>, the
+C<exec plugin> or when the daemon is set up to receive data from other hosts.
+
+=item B<HeartBeat> I<Seconds>
+
+B<Force> the heartbeat of newly created RRD-files. This setting should be unset
+in which case the heartbeat is set to twice the B<StepSize> which should equal
+the interval in which data is collected. Do not set this option unless you have
+a very good reason to do so.
+
+=item B<RRARows> I<NumRows>
+
+The C<rrdtool plugin> calculates the number of PDPs per CDP based on the
+B<StepSize>, this setting and a timespan. This plugin creates RRD-files with
+three times five RRAs, i.e. five RRAs with the CFs B<MIN>, B<AVERAGE>, and
+B<MAX>. The five RRAs are optimized for graphs covering one hour, one day, one
+week, one month, and one year.
+
+So for each timespan, it calculates how many PDPs need to be consolidated into
+one CDP by calculating:
+  number of PDPs = timespan / (stepsize * rrarows)
+
+Bottom line is, set this no smaller than the width of you graphs in pixels. The
+default is 1200.
+
+=item B<RRATimespan> I<Seconds>
+
+Adds an RRA-timespan, given in seconds. Use this option multiple times to have
+more then one RRA. If this option is never used, the built-in default of (3600,
+86400, 604800, 2678400, 31622400) is used.
+
+For more information on how RRA-sizes are calculated see B<RRARows> above.
+
+=item B<XFF> I<Factor>
+
+Set the "XFiles Factor". The default is 0.1. If unsure, don't set this option.
+I<Factor> must be in the range C<[0.0-1.0)>, i.e. between zero (inclusive) and
+one (exclusive).
+
+=item B<CacheFlush> I<Seconds>
+
+When the C<rrdtool> plugin uses a cache (by setting B<CacheTimeout>, see below)
+it writes all values for a certain RRD-file if the oldest value is older than
+(or equal to) the number of seconds specified. If some RRD-file is not updated
+anymore for some reason (the computer was shut down, the network is broken,
+etc.) some values may still be in the cache. If B<CacheFlush> is set, then the
+entire cache is searched for entries older than B<CacheTimeout> seconds and
+written to disk every I<Seconds> seconds. Since this is kind of expensive and
+does nothing under normal circumstances, this value should not be too small.
+900 seconds might be a good value, though setting this to 7200 seconds doesn't
+normally do much harm either.
+
+=item B<CacheTimeout> I<Seconds>
+
+If this option is set to a value greater than zero, the C<rrdtool plugin> will
+save values in a cache, as described above. Writing multiple values at once
+reduces IO-operations and thus lessens the load produced by updating the files.
+The trade off is that the graphs kind of "drag behind" and that more memory is
+used.
+
+=item B<WritesPerSecond> I<Updates>
+
+When collecting many statistics with collectd and the C<rrdtool> plugin, you
+will run serious performance problems. The B<CacheFlush> setting and the
+internal update queue assert that collectd continues to work just fine even
+under heavy load, but the system may become very unresponsive and slow. This is
+a problem especially if you create graphs from the RRD files on the same
+machine, for example using the C<graph.cgi> script included in the
+C<contrib/collection3/> directory.
+
+This setting is designed for very large setups. Setting this option to a value
+between 25 and 80 updates per second, depending on your hardware, will leave
+the server responsive enough to draw graphs even while all the cached values
+are written to disk. Flushed values, i.E<nbsp>e. values that are forced to disk
+by the B<FLUSH> command, are B<not> effected by this limit. They are still
+written as fast as possible, so that web frontends have up to date data when
+generating graphs.
+
+For example: If you have 100,000 RRD files and set B<WritesPerSecond> to 30
+updates per second, writing all values to disk will take approximately
+56E<nbsp>minutes. Together with the flushing ability that's integrated into
+"collection3" you'll end up with a responsive and fast system, up to date
+graphs and basically a "backup" of your values every hour.
+
+=item B<RandomTimeout> I<Seconds>
+
+When set, the actual timeout for each value is chosen randomly between
+I<CacheTimeout>-I<RandomTimeout> and I<CacheTimeout>+I<RandomTimeout>. The
+intention is to avoid high load situations that appear when many values timeout
+at the same time. This is especially a problem shortly after the daemon starts,
+because all values were added to the internal cache at roughly the same time.
+
+=back
+
+=head2 Plugin C<sensors>
+
+The I<Sensors plugin> uses B<lm_sensors> to retrieve sensor-values. This means
+that all the needed modules have to be loaded and lm_sensors has to be
+configured (most likely by editing F</etc/sensors.conf>. Read
+L<sensors.conf(5)> for details.
+
+The B<lm_sensors> homepage can be found at
+L<http://secure.netroedge.com/~lm78/>.
+
+=over 4
+
+=item B<SensorConfigFile> I<File>
+
+Read the I<lm_sensors> configuration from I<File>. When unset (recommended),
+the library's default will be used.
+
+=item B<Sensor> I<chip-bus-address/type-feature>
+
+Selects the name of the sensor which you want to collect or ignore, depending
+on the B<IgnoreSelected> below. For example, the option "B<Sensor>
+I<it8712-isa-0290/voltage-in1>" will cause collectd to gather data for the
+voltage sensor I<in1> of the I<it8712> on the isa bus at the address 0290.
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+If no configuration if given, the B<sensors>-plugin will collect data from all
+sensors. This may not be practical, especially for uninteresting sensors.
+Thus, you can use the B<Sensor>-option to pick the sensors you're interested
+in. Sometimes, however, it's easier/preferred to collect all sensors I<except> a
+few ones. This option enables you to do that: By setting B<IgnoreSelected> to
+I<true> the effect of B<Sensor> is inverted: All selected sensors are ignored
+and all other sensors are collected.
+
+=back
+
+=head2 Plugin C<sigrok>
+
+The I<sigrok plugin> uses I<libsigrok> to retrieve measurements from any device
+supported by the L<sigrok|http://sigrok.org/> project.
+
+B<Synopsis>
+
+ <Plugin sigrok>
+   LogLevel 3
+   <Device "AC Voltage">
+      Driver "fluke-dmm"
+      MinimumInterval 10
+      Conn "/dev/ttyUSB2"
+   </Device>
+   <Device "Sound Level">
+      Driver "cem-dt-885x"
+      Conn "/dev/ttyUSB1"
+   </Device>
+ </Plugin>
+
+=over 4
+
+=item B<LogLevel> B<0-5>
+
+The I<sigrok> logging level to pass on to the I<collectd> log, as a number
+between B<0> and B<5> (inclusive). These levels correspond to C<None>,
+C<Errors>, C<Warnings>, C<Informational>, C<Debug >and C<Spew>, respectively.
+The default is B<2> (C<Warnings>). The I<sigrok> log messages, regardless of
+their level, are always submitted to I<collectd> at its INFO log level.
+
+=item E<lt>B<Device> I<Name>E<gt>
+
+A sigrok-supported device, uniquely identified by this section's options. The
+I<Name> is passed to I<collectd> as the I<plugin instance>.
+
+=item B<Driver> I<DriverName>
+
+The sigrok driver to use for this device.
+
+=item B<Conn> I<ConnectionSpec>
+
+If the device cannot be auto-discovered, or more than one might be discovered
+by the driver, I<ConnectionSpec> specifies the connection string to the device.
+It can be of the form of a device path (e.g.E<nbsp>C</dev/ttyUSB2>), or, in
+case of a non-serial USB-connected device, the USB I<VendorID>B<.>I<ProductID>
+separated by a period (e.g.E<nbsp>C<0403.6001>). A USB device can also be
+specified as I<Bus>B<.>I<Address> (e.g.E<nbsp>C<1.41>).
+
+=item B<SerialComm> I<SerialSpec>
+
+For serial devices with non-standard port settings, this option can be used
+to specify them in a form understood by I<sigrok>, e.g.E<nbsp>C<9600/8n1>.
+This should not be necessary; drivers know how to communicate with devices they
+support.
+
+=item B<MinimumInterval> I<Seconds>
+
+Specifies the minimum time between measurement dispatches to I<collectd>, in
+seconds. Since some I<sigrok> supported devices can acquire measurements many
+times per second, it may be necessary to throttle these. For example, the
+I<RRD plugin> cannot process writes more than once per second.
+
+The default B<MinimumInterval> is B<0>, meaning measurements received from the
+device are always dispatched to I<collectd>. When throttled, unused
+measurements are discarded.
+
+=back
+
+=head2 Plugin C<smart>
+
+The C<smart> plugin collects SMART information from physical
+disks. Values collectd include temperature, power cycle count, poweron
+time and bad sectors. Also, all SMART attributes are collected along
+with the normalized current value, the worst value, the threshold and
+a human readable value.
+
+Using the following two options you can ignore some disks or configure the
+collection only of specific disks.
+
+=over 4
+
+=item B<Disk> I<Name>
+
+Select the disk I<Name>. Whether it is collected or ignored depends on the
+B<IgnoreSelected> setting, see below. As with other plugins that use the
+daemon's ignorelist functionality, a string that starts and ends with a slash
+is interpreted as a regular expression. Examples:
+
+  Disk "sdd"
+  Disk "/hda[34]/"
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Sets whether selected disks, i.E<nbsp>e. the ones matches by any of the B<Disk>
+statements, are ignored or if all other disks are ignored. The behavior
+(hopefully) is intuitive: If no B<Disk> option is configured, all disks are
+collected. If at least one B<Disk> option is given and no B<IgnoreSelected> or
+set to B<false>, B<only> matching disks will be collected. If B<IgnoreSelected>
+is set to B<true>, all disks are collected B<except> the ones matched.
+
+=back
+
+=head2 Plugin C<snmp>
+
+Since the configuration of the C<snmp plugin> is a little more complicated than
+other plugins, its documentation has been moved to an own manpage,
+L<collectd-snmp(5)>. Please see there for details.
+
+=head2 Plugin C<statsd>
+
+The I<statsd plugin> listens to a UDP socket, reads "events" in the statsd
+protocol and dispatches rates or other aggregates of these numbers
+periodically.
+
+The plugin implements the I<Counter>, I<Timer>, I<Gauge> and I<Set> types which
+are dispatched as the I<collectd> types C<derive>, C<latency>, C<gauge> and
+C<objects> respectively.
+
+The following configuration options are valid:
+
+=over 4
+
+=item B<Host> I<Host>
+
+Bind to the hostname / address I<Host>. By default, the plugin will bind to the
+"any" address, i.e. accept packets sent to any of the hosts addresses.
+
+=item B<Port> I<Port>
+
+UDP port to listen to. This can be either a service name or a port number.
+Defaults to C<8125>.
+
+=item B<DeleteCounters> B<false>|B<true>
+
+=item B<DeleteTimers> B<false>|B<true>
+
+=item B<DeleteGauges> B<false>|B<true>
+
+=item B<DeleteSets> B<false>|B<true>
+
+These options control what happens if metrics are not updated in an interval.
+If set to B<False>, the default, metrics are dispatched unchanged, i.e. the
+rate of counters and size of sets will be zero, timers report C<NaN> and gauges
+are unchanged. If set to B<True>, the such metrics are not dispatched and
+removed from the internal cache.
+
+=item B<TimerPercentile> I<Percent>
+
+Calculate and dispatch the configured percentile, i.e. compute the latency, so
+that I<Percent> of all reported timers are smaller than or equal to the
+computed latency. This is useful for cutting off the long tail latency, as it's
+often done in I<Service Level Agreements> (SLAs).
+
+Different percentiles can be calculated by setting this option several times.
+If none are specified, no percentiles are calculated / dispatched.
+
+=item B<TimerLower> B<false>|B<true>
+
+=item B<TimerUpper> B<false>|B<true>
+
+=item B<TimerSum> B<false>|B<true>
+
+=item B<TimerCount> B<false>|B<true>
+
+Calculate and dispatch various values out of I<Timer> metrics received during
+an interval. If set to B<False>, the default, these values aren't calculated /
+dispatched.
+
+=back
+
+=head2 Plugin C<swap>
+
+The I<Swap plugin> collects information about used and available swap space. On
+I<Linux> and I<Solaris>, the following options are available:
+
+=over 4
+
+=item B<ReportByDevice> B<false>|B<true>
+
+Configures how to report physical swap devices. If set to B<false> (the
+default), the summary over all swap devices is reported only, i.e. the globally
+used and available space over all devices. If B<true> is configured, the used
+and available space of each device will be reported separately.
+
+This option is only available if the I<Swap plugin> can read C</proc/swaps>
+(under Linux) or use the L<swapctl(2)> mechanism (under I<Solaris>).
+
+=item B<ReportBytes> B<false>|B<true>
+
+When enabled, the I<swap I/O> is reported in bytes. When disabled, the default,
+I<swap I/O> is reported in pages. This option is available under Linux only.
+
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of absolute swap metrics, i.e. number of I<bytes>
+available and used. Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of relative swap metrics, i.e. I<percent>
+available and free. Defaults to B<false>.
+
+This is useful for deploying I<collectd> in a heterogeneous environment, where
+swap sizes differ and you want to specify generic thresholds or similar.
+
+=back
+
+=head2 Plugin C<syslog>
+
+=over 4
+
+=item B<LogLevel> B<debug|info|notice|warning|err>
+
+Sets the log-level. If, for example, set to B<notice>, then all events with
+severity B<notice>, B<warning>, or B<err> will be submitted to the
+syslog-daemon.
+
+Please note that B<debug> is only available if collectd has been compiled with
+debugging support.
+
+=item B<NotifyLevel> B<OKAY>|B<WARNING>|B<FAILURE>
+
+Controls which notifications should be sent to syslog. The default behaviour is
+not to send any. Less severe notifications always imply logging more severe
+notifications: Setting this to B<OKAY> means all notifications will be sent to
+syslog, setting this to B<WARNING> will send B<WARNING> and B<FAILURE>
+notifications but will dismiss B<OKAY> notifications. Setting this option to
+B<FAILURE> will only send failures to syslog.
+
+=back
+
+=head2 Plugin C<table>
+
+The C<table plugin> provides generic means to parse tabular data and dispatch
+user specified values. Values are selected based on column numbers. For
+example, this plugin may be used to get values from the Linux L<proc(5)>
+filesystem or CSV (comma separated values) files.
+
+  <Plugin table>
+    <Table "/proc/slabinfo">
+      Instance "slabinfo"
+      Separator " "
+      <Result>
+        Type gauge
+        InstancePrefix "active_objs"
+        InstancesFrom 0
+        ValuesFrom 1
+      </Result>
+      <Result>
+        Type gauge
+        InstancePrefix "objperslab"
+        InstancesFrom 0
+        ValuesFrom 4
+      </Result>
+    </Table>
+  </Plugin>
+
+The configuration consists of one or more B<Table> blocks, each of which
+configures one file to parse. Within each B<Table> block, there are one or
+more B<Result> blocks, which configure which data to select and how to
+interpret it.
+
+The following options are available inside a B<Table> block:
+
+=over 4
+
+=item B<Instance> I<instance>
+
+If specified, I<instance> is used as the plugin instance. So, in the above
+example, the plugin name C<table-slabinfo> would be used. If omitted, the
+filename of the table is used instead, with all special characters replaced
+with an underscore (C<_>).
+
+=item B<Separator> I<string>
+
+Any character of I<string> is interpreted as a delimiter between the different
+columns of the table. A sequence of two or more contiguous delimiters in the
+table is considered to be a single delimiter, i.E<nbsp>e. there cannot be any
+empty columns. The plugin uses the L<strtok_r(3)> function to parse the lines
+of a table - see its documentation for more details. This option is mandatory.
+
+A horizontal tab, newline and carriage return may be specified by C<\\t>,
+C<\\n> and C<\\r> respectively. Please note that the double backslashes are
+required because of collectd's config parsing.
+
+=back
+
+The following options are available inside a B<Result> block:
+
+=over 4
+
+=item B<Type> I<type>
+
+Sets the type used to dispatch the values to the daemon. Detailed information
+about types and their configuration can be found in L<types.db(5)>. This
+option is mandatory.
+
+=item B<InstancePrefix> I<prefix>
+
+If specified, prepend I<prefix> to the type instance. If omitted, only the
+B<InstancesFrom> option is considered for the type instance.
+
+=item B<InstancesFrom> I<column0> [I<column1> ...]
+
+If specified, the content of the given columns (identified by the column
+number starting at zero) will be used to create the type instance for each
+row. Multiple values (and the instance prefix) will be joined together with
+dashes (I<->) as separation character. If omitted, only the B<InstancePrefix>
+option is considered for the type instance.
+
+The plugin itself does not check whether or not all built instances are
+different. It’s your responsibility to assure that each is unique. This is
+especially true, if you do not specify B<InstancesFrom>: B<You> have to make
+sure that the table only contains one row.
+
+If neither B<InstancePrefix> nor B<InstancesFrom> is given, the type instance
+will be empty.
+
+=item B<ValuesFrom> I<column0> [I<column1> ...]
+
+Specifies the columns (identified by the column numbers starting at zero)
+whose content is used as the actual data for the data sets that are dispatched
+to the daemon. How many such columns you need is determined by the B<Type>
+setting above. If you specify too many or not enough columns, the plugin will
+complain about that and no data will be submitted to the daemon. The plugin
+uses L<strtoll(3)> and L<strtod(3)> to parse counter and gauge values
+respectively, so anything supported by those functions is supported by the
+plugin as well. This option is mandatory.
+
+=back
+
+=head2 Plugin C<tail>
+
+The C<tail plugin> follows logfiles, just like L<tail(1)> does, parses
+each line and dispatches found values. What is matched can be configured by the
+user using (extended) regular expressions, as described in L<regex(7)>.
+
+  <Plugin "tail">
+    <File "/var/log/exim4/mainlog">
+      Instance "exim"
+      Interval 60
+      <Match>
+        Regex "S=([1-9][0-9]*)"
+        DSType "CounterAdd"
+        Type "ipt_bytes"
+        Instance "total"
+      </Match>
+      <Match>
+        Regex "\\<R=local_user\\>"
+        ExcludeRegex "\\<R=local_user\\>.*mail_spool defer"
+        DSType "CounterInc"
+        Type "counter"
+        Instance "local_user"
+      </Match>
+    </File>
+  </Plugin>
+
+The config consists of one or more B<File> blocks, each of which configures one
+logfile to parse. Within each B<File> block, there are one or more B<Match>
+blocks, which configure a regular expression to search for.
+
+The B<Instance> option in the B<File> block may be used to set the plugin
+instance. So in the above example the plugin name C<tail-foo> would be used.
+This plugin instance is for all B<Match> blocks that B<follow> it, until the
+next B<Instance> option. This way you can extract several plugin instances from
+one logfile, handy when parsing syslog and the like.
+
+The B<Interval> option allows you to define the length of time between reads. If
+this is not set, the default Interval will be used.
+
+Each B<Match> block has the following options to describe how the match should
+be performed:
+
+=over 4
+
+=item B<Regex> I<regex>
+
+Sets the regular expression to use for matching against a line. The first
+subexpression has to match something that can be turned into a number by
+L<strtoll(3)> or L<strtod(3)>, depending on the value of C<CounterAdd>, see
+below. Because B<extended> regular expressions are used, you do not need to use
+backslashes for subexpressions! If in doubt, please consult L<regex(7)>. Due to
+collectd's config parsing you need to escape backslashes, though. So if you
+want to match literal parentheses you need to do the following:
+
+  Regex "SPAM \\(Score: (-?[0-9]+\\.[0-9]+)\\)"
+
+=item B<ExcludeRegex> I<regex>
+
+Sets an optional regular expression to use for excluding lines from the match.
+An example which excludes all connections from localhost from the match:
+
+  ExcludeRegex "127\\.0\\.0\\.1"
+
+=item B<DSType> I<Type>
+
+Sets how the values are cumulated. I<Type> is one of:
+
+=over 4
+
+=item B<GaugeAverage>
+
+Calculate the average.
+
+=item B<GaugeMin>
+
+Use the smallest number only.
+
+=item B<GaugeMax>
+
+Use the greatest number only.
+
+=item B<GaugeLast>
+
+Use the last number found.
+
+=item B<CounterSet>
+
+=item B<DeriveSet>
+
+=item B<AbsoluteSet>
+
+The matched number is a counter. Simply I<sets> the internal counter to this
+value. Variants exist for C<COUNTER>, C<DERIVE>, and C<ABSOLUTE> data sources.
+
+=item B<GaugeAdd>
+
+=item B<CounterAdd>
+
+=item B<DeriveAdd>
+
+Add the matched value to the internal counter. In case of B<DeriveAdd>, the
+matched number may be negative, which will effectively subtract from the
+internal counter.
+
+=item B<GaugeInc>
+
+=item B<CounterInc>
+
+=item B<DeriveInc>
+
+Increase the internal counter by one. These B<DSType> are the only ones that do
+not use the matched subexpression, but simply count the number of matched
+lines. Thus, you may use a regular expression without submatch in this case.
+
+=back
+
+As you'd expect the B<Gauge*> types interpret the submatch as a floating point
+number, using L<strtod(3)>. The B<Counter*> and B<AbsoluteSet> types interpret
+the submatch as an unsigned integer using L<strtoull(3)>. The B<Derive*> types
+interpret the submatch as a signed integer using L<strtoll(3)>. B<CounterInc>
+and B<DeriveInc> do not use the submatch at all and it may be omitted in this
+case.
+
+=item B<Type> I<Type>
+
+Sets the type used to dispatch this value. Detailed information about types and
+their configuration can be found in L<types.db(5)>.
+
+=item B<Instance> I<TypeInstance>
+
+This optional setting sets the type instance to use.
+
+=back
+
+=head2 Plugin C<tail_csv>
+
+The I<tail_csv plugin> reads files in the CSV format, e.g. the statistics file
+written by I<Snort>.
+
+B<Synopsis:>
+
+ <Plugin "tail_csv">
+   <Metric "snort-dropped">
+       Type "percent"
+       Instance "dropped"
+       Index 1
+   </Metric>
+   <File "/var/log/snort/snort.stats">
+       Instance "snort-eth0"
+       Interval 600
+       Collect "snort-dropped"
+   </File>
+ </Plugin>
+
+The configuration consists of one or more B<Metric> blocks that define an index
+into the line of the CSV file and how this value is mapped to I<collectd's>
+internal representation. These are followed by one or more B<Instance> blocks
+which configure which file to read, in which interval and which metrics to
+extract.
+
+=over 4
+
+=item E<lt>B<Metric> I<Name>E<gt>
+
+The B<Metric> block configures a new metric to be extracted from the statistics
+file and how it is mapped on I<collectd's> data model. The string I<Name> is
+only used inside the B<Instance> blocks to refer to this block, so you can use
+one B<Metric> block for multiple CSV files.
+
+=over 4
+
+=item B<Type> I<Type>
+
+Configures which I<Type> to use when dispatching this metric. Types are defined
+in the L<types.db(5)> file, see the appropriate manual page for more
+information on specifying types. Only types with a single I<data source> are
+supported by the I<tail_csv plugin>. The information whether the value is an
+absolute value (i.e. a C<GAUGE>) or a rate (i.e. a C<DERIVE>) is taken from the
+I<Type's> definition.
+
+=item B<Instance> I<TypeInstance>
+
+If set, I<TypeInstance> is used to populate the type instance field of the
+created value lists. Otherwise, no type instance is used.
+
+=item B<ValueFrom> I<Index>
+
+Configure to read the value from the field with the zero-based index I<Index>.
+If the value is parsed as signed integer, unsigned integer or double depends on
+the B<Type> setting, see above.
+
+=back
+
+=item E<lt>B<File> I<Path>E<gt>
+
+Each B<File> block represents one CSV file to read. There must be at least one
+I<File> block but there can be multiple if you have multiple CSV files.
+
+=over 4
+
+=item B<Instance> I<PluginInstance>
+
+Sets the I<plugin instance> used when dispatching the values.
+
+=item B<Collect> I<Metric>
+
+Specifies which I<Metric> to collect. This option must be specified at least
+once, and you can use this option multiple times to specify more than one
+metric to be extracted from this statistic file.
+
+=item B<Interval> I<Seconds>
+
+Configures the interval in which to read values from this instance / file.
+Defaults to the plugin's default interval.
+
+=item B<TimeFrom> I<Index>
+
+Rather than using the local time when dispatching a value, read the timestamp
+from the field with the zero-based index I<Index>. The value is interpreted as
+seconds since epoch. The value is parsed as a double and may be factional.
+
+=back
+
+=back
+
+=head2 Plugin C<teamspeak2>
+
+The C<teamspeak2 plugin> connects to the query port of a teamspeak2 server and
+polls interesting global and virtual server data. The plugin can query only one
+physical server but unlimited virtual servers. You can use the following
+options to configure it:
+
+=over 4
+
+=item B<Host> I<hostname/ip>
+
+The hostname or ip which identifies the physical server.
+Default: 127.0.0.1
+
+=item B<Port> I<port>
+
+The query port of the physical server. This needs to be a string.
+Default: "51234"
+
+=item B<Server> I<port>
+
+This option has to be added once for every virtual server the plugin should
+query. If you want to query the virtual server on port 8767 this is what the
+option would look like:
+
+  Server "8767"
+
+This option, although numeric, needs to be a string, i.E<nbsp>e. you B<must>
+use quotes around it! If no such statement is given only global information
+will be collected.
+
+=back
+
+=head2 Plugin C<ted>
+
+The I<TED> plugin connects to a device of "The Energy Detective", a device to
+measure power consumption. These devices are usually connected to a serial
+(RS232) or USB port. The plugin opens a configured device and tries to read the
+current energy readings. For more information on TED, visit
+L<http://www.theenergydetective.com/>.
+
+Available configuration options:
+
+=over 4
+
+=item B<Device> I<Path>
+
+Path to the device on which TED is connected. collectd will need read and write
+permissions on that file.
+
+Default: B</dev/ttyUSB0>
+
+=item B<Retries> I<Num>
+
+Apparently reading from TED is not that reliable. You can therefore configure a
+number of retries here. You only configure the I<retries> here, to if you
+specify zero, one reading will be performed (but no retries if that fails); if
+you specify three, a maximum of four readings are performed. Negative values
+are illegal.
+
+Default: B<0>
+
+=back
+
+=head2 Plugin C<tcpconns>
+
+The C<tcpconns plugin> counts the number of currently established TCP
+connections based on the local port and/or the remote port. Since there may be
+a lot of connections the default if to count all connections with a local port,
+for which a listening socket is opened. You can use the following options to
+fine-tune the ports you are interested in:
+
+=over 4
+
+=item B<ListeningPorts> I<true>|I<false>
+
+If this option is set to I<true>, statistics for all local ports for which a
+listening socket exists are collected. The default depends on B<LocalPort> and
+B<RemotePort> (see below): If no port at all is specifically selected, the
+default is to collect listening ports. If specific ports (no matter if local or
+remote ports) are selected, this option defaults to I<false>, i.E<nbsp>e. only
+the selected ports will be collected unless this option is set to I<true>
+specifically.
+
+=item B<LocalPort> I<Port>
+
+Count the connections to a specific local port. This can be used to see how
+many connections are handled by a specific daemon, e.E<nbsp>g. the mailserver.
+You have to specify the port in numeric form, so for the mailserver example
+you'd need to set B<25>.
+
+=item B<RemotePort> I<Port>
+
+Count the connections to a specific remote port. This is useful to see how
+much a remote service is used. This is most useful if you want to know how many
+connections a local service has opened to remote services, e.E<nbsp>g. how many
+connections a mail server or news server has to other mail or news servers, or
+how many connections a web proxy holds to web servers. You have to give the
+port in numeric form.
+
+=item B<AllPortsSummary> I<true>|I<false>
+
+If this option is set to I<true> a summary of statistics from all connections
+are collectd. This option defaults to I<false>.
+
+=back
+
+=head2 Plugin C<thermal>
+
+=over 4
+
+=item B<ForceUseProcfs> I<true>|I<false>
+
+By default, the I<Thermal plugin> tries to read the statistics from the Linux
+C<sysfs> interface. If that is not available, the plugin falls back to the
+C<procfs> interface. By setting this option to I<true>, you can force the
+plugin to use the latter. This option defaults to I<false>.
+
+=item B<Device> I<Device>
+
+Selects the name of the thermal device that you want to collect or ignore,
+depending on the value of the B<IgnoreSelected> option. This option may be
+used multiple times to specify a list of devices.
+
+=item B<IgnoreSelected> I<true>|I<false>
+
+Invert the selection: If set to true, all devices B<except> the ones that
+match the device names specified by the B<Device> option are collected. By
+default only selected devices are collected if a selection is made. If no
+selection is configured at all, B<all> devices are selected.
+
+=back
+
+=head2 Plugin C<threshold>
+
+The I<Threshold plugin> checks values collected or received by I<collectd>
+against a configurable I<threshold> and issues I<notifications> if values are
+out of bounds.
+
+Documentation for this plugin is available in the L<collectd-threshold(5)>
+manual page.
+
+=head2 Plugin C<tokyotyrant>
+
+The I<TokyoTyrant plugin> connects to a TokyoTyrant server and collects a
+couple metrics: number of records, and database size on disk.
+
+=over 4
+
+=item B<Host> I<Hostname/IP>
+
+The hostname or ip which identifies the server.
+Default: B<127.0.0.1>
+
+=item B<Port> I<Service/Port>
+
+The query port of the server. This needs to be a string, even if the port is
+given in its numeric form.
+Default: B<1978>
+
+=back
+
+=head2 Plugin C<turbostat>
+
+The I<Turbostat plugin> reads CPU frequency and C-state residency on modern
+Intel processors by using the new Model Specific Registers.
+
+=over 4
+
+=item B<CoreCstates> I<Bitmask(Integer)>
+
+Bitmask of the list of core C states supported by the processor.
+This option should only be used if the automated detection fails.
+Default value extracted from the cpu model and family.
+
+Currently supported C-states (by this plugin): 3, 6, 7
+
+Example: (1<<3)+(1<<6)+(1<<7) = 392 for all states
+
+=item B<PackageCstates> I<Bitmask(Integer)>
+
+Bitmask of the list of pacages C states supported by the processor.
+This option should only be used if the automated detection fails.
+Default value extracted from the cpu model and family.
+
+Currently supported C-states (by this plugin): 2, 3, 6, 7, 8, 9, 10
+
+Example: (1<<2)+(1<<3)+(1<<6)+(1<<7) = 396 for states 2, 3, 6 and 7
+
+=item B<SystemManagementInterrupt> I<true>|I<false>
+
+Boolean enabling the collection of the I/O System-Management Interrupt
+counter'. This option should only be used if the automated detection
+fails or if you want to disable this feature.
+
+=item B<DigitalTemperatureSensor> I<true>|I<false>
+
+Boolean enabling the collection of the temperature of each core.
+This option should only be used if the automated detectionfails or 
+if you want to disable this feature.
+
+=item B<DigitalTemperatureSensor> I<true>|I<false>
+
+Boolean enabling the collection of the temperature of each package.
+This option should only be used if the automated detectionfails or 
+if you want to disable this feature.
+
+=item B<TCCActivationTemp> I<Temperature>
+
+Thermal Control Circuit Activation Temperature of the installed
+CPU. This temperature is used when collecting the temperature of
+cores or packages. This option should only be used if the automated
+detection fails. Default value extracted from B<MSR_IA32_TEMPERATURE_TARGET>
+
+=item B<RunningAveragePowerLimit> I<Bitmask(Integer)>
+
+Bitmask of the list of elements to be thermally monitored. This option
+should only be used if the automated detection fails or if you want to
+disable some collections. The different bits of this bitmask accepted
+by this plugin are:
+
+=over 4
+
+=item 0 ('1'): Package
+
+=item 1 ('2'): DRAM
+
+=item 2 ('4'): Cores
+
+=item 3 ('8'): Embedded graphic device
+
+=back
+
+=back
+
+=head2 Plugin C<unixsock>
+
+=over 4
+
+=item B<SocketFile> I<Path>
+
+Sets the socket-file which is to be created.
+
+=item B<SocketGroup> I<Group>
+
+If running as root change the group of the UNIX-socket after it has been
+created. Defaults to B<collectd>.
+
+=item B<SocketPerms> I<Permissions>
+
+Change the file permissions of the UNIX-socket after it has been created. The
+permissions must be given as a numeric, octal value as you would pass to
+L<chmod(1)>. Defaults to B<0770>.
+
+=item B<DeleteSocket> B<false>|B<true>
+
+If set to B<true>, delete the socket file before calling L<bind(2)>, if a file
+with the given name already exists. If I<collectd> crashes a socket file may be
+left over, preventing the daemon from opening a new socket when restarted.
+Since this is potentially dangerous, this defaults to B<false>.
+
+=back
+
+=head2 Plugin C<uuid>
+
+This plugin, if loaded, causes the Hostname to be taken from the machine's
+UUID. The UUID is a universally unique designation for the machine, usually
+taken from the machine's BIOS. This is most useful if the machine is running in
+a virtual environment such as Xen, in which case the UUID is preserved across
+shutdowns and migration.
+
+The following methods are used to find the machine's UUID, in order:
+
+=over 4
+
+=item
+
+Check I</etc/uuid> (or I<UUIDFile>).
+
+=item
+
+Check for UUID from HAL (L<http://www.freedesktop.org/wiki/Software/hal>) if
+present.
+
+=item
+
+Check for UUID from C<dmidecode> / SMBIOS.
+
+=item
+
+Check for UUID from Xen hypervisor.
+
+=back
+
+If no UUID can be found then the hostname is not modified.
+
+=over 4
+
+=item B<UUIDFile> I<Path>
+
+Take the UUID from the given file (default I</etc/uuid>).
+
+=back
+
+=head2 Plugin C<varnish>
+
+The I<varnish plugin> collects information about Varnish, an HTTP accelerator.
+It collects a subset of the values displayed by L<varnishstat(1)>, and
+organizes them in categories which can be enabled or disabled. Currently only
+metrics shown in L<varnishstat(1)>'s I<MAIN> section are collected. The exact
+meaning of each metric can be found in L<varnish-counters(7)>.
+
+Synopsis:
+
+ <Plugin "varnish">
+   <Instance "example">
+     CollectBackend     true
+     CollectBan         false
+     CollectCache       true
+     CollectConnections true
+     CollectDirectorDNS false
+     CollectESI         false
+     CollectFetch       false
+     CollectHCB         false
+     CollectObjects     false
+     CollectPurge       false
+     CollectSession     false
+     CollectSHM         true
+     CollectSMA         false
+     CollectSMS         false
+     CollectSM          false
+     CollectStruct      false
+     CollectTotals      false
+     CollectUptime      false
+     CollectVCL         false
+     CollectVSM         false
+     CollectWorkers     false
+   </Instance>
+ </Plugin>
+
+The configuration consists of one or more E<lt>B<Instance>E<nbsp>I<Name>E<gt>
+blocks. I<Name> is the parameter passed to "varnishd -n". If left empty, it
+will collectd statistics from the default "varnishd" instance (this should work
+fine in most cases).
+
+Inside each E<lt>B<Instance>E<gt> blocks, the following options are recognized:
+
+=over 4
+
+=item B<CollectBackend> B<true>|B<false>
+
+Back-end connection statistics, such as successful, reused,
+and closed connections. True by default.
+
+=item B<CollectBan> B<true>|B<false>
+
+Statistics about ban operations, such as number of bans added, retired, and
+number of objects tested against ban operations. Only available with Varnish
+3.x and above. False by default.
+
+=item B<CollectCache> B<true>|B<false>
+
+Cache hits and misses. True by default.
+
+=item B<CollectConnections> B<true>|B<false>
+
+Number of client connections received, accepted and dropped. True by default.
+
+=item B<CollectDirectorDNS> B<true>|B<false>
+
+DNS director lookup cache statistics. Only available with Varnish 3.x. False by
+default.
+
+=item B<CollectESI> B<true>|B<false>
+
+Edge Side Includes (ESI) parse statistics. False by default.
+
+=item B<CollectFetch> B<true>|B<false>
+
+Statistics about fetches (HTTP requests sent to the backend). False by default.
+
+=item B<CollectHCB> B<true>|B<false>
+
+Inserts and look-ups in the crit bit tree based hash. Look-ups are
+divided into locked and unlocked look-ups. False by default.
+
+=item B<CollectObjects> B<true>|B<false>
+
+Statistics on cached objects: number of objects expired, nuked (prematurely
+expired), saved, moved, etc. False by default.
+
+=item B<CollectPurge> B<true>|B<false>
+
+Statistics about purge operations, such as number of purges added, retired, and
+number of objects tested against purge operations. Only available with Varnish
+2.x. False by default.
+
+=item B<CollectSession> B<true>|B<false>
+
+Client session statistics. Number of past and current sessions, session herd and
+linger counters, etc. False by default. Note that if using Varnish 4.x, some
+metrics found in the Connections and Threads sections with previous versions of
+Varnish have been moved here.
+
+=item B<CollectSHM> B<true>|B<false>
+
+Statistics about the shared memory log, a memory region to store
+log messages which is flushed to disk when full. True by default.
+
+=item B<CollectSMA> B<true>|B<false>
+
+malloc or umem (umem_alloc(3MALLOC) based) storage statistics. The umem storage
+component is Solaris specific. Only available with Varnish 2.x. False by
+default.
+
+=item B<CollectSMS> B<true>|B<false>
+
+synth (synthetic content) storage statistics. This storage
+component is used internally only. False by default.
+
+=item B<CollectSM> B<true>|B<false>
+
+file (memory mapped file) storage statistics. Only available with Varnish 2.x.
+False by default.
+
+=item B<CollectStruct> B<true>|B<false>
+
+Current varnish internal state statistics. Number of current sessions, objects
+in cache store, open connections to backends (with Varnish 2.x), etc. False by
+default.
+
+=item B<CollectTotals> B<true>|B<false>
+
+Collects overview counters, such as the number of sessions created,
+the number of requests and bytes transferred. False by default.
+
+=item B<CollectUptime> B<true>|B<false>
+
+Varnish uptime. Only available with Varnish 3.x and above. False by default.
+
+=item B<CollectVCL> B<true>|B<false>
+
+Number of total (available + discarded) VCL (config files). False by default.
+
+=item B<CollectVSM> B<true>|B<false>
+
+Collect statistics about Varnish's shared memory usage (used by the logging and
+statistics subsystems). Only available with Varnish 4.x. False by default.
+
+=item B<CollectWorkers> B<true>|B<false>
+
+Collect statistics about worker threads. False by default.
+
+=back
+
+=head2 Plugin C<virt>
+
+This plugin allows CPU, disk and network load to be collected for virtualized
+guests on the machine. This means that these metrics can be collected for guest
+systems without installing any software on them - I<collectd> only runs on the
+host system. The statistics are collected through libvirt
+(L<http://libvirt.org/>).
+
+Only I<Connection> is required.
+
+=over 4
+
+=item B<Connection> I<uri>
+
+Connect to the hypervisor given by I<uri>. For example if using Xen use:
+
+ Connection "xen:///"
+
+Details which URIs allowed are given at L<http://libvirt.org/uri.html>.
+
+=item B<RefreshInterval> I<seconds>
+
+Refresh the list of domains and devices every I<seconds>. The default is 60
+seconds. Setting this to be the same or smaller than the I<Interval> will cause
+the list of domains and devices to be refreshed on every iteration.
+
+Refreshing the devices in particular is quite a costly operation, so if your
+virtualization setup is static you might consider increasing this. If this
+option is set to 0, refreshing is disabled completely.
+
+=item B<Domain> I<name>
+
+=item B<BlockDevice> I<name:dev>
+
+=item B<InterfaceDevice> I<name:dev>
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Select which domains and devices are collected.
+
+If I<IgnoreSelected> is not given or B<false> then only the listed domains and
+disk/network devices are collected.
+
+If I<IgnoreSelected> is B<true> then the test is reversed and the listed
+domains and disk/network devices are ignored, while the rest are collected.
+
+The domain name and device names may use a regular expression, if the name is
+surrounded by I</.../> and collectd was compiled with support for regexps.
+
+The default is to collect statistics for all domains and all their devices.
+
+Example:
+
+ BlockDevice "/:hdb/"
+ IgnoreSelected "true"
+
+Ignore all I<hdb> devices on any domain, but other block devices (eg. I<hda>)
+will be collected.
+
+=item B<HostnameFormat> B<name|uuid|hostname|...>
+
+When the virt plugin logs data, it sets the hostname of the collected data
+according to this setting. The default is to use the guest name as provided by
+the hypervisor, which is equal to setting B<name>.
+
+B<uuid> means use the guest's UUID. This is useful if you want to track the
+same guest across migrations.
+
+B<hostname> means to use the global B<Hostname> setting, which is probably not
+useful on its own because all guests will appear to have the same name.
+
+You can also specify combinations of these fields. For example B<name uuid>
+means to concatenate the guest name and UUID (with a literal colon character
+between, thus I<"foo:1234-1234-1234-1234">).
+
+=item B<InterfaceFormat> B<name>|B<address>
+
+When the virt plugin logs interface data, it sets the name of the collected
+data according to this setting. The default is to use the path as provided by
+the hypervisor (the "dev" property of the target node), which is equal to
+setting B<name>.
+
+B<address> means use the interface's mac address. This is useful since the
+interface path might change between reboots of a guest or across migrations.
+
+=item B<PluginInstanceFormat> B<name|uuid>
+
+When the virt plugin logs data, it sets the plugin_instance of the collected
+data according to this setting. The default is to use the guest name as provided
+by the hypervisor, which is equal to setting B<name>.
+
+B<uuid> means use the guest's UUID.
+
+=back
+
+=head2 Plugin C<vmem>
+
+The C<vmem> plugin collects information about the usage of virtual memory.
+Since the statistics provided by the Linux kernel are very detailed, they are
+collected very detailed. However, to get all the details, you have to switch
+them on manually. Most people just want an overview over, such as the number of
+pages read from swap space.
+
+=over 4
+
+=item B<Verbose> B<true>|B<false>
+
+Enables verbose collection of information. This will start collecting page
+"actions", e.E<nbsp>g. page allocations, (de)activations, steals and so on.
+Part of these statistics are collected on a "per zone" basis.
+
+=back
+
+=head2 Plugin C<vserver>
+
+This plugin doesn't have any options. B<VServer> support is only available for
+Linux. It cannot yet be found in a vanilla kernel, though. To make use of this
+plugin you need a kernel that has B<VServer> support built in, i.E<nbsp>e. you
+need to apply the patches and compile your own kernel, which will then provide
+the F</proc/virtual> filesystem that is required by this plugin.
+
+The B<VServer> homepage can be found at L<http://linux-vserver.org/>.
+
+B<Note>: The traffic collected by this plugin accounts for the amount of
+traffic passing a socket which might be a lot less than the actual on-wire
+traffic (e.E<nbsp>g. due to headers and retransmission). If you want to
+collect on-wire traffic you could, for example, use the logging facilities of
+iptables to feed data for the guest IPs into the iptables plugin.
+
+=head2 Plugin C<write_graphite>
+
+The C<write_graphite> plugin writes data to I<Graphite>, an open-source metrics
+storage and graphing project. The plugin connects to I<Carbon>, the data layer
+of I<Graphite>, via I<TCP> or I<UDP> and sends data via the "line based"
+protocol (per default using portE<nbsp>2003). The data will be sent in blocks
+of at most 1428 bytes to minimize the number of network packets.
+
+Synopsis:
+
+ <Plugin write_graphite>
+   <Node "example">
+     Host "localhost"
+     Port "2003"
+     Protocol "tcp"
+     LogSendErrors true
+     Prefix "collectd"
+   </Node>
+ </Plugin>
+
+The configuration consists of one or more E<lt>B<Node>E<nbsp>I<Name>E<gt>
+blocks. Inside the B<Node> blocks, the following options are recognized:
+
+=over 4
+
+=item B<Host> I<Address>
+
+Hostname or address to connect to. Defaults to C<localhost>.
+
+=item B<Port> I<Service>
+
+Service name or port number to connect to. Defaults to C<2003>.
+
+=item B<Protocol> I<String>
+
+Protocol to use when connecting to I<Graphite>. Defaults to C<tcp>.
+
+=item B<LogSendErrors> B<false>|B<true>
+
+If set to B<true> (the default), logs errors when sending data to I<Graphite>.
+If set to B<false>, it will not log the errors. This is especially useful when
+using Protocol UDP since many times we want to use the "fire-and-forget"
+approach and logging errors fills syslog with unneeded messages.
+
+=item B<Prefix> I<String>
+
+When set, I<String> is added in front of the host name. Dots and whitespace are
+I<not> escaped in this string (see B<EscapeCharacter> below).
+
+=item B<Postfix> I<String>
+
+When set, I<String> is appended to the host name. Dots and whitespace are
+I<not> escaped in this string (see B<EscapeCharacter> below).
+
+=item B<EscapeCharacter> I<Char>
+
+I<Carbon> uses the dot (C<.>) as escape character and doesn't allow whitespace
+in the identifier. The B<EscapeCharacter> option determines which character
+dots, whitespace and control characters are replaced with. Defaults to
+underscore (C<_>).
+
+=item B<StoreRates> B<false>|B<true>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.E<nbsp>e. as an increasing integer
+number.
+
+=item B<SeparateInstances> B<false>|B<true>
+
+If set to B<true>, the plugin instance and type instance will be in their own
+path component, for example C<host.cpu.0.cpu.idle>. If set to B<false> (the
+default), the plugin and plugin instance (and likewise the type and type
+instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
+
+=item B<AlwaysAppendDS> B<false>|B<true>
+
+If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
+identifier. If set to B<false> (the default), this is only done when there is
+more than one DS.
+
+=back
+
+=head2 Plugin C<write_tsdb>
+
+The C<write_tsdb> plugin writes data to I<OpenTSDB>, a scalable open-source
+time series database. The plugin connects to a I<TSD>, a masterless, no shared
+state daemon that ingests metrics and stores them in HBase. The plugin uses
+I<TCP> over the "line based" protocol with a default port 4242. The data will
+be sent in blocks of at most 1428 bytes to minimize the number of network
+packets.
+
+Synopsis:
+
+ <Plugin write_tsdb>
+   <Node "example">
+     Host "tsd-1.my.domain"
+     Port "4242"
+     HostTags "status=production"
+   </Node>
+ </Plugin>
+
+The configuration consists of one or more E<lt>B<Node>E<nbsp>I<Name>E<gt>
+blocks. Inside the B<Node> blocks, the following options are recognized:
+
+=over 4
+
+=item B<Host> I<Address>
+
+Hostname or address to connect to. Defaults to C<localhost>.
+
+=item B<Port> I<Service>
+
+Service name or port number to connect to. Defaults to C<4242>.
+
+
+=item B<HostTags> I<String>
+
+When set, I<HostTags> is added to the end of the metric. It is intended to be
+used for name=value pairs that the TSD will tag the metric with. Dots and
+whitespace are I<not> escaped in this string.
+
+=item B<StoreRates> B<false>|B<true>
+
+If set to B<true>, convert counter values to rates. If set to B<false>
+(the default) counter values are stored as is, as an increasing
+integer number.
+
+=item B<AlwaysAppendDS> B<false>|B<true>
+
+If set the B<true>, append the name of the I<Data Source> (DS) to the "metric"
+identifier. If set to B<false> (the default), this is only done when there is
+more than one DS.
+
+=back
+
+=head2 Plugin C<write_mongodb>
+
+The I<write_mongodb plugin> will send values to I<MongoDB>, a schema-less
+NoSQL database.
+
+B<Synopsis:>
+
+ <Plugin "write_mongodb">
+   <Node "default">
+     Host "localhost"
+     Port "27017"
+     Timeout 1000
+     StoreRates true
+   </Node>
+ </Plugin>
+
+The plugin can send values to multiple instances of I<MongoDB> by specifying
+one B<Node> block for each instance. Within the B<Node> blocks, the following
+options are available:
+
+=over 4
+
+=item B<Host> I<Address>
+
+Hostname or address to connect to. Defaults to C<localhost>.
+
+=item B<Port> I<Service>
+
+Service name or port number to connect to. Defaults to C<27017>.
+
+=item B<Timeout> I<Milliseconds>
+
+Set the timeout for each operation on I<MongoDB> to I<Timeout> milliseconds.
+Setting this option to zero means no timeout, which is the default.
+
+=item B<StoreRates> B<false>|B<true>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer
+number.
+
+=item B<Database> I<Database>
+
+=item B<User> I<User>
+
+=item B<Password> I<Password>
+
+Sets the information used when authenticating to a I<MongoDB> database. The
+fields are optional (in which case no authentication is attempted), but if you
+want to use authentication all three fields must be set.
+
+=back
+
+=head2 Plugin C<write_http>
+
+This output plugin submits values to an HTTP server using POST requests and
+encoding metrics with JSON or using the C<PUTVAL> command described in
+L<collectd-unixsock(5)>.
+
+Synopsis:
+
+ <Plugin "write_http">
+   <Node "example">
+     URL "http://example.com/post-collectd"
+     User "collectd"
+     Password "weCh3ik0"
+     Format JSON
+   </Node>
+ </Plugin>
+
+The plugin can send values to multiple HTTP servers by specifying one
+E<lt>B<Node>E<nbsp>I<Name>E<gt> block for each server. Within each B<Node>
+block, the following options are available:
+
+=over 4
+
+=item B<URL> I<URL>
+
+URL to which the values are submitted to. Mandatory.
+
+=item B<User> I<Username>
+
+Optional user name needed for authentication.
+
+=item B<Password> I<Password>
+
+Optional password needed for authentication.
+
+=item B<VerifyPeer> B<true>|B<false>
+
+Enable or disable peer SSL certificate verification. See
+L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enable or disable peer host name verification. If enabled, the plugin checks if
+the C<Common Name> or a C<Subject Alternate Name> field of the SSL certificate
+matches the host name provided by the B<URL> option. If this identity check
+fails, the connection is aborted. Obviously, only works when connecting to a
+SSL enabled server. Enabled by default.
+
+=item B<CACert> I<File>
+
+File that holds one or more SSL certificates. If you want to use HTTPS you will
+possibly need this option. What CA certificates come bundled with C<libcurl>
+and are checked by default depends on the distribution you use.
+
+=item B<CAPath> I<Directory>
+
+Directory holding one or more CA certificate files. You can use this if for
+some reason all the needed CA certificates aren't in the same file and can't be
+pointed to using the B<CACert> option. Requires C<libcurl> to be built against
+OpenSSL.
+
+=item B<ClientKey> I<File>
+
+File that holds the private key in PEM format to be used for certificate-based
+authentication.
+
+=item B<ClientCert> I<File>
+
+File that holds the SSL certificate to be used for certificate-based
+authentication.
+
+=item B<ClientKeyPass> I<Password>
+
+Password required to load the private key in B<ClientKey>.
+
+=item B<SSLVersion> B<SSLv2>|B<SSLv3>|B<TLSv1>|B<TLSv1_0>|B<TLSv1_1>|B<TLSv1_2>
+
+Define which SSL protocol version must be used. By default C<libcurl> will
+attempt to figure out the remote SSL protocol version. See
+L<curl_easy_setopt(3)> for more details.
+
+=item B<Format> B<Command>|B<JSON>
+
+Format of the output to generate. If set to B<Command>, will create output that
+is understood by the I<Exec> and I<UnixSock> plugins. When set to B<JSON>, will
+create output in the I<JavaScript Object Notation> (JSON).
+
+Defaults to B<Command>.
+
+=item B<StoreRates> B<true|false>
+
+If set to B<true>, convert counter values to rates. If set to B<false> (the
+default) counter values are stored as is, i.e. as an increasing integer number.
+
+=item B<BufferSize> I<Bytes>
+
+Sets the send buffer size to I<Bytes>. By increasing this buffer, less HTTP
+requests will be generated, but more metrics will be batched / metrics are
+cached for longer before being sent, introducing additional delay until they
+are available on the server side. I<Bytes> must be at least 1024 and cannot
+exceed the size of an C<int>, i.e. 2E<nbsp>GByte.
+Defaults to C<4096>.
+
+=item B<LowSpeedLimit> I<Bytes per Second>
+
+Sets the minimal transfer rate in I<Bytes per Second> below which the
+connection with the HTTP server will be considered too slow and aborted. All
+the data submitted over this connection will probably be lost. Defaults to 0,
+which means no minimum transfer rate is enforced.
+
+=item B<Timeout> I<Timeout>
+
+Sets the maximum time in milliseconds given for HTTP POST operations to
+complete. When this limit is reached, the POST operation will be aborted, and
+all the data in the current send buffer will probably be lost. Defaults to 0,
+which means the connection never times out.
+
+The C<write_http> plugin regularly submits the collected values to the HTTP
+server. How frequently this happens depends on how much data you are collecting
+and the size of B<BufferSize>. The optimal value to set B<Timeout> to is
+slightly below this interval, which you can estimate by monitoring the network
+traffic between collectd and the HTTP server.
+
+=back
+
+=head2 Plugin C<write_kafka>
+
+The I<write_kafka plugin> will send values to a I<Kafka> topic, a distributed
+queue.
+Synopsis:
+
+ <Plugin "write_kafka">
+   Property "metadata.broker.list" "broker1:9092,broker2:9092"
+   <Topic "collectd">
+     Format JSON
+   </Topic>
+ </Plugin>
+
+The following options are understood by the I<write_kafka plugin>:
+
+=over 4
+
+=item E<lt>B<Topic> I<Name>E<gt>
+
+The plugin's configuration consists of one or more B<Topic> blocks. Each block
+is given a unique I<Name> and specifies one kafka producer.
+Inside the B<Topic> block, the following per-topic options are
+understood:
+
+=over 4
+
+=item B<Property> I<String> I<String>
+
+Configure the named property for the current topic. Properties are
+forwarded to the kafka producer library B<librdkafka>.
+
+=item B<Key> I<String>
+
+Use the specified string as a partioning key for the topic. Kafka breaks
+topic into partitions and guarantees that for a given topology, the same
+consumer will be used for a specific key. The special (case insensitive)
+string B<Random> can be used to specify that an arbitrary partition should
+be used.
+
+=item B<Format> B<Command>|B<JSON>|B<Graphite>
+
+Selects the format in which messages are sent to the broker. If set to
+B<Command> (the default), values are sent as C<PUTVAL> commands which are
+identical to the syntax used by the I<Exec> and I<UnixSock plugins>.
+
+If set to B<JSON>, the values are encoded in the I<JavaScript Object Notation>,
+an easy and straight forward exchange format.
+
+If set to B<Graphite>, values are encoded in the I<Graphite> format, which is
+C<E<lt>metricE<gt> E<lt>valueE<gt> E<lt>timestampE<gt>\n>.
+
+=item B<StoreRates> B<true>|B<false>
+
+Determines whether or not C<COUNTER>, C<DERIVE> and C<ABSOLUTE> data sources
+are converted to a I<rate> (i.e. a C<GAUGE> value). If set to B<false> (the
+default), no conversion is performed. Otherwise the conversion is performed
+using the internal value cache.
+
+Please note that currently this option is only used if the B<Format> option has
+been set to B<JSON>.
+
+=item B<GraphitePrefix> (B<Format>=I<Graphite> only)
+
+A prefix can be added in the metric name when outputting in the I<Graphite>
+format. It's added before the I<Host> name.
+Metric name will be
+C<E<lt>prefixE<gt>E<lt>hostE<gt>E<lt>postfixE<gt>E<lt>pluginE<gt>E<lt>typeE<gt>E<lt>nameE<gt>>
+
+=item B<GraphitePostfix> (B<Format>=I<Graphite> only)
+
+A postfix can be added in the metric name when outputting in the I<Graphite>
+format. It's added after the I<Host> name.
+Metric name will be
+C<E<lt>prefixE<gt>E<lt>hostE<gt>E<lt>postfixE<gt>E<lt>pluginE<gt>E<lt>typeE<gt>E<lt>nameE<gt>>
+
+=item B<GraphiteEscapeChar> (B<Format>=I<Graphite> only)
+
+Specify a character to replace dots (.) in the host part of the metric name.
+In I<Graphite> metric name, dots are used as separators between different
+metric parts (host, plugin, type).
+Default is C<_> (I<Underscore>).
+
+=item B<GraphiteSeparateInstances> B<false>|B<true>
+
+If set to B<true>, the plugin instance and type instance will be in their own
+path component, for example C<host.cpu.0.cpu.idle>. If set to B<false> (the
+default), the plugin and plugin instance (and likewise the type and type
+instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
+
+This will be reflected in the C<ds_type> tag: If B<StoreRates> is enabled,
+converted values will have "rate" appended to the data source type, e.g.
+C<ds_type:derive:rate>.
+
+=back
+
+=item B<Property> I<String> I<String>
+
+Configure the kafka producer through properties, you almost always will
+want to set B<metadata.broker.list> to your Kafka broker list.
+
+=back
+
+=head2 Plugin C<write_redis>
+
+The I<write_redis plugin> submits values to I<Redis>, a data structure server.
+
+Synopsis:
+
+  <Plugin "write_redis">
+    <Node "example">
+        Host "localhost"
+        Port "6379"
+        Timeout 1000
+    </Node>
+  </Plugin>
+
+Values are submitted to I<Sorted Sets>, using the metric name as the key, and
+the timestamp as the score. Retrieving a date range can then be done using the
+C<ZRANGEBYSCORE> I<Redis> command. Additionnally, all the identifiers of these
+I<Sorted Sets> are kept in a I<Set> called C<collectd/values> and can be
+retrieved using the C<SMEMBERS> I<Redis> command. See
+L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
+details.
+
+The information shown in the synopsis above is the I<default configuration>
+which is used by the plugin if no configuration is present.
+
+The plugin can send values to multiple instances of I<Redis> by specifying
+one B<Node> block for each instance. Within the B<Node> blocks, the following
+options are available:
+
+=over 4
+
+=item B<Node> I<Nodename>
+
+The B<Node> block identifies a new I<Redis> node, that is a new I<Redis>
+instance running in an specified host and port. The name for node is a
+canonical identifier which is used as I<plugin instance>. It is limited to
+64E<nbsp>characters in length.
+
+=item B<Host> I<Hostname>
+
+The B<Host> option is the hostname or IP-address where the I<Redis> instance is
+running on.
+
+=item B<Port> I<Port>
+
+The B<Port> option is the TCP port on which the Redis instance accepts
+connections. Either a service name of a port number may be given. Please note
+that numerical port numbers must be given as a string, too.
+
+=item B<Timeout> I<Milliseconds>
+
+The B<Timeout> option sets the socket connection timeout, in milliseconds.
+
+=back
+
+=head2 Plugin C<write_riemann>
+
+The I<write_riemann plugin> will send values to I<Riemann>, a powerful stream
+aggregation and monitoring system. The plugin sends I<Protobuf> encoded data to
+I<Riemann> using UDP packets.
+
+Synopsis:
+
+ <Plugin "write_riemann">
+   <Node "example">
+     Host "localhost"
+     Port "5555"
+     Protocol UDP
+     StoreRates true
+     AlwaysAppendDS false
+     TTLFactor 2.0
+   </Node>
+   Tag "foobar"
+   Attribute "foo" "bar"
+ </Plugin>
+
+The following options are understood by the I<write_riemann plugin>:
+
+=over 4
+
+=item E<lt>B<Node> I<Name>E<gt>
+
+The plugin's configuration consists of one or more B<Node> blocks. Each block
+is given a unique I<Name> and specifies one connection to an instance of
+I<Riemann>. Indise the B<Node> block, the following per-connection options are
+understood:
+
+=over 4
+
+=item B<Host> I<Address>
+
+Hostname or address to connect to. Defaults to C<localhost>.
+
+=item B<Port> I<Service>
+
+Service name or port number to connect to. Defaults to C<5555>.
+
+=item B<Protocol> B<UDP>|B<TCP>
+
+Specify the protocol to use when communicating with I<Riemann>. Defaults to
+B<TCP>.
+
+=item B<Batch> B<true>|B<false>
+
+If set to B<true> and B<Protocol> is set to B<TCP>,
+events will be batched in memory and flushed at
+regular intervals or when B<BatchMaxSize> is exceeded.
+
+Notifications are not batched and sent as soon as possible.
+
+When enabled, it can occur that events get processed by the Riemann server
+close to or after their expiration time. Tune the B<TTLFactor> and
+B<BatchMaxSize> settings according to the amount of values collected, if this
+is an issue.
+
+Defaults to true
+
+=item B<BatchMaxSize> I<size>
+
+Maximum payload size for a riemann packet. Defaults to 8192
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
+
+This will be reflected in the C<ds_type> tag: If B<StoreRates> is enabled,
+converted values will have "rate" appended to the data source type, e.g.
+C<ds_type:derive:rate>.
+
+=item B<AlwaysAppendDS> B<false>|B<true>
+
+If set the B<true>, append the name of the I<Data Source> (DS) to the
+"service", i.e. the field that, together with the "host" field, uniquely
+identifies a metric in I<Riemann>. If set to B<false> (the default), this is
+only done when there is more than one DS.
+
+=item B<TTLFactor> I<Factor>
+
+I<Riemann> events have a I<Time to Live> (TTL) which specifies how long each
+event is considered active. I<collectd> populates this field based on the
+metrics interval setting. This setting controls the factor with which the
+interval is multiplied to set the TTL. The default value is B<2.0>. Unless you
+know exactly what you're doing, you should only increase this setting from its
+default value.
+
+=item B<Notifications> B<false>|B<true>
+
+If set to B<true>, create riemann events for notifications. This is B<true>
+by default. When processing thresholds from write_riemann, it might prove
+useful to avoid getting notification events.
+
+=item B<CheckThresholds> B<false>|B<true>
+
+If set to B<true>, attach state to events based on thresholds defined
+in the B<Threshold> plugin. Defaults to B<false>.
+
+=item B<EventServicePrefix> I<String>
+
+Add the given string as a prefix to the event service name.
+If B<EventServicePrefix> not set or set to an empty string (""),
+no prefix will be used.
+
+=back
+
+=item B<Tag> I<String>
+
+Add the given string as an additional tag to the metric being sent to
+I<Riemann>.
+
+=item B<Attribute> I<String> I<String>
+
+Consider the two given strings to be the key and value of an additional
+attribute for each metric being sent out to I<Riemann>.
+
+=back
+
+=head2 Plugin C<write_sensu>
+
+The I<write_sensu plugin> will send values to I<Sensu>, a powerful stream
+aggregation and monitoring system. The plugin sends I<JSON> encoded data to
+a local I<Sensu> client using a TCP socket.
+
+At the moment, the I<write_sensu plugin> does not send over a collectd_host
+parameter so it is not possible to use one collectd instance as a gateway for
+others. Each collectd host must pair with one I<Sensu> client.
+
+Synopsis:
+
+ <Plugin "write_sensu">
+   <Node "example">
+     Host "localhost"
+     Port "3030"
+     StoreRates true
+     AlwaysAppendDS false
+     MetricHandler "influx"
+     MetricHandler "default"
+     NotificationHandler "flapjack"
+     NotificationHandler "howling_monkey"
+     Notifications true
+   </Node>
+   Tag "foobar"
+   Attribute "foo" "bar"
+ </Plugin>
+
+The following options are understood by the I<write_sensu plugin>:
+
+=over 4
+
+=item E<lt>B<Node> I<Name>E<gt>
+
+The plugin's configuration consists of one or more B<Node> blocks. Each block
+is given a unique I<Name> and specifies one connection to an instance of
+I<Sensu>. Inside the B<Node> block, the following per-connection options are
+understood:
+
+=over 4
+
+=item B<Host> I<Address>
+
+Hostname or address to connect to. Defaults to C<localhost>.
+
+=item B<Port> I<Service>
+
+Service name or port number to connect to. Defaults to C<3030>.
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
+
+This will be reflected in the C<collectd_data_source_type> tag: If
+B<StoreRates> is enabled, converted values will have "rate" appended to the
+data source type, e.g.  C<collectd_data_source_type:derive:rate>.
+
+=item B<AlwaysAppendDS> B<false>|B<true>
+
+If set the B<true>, append the name of the I<Data Source> (DS) to the
+"service", i.e. the field that, together with the "host" field, uniquely
+identifies a metric in I<Sensu>. If set to B<false> (the default), this is
+only done when there is more than one DS.
+
+=item B<Notifications> B<false>|B<true>
+
+If set to B<true>, create I<Sensu> events for notifications. This is B<false>
+by default. At least one of B<Notifications> or B<Metrics> should be enabled.
+
+=item B<Metrics> B<false>|B<true>
+
+If set to B<true>, create I<Sensu> events for metrics. This is B<false>
+by default. At least one of B<Notifications> or B<Metrics> should be enabled.
+
+
+=item B<Separator> I<String>
+
+Sets the separator for I<Sensu> metrics name or checks. Defaults to "/".
+
+=item B<MetricHandler> I<String>
+
+Add a handler that will be set when metrics are sent to I<Sensu>. You can add
+several of them, one per line. Defaults to no handler.
+
+=item B<NotificationHandler> I<String>
+
+Add a handler that will be set when notifications are sent to I<Sensu>. You can
+add several of them, one per line. Defaults to no handler.
+
+=item B<EventServicePrefix> I<String>
+
+Add the given string as a prefix to the event service name.
+If B<EventServicePrefix> not set or set to an empty string (""),
+no prefix will be used.
+
+=back
+
+=item B<Tag> I<String>
+
+Add the given string as an additional tag to the metric being sent to
+I<Sensu>.
+
+=item B<Attribute> I<String> I<String>
+
+Consider the two given strings to be the key and value of an additional
+attribute for each metric being sent out to I<Sensu>.
+
+=back
+
+=head2 Plugin C<zookeeper>
+
+The I<zookeeper plugin> will collect statistics from a I<Zookeeper> server
+using the mntr command.  It requires Zookeeper 3.4.0+ and access to the
+client port.
+
+B<Synopsis:>
+
+ <Plugin "zookeeper">
+   Host "127.0.0.1"
+   Port "2181"
+ </Plugin>
+
+=over 4
+
+=item B<Host> I<Address>
+
+Hostname or address to connect to. Defaults to C<localhost>.
+
+=item B<Port> I<Service>
+
+Service name or port number to connect to. Defaults to C<2181>.
+
+=back
+
+=head1 THRESHOLD CONFIGURATION
+
+Starting with version C<4.3.0> collectd has support for B<monitoring>. By that
+we mean that the values are not only stored or sent somewhere, but that they
+are judged and, if a problem is recognized, acted upon. The only action
+collectd takes itself is to generate and dispatch a "notification". Plugins can
+register to receive notifications and perform appropriate further actions.
+
+Since systems and what you expect them to do differ a lot, you can configure
+B<thresholds> for your values freely. This gives you a lot of flexibility but
+also a lot of responsibility.
+
+Every time a value is out of range a notification is dispatched. This means
+that the idle percentage of your CPU needs to be less then the configured
+threshold only once for a notification to be generated. There's no such thing
+as a moving average or similar - at least not now.
+
+Also, all values that match a threshold are considered to be relevant or
+"interesting". As a consequence collectd will issue a notification if they are
+not received for B<Timeout> iterations. The B<Timeout> configuration option is
+explained in section L<"GLOBAL OPTIONS">. If, for example, B<Timeout> is set to
+"2" (the default) and some hosts sends it's CPU statistics to the server every
+60 seconds, a notification will be dispatched after about 120 seconds. It may
+take a little longer because the timeout is checked only once each B<Interval>
+on the server.
+
+When a value comes within range again or is received after it was missing, an
+"OKAY-notification" is dispatched.
+
+Here is a configuration example to get you started. Read below for more
+information.
+
+ <Plugin threshold>
+   <Type "foo">
+     WarningMin    0.00
+     WarningMax 1000.00
+     FailureMin    0.00
+     FailureMax 1200.00
+     Invert false
+     Instance "bar"
+   </Type>
+
+   <Plugin "interface">
+     Instance "eth0"
+     <Type "if_octets">
+       FailureMax 10000000
+       DataSource "rx"
+     </Type>
+   </Plugin>
+
+   <Host "hostname">
+     <Type "cpu">
+       Instance "idle"
+       FailureMin 10
+     </Type>
+
+     <Plugin "memory">
+       <Type "memory">
+         Instance "cached"
+         WarningMin 100000000
+       </Type>
+     </Plugin>
+   </Host>
+ </Plugin>
+
+There are basically two types of configuration statements: The C<Host>,
+C<Plugin>, and C<Type> blocks select the value for which a threshold should be
+configured. The C<Plugin> and C<Type> blocks may be specified further using the
+C<Instance> option. You can combine the block by nesting the blocks, though
+they must be nested in the above order, i.E<nbsp>e. C<Host> may contain either
+C<Plugin> and C<Type> blocks, C<Plugin> may only contain C<Type> blocks and
+C<Type> may not contain other blocks. If multiple blocks apply to the same
+value the most specific block is used.
+
+The other statements specify the threshold to configure. They B<must> be
+included in a C<Type> block. Currently the following statements are recognized:
+
+=over 4
+
+=item B<FailureMax> I<Value>
+
+=item B<WarningMax> I<Value>
+
+Sets the upper bound of acceptable values. If unset defaults to positive
+infinity. If a value is greater than B<FailureMax> a B<FAILURE> notification
+will be created. If the value is greater than B<WarningMax> but less than (or
+equal to) B<FailureMax> a B<WARNING> notification will be created.
+
+=item B<FailureMin> I<Value>
+
+=item B<WarningMin> I<Value>
+
+Sets the lower bound of acceptable values. If unset defaults to negative
+infinity. If a value is less than B<FailureMin> a B<FAILURE> notification will
+be created. If the value is less than B<WarningMin> but greater than (or equal
+to) B<FailureMin> a B<WARNING> notification will be created.
+
+=item B<DataSource> I<DSName>
+
+Some data sets have more than one "data source". Interesting examples are the
+C<if_octets> data set, which has received (C<rx>) and sent (C<tx>) bytes and
+the C<disk_ops> data set, which holds C<read> and C<write> operations. The
+system load data set, C<load>, even has three data sources: C<shortterm>,
+C<midterm>, and C<longterm>.
+
+Normally, all data sources are checked against a configured threshold. If this
+is undesirable, or if you want to specify different limits for each data
+source, you can use the B<DataSource> option to have a threshold apply only to
+one data source.
+
+=item B<Invert> B<true>|B<false>
+
+If set to B<true> the range of acceptable values is inverted, i.E<nbsp>e.
+values between B<FailureMin> and B<FailureMax> (B<WarningMin> and
+B<WarningMax>) are not okay. Defaults to B<false>.
+
+=item B<Persist> B<true>|B<false>
+
+Sets how often notifications are generated. If set to B<true> one notification
+will be generated for each value that is out of the acceptable range. If set to
+B<false> (the default) then a notification is only generated if a value is out
+of range but the previous value was okay.
+
+This applies to missing values, too: If set to B<true> a notification about a
+missing value is generated once every B<Interval> seconds. If set to B<false>
+only one such notification is generated until the value appears again.
+
+=item B<Percentage> B<true>|B<false>
+
+If set to B<true>, the minimum and maximum values given are interpreted as
+percentage value, relative to the other data sources. This is helpful for
+example for the "df" type, where you may want to issue a warning when less than
+5E<nbsp>% of the total space is available. Defaults to B<false>.
+
+=item B<Hits> I<Number>
+
+Delay creating the notification until the threshold has been passed I<Number>
+times. When a notification has been generated, or when a subsequent value is
+inside the threshold, the counter is reset. If, for example, a value is
+collected once every 10E<nbsp>seconds and B<Hits> is set to 3, a notification
+will be dispatched at most once every 30E<nbsp>seconds.
+
+This is useful when short bursts are not a problem. If, for example, 100% CPU
+usage for up to a minute is normal (and data is collected every
+10E<nbsp>seconds), you could set B<Hits> to B<6> to account for this.
+
+=item B<Hysteresis> I<Number>
+
+When set to non-zero, a hysteresis value is applied when checking minimum and
+maximum bounds. This is useful for values that increase slowly and fluctuate a
+bit while doing so. When these values come close to the threshold, they may
+"flap", i.e. switch between failure / warning case and okay case repeatedly.
+
+If, for example, the threshold is configures as
+
+  WarningMax 100.0
+  Hysteresis 1.0
+
+then a I<Warning> notification is created when the value exceeds I<101> and the
+corresponding I<Okay> notification is only created once the value falls below
+I<99>, thus avoiding the "flapping".
+
+=back
+
+=head1 FILTER CONFIGURATION
+
+Starting with collectd 4.6 there is a powerful filtering infrastructure
+implemented in the daemon. The concept has mostly been copied from
+I<ip_tables>, the packet filter infrastructure for Linux. We'll use a similar
+terminology, so that users that are familiar with iptables feel right at home.
+
+=head2 Terminology
+
+The following are the terms used in the remainder of the filter configuration
+documentation. For an ASCII-art schema of the mechanism, see
+L<"General structure"> below.
+
+=over 4
+
+=item B<Match>
+
+A I<match> is a criteria to select specific values. Examples are, of course, the
+name of the value or it's current value.
+
+Matches are implemented in plugins which you have to load prior to using the
+match. The name of such plugins starts with the "match_" prefix.
+
+=item B<Target>
+
+A I<target> is some action that is to be performed with data. Such actions
+could, for example, be to change part of the value's identifier or to ignore
+the value completely.
+
+Some of these targets are built into the daemon, see L<"Built-in targets">
+below. Other targets are implemented in plugins which you have to load prior to
+using the target. The name of such plugins starts with the "target_" prefix.
+
+=item B<Rule>
+
+The combination of any number of matches and at least one target is called a
+I<rule>. The target actions will be performed for all values for which B<all>
+matches apply. If the rule does not have any matches associated with it, the
+target action will be performed for all values.
+
+=item B<Chain>
+
+A I<chain> is a list of rules and possibly default targets. The rules are tried
+in order and if one matches, the associated target will be called. If a value
+is handled by a rule, it depends on the target whether or not any subsequent
+rules are considered or if traversal of the chain is aborted, see
+L<"Flow control"> below. After all rules have been checked, the default targets
+will be executed.
+
+=back
+
+=head2 General structure
+
+The following shows the resulting structure:
+
+ +---------+
+ ! Chain   !
+ +---------+
+      !
+      V
+ +---------+  +---------+  +---------+  +---------+
+ ! Rule    !->! Match   !->! Match   !->! Target  !
+ +---------+  +---------+  +---------+  +---------+
+      !
+      V
+ +---------+  +---------+  +---------+
+ ! Rule    !->! Target  !->! Target  !
+ +---------+  +---------+  +---------+
+      !
+      V
+      :
+      :
+      !
+      V
+ +---------+  +---------+  +---------+
+ ! Rule    !->! Match   !->! Target  !
+ +---------+  +---------+  +---------+
+      !
+      V
+ +---------+
+ ! Default !
+ ! Target  !
+ +---------+
+
+=head2 Flow control
+
+There are four ways to control which way a value takes through the filter
+mechanism:
+
+=over 4
+
+=item B<jump>
+
+The built-in B<jump> target can be used to "call" another chain, i.E<nbsp>e.
+process the value with another chain. When the called chain finishes, usually
+the next target or rule after the jump is executed.
+
+=item B<stop>
+
+The stop condition, signaled for example by the built-in target B<stop>, causes
+all processing of the value to be stopped immediately.
+
+=item B<return>
+
+Causes processing in the current chain to be aborted, but processing of the
+value generally will continue. This means that if the chain was called via
+B<Jump>, the next target or rule after the jump will be executed. If the chain
+was not called by another chain, control will be returned to the daemon and it
+may pass the value to another chain.
+
+=item B<continue>
+
+Most targets will signal the B<continue> condition, meaning that processing
+should continue normally. There is no special built-in target for this
+condition.
+
+=back
+
+=head2 Synopsis
+
+The configuration reflects this structure directly:
+
+ PostCacheChain "PostCache"
+ <Chain "PostCache">
+   <Rule "ignore_mysql_show">
+     <Match "regex">
+       Plugin "^mysql$"
+       Type "^mysql_command$"
+       TypeInstance "^show_"
+     </Match>
+     <Target "stop">
+     </Target>
+   </Rule>
+   <Target "write">
+     Plugin "rrdtool"
+   </Target>
+ </Chain>
+
+The above configuration example will ignore all values where the plugin field
+is "mysql", the type is "mysql_command" and the type instance begins with
+"show_". All other values will be sent to the C<rrdtool> write plugin via the
+default target of the chain. Since this chain is run after the value has been
+added to the cache, the MySQL C<show_*> command statistics will be available
+via the C<unixsock> plugin.
+
+=head2 List of configuration options
+
+=over 4
+
+=item B<PreCacheChain> I<ChainName>
+
+=item B<PostCacheChain> I<ChainName>
+
+Configure the name of the "pre-cache chain" and the "post-cache chain". The
+argument is the name of a I<chain> that should be executed before and/or after
+the values have been added to the cache.
+
+To understand the implications, it's important you know what is going on inside
+I<collectd>. The following diagram shows how values are passed from the
+read-plugins to the write-plugins:
+
+   +---------------+
+   !  Read-Plugin  !
+   +-------+-------+
+           !
+ + - - - - V - - - - +
+ : +---------------+ :
+ : !   Pre-Cache   ! :
+ : !     Chain     ! :
+ : +-------+-------+ :
+ :         !         :
+ :         V         :
+ : +-------+-------+ :  +---------------+
+ : !     Cache     !--->!  Value Cache  !
+ : !     insert    ! :  +---+---+-------+
+ : +-------+-------+ :      !   !
+ :         !   ,------------'   !
+ :         V   V     :          V
+ : +-------+---+---+ :  +-------+-------+
+ : !  Post-Cache   +--->! Write-Plugins !
+ : !     Chain     ! :  +---------------+
+ : +---------------+ :
+ :                   :
+ :  dispatch values  :
+ + - - - - - - - - - +
+
+After the values are passed from the "read" plugins to the dispatch functions,
+the pre-cache chain is run first. The values are added to the internal cache
+afterwards. The post-cache chain is run after the values have been added to the
+cache. So why is it such a huge deal if chains are run before or after the
+values have been added to this cache?
+
+Targets that change the identifier of a value list should be executed before
+the values are added to the cache, so that the name in the cache matches the
+name that is used in the "write" plugins. The C<unixsock> plugin, too, uses
+this cache to receive a list of all available values. If you change the
+identifier after the value list has been added to the cache, this may easily
+lead to confusion, but it's not forbidden of course.
+
+The cache is also used to convert counter values to rates. These rates are, for
+example, used by the C<value> match (see below). If you use the rate stored in
+the cache B<before> the new value is added, you will use the old, B<previous>
+rate. Write plugins may use this rate, too, see the C<csv> plugin, for example.
+The C<unixsock> plugin uses these rates too, to implement the C<GETVAL>
+command.
+
+Last but not last, the B<stop> target makes a difference: If the pre-cache
+chain returns the stop condition, the value will not be added to the cache and
+the post-cache chain will not be run.
+
+=item B<Chain> I<Name>
+
+Adds a new chain with a certain name. This name can be used to refer to a
+specific chain, for example to jump to it.
+
+Within the B<Chain> block, there can be B<Rule> blocks and B<Target> blocks.
+
+=item B<Rule> [I<Name>]
+
+Adds a new rule to the current chain. The name of the rule is optional and
+currently has no meaning for the daemon.
+
+Within the B<Rule> block, there may be any number of B<Match> blocks and there
+must be at least one B<Target> block.
+
+=item B<Match> I<Name>
+
+Adds a match to a B<Rule> block. The name specifies what kind of match should
+be performed. Available matches depend on the plugins that have been loaded.
+
+The arguments inside the B<Match> block are passed to the plugin implementing
+the match, so which arguments are valid here depends on the plugin being used.
+If you do not need any to pass any arguments to a match, you can use the
+shorter syntax:
+
+ Match "foobar"
+
+Which is equivalent to:
+
+ <Match "foobar">
+ </Match>
+
+=item B<Target> I<Name>
+
+Add a target to a rule or a default target to a chain. The name specifies what
+kind of target is to be added. Which targets are available depends on the
+plugins being loaded.
+
+The arguments inside the B<Target> block are passed to the plugin implementing
+the target, so which arguments are valid here depends on the plugin being used.
+If you do not need any to pass any arguments to a target, you can use the
+shorter syntax:
+
+ Target "stop"
+
+This is the same as writing:
+
+ <Target "stop">
+ </Target>
+
+=back
+
+=head2 Built-in targets
+
+The following targets are built into the core daemon and therefore need no
+plugins to be loaded:
+
+=over 4
+
+=item B<return>
+
+Signals the "return" condition, see the L<"Flow control"> section above. This
+causes the current chain to stop processing the value and returns control to
+the calling chain. The calling chain will continue processing targets and rules
+just after the B<jump> target (see below). This is very similar to the
+B<RETURN> target of iptables, see L<iptables(8)>.
+
+This target does not have any options.
+
+Example:
+
+ Target "return"
+
+=item B<stop>
+
+Signals the "stop" condition, see the L<"Flow control"> section above. This
+causes processing of the value to be aborted immediately. This is similar to
+the B<DROP> target of iptables, see L<iptables(8)>.
+
+This target does not have any options.
+
+Example:
+
+ Target "stop"
+
+=item B<write>
+
+Sends the value to "write" plugins.
+
+Available options:
+
+=over 4
+
+=item B<Plugin> I<Name>
+
+Name of the write plugin to which the data should be sent. This option may be
+given multiple times to send the data to more than one write plugin. If the
+plugin supports multiple instances, the plugin's instance(s) must also be
+specified.
+
+=back
+
+If no plugin is explicitly specified, the values will be sent to all available
+write plugins.
+
+Single-instance plugin example:
+
+ <Target "write">
+   Plugin "rrdtool"
+ </Target>
+
+Multi-instance plugin example:
+
+ <Plugin "write_graphite">
+   <Node "foo">
+   ...
+   </Node>
+   <Node "bar">
+   ...
+   </Node>
+ </Plugin>
+  ...
+ <Target "write">
+   Plugin "write_graphite/foo"
+ </Target>
+
+=item B<jump>
+
+Starts processing the rules of another chain, see L<"Flow control"> above. If
+the end of that chain is reached, or a stop condition is encountered,
+processing will continue right after the B<jump> target, i.E<nbsp>e. with the
+next target or the next rule. This is similar to the B<-j> command line option
+of iptables, see L<iptables(8)>.
+
+Available options:
+
+=over 4
+
+=item B<Chain> I<Name>
+
+Jumps to the chain I<Name>. This argument is required and may appear only once.
+
+=back
+
+Example:
+
+ <Target "jump">
+   Chain "foobar"
+ </Target>
+
+=back
+
+=head2 Available matches
+
+=over 4
+
+=item B<regex>
+
+Matches a value using regular expressions.
+
+Available options:
+
+=over 4
+
+=item B<Host> I<Regex>
+
+=item B<Plugin> I<Regex>
+
+=item B<PluginInstance> I<Regex>
+
+=item B<Type> I<Regex>
+
+=item B<TypeInstance> I<Regex>
+
+Match values where the given regular expressions match the various fields of
+the identifier of a value. If multiple regular expressions are given, B<all>
+regexen must match for a value to match.
+
+=item B<Invert> B<false>|B<true>
+
+When set to B<true>, the result of the match is inverted, i.e. all value lists
+where all regular expressions apply are not matched, all other value lists are
+matched. Defaults to B<false>.
+
+=back
+
+Example:
+
+ <Match "regex">
+   Host "customer[0-9]+"
+   Plugin "^foobar$"
+ </Match>
+
+=item B<timediff>
+
+Matches values that have a time which differs from the time on the server.
+
+This match is mainly intended for servers that receive values over the
+C<network> plugin and write them to disk using the C<rrdtool> plugin. RRDtool
+is very sensitive to the timestamp used when updating the RRD files. In
+particular, the time must be ever increasing. If a misbehaving client sends one
+packet with a timestamp far in the future, all further packets with a correct
+time will be ignored because of that one packet. What's worse, such corrupted
+RRD files are hard to fix.
+
+This match lets one match all values B<outside> a specified time range
+(relative to the server's time), so you can use the B<stop> target (see below)
+to ignore the value, for example.
+
+Available options:
+
+=over 4
+
+=item B<Future> I<Seconds>
+
+Matches all values that are I<ahead> of the server's time by I<Seconds> or more
+seconds. Set to zero for no limit. Either B<Future> or B<Past> must be
+non-zero.
+
+=item B<Past> I<Seconds>
+
+Matches all values that are I<behind> of the server's time by I<Seconds> or
+more seconds. Set to zero for no limit. Either B<Future> or B<Past> must be
+non-zero.
+
+=back
+
+Example:
+
+ <Match "timediff">
+   Future  300
+   Past   3600
+ </Match>
+
+This example matches all values that are five minutes or more ahead of the
+server or one hour (or more) lagging behind.
+
+=item B<value>
+
+Matches the actual value of data sources against given minimumE<nbsp>/ maximum
+values. If a data-set consists of more than one data-source, all data-sources
+must match the specified ranges for a positive match.
+
+Available options:
+
+=over 4
+
+=item B<Min> I<Value>
+
+Sets the smallest value which still results in a match. If unset, behaves like
+negative infinity.
+
+=item B<Max> I<Value>
+
+Sets the largest value which still results in a match. If unset, behaves like
+positive infinity.
+
+=item B<Invert> B<true>|B<false>
+
+Inverts the selection. If the B<Min> and B<Max> settings result in a match,
+no-match is returned and vice versa. Please note that the B<Invert> setting
+only effects how B<Min> and B<Max> are applied to a specific value. Especially
+the B<DataSource> and B<Satisfy> settings (see below) are not inverted.
+
+=item B<DataSource> I<DSName> [I<DSName> ...]
+
+Select one or more of the data sources. If no data source is configured, all
+data sources will be checked. If the type handled by the match does not have a
+data source of the specified name(s), this will always result in no match
+(independent of the B<Invert> setting).
+
+=item B<Satisfy> B<Any>|B<All>
+
+Specifies how checking with several data sources is performed. If set to
+B<Any>, the match succeeds if one of the data sources is in the configured
+range. If set to B<All> the match only succeeds if all data sources are within
+the configured range. Default is B<All>.
+
+Usually B<All> is used for positive matches, B<Any> is used for negative
+matches. This means that with B<All> you usually check that all values are in a
+"good" range, while with B<Any> you check if any value is within a "bad" range
+(or outside the "good" range).
+
+=back
+
+Either B<Min> or B<Max>, but not both, may be unset.
+
+Example:
+
+ # Match all values smaller than or equal to 100. Matches only if all data
+ # sources are below 100.
+ <Match "value">
+   Max 100
+   Satisfy "All"
+ </Match>
+
+ # Match if the value of any data source is outside the range of 0 - 100.
+ <Match "value">
+   Min   0
+   Max 100
+   Invert true
+   Satisfy "Any"
+ </Match>
+
+=item B<empty_counter>
+
+Matches all values with one or more data sources of type B<COUNTER> and where
+all counter values are zero. These counters usually I<never> increased since
+they started existing (and are therefore uninteresting), or got reset recently
+or overflowed and you had really, I<really> bad luck.
+
+Please keep in mind that ignoring such counters can result in confusing
+behavior: Counters which hardly ever increase will be zero for long periods of
+time. If the counter is reset for some reason (machine or service restarted,
+usually), the graph will be empty (NAN) for a long time. People may not
+understand why.
+
+=item B<hashed>
+
+Calculates a hash value of the host name and matches values according to that
+hash value. This makes it possible to divide all hosts into groups and match
+only values that are in a specific group. The intended use is in load
+balancing, where you want to handle only part of all data and leave the rest
+for other servers.
+
+The hashing function used tries to distribute the hosts evenly. First, it
+calculates a 32E<nbsp>bit hash value using the characters of the hostname:
+
+  hash_value = 0;
+  for (i = 0; host[i] != 0; i++)
+    hash_value = (hash_value * 251) + host[i];
+
+The constant 251 is a prime number which is supposed to make this hash value
+more random. The code then checks the group for this host according to the
+I<Total> and I<Match> arguments:
+
+  if ((hash_value % Total) == Match)
+    matches;
+  else
+    does not match;
+
+Please note that when you set I<Total> to two (i.E<nbsp>e. you have only two
+groups), then the least significant bit of the hash value will be the XOR of
+all least significant bits in the host name. One consequence is that when you
+have two hosts, "server0.example.com" and "server1.example.com", where the host
+name differs in one digit only and the digits differ by one, those hosts will
+never end up in the same group.
+
+Available options:
+
+=over 4
+
+=item B<Match> I<Match> I<Total>
+
+Divide the data into I<Total> groups and match all hosts in group I<Match> as
+described above. The groups are numbered from zero, i.E<nbsp>e. I<Match> must
+be smaller than I<Total>. I<Total> must be at least one, although only values
+greater than one really do make any sense.
+
+You can repeat this option to match multiple groups, for example:
+
+  Match 3 7
+  Match 5 7
+
+The above config will divide the data into seven groups and match groups three
+and five. One use would be to keep every value on two hosts so that if one
+fails the missing data can later be reconstructed from the second host.
+
+=back
+
+Example:
+
+ # Operate on the pre-cache chain, so that ignored values are not even in the
+ # global cache.
+ <Chain "PreCache">
+   <Rule>
+     <Match "hashed">
+       # Divide all received hosts in seven groups and accept all hosts in
+       # group three.
+       Match 3 7
+     </Match>
+     # If matched: Return and continue.
+     Target "return"
+   </Rule>
+   # If not matched: Return and stop.
+   Target "stop"
+ </Chain>
+
+=back
+
+=head2 Available targets
+
+=over 4
+
+=item B<notification>
+
+Creates and dispatches a notification.
+
+Available options:
+
+=over 4
+
+=item B<Message> I<String>
+
+This required option sets the message of the notification. The following
+placeholders will be replaced by an appropriate value:
+
+=over 4
+
+=item B<%{host}>
+
+=item B<%{plugin}>
+
+=item B<%{plugin_instance}>
+
+=item B<%{type}>
+
+=item B<%{type_instance}>
+
+These placeholders are replaced by the identifier field of the same name.
+
+=item B<%{ds:>I<name>B<}>
+
+These placeholders are replaced by a (hopefully) human readable representation
+of the current rate of this data source. If you changed the instance name
+(using the B<set> or B<replace> targets, see below), it may not be possible to
+convert counter values to rates.
+
+=back
+
+Please note that these placeholders are B<case sensitive>!
+
+=item B<Severity> B<"FAILURE">|B<"WARNING">|B<"OKAY">
+
+Sets the severity of the message. If omitted, the severity B<"WARNING"> is
+used.
+
+=back
+
+Example:
+
+  <Target "notification">
+    Message "Oops, the %{type_instance} temperature is currently %{ds:value}!"
+    Severity "WARNING"
+  </Target>
+
+=item B<replace>
+
+Replaces parts of the identifier using regular expressions.
+
+Available options:
+
+=over 4
+
+=item B<Host> I<Regex> I<Replacement>
+
+=item B<Plugin> I<Regex> I<Replacement>
+
+=item B<PluginInstance> I<Regex> I<Replacement>
+
+=item B<TypeInstance> I<Regex> I<Replacement>
+
+Match the appropriate field with the given regular expression I<Regex>. If the
+regular expression matches, that part that matches is replaced with
+I<Replacement>. If multiple places of the input buffer match a given regular
+expression, only the first occurrence will be replaced.
+
+You can specify each option multiple times to use multiple regular expressions
+one after another.
+
+=back
+
+Example:
+
+ <Target "replace">
+   # Replace "example.net" with "example.com"
+   Host "\\<example.net\\>" "example.com"
+
+   # Strip "www." from hostnames
+   Host "\\<www\\." ""
+ </Target>
+
+=item B<set>
+
+Sets part of the identifier of a value to a given string.
+
+Available options:
+
+=over 4
+
+=item B<Host> I<String>
+
+=item B<Plugin> I<String>
+
+=item B<PluginInstance> I<String>
+
+=item B<TypeInstance> I<String>
+
+Set the appropriate field to the given string. The strings for plugin instance
+and type instance may be empty, the strings for host and plugin may not be
+empty. It's currently not possible to set the type of a value this way.
+
+=back
+
+Example:
+
+ <Target "set">
+   PluginInstance "coretemp"
+   TypeInstance "core3"
+ </Target>
+
+=back
+
+=head2 Backwards compatibility
+
+If you use collectd with an old configuration, i.E<nbsp>e. one without a
+B<Chain> block, it will behave as it used to. This is equivalent to the
+following configuration:
+
+ <Chain "PostCache">
+   Target "write"
+ </Chain>
+
+If you specify a B<PostCacheChain>, the B<write> target will not be added
+anywhere and you will have to make sure that it is called where appropriate. We
+suggest to add the above snippet as default target to your "PostCache" chain.
+
+=head2 Examples
+
+Ignore all values, where the hostname does not contain a dot, i.E<nbsp>e. can't
+be an FQDN.
+
+ <Chain "PreCache">
+   <Rule "no_fqdn">
+     <Match "regex">
+       Host "^[^\.]*$"
+     </Match>
+     Target "stop"
+   </Rule>
+   Target "write"
+ </Chain>
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd-exec(5)>,
+L<collectd-perl(5)>,
+L<collectd-unixsock(5)>,
+L<types.db(5)>,
+L<hddtemp(8)>,
+L<iptables(8)>,
+L<kstat(3KSTAT)>,
+L<mbmon(1)>,
+L<psql(1)>,
+L<regex(7)>,
+L<rrdtool(1)>,
+L<sensors(1)>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octo@collectd.orgE<gt>
+
+=cut
diff --git a/src/collectd.pod b/src/collectd.pod
new file mode 100644 (file)
index 0000000..fb0403b
--- /dev/null
@@ -0,0 +1,147 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectd - System statistics collection daemon
+
+=head1 SYNOPSIS
+
+collectd I<[options]>
+
+=head1 DESCRIPTION
+
+collectd is a daemon that receives system statistics and makes them available
+in a number of ways. The main daemon itself doesn't have any real functionality
+apart from loading, querying and submitting to plugins. For a description of
+available plugins please see L</PLUGINS> below.
+
+=head1 OPTIONS
+
+Most of collectd's configuration is done using using a configfile. See
+L<collectd.conf(5)> for an in-depth description of all options.
+
+=over 4
+
+=item B<-C> I<E<lt>config-fileE<gt>>
+
+Specify an alternative config file. This is the place to go when you wish to
+change B<collectd>'s behavior. The path may be relative to the current working
+directory.
+
+=item B<-t>
+
+Test the configuration only. The program immediately exits after parsing the
+config file. A return code not equal to zero indicates an error.
+
+=item B<-T>
+
+Test the plugin read callbacks only. The program immediately exits after invoking
+the read callbacks once. A return code not equal to zero indicates an error.
+
+=item B<-P> I<E<lt>pid-fileE<gt>>
+
+Specify an alternative pid file. This overwrites any settings in the config 
+file. This is thought for init-scripts that require the PID-file in a certain
+directory to work correctly. For everyday-usage use the B<PIDFile>
+config-option.
+
+=item B<-f>
+
+Don't fork to the background. I<collectd> will also B<not> close standard file
+descriptors, detach from the session nor write a pid file. This is mainly
+thought for 'supervising' init replacements such as I<runit>. If using
+I<upstart> or I<systemd> though, starting with version 5.5.0 I<collectd> is
+able to notify these two init replacements, and B<does> require forking to the
+background for process supervision. The F<contrib/> directory has sample
+I<upstart> and I<systemd> configuration files.
+
+=item B<-h>
+
+Output usage information and exit.
+
+=back
+
+=head1 PLUGINS
+
+As noted above, the real power of collectd lies within it's plugins. A
+(hopefully complete) list of plugins and short descriptions can be found in the
+F<README> file that is distributed with the sourcecode. If you're using a
+package it's a good bet to search somewhere near F</usr/share/doc/collectd>.
+
+There are two big groups of plugins, B<input> and B<output> plugins:
+
+=over 4
+
+=item
+
+Input plugins are queried periodically. They somehow acquire the current value
+of whatever they where designed to work with and submit these values back to
+the daemon, i. e. they "dispatch" the values. As an example, the C<cpu plugin>
+reads the current cpu-counters of time spent in the various modes (user,
+system, nice, ...) and dispatches these counters to the daemon.
+
+=item
+
+Output plugins get the dispatched values from the daemon and does something
+with them. Common applications are writing to RRD-files, CSV-files or sending
+the data over a network link to a remote box.
+
+=back
+
+Of course not all plugins fit neatly into one of the two above categories. The
+C<network plugin>, for example, is able to send (i.E<nbsp>e. "write") B<and>
+receive (i.E<nbsp>e. "dispatch") values. Also, it opens a socket upon
+initialization and dispatches the values when it receives them and isn't
+triggered at the same time the input plugins are being read. You can think of
+the network receive part as working asynchronous if it helps.
+
+In addition to the above, there are "logging plugins". Right now those are the
+C<logfile plugin> and the C<syslog plugin>. With these plugins collectd can
+provide information about issues and significant situations to the user.
+Several loglevels let you suppress uninteresting messages.
+
+Starting with version C<4.3.0> collectd has support for B<monitoring>. This is
+done by checking thresholds defined by the user. If a value is out of range, a
+notification will be dispatched to "notification plugins". See
+L<collectd.conf(5)> for more detailed information about threshold checking.
+
+Please note that some plugins, that provide other means of communicating with
+the daemon, have manpages of their own to describe their functionality in more
+detail. In particular those are L<collectd-email(5)>, L<collectd-exec(5)>,
+L<collectd-perl(5)>, L<collectd-snmp(5)>, and L<collectd-unixsock(5)>
+
+=head1 SIGNALS
+
+B<collectd> accepts the following signals:
+
+=over 4
+
+=item B<SIGINT>, B<SIGTERM>
+
+These signals cause B<collectd> to shut down all plugins and terminate.
+
+=item B<SIGUSR1>
+
+This signal causes B<collectd> to signal all plugins to flush data from
+internal caches. E.E<nbsp>g. the C<rrdtool plugin> will write all pending data
+to the RRD files. This is the same as using the C<FLUSH -1> command of the
+C<unixsock plugin>.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd.conf(5)>,
+L<collectd-email(5)>,
+L<collectd-exec(5)>,
+L<collectd-perl(5)>,
+L<collectd-snmp(5)>,
+L<collectd-unixsock(5)>,
+L<types.db(5)>,
+L<http://collectd.org/>
+
+=head1 AUTHOR
+
+Florian Forster E<lt>octo@collectd.orgE<gt>
+
+=cut
diff --git a/src/collectdctl.1 b/src/collectdctl.1
new file mode 100644 (file)
index 0000000..5a5636f
--- /dev/null
@@ -0,0 +1,264 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTDCTL 1"
+.TH COLLECTDCTL 1 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectdctl \- Control interface for collectd
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+collectdctl \fI[options]\fR \fI<command>\fR \fI[command options]\fR
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+collectdctl provides a control interface for collectd, which may be used to
+interact with the daemon using the \f(CW\*(C`unixsock plugin\*(C'\fR.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+collectdctl supports the following options:
+.IP "\fB\-s\fR \fIsocket\fR" 4
+.IX Item "-s socket"
+Path to the \s-1UNIX\s0 socket opened by collectd's \f(CW\*(C`unixsock plugin\*(C'\fR.
+Default: /var/run/collectd\-unixsock
+.IP "\fB\-h\fR" 4
+.IX Item "-h"
+Display usage information and exit.
+.SH "AVAILABLE COMMANDS"
+.IX Header "AVAILABLE COMMANDS"
+The following commands are supported:
+.IP "\fBgetval\fR \fI<identifier>\fR" 4
+.IX Item "getval <identifier>"
+Query the latest collected value identified by the specified
+\&\fI<identifier>\fR (see below). The value-list associated with that
+data-set is returned as a list of key-value-pairs, each on its own line. Keys
+and values are separated by the equal sign (\f(CW\*(C`=\*(C'\fR).
+.IP "\fBflush\fR [\fBtimeout=\fR\fI<seconds>\fR] [\fBplugin=\fR\fI<name>\fR] [\fBidentifier=\fR\fI<id>\fR]" 4
+.IX Item "flush [timeout=<seconds>] [plugin=<name>] [identifier=<id>]"
+Flush the daemon. This is useful, e.\ g., to make sure that the latest
+values have been written to the respective \s-1RRD\s0 file before graphing them or
+copying them to somewhere else.
+.Sp
+The following options are supported by the flush command:
+.RS 4
+.IP "\fBtimeout=\fR\fI<seconds>\fR" 4
+.IX Item "timeout=<seconds>"
+Flush values older than the specified timeout (in seconds) only.
+.IP "\fBplugin=\fR\fI<name>\fR" 4
+.IX Item "plugin=<name>"
+Flush the specified plugin only. I.\ e., data cached by the specified
+plugin is written to disk (or network or whatever), if the plugin supports
+that operation.
+.Sp
+Example: \fBrrdtool\fR.
+.IP "\fBidentifier=\fR\fI<id>\fR" 4
+.IX Item "identifier=<id>"
+If this option is present, only the data specified by the specified identifier
+(see below) will be flushed. Note that this option is not supported by all
+plugins (e.\ g., the \f(CW\*(C`network\*(C'\fR plugin does not support this).
+.RE
+.RS 4
+.Sp
+The \fBplugin\fR and \fBidentifier\fR options may be specified more than once. In
+that case, all combinations of specified plugins and identifiers will be
+flushed only.
+.RE
+.IP "\fBlistval\fR" 4
+.IX Item "listval"
+Returns a list of all values (by their identifier) available to the
+\&\f(CW\*(C`unixsock\*(C'\fR plugin. Each value is printed on its own line. I.\ e., this
+command returns a list of valid identifiers that may be used with the other
+commands.
+.IP "\fBputval\fR \fI<identifier>\fR [\fBinterval=\fR\fI<seconds>\fR] \fI<value\-list(s)>\fR" 4
+.IX Item "putval <identifier> [interval=<seconds>] <value-list(s)>"
+Submit one or more values (identified by \fI<identifier>\fR, see below)
+to the daemon which will then dispatch them to the write plugins. \fBinterval\fR
+specifies the interval (in seconds) used to collect the values following that
+option. It defaults to the default of the running collectd instance receiving
+the data. Multiple \fI<value\-list(s)>\fR (see below) may be specified.
+Each of them will be submitted to the daemon. The values have to match the
+data-set definition specified by the type as given in the identifier (see
+\&\fItypes.db\fR\|(5) for details).
+.SH "IDENTIFIERS"
+.IX Header "IDENTIFIERS"
+An identifier has the following format:
+.PP
+[\fIhostname\fR/]\fIplugin\fR[\-\fIplugin_instance\fR]/\fItype\fR[\-\fItype_instance\fR]
+.PP
+Examples:
+ somehost/cpu\-0/cpu\-idle
+ uptime/uptime
+ otherhost/memory/memory\-used
+.PP
+Hostname defaults to the local (non-fully qualified) hostname if omitted. No
+error is returned if the specified identifier does not exist (this is a
+limitation in the \f(CW\*(C`libcollectdclient\*(C'\fR library).
+.SH "VALUE-LIST"
+.IX Header "VALUE-LIST"
+A value list describes one data-set as handled by collectd. It is a colon
+(\f(CW\*(C`:\*(C'\fR) separated list of the time and the values. Each value is either given
+as an integer if the data-type is a counter, or as a double if the data-type
+is a gauge value. A literal \f(CW\*(C`U\*(C'\fR is interpreted as an undefined gauge value.
+The number of values and the data-types have to match the type specified in
+the identifier (see \fItypes.db\fR\|(5) for details). The time is specified as
+epoch (i.\ e., standard \s-1UNIX\s0 time) or as a literal \f(CW\*(C`N\*(C'\fR which will be
+interpreted as now.
+.SH "EXAMPLES"
+.IX Header "EXAMPLES"
+.ie n .IP """collectdctl flush plugin=rrdtool identifier=somehost/cpu\-0/cpu\-wait""" 4
+.el .IP "\f(CWcollectdctl flush plugin=rrdtool identifier=somehost/cpu\-0/cpu\-wait\fR" 4
+.IX Item "collectdctl flush plugin=rrdtool identifier=somehost/cpu-0/cpu-wait"
+Flushes all \s-1CPU\s0 wait \s-1RRD\s0 values of the first \s-1CPU\s0 of the local host.
+I.\ e., writes all pending \s-1RRD\s0 updates of that data-source to disk.
+.ie n .IP """for ident in \`collectdctl listval | grep users/users\`; do collectdctl getval $ident; done""" 4
+.el .IP "\f(CWfor ident in \`collectdctl listval | grep users/users\`; do collectdctl getval $ident; done\fR" 4
+.IX Item "for ident in collectdctl listval | grep users/users; do collectdctl getval $ident; done"
+Query the latest number of logged in users on all hosts known to the local
+collectd instance.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIcollectd\-unixsock\fR\|(5),
+\&\fItypes.db\fR\|(5)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+collectd has been written by Florian Forster <octo at collectd.org>
+and many contributors (see `\s-1AUTHORS\s0').
+.PP
+collectdctl has been written by
+HXkon J Dugstad Johnsen <hakon\-dugstad.johnsen\ at\ telenor.com>
+and Sebastian Harl <sh at tokkee.org>.
diff --git a/src/collectdctl.c b/src/collectdctl.c
new file mode 100644 (file)
index 0000000..2329285
--- /dev/null
@@ -0,0 +1,608 @@
+/**
+ * collectd - src/collectdctl.c
+ * Copyright (C) 2010 Håkon J Dugstad Johnsen
+ * Copyright (C) 2010 Sebastian Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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:
+ *   Håkon J Dugstad Johnsen <hakon-dugstad.johnsen at telenor.com>
+ *   Sebastian "tokkee" Harl <sh@tokkee.org>
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+#include <assert.h>
+#include <errno.h>
+
+#if NAN_STATIC_DEFAULT
+# include <math.h>
+/* #endif NAN_STATIC_DEFAULT*/
+#elif NAN_STATIC_ISOC
+# ifndef __USE_ISOC99
+#  define DISABLE_ISOC99 1
+#  define __USE_ISOC99 1
+# endif /* !defined(__USE_ISOC99) */
+# include <math.h>
+# if DISABLE_ISOC99
+#  undef DISABLE_ISOC99
+#  undef __USE_ISOC99
+# endif /* DISABLE_ISOC99 */
+/* #endif NAN_STATIC_ISOC */
+#elif NAN_ZERO_ZERO
+# include <math.h>
+# ifdef NAN
+#  undef NAN
+# endif
+# define NAN (0.0 / 0.0)
+# ifndef isnan
+#  define isnan(f) ((f) != (f))
+# endif /* !defined(isnan) */
+# ifndef isfinite
+#  define isfinite(f) (((f) - (f)) == 0.0)
+# endif
+# ifndef isinf
+#  define isinf(f) (!isfinite(f) && !isnan(f))
+# endif
+#endif /* NAN_ZERO_ZERO */
+
+#include "libcollectdclient/collectd/client.h"
+
+#define DEFAULT_SOCK LOCALSTATEDIR"/run/"PACKAGE_NAME"-unixsock"
+
+extern char *optarg;
+extern int   optind;
+
+static void exit_usage (const char *name, int status) {
+  fprintf ((status == 0) ? stdout : stderr,
+      "Usage: %s [options] <command> [cmd options]\n\n"
+
+      "Available options:\n"
+      "  -s       Path to collectd's UNIX socket.\n"
+      "           Default: "DEFAULT_SOCK"\n"
+
+      "\n  -h       Display this help and exit.\n"
+
+      "\nAvailable commands:\n\n"
+
+      " * getval <identifier>\n"
+      " * flush [timeout=<seconds>] [plugin=<name>] [identifier=<id>]\n"
+      " * listval\n"
+      " * putval <identifier> [interval=<seconds>] <value-list(s)>\n"
+
+      "\nIdentifiers:\n\n"
+
+      "An identifier has the following format:\n\n"
+
+      "  [<hostname>/]<plugin>[-<plugin_instance>]/<type>[-<type_instance>]\n\n"
+
+      "Hostname defaults to the local hostname if omitted (e.g., uptime/uptime).\n"
+      "No error is returned if the specified identifier does not exist.\n"
+
+      "\n"PACKAGE" "VERSION", http://collectd.org/\n"
+      "by Florian octo Forster <octo@collectd.org>\n"
+      "for contributions see `AUTHORS'\n"
+      , name);
+  exit (status);
+}
+
+/* Count the number of occurrences of the character 'chr'
+ * in the specified string. */
+static int count_chars (const char *str, char chr) {
+  int count = 0;
+
+  while (*str != '\0') {
+    if (*str == chr) {
+      count++;
+    }
+    str++;
+  }
+
+  return count;
+} /* count_chars */
+
+static int array_grow (void **array, int *array_len, size_t elem_size)
+{
+  void *tmp;
+
+  assert ((array != NULL) && (array_len != NULL));
+
+  tmp = realloc (*array, (*array_len + 1) * elem_size);
+  if (tmp == NULL) {
+    fprintf (stderr, "ERROR: Failed to allocate memory.\n");
+    return (-1);
+  }
+
+  *array = tmp;
+  ++(*array_len);
+  return (0);
+} /* array_grow */
+
+static int parse_identifier (lcc_connection_t *c,
+    const char *value, lcc_identifier_t *ident)
+{
+  char hostname[1024];
+  char ident_str[1024] = "";
+  int  n_slashes;
+
+  int status;
+
+  n_slashes = count_chars (value, '/');
+  if (n_slashes == 1) {
+    /* The user has omitted the hostname part of the identifier
+     * (there is only one '/' in the identifier)
+     * Let's add the local hostname */
+    if (gethostname (hostname, sizeof (hostname)) != 0) {
+      fprintf (stderr, "ERROR: Failed to get local hostname: %s",
+          strerror (errno));
+      return (-1);
+    }
+    hostname[sizeof (hostname) - 1] = '\0';
+
+    snprintf (ident_str, sizeof (ident_str), "%s/%s", hostname, value);
+    ident_str[sizeof(ident_str) - 1] = '\0';
+  }
+  else {
+    strncpy (ident_str, value, sizeof (ident_str));
+    ident_str[sizeof (ident_str) - 1] = '\0';
+  }
+
+  status = lcc_string_to_identifier (c, ident, ident_str);
+  if (status != 0) {
+    fprintf (stderr, "ERROR: Failed to parse identifier ``%s'': %s.\n",
+        ident_str, lcc_strerror(c));
+    return (-1);
+  }
+  return (0);
+} /* parse_identifier */
+
+static int getval (lcc_connection_t *c, int argc, char **argv)
+{
+  lcc_identifier_t ident;
+
+  size_t   ret_values_num   = 0;
+  gauge_t *ret_values       = NULL;
+  char   **ret_values_names = NULL;
+
+  int status;
+  size_t i;
+
+  assert (strcasecmp (argv[0], "getval") == 0);
+
+  if (argc != 2) {
+    fprintf (stderr, "ERROR: getval: Missing identifier.\n");
+    return (-1);
+  }
+
+  memset (&ident, 0, sizeof (ident));
+  status = parse_identifier (c, argv[1], &ident);
+  if (status != 0)
+    return (status);
+
+#define BAIL_OUT(s) \
+  do { \
+    if (ret_values != NULL) \
+      free (ret_values); \
+    if (ret_values_names != NULL) { \
+      for (i = 0; i < ret_values_num; ++i) \
+        free (ret_values_names[i]); \
+      free (ret_values_names); \
+    } \
+    ret_values_num = 0; \
+    return (s); \
+  } while (0)
+
+  status = lcc_getval (c, &ident,
+      &ret_values_num, &ret_values, &ret_values_names);
+  if (status != 0) {
+    fprintf (stderr, "ERROR: %s\n", lcc_strerror (c));
+    BAIL_OUT (-1);
+  }
+
+  for (i = 0; i < ret_values_num; ++i)
+    printf ("%s=%e\n", ret_values_names[i], ret_values[i]);
+  BAIL_OUT (0);
+#undef BAIL_OUT
+} /* getval */
+
+static int flush (lcc_connection_t *c, int argc, char **argv)
+{
+  int timeout = -1;
+
+  lcc_identifier_t *identifiers = NULL;
+  int identifiers_num = 0;
+
+  char **plugins = NULL;
+  int plugins_num = 0;
+
+  int status;
+  int i;
+
+  assert (strcasecmp (argv[0], "flush") == 0);
+
+#define BAIL_OUT(s) \
+  do { \
+    if (identifiers != NULL) \
+      free (identifiers); \
+    identifiers_num = 0; \
+    if (plugins != NULL) \
+      free (plugins); \
+    plugins_num = 0; \
+    return (s); \
+  } while (0)
+
+  for (i = 1; i < argc; ++i) {
+    char *key, *value;
+
+    key   = argv[i];
+    value = strchr (argv[i], (int)'=');
+
+    if (! value) {
+      fprintf (stderr, "ERROR: flush: Invalid option ``%s''.\n", argv[i]);
+      BAIL_OUT (-1);
+    }
+
+    *value = '\0';
+    ++value;
+
+    if (strcasecmp (key, "timeout") == 0) {
+      char *endptr = NULL;
+
+      timeout = (int) strtol (value, &endptr, 0);
+
+      if (endptr == value) {
+        fprintf (stderr, "ERROR: Failed to parse timeout as number: %s.\n",
+            value);
+        BAIL_OUT (-1);
+      }
+      else if ((endptr != NULL) && (*endptr != '\0')) {
+        fprintf (stderr, "WARNING: Ignoring trailing garbage after timeout: "
+            "%s.\n", endptr);
+      }
+    }
+    else if (strcasecmp (key, "plugin") == 0) {
+      status = array_grow ((void *)&plugins, &plugins_num,
+          sizeof (*plugins));
+      if (status != 0)
+        BAIL_OUT (status);
+
+      plugins[plugins_num - 1] = value;
+    }
+    else if (strcasecmp (key, "identifier") == 0) {
+      status = array_grow ((void *)&identifiers, &identifiers_num,
+          sizeof (*identifiers));
+      if (status != 0)
+        BAIL_OUT (status);
+
+      memset (identifiers + (identifiers_num - 1), 0, sizeof (*identifiers));
+      status = parse_identifier (c, value,
+          identifiers + (identifiers_num - 1));
+      if (status != 0)
+        BAIL_OUT (status);
+    }
+    else {
+      fprintf (stderr, "ERROR: flush: Unknown option `%s'.\n", key);
+      BAIL_OUT (-1);
+    }
+  }
+
+  if (plugins_num == 0) {
+    status = array_grow ((void *)&plugins, &plugins_num, sizeof (*plugins));
+    if (status != 0)
+      BAIL_OUT (status);
+
+    assert (plugins_num == 1);
+    plugins[0] = NULL;
+  }
+
+  for (i = 0; i < plugins_num; ++i) {
+    if (identifiers_num == 0) {
+      status = lcc_flush (c, plugins[i], NULL, timeout);
+      if (status != 0)
+        fprintf (stderr, "ERROR: Failed to flush plugin `%s': %s.\n",
+            (plugins[i] == NULL) ? "(all)" : plugins[i], lcc_strerror (c));
+    }
+    else {
+      int j;
+
+      for (j = 0; j < identifiers_num; ++j) {
+        status = lcc_flush (c, plugins[i], identifiers + j, timeout);
+        if (status != 0) {
+          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",
+              (plugins[i] == NULL) ? "(all)" : plugins[i],
+              id, lcc_strerror (c));
+        }
+      }
+    }
+  }
+
+  BAIL_OUT (0);
+#undef BAIL_OUT
+} /* flush */
+
+static int listval (lcc_connection_t *c, int argc, char **argv)
+{
+  lcc_identifier_t *ret_ident     = NULL;
+  size_t            ret_ident_num = 0;
+
+  int status;
+  size_t i;
+
+  assert (strcasecmp (argv[0], "listval") == 0);
+
+  if (argc != 1) {
+    fprintf (stderr, "ERROR: listval: Does not accept any arguments.\n");
+    return (-1);
+  }
+
+#define BAIL_OUT(s) \
+  do { \
+    if (ret_ident != NULL) \
+      free (ret_ident); \
+    ret_ident_num = 0; \
+    return (s); \
+  } while (0)
+
+  status = lcc_listval (c, &ret_ident, &ret_ident_num);
+  if (status != 0) {
+    fprintf (stderr, "ERROR: %s\n", lcc_strerror (c));
+    BAIL_OUT (status);
+  }
+
+  for (i = 0; i < ret_ident_num; ++i) {
+    char id[1024];
+
+    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", lcc_strerror (c));
+      continue;
+    }
+
+    printf ("%s\n", id);
+  }
+  BAIL_OUT (0);
+#undef BAIL_OUT
+} /* listval */
+
+static int putval (lcc_connection_t *c, int argc, char **argv)
+{
+  lcc_value_list_t vl = LCC_VALUE_LIST_INIT;
+
+  /* 64 ought to be enough for anybody ;-) */
+  value_t values[64];
+  int     values_types[64];
+  size_t  values_len = 0;
+
+  int status;
+  int i;
+
+  assert (strcasecmp (argv[0], "putval") == 0);
+
+  if (argc < 3) {
+    fprintf (stderr, "ERROR: putval: Missing identifier "
+        "and/or value list.\n");
+    return (-1);
+  }
+
+  vl.values       = values;
+  vl.values_types = values_types;
+
+  status = parse_identifier (c, argv[1], &vl.identifier);
+  if (status != 0)
+    return (status);
+
+  for (i = 2; i < argc; ++i) {
+    char *tmp;
+
+    tmp = strchr (argv[i], (int)'=');
+
+    if (tmp != NULL) { /* option */
+      char *key   = argv[i];
+      char *value = tmp;
+
+      *value = '\0';
+      ++value;
+
+      if (strcasecmp (key, "interval") == 0) {
+        char *endptr;
+
+        vl.interval = strtol (value, &endptr, 0);
+
+        if (endptr == value) {
+          fprintf (stderr, "ERROR: Failed to parse interval as number: %s.\n",
+              value);
+          return (-1);
+        }
+        else if ((endptr != NULL) && (*endptr != '\0')) {
+          fprintf (stderr, "WARNING: Ignoring trailing garbage after "
+              "interval: %s.\n", endptr);
+        }
+      }
+      else {
+        fprintf (stderr, "ERROR: putval: Unknown option `%s'.\n", key);
+        return (-1);
+      }
+    }
+    else { /* value list */
+      char *value;
+
+      tmp = strchr (argv[i], (int)':');
+
+      if (tmp == NULL) {
+        fprintf (stderr, "ERROR: putval: Invalid value list: %s.\n",
+            argv[i]);
+        return (-1);
+      }
+
+      *tmp = '\0';
+      ++tmp;
+
+      if (strcasecmp (argv[i], "N") == 0) {
+        vl.time = 0;
+      }
+      else {
+        char *endptr;
+
+        vl.time = strtol (argv[i], &endptr, 0);
+
+        if (endptr == argv[i]) {
+          fprintf (stderr, "ERROR: Failed to parse time as number: %s.\n",
+              argv[i]);
+          return (-1);
+        }
+        else if ((endptr != NULL) && (*endptr != '\0')) {
+          fprintf (stderr, "ERROR: Garbage after time: %s.\n", endptr);
+          return (-1);
+        }
+      }
+
+      values_len = 0;
+      value = tmp;
+      while (value != 0) {
+        char *dot, *endptr;
+
+        tmp = strchr (value, (int)':');
+
+        if (tmp != NULL) {
+          *tmp = '\0';
+          ++tmp;
+        }
+
+        /* This is a bit of a hack, but parsing types.db just does not make
+         * much sense imho -- the server might have different types defined
+         * anyway. Also, lcc uses the type information for formatting the
+         * number only, so the real meaning does not matter. -tokkee */
+        dot = strchr (value, (int)'.');
+        endptr = NULL;
+        if (strcasecmp (value, "U") == 0) {
+          values[values_len].gauge = NAN;
+          values_types[values_len] = LCC_TYPE_GAUGE;
+        }
+        else if (dot) { /* floating point value */
+          values[values_len].gauge = strtod (value, &endptr);
+          values_types[values_len] = LCC_TYPE_GAUGE;
+        }
+        else { /* integer */
+          values[values_len].counter = strtol (value, &endptr, 0);
+          values_types[values_len] = LCC_TYPE_COUNTER;
+        }
+        ++values_len;
+
+        if (endptr == value) {
+          fprintf (stderr, "ERROR: Failed to parse value as number: %s.\n",
+              argv[i]);
+          return (-1);
+        }
+        else if ((endptr != NULL) && (*endptr != '\0')) {
+          fprintf (stderr, "ERROR: Garbage after value: %s.\n", endptr);
+          return (-1);
+        }
+
+        value = tmp;
+      }
+
+      assert (values_len >= 1);
+      vl.values_len = values_len;
+
+      status = lcc_putval (c, &vl);
+      if (status != 0) {
+        fprintf (stderr, "ERROR: %s\n", lcc_strerror (c));
+        return (-1);
+      }
+    }
+  }
+
+  if (values_len == 0) {
+    fprintf (stderr, "ERROR: putval: Missing value list(s).\n");
+    return (-1);
+  }
+  return (0);
+} /* putval */
+
+int main (int argc, char **argv) {
+  char address[1024] = "unix:"DEFAULT_SOCK;
+
+  lcc_connection_t *c;
+
+  int status;
+
+  while (42) {
+    int c;
+
+    c = getopt (argc, argv, "s:h");
+
+    if (c == -1)
+      break;
+
+    switch (c) {
+      case 's':
+        snprintf (address, sizeof (address), "unix:%s", optarg);
+        address[sizeof (address) - 1] = '\0';
+        break;
+      case 'h':
+        exit_usage (argv[0], 0);
+        break;
+      default:
+        exit_usage (argv[0], 1);
+    }
+  }
+
+  if (optind >= argc) {
+    fprintf (stderr, "%s: missing command\n", argv[0]);
+    exit_usage (argv[0], 1);
+  }
+
+  c = NULL;
+  status = lcc_connect (address, &c);
+  if (status != 0) {
+    fprintf (stderr, "ERROR: Failed to connect to daemon at %s: %s.\n",
+        address, strerror (errno));
+    return (1);
+  }
+
+  if (strcasecmp (argv[optind], "getval") == 0)
+    status = getval (c, argc - optind, argv + optind);
+  else if (strcasecmp (argv[optind], "flush") == 0)
+    status = flush (c, argc - optind, argv + optind);
+  else if (strcasecmp (argv[optind], "listval") == 0)
+    status = listval (c, argc - optind, argv + optind);
+  else if (strcasecmp (argv[optind], "putval") == 0)
+    status = putval (c, argc - optind, argv + optind);
+  else {
+    fprintf (stderr, "%s: invalid command: %s\n", argv[0], argv[optind]);
+    return (1);
+  }
+
+  LCC_DESTROY (c);
+
+  if (status != 0)
+    return (status);
+  return (0);
+} /* main */
+
+/* vim: set sw=2 ts=2 tw=78 expandtab : */
+
diff --git a/src/collectdctl.pod b/src/collectdctl.pod
new file mode 100644 (file)
index 0000000..d921330
--- /dev/null
@@ -0,0 +1,162 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectdctl - Control interface for collectd
+
+=head1 SYNOPSIS
+
+collectdctl I<[options]> I<E<lt>commandE<gt>> I<[command options]>
+
+=head1 DESCRIPTION
+
+collectdctl provides a control interface for collectd, which may be used to
+interact with the daemon using the C<unixsock plugin>.
+
+=head1 OPTIONS
+
+collectdctl supports the following options:
+
+=over 4
+
+=item B<-s> I<socket>
+
+Path to the UNIX socket opened by collectd's C<unixsock plugin>.
+Default: /var/run/collectd-unixsock
+
+=item B<-h>
+
+Display usage information and exit.
+
+=back
+
+=head1 AVAILABLE COMMANDS
+
+The following commands are supported:
+
+=over 4
+
+=item B<getval> I<E<lt>identifierE<gt>>
+
+Query the latest collected value identified by the specified
+I<E<lt>identifierE<gt>> (see below). The value-list associated with that
+data-set is returned as a list of key-value-pairs, each on its own line. Keys
+and values are separated by the equal sign (C<=>).
+
+=item B<flush> [B<timeout=>I<E<lt>secondsE<gt>>] [B<plugin=>I<E<lt>nameE<gt>>]
+[B<identifier=>I<E<lt>idE<gt>>]
+
+Flush the daemon. This is useful, e.E<nbsp>g., to make sure that the latest
+values have been written to the respective RRD file before graphing them or
+copying them to somewhere else.
+
+The following options are supported by the flush command:
+
+=over 4
+
+=item B<timeout=>I<E<lt>secondsE<gt>>
+
+Flush values older than the specified timeout (in seconds) only.
+
+=item B<plugin=>I<E<lt>nameE<gt>>
+
+Flush the specified plugin only. I.E<nbsp>e., data cached by the specified
+plugin is written to disk (or network or whatever), if the plugin supports
+that operation.
+
+Example: B<rrdtool>.
+
+=item B<identifier=>I<E<lt>idE<gt>>
+
+If this option is present, only the data specified by the specified identifier
+(see below) will be flushed. Note that this option is not supported by all
+plugins (e.E<nbsp>g., the C<network> plugin does not support this).
+
+=back
+
+The B<plugin> and B<identifier> options may be specified more than once. In
+that case, all combinations of specified plugins and identifiers will be
+flushed only.
+
+=item B<listval>
+
+Returns a list of all values (by their identifier) available to the
+C<unixsock> plugin. Each value is printed on its own line. I.E<nbsp>e., this
+command returns a list of valid identifiers that may be used with the other
+commands.
+
+=item B<putval> I<E<lt>identifierE<gt>> [B<interval=>I<E<lt>secondsE<gt>>]
+I<E<lt>value-list(s)E<gt>>
+
+Submit one or more values (identified by I<E<lt>identifierE<gt>>, see below)
+to the daemon which will then dispatch them to the write plugins. B<interval>
+specifies the interval (in seconds) used to collect the values following that
+option. It defaults to the default of the running collectd instance receiving
+the data. Multiple I<E<lt>value-list(s)E<gt>> (see below) may be specified.
+Each of them will be submitted to the daemon. The values have to match the
+data-set definition specified by the type as given in the identifier (see
+L<types.db(5)> for details).
+
+=back
+
+=head1 IDENTIFIERS
+
+An identifier has the following format:
+
+[I<hostname>/]I<plugin>[-I<plugin_instance>]/I<type>[-I<type_instance>]
+
+Examples:
+ somehost/cpu-0/cpu-idle
+ uptime/uptime
+ otherhost/memory/memory-used
+
+Hostname defaults to the local (non-fully qualified) hostname if omitted. No
+error is returned if the specified identifier does not exist (this is a
+limitation in the C<libcollectdclient> library).
+
+=head1 VALUE-LIST
+
+A value list describes one data-set as handled by collectd. It is a colon
+(C<:>) separated list of the time and the values. Each value is either given
+as an integer if the data-type is a counter, or as a double if the data-type
+is a gauge value. A literal C<U> is interpreted as an undefined gauge value.
+The number of values and the data-types have to match the type specified in
+the identifier (see L<types.db(5)> for details). The time is specified as
+epoch (i.E<nbsp>e., standard UNIX time) or as a literal C<N> which will be
+interpreted as now.
+
+=head1 EXAMPLES
+
+=over 4
+
+=item C<collectdctl flush plugin=rrdtool identifier=somehost/cpu-0/cpu-wait>
+
+Flushes all CPU wait RRD values of the first CPU of the local host.
+I.E<nbsp>e., writes all pending RRD updates of that data-source to disk.
+
+=item C<for ident in `collectdctl listval | grep users/users`; do
+      collectdctl getval $ident;
+  done>
+
+Query the latest number of logged in users on all hosts known to the local
+collectd instance.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<collectd-unixsock(5)>,
+L<types.db(5)>
+
+=head1 AUTHOR
+
+collectd has been written by Florian Forster E<lt>octo at collectd.orgE<gt>
+and many contributors (see `AUTHORS').
+
+collectdctl has been written by
+Håkon J Dugstad Johnsen E<lt>hakon-dugstad.johnsenE<nbsp>atE<nbsp>telenor.comE<gt>
+and Sebastian Harl E<lt>sh at tokkee.orgE<gt>.
+
+=cut
diff --git a/src/collectdmon.1 b/src/collectdmon.1
new file mode 100644 (file)
index 0000000..abdd424
--- /dev/null
@@ -0,0 +1,190 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "COLLECTDMON 1"
+.TH COLLECTDMON 1 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+collectdmon \- Monitoring daemon for collectd
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+collectdmon \fI[options]\fR [\-\- \fIcollectd options\fR]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+collectdmon is a small \*(L"wrapper\*(R" daemon which starts and monitors the collectd
+daemon. If collectd terminates it will automatically be restarted, unless
+collectdmon was told to shut it down.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+collectdmon supports the following options:
+.IP "\fB\-c\fR \fI<path>\fR" 4
+.IX Item "-c <path>"
+Specify the pathname of the collectd binary. You may either specify an
+absolute path or simply the name of the binary in which case the \fB\s-1PATH\s0\fR
+variable will be searched for it. The default is "\fBcollectd\fR".
+.IP "\fB\-P\fR \fI<pid\-file>\fR" 4
+.IX Item "-P <pid-file>"
+Specify the pid file. The default is "\fI/var/run/collectdmon.pid\fR".
+.IP "\fB\-h\fR" 4
+.IX Item "-h"
+Output usage information and exit.
+.IP "\fIcollectd options\fR" 4
+.IX Item "collectd options"
+Specify options that are passed on to collectd. If it is not already included,
+\&\fB\-f\fR will be added to these options. See \fIcollectd\fR\|(1).
+.SH "SIGNALS"
+.IX Header "SIGNALS"
+\&\fBcollectdmon\fR accepts the following signals:
+.IP "\fB\s-1SIGINT\s0\fR, \fB\s-1SIGTERM\s0\fR" 4
+.IX Item "SIGINT, SIGTERM"
+These signals cause \fBcollectdmon\fR to terminate \fBcollectd\fR, wait for its
+termination and then shut down.
+.IP "\fB\s-1SIGHUP\s0\fR" 4
+.IX Item "SIGHUP"
+This signal causes \fBcollectdmon\fR to terminate \fBcollectd\fR, wait for its
+termination and then restart it.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+<http://collectd.org/>
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+collectd has been written by Florian Forster <octo at collectd.org>
+and many contributors (see `\s-1AUTHORS\s0').
+.PP
+collectdmon has been written by Sebastian Harl <sh@tokkee.org>.
diff --git a/src/collectdmon.c b/src/collectdmon.c
new file mode 100644 (file)
index 0000000..c3f9525
--- /dev/null
@@ -0,0 +1,380 @@
+/**
+ * collectd - src/collectdmon.c
+ * Copyright (C) 2007       Sebastian Harl
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+#if !defined(__GNUC__) || !__GNUC__
+# define __attribute__(x) /**/
+#endif
+
+#include "config.h"
+
+#include <assert.h>
+
+#include <errno.h>
+
+#include <fcntl.h>
+
+#include <signal.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <string.h>
+
+#include <syslog.h>
+
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <time.h>
+
+#include <unistd.h>
+
+#ifndef COLLECTDMON_PIDFILE
+# define COLLECTDMON_PIDFILE LOCALSTATEDIR"/run/collectdmon.pid"
+#endif /* ! COLLECTDMON_PIDFILE */
+
+#ifndef WCOREDUMP
+# define WCOREDUMP(s) 0
+#endif /* ! WCOREDUMP */
+
+static int loop    = 0;
+static int restart = 0;
+
+static char  *pidfile      = NULL;
+static pid_t  collectd_pid = 0;
+
+static void exit_usage (char *name)
+{
+       printf ("Usage: %s <options> [-- <collectd options>]\n"
+
+                       "\nAvailable options:\n"
+                       "  -h         Display this help and exit.\n"
+                       "  -c <path>  Path to the collectd binary.\n"
+                       "  -P <file>  PID-file.\n"
+
+                       "\nFor <collectd options> see collectd.conf(5).\n"
+
+                       "\n"PACKAGE" "VERSION", http://collectd.org/\n"
+                       "by Florian octo Forster <octo@collectd.org>\n"
+                       "for contributions see `AUTHORS'\n", name);
+       exit (0);
+} /* exit_usage */
+
+static int pidfile_create (void)
+{
+       FILE *file = NULL;
+
+       if (NULL == pidfile)
+               pidfile = COLLECTDMON_PIDFILE;
+
+       if (NULL == (file = fopen (pidfile, "w"))) {
+               syslog (LOG_ERR, "Error: couldn't open PID-file (%s) for writing: %s",
+                               pidfile, strerror (errno));
+               return -1;
+       }
+
+       fprintf (file, "%i\n", (int)getpid ());
+       fclose (file);
+       return 0;
+} /* pidfile_create */
+
+static int pidfile_delete (void)
+{
+       assert (NULL != pidfile);
+
+       if (0 != unlink (pidfile)) {
+               syslog (LOG_ERR, "Error: couldn't delete PID-file (%s): %s",
+                               pidfile, strerror (errno));
+               return -1;
+       }
+       return 0;
+} /* pidfile_remove */
+
+static int daemonize (void)
+{
+       struct rlimit rl;
+
+       pid_t pid = 0;
+       int   i   = 0;
+
+       if (0 != chdir ("/")) {
+               fprintf (stderr, "Error: chdir() failed: %s\n", strerror (errno));
+               return -1;
+       }
+
+       if (0 != getrlimit (RLIMIT_NOFILE, &rl)) {
+               fprintf (stderr, "Error: getrlimit() failed: %s\n", strerror (errno));
+               return -1;
+       }
+
+       if (0 > (pid = fork ())) {
+               fprintf (stderr, "Error: fork() failed: %s\n", strerror (errno));
+               return -1;
+       }
+       else if (pid != 0) {
+               exit (0);
+       }
+
+       if (0 != pidfile_create ())
+               return -1;
+
+       setsid ();
+
+       if (RLIM_INFINITY == rl.rlim_max)
+               rl.rlim_max = 1024;
+
+       for (i = 0; i < (int)rl.rlim_max; ++i)
+               close (i);
+
+       errno = 0;
+       if (open ("/dev/null", O_RDWR) != 0) {
+               syslog (LOG_ERR, "Error: couldn't connect STDIN to /dev/null: %s",
+                               strerror (errno));
+               return -1;
+       }
+
+       errno = 0;
+       if (dup (0) != 1) {
+               syslog (LOG_ERR, "Error: couldn't connect STDOUT to /dev/null: %s",
+                               strerror (errno));
+               return -1;
+       }
+
+       errno = 0;
+       if (dup (0) != 2) {
+               syslog (LOG_ERR, "Error: couldn't connect STDERR to /dev/null: %s",
+                               strerror (errno));
+               return -1;
+       }
+       return 0;
+} /* daemonize */
+
+static int collectd_start (char **argv)
+{
+       pid_t pid = 0;
+
+       if (0 > (pid = fork ())) {
+               syslog (LOG_ERR, "Error: fork() failed: %s", strerror (errno));
+               return -1;
+       }
+       else if (pid != 0) {
+               collectd_pid = pid;
+               return 0;
+       }
+
+       execvp (argv[0], argv);
+       syslog (LOG_ERR, "Error: execvp(%s) failed: %s",
+                       argv[0], strerror (errno));
+       exit (-1);
+} /* collectd_start */
+
+static int collectd_stop (void)
+{
+       if (0 == collectd_pid)
+               return 0;
+
+       if (0 != kill (collectd_pid, SIGTERM)) {
+               syslog (LOG_ERR, "Error: kill() failed: %s", strerror (errno));
+               return -1;
+       }
+       return 0;
+} /* collectd_stop */
+
+static void sig_int_term_handler (int __attribute__((unused)) signo)
+{
+       ++loop;
+       return;
+} /* sig_int_term_handler */
+
+static void sig_hup_handler (int __attribute__((unused)) signo)
+{
+       ++restart;
+       return;
+} /* sig_hup_handler */
+
+static void log_status (int status)
+{
+       if (WIFEXITED (status)) {
+               if (0 == WEXITSTATUS (status))
+                       syslog (LOG_INFO, "Info: collectd terminated with exit status %i",
+                                       WEXITSTATUS (status));
+               else
+                       syslog (LOG_WARNING,
+                                       "Warning: collectd terminated with exit status %i",
+                                       WEXITSTATUS (status));
+       }
+       else if (WIFSIGNALED (status)) {
+               syslog (LOG_WARNING, "Warning: collectd was terminated by signal %i%s",
+                               WTERMSIG (status), WCOREDUMP (status) ? " (core dumped)" : "");
+       }
+       return;
+} /* log_status */
+
+static void check_respawn (void)
+{
+       time_t t = time (NULL);
+
+       static time_t timestamp = 0;
+       static int    counter   = 0;
+
+       if ((t - 120) < timestamp)
+               ++counter;
+       else {
+               timestamp = t;
+               counter   = 0;
+       }
+
+       if (10 < counter) {
+               unsigned int time_left = 300;
+
+               syslog (LOG_ERR, "Error: collectd is respawning too fast - "
+                               "disabled for %i seconds", time_left);
+
+               while ((0 < (time_left = sleep (time_left))) && (0 == loop));
+       }
+       return;
+} /* check_respawn */
+
+int main (int argc, char **argv)
+{
+       int    collectd_argc = 0;
+       char  *collectd      = NULL;
+       char **collectd_argv = NULL;
+
+       struct sigaction sa;
+
+       int i = 0;
+
+       /* parse command line options */
+       while (42) {
+               int c = getopt (argc, argv, "hc:P:");
+
+               if (-1 == c)
+                       break;
+
+               switch (c) {
+                       case 'c':
+                               collectd = optarg;
+                               break;
+                       case 'P':
+                               pidfile = optarg;
+                               break;
+                       case 'h':
+                       default:
+                               exit_usage (argv[0]);
+               }
+       }
+
+       for (i = optind; i < argc; ++i)
+               if (0 == strcmp (argv[i], "-f"))
+                       break;
+
+       /* i < argc => -f already present */
+       collectd_argc = 1 + argc - optind + ((i < argc) ? 0 : 1);
+       collectd_argv = (char **)calloc (collectd_argc + 1, sizeof (char *));
+
+       if (NULL == collectd_argv) {
+               fprintf (stderr, "Out of memory.");
+               return 3;
+       }
+
+       collectd_argv[0] = (NULL == collectd) ? "collectd" : collectd;
+
+       if (i == argc)
+               collectd_argv[collectd_argc - 1] = "-f";
+
+       for (i = optind; i < argc; ++i)
+               collectd_argv[i - optind + 1] = argv[i];
+
+       collectd_argv[collectd_argc] = NULL;
+
+       openlog ("collectdmon", LOG_CONS | LOG_PID, LOG_DAEMON);
+
+       if (-1 == daemonize ())
+               return 1;
+
+       sa.sa_handler = sig_int_term_handler;
+       sa.sa_flags   = 0;
+       sigemptyset (&sa.sa_mask);
+
+       if (0 != sigaction (SIGINT, &sa, NULL)) {
+               syslog (LOG_ERR, "Error: sigaction() failed: %s", strerror (errno));
+               return 1;
+       }
+
+       if (0 != sigaction (SIGTERM, &sa, NULL)) {
+               syslog (LOG_ERR, "Error: sigaction() failed: %s", strerror (errno));
+               return 1;
+       }
+
+       sa.sa_handler = sig_hup_handler;
+
+       if (0 != sigaction (SIGHUP, &sa, NULL)) {
+               syslog (LOG_ERR, "Error: sigaction() failed: %s", strerror (errno));
+               return 1;
+       }
+
+       while (0 == loop) {
+               int status = 0;
+
+               if (0 != collectd_start (collectd_argv)) {
+                       syslog (LOG_ERR, "Error: failed to start collectd.");
+                       break;
+               }
+
+               assert (0 < collectd_pid);
+               while ((collectd_pid != waitpid (collectd_pid, &status, 0))
+                               && (EINTR == errno))
+                       if ((0 != loop) || (0 != restart))
+                               collectd_stop ();
+
+               collectd_pid = 0;
+
+               log_status (status);
+               check_respawn ();
+
+               if (0 != restart) {
+                       syslog (LOG_INFO, "Info: restarting collectd");
+                       restart = 0;
+               }
+               else if (0 == loop)
+                       syslog (LOG_WARNING, "Warning: restarting collectd");
+       }
+
+       syslog (LOG_INFO, "Info: shutting down collectdmon");
+
+       pidfile_delete ();
+       closelog ();
+
+       free (collectd_argv);
+       return 0;
+} /* main */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/collectdmon.pod b/src/collectdmon.pod
new file mode 100644 (file)
index 0000000..8fa62f3
--- /dev/null
@@ -0,0 +1,75 @@
+=encoding UTF-8
+
+=head1 NAME
+
+collectdmon - Monitoring daemon for collectd
+
+=head1 SYNOPSIS
+
+collectdmon I<[options]> [-- I<collectd options>]
+
+=head1 DESCRIPTION
+
+collectdmon is a small "wrapper" daemon which starts and monitors the collectd
+daemon. If collectd terminates it will automatically be restarted, unless
+collectdmon was told to shut it down.
+
+=head1 OPTIONS
+
+collectdmon supports the following options:
+
+=over 4
+
+=item B<-c> I<E<lt>pathE<gt>>
+
+Specify the pathname of the collectd binary. You may either specify an
+absolute path or simply the name of the binary in which case the B<PATH>
+variable will be searched for it. The default is "B<collectd>".
+
+=item B<-P> I<E<lt>pid-fileE<gt>>
+
+Specify the pid file. The default is "I</var/run/collectdmon.pid>".
+
+=item B<-h>
+
+Output usage information and exit.
+
+=item I<collectd options>
+
+Specify options that are passed on to collectd. If it is not already included,
+B<-f> will be added to these options. See L<collectd(1)>.
+
+=back
+
+=head1 SIGNALS
+
+B<collectdmon> accepts the following signals:
+
+=over 4
+
+=item B<SIGINT>, B<SIGTERM>
+
+These signals cause B<collectdmon> to terminate B<collectd>, wait for its
+termination and then shut down.
+
+=item B<SIGHUP>
+
+This signal causes B<collectdmon> to terminate B<collectd>, wait for its
+termination and then restart it.
+
+=back
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<http://collectd.org/>
+
+=head1 AUTHOR
+
+collectd has been written by Florian Forster E<lt>octo at collectd.orgE<gt>
+and many contributors (see `AUTHORS').
+
+collectdmon has been written by Sebastian Harl E<lt>sh@tokkee.orgE<gt>.
+
+=cut
diff --git a/src/config.h.in b/src/config.h.in
new file mode 100644 (file)
index 0000000..7a22067
--- /dev/null
@@ -0,0 +1,1670 @@
+/* src/config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* User agent for http requests */
+#undef COLLECTD_USERAGENT
+
+/* wether or not to enable feature daemon mode */
+#undef COLLECT_DAEMON
+
+/* wether or not to enable feature debugging */
+#undef COLLECT_DEBUG
+
+/* wether or not to enable feature getifaddrs under Linux */
+#undef COLLECT_GETIFADDRS
+
+/* Wether or not to use the esmtp library */
+#undef COLLECT_LIBESMTP
+
+/* Define if endianflip is needed to convert to x86 representation. */
+#undef FP_LAYOUT_NEED_ENDIANFLIP
+
+/* Define if intswap is needed to convert to x86 representation. */
+#undef FP_LAYOUT_NEED_INTSWAP
+
+/* Define if doubles are stored in x86 representation. */
+#undef FP_LAYOUT_NEED_NOTHING
+
+/* Define to 1 if you have the <amqp.h> header file. */
+#undef HAVE_AMQP_H
+
+/* Define to 1 if `library_errno' is a member of `amqp_rpc_reply_t'. */
+#undef HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO
+
+/* Define to 1 if you have the <amqp_socket.h> header file. */
+#undef HAVE_AMQP_SOCKET_H
+
+/* Define if librabbitmq provides the new TCP socket interface. */
+#undef HAVE_AMQP_TCP_SOCKET
+
+/* Define to 1 if you have the <amqp_tcp_socket.h> header file. */
+#undef HAVE_AMQP_TCP_SOCKET_H
+
+/* Define to 1 if you have the `argz_add' function. */
+#undef HAVE_ARGZ_ADD
+
+/* Define to 1 if you have the `argz_append' function. */
+#undef HAVE_ARGZ_APPEND
+
+/* Define to 1 if you have the `argz_count' function. */
+#undef HAVE_ARGZ_COUNT
+
+/* Define to 1 if you have the `argz_create_sep' function. */
+#undef HAVE_ARGZ_CREATE_SEP
+
+/* Define to 1 if you have the <argz.h> header file. */
+#undef HAVE_ARGZ_H
+
+/* Define to 1 if you have the `argz_insert' function. */
+#undef HAVE_ARGZ_INSERT
+
+/* Define to 1 if you have the `argz_next' function. */
+#undef HAVE_ARGZ_NEXT
+
+/* Define to 1 if you have the `argz_stringify' function. */
+#undef HAVE_ARGZ_STRINGIFY
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <arpa/nameser_compat.h> header file. */
+#undef HAVE_ARPA_NAMESER_COMPAT_H
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#undef HAVE_ARPA_NAMESER_H
+
+/* Define to 1 if you have the <asm/msr-index.h> header file. */
+#undef HAVE_ASM_MSR_INDEX_H
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the <atasmart.h> header file. */
+#undef HAVE_ATASMART_H
+
+/* Define to 1 if you have the <bsd/nlist.h> header file. */
+#undef HAVE_BSD_NLIST_H
+
+/* Define if the clock_gettime(2) function is available. */
+#undef HAVE_CLOCK_GETTIME
+
+/* Define to 1 if you have the `closedir' function. */
+#undef HAVE_CLOSEDIR
+
+/* Define to 1 if you have the `closelog' function. */
+#undef HAVE_CLOSELOG
+
+/* Define to 1 if you have the <CoreFoundation/CoreFoundation.h> header file.
+   */
+#undef HAVE_COREFOUNDATION_COREFOUNDATION_H
+
+/* Define to 1 if you have the <cpuid.h> header file. */
+#undef HAVE_CPUID_H
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define if libcurl supports CURLOPT_TIMEOUT_MS option. */
+#undef HAVE_CURLOPT_TIMEOUT_MS
+
+/* Define if libcurl supports CURLOPT_USERNAME option. */
+#undef HAVE_CURLOPT_USERNAME
+
+/* Define to 1 if you have the <curl/curl.h> header file. */
+#undef HAVE_CURL_CURL_H
+
+/* Define to 1 if you have the <dbi/dbi.h> header file. */
+#undef HAVE_DBI_DBI_H
+
+/* Define to 1 if you have the declaration of `amqp_socket_close', and to 0 if
+   you don't. */
+#undef HAVE_DECL_AMQP_SOCKET_CLOSE
+
+/* Define to 1 if you have the declaration of `cygwin_conv_path', and to 0 if
+   you don't. */
+#undef HAVE_DECL_CYGWIN_CONV_PATH
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+   don't. */
+#undef HAVE_DECL_STRERROR_R
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the GNU dld library. */
+#undef HAVE_DLD
+
+/* Define to 1 if you have the <dld.h> header file. */
+#undef HAVE_DLD_H
+
+/* Define to 1 if you have the `dlerror' function. */
+#undef HAVE_DLERROR
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <dl.h> header file. */
+#undef HAVE_DL_H
+
+/* Define if you have the _dyld_func_lookup function. */
+#undef HAVE_DYLD
+
+/* Define to 1 if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if the system has the type `error_t'. */
+#undef HAVE_ERROR_T
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#undef HAVE_FNMATCH_H
+
+/* Define to 1 if you have the <fshelp.h> header file. */
+#undef HAVE_FSHELP_H
+
+/* Define to 1 if you have the <fs_info.h> header file. */
+#undef HAVE_FS_INFO_H
+
+/* Define to 1 if you have the <gcrypt.h> header file. */
+#undef HAVE_GCRYPT_H
+
+/* Define if the function getmntent exists. It's the version from libgen. */
+#undef HAVE_GEN_GETMNTENT
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getfsstat' function. */
+#undef HAVE_GETFSSTAT
+
+/* Define to 1 if you have the `getgrnam_r' function. */
+#undef HAVE_GETGRNAM_R
+
+/* Define to 1 if you have the `getifaddrs' function. */
+#undef HAVE_GETIFADDRS
+
+/* Define to 1 if you have the `getloadavg' function. */
+#undef HAVE_GETLOADAVG
+
+/* Define to 1 if you have the `getmntent' function. */
+#undef HAVE_GETMNTENT
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if you have the `getpwnam_r' function. */
+#undef HAVE_GETPWNAM_R
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `getutent' function. */
+#undef HAVE_GETUTENT
+
+/* Define to 1 if you have the `getutxent' function. */
+#undef HAVE_GETUTXENT
+
+/* Define to 1 if you have the `getvfsstat' function. */
+#undef HAVE_GETVFSSTAT
+
+/* Define to 1 if you have the <gm_protocol.h> header file. */
+#undef HAVE_GM_PROTOCOL_H
+
+/* Define to 1 if you have the <google/protobuf-c/protobuf-c.h> header file.
+   */
+#undef HAVE_GOOGLE_PROTOBUF_C_PROTOBUF_C_H
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
+#undef HAVE_HIREDIS_HIREDIS_H
+
+/* Define to 1 if you have the `host_statistics' function. */
+#undef HAVE_HOST_STATISTICS
+
+/* Define if the function htonll exists. */
+#undef HAVE_HTONLL
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define to 1 if you have the `if_indextoname' function. */
+#undef HAVE_IF_INDEXTONAME
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <IOKit/IOBSD.h> header file. */
+#undef HAVE_IOKIT_IOBSD_H
+
+/* Define to 1 if you have the <IOKit/IOKitLib.h> header file. */
+#undef HAVE_IOKIT_IOKITLIB_H
+
+/* Define to 1 if you have the <IOKit/IOTypes.h> header file. */
+#undef HAVE_IOKIT_IOTYPES_H
+
+/* Define to 1 if you have the <IOKit/ps/IOPowerSources.h> header file. */
+#undef HAVE_IOKIT_PS_IOPOWERSOURCES_H
+
+/* Define to 1 if you have the <IOKit/ps/IOPSKeys.h> header file. */
+#undef HAVE_IOKIT_PS_IOPSKEYS_H
+
+/* Define to 1 if you have the <IOKit/storage/IOBlockStorageDriver.h> header
+   file. */
+#undef HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDRIVER_H
+
+/* Define to 1 if the system has the type `ip6tc_handle_t'. */
+#undef HAVE_IP6TC_HANDLE_T
+
+/* Define to 1 if the system has the type `iptc_handle_t'. */
+#undef HAVE_IPTC_HANDLE_T
+
+/* Define to 1 if you have the <ip_vs.h> header file. */
+#undef HAVE_IP_VS_H
+
+/* Define to 1 if you have the <jni.h> header file. */
+#undef HAVE_JNI_H
+
+/* Define to 1 if you have the <kstat.h> header file. */
+#undef HAVE_KSTAT_H
+
+/* Define to 1 if `nwrites' is a member of `kstat_io_t'. */
+#undef HAVE_KSTAT_IO_T_NWRITES
+
+/* Define to 1 if `nwritten' is a member of `kstat_io_t'. */
+#undef HAVE_KSTAT_IO_T_NWRITTEN
+
+/* Define to 1 if `writes' is a member of `kstat_io_t'. */
+#undef HAVE_KSTAT_IO_T_WRITES
+
+/* Define to 1 if `wtime' is a member of `kstat_io_t'. */
+#undef HAVE_KSTAT_IO_T_WTIME
+
+/* Define to 1 if you have the <kvm.h> header file. */
+#undef HAVE_KVM_H
+
+/* Define to 1 if you have the <ldap.h> header file. */
+#undef HAVE_LDAP_H
+
+/* Define to 1 if you have the <libaquaero5.h> header file. */
+#undef HAVE_LIBAQUAERO5_H
+
+/* Define if libatasmart is present and usable. */
+#undef HAVE_LIBATASMART
+
+/* Define if you have the libdl library or equivalent. */
+#undef HAVE_LIBDL
+
+/* Define if libdlloader will be built on this platform */
+#undef HAVE_LIBDLLOADER
+
+/* Define to 1 if you have the esmtp library (-lesmtp). */
+#undef HAVE_LIBESMTP
+
+/* Define to 1 if you have the <libesmtp.h> header file. */
+#undef HAVE_LIBESMTP_H
+
+/* Define to 1 if you have the ganglia library (-lganglia). */
+#undef HAVE_LIBGANGLIA
+
+/* Define to 1 if you have the gcrypt library (-lgcrypt). */
+#undef HAVE_LIBGCRYPT
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have 'hal' library */
+#undef HAVE_LIBHAL
+
+/* Define to 1 if you have the <libiptc/libip6tc.h> header file. */
+#undef HAVE_LIBIPTC_LIBIP6TC_H
+
+/* Define to 1 if you have the <libiptc/libiptc.h> header file. */
+#undef HAVE_LIBIPTC_LIBIPTC_H
+
+/* Define to 1 if you have the 'kstat' library (-lkstat) */
+#undef HAVE_LIBKSTAT
+
+/* Define to 1 if you have the 'kvm' library with the 'kvm_getprocs' symbol
+   (-lkvm) */
+#undef HAVE_LIBKVM_GETPROCS
+
+/* Define to 1 if you have the 'kvm' library with the 'kvm_getswapinfo' symbol
+   (-lkvm) */
+#undef HAVE_LIBKVM_GETSWAPINFO
+
+/* Define to 1 if you have the 'kvm' library with the 'kvm_openfiles' symbol
+   (-lkvm) */
+#undef HAVE_LIBKVM_NLIST
+
+/* Define if liblvm2app is present and usable. */
+#undef HAVE_LIBLVM2APP
+
+/* Define if libmemcached is present and usable. */
+#undef HAVE_LIBMEMCACHED
+
+/* Define to 1 if you have the <libmemcached/memcached.h> header file. */
+#undef HAVE_LIBMEMCACHED_MEMCACHED_H
+
+/* Define if libmnl is present and usable. */
+#undef HAVE_LIBMNL
+
+/* Define to 1 if you have the <libmnl.h> header file. */
+#undef HAVE_LIBMNL_H
+
+/* Define to 1 if you have the <libmnl/libmnl.h> header file. */
+#undef HAVE_LIBMNL_LIBMNL_H
+
+/* Define to 1 if you have the netapp library (-lnetapp). */
+#undef HAVE_LIBNETAPP
+
+/* Define to 1 if you have the pcap library (-lpcap). */
+#undef HAVE_LIBPCAP
+
+/* Define if libperl is present and usable. */
+#undef HAVE_LIBPERL
+
+/* Define to 1 if you have the <libpq-fe.h> header file. */
+#undef HAVE_LIBPQ_FE_H
+
+/* Wether or not to use pthread (POSIX threads) library */
+#undef HAVE_LIBPTHREAD
+
+/* Define if librabbitmq is present and usable. */
+#undef HAVE_LIBRABBITMQ
+
+/* Define if librdkafka is present and usable. */
+#undef HAVE_LIBRDKAFKA
+
+/* Define if librdkafka log facility is present and usable. */
+#undef HAVE_LIBRDKAFKA_LOGGER
+
+/* Define if librdkafka log facility is present and usable. */
+#undef HAVE_LIBRDKAFKA_LOG_CB
+
+/* Define to 1 if you have the <librdkafka/rdkafka.h> header file. */
+#undef HAVE_LIBRDKAFKA_RDKAFKA_H
+
+/* Define to 1 if you have the 'resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define to 1 if you have the sensors library (-lsensors). */
+#undef HAVE_LIBSENSORS
+
+/* Define to 1 if you have the sigrok library (-lsigrok). */
+#undef HAVE_LIBSIGROK
+
+/* Define to 1 if you have the <libsigrok/libsigrok.h> header file. */
+#undef HAVE_LIBSIGROK_LIBSIGROK_H
+
+/* Define to 1 if you have the 'statgrab' library (-lstatgrab) */
+#undef HAVE_LIBSTATGRAB
+
+/* Define to 1 if libstatgrab version >= 0.90 */
+#undef HAVE_LIBSTATGRAB_0_90
+
+/* Define to 1 if you have the tokyotyrant library (-ltokyotyrant). */
+#undef HAVE_LIBTOKYOTYRANT
+
+/* Define to 1 if you have the udev library (-ludev). */
+#undef HAVE_LIBUDEV
+
+/* Define to 1 if you have the <libudev.h> header file. */
+#undef HAVE_LIBUDEV_H
+
+/* Define to 1 if you have the <libvirt/libvirt.h> header file. */
+#undef HAVE_LIBVIRT_LIBVIRT_H
+
+/* Define to 1 if you have the <libxml/parser.h> header file. */
+#undef HAVE_LIBXML_PARSER_H
+
+/* Define to 1 if you have the 'xmms' library (-lxmms). */
+#undef HAVE_LIBXMMS
+
+/* Define if libyajl is present and usable. */
+#undef HAVE_LIBYAJL
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <linux/config.h> header file. */
+#undef HAVE_LINUX_CONFIG_H
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+#undef HAVE_LINUX_ETHTOOL_H
+
+/* Define to 1 if you have the <linux/gen_stats.h> header file. */
+#undef HAVE_LINUX_GEN_STATS_H
+
+/* Define to 1 if you have the <linux/if.h> header file. */
+#undef HAVE_LINUX_IF_H
+
+/* Define to 1 if you have the <linux/inet_diag.h> header file. */
+#undef HAVE_LINUX_INET_DIAG_H
+
+/* Define to 1 if you have the <linux/ip_vs.h> header file. */
+#undef HAVE_LINUX_IP_VS_H
+
+/* Define to 1 if you have the <linux/major.h> header file. */
+#undef HAVE_LINUX_MAJOR_H
+
+/* Define to 1 if you have the <linux/netdevice.h> header file. */
+#undef HAVE_LINUX_NETDEVICE_H
+
+/* Define to 1 if you have the <linux/pkt_sched.h> header file. */
+#undef HAVE_LINUX_PKT_SCHED_H
+
+/* Define to 1 if you have the <linux/raid/md_u.h> header file. */
+#undef HAVE_LINUX_RAID_MD_U_H
+
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+#undef HAVE_LINUX_SOCKIOS_H
+
+/* Define to 1 if you have the <linux/un.h> header file. */
+#undef HAVE_LINUX_UN_H
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+#undef HAVE_LINUX_WIRELESS_H
+
+/* Define to 1 if you have the `listmntent' function. */
+#undef HAVE_LISTMNTENT
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define this if a modern libltdl is already installed */
+#undef HAVE_LTDL
+
+/* Define to 1 if you have the <lvm2app.h> header file. */
+#undef HAVE_LVM2APP_H
+
+/* Define to 1 if you have the <mach/host_priv.h> header file. */
+#undef HAVE_MACH_HOST_PRIV_H
+
+/* Define to 1 if you have the <mach/kern_return.h> header file. */
+#undef HAVE_MACH_KERN_RETURN_H
+
+/* Define to 1 if you have the <mach/mach_error.h> header file. */
+#undef HAVE_MACH_MACH_ERROR_H
+
+/* Define to 1 if you have the <mach/mach_host.h> header file. */
+#undef HAVE_MACH_MACH_HOST_H
+
+/* Define to 1 if you have the <mach/mach_init.h> header file. */
+#undef HAVE_MACH_MACH_INIT_H
+
+/* Define to 1 if you have the <mach/mach_port.h> header file. */
+#undef HAVE_MACH_MACH_PORT_H
+
+/* Define to 1 if you have the <mach/mach_types.h> header file. */
+#undef HAVE_MACH_MACH_TYPES_H
+
+/* Define to 1 if you have the <mach/message.h> header file. */
+#undef HAVE_MACH_MESSAGE_H
+
+/* Define to 1 if you have the <mach-o/dyld.h> header file. */
+#undef HAVE_MACH_O_DYLD_H
+
+/* Define to 1 if you have the <mach/processor.h> header file. */
+#undef HAVE_MACH_PROCESSOR_H
+
+/* Define to 1 if you have the <mach/processor_info.h> header file. */
+#undef HAVE_MACH_PROCESSOR_INFO_H
+
+/* Define to 1 if you have the <mach/processor_set.h> header file. */
+#undef HAVE_MACH_PROCESSOR_SET_H
+
+/* Define to 1 if you have the <mach/task.h> header file. */
+#undef HAVE_MACH_TASK_H
+
+/* Define to 1 if you have the <mach/thread_act.h> header file. */
+#undef HAVE_MACH_THREAD_ACT_H
+
+/* Define to 1 if you have the <mach/vm_map.h> header file. */
+#undef HAVE_MACH_VM_MAP_H
+
+/* Define to 1 if you have the <mach/vm_prot.h> header file. */
+#undef HAVE_MACH_VM_PROT_H
+
+/* Define to 1 if you have the <mach/vm_region.h> header file. */
+#undef HAVE_MACH_VM_REGION_H
+
+/* Define to 1 if you have the <mach/vm_statistics.h> header file. */
+#undef HAVE_MACH_VM_STATISTICS_H
+
+/* Define to 1 if you have the <math.h> header file. */
+#undef HAVE_MATH_H
+
+/* Define to 1 if you have the `memcpy' function. */
+#undef HAVE_MEMCPY
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <MicAccessApi.h> header file. */
+#undef HAVE_MICACCESSAPI_H
+
+/* Define to 1 if you have the <mntent.h> header file. */
+#undef HAVE_MNTENT_H
+
+/* Define to 1 if you have the <mnttab.h> header file. */
+#undef HAVE_MNTTAB_H
+
+/* Define to 1 if you have the <modbus/modbus.h> header file. */
+#undef HAVE_MODBUS_MODBUS_H
+
+/* Define to 1 if you have the <mongo.h> header file. */
+#undef HAVE_MONGO_H
+
+/* Define to 1 if you have the <mysql.h> header file. */
+#undef HAVE_MYSQL_H
+
+/* Define to 1 if you have the <mysql/mysql.h> header file. */
+#undef HAVE_MYSQL_MYSQL_H
+
+/* Define to 1 if you have the `nanosleep' function. */
+#undef HAVE_NANOSLEEP
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netapp_api.h> header file. */
+#undef HAVE_NETAPP_API_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/icmp6.h> header file. */
+#undef HAVE_NETINET_ICMP6_H
+
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+#undef HAVE_NETINET_IF_ETHER_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#undef HAVE_NETINET_IN_SYSTM_H
+
+/* Define to 1 if you have the <netinet/ip6.h> header file. */
+#undef HAVE_NETINET_IP6_H
+
+/* Define to 1 if you have the <netinet/ip_compat.h> header file. */
+#undef HAVE_NETINET_IP_COMPAT_H
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+#undef HAVE_NETINET_IP_H
+
+/* Define to 1 if you have the <netinet/ip_icmp.h> header file. */
+#undef HAVE_NETINET_IP_ICMP_H
+
+/* Define to 1 if you have the <netinet/ip_var.h> header file. */
+#undef HAVE_NETINET_IP_VAR_H
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define to 1 if you have the <netinet/udp.h> header file. */
+#undef HAVE_NETINET_UDP_H
+
+/* Define to 1 if you have the <net/if_arp.h> header file. */
+#undef HAVE_NET_IF_ARP_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define to 1 if you have the <net/if_ppp.h> header file. */
+#undef HAVE_NET_IF_PPP_H
+
+/* Define to 1 if you have the <net/ip_vs.h> header file. */
+#undef HAVE_NET_IP_VS_H
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+#undef HAVE_NET_PFVAR_H
+
+/* Define to 1 if you have the <net/ppp_defs.h> header file. */
+#undef HAVE_NET_PPP_DEFS_H
+
+/* Define to 1 if you have the <net-snmp/net-snmp-config.h> header file. */
+#undef HAVE_NET_SNMP_NET_SNMP_CONFIG_H
+
+/* Define to 1 if you have the <nlist.h> header file. */
+#undef HAVE_NLIST_H
+
+/* Define to 1 if you have the <oci.h> header file. */
+#undef HAVE_OCI_H
+
+/* Define if the function getmntent exists and takes one argument. */
+#undef HAVE_ONE_GETMNTENT
+
+/* Define to 1 if you have the `opendir' function. */
+#undef HAVE_OPENDIR
+
+/* Define to 1 if you have the <OpenIPMI/ipmi_smi.h> header file. */
+#undef HAVE_OPENIPMI_IPMI_SMI_H
+
+/* Define to 1 if you have the `openlog' function. */
+#undef HAVE_OPENLOG
+
+/* Define to 1 if you have the <oping.h> header file. */
+#undef HAVE_OPING_H
+
+/* Define to 1 if you have the <owcapi.h> header file. */
+#undef HAVE_OWCAPI_H
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define to 1 if you have the <pcap-bpf.h> header file. */
+#undef HAVE_PCAP_BPF_H
+
+/* Define to 1 if you have the <pcap.h> header file. */
+#undef HAVE_PCAP_H
+
+/* Define to 1 if you have the 'perfstat' library (-lperfstat) */
+#undef HAVE_PERFSTAT
+
+/* Define if Perl supports ithreads. */
+#undef HAVE_PERL_ITHREADS
+
+/* Define if Perl's struct mgvtbl has member svt_local. */
+#undef HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL
+
+/* Define to 1 if the aggregation plugin is enabled. */
+#undef HAVE_PLUGIN_AGGREGATION
+
+/* Define to 1 if the amqp plugin is enabled. */
+#undef HAVE_PLUGIN_AMQP
+
+/* Define to 1 if the apache plugin is enabled. */
+#undef HAVE_PLUGIN_APACHE
+
+/* Define to 1 if the apcups plugin is enabled. */
+#undef HAVE_PLUGIN_APCUPS
+
+/* Define to 1 if the apple_sensors plugin is enabled. */
+#undef HAVE_PLUGIN_APPLE_SENSORS
+
+/* Define to 1 if the aquaero plugin is enabled. */
+#undef HAVE_PLUGIN_AQUAERO
+
+/* Define to 1 if the ascent plugin is enabled. */
+#undef HAVE_PLUGIN_ASCENT
+
+/* Define to 1 if the barometer plugin is enabled. */
+#undef HAVE_PLUGIN_BAROMETER
+
+/* Define to 1 if the battery plugin is enabled. */
+#undef HAVE_PLUGIN_BATTERY
+
+/* Define to 1 if the bind plugin is enabled. */
+#undef HAVE_PLUGIN_BIND
+
+/* Define to 1 if the ceph plugin is enabled. */
+#undef HAVE_PLUGIN_CEPH
+
+/* Define to 1 if the cgroups plugin is enabled. */
+#undef HAVE_PLUGIN_CGROUPS
+
+/* Define to 1 if the conntrack plugin is enabled. */
+#undef HAVE_PLUGIN_CONNTRACK
+
+/* Define to 1 if the contextswitch plugin is enabled. */
+#undef HAVE_PLUGIN_CONTEXTSWITCH
+
+/* Define to 1 if the cpu plugin is enabled. */
+#undef HAVE_PLUGIN_CPU
+
+/* Define to 1 if the cpufreq plugin is enabled. */
+#undef HAVE_PLUGIN_CPUFREQ
+
+/* Define to 1 if the csv plugin is enabled. */
+#undef HAVE_PLUGIN_CSV
+
+/* Define to 1 if the curl plugin is enabled. */
+#undef HAVE_PLUGIN_CURL
+
+/* Define to 1 if the curl_json plugin is enabled. */
+#undef HAVE_PLUGIN_CURL_JSON
+
+/* Define to 1 if the curl_xml plugin is enabled. */
+#undef HAVE_PLUGIN_CURL_XML
+
+/* Define to 1 if the dbi plugin is enabled. */
+#undef HAVE_PLUGIN_DBI
+
+/* Define to 1 if the df plugin is enabled. */
+#undef HAVE_PLUGIN_DF
+
+/* Define to 1 if the disk plugin is enabled. */
+#undef HAVE_PLUGIN_DISK
+
+/* Define to 1 if the dns plugin is enabled. */
+#undef HAVE_PLUGIN_DNS
+
+/* Define to 1 if the drbd plugin is enabled. */
+#undef HAVE_PLUGIN_DRBD
+
+/* Define to 1 if the email plugin is enabled. */
+#undef HAVE_PLUGIN_EMAIL
+
+/* Define to 1 if the entropy plugin is enabled. */
+#undef HAVE_PLUGIN_ENTROPY
+
+/* Define to 1 if the ethstat plugin is enabled. */
+#undef HAVE_PLUGIN_ETHSTAT
+
+/* Define to 1 if the exec plugin is enabled. */
+#undef HAVE_PLUGIN_EXEC
+
+/* Define to 1 if the fhcount plugin is enabled. */
+#undef HAVE_PLUGIN_FHCOUNT
+
+/* Define to 1 if the filecount plugin is enabled. */
+#undef HAVE_PLUGIN_FILECOUNT
+
+/* Define to 1 if the fscache plugin is enabled. */
+#undef HAVE_PLUGIN_FSCACHE
+
+/* Define to 1 if the gmond plugin is enabled. */
+#undef HAVE_PLUGIN_GMOND
+
+/* Define to 1 if the hddtemp plugin is enabled. */
+#undef HAVE_PLUGIN_HDDTEMP
+
+/* Define to 1 if the interface plugin is enabled. */
+#undef HAVE_PLUGIN_INTERFACE
+
+/* Define to 1 if the ipc plugin is enabled. */
+#undef HAVE_PLUGIN_IPC
+
+/* Define to 1 if the ipmi plugin is enabled. */
+#undef HAVE_PLUGIN_IPMI
+
+/* Define to 1 if the iptables plugin is enabled. */
+#undef HAVE_PLUGIN_IPTABLES
+
+/* Define to 1 if the ipvs plugin is enabled. */
+#undef HAVE_PLUGIN_IPVS
+
+/* Define to 1 if the irq plugin is enabled. */
+#undef HAVE_PLUGIN_IRQ
+
+/* Define to 1 if the java plugin is enabled. */
+#undef HAVE_PLUGIN_JAVA
+
+/* Define to 1 if the load plugin is enabled. */
+#undef HAVE_PLUGIN_LOAD
+
+/* Define to 1 if the logfile plugin is enabled. */
+#undef HAVE_PLUGIN_LOGFILE
+
+/* Define to 1 if the log_logstash plugin is enabled. */
+#undef HAVE_PLUGIN_LOG_LOGSTASH
+
+/* Define to 1 if the lpar plugin is enabled. */
+#undef HAVE_PLUGIN_LPAR
+
+/* Define to 1 if the lvm plugin is enabled. */
+#undef HAVE_PLUGIN_LVM
+
+/* Define to 1 if the madwifi plugin is enabled. */
+#undef HAVE_PLUGIN_MADWIFI
+
+/* Define to 1 if the match_empty_counter plugin is enabled. */
+#undef HAVE_PLUGIN_MATCH_EMPTY_COUNTER
+
+/* Define to 1 if the match_hashed plugin is enabled. */
+#undef HAVE_PLUGIN_MATCH_HASHED
+
+/* Define to 1 if the match_regex plugin is enabled. */
+#undef HAVE_PLUGIN_MATCH_REGEX
+
+/* Define to 1 if the match_timediff plugin is enabled. */
+#undef HAVE_PLUGIN_MATCH_TIMEDIFF
+
+/* Define to 1 if the match_value plugin is enabled. */
+#undef HAVE_PLUGIN_MATCH_VALUE
+
+/* Define to 1 if the mbmon plugin is enabled. */
+#undef HAVE_PLUGIN_MBMON
+
+/* Define to 1 if the md plugin is enabled. */
+#undef HAVE_PLUGIN_MD
+
+/* Define to 1 if the memcachec plugin is enabled. */
+#undef HAVE_PLUGIN_MEMCACHEC
+
+/* Define to 1 if the memcached plugin is enabled. */
+#undef HAVE_PLUGIN_MEMCACHED
+
+/* Define to 1 if the memory plugin is enabled. */
+#undef HAVE_PLUGIN_MEMORY
+
+/* Define to 1 if the mic plugin is enabled. */
+#undef HAVE_PLUGIN_MIC
+
+/* Define to 1 if the modbus plugin is enabled. */
+#undef HAVE_PLUGIN_MODBUS
+
+/* Define to 1 if the multimeter plugin is enabled. */
+#undef HAVE_PLUGIN_MULTIMETER
+
+/* Define to 1 if the mysql plugin is enabled. */
+#undef HAVE_PLUGIN_MYSQL
+
+/* Define to 1 if the netapp plugin is enabled. */
+#undef HAVE_PLUGIN_NETAPP
+
+/* Define to 1 if the netlink plugin is enabled. */
+#undef HAVE_PLUGIN_NETLINK
+
+/* Define to 1 if the network plugin is enabled. */
+#undef HAVE_PLUGIN_NETWORK
+
+/* Define to 1 if the nfs plugin is enabled. */
+#undef HAVE_PLUGIN_NFS
+
+/* Define to 1 if the nginx plugin is enabled. */
+#undef HAVE_PLUGIN_NGINX
+
+/* Define to 1 if the notify_desktop plugin is enabled. */
+#undef HAVE_PLUGIN_NOTIFY_DESKTOP
+
+/* Define to 1 if the notify_email plugin is enabled. */
+#undef HAVE_PLUGIN_NOTIFY_EMAIL
+
+/* Define to 1 if the ntpd plugin is enabled. */
+#undef HAVE_PLUGIN_NTPD
+
+/* Define to 1 if the numa plugin is enabled. */
+#undef HAVE_PLUGIN_NUMA
+
+/* Define to 1 if the nut plugin is enabled. */
+#undef HAVE_PLUGIN_NUT
+
+/* Define to 1 if the olsrd plugin is enabled. */
+#undef HAVE_PLUGIN_OLSRD
+
+/* Define to 1 if the onewire plugin is enabled. */
+#undef HAVE_PLUGIN_ONEWIRE
+
+/* Define to 1 if the openldap plugin is enabled. */
+#undef HAVE_PLUGIN_OPENLDAP
+
+/* Define to 1 if the openvpn plugin is enabled. */
+#undef HAVE_PLUGIN_OPENVPN
+
+/* Define to 1 if the oracle plugin is enabled. */
+#undef HAVE_PLUGIN_ORACLE
+
+/* Define to 1 if the perl plugin is enabled. */
+#undef HAVE_PLUGIN_PERL
+
+/* Define to 1 if the pf plugin is enabled. */
+#undef HAVE_PLUGIN_PF
+
+/* Define to 1 if the pinba plugin is enabled. */
+#undef HAVE_PLUGIN_PINBA
+
+/* Define to 1 if the ping plugin is enabled. */
+#undef HAVE_PLUGIN_PING
+
+/* Define to 1 if the postgresql plugin is enabled. */
+#undef HAVE_PLUGIN_POSTGRESQL
+
+/* Define to 1 if the powerdns plugin is enabled. */
+#undef HAVE_PLUGIN_POWERDNS
+
+/* Define to 1 if the processes plugin is enabled. */
+#undef HAVE_PLUGIN_PROCESSES
+
+/* Define to 1 if the protocols plugin is enabled. */
+#undef HAVE_PLUGIN_PROTOCOLS
+
+/* Define to 1 if the python plugin is enabled. */
+#undef HAVE_PLUGIN_PYTHON
+
+/* Define to 1 if the redis plugin is enabled. */
+#undef HAVE_PLUGIN_REDIS
+
+/* Define to 1 if the routeros plugin is enabled. */
+#undef HAVE_PLUGIN_ROUTEROS
+
+/* Define to 1 if the rrdcached plugin is enabled. */
+#undef HAVE_PLUGIN_RRDCACHED
+
+/* Define to 1 if the rrdtool plugin is enabled. */
+#undef HAVE_PLUGIN_RRDTOOL
+
+/* Define to 1 if the sensors plugin is enabled. */
+#undef HAVE_PLUGIN_SENSORS
+
+/* Define to 1 if the serial plugin is enabled. */
+#undef HAVE_PLUGIN_SERIAL
+
+/* Define to 1 if the sigrok plugin is enabled. */
+#undef HAVE_PLUGIN_SIGROK
+
+/* Define to 1 if the smart plugin is enabled. */
+#undef HAVE_PLUGIN_SMART
+
+/* Define to 1 if the snmp plugin is enabled. */
+#undef HAVE_PLUGIN_SNMP
+
+/* Define to 1 if the statsd plugin is enabled. */
+#undef HAVE_PLUGIN_STATSD
+
+/* Define to 1 if the swap plugin is enabled. */
+#undef HAVE_PLUGIN_SWAP
+
+/* Define to 1 if the syslog plugin is enabled. */
+#undef HAVE_PLUGIN_SYSLOG
+
+/* Define to 1 if the table plugin is enabled. */
+#undef HAVE_PLUGIN_TABLE
+
+/* Define to 1 if the tail plugin is enabled. */
+#undef HAVE_PLUGIN_TAIL
+
+/* Define to 1 if the tail_csv plugin is enabled. */
+#undef HAVE_PLUGIN_TAIL_CSV
+
+/* Define to 1 if the tape plugin is enabled. */
+#undef HAVE_PLUGIN_TAPE
+
+/* Define to 1 if the target_notification plugin is enabled. */
+#undef HAVE_PLUGIN_TARGET_NOTIFICATION
+
+/* Define to 1 if the target_replace plugin is enabled. */
+#undef HAVE_PLUGIN_TARGET_REPLACE
+
+/* Define to 1 if the target_scale plugin is enabled. */
+#undef HAVE_PLUGIN_TARGET_SCALE
+
+/* Define to 1 if the target_set plugin is enabled. */
+#undef HAVE_PLUGIN_TARGET_SET
+
+/* Define to 1 if the target_v5upgrade plugin is enabled. */
+#undef HAVE_PLUGIN_TARGET_V5UPGRADE
+
+/* Define to 1 if the tcpconns plugin is enabled. */
+#undef HAVE_PLUGIN_TCPCONNS
+
+/* Define to 1 if the teamspeak2 plugin is enabled. */
+#undef HAVE_PLUGIN_TEAMSPEAK2
+
+/* Define to 1 if the ted plugin is enabled. */
+#undef HAVE_PLUGIN_TED
+
+/* Define to 1 if the thermal plugin is enabled. */
+#undef HAVE_PLUGIN_THERMAL
+
+/* Define to 1 if the threshold plugin is enabled. */
+#undef HAVE_PLUGIN_THRESHOLD
+
+/* Define to 1 if the tokyotyrant plugin is enabled. */
+#undef HAVE_PLUGIN_TOKYOTYRANT
+
+/* Define to 1 if the turbostat plugin is enabled. */
+#undef HAVE_PLUGIN_TURBOSTAT
+
+/* Define to 1 if the unixsock plugin is enabled. */
+#undef HAVE_PLUGIN_UNIXSOCK
+
+/* Define to 1 if the uptime plugin is enabled. */
+#undef HAVE_PLUGIN_UPTIME
+
+/* Define to 1 if the users plugin is enabled. */
+#undef HAVE_PLUGIN_USERS
+
+/* Define to 1 if the uuid plugin is enabled. */
+#undef HAVE_PLUGIN_UUID
+
+/* Define to 1 if the varnish plugin is enabled. */
+#undef HAVE_PLUGIN_VARNISH
+
+/* Define to 1 if the virt plugin is enabled. */
+#undef HAVE_PLUGIN_VIRT
+
+/* Define to 1 if the vmem plugin is enabled. */
+#undef HAVE_PLUGIN_VMEM
+
+/* Define to 1 if the vserver plugin is enabled. */
+#undef HAVE_PLUGIN_VSERVER
+
+/* Define to 1 if the wireless plugin is enabled. */
+#undef HAVE_PLUGIN_WIRELESS
+
+/* Define to 1 if the write_graphite plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_GRAPHITE
+
+/* Define to 1 if the write_http plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_HTTP
+
+/* Define to 1 if the write_kafka plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_KAFKA
+
+/* Define to 1 if the write_log plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_LOG
+
+/* Define to 1 if the write_mongodb plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_MONGODB
+
+/* Define to 1 if the write_redis plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_REDIS
+
+/* Define to 1 if the write_riemann plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_RIEMANN
+
+/* Define to 1 if the write_sensu plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_SENSU
+
+/* Define to 1 if the write_tsdb plugin is enabled. */
+#undef HAVE_PLUGIN_WRITE_TSDB
+
+/* Define to 1 if the xmms plugin is enabled. */
+#undef HAVE_PLUGIN_XMMS
+
+/* Define to 1 if the zfs_arc plugin is enabled. */
+#undef HAVE_PLUGIN_ZFS_ARC
+
+/* Define to 1 if the zookeeper plugin is enabled. */
+#undef HAVE_PLUGIN_ZOOKEEPER
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define if libtool can extract symbol lists from object files. */
+#undef HAVE_PRELOADED_SYMBOLS
+
+/* Define to 1 if you have the `processor_info' function. */
+#undef HAVE_PROCESSOR_INFO
+
+/* Define to 1 if you have the procinfo.h */
+#undef HAVE_PROCINFO_H
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define to 1 if you have the <Python.h> header file. */
+#undef HAVE_PYTHON_H
+
+/* Define to 1 if you have the `readdir' function. */
+#undef HAVE_READDIR
+
+/* Define to 1 if you have the `regcomp' function. */
+#undef HAVE_REGCOMP
+
+/* Define to 1 if you have the `regerror' function. */
+#undef HAVE_REGERROR
+
+/* Define to 1 if you have the `regexec' function. */
+#undef HAVE_REGEXEC
+
+/* Define to 1 if you have the <regex.h> header file. */
+#undef HAVE_REGEX_H
+
+/* Define to 1 if you have the `regfree' function. */
+#undef HAVE_REGFREE
+
+/* Define to 1 if you have the <routeros_api.h> header file. */
+#undef HAVE_ROUTEROS_API_H
+
+/* Define to 1 if you have the <rrd.h> header file. */
+#undef HAVE_RRD_H
+
+/* Define if struct rtnl_link_stats64 exists and is usable. */
+#undef HAVE_RTNL_LINK_STATS64
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the <sensors/sensors.h> header file. */
+#undef HAVE_SENSORS_SENSORS_H
+
+/* Define if the function getmntent exists. It's the version from libseq. */
+#undef HAVE_SEQ_GETMNTENT
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `setgroups' function. */
+#undef HAVE_SETGROUPS
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the shl_load function. */
+#undef HAVE_SHL_LOAD
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the `statfs' function. */
+#undef HAVE_STATFS
+
+/* Define to 1 if you have the <statgrab.h> header file. */
+#undef HAVE_STATGRAB_H
+
+/* Define to 1 if you have the `statvfs' function. */
+#undef HAVE_STATVFS
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#undef HAVE_STDARG_H
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strcmp' function. */
+#undef HAVE_STRCMP
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror_r' function. */
+#undef HAVE_STRERROR_R
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strlen' function. */
+#undef HAVE_STRLEN
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the `strncmp' function. */
+#undef HAVE_STRNCMP
+
+/* Define to 1 if you have the `strncpy' function. */
+#undef HAVE_STRNCPY
+
+/* Define to 1 if you have the `strptime' function. */
+#undef HAVE_STRPTIME
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define if struct if_data exists and is usable. */
+#undef HAVE_STRUCT_IF_DATA
+
+/* Define to 1 if `ifi_ibytes' is a member of `struct if_data'. */
+#undef HAVE_STRUCT_IF_DATA_IFI_IBYTES
+
+/* Define to 1 if `ifi_ierrors' is a member of `struct if_data'. */
+#undef HAVE_STRUCT_IF_DATA_IFI_IERRORS
+
+/* Define to 1 if `ifi_opackets' is a member of `struct if_data'. */
+#undef HAVE_STRUCT_IF_DATA_IFI_OPACKETS
+
+/* Define to 1 if `id' is a member of `struct inet_diag_req'. */
+#undef HAVE_STRUCT_INET_DIAG_REQ_ID
+
+/* Define to 1 if `idiag_states' is a member of `struct inet_diag_req'. */
+#undef HAVE_STRUCT_INET_DIAG_REQ_IDIAG_STATES
+
+/* Define to 1 if `imr_ifindex' is a member of `struct ip_mreqn'. */
+#undef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+
+/* Define if struct kinfo_proc exists in the FreeBSD variant. */
+#undef HAVE_STRUCT_KINFO_PROC_FREEBSD
+
+/* Define to 1 if `ki_pid' is a member of `struct kinfo_proc'. */
+#undef HAVE_STRUCT_KINFO_PROC_KI_PID
+
+/* Define to 1 if `ki_rssize' is a member of `struct kinfo_proc'. */
+#undef HAVE_STRUCT_KINFO_PROC_KI_RSSIZE
+
+/* Define to 1 if `ki_rusage' is a member of `struct kinfo_proc'. */
+#undef HAVE_STRUCT_KINFO_PROC_KI_RUSAGE
+
+/* Define if struct kinfo_proc exists in the OpenBSD variant. */
+#undef HAVE_STRUCT_KINFO_PROC_OPENBSD
+
+/* Define to 1 if `p_pid' is a member of `struct kinfo_proc'. */
+#undef HAVE_STRUCT_KINFO_PROC_P_PID
+
+/* Define to 1 if `p_vm_rssize' is a member of `struct kinfo_proc'. */
+#undef HAVE_STRUCT_KINFO_PROC_P_VM_RSSIZE
+
+/* Define if struct inet_diag_req exists and is usable. */
+#undef HAVE_STRUCT_LINUX_INET_DIAG_REQ
+
+/* Define if struct net_device_stats exists and is usable. */
+#undef HAVE_STRUCT_NET_DEVICE_STATS
+
+/* Define to 1 if `rx_bytes' is a member of `struct net_device_stats'. */
+#undef HAVE_STRUCT_NET_DEVICE_STATS_RX_BYTES
+
+/* Define to 1 if `rx_errors' is a member of `struct net_device_stats'. */
+#undef HAVE_STRUCT_NET_DEVICE_STATS_RX_ERRORS
+
+/* Define to 1 if `tx_packets' is a member of `struct net_device_stats'. */
+#undef HAVE_STRUCT_NET_DEVICE_STATS_TX_PACKETS
+
+/* Define to 1 if `tx_window_errors' is a member of `struct
+   rtnl_link_stats64'. */
+#undef HAVE_STRUCT_RTNL_LINK_STATS64_TX_WINDOW_ERRORS
+
+/* Define to 1 if `dest' is a member of `struct udphdr'. */
+#undef HAVE_STRUCT_UDPHDR_DEST
+
+/* Define to 1 if `source' is a member of `struct udphdr'. */
+#undef HAVE_STRUCT_UDPHDR_SOURCE
+
+/* Define to 1 if `uh_dport' is a member of `struct udphdr'. */
+#undef HAVE_STRUCT_UDPHDR_UH_DPORT
+
+/* Define to 1 if `uh_sport' is a member of `struct udphdr'. */
+#undef HAVE_STRUCT_UDPHDR_UH_SPORT
+
+/* Define if the function getmntent exists. It's the version from libsun. */
+#undef HAVE_SUN_GETMNTENT
+
+/* Define to 1 if you have the `swapctl' function. */
+#undef HAVE_SWAPCTL
+
+/* Define if the function swapctl exists and takes three arguments. */
+#undef HAVE_SWAPCTL_THREE_ARGS
+
+/* Define if the function swapctl exists and takes two arguments. */
+#undef HAVE_SWAPCTL_TWO_ARGS
+
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
+/* Define to 1 if you have the `sysctl' function. */
+#undef HAVE_SYSCTL
+
+/* Define to 1 if you have the `sysctlbyname' function. */
+#undef HAVE_SYSCTLBYNAME
+
+/* Define if sysctl supports kern.cp_times */
+#undef HAVE_SYSCTL_KERN_CP_TIMES
+
+/* Define to 1 if you have the `syslog' function. */
+#undef HAVE_SYSLOG
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/capability.h> header file. */
+#undef HAVE_SYS_CAPABILITY_H
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/dkstat.h> header file. */
+#undef HAVE_SYS_DKSTAT_H
+
+/* Define to 1 if you have the <sys/dl.h> header file. */
+#undef HAVE_SYS_DL_H
+
+/* Define to 1 if you have the <sys/fstyp.h> header file. */
+#undef HAVE_SYS_FSTYP_H
+
+/* Define to 1 if you have the <sys/fs_types.h> header file. */
+#undef HAVE_SYS_FS_TYPES_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/isa_defs.h> header file. */
+#undef HAVE_SYS_ISA_DEFS_H
+
+/* Define to 1 if you have the <sys/loadavg.h> header file. */
+#undef HAVE_SYS_LOADAVG_H
+
+/* Define to 1 if you have the <sys/mntent.h> header file. */
+#undef HAVE_SYS_MNTENT_H
+
+/* Define to 1 if you have the <sys/mnttab.h> header file. */
+#undef HAVE_SYS_MNTTAB_H
+
+/* Define to 1 if you have the <sys/mount.h> header file. */
+#undef HAVE_SYS_MOUNT_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/statfs.h> header file. */
+#undef HAVE_SYS_STATFS_H
+
+/* Define to 1 if you have the <sys/statvfs.h> header file. */
+#undef HAVE_SYS_STATVFS_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/swap.h> header file. */
+#undef HAVE_SYS_SWAP_H
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+#undef HAVE_SYS_UCRED_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the <sys/vfstab.h> header file. */
+#undef HAVE_SYS_VFSTAB_H
+
+/* Define to 1 if you have the <sys/vfs.h> header file. */
+#undef HAVE_SYS_VFS_H
+
+/* Define to 1 if you have the <sys/vmmeter.h> header file. */
+#undef HAVE_SYS_VMMETER_H
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* True if the enum-member TCA_STATS exists */
+#undef HAVE_TCA_STATS
+
+/* True if the enum-member TCA_STATS2 exists */
+#undef HAVE_TCA_STATS2
+
+/* Define to 1 if you have the <tcrdb.h> header file. */
+#undef HAVE_TCRDB_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the threadsafe rrd library (-lrrd_th). */
+#undef HAVE_THREADSAFE_LIBRRD
+
+/* Define to 1 if you have the `thread_info' function. */
+#undef HAVE_THREAD_INFO
+
+/* Define if the function getmntent exists and takes two arguments. */
+#undef HAVE_TWO_GETMNTENT
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <upsclient.h> header file. */
+#undef HAVE_UPSCLIENT_H
+
+/* Define to 1 if the system has the type `UPSCONN'. */
+#undef HAVE_UPSCONN
+
+/* Define to 1 if the system has the type `UPSCONN_t'. */
+#undef HAVE_UPSCONN_T
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
+
+/* Define to 1 if you have the <utmp.h> header file. */
+#undef HAVE_UTMP_H
+
+/* Varnish 2 API support */
+#undef HAVE_VARNISH_V2
+
+/* Varnish 3 API support */
+#undef HAVE_VARNISH_V3
+
+/* Varnish 4 API support */
+#undef HAVE_VARNISH_V4
+
+/* Define to 1 if you have the <varnish/vapi/vsc.h> header file. */
+#undef HAVE_VARNISH_VAPI_VSC_H
+
+/* Define to 1 if you have the <varnish/varnishapi.h> header file. */
+#undef HAVE_VARNISH_VARNISHAPI_H
+
+/* Define to 1 if you have the <varnish/vsc.h> header file. */
+#undef HAVE_VARNISH_VSC_H
+
+/* Define to 1 if you have the <vm/anon.h> header file. */
+#undef HAVE_VM_ANON_H
+
+/* Define to 1 if you have the <wordexp.h> header file. */
+#undef HAVE_WORDEXP_H
+
+/* This value is set to 1 to indicate that the system argz facility works */
+#undef HAVE_WORKING_ARGZ
+
+/* Define to 1 if you have the <xfs/xqm.h> header file. */
+#undef HAVE_XFS_XQM_H
+
+/* Define to 1 if you have the <yajl/yajl_parse.h> header file. */
+#undef HAVE_YAJL_YAJL_PARSE_H
+
+/* Define to 1 if you have the <yajl/yajl_version.h> header file. */
+#undef HAVE_YAJL_YAJL_VERSION_H
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* True if program is to be compiled for a AIX kernel */
+#undef KERNEL_AIX
+
+/* True if program is to be compiled for a Darwin kernel */
+#undef KERNEL_DARWIN
+
+/* True if program is to be compiled for a FreeBSD kernel */
+#undef KERNEL_FREEBSD
+
+/* True if program is to be compiled for a Linux kernel */
+#undef KERNEL_LINUX
+
+/* True if program is to be compiled for an OpenBSD kernel */
+#undef KERNEL_OPENBSD
+
+/* True if program is to be compiled for a Solaris kernel */
+#undef KERNEL_SOLARIS
+
+/* Define to used libtool version. */
+#undef LIBTOOL_VERSION
+
+/* Define if the OS needs help to load dependent libraries for dlopen(). */
+#undef LTDL_DLOPEN_DEPLIBS
+
+/* Define to the system default library search path. */
+#undef LT_DLSEARCH_PATH
+
+/* The archive extension */
+#undef LT_LIBEXT
+
+/* The archive prefix */
+#undef LT_LIBPREFIX
+
+/* Define to the extension used for runtime loadable modules, say, ".so". */
+#undef LT_MODULE_EXT
+
+/* Define to the name of the environment variable that determines the run-time
+   module search path. */
+#undef LT_MODULE_PATH_VAR
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#undef LT_OBJDIR
+
+/* Define to the shared library suffix, say, ".dylib". */
+#undef LT_SHARED_EXT
+
+/* Define if NAN is defined by default and can initialize static variables. */
+#undef NAN_STATIC_DEFAULT
+
+/* Define if NAN is defined by __USE_ISOC99 and can initialize static
+   variables. */
+#undef NAN_STATIC_ISOC
+
+/* Define if NAN can be defined as (0.0 / 0.0) */
+#undef NAN_ZERO_ZERO
+
+/* Define if dlsym() requires a leading underscore in symbol names. */
+#undef NEED_USCORE
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if your version of the 'perfstat' library supports donation */
+#undef PERFSTAT_SUPPORTS_DONATION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if strerror_r returns char *. */
+#undef STRERROR_R_CHAR_P
+
+/* Set to true if strptime is only exported in X/Open mode (GNU libc). */
+#undef STRPTIME_NEEDS_STANDARDS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Enable large inode numbers on Mac OS X 10.5.  */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to enforce ISO C99 compliance. */
+#undef _ISOC99_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to enforce POSIX.1-2008 compliance. */
+#undef _POSIX_C_SOURCE
+
+/* Define to enforce POSIX thread semantics under Solaris. */
+#undef _POSIX_PTHREAD_SEMANTICS
+
+/* Define to enable reentrancy interfaces. */
+#undef _REENTRANT
+
+/* Define to use the thread-safe version of errno under AIX. */
+#undef _THREAD_SAFE_ERRNO
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   #define below would cause a syntax error. */
+#undef _UINT32_T
+
+/* Define to enforce X/Open 7 (XSI) compliance. */
+#undef _XOPEN_SOURCE
+
+/* Define so that glibc/gnulib argp.h does not typedef error_t. */
+#undef __error_t_defined
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to a type to use for `error_t' if it is not otherwise available. */
+#undef error_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+   such a type exists and the standard includes do not define it. */
+#undef uint32_t
diff --git a/src/conntrack.c b/src/conntrack.c
new file mode 100644 (file)
index 0000000..49a3355
--- /dev/null
@@ -0,0 +1,141 @@
+/**
+ * collectd - src/conntrack.c
+ * Copyright (C) 2009  Tomasz Pala
+ *
+ * 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:
+ *   Tomasz Pala <gotar at pld-linux.org>
+ * based on entropy.c by:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+#define CONNTRACK_FILE "/proc/sys/net/netfilter/nf_conntrack_count"
+#define CONNTRACK_MAX_FILE "/proc/sys/net/netfilter/nf_conntrack_max"
+#define CONNTRACK_FILE_OLD "/proc/sys/net/ipv4/netfilter/ip_conntrack_count"
+#define CONNTRACK_MAX_FILE_OLD "/proc/sys/net/ipv4/netfilter/ip_conntrack_max"
+
+static const char *config_keys[] =
+{
+       "OldFiles"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+/*
+    Each table/chain combo that will be queried goes into this list
+*/
+
+static int old_files = 0;
+
+static int conntrack_config(const char *key, const char *value)
+{
+    if (strcmp(key, "OldFiles") == 0)
+        old_files = 1;
+
+    return 0;
+}
+
+static void conntrack_submit (const char *type, const char *type_instance,
+                             value_t conntrack)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = &conntrack;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "conntrack", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance,
+                         sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* static void conntrack_submit */
+
+static int conntrack_read (void)
+{
+       value_t conntrack, conntrack_max, conntrack_pct;
+       FILE *fh;
+       char buffer[64];
+       size_t buffer_len;
+
+       fh = fopen (old_files?CONNTRACK_FILE_OLD:CONNTRACK_FILE, "r");
+       if (fh == NULL)
+               return (-1);
+
+       memset (buffer, 0, sizeof (buffer));
+       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       {
+               fclose (fh);
+               return (-1);
+       }
+       fclose (fh);
+
+       /* strip trailing newline. */
+       buffer_len = strlen (buffer);
+       while ((buffer_len > 0) && isspace ((int) buffer[buffer_len - 1]))
+       {
+               buffer[buffer_len - 1] = 0;
+               buffer_len--;
+       }
+
+       if (parse_value (buffer, &conntrack, DS_TYPE_GAUGE) != 0)
+               return (-1);
+
+       conntrack_submit ("conntrack", NULL, conntrack);
+
+       fh = fopen (old_files?CONNTRACK_MAX_FILE_OLD:CONNTRACK_MAX_FILE, "r");
+       if (fh == NULL)
+               return (-1);
+
+       memset (buffer, 0, sizeof (buffer));
+       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       {
+               fclose (fh);
+               return (-1);
+       }
+       fclose (fh);
+
+       /* strip trailing newline. */
+       buffer_len = strlen (buffer);
+       while ((buffer_len > 0) && isspace ((int) buffer[buffer_len - 1]))
+       {
+               buffer[buffer_len - 1] = 0;
+               buffer_len--;
+       }
+
+       if (parse_value (buffer, &conntrack_max, DS_TYPE_GAUGE) != 0)
+               return (-1);
+
+       conntrack_submit ("conntrack", "max", conntrack_max);
+       conntrack_pct.gauge = (conntrack.gauge / conntrack_max.gauge) * 100;
+       conntrack_submit ("percent", "used", conntrack_pct);
+
+
+       return (0);
+} /* static int conntrack_read */
+
+void module_register (void)
+{
+    plugin_register_config ("conntrack", conntrack_config,
+                            config_keys, config_keys_num);
+       plugin_register_read ("conntrack", conntrack_read);
+} /* void module_register */
diff --git a/src/contextswitch.c b/src/contextswitch.c
new file mode 100644 (file)
index 0000000..344f76e
--- /dev/null
@@ -0,0 +1,154 @@
+/**
+ * collectd - src/contextswitch.c
+ * Copyright (C) 2009  Patrik Weiskircher
+ * Copyright (C) 2010  Kimo Rosenbaum
+ *
+ * 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:
+ *   Patrik Weiskircher <weiskircher at inqnet.at>
+ *   Kimo Rosenbaum <http://github.com/kimor79>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#ifdef HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+
+#if HAVE_SYSCTLBYNAME
+/* no global variables */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif KERNEL_LINUX
+/* no global variables */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+/* #endif HAVE_PERFSTAT */
+
+#else
+# error "No applicable input method."
+#endif
+
+static void cs_submit (derive_t context_switches)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = (derive_t) context_switches;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "contextswitch", sizeof (vl.plugin));
+       sstrncpy (vl.type, "contextswitch", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int cs_read (void)
+{
+#if HAVE_SYSCTLBYNAME
+       int value = 0;
+       size_t value_len = sizeof (value);
+       int status;
+
+       status = sysctlbyname ("vm.stats.sys.v_swtch",
+                       &value, &value_len,
+                       /* new pointer = */ NULL, /* new length = */ 0);
+       if (status != 0)
+       {
+               ERROR("contextswitch plugin: sysctlbyname "
+                               "(vm.stats.sys.v_swtch) failed");
+               return (-1);
+       }
+
+       cs_submit (value);
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif KERNEL_LINUX
+       FILE *fh;
+       char buffer[64];
+       int numfields;
+       char *fields[3];
+       derive_t result = 0;
+       int status = -2;
+
+       fh = fopen ("/proc/stat", "r");
+       if (fh == NULL) {
+               ERROR ("contextswitch plugin: unable to open /proc/stat: %s",
+                               sstrerror (errno, buffer, sizeof (buffer)));
+               return (-1);
+       }
+
+       while (fgets(buffer, sizeof(buffer), fh) != NULL)
+       {
+               char *endptr;
+
+               numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (numfields != 2)
+                       continue;
+
+               if (strcmp("ctxt", fields[0]) != 0)
+                       continue;
+
+               errno = 0;
+               endptr = NULL;
+               result = (derive_t) strtoll (fields[1], &endptr, /* base = */ 10);
+               if ((endptr == fields[1]) || (errno != 0)) {
+                       ERROR ("contextswitch plugin: Cannot parse ctxt value: %s",
+                                       fields[1]);
+                       status = -1;
+                       break;
+               }
+
+               cs_submit(result);
+               status = 0;
+               break;
+       }
+       fclose(fh);
+
+       if (status == -2)
+               ERROR ("contextswitch plugin: Unable to find context switch value.");
+/* #endif  KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+       int status = 0;
+       perfstat_cpu_total_t perfcputotal;
+
+       status = perfstat_cpu_total(NULL, &perfcputotal, sizeof(perfstat_cpu_total_t), 1);
+       if (status < 0)
+       {
+               char errbuf[1024];
+               ERROR ("contextswitch plugin: perfstat_cpu_total: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       cs_submit(perfcputotal.pswitch);
+       status = 0;
+#endif /* defined(HAVE_PERFSTAT) */
+
+       return status;
+}
+
+void module_register (void)
+{
+       plugin_register_read ("contextswitch", cs_read);
+} /* void module_register */
diff --git a/src/cpu.c b/src/cpu.c
new file mode 100644 (file)
index 0000000..57af2dd
--- /dev/null
+++ b/src/cpu.c
@@ -0,0 +1,843 @@
+/**
+ * collectd - src/cpu.c
+ * Copyright (C) 2005-2014  Florian octo Forster
+ * Copyright (C) 2008       Oleg King
+ * Copyright (C) 2009       Simon Kuhnle
+ * Copyright (C) 2009       Manuel Sanmartin
+ * Copyright (C) 2013-2014  Pierre-Yves Ritschard
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Oleg King <king2 at kaluga.ru>
+ *   Simon Kuhnle <simon at blarzwurst.de>
+ *   Manuel Sanmartin
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#ifdef HAVE_MACH_KERN_RETURN_H
+# include <mach/kern_return.h>
+#endif
+#ifdef HAVE_MACH_MACH_INIT_H
+# include <mach/mach_init.h>
+#endif
+#ifdef HAVE_MACH_HOST_PRIV_H
+# include <mach/host_priv.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#ifdef HAVE_MACH_PROCESSOR_INFO_H
+# include <mach/processor_info.h>
+#endif
+#ifdef HAVE_MACH_PROCESSOR_H
+# include <mach/processor.h>
+#endif
+#ifdef HAVE_MACH_VM_MAP_H
+# include <mach/vm_map.h>
+#endif
+
+#ifdef HAVE_LIBKSTAT
+# include <sys/sysinfo.h>
+#endif /* HAVE_LIBKSTAT */
+
+#if (defined(HAVE_SYSCTL) && HAVE_SYSCTL) \
+       || (defined(HAVE_SYSCTLBYNAME) && HAVE_SYSCTLBYNAME)
+# ifdef HAVE_SYS_SYSCTL_H
+#  include <sys/sysctl.h>
+# endif
+
+# ifdef HAVE_SYS_DKSTAT_H
+#  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_USER   0
+#  define CP_NICE   1
+#  define CP_SYS    2
+#  define CP_INTR   3
+#  define CP_IDLE   4
+#  define CPUSTATES 5
+# endif
+#endif /* HAVE_SYSCTL || HAVE_SYSCTLBYNAME */
+
+#if HAVE_SYSCTL
+# 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
+
+#define COLLECTD_CPU_STATE_USER 0
+#define COLLECTD_CPU_STATE_SYSTEM 1
+#define COLLECTD_CPU_STATE_WAIT 2
+#define COLLECTD_CPU_STATE_NICE 3
+#define COLLECTD_CPU_STATE_SWAP 4
+#define COLLECTD_CPU_STATE_INTERRUPT 5
+#define COLLECTD_CPU_STATE_SOFTIRQ 6
+#define COLLECTD_CPU_STATE_STEAL 7
+#define COLLECTD_CPU_STATE_IDLE 8
+#define COLLECTD_CPU_STATE_ACTIVE 9 /* sum of (!idle) */
+#define COLLECTD_CPU_STATE_MAX 10 /* #states */
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
+
+# ifdef HAVE_PERFSTAT
+#  include <sys/protosw.h>
+#  include <libperfstat.h>
+# endif /* HAVE_PERFSTAT */
+
+#if !PROCESSOR_CPU_LOAD_INFO && !KERNEL_LINUX && !HAVE_LIBKSTAT \
+       && !CAN_USE_SYSCTL && !HAVE_SYSCTLBYNAME && !HAVE_LIBSTATGRAB && !HAVE_PERFSTAT
+# error "No applicable input method."
+#endif
+
+static const char *cpu_state_names[] = {
+       "user",
+       "system",
+       "wait",
+       "nice",
+       "swap",
+       "interrupt",
+       "softirq",
+       "steal",
+       "idle",
+       "active"
+};
+
+#ifdef PROCESSOR_CPU_LOAD_INFO
+static mach_port_t port_host;
+static processor_port_array_t cpu_list;
+static mach_msg_type_number_t cpu_list_len;
+/* #endif PROCESSOR_CPU_LOAD_INFO */
+
+#elif defined(KERNEL_LINUX)
+/* no variables needed */
+/* #endif KERNEL_LINUX */
+
+#elif defined(HAVE_LIBKSTAT)
+/* colleague tells me that Sun doesn't sell systems with more than 100 or so CPUs.. */
+# define MAX_NUMCPU 256
+extern kstat_ctl_t *kc;
+static kstat_t *ksp[MAX_NUMCPU];
+static int numcpu;
+/* #endif HAVE_LIBKSTAT */
+
+#elif CAN_USE_SYSCTL
+static int numcpu;
+/* #endif CAN_USE_SYSCTL */
+
+#elif defined(HAVE_SYSCTLBYNAME)
+static int numcpu;
+#  ifdef HAVE_SYSCTL_KERN_CP_TIMES
+static int maxcpu;
+#  endif /* HAVE_SYSCTL_KERN_CP_TIMES */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif defined(HAVE_LIBSTATGRAB)
+/* no variables needed */
+/* #endif  HAVE_LIBSTATGRAB */
+
+#elif defined(HAVE_PERFSTAT)
+static perfstat_cpu_t *perfcpu;
+static int numcpu;
+static int pnumcpu;
+#endif /* HAVE_PERFSTAT */
+
+#define RATE_ADD(sum, val) do { \
+       if (isnan (sum))        \
+       (sum) = (val);          \
+       else if (!isnan (val))  \
+       (sum) += (val);         \
+} while (0)
+
+struct cpu_state_s
+{
+       value_to_rate_state_t conv;
+       gauge_t rate;
+       _Bool has_value;
+};
+typedef struct cpu_state_s cpu_state_t;
+
+static cpu_state_t *cpu_states = NULL;
+static size_t cpu_states_num = 0; /* #cpu_states allocated */
+
+/* Highest CPU number in the current iteration. Used by the dispatch logic to
+ * determine how many CPUs there were. Reset to 0 by cpu_reset(). */
+static size_t global_cpu_num = 0;
+
+static _Bool report_by_cpu = 1;
+static _Bool report_by_state = 1;
+static _Bool report_percent = 0;
+
+static const char *config_keys[] =
+{
+       "ReportByCpu",
+       "ReportByState",
+       "ValuesPercentage"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int cpu_config (char const *key, char const *value) /* {{{ */
+{
+       if (strcasecmp (key, "ReportByCpu") == 0)
+               report_by_cpu = IS_TRUE (value) ? 1 : 0;
+       else if (strcasecmp (key, "ValuesPercentage") == 0)
+               report_percent = IS_TRUE (value) ? 1 : 0;
+       else if (strcasecmp (key, "ReportByState") == 0)
+               report_by_state = IS_TRUE (value) ? 1 : 0;
+       else
+               return (-1);
+
+       return (0);
+} /* }}} int cpu_config */
+
+static int init (void)
+{
+#if PROCESSOR_CPU_LOAD_INFO
+       kern_return_t status;
+
+       port_host = mach_host_self ();
+
+       /* FIXME: Free `cpu_list' if it's not NULL */
+       if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS)
+       {
+               ERROR ("cpu plugin: host_processors returned %i", (int) status);
+               cpu_list_len = 0;
+               return (-1);
+       }
+
+       DEBUG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors");
+       INFO ("cpu plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
+/* #endif PROCESSOR_CPU_LOAD_INFO */
+
+#elif defined(HAVE_LIBKSTAT)
+       kstat_t *ksp_chain;
+
+       numcpu = 0;
+
+       if (kc == NULL)
+               return (-1);
+
+       /* Solaris doesn't count linear.. *sigh* */
+       for (numcpu = 0, ksp_chain = kc->kc_chain;
+                       (numcpu < MAX_NUMCPU) && (ksp_chain != NULL);
+                       ksp_chain = ksp_chain->ks_next)
+               if (strncmp (ksp_chain->ks_module, "cpu_stat", 8) == 0)
+                       ksp[numcpu++] = ksp_chain;
+/* #endif HAVE_LIBKSTAT */
+
+#elif CAN_USE_SYSCTL
+       size_t numcpu_size;
+       int mib[2] = {CTL_HW, HW_NCPU};
+       int status;
+
+       numcpu = 0;
+       numcpu_size = sizeof (numcpu);
+
+       status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+                       &numcpu, &numcpu_size, NULL, 0);
+       if (status == -1)
+       {
+               char errbuf[1024];
+               WARNING ("cpu plugin: sysctl: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+/* #endif CAN_USE_SYSCTL */
+
+#elif defined (HAVE_SYSCTLBYNAME)
+       size_t numcpu_size;
+
+       numcpu_size = sizeof (numcpu);
+
+       if (sysctlbyname ("hw.ncpu", &numcpu, &numcpu_size, NULL, 0) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("cpu plugin: sysctlbyname(hw.ncpu): %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+#ifdef HAVE_SYSCTL_KERN_CP_TIMES
+       numcpu_size = sizeof (maxcpu);
+
+       if (sysctlbyname("kern.smp.maxcpus", &maxcpu, &numcpu_size, NULL, 0) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("cpu plugin: sysctlbyname(kern.smp.maxcpus): %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+#else
+       if (numcpu != 1)
+               NOTICE ("cpu: Only one processor supported when using `sysctlbyname' (found %i)", numcpu);
+#endif
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif defined(HAVE_LIBSTATGRAB)
+       /* nothing to initialize */
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif defined(HAVE_PERFSTAT)
+       /* nothing to initialize */
+#endif /* HAVE_PERFSTAT */
+
+       return (0);
+} /* int init */
+
+static void submit_value (int cpu_num, int cpu_state, const char *type, value_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       memcpy(&values[0], &value, sizeof(value));
+
+       vl.values = values;
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, cpu_state_names[cpu_state],
+                       sizeof (vl.type_instance));
+
+       if (cpu_num >= 0) {
+               ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+                               "%i", cpu_num);
+       }
+       plugin_dispatch_values (&vl);
+}
+
+static void submit_percent(int cpu_num, int cpu_state, gauge_t percent)
+{
+       value_t value;
+
+       /* This function is called for all known CPU states, but each read
+        * method will only report a subset. The remaining states are left as
+        * NAN and we ignore them here. */
+       if (isnan (percent))
+               return;
+
+       value.gauge = percent;
+       submit_value (cpu_num, cpu_state, "percent", value);
+}
+
+static void submit_derive(int cpu_num, int cpu_state, derive_t derive)
+{
+       value_t value;
+
+       value.derive = derive;
+       submit_value (cpu_num, cpu_state, "cpu", value);
+}
+
+/* Takes the zero-index number of a CPU and makes sure that the module-global
+ * cpu_states buffer is large enough. Returne ENOMEM on erorr. */
+static int cpu_states_alloc (size_t cpu_num) /* {{{ */
+{
+       cpu_state_t *tmp;
+       size_t sz;
+
+       sz = (((size_t) cpu_num) + 1) * COLLECTD_CPU_STATE_MAX;
+       assert (sz > 0);
+
+       /* We already have enough space. */
+       if (cpu_states_num >= sz)
+               return 0;
+
+       tmp = realloc (cpu_states, sz * sizeof (*cpu_states));
+       if (tmp == NULL)
+       {
+               ERROR ("cpu plugin: realloc failed.");
+               return (ENOMEM);
+       }
+       cpu_states = tmp;
+       tmp = cpu_states + cpu_states_num;
+
+       memset (tmp, 0, (sz - cpu_states_num) * sizeof (*cpu_states));
+       cpu_states_num = sz;
+       return 0;
+} /* }}} cpu_states_alloc */
+
+static cpu_state_t *get_cpu_state (size_t cpu_num, size_t state) /* {{{ */
+{
+       size_t index = ((cpu_num * COLLECTD_CPU_STATE_MAX) + state);
+
+       if (index >= cpu_states_num)
+               return (NULL);
+
+       return (&cpu_states[index]);
+} /* }}} cpu_state_t *get_cpu_state */
+
+/* Populates the per-CPU COLLECTD_CPU_STATE_ACTIVE rate and the global rate_by_state
+ * array. */
+static void aggregate (gauge_t *sum_by_state) /* {{{ */
+{
+       size_t cpu_num;
+       size_t state;
+
+       for (state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
+               sum_by_state[state] = NAN;
+
+       for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+       {
+               cpu_state_t *this_cpu_states = get_cpu_state (cpu_num, 0);
+
+               this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate = NAN;
+
+               for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+               {
+                       if (!this_cpu_states[state].has_value)
+                               continue;
+
+                       RATE_ADD (sum_by_state[state], this_cpu_states[state].rate);
+                       if (state != COLLECTD_CPU_STATE_IDLE)
+                               RATE_ADD (this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate, this_cpu_states[state].rate);
+               }
+
+               if (!isnan (this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate))
+                       this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].has_value = 1;
+
+               RATE_ADD (sum_by_state[COLLECTD_CPU_STATE_ACTIVE], this_cpu_states[COLLECTD_CPU_STATE_ACTIVE].rate);
+       }
+} /* }}} void aggregate */
+
+/* Commits (dispatches) the values for one CPU or the global aggregation.
+ * cpu_num is the index of the CPU to be committed or -1 in case of the global
+ * aggregation. rates is a pointer to COLLECTD_CPU_STATE_MAX gauge_t values holding the
+ * current rate; each rate may be NAN. Calculates the percentage of each state
+ * and dispatches the metric. */
+static void cpu_commit_one (int cpu_num, /* {{{ */
+               gauge_t rates[static COLLECTD_CPU_STATE_MAX])
+{
+       size_t state;
+       gauge_t sum;
+
+       sum = rates[COLLECTD_CPU_STATE_ACTIVE];
+       RATE_ADD (sum, rates[COLLECTD_CPU_STATE_IDLE]);
+
+       if (!report_by_state)
+       {
+               gauge_t percent = 100.0 * rates[COLLECTD_CPU_STATE_ACTIVE] / sum;
+               submit_percent (cpu_num, COLLECTD_CPU_STATE_ACTIVE, percent);
+               return;
+       }
+
+       for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+       {
+               gauge_t percent = 100.0 * rates[state] / sum;
+               submit_percent (cpu_num, state, percent);
+       }
+} /* }}} void cpu_commit_one */
+
+/* Resets the internal aggregation. This is called by the read callback after
+ * each iteration / after each call to cpu_commit(). */
+static void cpu_reset (void) /* {{{ */
+{
+       size_t i;
+
+       for (i = 0; i < cpu_states_num; i++)
+               cpu_states[i].has_value = 0;
+
+       global_cpu_num = 0;
+} /* }}} void cpu_reset */
+
+/* Legacy behavior: Dispatches the raw derive values without any aggregation. */
+static void cpu_commit_without_aggregation (void) /* {{{ */
+{
+       int state;
+
+       for (state = 0; state < COLLECTD_CPU_STATE_ACTIVE; state++)
+       {
+               size_t cpu_num;
+
+               for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+               {
+                       cpu_state_t *s = get_cpu_state (cpu_num, state);
+
+                       if (!s->has_value)
+                               continue;
+
+                       submit_derive ((int) cpu_num, (int) state, s->conv.last_value.derive);
+               }
+       }
+} /* }}} void cpu_commit_without_aggregation */
+
+/* Aggregates the internal state and dispatches the metrics. */
+static void cpu_commit (void) /* {{{ */
+{
+       gauge_t global_rates[COLLECTD_CPU_STATE_MAX] = {
+               NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN /* Batman! */
+       };
+       size_t cpu_num;
+
+       if (report_by_state && report_by_cpu && !report_percent)
+       {
+               cpu_commit_without_aggregation ();
+               return;
+       }
+
+       aggregate (global_rates);
+
+       if (!report_by_cpu)
+       {
+               cpu_commit_one (-1, global_rates);
+               return;
+       }
+
+       for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+       {
+               cpu_state_t *this_cpu_states = get_cpu_state (cpu_num, 0);
+               gauge_t local_rates[COLLECTD_CPU_STATE_MAX] = {
+                       NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN
+               };
+               size_t state;
+
+               for (state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
+                       if (this_cpu_states[state].has_value)
+                               local_rates[state] = this_cpu_states[state].rate;
+
+               cpu_commit_one ((int) cpu_num, local_rates);
+       }
+} /* }}} void cpu_commit */
+
+/* Adds a derive value to the internal state. This should be used by each read
+ * function for each state. At the end of the iteration, the read function
+ * should call cpu_commit(). */
+static int cpu_stage (size_t cpu_num, size_t state, derive_t value, cdtime_t now) /* {{{ */
+{
+       int status;
+       cpu_state_t *s;
+       value_t v;
+
+       if (state >= COLLECTD_CPU_STATE_ACTIVE)
+               return (EINVAL);
+
+       status = cpu_states_alloc (cpu_num);
+       if (status != 0)
+               return (status);
+
+       if (global_cpu_num <= cpu_num)
+               global_cpu_num = cpu_num + 1;
+
+       s = get_cpu_state (cpu_num, state);
+
+       v.gauge = NAN;
+       status = value_to_rate (&v, value, &s->conv, DS_TYPE_DERIVE, now);
+       if (status != 0)
+               return (status);
+
+       s->rate = v.gauge;
+       s->has_value = 1;
+       return (0);
+} /* }}} int cpu_stage */
+
+static int cpu_read (void)
+{
+       cdtime_t now = cdtime ();
+
+#if PROCESSOR_CPU_LOAD_INFO /* {{{ */
+       int cpu;
+
+       kern_return_t status;
+
+       processor_cpu_load_info_data_t cpu_info;
+       mach_msg_type_number_t         cpu_info_len;
+
+       host_t cpu_host;
+
+       for (cpu = 0; cpu < cpu_list_len; cpu++)
+       {
+               cpu_host = 0;
+               cpu_info_len = PROCESSOR_BASIC_INFO_COUNT;
+
+               status = processor_info (cpu_list[cpu], PROCESSOR_CPU_LOAD_INFO, &cpu_host,
+                               (processor_info_t) &cpu_info, &cpu_info_len);
+               if (status != KERN_SUCCESS)
+               {
+                       ERROR ("cpu plugin: processor_info (PROCESSOR_CPU_LOAD_INFO) failed: %s",
+                                       mach_error_string (status));
+                       continue;
+               }
+
+               if (cpu_info_len < COLLECTD_CPU_STATE_MAX)
+               {
+                       ERROR ("cpu plugin: processor_info returned only %i elements..", cpu_info_len);
+                       continue;
+               }
+
+               cpu_stage (cpu, COLLECTD_CPU_STATE_USER,   (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_USER],   now);
+               cpu_stage (cpu, COLLECTD_CPU_STATE_NICE,   (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_NICE],   now);
+               cpu_stage (cpu, COLLECTD_CPU_STATE_SYSTEM, (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_SYSTEM], now);
+               cpu_stage (cpu, COLLECTD_CPU_STATE_IDLE,   (derive_t) cpu_info.cpu_ticks[COLLECTD_CPU_STATE_IDLE],   now);
+       }
+/* }}} #endif PROCESSOR_CPU_LOAD_INFO */
+
+#elif defined(KERNEL_LINUX) /* {{{ */
+       int cpu;
+       FILE *fh;
+       char buf[1024];
+
+       char *fields[9];
+       int numfields;
+
+       if ((fh = fopen ("/proc/stat", "r")) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("cpu plugin: fopen (/proc/stat) failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buf, 1024, fh) != NULL)
+       {
+               if (strncmp (buf, "cpu", 3))
+                       continue;
+               if ((buf[3] < '0') || (buf[3] > '9'))
+                       continue;
+
+               numfields = strsplit (buf, fields, 9);
+               if (numfields < 5)
+                       continue;
+
+               cpu = atoi (fields[0] + 3);
+
+               cpu_stage (cpu, COLLECTD_CPU_STATE_USER,   (derive_t) atoll(fields[1]), now);
+               cpu_stage (cpu, COLLECTD_CPU_STATE_NICE,   (derive_t) atoll(fields[2]), now);
+               cpu_stage (cpu, COLLECTD_CPU_STATE_SYSTEM, (derive_t) atoll(fields[3]), now);
+               cpu_stage (cpu, COLLECTD_CPU_STATE_IDLE,   (derive_t) atoll(fields[4]), now);
+
+               if (numfields >= 8)
+               {
+                       cpu_stage (cpu, COLLECTD_CPU_STATE_WAIT,      (derive_t) atoll(fields[5]), now);
+                       cpu_stage (cpu, COLLECTD_CPU_STATE_INTERRUPT, (derive_t) atoll(fields[6]), now);
+                       cpu_stage (cpu, COLLECTD_CPU_STATE_SOFTIRQ,   (derive_t) atoll(fields[7]), now);
+
+                       if (numfields >= 9)
+                               cpu_stage (cpu, COLLECTD_CPU_STATE_STEAL, (derive_t) atoll(fields[8]), now);
+               }
+       }
+       fclose (fh);
+/* }}} #endif defined(KERNEL_LINUX) */
+
+#elif defined(HAVE_LIBKSTAT) /* {{{ */
+       int cpu;
+       static cpu_stat_t cs;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (cpu = 0; cpu < numcpu; cpu++)
+       {
+               if (kstat_read (kc, ksp[cpu], &cs) == -1)
+                       continue; /* error message? */
+
+               cpu_stage (ksp[cpu]->ks_instance, COLLECTD_CPU_STATE_IDLE,   (derive_t) cs.cpu_sysinfo.cpu[CPU_IDLE],   now);
+               cpu_stage (ksp[cpu]->ks_instance, COLLECTD_CPU_STATE_USER,   (derive_t) cs.cpu_sysinfo.cpu[CPU_USER],   now);
+               cpu_stage (ksp[cpu]->ks_instance, COLLECTD_CPU_STATE_SYSTEM, (derive_t) cs.cpu_sysinfo.cpu[CPU_KERNEL], now);
+               cpu_stage (ksp[cpu]->ks_instance, COLLECTD_CPU_STATE_WAIT,   (derive_t) cs.cpu_sysinfo.cpu[CPU_WAIT],   now);
+       }
+/* }}} #endif defined(HAVE_LIBKSTAT) */
+
+#elif CAN_USE_SYSCTL /* {{{ */
+       uint64_t cpuinfo[numcpu][CPUSTATES];
+       size_t cpuinfo_size;
+       int status;
+       int i;
+
+       if (numcpu < 1)
+       {
+               ERROR ("cpu plugin: Could not determine number of "
+                               "installed CPUs using sysctl(3).");
+               return (-1);
+       }
+
+       memset (cpuinfo, 0, sizeof (cpuinfo));
+
+#if defined(KERN_CPTIME2)
+       if (numcpu > 1) {
+               for (i = 0; i < numcpu; i++) {
+                       int mib[] = {CTL_KERN, KERN_CPTIME2, i};
+
+                       cpuinfo_size = sizeof (cpuinfo[0]);
+
+                       status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+                                       cpuinfo[i], &cpuinfo_size, NULL, 0);
+                       if (status == -1) {
+                               char errbuf[1024];
+                               ERROR ("cpu plugin: sysctl failed: %s.",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                               return (-1);
+                       }
+               }
+       }
+       else
+#endif /* defined(KERN_CPTIME2) */
+       {
+               int mib[] = {CTL_KERN, KERN_CPTIME};
+               long cpuinfo_tmp[CPUSTATES];
+
+               cpuinfo_size = sizeof(cpuinfo_tmp);
+
+               status = sysctl (mib, STATIC_ARRAY_SIZE (mib),
+                                       &cpuinfo_tmp, &cpuinfo_size, NULL, 0);
+               if (status == -1)
+               {
+                       char errbuf[1024];
+                       ERROR ("cpu plugin: sysctl failed: %s.",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+
+               for(i = 0; i < CPUSTATES; i++) {
+                       cpuinfo[0][i] = cpuinfo_tmp[i];
+               }
+       }
+
+       for (i = 0; i < numcpu; i++) {
+               cpu_stage (i, COLLECTD_CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_IDLE,      (derive_t) cpuinfo[i][CP_IDLE], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_INTERRUPT, (derive_t) cpuinfo[i][CP_INTR], now);
+       }
+/* }}} #endif CAN_USE_SYSCTL */
+
+#elif defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYSCTL_KERN_CP_TIMES) /* {{{ */
+       long cpuinfo[maxcpu][CPUSTATES];
+       size_t cpuinfo_size;
+       int i;
+
+       memset (cpuinfo, 0, sizeof (cpuinfo));
+
+       cpuinfo_size = sizeof (cpuinfo);
+       if (sysctlbyname("kern.cp_times", &cpuinfo, &cpuinfo_size, NULL, 0) < 0)
+       {
+               char errbuf[1024];
+               ERROR ("cpu plugin: sysctlbyname failed: %s.",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       for (i = 0; i < numcpu; i++) {
+               cpu_stage (i, COLLECTD_CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_IDLE,      (derive_t) cpuinfo[i][CP_IDLE], now);
+               cpu_stage (i, COLLECTD_CPU_STATE_INTERRUPT, (derive_t) cpuinfo[i][CP_INTR], now);
+       }
+/* }}} #endif HAVE_SYSCTL_KERN_CP_TIMES */
+
+#elif defined(HAVE_SYSCTLBYNAME) /* {{{ */
+       long cpuinfo[CPUSTATES];
+       size_t cpuinfo_size;
+
+       cpuinfo_size = sizeof (cpuinfo);
+
+       if (sysctlbyname("kern.cp_time", &cpuinfo, &cpuinfo_size, NULL, 0) < 0)
+       {
+               char errbuf[1024];
+               ERROR ("cpu plugin: sysctlbyname failed: %s.",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       cpu_stage (0, COLLECTD_CPU_STATE_USER,      (derive_t) cpuinfo[CP_USER], now);
+       cpu_stage (0, COLLECTD_CPU_STATE_NICE,      (derive_t) cpuinfo[CP_NICE], now);
+       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 */
+
+#elif defined(HAVE_LIBSTATGRAB) /* {{{ */
+       sg_cpu_stats *cs;
+       cs = sg_get_cpu_stats ();
+
+       if (cs == NULL)
+       {
+               ERROR ("cpu plugin: sg_get_cpu_stats failed.");
+               return (-1);
+       }
+
+       cpu_state (0, COLLECTD_CPU_STATE_IDLE,   (derive_t) cs->idle);
+       cpu_state (0, COLLECTD_CPU_STATE_NICE,   (derive_t) cs->nice);
+       cpu_state (0, COLLECTD_CPU_STATE_SWAP,   (derive_t) cs->swap);
+       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 */
+
+#elif defined(HAVE_PERFSTAT) /* {{{ */
+       perfstat_id_t id;
+       int i, cpus;
+
+       numcpu =  perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0);
+       if(numcpu == -1)
+       {
+               char errbuf[1024];
+               WARNING ("cpu plugin: perfstat_cpu: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       if (pnumcpu != numcpu || perfcpu == NULL)
+       {
+               if (perfcpu != NULL)
+                       free(perfcpu);
+               perfcpu = malloc(numcpu * sizeof(perfstat_cpu_t));
+       }
+       pnumcpu = numcpu;
+
+       id.name[0] = '\0';
+       if ((cpus = perfstat_cpu(&id, perfcpu, sizeof(perfstat_cpu_t), numcpu)) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("cpu plugin: perfstat_cpu: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       for (i = 0; i < cpus; i++)
+       {
+               cpu_stage (i, COLLECTD_CPU_STATE_IDLE,   (derive_t) perfcpu[i].idle, now);
+               cpu_stage (i, COLLECTD_CPU_STATE_SYSTEM, (derive_t) perfcpu[i].sys,  now);
+               cpu_stage (i, COLLECTD_CPU_STATE_USER,   (derive_t) perfcpu[i].user, now);
+               cpu_stage (i, COLLECTD_CPU_STATE_WAIT,   (derive_t) perfcpu[i].wait, now);
+       }
+#endif /* }}} HAVE_PERFSTAT */
+
+       cpu_commit ();
+       cpu_reset ();
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_init ("cpu", init);
+       plugin_register_config ("cpu", cpu_config, config_keys, config_keys_num);
+       plugin_register_read ("cpu", cpu_read);
+} /* void module_register */
+
+/* vim: set sw=8 sts=8 noet fdm=marker : */
diff --git a/src/cpufreq.c b/src/cpufreq.c
new file mode 100644 (file)
index 0000000..b92b1d0
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * collectd - src/cpufreq.c
+ * Copyright (C) 2005-2007  Peter Holik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Peter Holik <peter at holik.at>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#define MODULE_NAME "cpufreq"
+
+static int num_cpu = 0;
+
+static int cpufreq_init (void)
+{
+        int status;
+       char filename[256];
+
+       num_cpu = 0;
+
+       while (1)
+       {
+               status = ssnprintf (filename, sizeof (filename),
+                               "/sys/devices/system/cpu/cpu%d/cpufreq/"
+                               "scaling_cur_freq", num_cpu);
+               if ((status < 1) || ((unsigned int)status >= sizeof (filename)))
+                       break;
+
+               if (access (filename, R_OK))
+                       break;
+
+               num_cpu++;
+       }
+
+       INFO ("cpufreq plugin: Found %d CPU%s", num_cpu,
+                       (num_cpu == 1) ? "" : "s");
+
+       if (num_cpu == 0)
+               plugin_unregister_read ("cpufreq");
+
+       return (0);
+} /* int cpufreq_init */
+
+static void cpufreq_submit (int cpu_num, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "cpufreq", sizeof (vl.plugin));
+       sstrncpy (vl.type, "cpufreq", sizeof (vl.type));
+       ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+                       "%i", cpu_num);
+
+       plugin_dispatch_values (&vl);
+}
+
+static int cpufreq_read (void)
+{
+        int status;
+       unsigned long long val;
+       int i = 0;
+       FILE *fp;
+       char filename[256];
+       char buffer[16];
+
+       for (i = 0; i < num_cpu; i++)
+       {
+               status = ssnprintf (filename, sizeof (filename),
+                               "/sys/devices/system/cpu/cpu%d/cpufreq/"
+                               "scaling_cur_freq", i);
+               if ((status < 1) || ((unsigned int)status >= sizeof (filename)))
+                       return (-1);
+
+               if ((fp = fopen (filename, "r")) == NULL)
+               {
+                       char errbuf[1024];
+                       WARNING ("cpufreq: fopen (%s): %s", filename,
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       return (-1);
+               }
+
+               if (fgets (buffer, 16, fp) == NULL)
+               {
+                       char errbuf[1024];
+                       WARNING ("cpufreq: fgets: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       fclose (fp);
+                       return (-1);
+               }
+
+               if (fclose (fp))
+               {
+                       char errbuf[1024];
+                       WARNING ("cpufreq: fclose: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+               }
+
+
+               /* You're seeing correctly: The file is reporting kHz values.. */
+               val = atoll (buffer) * 1000;
+
+               cpufreq_submit (i, val);
+       }
+
+       return (0);
+} /* int cpufreq_read */
+
+void module_register (void)
+{
+       plugin_register_init ("cpufreq", cpufreq_init);
+       plugin_register_read ("cpufreq", cpufreq_read);
+}
diff --git a/src/cpython.h b/src/cpython.h
new file mode 100644 (file)
index 0000000..81e580d
--- /dev/null
@@ -0,0 +1,209 @@
+/**
+ * collectd - src/cpython.h
+ * Copyright (C) 2009  Sven Trenkel
+ *
+ * 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:
+ *   Sven Trenkel <collectd at semidefinite.de>  
+ **/
+
+/* Some python versions don't include this by default. */
+
+#include <longintrepr.h>
+
+/* These two macros are basically Py_BEGIN_ALLOW_THREADS and Py_BEGIN_ALLOW_THREADS
+ * from the other direction. If a Python thread calls a C function
+ * Py_BEGIN_ALLOW_THREADS is used to allow other python threads to run because
+ * we don't intend to call any Python functions.
+ *
+ * These two macros are used whenever a C thread intends to call some Python
+ * function, usually because some registered callback was triggered.
+ * Just like Py_BEGIN_ALLOW_THREADS it opens a block so these macros have to be
+ * used in pairs. They acquire the GIL, create a new Python thread state and swap
+ * the current thread state with the new one. This means this thread is now allowed
+ * to execute Python code. */
+
+#define CPY_LOCK_THREADS {\
+       PyGILState_STATE gil_state;\
+       gil_state = PyGILState_Ensure();
+
+#define CPY_RETURN_FROM_THREADS \
+       PyGILState_Release(gil_state);\
+       return
+
+#define CPY_RELEASE_THREADS \
+       PyGILState_Release(gil_state);\
+}
+
+/* Python 2.4 has this macro, older versions do not. */
+#ifndef Py_VISIT
+#define Py_VISIT(o) do {\
+       int _vret;\
+       if ((o) != NULL) {\
+               _vret = visit((o), arg);\
+               if (_vret != 0)\
+               return _vret;\
+       }\
+} while (0)
+#endif
+
+/* Python 2.4 has this macro, older versions do not. */
+#ifndef Py_CLEAR
+#define Py_CLEAR(o) do {\
+       PyObject *tmp = o;\
+       (o) = NULL;\
+       Py_XDECREF(tmp);\
+} while (0)
+#endif
+
+/* Python 2.4 has this macro, older versions do not. */
+#ifndef Py_RETURN_NONE
+# define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
+#endif
+
+/* This macro is a shortcut for calls like
+ * x = PyObject_Repr(x);
+ * This can't be done like this example because this would leak
+ * a reference the the original x and crash in case of x == NULL.
+ * This calling syntax is less than elegant but it works, saves
+ * a lot of lines and avoids potential refcount errors. */
+
+#define CPY_SUBSTITUTE(func, a, ...) do {\
+       if ((a) != NULL) {\
+               PyObject *__tmp = (a);\
+               (a) = func(__VA_ARGS__);\
+               Py_DECREF(__tmp);\
+       }\
+} while(0)
+
+/* Python3 compatibility layer. To keep the actual code as clean as possible
+ * do a lot of defines here. */
+
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#endif
+
+#ifdef IS_PY3K
+
+#define PyInt_FromLong PyLong_FromLong
+#define CPY_INIT_TYPE         PyVarObject_HEAD_INIT(NULL, 0)
+#define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyBytes_Check(o))
+#define CPY_STRCAT_AND_DEL(a, b) do {\
+       CPY_STRCAT((a), (b));\
+       Py_XDECREF((b));\
+} while (0)
+static inline void CPY_STRCAT(PyObject **a, PyObject *b) {
+       PyObject *ret;
+       
+       if (!a || !*a)
+               return;
+       
+       ret = PyUnicode_Concat(*a, b);
+       Py_DECREF(*a);
+       *a = ret;
+}
+
+#else
+
+#define CPY_INIT_TYPE         PyObject_HEAD_INIT(NULL) 0,
+#define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyString_Check(o))
+#define CPY_STRCAT_AND_DEL PyString_ConcatAndDel
+#define CPY_STRCAT PyString_Concat
+
+#endif
+
+static inline const char *cpy_unicode_or_bytes_to_string(PyObject **o) {
+       if (PyUnicode_Check(*o)) {
+               PyObject *tmp;
+               tmp = PyUnicode_AsEncodedString(*o, NULL, NULL); /* New reference. */
+               if (tmp == NULL)
+                       return NULL;
+               Py_DECREF(*o);
+               *o = tmp;
+       }
+#ifdef IS_PY3K
+       return PyBytes_AsString(*o);
+#else
+       return PyString_AsString(*o);
+#endif
+}
+
+static inline PyObject *cpy_string_to_unicode_or_bytes(const char *buf) {
+#ifdef IS_PY3K
+/* Python3 preferrs unicode */
+       PyObject *ret;
+       ret = PyUnicode_Decode(buf, strlen(buf), NULL, NULL);
+       if (ret != NULL)
+               return ret;
+       PyErr_Clear();
+       return PyBytes_FromString(buf);
+#else
+       return PyString_FromString(buf);
+#endif 
+}
+
+void cpy_log_exception(const char *context);
+
+/* Python object declarations. */
+
+typedef struct {
+       PyObject_HEAD        /* No semicolon! */
+       PyObject *parent;    /* Config */
+       PyObject *key;       /* String */
+       PyObject *values;    /* Sequence */
+       PyObject *children;  /* Sequence */
+} Config;
+PyTypeObject ConfigType;
+
+typedef struct {
+       PyObject_HEAD        /* No semicolon! */
+       double time;
+       char host[DATA_MAX_NAME_LEN];
+       char plugin[DATA_MAX_NAME_LEN];
+       char plugin_instance[DATA_MAX_NAME_LEN];
+       char type[DATA_MAX_NAME_LEN];
+       char type_instance[DATA_MAX_NAME_LEN];
+} PluginData;
+PyTypeObject PluginDataType;
+#define PluginData_New() PyObject_CallFunctionObjArgs((PyObject *) &PluginDataType, (void *) 0)
+
+typedef struct {
+       PluginData data;
+       PyObject *values;    /* Sequence */
+       PyObject *meta;      /* dict */
+       double interval;
+} Values;
+PyTypeObject ValuesType;
+#define Values_New() PyObject_CallFunctionObjArgs((PyObject *) &ValuesType, (void *) 0)
+
+typedef struct {
+       PluginData data;
+       int severity;
+       char message[NOTIF_MAX_MSG_LEN];
+} Notification;
+PyTypeObject NotificationType;
+#define Notification_New() PyObject_CallFunctionObjArgs((PyObject *) &NotificationType, (void *) 0)
+
+typedef PyLongObject Signed;
+PyTypeObject SignedType;
+
+typedef PyLongObject Unsigned;
+PyTypeObject UnsignedType;
+
diff --git a/src/csv.c b/src/csv.c
new file mode 100644 (file)
index 0000000..b6e535e
--- /dev/null
+++ b/src/csv.c
@@ -0,0 +1,373 @@
+/**
+ * collectd - src/csv.c
+ * Copyright (C) 2007-2009  Florian octo Forster
+ * Copyright (C) 2009       Doug MacEachern
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Doug MacEachern <dougm@hyperic.com>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_cache.h"
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+       "DataDir",
+       "StoreRates"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char *datadir   = NULL;
+static int store_rates = 0;
+static int use_stdio   = 0;
+
+static int value_list_to_string (char *buffer, int buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       int offset;
+       int status;
+       int i;
+       gauge_t *rates = NULL;
+
+       assert (0 == strcmp (ds->type, vl->type));
+
+       memset (buffer, '\0', buffer_len);
+
+       status = ssnprintf (buffer, buffer_len, "%.3f",
+                       CDTIME_T_TO_DOUBLE (vl->time));
+       if ((status < 1) || (status >= buffer_len))
+               return (-1);
+       offset = status;
+
+       for (i = 0; i < ds->ds_num; i++)
+       {
+               if ((ds->ds[i].type != DS_TYPE_COUNTER)
+                               && (ds->ds[i].type != DS_TYPE_GAUGE)
+                               && (ds->ds[i].type != DS_TYPE_DERIVE)
+                               && (ds->ds[i].type != DS_TYPE_ABSOLUTE))
+                       return (-1);
+
+               if (ds->ds[i].type == DS_TYPE_GAUGE) 
+               {
+                       status = ssnprintf (buffer + offset, buffer_len - offset,
+                                       ",%lf", vl->values[i].gauge);
+               } 
+               else if (store_rates != 0)
+               {
+                       if (rates == NULL)
+                               rates = uc_get_rate (ds, vl);
+                       if (rates == NULL)
+                       {
+                               WARNING ("csv plugin: "
+                                               "uc_get_rate failed.");
+                               return (-1);
+                       }
+                       status = ssnprintf (buffer + offset,
+                                       buffer_len - offset,
+                                       ",%lf", rates[i]);
+               }
+               else if (ds->ds[i].type == DS_TYPE_COUNTER)
+               {
+                       status = ssnprintf (buffer + offset,
+                                       buffer_len - offset,
+                                       ",%llu",
+                                       vl->values[i].counter);
+               }
+               else if (ds->ds[i].type == DS_TYPE_DERIVE)
+               {
+                       status = ssnprintf (buffer + offset,
+                                       buffer_len - offset,
+                                       ",%"PRIi64,
+                                       vl->values[i].derive);
+               }
+               else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+               {
+                       status = ssnprintf (buffer + offset,
+                                       buffer_len - offset,
+                                       ",%"PRIu64,
+                                       vl->values[i].absolute);
+               }
+
+               if ((status < 1) || (status >= (buffer_len - offset)))
+               {
+                       sfree (rates);
+                       return (-1);
+               }
+
+               offset += status;
+       } /* for ds->ds_num */
+
+       sfree (rates);
+       return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, size_t buffer_size,
+               value_list_t const *vl)
+{
+       int status;
+
+       char *ptr = buffer;
+       size_t ptr_size = buffer_size;
+       time_t now;
+       struct tm struct_tm;
+
+       if (datadir != NULL)
+       {
+               size_t len = strlen (datadir) + 1;
+
+               if (len >= ptr_size)
+                       return (ENOBUFS);
+
+               memcpy (ptr, datadir, len);
+               ptr[len-1] = '/';
+               ptr_size -= len;
+               ptr += len;
+       }
+
+       status = FORMAT_VL (ptr, ptr_size, vl);
+       if (status != 0)
+               return (status);
+
+       /* Skip all the time formatting stuff when printing to STDOUT or
+        * STDERR. */
+       if (use_stdio)
+               return (0);
+
+       ptr_size -= strlen (ptr);
+       ptr +=  strlen (ptr);
+
+       /* "-2013-07-12" => 11 bytes */
+       if (ptr_size < 12)
+       {
+               ERROR ("csv plugin: Buffer too small.");
+               return (ENOMEM);
+       }
+
+       /* TODO: Find a way to minimize the calls to `localtime_r',
+        * since they are pretty expensive.. */
+       now = time (NULL);
+       if (localtime_r (&now, &struct_tm) == NULL)
+       {
+               ERROR ("csv plugin: localtime_r failed");
+               return (-1);
+       }
+
+       status = strftime (ptr, ptr_size, "-%Y-%m-%d", &struct_tm);
+       if (status == 0) /* yep, it returns zero on error. */
+       {
+               ERROR ("csv plugin: strftime failed");
+               return (-1);
+       }
+
+       return (0);
+} /* int value_list_to_filename */
+
+static int csv_create_file (const char *filename, const data_set_t *ds)
+{
+       FILE *csv;
+       int i;
+
+       if (check_create_dir (filename))
+               return (-1);
+
+       csv = fopen (filename, "w");
+       if (csv == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("csv plugin: fopen (%s) failed: %s",
+                               filename,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       fprintf (csv, "epoch");
+       for (i = 0; i < ds->ds_num; i++)
+               fprintf (csv, ",%s", ds->ds[i].name);
+
+       fprintf (csv, "\n");
+       fclose (csv);
+
+       return 0;
+} /* int csv_create_file */
+
+static int csv_config (const char *key, const char *value)
+{
+       if (strcasecmp ("DataDir", key) == 0)
+       {
+               if (datadir != NULL)
+               {
+                       free (datadir);
+                       datadir = NULL;
+               }
+               if (strcasecmp ("stdout", value) == 0)
+               {
+                       use_stdio = 1;
+                       return (0);
+               }
+               else if (strcasecmp ("stderr", value) == 0)
+               {
+                       use_stdio = 2;
+                       return (0);
+               }
+               datadir = strdup (value);
+               if (datadir != NULL)
+               {
+                       int len = strlen (datadir);
+                       while ((len > 0) && (datadir[len - 1] == '/'))
+                       {
+                               len--;
+                               datadir[len] = '\0';
+                       }
+                       if (len <= 0)
+                       {
+                               free (datadir);
+                               datadir = NULL;
+                       }
+               }
+       }
+       else if (strcasecmp ("StoreRates", key) == 0)
+       {
+               if (IS_TRUE (value))
+                       store_rates = 1;
+               else
+                       store_rates = 0;
+       }
+       else
+       {
+               return (-1);
+       }
+       return (0);
+} /* int csv_config */
+
+static int csv_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       struct stat  statbuf;
+       char         filename[512];
+       char         values[4096];
+       FILE        *csv;
+       int          csv_fd;
+       struct flock fl;
+       int          status;
+
+       if (0 != strcmp (ds->type, vl->type)) {
+               ERROR ("csv plugin: DS type does not match value list type");
+               return -1;
+       }
+
+       status = value_list_to_filename (filename, sizeof (filename), vl);
+       if (status != 0)
+               return (-1);
+
+       DEBUG ("csv plugin: csv_write: filename = %s;", filename);
+
+       if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+               return (-1);
+
+       if (use_stdio)
+       {
+               size_t i;
+
+               escape_string (filename, sizeof (filename));
+
+               /* Replace commas by colons for PUTVAL compatible output. */
+               for (i = 0; i < sizeof (values); i++)
+               {
+                       if (values[i] == 0)
+                               break;
+                       else if (values[i] == ',')
+                               values[i] = ':';
+               }
+
+               fprintf (use_stdio == 1 ? stdout : stderr,
+                        "PUTVAL %s interval=%.3f %s\n",
+                        filename,
+                        CDTIME_T_TO_DOUBLE (vl->interval),
+                        values);
+               return (0);
+       }
+
+       if (stat (filename, &statbuf) == -1)
+       {
+               if (errno == ENOENT)
+               {
+                       if (csv_create_file (filename, ds))
+                               return (-1);
+               }
+               else
+               {
+                       char errbuf[1024];
+                       ERROR ("stat(%s) failed: %s", filename,
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       return (-1);
+               }
+       }
+       else if (!S_ISREG (statbuf.st_mode))
+       {
+               ERROR ("stat(%s): Not a regular file!",
+                               filename);
+               return (-1);
+       }
+
+       csv = fopen (filename, "a");
+       if (csv == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("csv plugin: fopen (%s) failed: %s", filename,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+       csv_fd = fileno (csv);
+
+       memset (&fl, '\0', sizeof (fl));
+       fl.l_start  = 0;
+       fl.l_len    = 0; /* till end of file */
+       fl.l_pid    = getpid ();
+       fl.l_type   = F_WRLCK;
+       fl.l_whence = SEEK_SET;
+
+       status = fcntl (csv_fd, F_SETLK, &fl);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("csv plugin: flock (%s) failed: %s", filename,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               fclose (csv);
+               return (-1);
+       }
+
+       fprintf (csv, "%s\n", values);
+
+       /* The lock is implicitely released. I we don't release it explicitely
+        * because the `FILE *' may need to flush a cache first */
+       fclose (csv);
+
+       return (0);
+} /* int csv_write */
+
+void module_register (void)
+{
+       plugin_register_config ("csv", csv_config,
+                       config_keys, config_keys_num);
+       plugin_register_write ("csv", csv_write, /* user_data = */ NULL);
+} /* void module_register */
diff --git a/src/curl.c b/src/curl.c
new file mode 100644 (file)
index 0000000..b750f80
--- /dev/null
@@ -0,0 +1,739 @@
+/**
+ * collectd - src/curl.c
+ * Copyright (C) 2006-2009  Florian octo Forster
+ * Copyright (C) 2009       Aman Gupta
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Aman Gupta <aman at tmm1.net>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_match.h"
+#include "utils_time.h"
+
+#include <curl/curl.h>
+
+/*
+ * Data types
+ */
+struct web_match_s;
+typedef struct web_match_s web_match_t;
+struct web_match_s /* {{{ */
+{
+  char *regex;
+  char *exclude_regex;
+  int dstype;
+  char *type;
+  char *instance;
+
+  cu_match_t *match;
+
+  web_match_t *next;
+}; /* }}} */
+
+struct web_page_s;
+typedef struct web_page_s web_page_t;
+struct web_page_s /* {{{ */
+{
+  char *instance;
+
+  char *url;
+  char *user;
+  char *pass;
+  char *credentials;
+  _Bool digest;
+  _Bool verify_peer;
+  _Bool verify_host;
+  char *cacert;
+  struct curl_slist *headers;
+  char *post_body;
+  _Bool response_time;
+  _Bool response_code;
+  int timeout;
+
+  CURL *curl;
+  char curl_errbuf[CURL_ERROR_SIZE];
+  char *buffer;
+  size_t buffer_size;
+  size_t buffer_fill;
+
+  web_match_t *matches;
+
+  web_page_t *next;
+}; /* }}} */
+
+/*
+ * Global variables;
+ */
+/* static CURLM *curl = NULL; */
+static web_page_t *pages_g = NULL;
+
+/*
+ * Private functions
+ */
+static size_t cc_curl_callback (void *buf, /* {{{ */
+    size_t size, size_t nmemb, void *user_data)
+{
+  web_page_t *wp;
+  size_t len;
+
+  len = size * nmemb;
+  if (len <= 0)
+    return (len);
+
+  wp = user_data;
+  if (wp == NULL)
+    return (0);
+
+  if ((wp->buffer_fill + len) >= wp->buffer_size)
+  {
+    char *temp;
+    size_t temp_size;
+
+    temp_size = wp->buffer_fill + len + 1;
+    temp = (char *) realloc (wp->buffer, temp_size);
+    if (temp == NULL)
+    {
+      ERROR ("curl plugin: realloc failed.");
+      return (0);
+    }
+    wp->buffer = temp;
+    wp->buffer_size = temp_size;
+  }
+
+  memcpy (wp->buffer + wp->buffer_fill, (char *) buf, len);
+  wp->buffer_fill += len;
+  wp->buffer[wp->buffer_fill] = 0;
+
+  return (len);
+} /* }}} size_t cc_curl_callback */
+
+static void cc_web_match_free (web_match_t *wm) /* {{{ */
+{
+  if (wm == NULL)
+    return;
+
+  sfree (wm->regex);
+  sfree (wm->type);
+  sfree (wm->instance);
+  match_destroy (wm->match);
+  cc_web_match_free (wm->next);
+  sfree (wm);
+} /* }}} void cc_web_match_free */
+
+static void cc_web_page_free (web_page_t *wp) /* {{{ */
+{
+  if (wp == NULL)
+    return;
+
+  if (wp->curl != NULL)
+    curl_easy_cleanup (wp->curl);
+  wp->curl = NULL;
+
+  sfree (wp->instance);
+
+  sfree (wp->url);
+  sfree (wp->user);
+  sfree (wp->pass);
+  sfree (wp->credentials);
+  sfree (wp->cacert);
+  sfree (wp->post_body);
+  curl_slist_free_all (wp->headers);
+
+  sfree (wp->buffer);
+
+  cc_web_match_free (wp->matches);
+  cc_web_page_free (wp->next);
+  sfree (wp);
+} /* }}} void cc_web_page_free */
+
+static int cc_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl plugin: `%s' needs exactly one string argument.", name);
+    return (-1);
+  }
+
+  *dest = curl_slist_append(*dest, ci->values[0].value.string);
+  if (*dest == NULL)
+    return (-1);
+
+  return (0);
+} /* }}} int cc_config_append_string */
+
+static int cc_config_add_match_dstype (int *dstype_ret, /* {{{ */
+    oconfig_item_t *ci)
+{
+  int dstype;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl plugin: `DSType' needs exactly one string argument.");
+    return (-1);
+  }
+
+  if (strncasecmp ("Gauge", ci->values[0].value.string,
+        strlen ("Gauge")) == 0)
+  {
+    dstype = UTILS_MATCH_DS_TYPE_GAUGE;
+    if (strcasecmp ("GaugeAverage", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_AVERAGE;
+    else if (strcasecmp ("GaugeMin", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_MIN;
+    else if (strcasecmp ("GaugeMax", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_MAX;
+    else if (strcasecmp ("GaugeLast", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_LAST;
+    else
+      dstype = 0;
+  }
+  else if (strncasecmp ("Counter", ci->values[0].value.string,
+        strlen ("Counter")) == 0)
+  {
+    dstype = UTILS_MATCH_DS_TYPE_COUNTER;
+    if (strcasecmp ("CounterSet", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_COUNTER_SET;
+    else if (strcasecmp ("CounterAdd", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_COUNTER_ADD;
+    else if (strcasecmp ("CounterInc", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_COUNTER_INC;
+    else
+      dstype = 0;
+  }
+else if (strncasecmp ("Derive", ci->values[0].value.string,
+        strlen ("Derive")) == 0)
+  {
+    dstype = UTILS_MATCH_DS_TYPE_DERIVE;
+    if (strcasecmp ("DeriveSet", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_DERIVE_SET;
+    else if (strcasecmp ("DeriveAdd", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_DERIVE_ADD;
+    else if (strcasecmp ("DeriveInc", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_DERIVE_INC;
+    else
+      dstype = 0;
+  }
+else if (strncasecmp ("Absolute", ci->values[0].value.string,
+        strlen ("Absolute")) == 0)
+  {
+    dstype = UTILS_MATCH_DS_TYPE_ABSOLUTE;
+    if (strcasecmp ("AbsoluteSet", ci->values[0].value.string) == 0) /* Absolute DS is reset-on-read so no sense doin anything else but set */
+      dstype |= UTILS_MATCH_CF_ABSOLUTE_SET;
+    else
+      dstype = 0;
+  }
+
+  else
+  {
+    dstype = 0;
+  }
+
+  if (dstype == 0)
+  {
+    WARNING ("curl plugin: `%s' is not a valid argument to `DSType'.",
+       ci->values[0].value.string);
+    return (-1);
+  }
+
+  *dstype_ret = dstype;
+  return (0);
+} /* }}} int cc_config_add_match_dstype */
+
+static int cc_config_add_match (web_page_t *page, /* {{{ */
+    oconfig_item_t *ci)
+{
+  web_match_t *match;
+  int status;
+  int i;
+
+  if (ci->values_num != 0)
+  {
+    WARNING ("curl plugin: Ignoring arguments for the `Match' block.");
+  }
+
+  match = (web_match_t *) malloc (sizeof (*match));
+  if (match == NULL)
+  {
+    ERROR ("curl plugin: malloc failed.");
+    return (-1);
+  }
+  memset (match, 0, sizeof (*match));
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Regex", child->key) == 0)
+      status = cf_util_get_string (child, &match->regex);
+    else if (strcasecmp ("ExcludeRegex", child->key) == 0)
+      status = cf_util_get_string (child, &match->exclude_regex);
+    else if (strcasecmp ("DSType", child->key) == 0)
+      status = cc_config_add_match_dstype (&match->dstype, child);
+    else if (strcasecmp ("Type", child->key) == 0)
+      status = cf_util_get_string (child, &match->type);
+    else if (strcasecmp ("Instance", child->key) == 0)
+      status = cf_util_get_string (child, &match->instance);
+    else
+    {
+      WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  while (status == 0)
+  {
+    if (match->regex == NULL)
+    {
+      WARNING ("curl plugin: `Regex' missing in `Match' block.");
+      status = -1;
+    }
+
+    if (match->type == NULL)
+    {
+      WARNING ("curl plugin: `Type' missing in `Match' block.");
+      status = -1;
+    }
+
+    if (match->dstype == 0)
+    {
+      WARNING ("curl plugin: `DSType' missing in `Match' block.");
+      status = -1;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+    return (status);
+
+  match->match = match_create_simple (match->regex, match->exclude_regex,
+      match->dstype);
+  if (match->match == NULL)
+  {
+    ERROR ("curl plugin: tail_match_add_match_simple failed.");
+    cc_web_match_free (match);
+    return (-1);
+  }
+  else
+  {
+    web_match_t *prev;
+
+    prev = page->matches;
+    while ((prev != NULL) && (prev->next != NULL))
+      prev = prev->next;
+
+    if (prev == NULL)
+      page->matches = match;
+    else
+      prev->next = match;
+  }
+
+  return (0);
+} /* }}} int cc_config_add_match */
+
+static int cc_page_init_curl (web_page_t *wp) /* {{{ */
+{
+  wp->curl = curl_easy_init ();
+  if (wp->curl == NULL)
+  {
+    ERROR ("curl plugin: curl_easy_init failed.");
+    return (-1);
+  }
+
+  curl_easy_setopt (wp->curl, CURLOPT_NOSIGNAL, 1L);
+  curl_easy_setopt (wp->curl, CURLOPT_WRITEFUNCTION, cc_curl_callback);
+  curl_easy_setopt (wp->curl, CURLOPT_WRITEDATA, wp);
+  curl_easy_setopt (wp->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+  curl_easy_setopt (wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
+  curl_easy_setopt (wp->curl, CURLOPT_URL, wp->url);
+  curl_easy_setopt (wp->curl, CURLOPT_FOLLOWLOCATION, 1L);
+  curl_easy_setopt (wp->curl, CURLOPT_MAXREDIRS, 50L);
+
+  if (wp->user != NULL)
+  {
+#ifdef HAVE_CURLOPT_USERNAME
+    curl_easy_setopt (wp->curl, CURLOPT_USERNAME, wp->user);
+    curl_easy_setopt (wp->curl, CURLOPT_PASSWORD,
+        (wp->pass == NULL) ? "" : wp->pass);
+#else
+    size_t credentials_size;
+
+    credentials_size = strlen (wp->user) + 2;
+    if (wp->pass != NULL)
+      credentials_size += strlen (wp->pass);
+
+    wp->credentials = (char *) malloc (credentials_size);
+    if (wp->credentials == NULL)
+    {
+      ERROR ("curl plugin: malloc failed.");
+      return (-1);
+    }
+
+    ssnprintf (wp->credentials, credentials_size, "%s:%s",
+        wp->user, (wp->pass == NULL) ? "" : wp->pass);
+    curl_easy_setopt (wp->curl, CURLOPT_USERPWD, wp->credentials);
+#endif
+
+    if (wp->digest)
+      curl_easy_setopt (wp->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+  }
+
+  curl_easy_setopt (wp->curl, CURLOPT_SSL_VERIFYPEER, (long) wp->verify_peer);
+  curl_easy_setopt (wp->curl, CURLOPT_SSL_VERIFYHOST,
+      wp->verify_host ? 2L : 0L);
+  if (wp->cacert != NULL)
+    curl_easy_setopt (wp->curl, CURLOPT_CAINFO, wp->cacert);
+  if (wp->headers != NULL)
+    curl_easy_setopt (wp->curl, CURLOPT_HTTPHEADER, wp->headers);
+  if (wp->post_body != NULL)
+    curl_easy_setopt (wp->curl, CURLOPT_POSTFIELDS, wp->post_body);
+
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+  if (wp->timeout >= 0)
+    curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS, (long) wp->timeout);
+  else
+    curl_easy_setopt (wp->curl, CURLOPT_TIMEOUT_MS,
+       CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
+  return (0);
+} /* }}} int cc_page_init_curl */
+
+static int cc_config_add_page (oconfig_item_t *ci) /* {{{ */
+{
+  web_page_t *page;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl plugin: `Page' blocks need exactly one string argument.");
+    return (-1);
+  }
+
+  page = (web_page_t *) malloc (sizeof (*page));
+  if (page == NULL)
+  {
+    ERROR ("curl plugin: malloc failed.");
+    return (-1);
+  }
+  memset (page, 0, sizeof (*page));
+  page->url = NULL;
+  page->user = NULL;
+  page->pass = NULL;
+  page->digest = 0;
+  page->verify_peer = 1;
+  page->verify_host = 1;
+  page->response_time = 0;
+  page->response_code = 0;
+  page->timeout = -1;
+
+  page->instance = strdup (ci->values[0].value.string);
+  if (page->instance == NULL)
+  {
+    ERROR ("curl plugin: strdup failed.");
+    sfree (page);
+    return (-1);
+  }
+
+  /* Process all children */
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("URL", child->key) == 0)
+      status = cf_util_get_string (child, &page->url);
+    else if (strcasecmp ("User", child->key) == 0)
+      status = cf_util_get_string (child, &page->user);
+    else if (strcasecmp ("Password", child->key) == 0)
+      status = cf_util_get_string (child, &page->pass);
+    else if (strcasecmp ("Digest", child->key) == 0)
+      status = cf_util_get_boolean (child, &page->digest);
+    else if (strcasecmp ("VerifyPeer", child->key) == 0)
+      status = cf_util_get_boolean (child, &page->verify_peer);
+    else if (strcasecmp ("VerifyHost", child->key) == 0)
+      status = cf_util_get_boolean (child, &page->verify_host);
+    else if (strcasecmp ("MeasureResponseTime", child->key) == 0)
+      status = cf_util_get_boolean (child, &page->response_time);
+    else if (strcasecmp ("MeasureResponseCode", child->key) == 0)
+      status = cf_util_get_boolean (child, &page->response_code);
+    else if (strcasecmp ("CACert", child->key) == 0)
+      status = cf_util_get_string (child, &page->cacert);
+    else if (strcasecmp ("Match", child->key) == 0)
+      /* Be liberal with failing matches => don't set `status'. */
+      cc_config_add_match (page, child);
+    else if (strcasecmp ("Header", child->key) == 0)
+      status = cc_config_append_string ("Header", &page->headers, child);
+    else if (strcasecmp ("Post", child->key) == 0)
+      status = cf_util_get_string (child, &page->post_body);
+    else if (strcasecmp ("Timeout", child->key) == 0)
+      status = cf_util_get_int (child, &page->timeout);
+    else
+    {
+      WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  /* Additionial sanity checks and libCURL initialization. */
+  while (status == 0)
+  {
+    if (page->url == NULL)
+    {
+      WARNING ("curl plugin: `URL' missing in `Page' block.");
+      status = -1;
+    }
+
+    if (page->matches == NULL && !page->response_time && !page->response_code)
+    {
+      assert (page->instance != NULL);
+      WARNING ("curl plugin: No (valid) `Match' block "
+          "or MeasureResponseTime or MeasureResponseCode within "
+          "`Page' block `%s'.", page->instance);
+      status = -1;
+    }
+
+    if (status == 0)
+      status = cc_page_init_curl (page);
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+  {
+    cc_web_page_free (page);
+    return (status);
+  }
+
+  /* Add the new page to the linked list */
+  if (pages_g == NULL)
+    pages_g = page;
+  else
+  {
+    web_page_t *prev;
+
+    prev = pages_g;
+    while ((prev != NULL) && (prev->next != NULL))
+      prev = prev->next;
+    prev->next = page;
+  }
+
+  return (0);
+} /* }}} int cc_config_add_page */
+
+static int cc_config (oconfig_item_t *ci) /* {{{ */
+{
+  int success;
+  int errors;
+  int status;
+  int i;
+
+  success = 0;
+  errors = 0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Page", child->key) == 0)
+    {
+      status = cc_config_add_page (child);
+      if (status == 0)
+        success++;
+      else
+        errors++;
+    }
+    else
+    {
+      WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
+      errors++;
+    }
+  }
+
+  if ((success == 0) && (errors > 0))
+  {
+    ERROR ("curl plugin: All statements failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cc_config */
+
+static int cc_init (void) /* {{{ */
+{
+  if (pages_g == NULL)
+  {
+    INFO ("curl plugin: No pages have been defined.");
+    return (-1);
+  }
+  curl_global_init (CURL_GLOBAL_SSL);
+  return (0);
+} /* }}} int cc_init */
+
+static void cc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */
+    const cu_match_value_t *mv)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0] = mv->value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, wm->type, sizeof (vl.type));
+  if (wm->instance != NULL)
+    sstrncpy (vl.type_instance, wm->instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* }}} void cc_submit */
+
+static void cc_submit_response_code (const web_page_t *wp, long code) /* {{{ */
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = code;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, "response_code", sizeof (vl.type));
+
+  plugin_dispatch_values (&vl);
+} /* }}} void cc_submit_response_code */
+
+static void cc_submit_response_time (const web_page_t *wp, /* {{{ */
+    cdtime_t response_time)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = CDTIME_T_TO_DOUBLE (response_time);
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "curl", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, "response_time", sizeof (vl.type));
+
+  plugin_dispatch_values (&vl);
+} /* }}} void cc_submit_response_time */
+
+static int cc_read_page (web_page_t *wp) /* {{{ */
+{
+  web_match_t *wm;
+  int status;
+  cdtime_t start = 0;
+
+  if (wp->response_time)
+    start = cdtime ();
+
+  wp->buffer_fill = 0;
+  status = curl_easy_perform (wp->curl);
+  if (status != CURLE_OK)
+  {
+    ERROR ("curl plugin: curl_easy_perform failed with status %i: %s",
+        status, wp->curl_errbuf);
+    return (-1);
+  }
+
+  if (wp->response_time)
+    cc_submit_response_time (wp, cdtime() - start);
+
+  if(wp->response_code)
+  {
+    long response_code = 0;
+    status = curl_easy_getinfo(wp->curl, CURLINFO_RESPONSE_CODE, &response_code);
+    if(status != CURLE_OK) {
+      ERROR ("curl plugin: Fetching response code failed with status %i: %s",
+        status, wp->curl_errbuf);
+    } else {
+      cc_submit_response_code(wp, response_code);
+    }
+  }
+
+  for (wm = wp->matches; wm != NULL; wm = wm->next)
+  {
+    cu_match_value_t *mv;
+
+    status = match_apply (wm->match, wp->buffer);
+    if (status != 0)
+    {
+      WARNING ("curl plugin: match_apply failed.");
+      continue;
+    }
+
+    mv = match_get_user_data (wm->match);
+    if (mv == NULL)
+    {
+      WARNING ("curl plugin: match_get_user_data returned NULL.");
+      continue;
+    }
+
+    cc_submit (wp, wm, mv);
+    match_value_reset (mv);
+  } /* for (wm = wp->matches; wm != NULL; wm = wm->next) */
+
+  return (0);
+} /* }}} int cc_read_page */
+
+static int cc_read (void) /* {{{ */
+{
+  web_page_t *wp;
+
+  for (wp = pages_g; wp != NULL; wp = wp->next)
+    cc_read_page (wp);
+
+  return (0);
+} /* }}} int cc_read */
+
+static int cc_shutdown (void) /* {{{ */
+{
+  cc_web_page_free (pages_g);
+  pages_g = NULL;
+
+  return (0);
+} /* }}} int cc_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("curl", cc_config);
+  plugin_register_init ("curl", cc_init);
+  plugin_register_read ("curl", cc_read);
+  plugin_register_shutdown ("curl", cc_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/curl_json.c b/src/curl_json.c
new file mode 100644 (file)
index 0000000..3a5a3ab
--- /dev/null
@@ -0,0 +1,1029 @@
+/**
+ * collectd - src/curl_json.c
+ * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2006-2013  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Doug MacEachern <dougm at hyperic.com>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_avltree.h"
+#include "utils_complain.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <curl/curl.h>
+
+#include <yajl/yajl_parse.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 CJ_DEFAULT_HOST "localhost"
+#define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
+#define CJ_IS_KEY(key) ((key)->magic == CJ_KEY_MAGIC)
+#define CJ_ANY "*"
+#define COUCH_MIN(x,y) ((x) < (y) ? (x) : (y))
+
+struct cj_key_s;
+typedef struct cj_key_s cj_key_t;
+struct cj_key_s /* {{{ */
+{
+  unsigned long magic;
+  char *path;
+  char *type;
+  char *instance;
+};
+/* }}} */
+
+struct cj_s /* {{{ */
+{
+  char *instance;
+  char *host;
+
+  char *sock;
+
+  char *url;
+  char *user;
+  char *pass;
+  char *credentials;
+  _Bool digest;
+  _Bool verify_peer;
+  _Bool verify_host;
+  char *cacert;
+  struct curl_slist *headers;
+  char *post_body;
+  cdtime_t interval;
+  int timeout;
+
+  CURL *curl;
+  char curl_errbuf[CURL_ERROR_SIZE];
+
+  yajl_handle yajl;
+  c_avl_tree_t *tree;
+  cj_key_t *key;
+  int depth;
+  struct {
+    union {
+      c_avl_tree_t *tree;
+      cj_key_t *key;
+    };
+    _Bool in_array;
+    int index;
+    char name[DATA_MAX_NAME_LEN];
+  } state[YAJL_MAX_DEPTH];
+};
+typedef struct cj_s cj_t; /* }}} */
+
+#if HAVE_YAJL_V2
+typedef size_t yajl_len_t;
+#else
+typedef unsigned int yajl_len_t;
+#endif
+
+static int cj_read (user_data_t *ud);
+static void cj_submit (cj_t *db, cj_key_t *key, value_t *value);
+
+static size_t cj_curl_callback (void *buf, /* {{{ */
+    size_t size, size_t nmemb, void *user_data)
+{
+  cj_t *db;
+  size_t len;
+  yajl_status status;
+
+  len = size * nmemb;
+
+  if (len <= 0)
+    return (len);
+
+  db = user_data;
+  if (db == NULL)
+    return (0);
+
+  status = yajl_parse(db->yajl, (unsigned char *)buf, len);
+  if (status == yajl_status_ok)
+    return (len);
+#if !HAVE_YAJL_V2
+  else if (status == yajl_status_insufficient_data)
+    return (len);
+#endif
+
+  if (status != yajl_status_ok)
+  {
+    unsigned char *msg =
+      yajl_get_error(db->yajl, /* verbose = */ 1,
+          /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
+    ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
+    yajl_free_error(db->yajl, msg);
+    return (0); /* abort write callback */
+  }
+
+  return (len);
+} /* }}} size_t cj_curl_callback */
+
+static int cj_get_type (cj_key_t *key)
+{
+  const data_set_t *ds;
+
+  ds = plugin_get_ds (key->type);
+  if (ds == NULL)
+  {
+    static char type[DATA_MAX_NAME_LEN] = "!!!invalid!!!";
+
+    assert (key->type != NULL);
+    if (strcmp (type, key->type) != 0)
+    {
+      ERROR ("curl_json plugin: Unable to look up DS type \"%s\".",
+          key->type);
+      sstrncpy (type, key->type, sizeof (type));
+    }
+
+    return -1;
+  }
+  else if (ds->ds_num > 1)
+  {
+    static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
+
+    c_complain_once (LOG_WARNING, &complaint,
+        "curl_json plugin: The type \"%s\" has more than one data source. "
+        "This is currently not supported. I will return the type of the "
+        "first data source, but this will likely lead to problems later on.",
+        key->type);
+  }
+
+  return ds->ds[0].type;
+}
+
+static int cj_cb_map_key (void *ctx, const unsigned char *val,
+    yajl_len_t len);
+
+static void cj_cb_inc_array_index (void *ctx, _Bool update_key)
+{
+  cj_t *db = (cj_t *)ctx;
+
+  if (!db->state[db->depth].in_array)
+    return;
+
+  db->state[db->depth].index++;
+
+  if (update_key)
+  {
+    char name[DATA_MAX_NAME_LEN];
+
+    ssnprintf (name, sizeof (name), "%d", db->state[db->depth].index - 1);
+
+    cj_cb_map_key (ctx, (unsigned char *)name, (yajl_len_t) strlen (name));
+  }
+}
+
+/* yajl callbacks */
+#define CJ_CB_ABORT    0
+#define CJ_CB_CONTINUE 1
+
+static int cj_cb_boolean (void * ctx, int boolVal)
+{
+  cj_cb_inc_array_index (ctx, /* update_key = */ 0);
+  return (CJ_CB_CONTINUE);
+}
+
+static int cj_cb_null (void * ctx)
+{
+  cj_cb_inc_array_index (ctx, /* update_key = */ 0);
+  return (CJ_CB_CONTINUE);
+}
+
+static int cj_cb_number (void *ctx,
+    const char *number, yajl_len_t number_len)
+{
+  char buffer[number_len + 1];
+
+  cj_t *db = (cj_t *)ctx;
+  cj_key_t *key = db->state[db->depth].key;
+  value_t vt;
+  int type;
+  int status;
+
+  /* Create a null-terminated version of the string. */
+  memcpy (buffer, number, number_len);
+  buffer[sizeof (buffer) - 1] = 0;
+
+  if ((key == NULL) || !CJ_IS_KEY (key)) {
+    if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/)
+      NOTICE ("curl_json plugin: Found \"%s\", but the configuration expects"
+              " a map.", buffer);
+    cj_cb_inc_array_index (ctx, /* update_key = */ 1);
+    key = db->state[db->depth].key;
+    if (key == NULL) {
+      return (CJ_CB_CONTINUE);
+    }
+  }
+  else
+  {
+    cj_cb_inc_array_index (ctx, /* update_key = */ 1);
+  }
+
+  type = cj_get_type (key);
+  status = parse_value (buffer, &vt, type);
+  if (status != 0)
+  {
+    NOTICE ("curl_json plugin: Unable to parse number: \"%s\"", buffer);
+    return (CJ_CB_CONTINUE);
+  }
+
+  cj_submit (db, key, &vt);
+  return (CJ_CB_CONTINUE);
+} /* int cj_cb_number */
+
+/* Queries the key-tree of the parent context for "in_name" and, if found,
+ * updates the "key" field of the current context. Otherwise, "key" is set to
+ * NULL. */
+static int cj_cb_map_key (void *ctx,
+    unsigned char const *in_name, yajl_len_t in_name_len)
+{
+  cj_t *db = (cj_t *)ctx;
+  c_avl_tree_t *tree;
+
+  tree = db->state[db->depth-1].tree;
+
+  if (tree != NULL)
+  {
+    cj_key_t *value = NULL;
+    char *name;
+    size_t name_len;
+
+    /* Create a null-terminated version of the name. */
+    name = db->state[db->depth].name;
+    name_len = COUCH_MIN ((size_t) in_name_len,
+        sizeof (db->state[db->depth].name) - 1);
+    memcpy (name, in_name, name_len);
+    name[name_len] = 0;
+
+    if (c_avl_get (tree, name, (void *) &value) == 0) {
+      if (CJ_IS_KEY((cj_key_t*)value)) {
+        db->state[db->depth].key = value;
+      }
+      else {
+        db->state[db->depth].tree = (c_avl_tree_t*) value;
+      }
+    }
+    else if (c_avl_get (tree, CJ_ANY, (void *) &value) == 0)
+      if (CJ_IS_KEY((cj_key_t*)value)) {
+        db->state[db->depth].key = value;
+      }
+      else {
+        db->state[db->depth].tree = (c_avl_tree_t*) value;
+      }
+    else
+      db->state[db->depth].key = NULL;
+  }
+
+  return (CJ_CB_CONTINUE);
+}
+
+static int cj_cb_string (void *ctx, const unsigned char *val,
+    yajl_len_t len)
+{
+  /* Handle the string as if it was a number. */
+  return (cj_cb_number (ctx, (const char *) val, len));
+} /* int cj_cb_string */
+
+static int cj_cb_start (void *ctx)
+{
+  cj_t *db = (cj_t *)ctx;
+  if (++db->depth >= YAJL_MAX_DEPTH)
+  {
+    ERROR ("curl_json plugin: %s depth exceeds max, aborting.",
+           db->url ? db->url : db->sock);
+    return (CJ_CB_ABORT);
+  }
+  return (CJ_CB_CONTINUE);
+}
+
+static int cj_cb_end (void *ctx)
+{
+  cj_t *db = (cj_t *)ctx;
+  db->state[db->depth].tree = NULL;
+  --db->depth;
+  return (CJ_CB_CONTINUE);
+}
+
+static int cj_cb_start_map (void *ctx)
+{
+  cj_cb_inc_array_index (ctx, /* update_key = */ 1);
+  return cj_cb_start (ctx);
+}
+
+static int cj_cb_end_map (void *ctx)
+{
+  return cj_cb_end (ctx);
+}
+
+static int cj_cb_start_array (void * ctx)
+{
+  cj_t *db = (cj_t *)ctx;
+  cj_cb_inc_array_index (ctx, /* update_key = */ 1);
+  if (db->depth+1 < YAJL_MAX_DEPTH) {
+    db->state[db->depth+1].in_array = 1;
+    db->state[db->depth+1].index = 0;
+  }
+  return cj_cb_start (ctx);
+}
+
+static int cj_cb_end_array (void * ctx)
+{
+  cj_t *db = (cj_t *)ctx;
+  db->state[db->depth].in_array = 0;
+  return cj_cb_end (ctx);
+}
+
+static yajl_callbacks ycallbacks = {
+  cj_cb_null, /* null */
+  cj_cb_boolean, /* boolean */
+  NULL, /* integer */
+  NULL, /* double */
+  cj_cb_number,
+  cj_cb_string,
+  cj_cb_start_map,
+  cj_cb_map_key,
+  cj_cb_end_map,
+  cj_cb_start_array,
+  cj_cb_end_array
+};
+
+/* end yajl callbacks */
+
+static void cj_key_free (cj_key_t *key) /* {{{ */
+{
+  if (key == NULL)
+    return;
+
+  sfree (key->path);
+  sfree (key->type);
+  sfree (key->instance);
+
+  sfree (key);
+} /* }}} void cj_key_free */
+
+static void cj_tree_free (c_avl_tree_t *tree) /* {{{ */
+{
+  char *name;
+  void *value;
+
+  while (c_avl_pick (tree, (void *) &name, (void *) &value) == 0)
+  {
+    cj_key_t *key = (cj_key_t *)value;
+
+    if (CJ_IS_KEY(key))
+      cj_key_free (key);
+    else
+      cj_tree_free ((c_avl_tree_t *)value);
+
+    sfree (name);
+  }
+
+  c_avl_destroy (tree);
+} /* }}} void cj_tree_free */
+
+static void cj_free (void *arg) /* {{{ */
+{
+  cj_t *db;
+
+  DEBUG ("curl_json plugin: cj_free (arg = %p);", arg);
+
+  db = (cj_t *) arg;
+
+  if (db == NULL)
+    return;
+
+  if (db->curl != NULL)
+    curl_easy_cleanup (db->curl);
+  db->curl = NULL;
+
+  if (db->tree != NULL)
+    cj_tree_free (db->tree);
+  db->tree = NULL;
+
+  sfree (db->instance);
+  sfree (db->host);
+
+  sfree (db->sock);
+
+  sfree (db->url);
+  sfree (db->user);
+  sfree (db->pass);
+  sfree (db->credentials);
+  sfree (db->cacert);
+  sfree (db->post_body);
+  curl_slist_free_all (db->headers);
+
+  sfree (db);
+} /* }}} void cj_free */
+
+/* Configuration handling functions {{{ */
+
+static c_avl_tree_t *cj_avl_create(void)
+{
+  return c_avl_create ((int (*) (const void *, const void *)) strcmp);
+}
+
+static int cj_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl_json plugin: `%s' needs exactly one string argument.", name);
+    return (-1);
+  }
+
+  *dest = curl_slist_append(*dest, ci->values[0].value.string);
+  if (*dest == NULL)
+    return (-1);
+
+  return (0);
+} /* }}} int cj_config_append_string */
+
+static int cj_config_add_key (cj_t *db, /* {{{ */
+                                   oconfig_item_t *ci)
+{
+  cj_key_t *key;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl_json plugin: The `Key' block "
+             "needs exactly one string argument.");
+    return (-1);
+  }
+
+  key = (cj_key_t *) malloc (sizeof (*key));
+  if (key == NULL)
+  {
+    ERROR ("curl_json plugin: malloc failed.");
+    return (-1);
+  }
+  memset (key, 0, sizeof (*key));
+  key->magic = CJ_KEY_MAGIC;
+
+  if (strcasecmp ("Key", ci->key) == 0)
+  {
+    status = cf_util_get_string (ci, &key->path);
+    if (status != 0)
+    {
+      sfree (key);
+      return (status);
+    }
+  }
+  else
+  {
+    ERROR ("curl_json plugin: cj_config: "
+           "Invalid key: %s", ci->key);
+    return (-1);
+  }
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Type", child->key) == 0)
+      status = cf_util_get_string (child, &key->type);
+    else if (strcasecmp ("Instance", child->key) == 0)
+      status = cf_util_get_string (child, &key->instance);
+    else
+    {
+      WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  while (status == 0)
+  {
+    if (key->type == NULL)
+    {
+      WARNING ("curl_json plugin: `Type' missing in `Key' block.");
+      status = -1;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  /* store path in a tree that will match the json map structure, example:
+   * "httpd/requests/count",
+   * "httpd/requests/current" ->
+   * { "httpd": { "requests": { "count": $key, "current": $key } } }
+   */
+  if (status == 0)
+  {
+    char *ptr;
+    char *name;
+    char ent[PATH_MAX];
+    c_avl_tree_t *tree;
+
+    if (db->tree == NULL)
+      db->tree = cj_avl_create();
+
+    tree = db->tree;
+    name = key->path;
+    ptr = key->path;
+    if (*ptr == '/')
+      ++ptr;
+
+    name = ptr;
+    while (*ptr)
+    {
+      if (*ptr == '/')
+      {
+        c_avl_tree_t *value;
+        int len;
+
+        len = ptr-name;
+        if (len == 0)
+          break;
+        len = COUCH_MIN(len, sizeof (ent)-1);
+        sstrncpy (ent, name, len+1);
+
+        if (c_avl_get (tree, ent, (void *) &value) != 0)
+        {
+          value = cj_avl_create ();
+          c_avl_insert (tree, strdup (ent), value);
+        }
+
+        tree = value;
+        name = ptr+1;
+      }
+      ++ptr;
+    }
+    if (*name)
+      c_avl_insert (tree, strdup(name), key);
+    else
+    {
+      ERROR ("curl_json plugin: invalid key: %s", key->path);
+      status = -1;
+    }
+  }
+
+  return (status);
+} /* }}} int cj_config_add_key */
+
+static int cj_init_curl (cj_t *db) /* {{{ */
+{
+  db->curl = curl_easy_init ();
+  if (db->curl == NULL)
+  {
+    ERROR ("curl_json plugin: curl_easy_init failed.");
+    return (-1);
+  }
+
+  curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1L);
+  curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cj_curl_callback);
+  curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
+  curl_easy_setopt (db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+  curl_easy_setopt (db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
+  curl_easy_setopt (db->curl, CURLOPT_URL, db->url);
+  curl_easy_setopt (db->curl, CURLOPT_FOLLOWLOCATION, 1L);
+  curl_easy_setopt (db->curl, CURLOPT_MAXREDIRS, 50L);
+
+  if (db->user != NULL)
+  {
+#ifdef HAVE_CURLOPT_USERNAME
+    curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
+    curl_easy_setopt (db->curl, CURLOPT_PASSWORD,
+        (db->pass == NULL) ? "" : db->pass);
+#else
+    size_t credentials_size;
+
+    credentials_size = strlen (db->user) + 2;
+    if (db->pass != NULL)
+      credentials_size += strlen (db->pass);
+
+    db->credentials = (char *) malloc (credentials_size);
+    if (db->credentials == NULL)
+    {
+      ERROR ("curl_json plugin: malloc failed.");
+      return (-1);
+    }
+
+    ssnprintf (db->credentials, credentials_size, "%s:%s",
+               db->user, (db->pass == NULL) ? "" : db->pass);
+    curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
+#endif
+
+    if (db->digest)
+      curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+  }
+
+  curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, (long) db->verify_peer);
+  curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYHOST,
+                    db->verify_host ? 2L : 0L);
+  if (db->cacert != NULL)
+    curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
+  if (db->headers != NULL)
+    curl_easy_setopt (db->curl, CURLOPT_HTTPHEADER, db->headers);
+  if (db->post_body != NULL)
+    curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
+
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+  if (db->timeout >= 0)
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
+  else if (db->interval > 0)
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
+        CDTIME_T_TO_MS(db->timeout));
+  else
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
+        CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
+  return (0);
+} /* }}} int cj_init_curl */
+
+static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */
+{
+  cj_t *db;
+  int status = 0;
+  int i;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl_json plugin: The `URL' block "
+             "needs exactly one string argument.");
+    return (-1);
+  }
+
+  db = (cj_t *) malloc (sizeof (*db));
+  if (db == NULL)
+  {
+    ERROR ("curl_json plugin: malloc failed.");
+    return (-1);
+  }
+  memset (db, 0, sizeof (*db));
+
+  db->timeout = -1;
+
+  if (strcasecmp ("URL", ci->key) == 0)
+    status = cf_util_get_string (ci, &db->url);
+  else if (strcasecmp ("Sock", ci->key) == 0)
+    status = cf_util_get_string (ci, &db->sock);
+  else
+  {
+    ERROR ("curl_json plugin: cj_config: "
+           "Invalid key: %s", ci->key);
+    return (-1);
+  }
+  if (status != 0)
+  {
+    sfree (db);
+    return (status);
+  }
+
+  /* Fill the `cj_t' structure.. */
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Instance", child->key) == 0)
+      status = cf_util_get_string (child, &db->instance);
+    else if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &db->host);
+    else if (db->url && strcasecmp ("User", child->key) == 0)
+      status = cf_util_get_string (child, &db->user);
+    else if (db->url && strcasecmp ("Password", child->key) == 0)
+      status = cf_util_get_string (child, &db->pass);
+    else if (strcasecmp ("Digest", child->key) == 0)
+      status = cf_util_get_boolean (child, &db->digest);
+    else if (db->url && strcasecmp ("VerifyPeer", child->key) == 0)
+      status = cf_util_get_boolean (child, &db->verify_peer);
+    else if (db->url && strcasecmp ("VerifyHost", child->key) == 0)
+      status = cf_util_get_boolean (child, &db->verify_host);
+    else if (db->url && strcasecmp ("CACert", child->key) == 0)
+      status = cf_util_get_string (child, &db->cacert);
+    else if (db->url && strcasecmp ("Header", child->key) == 0)
+      status = cj_config_append_string ("Header", &db->headers, child);
+    else if (db->url && strcasecmp ("Post", child->key) == 0)
+      status = cf_util_get_string (child, &db->post_body);
+    else if (strcasecmp ("Key", child->key) == 0)
+      status = cj_config_add_key (db, child);
+    else if (strcasecmp ("Interval", child->key) == 0)
+      status = cf_util_get_cdtime(child, &db->interval);
+    else if (strcasecmp ("Timeout", child->key) == 0)
+      status = cf_util_get_int (child, &db->timeout);
+    else
+    {
+      WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if (status == 0)
+  {
+    if (db->tree == NULL)
+    {
+      WARNING ("curl_json plugin: No (valid) `Key' block within `%s' \"`%s'\".",
+               db->url ? "URL" : "Sock", db->url ? db->url : db->sock);
+      status = -1;
+    }
+    if (status == 0 && db->url)
+      status = cj_init_curl (db);
+  }
+
+  /* If all went well, register this database for reading */
+  if (status == 0)
+  {
+    user_data_t ud;
+    char *cb_name;
+    struct timespec interval = { 0, 0 };
+
+    CDTIME_T_TO_TIMESPEC (db->interval, &interval);
+
+    if (db->instance == NULL)
+      db->instance = strdup("default");
+
+    DEBUG ("curl_json plugin: Registering new read callback: %s",
+           db->instance);
+
+    memset (&ud, 0, sizeof (ud));
+    ud.data = (void *) db;
+    ud.free_func = cj_free;
+
+    cb_name = ssnprintf_alloc ("curl_json-%s-%s",
+               db->instance, db->url ? db->url : db->sock);
+
+    plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
+                                  /* interval = */ (db->interval > 0) ? &interval : NULL,
+                                  &ud);
+    sfree (cb_name);
+  }
+  else
+  {
+    cj_free (db);
+    return (-1);
+  }
+
+  return (0);
+}
+ /* }}} int cj_config_add_database */
+
+static int cj_config (oconfig_item_t *ci) /* {{{ */
+{
+  int success;
+  int errors;
+  int status;
+  int i;
+
+  success = 0;
+  errors = 0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Sock", child->key) == 0
+        || strcasecmp ("URL", child->key) == 0)
+    {
+      status = cj_config_add_url (child);
+      if (status == 0)
+        success++;
+      else
+        errors++;
+    }
+    else
+    {
+      WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
+      errors++;
+    }
+  }
+
+  if ((success == 0) && (errors > 0))
+  {
+    ERROR ("curl_json plugin: All statements failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cj_config */
+
+/* }}} End of configuration handling functions */
+
+static void cj_submit (cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
+{
+  value_list_t vl = VALUE_LIST_INIT;
+  char *host;
+
+  vl.values     = value;
+  vl.values_len = 1;
+
+  if ((db->host == NULL)
+      || (strcmp ("", db->host) == 0)
+      || (strcmp (CJ_DEFAULT_HOST, db->host) == 0))
+    host = hostname_g;
+  else
+    host = db->host;
+
+  if (key->instance == NULL)
+  {
+    int i, len = 0;
+    for (i = 0; i < db->depth; i++)
+      len += ssnprintf(vl.type_instance+len, sizeof(vl.type_instance)-len,
+                       i ? "-%s" : "%s", db->state[i+1].name);
+  }
+  else
+    sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
+
+  sstrncpy (vl.host, host, sizeof (vl.host));
+  sstrncpy (vl.plugin, "curl_json", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, key->type, sizeof (vl.type));
+
+  if (db->interval > 0)
+    vl.interval = db->interval;
+
+  plugin_dispatch_values (&vl);
+} /* }}} int cj_submit */
+
+static int cj_sock_perform (cj_t *db) /* {{{ */
+{
+  char errbuf[1024];
+  struct sockaddr_un sa_unix = {};
+  sa_unix.sun_family = AF_UNIX;
+  sstrncpy (sa_unix.sun_path, db->sock, sizeof (sa_unix.sun_path));
+
+  int fd = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (fd < 0)
+    return (-1);
+  if (connect (fd, (struct sockaddr *)&sa_unix, sizeof(sa_unix)) < 0)
+  {
+    ERROR ("curl_json plugin: connect(%s) failed: %s",
+           (db->sock != NULL) ? db->sock : "<null>",
+           sstrerror(errno, errbuf, sizeof (errbuf)));
+    close (fd);
+    return (-1);
+  }
+
+  ssize_t red;
+  do {
+    unsigned char buffer[4096];
+    red = read (fd, buffer, sizeof(buffer));
+    if (red < 0) {
+        ERROR ("curl_json plugin: read(%s) failed: %s",
+               (db->sock != NULL) ? db->sock : "<null>",
+               sstrerror(errno, errbuf, sizeof (errbuf)));
+        close (fd);
+        return (-1);
+    }
+    if (!cj_curl_callback (buffer, red, 1, db))
+        break;
+  } while (red > 0);
+  close (fd);
+  return (0);
+} /* }}} int cj_sock_perform */
+
+
+static int cj_curl_perform(cj_t *db) /* {{{ */
+{
+  int status;
+  long rc;
+  char *url;
+  url = db->url;
+
+  status = curl_easy_perform (db->curl);
+  if (status != CURLE_OK)
+  {
+    ERROR ("curl_json plugin: curl_easy_perform failed with status %i: %s (%s)",
+           status, db->curl_errbuf, url);
+    return (-1);
+  }
+
+  curl_easy_getinfo(db->curl, CURLINFO_EFFECTIVE_URL, &url);
+  curl_easy_getinfo(db->curl, CURLINFO_RESPONSE_CODE, &rc);
+
+  /* The response code is zero if a non-HTTP transport was used. */
+  if ((rc != 0) && (rc != 200))
+  {
+    ERROR ("curl_json plugin: curl_easy_perform failed with "
+        "response code %ld (%s)", rc, url);
+    return (-1);
+  }
+  return (0);
+} /* }}} int cj_curl_perform */
+
+static int cj_perform (cj_t *db) /* {{{ */
+{
+  int status;
+  yajl_handle yprev = db->yajl;
+
+  db->yajl = yajl_alloc (&ycallbacks,
+#if HAVE_YAJL_V2
+      /* alloc funcs = */ NULL,
+#else
+      /* alloc funcs = */ NULL, NULL,
+#endif
+      /* context = */ (void *)db);
+  if (db->yajl == NULL)
+  {
+    ERROR ("curl_json plugin: yajl_alloc failed.");
+    db->yajl = yprev;
+    return (-1);
+  }
+
+  if (db->url)
+    status = cj_curl_perform (db);
+  else
+    status = cj_sock_perform (db);
+  if (status < 0)
+  {
+    yajl_free (db->yajl);
+    db->yajl = yprev;
+    return (-1);
+  }
+
+#if HAVE_YAJL_V2
+    status = yajl_complete_parse(db->yajl);
+#else
+    status = yajl_parse_complete(db->yajl);
+#endif
+  if (status != yajl_status_ok)
+  {
+    unsigned char *errmsg;
+
+    errmsg = yajl_get_error (db->yajl, /* verbose = */ 0,
+        /* jsonText = */ NULL, /* jsonTextLen = */ 0);
+    ERROR ("curl_json plugin: yajl_parse_complete failed: %s",
+        (char *) errmsg);
+    yajl_free_error (db->yajl, errmsg);
+    yajl_free (db->yajl);
+    db->yajl = yprev;
+    return (-1);
+  }
+
+  yajl_free (db->yajl);
+  db->yajl = yprev;
+  return (0);
+} /* }}} int cj_perform */
+
+static int cj_read (user_data_t *ud) /* {{{ */
+{
+  cj_t *db;
+
+  if ((ud == NULL) || (ud->data == NULL))
+  {
+    ERROR ("curl_json plugin: cj_read: Invalid user data.");
+    return (-1);
+  }
+
+  db = (cj_t *) ud->data;
+
+  db->depth = 0;
+  memset (&db->state, 0, sizeof(db->state));
+  db->state[db->depth].tree = db->tree;
+  db->key = NULL;
+
+  return cj_perform (db);
+} /* }}} int cj_read */
+
+static int cj_init (void) /* {{{ */
+{
+  /* Call this while collectd is still single-threaded to avoid
+   * initialization issues in libgcrypt. */
+  curl_global_init (CURL_GLOBAL_SSL);
+  return (0);
+} /* }}} int cj_init */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("curl_json", cj_config);
+  plugin_register_init ("curl_json", cj_init);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/curl_xml.c b/src/curl_xml.c
new file mode 100644 (file)
index 0000000..689d5e1
--- /dev/null
@@ -0,0 +1,1084 @@
+/**
+ * collectd - src/curl_xml.c
+ * Copyright (C) 2009,2010       Amit Gupta
+ *
+ * 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:
+ *   Amit Gupta <amit.gupta221 at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_llist.h"
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <curl/curl.h>
+
+#define CX_DEFAULT_HOST "localhost"
+
+/*
+ * Private data structures
+ */
+struct cx_values_s /* {{{ */
+{
+  char path[DATA_MAX_NAME_LEN];
+  size_t path_len;
+};
+typedef struct cx_values_s cx_values_t;
+/* }}} */
+
+struct cx_xpath_s /* {{{ */
+{
+  char *path;
+  char *type;
+  cx_values_t *values;
+  int values_len;
+  char *instance_prefix;
+  char *instance;
+  int is_table;
+  unsigned long magic;
+};
+typedef struct cx_xpath_s cx_xpath_t;
+/* }}} */
+
+struct cx_namespace_s /* {{{ */
+{
+  char *prefix;
+  char *url;
+};
+typedef struct cx_namespace_s cx_namespace_t;
+/* }}} */
+
+struct cx_s /* {{{ */
+{
+  char *instance;
+  char *host;
+
+  char *url;
+  char *user;
+  char *pass;
+  char *credentials;
+  _Bool digest;
+  _Bool verify_peer;
+  _Bool verify_host;
+  char *cacert;
+  char *post_body;
+  int timeout;
+  struct curl_slist *headers;
+
+  cx_namespace_t *namespaces;
+  size_t namespaces_num;
+
+  CURL *curl;
+  char curl_errbuf[CURL_ERROR_SIZE];
+  char *buffer;
+  size_t buffer_size;
+  size_t buffer_fill;
+
+  llist_t *list; /* list of xpath blocks */
+};
+typedef struct cx_s cx_t; /* }}} */
+
+/*
+ * Private functions
+ */
+static size_t cx_curl_callback (void *buf, /* {{{ */
+    size_t size, size_t nmemb, void *user_data)
+{
+  size_t len = size * nmemb;
+  cx_t *db;
+
+  db = user_data;
+  if (db == NULL)
+  {
+    ERROR ("curl_xml plugin: cx_curl_callback: "
+           "user_data pointer is NULL.");
+    return (0);
+  }
+
+   if (len <= 0)
+    return (len);
+
+  if ((db->buffer_fill + len) >= db->buffer_size)
+  {
+    char *temp;
+
+    temp = (char *) realloc (db->buffer,
+                    db->buffer_fill + len + 1);
+    if (temp == NULL)
+    {
+      ERROR ("curl_xml plugin: realloc failed.");
+      return (0);
+    }
+    db->buffer = temp;
+    db->buffer_size = db->buffer_fill + len + 1;
+  }
+
+  memcpy (db->buffer + db->buffer_fill, (char *) buf, len);
+  db->buffer_fill += len;
+  db->buffer[db->buffer_fill] = 0;
+
+  return (len);
+} /* }}} size_t cx_curl_callback */
+
+static void cx_xpath_free (cx_xpath_t *xpath) /* {{{ */
+{
+  if (xpath == NULL)
+    return;
+
+  sfree (xpath->path);
+  sfree (xpath->type);
+  sfree (xpath->instance_prefix);
+  sfree (xpath->instance);
+  sfree (xpath->values);
+  sfree (xpath);
+} /* }}} void cx_xpath_free */
+
+static void cx_list_free (llist_t *list) /* {{{ */
+{
+  llentry_t *le;
+
+  le = llist_head (list);
+  while (le != NULL)
+  {
+    llentry_t *le_next;
+
+    le_next = le->next;
+
+    sfree (le->key);
+    cx_xpath_free (le->value);
+
+    le = le_next;
+  }
+
+  llist_destroy (list);
+  list = NULL;
+} /* }}} void cx_list_free */
+
+static void cx_free (void *arg) /* {{{ */
+{
+  cx_t *db;
+  size_t i;
+
+  DEBUG ("curl_xml plugin: cx_free (arg = %p);", arg);
+
+  db = (cx_t *) arg;
+
+  if (db == NULL)
+    return;
+
+  if (db->curl != NULL)
+    curl_easy_cleanup (db->curl);
+  db->curl = NULL;
+
+  if (db->list != NULL)
+    cx_list_free (db->list);
+
+  sfree (db->buffer);
+  sfree (db->instance);
+  sfree (db->host);
+
+  sfree (db->url);
+  sfree (db->user);
+  sfree (db->pass);
+  sfree (db->credentials);
+  sfree (db->cacert);
+  sfree (db->post_body);
+  curl_slist_free_all (db->headers);
+
+  for (i = 0; i < db->namespaces_num; i++)
+  {
+    sfree (db->namespaces[i].prefix);
+    sfree (db->namespaces[i].url);
+  }
+  sfree (db->namespaces);
+
+  sfree (db);
+} /* }}} void cx_free */
+
+static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl_xml plugin: `%s' needs exactly one string argument.", name);
+    return (-1);
+  }
+
+  *dest = curl_slist_append(*dest, ci->values[0].value.string);
+  if (*dest == NULL)
+    return (-1);
+
+  return (0);
+} /* }}} int cx_config_append_string */
+
+static int cx_check_type (const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */
+{
+  if (!ds)
+  {
+    WARNING ("curl_xml plugin: DataSet `%s' not defined.", xpath->type);
+    return (-1);
+  }
+
+  if (ds->ds_num != xpath->values_len)
+  {
+    WARNING ("curl_xml plugin: DataSet `%s' requires %i values, but config talks about %i",
+        xpath->type, ds->ds_num, xpath->values_len);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} cx_check_type */
+
+static xmlXPathObjectPtr cx_evaluate_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ 
+           xmlChar *expr)
+{
+  xmlXPathObjectPtr xpath_obj;
+
+  /* XXX: When to free this? */
+  xpath_obj = xmlXPathEvalExpression(BAD_CAST expr, xpath_ctx);
+  if (xpath_obj == NULL)
+  {
+     WARNING ("curl_xml plugin: "
+               "Error unable to evaluate xpath expression \"%s\". Skipping...", expr);
+     return NULL;
+  }
+
+  return xpath_obj;
+} /* }}} cx_evaluate_xpath */
+
+static int cx_if_not_text_node (xmlNodePtr node) /* {{{ */
+{
+  if (node->type == XML_TEXT_NODE || node->type == XML_ATTRIBUTE_NODE ||
+      node->type == XML_ELEMENT_NODE)
+    return (0);
+
+  WARNING ("curl_xml plugin: "
+           "Node \"%s\" doesn't seem to be a text node. Skipping...", node->name);
+  return -1;
+} /* }}} cx_if_not_text_node */
+
+static int cx_handle_single_value_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
+    cx_xpath_t *xpath,
+    const data_set_t *ds, value_list_t *vl, int index)
+{
+  xmlXPathObjectPtr values_node_obj;
+  xmlNodeSetPtr values_node;
+  int tmp_size;
+  char *node_value;
+
+  values_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST xpath->values[index].path);
+  if (values_node_obj == NULL)
+    return (-1); /* Error already logged. */
+
+  values_node = values_node_obj->nodesetval;
+  tmp_size = (values_node) ? values_node->nodeNr : 0;
+
+  if (tmp_size == 0)
+  {
+    WARNING ("curl_xml plugin: "
+        "relative xpath expression \"%s\" doesn't match any of the nodes. "
+        "Skipping...", xpath->values[index].path);
+    xmlXPathFreeObject (values_node_obj);
+    return (-1);
+  }
+
+  if (tmp_size > 1)
+  {
+    WARNING ("curl_xml plugin: "
+        "relative xpath expression \"%s\" is expected to return "
+        "only one node. Skipping...", xpath->values[index].path);
+    xmlXPathFreeObject (values_node_obj);
+    return (-1);
+  }
+
+  /* ignoring the element if other than textnode/attribute*/
+  if (cx_if_not_text_node(values_node->nodeTab[0]))
+  {
+    WARNING ("curl_xml plugin: "
+        "relative xpath expression \"%s\" is expected to return "
+        "only text/attribute node which is not the case. Skipping...", 
+        xpath->values[index].path);
+    xmlXPathFreeObject (values_node_obj);
+    return (-1);
+  }
+
+  node_value = (char *) xmlNodeGetContent(values_node->nodeTab[0]);
+  switch (ds->ds[index].type)
+  {
+    case DS_TYPE_COUNTER:
+      vl->values[index].counter = (counter_t) strtoull (node_value,
+          /* endptr = */ NULL, /* base = */ 0);
+      break;
+    case DS_TYPE_DERIVE:
+      vl->values[index].derive = (derive_t) strtoll (node_value,
+          /* endptr = */ NULL, /* base = */ 0);
+      break;
+    case DS_TYPE_ABSOLUTE:
+      vl->values[index].absolute = (absolute_t) strtoull (node_value,
+          /* endptr = */ NULL, /* base = */ 0);
+      break;
+    case DS_TYPE_GAUGE: 
+      vl->values[index].gauge = (gauge_t) strtod (node_value,
+          /* endptr = */ NULL);
+  }
+
+  /* free up object */
+  xmlXPathFreeObject (values_node_obj);
+  sfree (node_value);
+
+  /* We have reached here which means that
+   * we have got something to work */
+  return (0);
+} /* }}} int cx_handle_single_value_xpath */
+
+static int cx_handle_all_value_xpaths (xmlXPathContextPtr xpath_ctx, /* {{{ */
+    cx_xpath_t *xpath,
+    const data_set_t *ds, value_list_t *vl)
+{
+  value_t values[xpath->values_len];
+  int status;
+  int i;
+
+  assert (xpath->values_len > 0);
+  assert (xpath->values_len == vl->values_len);
+  assert (xpath->values_len == ds->ds_num);
+  vl->values = values;
+
+  for (i = 0; i < xpath->values_len; i++)
+  {
+    status = cx_handle_single_value_xpath (xpath_ctx, xpath, ds, vl, i);
+    if (status != 0)
+      return (-1); /* An error has been printed. */
+  } /* for (i = 0; i < xpath->values_len; i++) */
+
+  plugin_dispatch_values (vl);
+  vl->values = NULL;
+
+  return (0);
+} /* }}} int cx_handle_all_value_xpaths */
+
+static int cx_handle_instance_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */
+    cx_xpath_t *xpath, value_list_t *vl,
+    _Bool is_table)
+{
+  xmlXPathObjectPtr instance_node_obj = NULL;
+  xmlNodeSetPtr instance_node = NULL;
+
+  memset (vl->type_instance, 0, sizeof (vl->type_instance));
+
+  /* If the base xpath returns more than one block, the result is assumed to be
+   * a table. The `Instance' option is not optional in this case. Check for the
+   * condition and inform the user. */
+  if (is_table && (xpath->instance == NULL))
+  {
+    WARNING ("curl_xml plugin: "
+        "Base-XPath %s is a table (more than one result was returned), "
+        "but no instance-XPath has been defined.",
+        xpath->path);
+    return (-1);
+  }
+
+  /* instance has to be an xpath expression */
+  if (xpath->instance != NULL)
+  {
+    int tmp_size;
+
+    instance_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST xpath->instance);
+    if (instance_node_obj == NULL)
+      return (-1); /* error is logged already */
+
+    instance_node = instance_node_obj->nodesetval;
+    tmp_size = (instance_node) ? instance_node->nodeNr : 0;
+
+    if (tmp_size <= 0)
+    {
+      WARNING ("curl_xml plugin: "
+          "relative xpath expression for 'InstanceFrom' \"%s\" doesn't match "
+          "any of the nodes. Skipping the node.", xpath->instance);
+      xmlXPathFreeObject (instance_node_obj);
+      return (-1);
+    }
+
+    if (tmp_size > 1)
+    {
+      WARNING ("curl_xml plugin: "
+          "relative xpath expression for 'InstanceFrom' \"%s\" is expected "
+          "to return only one text node. Skipping the node.", xpath->instance);
+      xmlXPathFreeObject (instance_node_obj);
+      return (-1);
+    }
+
+    /* ignoring the element if other than textnode/attribute */
+    if (cx_if_not_text_node(instance_node->nodeTab[0]))
+    {
+      WARNING ("curl_xml plugin: "
+          "relative xpath expression \"%s\" is expected to return only text node "
+          "which is not the case. Skipping the node.", xpath->instance);
+      xmlXPathFreeObject (instance_node_obj);
+      return (-1);
+    }
+  } /* if (xpath->instance != NULL) */
+
+  if (xpath->instance_prefix != NULL)
+  {
+    if (instance_node != NULL)
+    {
+      char *node_value = (char *) xmlNodeGetContent(instance_node->nodeTab[0]);
+      ssnprintf (vl->type_instance, sizeof (vl->type_instance),"%s%s",
+          xpath->instance_prefix, node_value);
+      sfree (node_value);
+    }
+    else
+      sstrncpy (vl->type_instance, xpath->instance_prefix,
+          sizeof (vl->type_instance));
+  }
+  else
+  {
+    /* If instance_prefix and instance_node are NULL, then
+     * don't set the type_instance */
+    if (instance_node != NULL)
+    {
+      char *node_value = (char *) xmlNodeGetContent(instance_node->nodeTab[0]);
+      sstrncpy (vl->type_instance, node_value, sizeof (vl->type_instance));
+      sfree (node_value);
+    }
+  }
+
+  /* Free `instance_node_obj' this late, because `instance_node' points to
+   * somewhere inside this structure. */
+  xmlXPathFreeObject (instance_node_obj);
+
+  return (0);
+} /* }}} int cx_handle_instance_xpath */
+
+static int  cx_handle_base_xpath (char const *plugin_instance, /* {{{ */
+    char const *host,
+    xmlXPathContextPtr xpath_ctx, const data_set_t *ds, 
+    char *base_xpath, cx_xpath_t *xpath)
+{
+  int total_nodes;
+  int i;
+
+  xmlXPathObjectPtr base_node_obj = NULL;
+  xmlNodeSetPtr base_nodes = NULL;
+
+  value_list_t vl = VALUE_LIST_INIT;
+
+  base_node_obj = cx_evaluate_xpath (xpath_ctx, BAD_CAST base_xpath); 
+  if (base_node_obj == NULL)
+    return -1; /* error is logged already */
+
+  base_nodes = base_node_obj->nodesetval;
+  total_nodes = (base_nodes) ? base_nodes->nodeNr : 0;
+
+  if (total_nodes == 0)
+  {
+     ERROR ("curl_xml plugin: "
+              "xpath expression \"%s\" doesn't match any of the nodes. "
+              "Skipping the xpath block...", base_xpath);
+     xmlXPathFreeObject (base_node_obj);
+     return -1;
+  }
+
+  /* If base_xpath returned multiple results, then */
+  /* Instance in the xpath block is required */ 
+  if (total_nodes > 1 && xpath->instance == NULL)
+  {
+    ERROR ("curl_xml plugin: "
+             "InstanceFrom is must in xpath block since the base xpath expression \"%s\" "
+             "returned multiple results. Skipping the xpath block...", base_xpath);
+    return -1;
+  }
+
+  /* set the values for the value_list */
+  vl.values_len = ds->ds_num;
+  sstrncpy (vl.type, xpath->type, sizeof (vl.type));
+  sstrncpy (vl.plugin, "curl_xml", sizeof (vl.plugin));
+  sstrncpy (vl.host, (host != NULL) ? host : hostname_g, sizeof (vl.host));
+  if (plugin_instance != NULL)
+    sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); 
+
+  for (i = 0; i < total_nodes; i++)
+  {
+    int status;
+
+    xpath_ctx->node = base_nodes->nodeTab[i];
+
+    status = cx_handle_instance_xpath (xpath_ctx, xpath, &vl,
+        /* is_table = */ (total_nodes > 1));
+    if (status != 0)
+      continue; /* An error has already been reported. */
+
+    status = cx_handle_all_value_xpaths (xpath_ctx, xpath, ds, &vl);
+    if (status != 0)
+      continue; /* An error has been logged. */
+  } /* for (i = 0; i < total_nodes; i++) */
+
+  /* free up the allocated memory */
+  xmlXPathFreeObject (base_node_obj); 
+
+  return (0); 
+} /* }}} cx_handle_base_xpath */
+
+static int cx_handle_parsed_xml(xmlDocPtr doc, /* {{{ */ 
+                       xmlXPathContextPtr xpath_ctx, cx_t *db)
+{
+  llentry_t *le;
+  const data_set_t *ds;
+  cx_xpath_t *xpath;
+  int status=-1;
+  
+
+  le = llist_head (db->list);
+  while (le != NULL)
+  {
+    /* get the ds */
+    xpath = (cx_xpath_t *) le->value;
+    ds = plugin_get_ds (xpath->type);
+
+    if ( (cx_check_type(ds, xpath) == 0) &&
+         (cx_handle_base_xpath(db->instance, db->host,
+                               xpath_ctx, ds, le->key, xpath) == 0) )
+      status = 0; /* we got atleast one success */
+
+    le = le->next;
+  } /* while (le != NULL) */
+
+  return status;
+} /* }}} cx_handle_parsed_xml */
+
+static int cx_parse_stats_xml(xmlChar* xml, cx_t *db) /* {{{ */
+{
+  int status;
+  xmlDocPtr doc;
+  xmlXPathContextPtr xpath_ctx;
+  size_t i;
+
+  /* Load the XML */
+  doc = xmlParseDoc(xml);
+  if (doc == NULL)
+  {
+    ERROR ("curl_xml plugin: Failed to parse the xml document  - %s", xml);
+    return (-1);
+  }
+
+  xpath_ctx = xmlXPathNewContext(doc);
+  if(xpath_ctx == NULL)
+  {
+    ERROR ("curl_xml plugin: Failed to create the xml context");
+    xmlFreeDoc(doc);
+    return (-1);
+  }
+
+  for (i = 0; i < db->namespaces_num; i++)
+  {
+    cx_namespace_t const *ns = db->namespaces + i;
+    status = xmlXPathRegisterNs (xpath_ctx,
+        BAD_CAST ns->prefix, BAD_CAST ns->url);
+    if (status != 0)
+    {
+      ERROR ("curl_xml plugin: "
+          "unable to register NS with prefix=\"%s\" and href=\"%s\"\n",
+          ns->prefix, ns->url);
+      xmlXPathFreeContext(xpath_ctx);
+      xmlFreeDoc (doc);
+      return (status);
+    }
+  }
+
+  status = cx_handle_parsed_xml (doc, xpath_ctx, db);
+  /* Cleanup */
+  xmlXPathFreeContext(xpath_ctx);
+  xmlFreeDoc(doc);
+  return status;
+} /* }}} cx_parse_stats_xml */
+
+static int cx_curl_perform (cx_t *db, CURL *curl) /* {{{ */
+{
+  int status;
+  long rc;
+  char *ptr;
+  char *url;
+  url = db->url;
+
+  db->buffer_fill = 0; 
+  status = curl_easy_perform (curl);
+  if (status != CURLE_OK)
+  {
+    ERROR ("curl_xml plugin: curl_easy_perform failed with status %i: %s (%s)",
+           status, db->curl_errbuf, url);
+    return (-1);
+  }
+
+  curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
+  curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
+
+  /* The response code is zero if a non-HTTP transport was used. */
+  if ((rc != 0) && (rc != 200))
+  {
+    ERROR ("curl_xml plugin: curl_easy_perform failed with response code %ld (%s)",
+           rc, url);
+    return (-1);
+  }
+
+  ptr = db->buffer;
+
+  status = cx_parse_stats_xml(BAD_CAST ptr, db);
+  db->buffer_fill = 0;
+
+  return status;
+} /* }}} int cx_curl_perform */
+
+static int cx_read (user_data_t *ud) /* {{{ */
+{
+  cx_t *db;
+
+  if ((ud == NULL) || (ud->data == NULL))
+  {
+    ERROR ("curl_xml plugin: cx_read: Invalid user data.");
+    return (-1);
+  }
+
+  db = (cx_t *) ud->data;
+
+  return cx_curl_perform (db, db->curl);
+} /* }}} int cx_read */
+
+/* Configuration handling functions {{{ */
+
+static int cx_config_add_values (const char *name, cx_xpath_t *xpath, /* {{{ */
+                                      oconfig_item_t *ci)
+{
+  int i;
+
+  if (ci->values_num < 1)
+  {
+    WARNING ("curl_xml plugin: `ValuesFrom' needs at least one argument.");
+    return (-1);
+  }
+
+  for (i = 0; i < ci->values_num; i++)
+    if (ci->values[i].type != OCONFIG_TYPE_STRING)
+    {
+      WARNING ("curl_xml plugin: `ValuesFrom' needs only string argument.");
+      return (-1);
+    }
+
+  sfree (xpath->values);
+
+  xpath->values_len = 0;
+  xpath->values = (cx_values_t *) malloc (sizeof (cx_values_t) * ci->values_num);
+  if (xpath->values == NULL)
+    return (-1);
+  xpath->values_len = ci->values_num;
+
+  /* populate cx_values_t structure */
+  for (i = 0; i < ci->values_num; i++)
+  {
+    xpath->values[i].path_len = sizeof (ci->values[i].value.string);
+    sstrncpy (xpath->values[i].path, ci->values[i].value.string, sizeof (xpath->values[i].path));
+  }
+
+  return (0); 
+} /* }}} cx_config_add_values */
+
+static int cx_config_add_xpath (cx_t *db, /* {{{ */
+                                   oconfig_item_t *ci)
+{
+  cx_xpath_t *xpath;
+  int status;
+  int i;
+
+  xpath = (cx_xpath_t *) malloc (sizeof (*xpath));
+  if (xpath == NULL)
+  {
+    ERROR ("curl_xml plugin: malloc failed.");
+    return (-1);
+  }
+  memset (xpath, 0, sizeof (*xpath));
+
+  status = cf_util_get_string (ci, &xpath->path);
+  if (status != 0)
+  {
+    sfree (xpath);
+    return (status);
+  }
+
+  /* error out if xpath->path is an empty string */
+  if (*xpath->path == 0)
+  {
+    ERROR ("curl_xml plugin: invalid xpath. "
+           "xpath value can't be an empty string");
+    return (-1);
+  }
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Type", child->key) == 0)
+      status = cf_util_get_string (child, &xpath->type);
+    else if (strcasecmp ("InstancePrefix", child->key) == 0)
+      status = cf_util_get_string (child, &xpath->instance_prefix);
+    else if (strcasecmp ("InstanceFrom", child->key) == 0)
+      status = cf_util_get_string (child, &xpath->instance);
+    else if (strcasecmp ("ValuesFrom", child->key) == 0)
+      status = cx_config_add_values ("ValuesFrom", xpath, child);
+    else
+    {
+      WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  if (status == 0 && xpath->type == NULL)
+  {
+    WARNING ("curl_xml plugin: `Type' missing in `xpath' block.");
+    status = -1;
+  }
+
+  if (status == 0)
+  {
+    char *name;
+    llentry_t *le;
+
+    if (db->list == NULL)
+    {
+      db->list = llist_create();
+      if (db->list == NULL)
+      {
+        ERROR ("curl_xml plugin: list creation failed.");
+        return (-1);
+      }
+    }
+
+    name = strdup(xpath->path);
+    if (name == NULL)
+    {
+        ERROR ("curl_xml plugin: strdup failed.");
+        return (-1);
+    }
+
+    le = llentry_create (name, xpath);
+    if (le == NULL)
+    {
+      ERROR ("curl_xml plugin: llentry_create failed.");
+      return (-1);
+    }
+
+    llist_append (db->list, le);
+  }
+
+  return (status);
+} /* }}} int cx_config_add_xpath */
+
+static int cx_config_add_namespace (cx_t *db, /* {{{ */
+    oconfig_item_t *ci)
+{
+  cx_namespace_t *ns;
+
+  if ((ci->values_num != 2)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || (ci->values[1].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl_xml plugin: The `Namespace' option "
+             "needs exactly two string arguments.");
+    return (EINVAL);
+  }
+
+  ns = realloc (db->namespaces, sizeof (*db->namespaces)
+      * (db->namespaces_num + 1));
+  if (ns == NULL)
+  {
+    ERROR ("curl_xml plugin: realloc failed.");
+    return (ENOMEM);
+  }
+  db->namespaces = ns;
+  ns = db->namespaces + db->namespaces_num;
+  memset (ns, 0, sizeof (*ns));
+
+  ns->prefix = strdup (ci->values[0].value.string);
+  ns->url = strdup (ci->values[1].value.string);
+
+  if ((ns->prefix == NULL) || (ns->url == NULL))
+  {
+    sfree (ns->prefix);
+    sfree (ns->url);
+    ERROR ("curl_xml plugin: strdup failed.");
+    return (ENOMEM);
+  }
+
+  db->namespaces_num++;
+  return (0);
+} /* }}} int cx_config_add_namespace */
+
+/* Initialize db->curl */
+static int cx_init_curl (cx_t *db) /* {{{ */
+{
+  db->curl = curl_easy_init ();
+  if (db->curl == NULL)
+  {
+    ERROR ("curl_xml plugin: curl_easy_init failed.");
+    return (-1);
+  }
+
+  curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1L);
+  curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cx_curl_callback);
+  curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
+  curl_easy_setopt (db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+  curl_easy_setopt (db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
+  curl_easy_setopt (db->curl, CURLOPT_URL, db->url);
+  curl_easy_setopt (db->curl, CURLOPT_FOLLOWLOCATION, 1L);
+  curl_easy_setopt (db->curl, CURLOPT_MAXREDIRS, 50L);
+
+  if (db->user != NULL)
+  {
+#ifdef HAVE_CURLOPT_USERNAME
+    curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
+    curl_easy_setopt (db->curl, CURLOPT_PASSWORD,
+        (db->pass == NULL) ? "" : db->pass);
+#else
+    size_t credentials_size;
+
+    credentials_size = strlen (db->user) + 2;
+    if (db->pass != NULL)
+      credentials_size += strlen (db->pass);
+
+    db->credentials = (char *) malloc (credentials_size);
+    if (db->credentials == NULL)
+    {
+      ERROR ("curl_xml plugin: malloc failed.");
+      return (-1);
+    }
+
+    ssnprintf (db->credentials, credentials_size, "%s:%s",
+               db->user, (db->pass == NULL) ? "" : db->pass);
+    curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
+#endif
+
+    if (db->digest)
+      curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+  }
+
+  curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, db->verify_peer ? 1L : 0L);
+  curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYHOST,
+                    db->verify_host ? 2L : 0L);
+  if (db->cacert != NULL)
+    curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
+  if (db->headers != NULL)
+    curl_easy_setopt (db->curl, CURLOPT_HTTPHEADER, db->headers);
+  if (db->post_body != NULL)
+    curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
+
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+  if (db->timeout >= 0)
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS, (long) db->timeout);
+  else
+    curl_easy_setopt (db->curl, CURLOPT_TIMEOUT_MS,
+       CDTIME_T_TO_MS(plugin_get_interval()));
+#endif
+
+  return (0);
+} /* }}} int cx_init_curl */
+
+static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */
+{
+  cx_t *db;
+  int status = 0;
+  int i;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("curl_xml plugin: The `URL' block "
+             "needs exactly one string argument.");
+    return (-1);
+  }
+
+  db = (cx_t *) malloc (sizeof (*db));
+  if (db == NULL)
+  {
+    ERROR ("curl_xml plugin: malloc failed.");
+    return (-1);
+  }
+  memset (db, 0, sizeof (*db));
+
+  db->timeout = -1;
+
+  if (strcasecmp ("URL", ci->key) == 0)
+  {
+    status = cf_util_get_string (ci, &db->url);
+    if (status != 0)
+    {
+      sfree (db);
+      return (status);
+    }
+  }
+  else
+  {
+    ERROR ("curl_xml plugin: cx_config: "
+           "Invalid key: %s", ci->key);
+    return (-1);
+  }
+
+  /* Fill the `cx_t' structure.. */
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Instance", child->key) == 0)
+      status = cf_util_get_string (child, &db->instance);
+    else if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &db->host);
+    else if (strcasecmp ("User", child->key) == 0)
+      status = cf_util_get_string (child, &db->user);
+    else if (strcasecmp ("Password", child->key) == 0)
+      status = cf_util_get_string (child, &db->pass);
+    else if (strcasecmp ("Digest", child->key) == 0)
+      status = cf_util_get_boolean (child, &db->digest);
+    else if (strcasecmp ("VerifyPeer", child->key) == 0)
+      status = cf_util_get_boolean (child, &db->verify_peer);
+    else if (strcasecmp ("VerifyHost", child->key) == 0)
+      status = cf_util_get_boolean (child, &db->verify_host);
+    else if (strcasecmp ("CACert", child->key) == 0)
+      status = cf_util_get_string (child, &db->cacert);
+    else if (strcasecmp ("xpath", child->key) == 0)
+      status = cx_config_add_xpath (db, child);
+    else if (strcasecmp ("Header", child->key) == 0)
+      status = cx_config_append_string ("Header", &db->headers, child);
+    else if (strcasecmp ("Post", child->key) == 0)
+      status = cf_util_get_string (child, &db->post_body);
+    else if (strcasecmp ("Namespace", child->key) == 0)
+      status = cx_config_add_namespace (db, child);
+    else if (strcasecmp ("Timeout", child->key) == 0)
+      status = cf_util_get_int (child, &db->timeout);
+    else
+    {
+      WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if (status == 0)
+  {
+    if (db->list == NULL)
+    {
+      WARNING ("curl_xml plugin: No (valid) `Key' block "
+               "within `URL' block `%s'.", db->url);
+      status = -1;
+    }
+    if (status == 0)
+      status = cx_init_curl (db);
+  }
+
+  /* If all went well, register this database for reading */
+  if (status == 0)
+  {
+    user_data_t ud;
+    char *cb_name;
+
+    if (db->instance == NULL)
+      db->instance = strdup("default");
+
+    DEBUG ("curl_xml plugin: Registering new read callback: %s",
+           db->instance);
+
+    memset (&ud, 0, sizeof (ud));
+    ud.data = (void *) db;
+    ud.free_func = cx_free;
+
+    cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
+    plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
+                                  /* interval = */ NULL, &ud);
+    sfree (cb_name);
+  }
+  else
+  {
+    cx_free (db);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cx_config_add_url */
+
+/* }}} End of configuration handling functions */
+
+static int cx_config (oconfig_item_t *ci) /* {{{ */
+{
+  int success;
+  int errors;
+  int status;
+  int i;
+
+  success = 0;
+  errors = 0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("URL", child->key) == 0)
+    {
+      status = cx_config_add_url (child);
+      if (status == 0)
+        success++;
+      else
+        errors++;
+    }
+    else
+    {
+      WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
+      errors++;
+    }
+  }
+
+  if ((success == 0) && (errors > 0))
+  {
+    ERROR ("curl_xml plugin: All statements failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cx_config */
+
+static int cx_init (void) /* {{{ */
+{
+  /* Call this while collectd is still single-threaded to avoid
+   * initialization issues in libgcrypt. */
+  curl_global_init (CURL_GLOBAL_SSL);
+  return (0);
+} /* }}} int cx_init */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("curl_xml", cx_config);
+  plugin_register_init ("curl_xml", cx_init);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
new file mode 100644 (file)
index 0000000..7f826e3
--- /dev/null
@@ -0,0 +1,104 @@
+if COMPILER_IS_GCC
+AM_CFLAGS = -Wall -Werror
+endif
+
+AM_CPPFLAGS = -I$(top_srcdir)/src
+AM_CPPFLAGS += -DPREFIX='"${prefix}"'
+AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
+AM_CPPFLAGS += -DLOCALSTATEDIR='"${localstatedir}"'
+AM_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
+if BUILD_FEATURE_DAEMON
+AM_CPPFLAGS += -DPIDFILE='"${localstatedir}/run/${PACKAGE_NAME}.pid"'
+endif
+AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
+AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+sbin_PROGRAMS = collectd
+
+noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libplugin_mock.la
+
+libavltree_la_SOURCES = utils_avltree.c utils_avltree.h
+
+libcommon_la_SOURCES = common.c common.h
+
+libheap_la_SOURCES = utils_heap.c utils_heap.h
+
+libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
+
+collectd_SOURCES = collectd.c collectd.h \
+                  configfile.c configfile.h \
+                  filter_chain.c filter_chain.h \
+                  meta_data.c meta_data.h \
+                  plugin.c plugin.h \
+                  utils_cache.c utils_cache.h \
+                  utils_complain.c utils_complain.h \
+                  utils_llist.c utils_llist.h \
+                  utils_random.c utils_random.h \
+                  utils_tail_match.c utils_tail_match.h \
+                  utils_match.c utils_match.h \
+                  utils_subst.c utils_subst.h \
+                  utils_tail.c utils_tail.h \
+                  utils_time.c utils_time.h \
+                  types_list.c types_list.h \
+                  utils_threshold.c utils_threshold.h
+
+
+collectd_CPPFLAGS =  $(AM_CPPFLAGS) $(LTDLINCL)
+collectd_CFLAGS = $(AM_CFLAGS)
+collectd_LDFLAGS = -export-dynamic
+collectd_LDADD = libavltree.la libcommon.la libheap.la -lm
+collectd_DEPENDENCIES =
+
+# Link to these libraries..
+if BUILD_WITH_LIBRT
+collectd_LDADD += -lrt
+endif
+if BUILD_WITH_LIBPOSIX4
+collectd_LDADD += -lposix4
+endif
+if BUILD_WITH_LIBSOCKET
+collectd_LDADD += -lsocket
+endif
+if BUILD_WITH_LIBRESOLV
+collectd_LDADD += -lresolv
+endif
+if BUILD_WITH_LIBPTHREAD
+collectd_LDADD += -lpthread
+endif
+if BUILD_WITH_LIBKSTAT
+collectd_LDADD += -lkstat
+endif
+if BUILD_WITH_LIBDEVINFO
+collectd_LDADD += -ldevinfo
+endif
+if BUILD_AIX
+collectd_LDFLAGS += -Wl,-bexpall,-brtllib
+endif
+
+# The daemon needs to call sg_init, so we need to link it against libstatgrab,
+# too. -octo
+if BUILD_WITH_LIBSTATGRAB
+collectd_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+collectd_LDADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+endif
+
+if BUILD_WITH_OWN_LIBOCONFIG
+collectd_LDADD += $(LIBLTDL) $(top_builddir)/src/liboconfig/liboconfig.la
+collectd_DEPENDENCIES += $(top_builddir)/src/liboconfig/liboconfig.la
+else
+collectd_LDADD += -loconfig
+endif
+
+check_PROGRAMS = test_common test_utils_avltree test_utils_heap
+TESTS = test_common test_utils_avltree test_utils_heap
+
+test_common_SOURCES = common_test.c ../testing.h
+test_common_LDADD = libcommon.la libplugin_mock.la
+
+test_utils_avltree_SOURCES = utils_avltree_test.c ../testing.h
+test_utils_avltree_LDADD = libavltree.la
+
+test_utils_heap_SOURCES = utils_heap_test.c ../testing.h
+test_utils_heap_LDADD = libheap.la
diff --git a/src/daemon/Makefile.in b/src/daemon/Makefile.in
new file mode 100644 (file)
index 0000000..fe887f9
--- /dev/null
@@ -0,0 +1,1565 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@BUILD_FEATURE_DAEMON_TRUE@am__append_1 = -DPIDFILE='"${localstatedir}/run/${PACKAGE_NAME}.pid"'
+sbin_PROGRAMS = collectd$(EXEEXT)
+
+# Link to these libraries..
+@BUILD_WITH_LIBRT_TRUE@am__append_2 = -lrt
+@BUILD_WITH_LIBPOSIX4_TRUE@am__append_3 = -lposix4
+@BUILD_WITH_LIBSOCKET_TRUE@am__append_4 = -lsocket
+@BUILD_WITH_LIBRESOLV_TRUE@am__append_5 = -lresolv
+@BUILD_WITH_LIBPTHREAD_TRUE@am__append_6 = -lpthread
+@BUILD_WITH_LIBKSTAT_TRUE@am__append_7 = -lkstat
+@BUILD_WITH_LIBDEVINFO_TRUE@am__append_8 = -ldevinfo
+@BUILD_AIX_TRUE@am__append_9 = -Wl,-bexpall,-brtllib
+
+# The daemon needs to call sg_init, so we need to link it against libstatgrab,
+# too. -octo
+@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_10 = $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
+@BUILD_WITH_LIBSTATGRAB_TRUE@am__append_11 = $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+@BUILD_WITH_OWN_LIBOCONFIG_TRUE@am__append_12 = $(LIBLTDL) $(top_builddir)/src/liboconfig/liboconfig.la
+@BUILD_WITH_OWN_LIBOCONFIG_TRUE@am__append_13 = $(top_builddir)/src/liboconfig/liboconfig.la
+@BUILD_WITH_OWN_LIBOCONFIG_FALSE@am__append_14 = -loconfig
+check_PROGRAMS = test_common$(EXEEXT) test_utils_avltree$(EXEEXT) \
+       test_utils_heap$(EXEEXT)
+TESTS = test_common$(EXEEXT) test_utils_avltree$(EXEEXT) \
+       test_utils_heap$(EXEEXT)
+subdir = src/daemon
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+       $(top_srcdir)/libltdl/config/depcomp \
+       $(top_srcdir)/libltdl/config/test-driver
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libavltree_la_LIBADD =
+am_libavltree_la_OBJECTS = utils_avltree.lo
+libavltree_la_OBJECTS = $(am_libavltree_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libcommon_la_LIBADD =
+am_libcommon_la_OBJECTS = common.lo
+libcommon_la_OBJECTS = $(am_libcommon_la_OBJECTS)
+libheap_la_LIBADD =
+am_libheap_la_OBJECTS = utils_heap.lo
+libheap_la_OBJECTS = $(am_libheap_la_OBJECTS)
+libplugin_mock_la_LIBADD =
+am_libplugin_mock_la_OBJECTS = plugin_mock.lo utils_cache_mock.lo \
+       utils_time_mock.lo
+libplugin_mock_la_OBJECTS = $(am_libplugin_mock_la_OBJECTS)
+am__installdirs = "$(DESTDIR)$(sbindir)"
+PROGRAMS = $(sbin_PROGRAMS)
+am_collectd_OBJECTS = collectd-collectd.$(OBJEXT) \
+       collectd-configfile.$(OBJEXT) collectd-filter_chain.$(OBJEXT) \
+       collectd-meta_data.$(OBJEXT) collectd-plugin.$(OBJEXT) \
+       collectd-utils_cache.$(OBJEXT) \
+       collectd-utils_complain.$(OBJEXT) \
+       collectd-utils_llist.$(OBJEXT) collectd-utils_random.$(OBJEXT) \
+       collectd-utils_tail_match.$(OBJEXT) \
+       collectd-utils_match.$(OBJEXT) collectd-utils_subst.$(OBJEXT) \
+       collectd-utils_tail.$(OBJEXT) collectd-utils_time.$(OBJEXT) \
+       collectd-types_list.$(OBJEXT) \
+       collectd-utils_threshold.$(OBJEXT)
+collectd_OBJECTS = $(am_collectd_OBJECTS)
+am__DEPENDENCIES_1 =
+@BUILD_WITH_LIBSTATGRAB_TRUE@am__DEPENDENCIES_2 =  \
+@BUILD_WITH_LIBSTATGRAB_TRUE@  $(am__DEPENDENCIES_1)
+@BUILD_WITH_OWN_LIBOCONFIG_TRUE@am__DEPENDENCIES_3 =  \
+@BUILD_WITH_OWN_LIBOCONFIG_TRUE@       $(am__DEPENDENCIES_1) \
+@BUILD_WITH_OWN_LIBOCONFIG_TRUE@       $(top_builddir)/src/liboconfig/liboconfig.la
+collectd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(collectd_CFLAGS) \
+       $(CFLAGS) $(collectd_LDFLAGS) $(LDFLAGS) -o $@
+am_test_common_OBJECTS = common_test.$(OBJEXT)
+test_common_OBJECTS = $(am_test_common_OBJECTS)
+test_common_DEPENDENCIES = libcommon.la libplugin_mock.la
+am_test_utils_avltree_OBJECTS = utils_avltree_test.$(OBJEXT)
+test_utils_avltree_OBJECTS = $(am_test_utils_avltree_OBJECTS)
+test_utils_avltree_DEPENDENCIES = libavltree.la
+am_test_utils_heap_OBJECTS = utils_heap_test.$(OBJEXT)
+test_utils_heap_OBJECTS = $(am_test_utils_heap_OBJECTS)
+test_utils_heap_DEPENDENCIES = libheap.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/libltdl/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libavltree_la_SOURCES) $(libcommon_la_SOURCES) \
+       $(libheap_la_SOURCES) $(libplugin_mock_la_SOURCES) \
+       $(collectd_SOURCES) $(test_common_SOURCES) \
+       $(test_utils_avltree_SOURCES) $(test_utils_heap_SOURCES)
+DIST_SOURCES = $(libavltree_la_SOURCES) $(libcommon_la_SOURCES) \
+       $(libheap_la_SOURCES) $(libplugin_mock_la_SOURCES) \
+       $(collectd_SOURCES) $(test_common_SOURCES) \
+       $(test_utils_avltree_SOURCES) $(test_utils_heap_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+  mgn= red= grn= lgn= blu= brg= std=; \
+  am__color_tests=no
+am__tty_colors = { \
+  $(am__tty_colors_dummy); \
+  if test "X$(AM_COLOR_TESTS)" = Xno; then \
+    am__color_tests=no; \
+  elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+    am__color_tests=yes; \
+  elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+    am__color_tests=yes; \
+  fi; \
+  if test $$am__color_tests = yes; then \
+    red='\e[0;31m'; \
+    grn='\e[0;32m'; \
+    lgn='\e[1;32m'; \
+    blu='\e[1;34m'; \
+    mgn='\e[0;35m'; \
+    brg='\e[1m'; \
+    std='\e[m'; \
+  fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__recheck_rx = ^[    ]*:recheck:[    ]*
+am__global_test_result_rx = ^[         ]*:global-test-result:[         ]*
+am__copy_in_global_log_rx = ^[         ]*:copy-in-global-log:[         ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+  recheck = 1; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+        { \
+          if ((getline line2 < ($$0 ".log")) < 0) \
+           recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+        { \
+          recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+        { \
+          break; \
+        } \
+    }; \
+  if (recheck) \
+    print $$0; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+  print "fatal: making $@: " msg | "cat >&2"; \
+  exit 1; \
+} \
+function rst_section(header) \
+{ \
+  print header; \
+  len = length(header); \
+  for (i = 1; i <= len; i = i + 1) \
+    printf "="; \
+  printf "\n\n"; \
+} \
+{ \
+  copy_in_global_log = 1; \
+  global_test_result = "RUN"; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+         fatal("failed to read from " $$0 ".trs"); \
+      if (line ~ /$(am__global_test_result_rx)/) \
+        { \
+          sub("$(am__global_test_result_rx)", "", line); \
+          sub("[       ]*$$", "", line); \
+          global_test_result = line; \
+        } \
+      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+        copy_in_global_log = 0; \
+    }; \
+  if (copy_in_global_log) \
+    { \
+      rst_section(global_test_result ": " $$0); \
+      while ((rc = (getline line < ($$0 ".log"))) != 0) \
+      { \
+        if (rc < 0) \
+          fatal("failed to read from " $$0 ".log"); \
+        print line; \
+      }; \
+      printf "\n"; \
+    }; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this.  Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test.  Creates the
+# directory for the log if needed.  Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log.  Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup);                                     \
+$(am__vpath_adj_setup) $(am__vpath_adj)                        \
+$(am__tty_colors);                                     \
+srcdir=$(srcdir); export srcdir;                       \
+case "$@" in                                           \
+  */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;;   \
+    *) am__odir=.;;                                    \
+esac;                                                  \
+test "x$$am__odir" = x"." || test -d "$$am__odir"      \
+  || $(MKDIR_P) "$$am__odir" || exit $$?;              \
+if test -f "./$$f"; then dir=./;                       \
+elif test -f "$$f"; then dir=;                         \
+else dir="$(srcdir)/"; fi;                             \
+tst=$$dir$$f; log='$@';                                \
+if test -n '$(DISABLE_HARD_ERRORS)'; then              \
+  am__enable_hard_errors=no;                           \
+else                                                   \
+  am__enable_hard_errors=yes;                          \
+fi;                                                    \
+case " $(XFAIL_TESTS) " in                             \
+  *[\ \        ]$$f[\ \        ]* | *[\ \      ]$$dir$$f[\ \   ]*) \
+    am__expect_failure=yes;;                           \
+  *)                                                   \
+    am__expect_failure=no;;                            \
+esac;                                                  \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed).  The result is saved in the shell variable
+# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/libltdl/config/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/libltdl/config/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+       $(TEST_LOG_FLAGS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_WITH_LIBAQUAERO5_CFLAGS = @BUILD_WITH_LIBAQUAERO5_CFLAGS@
+BUILD_WITH_LIBAQUAERO5_LDFLAGS = @BUILD_WITH_LIBAQUAERO5_LDFLAGS@
+BUILD_WITH_LIBATASMART_CPPFLAGS = @BUILD_WITH_LIBATASMART_CPPFLAGS@
+BUILD_WITH_LIBATASMART_LDFLAGS = @BUILD_WITH_LIBATASMART_LDFLAGS@
+BUILD_WITH_LIBATASMART_LIBS = @BUILD_WITH_LIBATASMART_LIBS@
+BUILD_WITH_LIBCURL_CFLAGS = @BUILD_WITH_LIBCURL_CFLAGS@
+BUILD_WITH_LIBCURL_LIBS = @BUILD_WITH_LIBCURL_LIBS@
+BUILD_WITH_LIBDBI_CPPFLAGS = @BUILD_WITH_LIBDBI_CPPFLAGS@
+BUILD_WITH_LIBDBI_LDFLAGS = @BUILD_WITH_LIBDBI_LDFLAGS@
+BUILD_WITH_LIBDBI_LIBS = @BUILD_WITH_LIBDBI_LIBS@
+BUILD_WITH_LIBHAL_CFLAGS = @BUILD_WITH_LIBHAL_CFLAGS@
+BUILD_WITH_LIBHAL_LIBS = @BUILD_WITH_LIBHAL_LIBS@
+BUILD_WITH_LIBHIREDIS_CPPFLAGS = @BUILD_WITH_LIBHIREDIS_CPPFLAGS@
+BUILD_WITH_LIBHIREDIS_LDFLAGS = @BUILD_WITH_LIBHIREDIS_LDFLAGS@
+BUILD_WITH_LIBIPTC_CPPFLAGS = @BUILD_WITH_LIBIPTC_CPPFLAGS@
+BUILD_WITH_LIBIPTC_LDFLAGS = @BUILD_WITH_LIBIPTC_LDFLAGS@
+BUILD_WITH_LIBLDAP_CPPFLAGS = @BUILD_WITH_LIBLDAP_CPPFLAGS@
+BUILD_WITH_LIBLDAP_LDFLAGS = @BUILD_WITH_LIBLDAP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_CPPFLAGS = @BUILD_WITH_LIBLVM2APP_CPPFLAGS@
+BUILD_WITH_LIBLVM2APP_LDFLAGS = @BUILD_WITH_LIBLVM2APP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_LIBS = @BUILD_WITH_LIBLVM2APP_LIBS@
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS = @BUILD_WITH_LIBMEMCACHED_CPPFLAGS@
+BUILD_WITH_LIBMEMCACHED_LDFLAGS = @BUILD_WITH_LIBMEMCACHED_LDFLAGS@
+BUILD_WITH_LIBMEMCACHED_LIBS = @BUILD_WITH_LIBMEMCACHED_LIBS@
+BUILD_WITH_LIBMNL_CFLAGS = @BUILD_WITH_LIBMNL_CFLAGS@
+BUILD_WITH_LIBMNL_LIBS = @BUILD_WITH_LIBMNL_LIBS@
+BUILD_WITH_LIBMODBUS_CFLAGS = @BUILD_WITH_LIBMODBUS_CFLAGS@
+BUILD_WITH_LIBMODBUS_LIBS = @BUILD_WITH_LIBMODBUS_LIBS@
+BUILD_WITH_LIBMONGOC_CPPFLAGS = @BUILD_WITH_LIBMONGOC_CPPFLAGS@
+BUILD_WITH_LIBMONGOC_LDFLAGS = @BUILD_WITH_LIBMONGOC_LDFLAGS@
+BUILD_WITH_LIBMYSQL_CFLAGS = @BUILD_WITH_LIBMYSQL_CFLAGS@
+BUILD_WITH_LIBMYSQL_LIBS = @BUILD_WITH_LIBMYSQL_LIBS@
+BUILD_WITH_LIBOPING_CPPFLAGS = @BUILD_WITH_LIBOPING_CPPFLAGS@
+BUILD_WITH_LIBOPING_LDFLAGS = @BUILD_WITH_LIBOPING_LDFLAGS@
+BUILD_WITH_LIBOWCAPI_CPPFLAGS = @BUILD_WITH_LIBOWCAPI_CPPFLAGS@
+BUILD_WITH_LIBOWCAPI_LIBS = @BUILD_WITH_LIBOWCAPI_LIBS@
+BUILD_WITH_LIBPQ_CPPFLAGS = @BUILD_WITH_LIBPQ_CPPFLAGS@
+BUILD_WITH_LIBPQ_LDFLAGS = @BUILD_WITH_LIBPQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS = @BUILD_WITH_LIBRABBITMQ_CPPFLAGS@
+BUILD_WITH_LIBRABBITMQ_LDFLAGS = @BUILD_WITH_LIBRABBITMQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_LIBS = @BUILD_WITH_LIBRABBITMQ_LIBS@
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS = @BUILD_WITH_LIBRDKAFKA_CPPFLAGS@
+BUILD_WITH_LIBRDKAFKA_LDFLAGS = @BUILD_WITH_LIBRDKAFKA_LDFLAGS@
+BUILD_WITH_LIBRDKAFKA_LIBS = @BUILD_WITH_LIBRDKAFKA_LIBS@
+BUILD_WITH_LIBROUTEROS_CPPFLAGS = @BUILD_WITH_LIBROUTEROS_CPPFLAGS@
+BUILD_WITH_LIBROUTEROS_LDFLAGS = @BUILD_WITH_LIBROUTEROS_LDFLAGS@
+BUILD_WITH_LIBRRD_CFLAGS = @BUILD_WITH_LIBRRD_CFLAGS@
+BUILD_WITH_LIBRRD_LDFLAGS = @BUILD_WITH_LIBRRD_LDFLAGS@
+BUILD_WITH_LIBSENSORS_CFLAGS = @BUILD_WITH_LIBSENSORS_CFLAGS@
+BUILD_WITH_LIBSENSORS_LDFLAGS = @BUILD_WITH_LIBSENSORS_LDFLAGS@
+BUILD_WITH_LIBSIGROK_CFLAGS = @BUILD_WITH_LIBSIGROK_CFLAGS@
+BUILD_WITH_LIBSIGROK_LDFLAGS = @BUILD_WITH_LIBSIGROK_LDFLAGS@
+BUILD_WITH_LIBSNMP_CFLAGS = @BUILD_WITH_LIBSNMP_CFLAGS@
+BUILD_WITH_LIBSNMP_LIBS = @BUILD_WITH_LIBSNMP_LIBS@
+BUILD_WITH_LIBSTATGRAB_CFLAGS = @BUILD_WITH_LIBSTATGRAB_CFLAGS@
+BUILD_WITH_LIBSTATGRAB_LDFLAGS = @BUILD_WITH_LIBSTATGRAB_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LIBS = @BUILD_WITH_LIBTOKYOTYRANT_LIBS@
+BUILD_WITH_LIBUDEV_CFLAGS = @BUILD_WITH_LIBUDEV_CFLAGS@
+BUILD_WITH_LIBUDEV_LDFLAGS = @BUILD_WITH_LIBUDEV_LDFLAGS@
+BUILD_WITH_LIBUPSCLIENT_CFLAGS = @BUILD_WITH_LIBUPSCLIENT_CFLAGS@
+BUILD_WITH_LIBUPSCLIENT_LIBS = @BUILD_WITH_LIBUPSCLIENT_LIBS@
+BUILD_WITH_LIBVARNISH_CFLAGS = @BUILD_WITH_LIBVARNISH_CFLAGS@
+BUILD_WITH_LIBVARNISH_LIBS = @BUILD_WITH_LIBVARNISH_LIBS@
+BUILD_WITH_LIBVIRT_CFLAGS = @BUILD_WITH_LIBVIRT_CFLAGS@
+BUILD_WITH_LIBVIRT_LIBS = @BUILD_WITH_LIBVIRT_LIBS@
+BUILD_WITH_LIBXML2_CFLAGS = @BUILD_WITH_LIBXML2_CFLAGS@
+BUILD_WITH_LIBXML2_LIBS = @BUILD_WITH_LIBXML2_LIBS@
+BUILD_WITH_LIBXMMS_CFLAGS = @BUILD_WITH_LIBXMMS_CFLAGS@
+BUILD_WITH_LIBXMMS_LIBS = @BUILD_WITH_LIBXMMS_LIBS@
+BUILD_WITH_LIBYAJL_CPPFLAGS = @BUILD_WITH_LIBYAJL_CPPFLAGS@
+BUILD_WITH_LIBYAJL_LDFLAGS = @BUILD_WITH_LIBYAJL_LDFLAGS@
+BUILD_WITH_LIBYAJL_LIBS = @BUILD_WITH_LIBYAJL_LIBS@
+BUILD_WITH_MIC_CPPFLAGS = @BUILD_WITH_MIC_CPPFLAGS@
+BUILD_WITH_MIC_LDADD = @BUILD_WITH_MIC_LDADD@
+BUILD_WITH_MIC_LIBPATH = @BUILD_WITH_MIC_LIBPATH@
+BUILD_WITH_OPENIPMI_CFLAGS = @BUILD_WITH_OPENIPMI_CFLAGS@
+BUILD_WITH_OPENIPMI_LIBS = @BUILD_WITH_OPENIPMI_LIBS@
+BUILD_WITH_ORACLE_CFLAGS = @BUILD_WITH_ORACLE_CFLAGS@
+BUILD_WITH_ORACLE_LIBS = @BUILD_WITH_ORACLE_LIBS@
+BUILD_WITH_PYTHON_CPPFLAGS = @BUILD_WITH_PYTHON_CPPFLAGS@
+BUILD_WITH_PYTHON_LDFLAGS = @BUILD_WITH_PYTHON_LDFLAGS@
+BUILD_WITH_PYTHON_LIBS = @BUILD_WITH_PYTHON_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_LOG_LEVEL = @DEFAULT_LOG_LEVEL@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GANGLIA_CPPFLAGS = @GANGLIA_CPPFLAGS@
+GANGLIA_LDFLAGS = @GANGLIA_LDFLAGS@
+GANGLIA_LIBS = @GANGLIA_LIBS@
+GCRYPT_CPPFLAGS = @GCRYPT_CPPFLAGS@
+GCRYPT_LDFLAGS = @GCRYPT_LDFLAGS@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVA_CFLAGS = @JAVA_CFLAGS@
+JAVA_CPPFLAGS = @JAVA_CPPFLAGS@
+JAVA_LDFLAGS = @JAVA_LDFLAGS@
+JAVA_LIBS = @JAVA_LIBS@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_DIR = @KERNEL_DIR@
+LCC_VERSION_EXTRA = @LCC_VERSION_EXTRA@
+LCC_VERSION_MAJOR = @LCC_VERSION_MAJOR@
+LCC_VERSION_MINOR = @LCC_VERSION_MINOR@
+LCC_VERSION_PATCH = @LCC_VERSION_PATCH@
+LCC_VERSION_STRING = @LCC_VERSION_STRING@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBNETAPP_CPPFLAGS = @LIBNETAPP_CPPFLAGS@
+LIBNETAPP_LDFLAGS = @LIBNETAPP_LDFLAGS@
+LIBNETAPP_LIBS = @LIBNETAPP_LIBS@
+LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
+LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOAD_PLUGIN_CSV = @LOAD_PLUGIN_CSV@
+LOAD_PLUGIN_LOGFILE = @LOAD_PLUGIN_LOGFILE@
+LOAD_PLUGIN_LOG_LOGSTASH = @LOAD_PLUGIN_LOG_LOGSTASH@
+LOAD_PLUGIN_NETWORK = @LOAD_PLUGIN_NETWORK@
+LOAD_PLUGIN_RRDTOOL = @LOAD_PLUGIN_RRDTOOL@
+LOAD_PLUGIN_SYSLOG = @LOAD_PLUGIN_SYSLOG@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_BINDINGS = @PERL_BINDINGS@
+PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_LIBS = @PERL_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_protoc_c = @have_protoc_c@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@COMPILER_IS_GCC_TRUE@AM_CFLAGS = -Wall -Werror
+AM_CPPFLAGS = -I$(top_srcdir)/src -DPREFIX='"${prefix}"' \
+       -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"' \
+       -DLOCALSTATEDIR='"${localstatedir}"' \
+       -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"' \
+       $(am__append_1) -DPLUGINDIR='"${pkglibdir}"' \
+       -DPKGDATADIR='"${pkgdatadir}"'
+AUTOMAKE_OPTIONS = subdir-objects
+noinst_LTLIBRARIES = libavltree.la libcommon.la libheap.la libplugin_mock.la
+libavltree_la_SOURCES = utils_avltree.c utils_avltree.h
+libcommon_la_SOURCES = common.c common.h
+libheap_la_SOURCES = utils_heap.c utils_heap.h
+libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
+collectd_SOURCES = collectd.c collectd.h \
+                  configfile.c configfile.h \
+                  filter_chain.c filter_chain.h \
+                  meta_data.c meta_data.h \
+                  plugin.c plugin.h \
+                  utils_cache.c utils_cache.h \
+                  utils_complain.c utils_complain.h \
+                  utils_llist.c utils_llist.h \
+                  utils_random.c utils_random.h \
+                  utils_tail_match.c utils_tail_match.h \
+                  utils_match.c utils_match.h \
+                  utils_subst.c utils_subst.h \
+                  utils_tail.c utils_tail.h \
+                  utils_time.c utils_time.h \
+                  types_list.c types_list.h \
+                  utils_threshold.c utils_threshold.h
+
+collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
+collectd_CFLAGS = $(AM_CFLAGS) $(am__append_10)
+collectd_LDFLAGS = -export-dynamic $(am__append_9)
+collectd_LDADD = libavltree.la libcommon.la libheap.la -lm \
+       $(am__append_2) $(am__append_3) $(am__append_4) \
+       $(am__append_5) $(am__append_6) $(am__append_7) \
+       $(am__append_8) $(am__append_11) $(am__append_12) \
+       $(am__append_14)
+collectd_DEPENDENCIES = $(am__append_13)
+test_common_SOURCES = common_test.c ../testing.h
+test_common_LDADD = libcommon.la libplugin_mock.la
+test_utils_avltree_SOURCES = utils_avltree_test.c ../testing.h
+test_utils_avltree_LDADD = libavltree.la
+test_utils_heap_SOURCES = utils_heap_test.c ../testing.h
+test_utils_heap_LDADD = libheap.la
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/daemon/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign src/daemon/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+       @list='$(noinst_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
+
+libavltree.la: $(libavltree_la_OBJECTS) $(libavltree_la_DEPENDENCIES) $(EXTRA_libavltree_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(LINK)  $(libavltree_la_OBJECTS) $(libavltree_la_LIBADD) $(LIBS)
+
+libcommon.la: $(libcommon_la_OBJECTS) $(libcommon_la_DEPENDENCIES) $(EXTRA_libcommon_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(LINK)  $(libcommon_la_OBJECTS) $(libcommon_la_LIBADD) $(LIBS)
+
+libheap.la: $(libheap_la_OBJECTS) $(libheap_la_DEPENDENCIES) $(EXTRA_libheap_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(LINK)  $(libheap_la_OBJECTS) $(libheap_la_LIBADD) $(LIBS)
+
+libplugin_mock.la: $(libplugin_mock_la_OBJECTS) $(libplugin_mock_la_DEPENDENCIES) $(EXTRA_libplugin_mock_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(LINK)  $(libplugin_mock_la_OBJECTS) $(libplugin_mock_la_LIBADD) $(LIBS)
+
+clean-checkPROGRAMS:
+       @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+       fi; \
+       for p in $$list; do echo "$$p $$p"; done | \
+       sed 's/$(EXEEXT)$$//' | \
+       while read p p1; do if test -f $$p \
+        || test -f $$p1 \
+         ; then echo "$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n;h' \
+           -e 's|.*|.|' \
+           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+       sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) files[d] = files[d] " " $$1; \
+           else { print "f", $$3 "/" $$4, $$1; } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+           test -z "$$files" || { \
+           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
+           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
+           } \
+       ; done
+
+uninstall-sbinPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+       files=`for p in $$list; do echo "$$p"; done | \
+         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+             -e 's/$$/$(EXEEXT)/' \
+       `; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(sbindir)" && rm -f $$files
+
+clean-sbinPROGRAMS:
+       @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+
+collectd$(EXEEXT): $(collectd_OBJECTS) $(collectd_DEPENDENCIES) $(EXTRA_collectd_DEPENDENCIES) 
+       @rm -f collectd$(EXEEXT)
+       $(AM_V_CCLD)$(collectd_LINK) $(collectd_OBJECTS) $(collectd_LDADD) $(LIBS)
+
+test_common$(EXEEXT): $(test_common_OBJECTS) $(test_common_DEPENDENCIES) $(EXTRA_test_common_DEPENDENCIES) 
+       @rm -f test_common$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_common_OBJECTS) $(test_common_LDADD) $(LIBS)
+
+test_utils_avltree$(EXEEXT): $(test_utils_avltree_OBJECTS) $(test_utils_avltree_DEPENDENCIES) $(EXTRA_test_utils_avltree_DEPENDENCIES) 
+       @rm -f test_utils_avltree$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_utils_avltree_OBJECTS) $(test_utils_avltree_LDADD) $(LIBS)
+
+test_utils_heap$(EXEEXT): $(test_utils_heap_OBJECTS) $(test_utils_heap_DEPENDENCIES) $(EXTRA_test_utils_heap_DEPENDENCIES) 
+       @rm -f test_utils_heap$(EXEEXT)
+       $(AM_V_CCLD)$(LINK) $(test_utils_heap_OBJECTS) $(test_utils_heap_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-collectd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-configfile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-filter_chain.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-meta_data.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-plugin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-types_list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_cache.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_complain.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_llist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_match.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_random.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_subst.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_tail.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_tail_match.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_threshold.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collectd-utils_time.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_mock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_avltree.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_avltree_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_cache_mock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_heap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_heap_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils_time_mock.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@   $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@   $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+collectd-collectd.o: collectd.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-collectd.o -MD -MP -MF $(DEPDIR)/collectd-collectd.Tpo -c -o collectd-collectd.o `test -f 'collectd.c' || echo '$(srcdir)/'`collectd.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-collectd.Tpo $(DEPDIR)/collectd-collectd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectd.c' object='collectd-collectd.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-collectd.o `test -f 'collectd.c' || echo '$(srcdir)/'`collectd.c
+
+collectd-collectd.obj: collectd.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-collectd.obj -MD -MP -MF $(DEPDIR)/collectd-collectd.Tpo -c -o collectd-collectd.obj `if test -f 'collectd.c'; then $(CYGPATH_W) 'collectd.c'; else $(CYGPATH_W) '$(srcdir)/collectd.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-collectd.Tpo $(DEPDIR)/collectd-collectd.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='collectd.c' object='collectd-collectd.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-collectd.obj `if test -f 'collectd.c'; then $(CYGPATH_W) 'collectd.c'; else $(CYGPATH_W) '$(srcdir)/collectd.c'; fi`
+
+collectd-configfile.o: configfile.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-configfile.o -MD -MP -MF $(DEPDIR)/collectd-configfile.Tpo -c -o collectd-configfile.o `test -f 'configfile.c' || echo '$(srcdir)/'`configfile.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-configfile.Tpo $(DEPDIR)/collectd-configfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='configfile.c' object='collectd-configfile.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-configfile.o `test -f 'configfile.c' || echo '$(srcdir)/'`configfile.c
+
+collectd-configfile.obj: configfile.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-configfile.obj -MD -MP -MF $(DEPDIR)/collectd-configfile.Tpo -c -o collectd-configfile.obj `if test -f 'configfile.c'; then $(CYGPATH_W) 'configfile.c'; else $(CYGPATH_W) '$(srcdir)/configfile.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-configfile.Tpo $(DEPDIR)/collectd-configfile.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='configfile.c' object='collectd-configfile.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-configfile.obj `if test -f 'configfile.c'; then $(CYGPATH_W) 'configfile.c'; else $(CYGPATH_W) '$(srcdir)/configfile.c'; fi`
+
+collectd-filter_chain.o: filter_chain.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-filter_chain.o -MD -MP -MF $(DEPDIR)/collectd-filter_chain.Tpo -c -o collectd-filter_chain.o `test -f 'filter_chain.c' || echo '$(srcdir)/'`filter_chain.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-filter_chain.Tpo $(DEPDIR)/collectd-filter_chain.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='filter_chain.c' object='collectd-filter_chain.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-filter_chain.o `test -f 'filter_chain.c' || echo '$(srcdir)/'`filter_chain.c
+
+collectd-filter_chain.obj: filter_chain.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-filter_chain.obj -MD -MP -MF $(DEPDIR)/collectd-filter_chain.Tpo -c -o collectd-filter_chain.obj `if test -f 'filter_chain.c'; then $(CYGPATH_W) 'filter_chain.c'; else $(CYGPATH_W) '$(srcdir)/filter_chain.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-filter_chain.Tpo $(DEPDIR)/collectd-filter_chain.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='filter_chain.c' object='collectd-filter_chain.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-filter_chain.obj `if test -f 'filter_chain.c'; then $(CYGPATH_W) 'filter_chain.c'; else $(CYGPATH_W) '$(srcdir)/filter_chain.c'; fi`
+
+collectd-meta_data.o: meta_data.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-meta_data.o -MD -MP -MF $(DEPDIR)/collectd-meta_data.Tpo -c -o collectd-meta_data.o `test -f 'meta_data.c' || echo '$(srcdir)/'`meta_data.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-meta_data.Tpo $(DEPDIR)/collectd-meta_data.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='meta_data.c' object='collectd-meta_data.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-meta_data.o `test -f 'meta_data.c' || echo '$(srcdir)/'`meta_data.c
+
+collectd-meta_data.obj: meta_data.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-meta_data.obj -MD -MP -MF $(DEPDIR)/collectd-meta_data.Tpo -c -o collectd-meta_data.obj `if test -f 'meta_data.c'; then $(CYGPATH_W) 'meta_data.c'; else $(CYGPATH_W) '$(srcdir)/meta_data.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-meta_data.Tpo $(DEPDIR)/collectd-meta_data.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='meta_data.c' object='collectd-meta_data.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-meta_data.obj `if test -f 'meta_data.c'; then $(CYGPATH_W) 'meta_data.c'; else $(CYGPATH_W) '$(srcdir)/meta_data.c'; fi`
+
+collectd-plugin.o: plugin.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-plugin.o -MD -MP -MF $(DEPDIR)/collectd-plugin.Tpo -c -o collectd-plugin.o `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-plugin.Tpo $(DEPDIR)/collectd-plugin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='plugin.c' object='collectd-plugin.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-plugin.o `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c
+
+collectd-plugin.obj: plugin.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-plugin.obj -MD -MP -MF $(DEPDIR)/collectd-plugin.Tpo -c -o collectd-plugin.obj `if test -f 'plugin.c'; then $(CYGPATH_W) 'plugin.c'; else $(CYGPATH_W) '$(srcdir)/plugin.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-plugin.Tpo $(DEPDIR)/collectd-plugin.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='plugin.c' object='collectd-plugin.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-plugin.obj `if test -f 'plugin.c'; then $(CYGPATH_W) 'plugin.c'; else $(CYGPATH_W) '$(srcdir)/plugin.c'; fi`
+
+collectd-utils_cache.o: utils_cache.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_cache.o -MD -MP -MF $(DEPDIR)/collectd-utils_cache.Tpo -c -o collectd-utils_cache.o `test -f 'utils_cache.c' || echo '$(srcdir)/'`utils_cache.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_cache.Tpo $(DEPDIR)/collectd-utils_cache.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_cache.c' object='collectd-utils_cache.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_cache.o `test -f 'utils_cache.c' || echo '$(srcdir)/'`utils_cache.c
+
+collectd-utils_cache.obj: utils_cache.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_cache.obj -MD -MP -MF $(DEPDIR)/collectd-utils_cache.Tpo -c -o collectd-utils_cache.obj `if test -f 'utils_cache.c'; then $(CYGPATH_W) 'utils_cache.c'; else $(CYGPATH_W) '$(srcdir)/utils_cache.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_cache.Tpo $(DEPDIR)/collectd-utils_cache.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_cache.c' object='collectd-utils_cache.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_cache.obj `if test -f 'utils_cache.c'; then $(CYGPATH_W) 'utils_cache.c'; else $(CYGPATH_W) '$(srcdir)/utils_cache.c'; fi`
+
+collectd-utils_complain.o: utils_complain.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_complain.o -MD -MP -MF $(DEPDIR)/collectd-utils_complain.Tpo -c -o collectd-utils_complain.o `test -f 'utils_complain.c' || echo '$(srcdir)/'`utils_complain.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_complain.Tpo $(DEPDIR)/collectd-utils_complain.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_complain.c' object='collectd-utils_complain.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_complain.o `test -f 'utils_complain.c' || echo '$(srcdir)/'`utils_complain.c
+
+collectd-utils_complain.obj: utils_complain.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_complain.obj -MD -MP -MF $(DEPDIR)/collectd-utils_complain.Tpo -c -o collectd-utils_complain.obj `if test -f 'utils_complain.c'; then $(CYGPATH_W) 'utils_complain.c'; else $(CYGPATH_W) '$(srcdir)/utils_complain.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_complain.Tpo $(DEPDIR)/collectd-utils_complain.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_complain.c' object='collectd-utils_complain.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_complain.obj `if test -f 'utils_complain.c'; then $(CYGPATH_W) 'utils_complain.c'; else $(CYGPATH_W) '$(srcdir)/utils_complain.c'; fi`
+
+collectd-utils_llist.o: utils_llist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_llist.o -MD -MP -MF $(DEPDIR)/collectd-utils_llist.Tpo -c -o collectd-utils_llist.o `test -f 'utils_llist.c' || echo '$(srcdir)/'`utils_llist.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_llist.Tpo $(DEPDIR)/collectd-utils_llist.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_llist.c' object='collectd-utils_llist.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_llist.o `test -f 'utils_llist.c' || echo '$(srcdir)/'`utils_llist.c
+
+collectd-utils_llist.obj: utils_llist.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_llist.obj -MD -MP -MF $(DEPDIR)/collectd-utils_llist.Tpo -c -o collectd-utils_llist.obj `if test -f 'utils_llist.c'; then $(CYGPATH_W) 'utils_llist.c'; else $(CYGPATH_W) '$(srcdir)/utils_llist.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_llist.Tpo $(DEPDIR)/collectd-utils_llist.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_llist.c' object='collectd-utils_llist.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_llist.obj `if test -f 'utils_llist.c'; then $(CYGPATH_W) 'utils_llist.c'; else $(CYGPATH_W) '$(srcdir)/utils_llist.c'; fi`
+
+collectd-utils_random.o: utils_random.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_random.o -MD -MP -MF $(DEPDIR)/collectd-utils_random.Tpo -c -o collectd-utils_random.o `test -f 'utils_random.c' || echo '$(srcdir)/'`utils_random.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_random.Tpo $(DEPDIR)/collectd-utils_random.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_random.c' object='collectd-utils_random.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_random.o `test -f 'utils_random.c' || echo '$(srcdir)/'`utils_random.c
+
+collectd-utils_random.obj: utils_random.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_random.obj -MD -MP -MF $(DEPDIR)/collectd-utils_random.Tpo -c -o collectd-utils_random.obj `if test -f 'utils_random.c'; then $(CYGPATH_W) 'utils_random.c'; else $(CYGPATH_W) '$(srcdir)/utils_random.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_random.Tpo $(DEPDIR)/collectd-utils_random.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_random.c' object='collectd-utils_random.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_random.obj `if test -f 'utils_random.c'; then $(CYGPATH_W) 'utils_random.c'; else $(CYGPATH_W) '$(srcdir)/utils_random.c'; fi`
+
+collectd-utils_tail_match.o: utils_tail_match.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_tail_match.o -MD -MP -MF $(DEPDIR)/collectd-utils_tail_match.Tpo -c -o collectd-utils_tail_match.o `test -f 'utils_tail_match.c' || echo '$(srcdir)/'`utils_tail_match.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_tail_match.Tpo $(DEPDIR)/collectd-utils_tail_match.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_tail_match.c' object='collectd-utils_tail_match.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_tail_match.o `test -f 'utils_tail_match.c' || echo '$(srcdir)/'`utils_tail_match.c
+
+collectd-utils_tail_match.obj: utils_tail_match.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_tail_match.obj -MD -MP -MF $(DEPDIR)/collectd-utils_tail_match.Tpo -c -o collectd-utils_tail_match.obj `if test -f 'utils_tail_match.c'; then $(CYGPATH_W) 'utils_tail_match.c'; else $(CYGPATH_W) '$(srcdir)/utils_tail_match.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_tail_match.Tpo $(DEPDIR)/collectd-utils_tail_match.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_tail_match.c' object='collectd-utils_tail_match.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_tail_match.obj `if test -f 'utils_tail_match.c'; then $(CYGPATH_W) 'utils_tail_match.c'; else $(CYGPATH_W) '$(srcdir)/utils_tail_match.c'; fi`
+
+collectd-utils_match.o: utils_match.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_match.o -MD -MP -MF $(DEPDIR)/collectd-utils_match.Tpo -c -o collectd-utils_match.o `test -f 'utils_match.c' || echo '$(srcdir)/'`utils_match.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_match.Tpo $(DEPDIR)/collectd-utils_match.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_match.c' object='collectd-utils_match.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_match.o `test -f 'utils_match.c' || echo '$(srcdir)/'`utils_match.c
+
+collectd-utils_match.obj: utils_match.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_match.obj -MD -MP -MF $(DEPDIR)/collectd-utils_match.Tpo -c -o collectd-utils_match.obj `if test -f 'utils_match.c'; then $(CYGPATH_W) 'utils_match.c'; else $(CYGPATH_W) '$(srcdir)/utils_match.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_match.Tpo $(DEPDIR)/collectd-utils_match.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_match.c' object='collectd-utils_match.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_match.obj `if test -f 'utils_match.c'; then $(CYGPATH_W) 'utils_match.c'; else $(CYGPATH_W) '$(srcdir)/utils_match.c'; fi`
+
+collectd-utils_subst.o: utils_subst.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_subst.o -MD -MP -MF $(DEPDIR)/collectd-utils_subst.Tpo -c -o collectd-utils_subst.o `test -f 'utils_subst.c' || echo '$(srcdir)/'`utils_subst.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_subst.Tpo $(DEPDIR)/collectd-utils_subst.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_subst.c' object='collectd-utils_subst.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_subst.o `test -f 'utils_subst.c' || echo '$(srcdir)/'`utils_subst.c
+
+collectd-utils_subst.obj: utils_subst.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_subst.obj -MD -MP -MF $(DEPDIR)/collectd-utils_subst.Tpo -c -o collectd-utils_subst.obj `if test -f 'utils_subst.c'; then $(CYGPATH_W) 'utils_subst.c'; else $(CYGPATH_W) '$(srcdir)/utils_subst.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_subst.Tpo $(DEPDIR)/collectd-utils_subst.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_subst.c' object='collectd-utils_subst.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_subst.obj `if test -f 'utils_subst.c'; then $(CYGPATH_W) 'utils_subst.c'; else $(CYGPATH_W) '$(srcdir)/utils_subst.c'; fi`
+
+collectd-utils_tail.o: utils_tail.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_tail.o -MD -MP -MF $(DEPDIR)/collectd-utils_tail.Tpo -c -o collectd-utils_tail.o `test -f 'utils_tail.c' || echo '$(srcdir)/'`utils_tail.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_tail.Tpo $(DEPDIR)/collectd-utils_tail.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_tail.c' object='collectd-utils_tail.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_tail.o `test -f 'utils_tail.c' || echo '$(srcdir)/'`utils_tail.c
+
+collectd-utils_tail.obj: utils_tail.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_tail.obj -MD -MP -MF $(DEPDIR)/collectd-utils_tail.Tpo -c -o collectd-utils_tail.obj `if test -f 'utils_tail.c'; then $(CYGPATH_W) 'utils_tail.c'; else $(CYGPATH_W) '$(srcdir)/utils_tail.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_tail.Tpo $(DEPDIR)/collectd-utils_tail.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_tail.c' object='collectd-utils_tail.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_tail.obj `if test -f 'utils_tail.c'; then $(CYGPATH_W) 'utils_tail.c'; else $(CYGPATH_W) '$(srcdir)/utils_tail.c'; fi`
+
+collectd-utils_time.o: utils_time.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_time.o -MD -MP -MF $(DEPDIR)/collectd-utils_time.Tpo -c -o collectd-utils_time.o `test -f 'utils_time.c' || echo '$(srcdir)/'`utils_time.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_time.Tpo $(DEPDIR)/collectd-utils_time.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_time.c' object='collectd-utils_time.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_time.o `test -f 'utils_time.c' || echo '$(srcdir)/'`utils_time.c
+
+collectd-utils_time.obj: utils_time.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_time.obj -MD -MP -MF $(DEPDIR)/collectd-utils_time.Tpo -c -o collectd-utils_time.obj `if test -f 'utils_time.c'; then $(CYGPATH_W) 'utils_time.c'; else $(CYGPATH_W) '$(srcdir)/utils_time.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_time.Tpo $(DEPDIR)/collectd-utils_time.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_time.c' object='collectd-utils_time.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_time.obj `if test -f 'utils_time.c'; then $(CYGPATH_W) 'utils_time.c'; else $(CYGPATH_W) '$(srcdir)/utils_time.c'; fi`
+
+collectd-types_list.o: types_list.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-types_list.o -MD -MP -MF $(DEPDIR)/collectd-types_list.Tpo -c -o collectd-types_list.o `test -f 'types_list.c' || echo '$(srcdir)/'`types_list.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-types_list.Tpo $(DEPDIR)/collectd-types_list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='types_list.c' object='collectd-types_list.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-types_list.o `test -f 'types_list.c' || echo '$(srcdir)/'`types_list.c
+
+collectd-types_list.obj: types_list.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-types_list.obj -MD -MP -MF $(DEPDIR)/collectd-types_list.Tpo -c -o collectd-types_list.obj `if test -f 'types_list.c'; then $(CYGPATH_W) 'types_list.c'; else $(CYGPATH_W) '$(srcdir)/types_list.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-types_list.Tpo $(DEPDIR)/collectd-types_list.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='types_list.c' object='collectd-types_list.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-types_list.obj `if test -f 'types_list.c'; then $(CYGPATH_W) 'types_list.c'; else $(CYGPATH_W) '$(srcdir)/types_list.c'; fi`
+
+collectd-utils_threshold.o: utils_threshold.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_threshold.o -MD -MP -MF $(DEPDIR)/collectd-utils_threshold.Tpo -c -o collectd-utils_threshold.o `test -f 'utils_threshold.c' || echo '$(srcdir)/'`utils_threshold.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_threshold.Tpo $(DEPDIR)/collectd-utils_threshold.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_threshold.c' object='collectd-utils_threshold.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_threshold.o `test -f 'utils_threshold.c' || echo '$(srcdir)/'`utils_threshold.c
+
+collectd-utils_threshold.obj: utils_threshold.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -MT collectd-utils_threshold.obj -MD -MP -MF $(DEPDIR)/collectd-utils_threshold.Tpo -c -o collectd-utils_threshold.obj `if test -f 'utils_threshold.c'; then $(CYGPATH_W) 'utils_threshold.c'; else $(CYGPATH_W) '$(srcdir)/utils_threshold.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/collectd-utils_threshold.Tpo $(DEPDIR)/collectd-utils_threshold.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils_threshold.c' object='collectd-utils_threshold.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(collectd_CPPFLAGS) $(CPPFLAGS) $(collectd_CFLAGS) $(CFLAGS) -c -o collectd-utils_threshold.obj `if test -f 'utils_threshold.c'; then $(CYGPATH_W) 'utils_threshold.c'; else $(CYGPATH_W) '$(srcdir)/utils_threshold.c'; fi`
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+       rm -f $< $@
+       $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+       @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+       @$(am__set_TESTS_bases); \
+       am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+       redo_bases=`for i in $$bases; do \
+                     am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+                   done`; \
+       if test -n "$$redo_bases"; then \
+         redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+         redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+         if $(am__make_dryrun); then :; else \
+           rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+         fi; \
+       fi; \
+       if test -n "$$am__remaking_logs"; then \
+         echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+              "recursion detected" >&2; \
+       else \
+         am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+       fi; \
+       if $(am__make_dryrun); then :; else \
+         st=0;  \
+         errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+         for i in $$redo_bases; do \
+           test -f $$i.trs && test -r $$i.trs \
+             || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+           test -f $$i.log && test -r $$i.log \
+             || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+         done; \
+         test $$st -eq 0 || exit 1; \
+       fi
+       @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+       ws='[   ]'; \
+       results=`for b in $$bases; do echo $$b.trs; done`; \
+       test -n "$$results" || results=/dev/null; \
+       all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+       pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+       fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+       skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+       xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+       xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+       error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+       if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+         success=true; \
+       else \
+         success=false; \
+       fi; \
+       br='==================='; br=$$br$$br$$br$$br; \
+       result_count () \
+       { \
+           if test x"$$1" = x"--maybe-color"; then \
+             maybe_colorize=yes; \
+           elif test x"$$1" = x"--no-color"; then \
+             maybe_colorize=no; \
+           else \
+             echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+           fi; \
+           shift; \
+           desc=$$1 count=$$2; \
+           if test $$maybe_colorize = yes && test $$count -gt 0; then \
+             color_start=$$3 color_end=$$std; \
+           else \
+             color_start= color_end=; \
+           fi; \
+           echo "$${color_start}# $$desc $$count$${color_end}"; \
+       }; \
+       create_testsuite_report () \
+       { \
+         result_count $$1 "TOTAL:" $$all   "$$brg"; \
+         result_count $$1 "PASS: " $$pass  "$$grn"; \
+         result_count $$1 "SKIP: " $$skip  "$$blu"; \
+         result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+         result_count $$1 "FAIL: " $$fail  "$$red"; \
+         result_count $$1 "XPASS:" $$xpass "$$red"; \
+         result_count $$1 "ERROR:" $$error "$$mgn"; \
+       }; \
+       {                                                               \
+         echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |       \
+           $(am__rst_title);                                           \
+         create_testsuite_report --no-color;                           \
+         echo;                                                         \
+         echo ".. contents:: :depth: 2";                               \
+         echo;                                                         \
+         for b in $$bases; do echo $$b; done                           \
+           | $(am__create_global_log);                                 \
+       } >$(TEST_SUITE_LOG).tmp || exit 1;                             \
+       mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);                     \
+       if $$success; then                                              \
+         col="$$grn";                                                  \
+        else                                                           \
+         col="$$red";                                                  \
+         test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);               \
+       fi;                                                             \
+       echo "$${col}$$br$${std}";                                      \
+       echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}";   \
+       echo "$${col}$$br$${std}";                                      \
+       create_testsuite_report --maybe-color;                          \
+       echo "$$col$$br$$std";                                          \
+       if $$success; then :; else                                      \
+         echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";         \
+         if test -n "$(PACKAGE_BUGREPORT)"; then                       \
+           echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+         fi;                                                           \
+         echo "$$col$$br$$std";                                        \
+       fi;                                                             \
+       $$success || exit 1
+
+check-TESTS:
+       @list='$(RECHECK_LOGS)';           test -z "$$list" || rm -f $$list
+       @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+       log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+       exit $$?;
+recheck: all $(check_PROGRAMS)
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       bases=`for i in $$bases; do echo $$i; done \
+                | $(am__list_recheck_tests)` || exit 1; \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       log_list=`echo $$log_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+               am__force_recheck=am--force-recheck \
+               TEST_LOGS="$$log_list"; \
+       exit $$?
+test_common.log: test_common$(EXEEXT)
+       @p='test_common$(EXEEXT)'; \
+       b='test_common'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+test_utils_avltree.log: test_utils_avltree$(EXEEXT)
+       @p='test_utils_avltree$(EXEEXT)'; \
+       b='test_utils_avltree'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+test_utils_heap.log: test_utils_heap$(EXEEXT)
+       @p='test_utils_heap$(EXEEXT)'; \
+       b='test_utils_heap'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+       @p='$<'; \
+       $(am__set_b); \
+       $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@      @p='$<'; \
+@am__EXEEXT_TRUE@      $(am__set_b); \
+@am__EXEEXT_TRUE@      $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@      --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@      $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@      "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+       $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs:
+       for dir in "$(DESTDIR)$(sbindir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+       -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+       -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+       -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+       clean-noinstLTLIBRARIES clean-sbinPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-sbinPROGRAMS
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+       clean-checkPROGRAMS clean-generic clean-libtool \
+       clean-noinstLTLIBRARIES clean-sbinPROGRAMS cscopelist-am ctags \
+       ctags-am distclean distclean-compile distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-sbinPROGRAMS install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       recheck tags tags-am uninstall uninstall-am \
+       uninstall-sbinPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c
new file mode 100644 (file)
index 0000000..1b9c374
--- /dev/null
@@ -0,0 +1,718 @@
+/**
+ * collectd - src/collectd.c
+ * Copyright (C) 2005-2007  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Alvaro Barcellos <alvaro.barcellos at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+
+#include "plugin.h"
+#include "configfile.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+#include <pthread.h>
+
+#if HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
+
+#ifndef COLLECTD_LOCALE
+# define COLLECTD_LOCALE "C"
+#endif
+
+/*
+ * Global variables
+ */
+char hostname_g[DATA_MAX_NAME_LEN];
+cdtime_t interval_g;
+int  pidfile_from_cli = 0;
+int  timeout_g;
+#if HAVE_LIBKSTAT
+kstat_ctl_t *kc;
+#endif /* HAVE_LIBKSTAT */
+
+static int loop = 0;
+
+static void *do_flush (void __attribute__((unused)) *arg)
+{
+       INFO ("Flushing all data.");
+       plugin_flush (/* plugin = */ NULL,
+                       /* timeout = */ 0,
+                       /* ident = */ NULL);
+       INFO ("Finished flushing all data.");
+       pthread_exit (NULL);
+       return NULL;
+}
+
+static void sig_int_handler (int __attribute__((unused)) signal)
+{
+       loop++;
+}
+
+static void sig_term_handler (int __attribute__((unused)) signal)
+{
+       loop++;
+}
+
+static void sig_usr1_handler (int __attribute__((unused)) signal)
+{
+       pthread_t      thread;
+       pthread_attr_t attr;
+
+       /* flushing the data might take a while,
+        * so it should be done asynchronously */
+       pthread_attr_init (&attr);
+       pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+       pthread_create (&thread, &attr, do_flush, NULL);
+       pthread_attr_destroy (&attr);
+}
+
+static int init_hostname (void)
+{
+       const char *str;
+
+       struct addrinfo  ai_hints;
+       struct addrinfo *ai_list;
+       struct addrinfo *ai_ptr;
+       int status;
+
+       str = global_option_get ("Hostname");
+       if (str != NULL)
+       {
+               sstrncpy (hostname_g, str, sizeof (hostname_g));
+               return (0);
+       }
+
+       if (gethostname (hostname_g, sizeof (hostname_g)) != 0)
+       {
+               fprintf (stderr, "`gethostname' failed and no "
+                               "hostname was configured.\n");
+               return (-1);
+       }
+
+       str = global_option_get ("FQDNLookup");
+       if (IS_FALSE (str))
+               return (0);
+
+       memset (&ai_hints, '\0', sizeof (ai_hints));
+       ai_hints.ai_flags = AI_CANONNAME;
+
+       status = getaddrinfo (hostname_g, NULL, &ai_hints, &ai_list);
+       if (status != 0)
+       {
+               ERROR ("Looking up \"%s\" failed. You have set the "
+                               "\"FQDNLookup\" option, but I cannot resolve "
+                               "my hostname to a fully qualified domain "
+                               "name. Please fix the network "
+                               "configuration.", hostname_g);
+               return (-1);
+       }
+
+       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               if (ai_ptr->ai_canonname == NULL)
+                       continue;
+
+               sstrncpy (hostname_g, ai_ptr->ai_canonname, sizeof (hostname_g));
+               break;
+       }
+
+       freeaddrinfo (ai_list);
+       return (0);
+} /* int init_hostname */
+
+static int init_global_variables (void)
+{
+       char const *str;
+
+       interval_g = cf_get_default_interval ();
+       assert (interval_g > 0);
+       DEBUG ("interval_g = %.3f;", CDTIME_T_TO_DOUBLE (interval_g));
+
+       str = global_option_get ("Timeout");
+       if (str == NULL)
+               str = "2";
+       timeout_g = atoi (str);
+       if (timeout_g <= 1)
+       {
+               fprintf (stderr, "Cannot set the timeout to a correct value.\n"
+                               "Please check your settings.\n");
+               return (-1);
+       }
+       DEBUG ("timeout_g = %i;", timeout_g);
+
+       if (init_hostname () != 0)
+               return (-1);
+       DEBUG ("hostname_g = %s;", hostname_g);
+
+       return (0);
+} /* int init_global_variables */
+
+static int change_basedir (const char *orig_dir)
+{
+       char *dir;
+       size_t dirlen;
+       int status;
+
+       dir = strdup (orig_dir);
+       if (dir == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("strdup failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       dirlen = strlen (dir);
+       while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
+               dir[--dirlen] = '\0';
+
+       if (dirlen <= 0)
+               return (-1);
+
+       status = chdir (dir);
+       if (status == 0)
+       {
+               free (dir);
+               return (0);
+       }
+       else if (errno != ENOENT)
+       {
+               char errbuf[1024];
+               ERROR ("change_basedir: chdir (%s): %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               free (dir);
+               return (-1);
+       }
+
+       status = mkdir (dir, S_IRWXU | S_IRWXG | S_IRWXO);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("change_basedir: mkdir (%s): %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               free (dir);
+               return (-1);
+       }
+
+       status = chdir (dir);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("change_basedir: chdir (%s): %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               free (dir);
+               return (-1);
+       }
+
+       free (dir);
+       return (0);
+} /* static int change_basedir (char *dir) */
+
+#if HAVE_LIBKSTAT
+static void update_kstat (void)
+{
+       if (kc == NULL)
+       {
+               if ((kc = kstat_open ()) == NULL)
+                       ERROR ("Unable to open kstat control structure");
+       }
+       else
+       {
+               kid_t kid;
+               kid = kstat_chain_update (kc);
+               if (kid > 0)
+               {
+                       INFO ("kstat chain has been updated");
+                       plugin_init_all ();
+               }
+               else if (kid < 0)
+                       ERROR ("kstat chain update failed");
+               /* else: everything works as expected */
+       }
+
+       return;
+} /* static void update_kstat (void) */
+#endif /* HAVE_LIBKSTAT */
+
+/* TODO
+ * Remove all settings but `-f' and `-C'
+ */
+static void exit_usage (int status)
+{
+       printf ("Usage: "PACKAGE" [OPTIONS]\n\n"
+
+                       "Available options:\n"
+                       "  General:\n"
+                       "    -C <file>       Configuration file.\n"
+                       "                    Default: "CONFIGFILE"\n"
+                       "    -t              Test config and exit.\n"
+                       "    -T              Test plugin read and exit.\n"
+                       "    -P <file>       PID-file.\n"
+                       "                    Default: "PIDFILE"\n"
+#if COLLECT_DAEMON
+                       "    -f              Don't fork to the background.\n"
+#endif
+                       "    -h              Display help (this message)\n"
+                       "\nBuiltin defaults:\n"
+                       "  Config file       "CONFIGFILE"\n"
+                       "  PID file          "PIDFILE"\n"
+                       "  Plugin directory  "PLUGINDIR"\n"
+                       "  Data directory    "PKGLOCALSTATEDIR"\n"
+                       "\n"PACKAGE" "VERSION", http://collectd.org/\n"
+                       "by Florian octo Forster <octo@collectd.org>\n"
+                       "for contributions see `AUTHORS'\n");
+       exit (status);
+} /* static void exit_usage (int status) */
+
+static int do_init (void)
+{
+#if HAVE_SETLOCALE
+       if (setlocale (LC_NUMERIC, COLLECTD_LOCALE) == NULL)
+               WARNING ("setlocale (\"%s\") failed.", COLLECTD_LOCALE);
+#endif
+
+#if HAVE_LIBKSTAT
+       kc = NULL;
+       update_kstat ();
+#endif
+
+#if HAVE_LIBSTATGRAB
+       if (sg_init (
+# if HAVE_LIBSTATGRAB_0_90
+                   0
+# endif
+                   ))
+       {
+               ERROR ("sg_init: %s", sg_str_error (sg_get_error ()));
+               return (-1);
+       }
+
+       if (sg_drop_privileges ())
+       {
+               ERROR ("sg_drop_privileges: %s", sg_str_error (sg_get_error ()));
+               return (-1);
+       }
+#endif
+
+       plugin_init_all ();
+
+       return (0);
+} /* int do_init () */
+
+
+static int do_loop (void)
+{
+       cdtime_t interval = cf_get_default_interval ();
+       cdtime_t wait_until;
+
+       wait_until = cdtime () + interval;
+
+       while (loop == 0)
+       {
+               struct timespec ts_wait = { 0, 0 };
+               cdtime_t now;
+
+#if HAVE_LIBKSTAT
+               update_kstat ();
+#endif
+
+               /* Issue all plugins */
+               plugin_read_all ();
+
+               now = cdtime ();
+               if (now >= wait_until)
+               {
+                       WARNING ("Not sleeping because the next interval is "
+                                       "%.3f seconds in the past!",
+                                       CDTIME_T_TO_DOUBLE (now - wait_until));
+                       wait_until = now + interval;
+                       continue;
+               }
+
+               CDTIME_T_TO_TIMESPEC (wait_until - now, &ts_wait);
+               wait_until = wait_until + interval;
+
+               while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) != 0))
+               {
+                       if (errno != EINTR)
+                       {
+                               char errbuf[1024];
+                               ERROR ("nanosleep failed: %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+               }
+       } /* while (loop == 0) */
+
+       return (0);
+} /* int do_loop */
+
+static int do_shutdown (void)
+{
+       plugin_shutdown_all ();
+       return (0);
+} /* int do_shutdown */
+
+#if COLLECT_DAEMON
+static int pidfile_create (void)
+{
+       FILE *fh;
+       const char *file = global_option_get ("PIDFile");
+
+       if ((fh = fopen (file, "w")) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("fopen (%s): %s", file,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (1);
+       }
+
+       fprintf (fh, "%i\n", (int) getpid ());
+       fclose(fh);
+
+       return (0);
+} /* static int pidfile_create (const char *file) */
+
+static int pidfile_remove (void)
+{
+       const char *file = global_option_get ("PIDFile");
+
+       DEBUG ("unlink (%s)", (file != NULL) ? file : "<null>");
+       return (unlink (file));
+} /* static int pidfile_remove (const char *file) */
+#endif /* COLLECT_DAEMON */
+
+#ifdef KERNEL_LINUX
+int notify_upstart (void)
+{
+    const char  *upstart_job = getenv("UPSTART_JOB");
+
+    if (upstart_job == NULL)
+        return 0;
+
+    if (strcmp(upstart_job, "collectd") != 0)
+        return 0;
+
+    WARNING ("supervised by upstart, will stop to signal readyness");
+    raise(SIGSTOP);
+    unsetenv("UPSTART_JOB");
+
+    return 1;
+}
+
+int notify_systemd (void)
+{
+    int                  fd = -1;
+    const char          *notifysocket = getenv("NOTIFY_SOCKET");
+    struct sockaddr_un   su;
+    struct iovec         iov;
+    struct msghdr        hdr;
+
+    if (notifysocket == NULL)
+        return 0;
+
+    if ((strchr("@/", notifysocket[0])) == NULL ||
+        strlen(notifysocket) < 2)
+        return 0;
+
+    WARNING ("supervised by systemd, will signal readyness");
+    if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+        WARNING ("cannot contact systemd socket %s", notifysocket);
+        return 0;
+    }
+
+    bzero(&su, sizeof(su));
+    su.sun_family = AF_UNIX;
+    sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
+
+    if (notifysocket[0] == '@')
+        su.sun_path[0] = 0;
+
+    bzero(&iov, sizeof(iov));
+    iov.iov_base = "READY=1";
+    iov.iov_len = strlen("READY=1");
+
+    bzero(&hdr, sizeof(hdr));
+    hdr.msg_name = &su;
+    hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
+        strlen(notifysocket);
+    hdr.msg_iov = &iov;
+    hdr.msg_iovlen = 1;
+
+    unsetenv("NOTIFY_SOCKET");
+    if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
+        WARNING ("cannot send notification to systemd");
+        close(fd);
+        return 0;
+    }
+    close(fd);
+    return 1;
+}
+#endif /* KERNEL_LINUX */
+
+int main (int argc, char **argv)
+{
+       struct sigaction sig_int_action;
+       struct sigaction sig_term_action;
+       struct sigaction sig_usr1_action;
+       struct sigaction sig_pipe_action;
+       char *configfile = CONFIGFILE;
+       int test_config  = 0;
+       int test_readall = 0;
+       const char *basedir;
+#if COLLECT_DAEMON
+       struct sigaction sig_chld_action;
+       pid_t pid;
+       int daemonize    = 1;
+#endif
+       int exit_status = 0;
+
+       /* read options */
+       while (1)
+       {
+               int c;
+
+               c = getopt (argc, argv, "htTC:"
+#if COLLECT_DAEMON
+                               "fP:"
+#endif
+               );
+
+               if (c == -1)
+                       break;
+
+               switch (c)
+               {
+                       case 'C':
+                               configfile = optarg;
+                               break;
+                       case 't':
+                               test_config = 1;
+                               break;
+                       case 'T':
+                               test_readall = 1;
+                               global_option_set ("ReadThreads", "-1");
+#if COLLECT_DAEMON
+                               daemonize = 0;
+#endif /* COLLECT_DAEMON */
+                               break;
+#if COLLECT_DAEMON
+                       case 'P':
+                               global_option_set ("PIDFile", optarg);
+                               pidfile_from_cli = 1;
+                               break;
+                       case 'f':
+                               daemonize = 0;
+                               break;
+#endif /* COLLECT_DAEMON */
+                       case 'h':
+                               exit_usage (0);
+                               break;
+                       default:
+                               exit_usage (1);
+               } /* switch (c) */
+       } /* while (1) */
+
+       if (optind < argc)
+               exit_usage (1);
+
+       plugin_init_ctx ();
+
+       /*
+        * Read options from the config file, the environment and the command
+        * line (in that order, with later options overwriting previous ones in
+        * general).
+        * Also, this will automatically load modules.
+        */
+       if (cf_read (configfile))
+       {
+               fprintf (stderr, "Error: Reading the config file failed!\n"
+                               "Read the syslog for details.\n");
+               return (1);
+       }
+
+       /*
+        * Change directory. We do this _after_ reading the config and loading
+        * modules to relative paths work as expected.
+        */
+       if ((basedir = global_option_get ("BaseDir")) == NULL)
+       {
+               fprintf (stderr, "Don't have a basedir to use. This should not happen. Ever.");
+               return (1);
+       }
+       else if (change_basedir (basedir))
+       {
+               fprintf (stderr, "Error: Unable to change to directory `%s'.\n", basedir);
+               return (1);
+       }
+
+       /*
+        * Set global variables or, if that failes, exit. We cannot run with
+        * them being uninitialized. If nothing is configured, then defaults
+        * are being used. So this means that the user has actually done
+        * something wrong.
+        */
+       if (init_global_variables () != 0)
+               return (1);
+
+       if (test_config)
+               return (0);
+
+#if COLLECT_DAEMON
+       /*
+        * fork off child
+        */
+       memset (&sig_chld_action, '\0', sizeof (sig_chld_action));
+       sig_chld_action.sa_handler = SIG_IGN;
+       sigaction (SIGCHLD, &sig_chld_action, NULL);
+
+    /*
+     * Only daemonize if we're not being supervised
+     * by upstart or systemd (when using Linux).
+     */
+       if (daemonize
+#ifdef KERNEL_LINUX
+           && notify_upstart() == 0 && notify_systemd() == 0
+#endif
+       )
+       {
+               if ((pid = fork ()) == -1)
+               {
+                       /* error */
+                       char errbuf[1024];
+                       fprintf (stderr, "fork: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       return (1);
+               }
+               else if (pid != 0)
+               {
+                       /* parent */
+                       /* printf ("Running (PID %i)\n", pid); */
+                       return (0);
+               }
+
+               /* Detach from session */
+               setsid ();
+
+               /* Write pidfile */
+               if (pidfile_create ())
+                       exit (2);
+
+               /* close standard descriptors */
+               close (2);
+               close (1);
+               close (0);
+
+               if (open ("/dev/null", O_RDWR) != 0)
+               {
+                       ERROR ("Error: Could not connect `STDIN' to `/dev/null'");
+                       return (1);
+               }
+               if (dup (0) != 1)
+               {
+                       ERROR ("Error: Could not connect `STDOUT' to `/dev/null'");
+                       return (1);
+               }
+               if (dup (0) != 2)
+               {
+                       ERROR ("Error: Could not connect `STDERR' to `/dev/null'");
+                       return (1);
+               }
+       } /* if (daemonize) */
+#endif /* COLLECT_DAEMON */
+
+       memset (&sig_pipe_action, '\0', sizeof (sig_pipe_action));
+       sig_pipe_action.sa_handler = SIG_IGN;
+       sigaction (SIGPIPE, &sig_pipe_action, NULL);
+
+       /*
+        * install signal handlers
+        */
+       memset (&sig_int_action, '\0', sizeof (sig_int_action));
+       sig_int_action.sa_handler = sig_int_handler;
+       if (0 != sigaction (SIGINT, &sig_int_action, NULL)) {
+               char errbuf[1024];
+               ERROR ("Error: Failed to install a signal handler for signal INT: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (1);
+       }
+
+       memset (&sig_term_action, '\0', sizeof (sig_term_action));
+       sig_term_action.sa_handler = sig_term_handler;
+       if (0 != sigaction (SIGTERM, &sig_term_action, NULL)) {
+               char errbuf[1024];
+               ERROR ("Error: Failed to install a signal handler for signal TERM: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (1);
+       }
+
+       memset (&sig_usr1_action, '\0', sizeof (sig_usr1_action));
+       sig_usr1_action.sa_handler = sig_usr1_handler;
+       if (0 != sigaction (SIGUSR1, &sig_usr1_action, NULL)) {
+               char errbuf[1024];
+               ERROR ("Error: Failed to install a signal handler for signal USR1: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (1);
+       }
+
+       /*
+        * run the actual loops
+        */
+       do_init ();
+
+       if (test_readall)
+       {
+               if (plugin_read_all_once () != 0)
+                       exit_status = 1;
+       }
+       else
+       {
+               INFO ("Initialization complete, entering read-loop.");
+               do_loop ();
+       }
+
+       /* close syslog */
+       INFO ("Exiting normally.");
+
+       do_shutdown ();
+
+#if COLLECT_DAEMON
+       if (daemonize)
+               pidfile_remove ();
+#endif /* COLLECT_DAEMON */
+
+       return (exit_status);
+} /* int main */
diff --git a/src/daemon/collectd.h b/src/daemon/collectd.h
new file mode 100644 (file)
index 0000000..80b753c
--- /dev/null
@@ -0,0 +1,319 @@
+/**
+ * collectd - src/collectd.h
+ * Copyright (C) 2005,2006  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef COLLECTD_H
+#define COLLECTD_H
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+#if HAVE_SIGNAL_H
+# include <signal.h>
+#endif
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#if HAVE_ERRNO_H
+# include <errno.h>
+#endif
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h>
+# else
+#  include <time.h>
+# endif
+#endif
+
+#if HAVE_ASSERT_H
+# include <assert.h>
+#else
+# define assert(...) /* nop */
+#endif
+
+#if !defined(HAVE__BOOL) || !HAVE__BOOL
+typedef int _Bool;
+# undef HAVE__BOOL
+# define HAVE__BOOL 1
+#endif
+
+#if NAN_STATIC_DEFAULT
+# include <math.h>
+/* #endif NAN_STATIC_DEFAULT*/
+#elif NAN_STATIC_ISOC
+# ifndef __USE_ISOC99
+#  define DISABLE_ISOC99 1
+#  define __USE_ISOC99 1
+# endif /* !defined(__USE_ISOC99) */
+# include <math.h>
+# if DISABLE_ISOC99
+#  undef DISABLE_ISOC99
+#  undef __USE_ISOC99
+# endif /* DISABLE_ISOC99 */
+/* #endif NAN_STATIC_ISOC */
+#elif NAN_ZERO_ZERO
+# include <math.h>
+# ifdef NAN
+#  undef NAN
+# endif
+# define NAN (0.0 / 0.0)
+# ifndef isnan
+#  define isnan(f) ((f) != (f))
+# endif /* !defined(isnan) */
+# ifndef isfinite
+#  define isfinite(f) (((f) - (f)) == 0.0)
+# endif
+# ifndef isinf
+#  define isinf(f) (!isfinite(f) && !isnan(f))
+# endif
+#endif /* NAN_ZERO_ZERO */
+
+/* Try really, really hard to determine endianess. Under NexentaStor 1.0.2 this
+ * information is in <sys/isa_defs.h>, possibly some other Solaris versions do
+ * this too.. */
+#if HAVE_ENDIAN_H
+# include <endian.h>
+#elif HAVE_SYS_ISA_DEFS_H
+# include <sys/isa_defs.h>
+#endif
+
+#ifndef BYTE_ORDER
+# if defined(_BYTE_ORDER)
+#  define BYTE_ORDER _BYTE_ORDER
+# elif defined(__BYTE_ORDER)
+#  define BYTE_ORDER __BYTE_ORDER
+# elif defined(__DARWIN_BYTE_ORDER)
+#  define BYTE_ORDER __DARWIN_BYTE_ORDER
+# endif
+#endif
+#ifndef BIG_ENDIAN
+# if defined(_BIG_ENDIAN)
+#  define BIG_ENDIAN _BIG_ENDIAN
+# elif defined(__BIG_ENDIAN)
+#  define BIG_ENDIAN __BIG_ENDIAN
+# elif defined(__DARWIN_BIG_ENDIAN)
+#  define BIG_ENDIAN __DARWIN_BIG_ENDIAN
+# endif
+#endif
+#ifndef LITTLE_ENDIAN
+# if defined(_LITTLE_ENDIAN)
+#  define LITTLE_ENDIAN _LITTLE_ENDIAN
+# elif defined(__LITTLE_ENDIAN)
+#  define LITTLE_ENDIAN __LITTLE_ENDIAN
+# elif defined(__DARWIN_LITTLE_ENDIAN)
+#  define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
+# endif
+#endif
+#ifndef BYTE_ORDER
+# if defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN)
+#  undef BIG_ENDIAN
+#  define BIG_ENDIAN 4321
+#  define LITTLE_ENDIAN 1234
+#  define BYTE_ORDER BIG_ENDIAN
+# elif !defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN)
+#  undef LITTLE_ENDIAN
+#  define BIG_ENDIAN 4321
+#  define LITTLE_ENDIAN 1234
+#  define BYTE_ORDER LITTLE_ENDIAN
+# endif
+#endif
+#if !defined(BYTE_ORDER) || !defined(BIG_ENDIAN)
+# error "Cannot determine byte order"
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+#  include <ndir.h>
+# endif
+#endif
+
+#if HAVE_STDARG_H
+# include <stdarg.h>
+#endif
+#if HAVE_CTYPE_H
+# include <ctype.h>
+#endif
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
+#ifndef PACKAGE_NAME
+#define PACKAGE_NAME "collectd"
+#endif
+
+#ifndef PREFIX
+#define PREFIX "/opt/" PACKAGE_NAME
+#endif
+
+#ifndef SYSCONFDIR
+#define SYSCONFDIR PREFIX "/etc"
+#endif
+
+#ifndef CONFIGFILE
+#define CONFIGFILE SYSCONFDIR"/collectd.conf"
+#endif
+
+#ifndef LOCALSTATEDIR
+#define LOCALSTATEDIR PREFIX "/var"
+#endif
+
+#ifndef PKGLOCALSTATEDIR
+#define PKGLOCALSTATEDIR PREFIX "/var/lib/" PACKAGE_NAME
+#endif
+
+#ifndef PIDFILE
+#define PIDFILE PREFIX "/var/run/" PACKAGE_NAME ".pid"
+#endif
+
+#ifndef PLUGINDIR
+#define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
+#endif
+
+#ifndef PKGDATADIR
+#define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
+#endif
+
+#ifndef COLLECTD_GRP_NAME
+# define COLLECTD_GRP_NAME "collectd"
+#endif
+
+#ifndef COLLECTD_DEFAULT_INTERVAL
+# define COLLECTD_DEFAULT_INTERVAL 10.0
+#endif
+
+ #ifndef COLLECTD_USERAGENT
+ # define COLLECTD_USERAGENT PACKAGE_NAME"/"PACKAGE_VERSION
+ #endif
+
+/* Only enable __attribute__() for compilers known to support it. */
+#if defined(__clang__)
+# define clang_attr(x) __attribute__(x)
+# define gcc_attr(x) /**/
+#elif __GNUC__
+# define clang_attr(x) /**/
+# define gcc_attr(x) __attribute__(x)
+#else
+# define clang_attr(x) /**/
+# define gcc_attr(x) /**/
+# define __attribute__(x) /**/
+#endif
+
+#if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
+# undef strcpy
+# undef strcat
+# undef strtok
+# pragma GCC poison strcpy strcat strtok
+#endif
+
+/* 
+ * Special hack for the perl plugin: Because the later included perl.h defines
+ * a macro which is never used, but contains `sprintf', we cannot poison that
+ * identifies just yet. The parl plugin will do that itself once perl.h is
+ * included.
+ */
+#ifndef DONT_POISON_SPRINTF_YET
+# if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
+#  undef sprintf
+#  pragma GCC poison sprintf
+# endif
+#endif
+
+#ifndef GAUGE_FORMAT
+# define GAUGE_FORMAT "%.15g"
+#endif
+
+/* Type for time as used by "utils_time.h" */
+typedef uint64_t cdtime_t;
+
+extern char     hostname_g[];
+extern cdtime_t interval_g;
+extern int      pidfile_from_cli;
+extern int      timeout_g;
+
+#endif /* COLLECTD_H */
diff --git a/src/daemon/common.c b/src/daemon/common.c
new file mode 100644 (file)
index 0000000..e396b79
--- /dev/null
@@ -0,0 +1,1649 @@
+/**
+ * collectd - src/common.c
+ * Copyright (C) 2005-2014  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Niki W. Waibel <niki.waibel@gmx.net>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Michał Mirosław <mirq-linux at rere.qmqm.pl>
+**/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_cache.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+#ifdef HAVE_MATH_H
+# include <math.h>
+#endif
+
+/* for getaddrinfo */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+/* for ntohl and htonl */
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_LIBKSTAT
+extern kstat_ctl_t *kc;
+#endif
+
+#if !HAVE_GETPWNAM_R
+static pthread_mutex_t getpwnam_r_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#if !HAVE_STRERROR_R
+static pthread_mutex_t strerror_r_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+char *sstrncpy (char *dest, const char *src, size_t n)
+{
+       strncpy (dest, src, n);
+       dest[n - 1] = '\0';
+
+       return (dest);
+} /* char *sstrncpy */
+
+int ssnprintf (char *dest, size_t n, const char *format, ...)
+{
+       int ret = 0;
+       va_list ap;
+
+       va_start (ap, format);
+       ret = vsnprintf (dest, n, format, ap);
+       dest[n - 1] = '\0';
+       va_end (ap);
+
+       return (ret);
+} /* int ssnprintf */
+
+char *ssnprintf_alloc (char const *format, ...) /* {{{ */
+{
+       char static_buffer[1024] = "";
+       char *alloc_buffer;
+       size_t alloc_buffer_size;
+       int status;
+       va_list ap;
+
+       /* Try printing into the static buffer. In many cases it will be
+        * sufficiently large and we can simply return a strdup() of this
+        * buffer. */
+       va_start (ap, format);
+       status = vsnprintf (static_buffer, sizeof (static_buffer), format, ap);
+       va_end (ap);
+       if (status < 0)
+               return (NULL);
+
+       /* "status" does not include the null byte. */
+       alloc_buffer_size = (size_t) (status + 1);
+       if (alloc_buffer_size <= sizeof (static_buffer))
+               return (strdup (static_buffer));
+
+       /* Allocate a buffer large enough to hold the string. */
+       alloc_buffer = malloc (alloc_buffer_size);
+       if (alloc_buffer == NULL)
+               return (NULL);
+       memset (alloc_buffer, 0, alloc_buffer_size);
+
+       /* Print again into this new buffer. */
+       va_start (ap, format);
+       status = vsnprintf (alloc_buffer, alloc_buffer_size, format, ap);
+       va_end (ap);
+       if (status < 0)
+       {
+               sfree (alloc_buffer);
+               return (NULL);
+       }
+
+       return (alloc_buffer);
+} /* }}} char *ssnprintf_alloc */
+
+char *sstrdup (const char *s)
+{
+       char *r;
+       size_t sz;
+
+       if (s == NULL)
+               return (NULL);
+
+       /* Do not use `strdup' here, because it's not specified in POSIX. It's
+        * ``only'' an XSI extension. */
+       sz = strlen (s) + 1;
+       r = (char *) malloc (sizeof (char) * sz);
+       if (r == NULL)
+       {
+               ERROR ("sstrdup: Out of memory.");
+               exit (3);
+       }
+       memcpy (r, s, sizeof (char) * sz);
+
+       return (r);
+} /* char *sstrdup */
+
+/* Even though Posix requires "strerror_r" to return an "int",
+ * some systems (e.g. the GNU libc) return a "char *" _and_
+ * ignore the second argument ... -tokkee */
+char *sstrerror (int errnum, char *buf, size_t buflen)
+{
+       buf[0] = '\0';
+
+#if !HAVE_STRERROR_R
+       {
+               char *temp;
+
+               pthread_mutex_lock (&strerror_r_lock);
+
+               temp = strerror (errnum);
+               sstrncpy (buf, temp, buflen);
+
+               pthread_mutex_unlock (&strerror_r_lock);
+       }
+/* #endif !HAVE_STRERROR_R */
+
+#elif STRERROR_R_CHAR_P
+       {
+               char *temp;
+               temp = strerror_r (errnum, buf, buflen);
+               if (buf[0] == '\0')
+               {
+                       if ((temp != NULL) && (temp != buf) && (temp[0] != '\0'))
+                               sstrncpy (buf, temp, buflen);
+                       else
+                               sstrncpy (buf, "strerror_r did not return "
+                                               "an error message", buflen);
+               }
+       }
+/* #endif STRERROR_R_CHAR_P */
+
+#else
+       if (strerror_r (errnum, buf, buflen) != 0)
+       {
+               ssnprintf (buf, buflen, "Error #%i; "
+                               "Additionally, strerror_r failed.",
+                               errnum);
+       }
+#endif /* STRERROR_R_CHAR_P */
+
+       return (buf);
+} /* char *sstrerror */
+
+void *smalloc (size_t size)
+{
+       void *r;
+
+       if ((r = malloc (size)) == NULL)
+       {
+               ERROR ("Not enough memory.");
+               exit (3);
+       }
+
+       return (r);
+} /* void *smalloc */
+
+#if 0
+void sfree (void **ptr)
+{
+       if (ptr == NULL)
+               return;
+
+       if (*ptr != NULL)
+               free (*ptr);
+
+       *ptr = NULL;
+}
+#endif
+
+ssize_t sread (int fd, void *buf, size_t count)
+{
+       char    *ptr;
+       size_t   nleft;
+       ssize_t  status;
+
+       ptr   = (char *) buf;
+       nleft = count;
+
+       while (nleft > 0)
+       {
+               status = read (fd, (void *) ptr, nleft);
+
+               if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+                       continue;
+
+               if (status < 0)
+                       return (status);
+
+               if (status == 0)
+               {
+                       DEBUG ("Received EOF from fd %i. "
+                                       "Closing fd and returning error.",
+                                       fd);
+                       close (fd);
+                       return (-1);
+               }
+
+               assert ((0 > status) || (nleft >= (size_t)status));
+
+               nleft = nleft - status;
+               ptr   = ptr   + status;
+       }
+
+       return (0);
+}
+
+
+ssize_t swrite (int fd, const void *buf, size_t count)
+{
+       const char *ptr;
+       size_t      nleft;
+       ssize_t     status;
+
+       ptr   = (const char *) buf;
+       nleft = count;
+
+       while (nleft > 0)
+       {
+               status = write (fd, (const void *) ptr, nleft);
+
+               if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+                       continue;
+
+               if (status < 0)
+                       return (status);
+
+               nleft = nleft - status;
+               ptr   = ptr   + status;
+       }
+
+       return (0);
+}
+
+int strsplit (char *string, char **fields, size_t size)
+{
+       size_t i;
+       char *ptr;
+       char *saveptr;
+
+       i = 0;
+       ptr = string;
+       saveptr = NULL;
+       while ((fields[i] = strtok_r (ptr, " \t\r\n", &saveptr)) != NULL)
+       {
+               ptr = NULL;
+               i++;
+
+               if (i >= size)
+                       break;
+       }
+
+       return ((int) i);
+}
+
+int strjoin (char *dst, size_t dst_len,
+               char **fields, size_t fields_num,
+               const char *sep)
+{
+       size_t field_len;
+       size_t sep_len;
+       int i;
+
+       memset (dst, '\0', dst_len);
+
+       if (fields_num <= 0)
+               return (-1);
+
+       sep_len = 0;
+       if (sep != NULL)
+               sep_len = strlen (sep);
+
+       for (i = 0; i < (int)fields_num; i++)
+       {
+               if ((i > 0) && (sep_len > 0))
+               {
+                       if (dst_len <= sep_len)
+                               return (-1);
+
+                       strncat (dst, sep, dst_len);
+                       dst_len -= sep_len;
+               }
+
+               field_len = strlen (fields[i]);
+
+               if (dst_len <= field_len)
+                       return (-1);
+
+               strncat (dst, fields[i], dst_len);
+               dst_len -= field_len;
+       }
+
+       return (strlen (dst));
+}
+
+int strsubstitute (char *str, char c_from, char c_to)
+{
+       int ret;
+
+       if (str == NULL)
+               return (-1);
+
+       ret = 0;
+       while (*str != '\0')
+       {
+               if (*str == c_from)
+               {
+                       *str = c_to;
+                       ret++;
+               }
+               str++;
+       }
+
+       return (ret);
+} /* int strsubstitute */
+
+int escape_string (char *buffer, size_t buffer_size)
+{
+  char *temp;
+  size_t i;
+  size_t j;
+
+  /* Check if we need to escape at all first */
+  temp = strpbrk (buffer, " \t\"\\");
+  if (temp == NULL)
+    return (0);
+
+  if (buffer_size < 3)
+    return (EINVAL);
+
+  temp = (char *) malloc (buffer_size);
+  if (temp == NULL)
+    return (ENOMEM);
+  memset (temp, 0, buffer_size);
+
+  temp[0] = '"';
+  j = 1;
+
+  for (i = 0; i < buffer_size; i++)
+  {
+    if (buffer[i] == 0)
+    {
+      break;
+    }
+    else if ((buffer[i] == '"') || (buffer[i] == '\\'))
+    {
+      if (j > (buffer_size - 4))
+        break;
+      temp[j] = '\\';
+      temp[j + 1] = buffer[i];
+      j += 2;
+    }
+    else
+    {
+      if (j > (buffer_size - 3))
+        break;
+      temp[j] = buffer[i];
+      j++;
+    }
+  }
+
+  assert ((j + 1) < buffer_size);
+  temp[j] = '"';
+  temp[j + 1] = 0;
+
+  sstrncpy (buffer, temp, buffer_size);
+  sfree (temp);
+  return (0);
+} /* int escape_string */
+
+int strunescape (char *buf, size_t buf_len)
+{
+       size_t i;
+
+       for (i = 0; (i < buf_len) && (buf[i] != '\0'); ++i)
+       {
+               if (buf[i] != '\\')
+                       continue;
+
+               if (((i + 1) >= buf_len) || (buf[i + 1] == 0)) {
+                       ERROR ("string unescape: backslash found at end of string.");
+                       /* Ensure null-byte at the end of the buffer. */
+                       buf[i] = 0;
+                       return (-1);
+               }
+
+               switch (buf[i + 1]) {
+                       case 't':
+                               buf[i] = '\t';
+                               break;
+                       case 'n':
+                               buf[i] = '\n';
+                               break;
+                       case 'r':
+                               buf[i] = '\r';
+                               break;
+                       default:
+                               buf[i] = buf[i + 1];
+                               break;
+               }
+
+               /* Move everything after the position one position to the left.
+                * Add a null-byte as last character in the buffer. */
+               memmove (buf + i + 1, buf + i + 2, buf_len - i - 2);
+               buf[buf_len - 1] = 0;
+       }
+       return (0);
+} /* int strunescape */
+
+size_t strstripnewline (char *buffer)
+{
+       size_t buffer_len = strlen (buffer);
+
+       while (buffer_len > 0)
+       {
+               if ((buffer[buffer_len - 1] != '\n')
+                               && (buffer[buffer_len - 1] != '\r'))
+                       break;
+               buffer_len--;
+               buffer[buffer_len] = 0;
+       }
+
+       return (buffer_len);
+} /* size_t strstripnewline */
+
+int escape_slashes (char *buffer, size_t buffer_size)
+{
+       int i;
+       size_t buffer_len;
+
+       buffer_len = strlen (buffer);
+
+       if (buffer_len <= 1)
+       {
+               if (strcmp ("/", buffer) == 0)
+               {
+                       if (buffer_size < 5)
+                               return (-1);
+                       sstrncpy (buffer, "root", buffer_size);
+               }
+               return (0);
+       }
+
+       /* Move one to the left */
+       if (buffer[0] == '/')
+       {
+               memmove (buffer, buffer + 1, buffer_len);
+               buffer_len--;
+       }
+
+       for (i = 0; i < buffer_len - 1; i++)
+       {
+               if (buffer[i] == '/')
+                       buffer[i] = '_';
+       }
+
+       return (0);
+} /* int escape_slashes */
+
+void replace_special (char *buffer, size_t buffer_size)
+{
+       size_t i;
+
+       for (i = 0; i < buffer_size; i++)
+       {
+               if (buffer[i] == 0)
+                       return;
+               if ((!isalnum ((int) buffer[i])) && (buffer[i] != '-'))
+                       buffer[i] = '_';
+       }
+} /* void replace_special */
+
+int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta)
+{
+       struct timeval *larger;
+       struct timeval *smaller;
+
+       int status;
+
+       NORMALIZE_TIMEVAL (tv0);
+       NORMALIZE_TIMEVAL (tv1);
+
+       if ((tv0.tv_sec == tv1.tv_sec) && (tv0.tv_usec == tv1.tv_usec))
+       {
+               if (delta != NULL) {
+                       delta->tv_sec  = 0;
+                       delta->tv_usec = 0;
+               }
+               return (0);
+       }
+
+       if ((tv0.tv_sec < tv1.tv_sec)
+                       || ((tv0.tv_sec == tv1.tv_sec) && (tv0.tv_usec < tv1.tv_usec)))
+       {
+               larger  = &tv1;
+               smaller = &tv0;
+               status  = -1;
+       }
+       else
+       {
+               larger  = &tv0;
+               smaller = &tv1;
+               status  = 1;
+       }
+
+       if (delta != NULL) {
+               delta->tv_sec = larger->tv_sec - smaller->tv_sec;
+
+               if (smaller->tv_usec <= larger->tv_usec)
+                       delta->tv_usec = larger->tv_usec - smaller->tv_usec;
+               else
+               {
+                       --delta->tv_sec;
+                       delta->tv_usec = 1000000 + larger->tv_usec - smaller->tv_usec;
+               }
+       }
+
+       assert ((delta == NULL)
+                       || ((0 <= delta->tv_usec) && (delta->tv_usec < 1000000)));
+
+       return (status);
+} /* int timeval_cmp */
+
+int check_create_dir (const char *file_orig)
+{
+       struct stat statbuf;
+
+       char  file_copy[512];
+       char  dir[512];
+       int   dir_len = 512;
+       char *fields[16];
+       int   fields_num;
+       char *ptr;
+       char *saveptr;
+       int   last_is_file = 1;
+       int   path_is_absolute = 0;
+       size_t len;
+       int   i;
+
+       /*
+        * Sanity checks first
+        */
+       if (file_orig == NULL)
+               return (-1);
+
+       if ((len = strlen (file_orig)) < 1)
+               return (-1);
+       else if (len >= sizeof (file_copy))
+               return (-1);
+
+       /*
+        * If `file_orig' ends in a slash the last component is a directory,
+        * otherwise it's a file. Act accordingly..
+        */
+       if (file_orig[len - 1] == '/')
+               last_is_file = 0;
+       if (file_orig[0] == '/')
+               path_is_absolute = 1;
+
+       /*
+        * Create a copy for `strtok_r' to destroy
+        */
+       sstrncpy (file_copy, file_orig, sizeof (file_copy));
+
+       /*
+        * Break into components. This will eat up several slashes in a row and
+        * remove leading and trailing slashes..
+        */
+       ptr = file_copy;
+       saveptr = NULL;
+       fields_num = 0;
+       while ((fields[fields_num] = strtok_r (ptr, "/", &saveptr)) != NULL)
+       {
+               ptr = NULL;
+               fields_num++;
+
+               if (fields_num >= 16)
+                       break;
+       }
+
+       /*
+        * For each component, do..
+        */
+       for (i = 0; i < (fields_num - last_is_file); i++)
+       {
+               /*
+                * Do not create directories that start with a dot. This
+                * prevents `../../' attacks and other likely malicious
+                * behavior.
+                */
+               if (fields[i][0] == '.')
+               {
+                       ERROR ("Cowardly refusing to create a directory that "
+                                       "begins with a `.' (dot): `%s'", file_orig);
+                       return (-2);
+               }
+
+               /*
+                * Join the components together again
+                */
+               dir[0] = '/';
+               if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute,
+                                       fields, i + 1, "/") < 0)
+               {
+                       ERROR ("strjoin failed: `%s', component #%i", file_orig, i);
+                       return (-1);
+               }
+
+               while (42) {
+                       if ((stat (dir, &statbuf) == -1)
+                                       && (lstat (dir, &statbuf) == -1))
+                       {
+                               if (errno == ENOENT)
+                               {
+                                       if (mkdir (dir, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
+                                               break;
+
+                                       /* this might happen, if a different thread created
+                                        * the directory in the meantime
+                                        * => call stat() again to check for S_ISDIR() */
+                                       if (EEXIST == errno)
+                                               continue;
+
+                                       char errbuf[1024];
+                                       ERROR ("check_create_dir: mkdir (%s): %s", dir,
+                                                       sstrerror (errno,
+                                                               errbuf, sizeof (errbuf)));
+                                       return (-1);
+                               }
+                               else
+                               {
+                                       char errbuf[1024];
+                                       ERROR ("check_create_dir: stat (%s): %s", dir,
+                                                       sstrerror (errno, errbuf,
+                                                               sizeof (errbuf)));
+                                       return (-1);
+                               }
+                       }
+                       else if (!S_ISDIR (statbuf.st_mode))
+                       {
+                               ERROR ("check_create_dir: `%s' exists but is not "
+                                               "a directory!", dir);
+                               return (-1);
+                       }
+                       break;
+               }
+       }
+
+       return (0);
+} /* check_create_dir */
+
+#ifdef HAVE_LIBKSTAT
+int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
+{
+       char ident[128];
+
+       *ksp_ptr = NULL;
+
+       if (kc == NULL)
+               return (-1);
+
+       ssnprintf (ident, sizeof (ident), "%s,%i,%s", module, instance, name);
+
+       *ksp_ptr = kstat_lookup (kc, module, instance, name);
+       if (*ksp_ptr == NULL)
+       {
+               ERROR ("get_kstat: Cound not find kstat %s", ident);
+               return (-1);
+       }
+
+       if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
+       {
+               ERROR ("get_kstat: kstat %s has wrong type", ident);
+               *ksp_ptr = NULL;
+               return (-1);
+       }
+
+#ifdef assert
+       assert (*ksp_ptr != NULL);
+       assert ((*ksp_ptr)->ks_type == KSTAT_TYPE_NAMED);
+#endif
+
+       if (kstat_read (kc, *ksp_ptr, NULL) == -1)
+       {
+               ERROR ("get_kstat: kstat %s could not be read", ident);
+               return (-1);
+       }
+
+       if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED)
+       {
+               ERROR ("get_kstat: kstat %s has wrong type", ident);
+               return (-1);
+       }
+
+       return (0);
+}
+
+long long get_kstat_value (kstat_t *ksp, char *name)
+{
+       kstat_named_t *kn;
+       long long retval = -1LL;
+
+       if (ksp == NULL)
+       {
+               ERROR ("get_kstat_value (\"%s\"): ksp is NULL.", name);
+               return (-1LL);
+       }
+       else if (ksp->ks_type != KSTAT_TYPE_NAMED)
+       {
+               ERROR ("get_kstat_value (\"%s\"): ksp->ks_type (%#x) "
+                               "is not KSTAT_TYPE_NAMED (%#x).",
+                               name,
+                               (unsigned int) ksp->ks_type,
+                               (unsigned int) KSTAT_TYPE_NAMED);
+               return (-1LL);
+       }
+
+       if ((kn = (kstat_named_t *) kstat_data_lookup (ksp, name)) == NULL)
+               return (-1LL);
+
+       if (kn->data_type == KSTAT_DATA_INT32)
+               retval = (long long) kn->value.i32;
+       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 */
+       else if (kn->data_type == KSTAT_DATA_UINT64)
+               retval = (long long) kn->value.ui64; /* XXX: Might overflow! */
+       else
+               WARNING ("get_kstat_value: Not a numeric value: %s", name);
+
+       return (retval);
+}
+#endif /* HAVE_LIBKSTAT */
+
+#ifndef HAVE_HTONLL
+unsigned long long ntohll (unsigned long long n)
+{
+#if BYTE_ORDER == BIG_ENDIAN
+       return (n);
+#else
+       return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
+#endif
+} /* unsigned long long ntohll */
+
+unsigned long long htonll (unsigned long long n)
+{
+#if BYTE_ORDER == BIG_ENDIAN
+       return (n);
+#else
+       return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
+#endif
+} /* unsigned long long htonll */
+#endif /* HAVE_HTONLL */
+
+#if 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
+#  define FP_CONVERT(A) ((((uint64_t)(A) & 0xff00000000000000LL) >> 56) | \
+                         (((uint64_t)(A) & 0x00ff000000000000LL) >> 40) | \
+                         (((uint64_t)(A) & 0x0000ff0000000000LL) >> 24) | \
+                         (((uint64_t)(A) & 0x000000ff00000000LL) >> 8)  | \
+                         (((uint64_t)(A) & 0x00000000ff000000LL) << 8)  | \
+                         (((uint64_t)(A) & 0x0000000000ff0000LL) << 24) | \
+                         (((uint64_t)(A) & 0x000000000000ff00LL) << 40) | \
+                         (((uint64_t)(A) & 0x00000000000000ffLL) << 56))
+# else
+#  define FP_CONVERT(A) ((((uint64_t)(A) & 0xffffffff00000000LL) >> 32) | \
+                         (((uint64_t)(A) & 0x00000000ffffffffLL) << 32))
+# endif
+
+double ntohd (double d)
+{
+       union
+       {
+               uint8_t  byte[8];
+               uint64_t integer;
+               double   floating;
+       } ret;
+
+       ret.floating = d;
+
+       /* NAN in x86 byte order */
+       if ((ret.byte[0] == 0x00) && (ret.byte[1] == 0x00)
+                       && (ret.byte[2] == 0x00) && (ret.byte[3] == 0x00)
+                       && (ret.byte[4] == 0x00) && (ret.byte[5] == 0x00)
+                       && (ret.byte[6] == 0xf8) && (ret.byte[7] == 0x7f))
+       {
+               return (NAN);
+       }
+       else
+       {
+               uint64_t tmp;
+
+               tmp = ret.integer;
+               ret.integer = FP_CONVERT (tmp);
+               return (ret.floating);
+       }
+} /* double ntohd */
+
+double htond (double d)
+{
+       union
+       {
+               uint8_t  byte[8];
+               uint64_t integer;
+               double   floating;
+       } ret;
+
+       if (isnan (d))
+       {
+               ret.byte[0] = ret.byte[1] = ret.byte[2] = ret.byte[3] = 0x00;
+               ret.byte[4] = ret.byte[5] = 0x00;
+               ret.byte[6] = 0xf8;
+               ret.byte[7] = 0x7f;
+               return (ret.floating);
+       }
+       else
+       {
+               uint64_t tmp;
+
+               ret.floating = d;
+               tmp = FP_CONVERT (ret.integer);
+               ret.integer = tmp;
+               return (ret.floating);
+       }
+} /* double htond */
+#endif /* FP_LAYOUT_NEED_ENDIANFLIP || FP_LAYOUT_NEED_INTSWAP */
+
+int format_name (char *ret, int ret_len,
+               const char *hostname,
+               const char *plugin, const char *plugin_instance,
+               const char *type, const char *type_instance)
+{
+  char *buffer;
+  size_t buffer_size;
+
+  buffer = ret;
+  buffer_size = (size_t) ret_len;
+
+#define APPEND(str) do {                                               \
+  size_t l = strlen (str);                                             \
+  if (l >= buffer_size)                                                \
+    return (ENOBUFS);                                                  \
+  memcpy (buffer, (str), l);                                           \
+  buffer += l; buffer_size -= l;                                       \
+} while (0)
+
+  assert (plugin != NULL);
+  assert (type != NULL);
+
+  APPEND (hostname);
+  APPEND ("/");
+  APPEND (plugin);
+  if ((plugin_instance != NULL) && (plugin_instance[0] != 0))
+  {
+    APPEND ("-");
+    APPEND (plugin_instance);
+  }
+  APPEND ("/");
+  APPEND (type);
+  if ((type_instance != NULL) && (type_instance[0] != 0))
+  {
+    APPEND ("-");
+    APPEND (type_instance);
+  }
+  assert (buffer_size > 0);
+  buffer[0] = 0;
+
+#undef APPEND
+  return (0);
+} /* int format_name */
+
+int format_values (char *ret, size_t ret_len, /* {{{ */
+               const data_set_t *ds, const value_list_t *vl,
+               _Bool store_rates)
+{
+        size_t offset = 0;
+        int status;
+        int i;
+        gauge_t *rates = NULL;
+
+        assert (0 == strcmp (ds->type, vl->type));
+
+        memset (ret, 0, ret_len);
+
+#define BUFFER_ADD(...) do { \
+        status = ssnprintf (ret + offset, ret_len - offset, \
+                        __VA_ARGS__); \
+        if (status < 1) \
+        { \
+                sfree (rates); \
+                return (-1); \
+        } \
+        else if (((size_t) status) >= (ret_len - offset)) \
+        { \
+                sfree (rates); \
+                return (-1); \
+        } \
+        else \
+                offset += ((size_t) status); \
+} while (0)
+
+        BUFFER_ADD ("%.3f", CDTIME_T_TO_DOUBLE (vl->time));
+
+        for (i = 0; i < ds->ds_num; i++)
+        {
+                if (ds->ds[i].type == DS_TYPE_GAUGE)
+                        BUFFER_ADD (":"GAUGE_FORMAT, vl->values[i].gauge);
+                else if (store_rates)
+                {
+                        if (rates == NULL)
+                                rates = uc_get_rate (ds, vl);
+                        if (rates == NULL)
+                        {
+                                WARNING ("format_values: uc_get_rate failed.");
+                                return (-1);
+                        }
+                        BUFFER_ADD (":"GAUGE_FORMAT, rates[i]);
+                }
+                else if (ds->ds[i].type == DS_TYPE_COUNTER)
+                        BUFFER_ADD (":%llu", vl->values[i].counter);
+                else if (ds->ds[i].type == DS_TYPE_DERIVE)
+                        BUFFER_ADD (":%"PRIi64, vl->values[i].derive);
+                else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+                        BUFFER_ADD (":%"PRIu64, vl->values[i].absolute);
+                else
+                {
+                        ERROR ("format_values: Unknown data source type: %i",
+                                        ds->ds[i].type);
+                        sfree (rates);
+                        return (-1);
+                }
+        } /* for ds->ds_num */
+
+#undef BUFFER_ADD
+
+        sfree (rates);
+        return (0);
+} /* }}} int format_values */
+
+int parse_identifier (char *str, char **ret_host,
+               char **ret_plugin, char **ret_plugin_instance,
+               char **ret_type, char **ret_type_instance)
+{
+       char *hostname = NULL;
+       char *plugin = NULL;
+       char *plugin_instance = NULL;
+       char *type = NULL;
+       char *type_instance = NULL;
+
+       hostname = str;
+       if (hostname == NULL)
+               return (-1);
+
+       plugin = strchr (hostname, '/');
+       if (plugin == NULL)
+               return (-1);
+       *plugin = '\0'; plugin++;
+
+       type = strchr (plugin, '/');
+       if (type == NULL)
+               return (-1);
+       *type = '\0'; type++;
+
+       plugin_instance = strchr (plugin, '-');
+       if (plugin_instance != NULL)
+       {
+               *plugin_instance = '\0';
+               plugin_instance++;
+       }
+
+       type_instance = strchr (type, '-');
+       if (type_instance != NULL)
+       {
+               *type_instance = '\0';
+               type_instance++;
+       }
+
+       *ret_host = hostname;
+       *ret_plugin = plugin;
+       *ret_plugin_instance = plugin_instance;
+       *ret_type = type;
+       *ret_type_instance = type_instance;
+       return (0);
+} /* int parse_identifier */
+
+int parse_identifier_vl (const char *str, value_list_t *vl) /* {{{ */
+{
+       char str_copy[6 * DATA_MAX_NAME_LEN];
+       char *host = NULL;
+       char *plugin = NULL;
+       char *plugin_instance = NULL;
+       char *type = NULL;
+       char *type_instance = NULL;
+       int status;
+
+       if ((str == NULL) || (vl == NULL))
+               return (EINVAL);
+
+       sstrncpy (str_copy, str, sizeof (str_copy));
+
+       status = parse_identifier (str_copy, &host,
+                       &plugin, &plugin_instance,
+                       &type, &type_instance);
+       if (status != 0)
+               return (status);
+
+       sstrncpy (vl->host, host, sizeof (vl->host));
+       sstrncpy (vl->plugin, plugin, sizeof (vl->plugin));
+       sstrncpy (vl->plugin_instance,
+                       (plugin_instance != NULL) ? plugin_instance : "",
+                       sizeof (vl->plugin_instance));
+       sstrncpy (vl->type, type, sizeof (vl->type));
+       sstrncpy (vl->type_instance,
+                       (type_instance != NULL) ? type_instance : "",
+                       sizeof (vl->type_instance));
+
+       return (0);
+} /* }}} int parse_identifier_vl */
+
+int parse_value (const char *value_orig, value_t *ret_value, int ds_type)
+{
+  char *value;
+  char *endptr = NULL;
+  size_t value_len;
+
+  if (value_orig == NULL)
+    return (EINVAL);
+
+  value = strdup (value_orig);
+  if (value == NULL)
+    return (ENOMEM);
+  value_len = strlen (value);
+
+  while ((value_len > 0) && isspace ((int) value[value_len - 1]))
+  {
+    value[value_len - 1] = 0;
+    value_len--;
+  }
+
+  switch (ds_type)
+  {
+    case DS_TYPE_COUNTER:
+      ret_value->counter = (counter_t) strtoull (value, &endptr, 0);
+      break;
+
+    case DS_TYPE_GAUGE:
+      ret_value->gauge = (gauge_t) strtod (value, &endptr);
+      break;
+
+    case DS_TYPE_DERIVE:
+      ret_value->derive = (derive_t) strtoll (value, &endptr, 0);
+      break;
+
+    case DS_TYPE_ABSOLUTE:
+      ret_value->absolute = (absolute_t) strtoull (value, &endptr, 0);
+      break;
+
+    default:
+      sfree (value);
+      ERROR ("parse_value: Invalid data source type: %i.", ds_type);
+      return -1;
+  }
+
+  if (value == endptr) {
+    ERROR ("parse_value: Failed to parse string as %s: %s.",
+        DS_TYPE_TO_STRING (ds_type), value);
+    sfree (value);
+    return -1;
+  }
+  else if ((NULL != endptr) && ('\0' != *endptr))
+    INFO ("parse_value: Ignoring trailing garbage \"%s\" after %s value. "
+        "Input string was \"%s\".",
+        endptr, DS_TYPE_TO_STRING (ds_type), value_orig);
+
+  sfree (value);
+  return 0;
+} /* int parse_value */
+
+int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
+{
+       int i;
+       char *dummy;
+       char *ptr;
+       char *saveptr;
+
+       i = -1;
+       dummy = buffer;
+       saveptr = NULL;
+       while ((ptr = strtok_r (dummy, ":", &saveptr)) != NULL)
+       {
+               dummy = NULL;
+
+               if (i >= vl->values_len)
+               {
+                       /* Make sure i is invalid. */
+                       i = vl->values_len + 1;
+                       break;
+               }
+
+               if (i == -1)
+               {
+                       if (strcmp ("N", ptr) == 0)
+                               vl->time = cdtime ();
+                       else
+                       {
+                               char *endptr = NULL;
+                               double tmp;
+
+                               errno = 0;
+                               tmp = strtod (ptr, &endptr);
+                               if ((errno != 0)                    /* Overflow */
+                                               || (endptr == ptr)  /* Invalid string */
+                                               || (endptr == NULL) /* This should not happen */
+                                               || (*endptr != 0))  /* Trailing chars */
+                                       return (-1);
+
+                               vl->time = DOUBLE_TO_CDTIME_T (tmp);
+                       }
+               }
+               else
+               {
+                       if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
+                               vl->values[i].gauge = NAN;
+                       else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
+                               return -1;
+               }
+
+               i++;
+       } /* while (strtok_r) */
+
+       if ((ptr != NULL) || (i != vl->values_len))
+               return (-1);
+       return (0);
+} /* int parse_values */
+
+#if !HAVE_GETPWNAM_R
+int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf,
+               size_t buflen, struct passwd **pwbufp)
+{
+       int status = 0;
+       struct passwd *pw;
+
+       memset (pwbuf, '\0', sizeof (struct passwd));
+
+       pthread_mutex_lock (&getpwnam_r_lock);
+
+       do
+       {
+               pw = getpwnam (name);
+               if (pw == NULL)
+               {
+                       status = (errno != 0) ? errno : ENOENT;
+                       break;
+               }
+
+#define GETPWNAM_COPY_MEMBER(member) \
+               if (pw->member != NULL) \
+               { \
+                       int len = strlen (pw->member); \
+                       if (len >= buflen) \
+                       { \
+                               status = ENOMEM; \
+                               break; \
+                       } \
+                       sstrncpy (buf, pw->member, buflen); \
+                       pwbuf->member = buf; \
+                       buf    += (len + 1); \
+                       buflen -= (len + 1); \
+               }
+               GETPWNAM_COPY_MEMBER(pw_name);
+               GETPWNAM_COPY_MEMBER(pw_passwd);
+               GETPWNAM_COPY_MEMBER(pw_gecos);
+               GETPWNAM_COPY_MEMBER(pw_dir);
+               GETPWNAM_COPY_MEMBER(pw_shell);
+
+               pwbuf->pw_uid = pw->pw_uid;
+               pwbuf->pw_gid = pw->pw_gid;
+
+               if (pwbufp != NULL)
+                       *pwbufp = pwbuf;
+       } while (0);
+
+       pthread_mutex_unlock (&getpwnam_r_lock);
+
+       return (status);
+} /* int getpwnam_r */
+#endif /* !HAVE_GETPWNAM_R */
+
+int notification_init (notification_t *n, int severity, const char *message,
+               const char *host,
+               const char *plugin, const char *plugin_instance,
+               const char *type, const char *type_instance)
+{
+       memset (n, '\0', sizeof (notification_t));
+
+       n->severity = severity;
+
+       if (message != NULL)
+               sstrncpy (n->message, message, sizeof (n->message));
+       if (host != NULL)
+               sstrncpy (n->host, host, sizeof (n->host));
+       if (plugin != NULL)
+               sstrncpy (n->plugin, plugin, sizeof (n->plugin));
+       if (plugin_instance != NULL)
+               sstrncpy (n->plugin_instance, plugin_instance,
+                               sizeof (n->plugin_instance));
+       if (type != NULL)
+               sstrncpy (n->type, type, sizeof (n->type));
+       if (type_instance != NULL)
+               sstrncpy (n->type_instance, type_instance,
+                               sizeof (n->type_instance));
+
+       return (0);
+} /* int notification_init */
+
+int walk_directory (const char *dir, dirwalk_callback_f callback,
+               void *user_data, int include_hidden)
+{
+       struct dirent *ent;
+       DIR *dh;
+       int success;
+       int failure;
+
+       success = 0;
+       failure = 0;
+
+       if ((dh = opendir (dir)) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("walk_directory: Cannot open '%s': %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       while ((ent = readdir (dh)) != NULL)
+       {
+               int status;
+
+               if (include_hidden)
+               {
+                       if ((strcmp (".", ent->d_name) == 0)
+                                       || (strcmp ("..", ent->d_name) == 0))
+                               continue;
+               }
+               else /* if (!include_hidden) */
+               {
+                       if (ent->d_name[0]=='.')
+                               continue;
+               }
+
+               status = (*callback) (dir, ent->d_name, user_data);
+               if (status != 0)
+                       failure++;
+               else
+                       success++;
+       }
+
+       closedir (dh);
+
+       if ((success == 0) && (failure > 0))
+               return (-1);
+       return (0);
+}
+
+ssize_t read_file_contents (const char *filename, char *buf, size_t bufsize)
+{
+       FILE *fh;
+       ssize_t ret;
+
+       fh = fopen (filename, "r");
+       if (fh == NULL)
+               return (-1);
+
+       ret = (ssize_t) fread (buf, 1, bufsize, fh);
+       if ((ret == 0) && (ferror (fh) != 0))
+       {
+               ERROR ("read_file_contents: Reading file \"%s\" failed.",
+                               filename);
+               ret = -1;
+       }
+
+       fclose(fh);
+       return (ret);
+}
+
+counter_t counter_diff (counter_t old_value, counter_t new_value)
+{
+       counter_t diff;
+
+       if (old_value > new_value)
+       {
+               if (old_value <= 4294967295U)
+                       diff = (4294967295U - old_value) + new_value;
+               else
+                       diff = (18446744073709551615ULL - old_value)
+                               + new_value;
+       }
+       else
+       {
+               diff = new_value - old_value;
+       }
+
+       return (diff);
+} /* counter_t counter_diff */
+
+int rate_to_value (value_t *ret_value, gauge_t rate, /* {{{ */
+               rate_to_value_state_t *state,
+               int ds_type, cdtime_t t)
+{
+       gauge_t delta_gauge;
+       cdtime_t delta_t;
+
+       if (ds_type == DS_TYPE_GAUGE)
+       {
+               state->last_value.gauge = rate;
+               state->last_time = t;
+
+               *ret_value = state->last_value;
+               return (0);
+       }
+
+       /* Counter and absolute can't handle negative rates. Reset "last time"
+        * to zero, so that the next valid rate will re-initialize the
+        * structure. */
+       if ((rate < 0.0)
+                       && ((ds_type == DS_TYPE_COUNTER)
+                               || (ds_type == DS_TYPE_ABSOLUTE)))
+       {
+               memset (state, 0, sizeof (*state));
+               return (EINVAL);
+       }
+
+       /* Another invalid state: The time is not increasing. */
+       if (t <= state->last_time)
+       {
+               memset (state, 0, sizeof (*state));
+               return (EINVAL);
+       }
+
+       delta_t = t - state->last_time;
+       delta_gauge = (rate * CDTIME_T_TO_DOUBLE (delta_t)) + state->residual;
+
+       /* Previous value is invalid. */
+       if (state->last_time == 0) /* {{{ */
+       {
+               if (ds_type == DS_TYPE_DERIVE)
+               {
+                       state->last_value.derive = (derive_t) rate;
+                       state->residual = rate - ((gauge_t) state->last_value.derive);
+               }
+               else if (ds_type == DS_TYPE_COUNTER)
+               {
+                       state->last_value.counter = (counter_t) rate;
+                       state->residual = rate - ((gauge_t) state->last_value.counter);
+               }
+               else if (ds_type == DS_TYPE_ABSOLUTE)
+               {
+                       state->last_value.absolute = (absolute_t) rate;
+                       state->residual = rate - ((gauge_t) state->last_value.absolute);
+               }
+               else
+               {
+                       assert (23 == 42);
+               }
+
+               state->last_time = t;
+               return (EAGAIN);
+       } /* }}} */
+
+       if (ds_type == DS_TYPE_DERIVE)
+       {
+               derive_t delta_derive = (derive_t) delta_gauge;
+
+               state->last_value.derive += delta_derive;
+               state->residual = delta_gauge - ((gauge_t) delta_derive);
+       }
+       else if (ds_type == DS_TYPE_COUNTER)
+       {
+               counter_t delta_counter = (counter_t) delta_gauge;
+
+               state->last_value.counter += delta_counter;
+               state->residual = delta_gauge - ((gauge_t) delta_counter);
+       }
+       else if (ds_type == DS_TYPE_ABSOLUTE)
+       {
+               absolute_t delta_absolute = (absolute_t) delta_gauge;
+
+               state->last_value.absolute = delta_absolute;
+               state->residual = delta_gauge - ((gauge_t) delta_absolute);
+       }
+       else
+       {
+               assert (23 == 42);
+       }
+
+        state->last_time = t;
+       *ret_value = state->last_value;
+       return (0);
+} /* }}} value_t rate_to_value */
+
+int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
+               value_to_rate_state_t *state,
+               int ds_type, cdtime_t t)
+{
+       double interval;
+
+       /* Another invalid state: The time is not increasing. */
+       if (t <= state->last_time)
+       {
+               memset (state, 0, sizeof (*state));
+               return (EINVAL);
+       }
+
+       interval = CDTIME_T_TO_DOUBLE(t - state->last_time);
+
+       /* Previous value is invalid. */
+       if (state->last_time == 0) /* {{{ */
+       {
+               if (ds_type == DS_TYPE_DERIVE)
+               {
+                       state->last_value.derive = value;
+               }
+               else if (ds_type == DS_TYPE_COUNTER)
+               {
+                       state->last_value.counter = (counter_t) value;
+               }
+               else if (ds_type == DS_TYPE_ABSOLUTE)
+               {
+                       state->last_value.absolute = (absolute_t) value;
+               }
+               else
+               {
+                       assert (23 == 42);
+               }
+
+               state->last_time = t;
+               return (EAGAIN);
+       } /* }}} */
+
+       if (ds_type == DS_TYPE_DERIVE)
+       {
+               ret_rate->gauge = (value - state->last_value.derive) / interval;
+               state->last_value.derive = value;
+       }
+       else if (ds_type == DS_TYPE_COUNTER)
+       {
+               ret_rate->gauge = (((counter_t)value) - state->last_value.counter) / interval;
+               state->last_value.counter = (counter_t) value;
+       }
+       else if (ds_type == DS_TYPE_ABSOLUTE)
+       {
+               ret_rate->gauge = (((absolute_t)value) - state->last_value.absolute) / interval;
+               state->last_value.absolute = (absolute_t) value;
+       }
+       else
+       {
+               assert (23 == 42);
+       }
+
+        state->last_time = t;
+       return (0);
+} /* }}} value_t rate_to_value */
+
+int service_name_to_port_number (const char *service_name)
+{
+       struct addrinfo *ai_list;
+       struct addrinfo *ai_ptr;
+       struct addrinfo ai_hints;
+       int status;
+       int service_number;
+
+       if (service_name == NULL)
+               return (-1);
+
+       ai_list = NULL;
+       memset (&ai_hints, 0, sizeof (ai_hints));
+       ai_hints.ai_family = AF_UNSPEC;
+
+       status = getaddrinfo (/* node = */ NULL, service_name,
+                       &ai_hints, &ai_list);
+       if (status != 0)
+       {
+               ERROR ("service_name_to_port_number: getaddrinfo failed: %s",
+                               gai_strerror (status));
+               return (-1);
+       }
+
+       service_number = -1;
+       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               if (ai_ptr->ai_family == AF_INET)
+               {
+                       struct sockaddr_in *sa;
+
+                       sa = (void *) ai_ptr->ai_addr;
+                       service_number = (int) ntohs (sa->sin_port);
+               }
+               else if (ai_ptr->ai_family == AF_INET6)
+               {
+                       struct sockaddr_in6 *sa;
+
+                       sa = (void *) ai_ptr->ai_addr;
+                       service_number = (int) ntohs (sa->sin6_port);
+               }
+
+               if ((service_number > 0) && (service_number <= 65535))
+                       break;
+       }
+
+       freeaddrinfo (ai_list);
+
+       if ((service_number > 0) && (service_number <= 65535))
+               return (service_number);
+       return (-1);
+} /* int service_name_to_port_number */
+
+int strtoderive (const char *string, derive_t *ret_value) /* {{{ */
+{
+       derive_t tmp;
+       char *endptr;
+
+       if ((string == NULL) || (ret_value == NULL))
+               return (EINVAL);
+
+       errno = 0;
+       endptr = NULL;
+       tmp = (derive_t) strtoll (string, &endptr, /* base = */ 0);
+       if ((endptr == string) || (errno != 0))
+               return (-1);
+
+       *ret_value = tmp;
+       return (0);
+} /* }}} int strtoderive */
+
+int strtogauge (const char *string, gauge_t *ret_value) /* {{{ */
+{
+       gauge_t tmp;
+       char *endptr = NULL;
+
+       if ((string == NULL) || (ret_value == NULL))
+               return (EINVAL);
+
+       errno = 0;
+       endptr = NULL;
+       tmp = (gauge_t) strtod (string, &endptr);
+       if (errno != 0)
+               return (errno);
+       else if ((endptr == NULL) || (*endptr != 0))
+               return (EINVAL);
+
+       *ret_value = tmp;
+       return (0);
+} /* }}} int strtogauge */
+
+int strarray_add (char ***ret_array, size_t *ret_array_len, char const *str) /* {{{ */
+{
+       char **array;
+       size_t array_len = *ret_array_len;
+
+       if (str == NULL)
+               return (EINVAL);
+
+       array = realloc (*ret_array,
+            (array_len + 1) * sizeof (*array));
+       if (array == NULL)
+               return (ENOMEM);
+       *ret_array = array;
+
+       array[array_len] = strdup (str);
+       if (array[array_len] == NULL)
+               return (ENOMEM);
+
+       array_len++;
+        *ret_array_len = array_len;
+       return (0);
+} /* }}} int strarray_add */
+
+void strarray_free (char **array, size_t array_len) /* {{{ */
+{
+       size_t i;
+
+       for (i = 0; i < array_len; i++)
+               sfree (array[i]);
+       sfree (array);
+} /* }}} void strarray_free */
diff --git a/src/daemon/common.h b/src/daemon/common.h
new file mode 100644 (file)
index 0000000..da21cad
--- /dev/null
@@ -0,0 +1,378 @@
+/**
+ * collectd - src/common.h
+ * Copyright (C) 2005-2014  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "collectd.h"
+#include "plugin.h"
+
+#if HAVE_PWD_H
+# include <pwd.h>
+#endif
+
+#define sfree(ptr) \
+       do { \
+               if((ptr) != NULL) { \
+                       free(ptr); \
+               } \
+               (ptr) = NULL; \
+       } while (0)
+
+#define STATIC_ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
+
+#define IS_TRUE(s) ((strcasecmp ("true", (s)) == 0) \
+               || (strcasecmp ("yes", (s)) == 0) \
+               || (strcasecmp ("on", (s)) == 0))
+#define IS_FALSE(s) ((strcasecmp ("false", (s)) == 0) \
+               || (strcasecmp ("no", (s)) == 0) \
+               || (strcasecmp ("off", (s)) == 0))
+
+struct rate_to_value_state_s
+{
+  value_t last_value;
+  cdtime_t last_time;
+  gauge_t residual;
+};
+typedef struct rate_to_value_state_s rate_to_value_state_t;
+
+struct value_to_rate_state_s
+{
+  value_t last_value;
+  cdtime_t last_time;
+};
+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 *dest, size_t n, const char *format, ...);
+
+__attribute__ ((format(printf,1,2)))
+char *ssnprintf_alloc (char const *format, ...);
+
+char *sstrdup(const char *s);
+void *smalloc(size_t size);
+char *sstrerror (int errnum, char *buf, size_t buflen);
+
+/*
+ * NAME
+ *   sread
+ *
+ * DESCRIPTION
+ *   Reads exactly `n' bytes or fails. Syntax and other behavior is analogous
+ *   to `read(2)'. If EOF is received the file descriptor is closed and an
+ *   error is returned.
+ *
+ * PARAMETERS
+ *   `fd'          File descriptor to write to.
+ *   `buf'         Buffer that is to be written.
+ *   `count'       Number of bytes in the buffer.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if an error occurred. `errno' is set in this
+ *   case.
+ */
+ssize_t sread (int fd, void *buf, size_t count);
+
+/*
+ * NAME
+ *   swrite
+ *
+ * DESCRIPTION
+ *   Writes exactly `n' bytes or fails. Syntax and other behavior is analogous
+ *   to `write(2)'.
+ *
+ * PARAMETERS
+ *   `fd'          File descriptor to write to.
+ *   `buf'         Buffer that is to be written.
+ *   `count'       Number of bytes in the buffer.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if an error occurred. `errno' is set in this
+ *   case.
+ */
+ssize_t swrite (int fd, const void *buf, size_t count);
+
+/*
+ * NAME
+ *   strsplit
+ *
+ * DESCRIPTION
+ *   Splits a string into parts and stores pointers to the parts in `fields'.
+ *   The characters split at are: " ", "\t", "\r", and "\n".
+ *
+ * PARAMETERS
+ *   `string'      String to split. This string will be modified. `fields' will
+ *                 contain pointers to parts of this string, so free'ing it
+ *                 will destroy `fields' as well.
+ *   `fields'      Array of strings where pointers to the parts will be stored.
+ *   `size'        Number of elements in the array. No more than `size'
+ *                 pointers will be stored in `fields'.
+ *
+ * RETURN VALUE
+ *    Returns the number of parts stored in `fields'.
+ */
+int strsplit (char *string, char **fields, size_t size);
+
+/*
+ * NAME
+ *   strjoin
+ *
+ * DESCRIPTION
+ *   Joins together several parts of a string using `sep' as a separator. This
+ *   is equivalent to the Perl built-in `join'.
+ *
+ * PARAMETERS
+ *   `dst'         Buffer where the result is stored.
+ *   `dst_len'     Length of the destination buffer. No more than this many
+ *                 bytes will be written to the memory pointed to by `dst',
+ *                 including the trailing null-byte.
+ *   `fields'      Array of strings to be joined.
+ *   `fields_num'  Number of elements in the `fields' array.
+ *   `sep'         String to be inserted between any two elements of `fields'.
+ *                 This string is neither prepended nor appended to the result.
+ *                 Instead of passing "" (empty string) one can pass NULL.
+ *
+ * RETURN VALUE
+ *   Returns the number of characters in `dst', NOT including the trailing
+ *   null-byte. If an error occurred (empty array or `dst' too small) a value
+ *   smaller than zero will be returned.
+ */
+int strjoin (char *dst, size_t dst_len, char **fields, size_t fields_num, const char *sep);
+
+/*
+ * NAME
+ *   escape_slashes
+ *
+ * DESCRIPTION
+ *   Removes slashes ("/") from "buffer". If buffer contains a single slash,
+ *   the result will be "root". Leading slashes are removed. All other slashes
+ *   are replaced with underscores ("_").
+ *   This function is used by plugin_dispatch_values() to escape all parts of
+ *   the identifier.
+ *
+ * PARAMETERS
+ *   `buffer'         String to be escaped.
+ *   `buffer_size'    Size of the buffer. No more then this many bytes will be
+ *                    written to `buffer', including the trailing null-byte.
+ *
+ * RETURN VALUE
+ *   Returns zero upon success and a value smaller than zero upon failure.
+ */
+int escape_slashes (char *buffer, size_t buffer_size);
+
+/**
+ * NAME
+ *   escape_string
+ *
+ * DESCRIPTION
+ *   escape_string quotes and escapes a string to be usable with collectd's
+ *   plain text protocol. "simple" strings are left as they are, for example if
+ *   buffer is 'simple' before the call, it will remain 'simple'. However, if
+ *   buffer contains 'more "complex"' before the call, the returned buffer will
+ *   contain '"more \"complex\""'.
+ *
+ *   If the buffer is too small to contain the escaped string, the string will
+ *   be truncated. However, leading and trailing double quotes, as well as an
+ *   ending null byte are guaranteed.
+ *
+ * RETURN VALUE
+ *   Returns zero on success, even if the string was truncated. Non-zero on
+ *   failure.
+ */
+int escape_string (char *buffer, size_t buffer_size);
+
+/*
+ * NAME
+ *   replace_special
+ *
+ * DESCRIPTION
+ *   Replaces any special characters (anything that's not alpha-numeric or a
+ *   dash) with an underscore.
+ *
+ *   E.g. "foo$bar&" would become "foo_bar_".
+ *
+ * PARAMETERS
+ *   `buffer'      String to be handled.
+ *   `buffer_size' Length of the string. The function returns after
+ *                 encountering a null-byte or reading this many bytes.
+ */
+void replace_special (char *buffer, size_t buffer_size);
+
+int strsubstitute (char *str, char c_from, char c_to);
+
+/*
+ * NAME
+ *   strunescape
+ *
+ * DESCRIPTION
+ *   Replaces any escaped characters in a string with the appropriate special
+ *   characters. The following escaped characters are recognized:
+ *
+ *     \t -> <tab>
+ *     \n -> <newline>
+ *     \r -> <carriage return>
+ *
+ *   For all other escacped characters only the backslash will be removed.
+ *
+ * PARAMETERS
+ *   `buf'         String to be unescaped.
+ *   `buf_len'     Length of the string, including the terminating null-byte.
+ *
+ * RETURN VALUE
+ *   Returns zero upon success, a value less than zero else.
+ */
+int strunescape (char *buf, size_t buf_len);
+
+/**
+ * Removed trailing newline characters (CR and LF) from buffer, which must be
+ * null terminated. Returns the length of the resulting string.
+ */
+__attribute__((nonnull (1)))
+size_t strstripnewline (char *buffer);
+
+/*
+ * NAME
+ *   timeval_cmp
+ *
+ * DESCRIPTION
+ *   Compare the two time values `tv0' and `tv1' and store the absolut value
+ *   of the difference in the time value pointed to by `delta' if it does not
+ *   equal NULL.
+ *
+ * RETURN VALUE
+ *   Returns an integer less than, equal to, or greater than zero if `tv0' is
+ *   less than, equal to, or greater than `tv1' respectively.
+ */
+int timeval_cmp (struct timeval tv0, struct timeval tv1, struct timeval *delta);
+
+/* make sure tv_usec stores less than a second */
+#define NORMALIZE_TIMEVAL(tv) \
+       do { \
+               (tv).tv_sec += (tv).tv_usec / 1000000; \
+               (tv).tv_usec = (tv).tv_usec % 1000000; \
+       } while (0)
+
+/* make sure tv_sec stores less than a second */
+#define NORMALIZE_TIMESPEC(tv) \
+       do { \
+               (tv).tv_sec += (tv).tv_nsec / 1000000000; \
+               (tv).tv_nsec = (tv).tv_nsec % 1000000000; \
+       } while (0)
+
+int check_create_dir (const char *file_orig);
+
+#ifdef HAVE_LIBKSTAT
+int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name);
+long long get_kstat_value (kstat_t *ksp, char *name);
+#endif
+
+#ifndef HAVE_HTONLL
+unsigned long long ntohll (unsigned long long n);
+unsigned long long htonll (unsigned long long n);
+#endif
+
+#if FP_LAYOUT_NEED_NOTHING
+# define ntohd(d) (d)
+# define htond(d) (d)
+#elif FP_LAYOUT_NEED_ENDIANFLIP || FP_LAYOUT_NEED_INTSWAP
+double ntohd (double d);
+double htond (double d);
+#else
+# error "Don't know how to convert between host and network representation of doubles."
+#endif
+
+int format_name (char *ret, int ret_len,
+               const char *hostname,
+               const char *plugin, const char *plugin_instance,
+               const char *type, const char *type_instance);
+#define FORMAT_VL(ret, ret_len, vl) \
+       format_name (ret, ret_len, (vl)->host, (vl)->plugin, (vl)->plugin_instance, \
+                       (vl)->type, (vl)->type_instance)
+int format_values (char *ret, size_t ret_len,
+               const data_set_t *ds, const value_list_t *vl,
+               _Bool store_rates);
+
+int parse_identifier (char *str, char **ret_host,
+               char **ret_plugin, char **ret_plugin_instance,
+               char **ret_type, char **ret_type_instance);
+int parse_identifier_vl (const char *str, value_list_t *vl);
+int parse_value (const char *value, value_t *ret_value, int ds_type);
+int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds);
+
+#if !HAVE_GETPWNAM_R
+int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf,
+               size_t buflen, struct passwd **pwbufp);
+#endif
+
+int notification_init (notification_t *n, int severity, const char *message,
+               const char *host,
+               const char *plugin, const char *plugin_instance,
+               const char *type, const char *type_instance);
+#define NOTIFICATION_INIT_VL(n, vl) \
+       notification_init (n, NOTIF_FAILURE, NULL, \
+                       (vl)->host, (vl)->plugin, (vl)->plugin_instance, \
+                       (vl)->type, (vl)->type_instance)
+
+typedef int (*dirwalk_callback_f)(const char *dirname, const char *filename,
+               void *user_data);
+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);
+
+counter_t counter_diff (counter_t old_value, counter_t new_value);
+
+/* Convert a rate back to a value_t. When converting to a derive_t, counter_t
+ * or absoltue_t, take fractional residuals into account. This is important
+ * when scaling counters, for example.
+ * Returns zero on success. Returns EAGAIN when called for the first time; in
+ * this case the value_t is invalid and the next call should succeed. Other
+ * return values indicate an error. */
+int rate_to_value (value_t *ret_value, gauge_t rate,
+               rate_to_value_state_t *state, int ds_type, cdtime_t t);
+
+int value_to_rate (value_t *ret_rate, derive_t value,
+               value_to_rate_state_t *state, int ds_type, cdtime_t t);
+
+/* Converts a service name (a string) to a port number
+ * (in the range [1-65535]). Returns less than zero on error. */
+int service_name_to_port_number (const char *service_name);
+
+/** Parse a string to a derive_t value. Returns zero on success or non-zero on
+ * failure. If failure is returned, ret_value is not touched. */
+int strtoderive (const char *string, derive_t *ret_value);
+
+/** Parse a string to a gauge_t value. Returns zero on success or non-zero on
+ * failure. If failure is returned, ret_value is not touched. */
+int strtogauge (const char *string, gauge_t *ret_value);
+
+int strarray_add (char ***ret_array, size_t *ret_array_len, char const *str);
+void strarray_free (char **array, size_t array_len);
+
+#endif /* COMMON_H */
diff --git a/src/daemon/common_test.c b/src/daemon/common_test.c
new file mode 100644 (file)
index 0000000..1fa8f32
--- /dev/null
@@ -0,0 +1,246 @@
+/**
+ * collectd - src/tests/test_common.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "testing.h"
+#include "common.h"
+
+DEF_TEST(sstrncpy)
+{
+  char buffer[16] = "";
+  char *ptr = &buffer[4];
+  char *ret;
+
+  buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
+  buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
+
+  ret = sstrncpy (ptr, "foobar", 8);
+  OK(ret == ptr);
+  STREQ ("foobar", ptr);
+  OK(buffer[3] == buffer[12]);
+
+  ret = sstrncpy (ptr, "abc", 8);
+  OK(ret == ptr);
+  STREQ ("abc", ptr);
+  OK(buffer[3] == buffer[12]);
+
+  ret = sstrncpy (ptr, "collectd", 8);
+  OK(ret == ptr);
+  OK(ptr[7] == 0);
+  STREQ ("collect", ptr);
+  OK(buffer[3] == buffer[12]);
+
+  return (0);
+}
+
+DEF_TEST(ssnprintf)
+{
+  char buffer[16] = "";
+  char *ptr = &buffer[4];
+  int status;
+
+  buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
+  buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
+
+  status = ssnprintf (ptr, 8, "%i", 1337);
+  OK(status == 4);
+  STREQ ("1337", ptr);
+
+  status = ssnprintf (ptr, 8, "%s", "collectd");
+  OK(status == 8);
+  OK(ptr[7] == 0);
+  STREQ ("collect", ptr);
+  OK(buffer[3] == buffer[12]);
+
+  return (0);
+}
+
+DEF_TEST(sstrdup)
+{
+  char *ptr;
+
+  ptr = sstrdup ("collectd");
+  OK(ptr != NULL);
+  STREQ ("collectd", ptr);
+
+  sfree(ptr);
+  OK(ptr == NULL);
+
+  ptr = sstrdup (NULL);
+  OK(ptr == NULL);
+
+  return (0);
+}
+
+DEF_TEST(strsplit)
+{
+  char buffer[32];
+  char *fields[8];
+  int status;
+
+  strncpy (buffer, "foo bar", sizeof (buffer));
+  status = strsplit (buffer, fields, 8);
+  OK(status == 2);
+  STREQ ("foo", fields[0]);
+  STREQ ("bar", fields[1]);
+
+  strncpy (buffer, "foo \t bar", sizeof (buffer));
+  status = strsplit (buffer, fields, 8);
+  OK(status == 2);
+  STREQ ("foo", fields[0]);
+  STREQ ("bar", fields[1]);
+
+  strncpy (buffer, "one two\tthree\rfour\nfive", sizeof (buffer));
+  status = strsplit (buffer, fields, 8);
+  OK(status == 5);
+  STREQ ("one", fields[0]);
+  STREQ ("two", fields[1]);
+  STREQ ("three", fields[2]);
+  STREQ ("four", fields[3]);
+  STREQ ("five", fields[4]);
+
+  strncpy (buffer, "\twith trailing\n", sizeof (buffer));
+  status = strsplit (buffer, fields, 8);
+  OK(status == 2);
+  STREQ ("with", fields[0]);
+  STREQ ("trailing", fields[1]);
+
+  strncpy (buffer, "1 2 3 4 5 6 7 8 9 10 11 12 13", sizeof (buffer));
+  status = strsplit (buffer, fields, 8);
+  OK(status == 8);
+  STREQ ("7", fields[6]);
+  STREQ ("8", fields[7]);
+
+  strncpy (buffer, "single", sizeof (buffer));
+  status = strsplit (buffer, fields, 8);
+  OK(status == 1);
+  STREQ ("single", fields[0]);
+
+  strncpy (buffer, "", sizeof (buffer));
+  status = strsplit (buffer, fields, 8);
+  OK(status == 0);
+
+  return (0);
+}
+
+DEF_TEST(strjoin)
+{
+  char buffer[16];
+  char *fields[4];
+  int status;
+
+  fields[0] = "foo";
+  fields[1] = "bar";
+  fields[2] = "baz";
+  fields[3] = "qux";
+
+  status = strjoin (buffer, sizeof (buffer), fields, 2, "!");
+  OK(status == 7);
+  STREQ ("foo!bar", buffer);
+
+  status = strjoin (buffer, sizeof (buffer), fields, 1, "!");
+  OK(status == 3);
+  STREQ ("foo", buffer);
+
+  status = strjoin (buffer, sizeof (buffer), fields, 0, "!");
+  OK(status < 0);
+
+  status = strjoin (buffer, sizeof (buffer), fields, 2, "rcht");
+  OK(status == 10);
+  STREQ ("foorchtbar", buffer);
+
+  status = strjoin (buffer, sizeof (buffer), fields, 4, "");
+  OK(status == 12);
+  STREQ ("foobarbazqux", buffer);
+
+  status = strjoin (buffer, sizeof (buffer), fields, 4, "!");
+  OK(status == 15);
+  STREQ ("foo!bar!baz!qux", buffer);
+
+  fields[0] = "0123";
+  fields[1] = "4567";
+  fields[2] = "8901";
+  fields[3] = "2345";
+  status = strjoin (buffer, sizeof (buffer), fields, 4, "-");
+  OK(status < 0);
+
+  return (0);
+}
+
+DEF_TEST(strunescape)
+{
+  char buffer[16];
+  int status;
+
+  strncpy (buffer, "foo\\tbar", sizeof (buffer));
+  status = strunescape (buffer, sizeof (buffer));
+  OK(status == 0);
+  STREQ ("foo\tbar", buffer);
+
+  strncpy (buffer, "\\tfoo\\r\\n", sizeof (buffer));
+  status = strunescape (buffer, sizeof (buffer));
+  OK(status == 0);
+  STREQ ("\tfoo\r\n", buffer);
+
+  strncpy (buffer, "With \\\"quotes\\\"", sizeof (buffer));
+  status = strunescape (buffer, sizeof (buffer));
+  OK(status == 0);
+  STREQ ("With \"quotes\"", buffer);
+
+  /* Backslash before null byte */
+  strncpy (buffer, "\\tbackslash end\\", sizeof (buffer));
+  status = strunescape (buffer, sizeof (buffer));
+  OK(status != 0);
+  STREQ ("\tbackslash end", buffer);
+  return (0);
+
+  /* Backslash at buffer end */
+  strncpy (buffer, "\\t3\\56", sizeof (buffer));
+  status = strunescape (buffer, 4);
+  OK(status != 0);
+  OK(buffer[0] == '\t');
+  OK(buffer[1] == '3');
+  OK(buffer[2] == 0);
+  OK(buffer[3] == 0);
+  OK(buffer[4] == '5');
+  OK(buffer[5] == '6');
+  OK(buffer[6] == '7');
+
+  return (0);
+}
+
+int main (void)
+{
+  RUN_TEST(sstrncpy);
+  RUN_TEST(ssnprintf);
+  RUN_TEST(sstrdup);
+  RUN_TEST(strsplit);
+  RUN_TEST(strjoin);
+  RUN_TEST(strunescape);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/configfile.c b/src/daemon/configfile.c
new file mode 100644 (file)
index 0000000..02fd96f
--- /dev/null
@@ -0,0 +1,1353 @@
+/**
+ * collectd - src/configfile.c
+ * Copyright (C) 2005-2011  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
+ **/
+
+#include "collectd.h"
+
+#include "liboconfig/oconfig.h"
+
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "types_list.h"
+#include "filter_chain.h"
+
+#if HAVE_WORDEXP_H
+# include <wordexp.h>
+#endif /* HAVE_WORDEXP_H */
+
+#if HAVE_FNMATCH_H
+# include <fnmatch.h>
+#endif /* HAVE_FNMATCH_H */
+
+#if HAVE_LIBGEN_H
+# include <libgen.h>
+#endif /* HAVE_LIBGEN_H */
+
+#define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
+
+/*
+ * Private types
+ */
+typedef struct cf_callback
+{
+       const char  *type;
+       int  (*callback) (const char *, const char *);
+       const char **keys;
+       int    keys_num;
+       plugin_ctx_t ctx;
+       struct cf_callback *next;
+} cf_callback_t;
+
+typedef struct cf_complex_callback_s
+{
+       char *type;
+       int (*callback) (oconfig_item_t *);
+       plugin_ctx_t ctx;
+       struct cf_complex_callback_s *next;
+} cf_complex_callback_t;
+
+typedef struct cf_value_map_s
+{
+       char *key;
+       int (*func) (const oconfig_item_t *);
+} cf_value_map_t;
+
+typedef struct cf_global_option_s
+{
+       char *key;
+       char *value;
+       char *def;
+} cf_global_option_t;
+
+/*
+ * Prototypes of callback functions
+ */
+static int dispatch_value_typesdb (const oconfig_item_t *ci);
+static int dispatch_value_plugindir (const oconfig_item_t *ci);
+static int dispatch_loadplugin (const oconfig_item_t *ci);
+
+/*
+ * Private variables
+ */
+static cf_callback_t *first_callback = NULL;
+static cf_complex_callback_t *complex_callback_head = NULL;
+
+static cf_value_map_t cf_value_map[] =
+{
+       {"TypesDB",    dispatch_value_typesdb},
+       {"PluginDir",  dispatch_value_plugindir},
+       {"LoadPlugin", dispatch_loadplugin}
+};
+static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map);
+
+static cf_global_option_t cf_global_options[] =
+{
+       {"BaseDir",     NULL, PKGLOCALSTATEDIR},
+       {"PIDFile",     NULL, PIDFILE},
+       {"Hostname",    NULL, NULL},
+       {"FQDNLookup",  NULL, "true"},
+       {"Interval",    NULL, NULL},
+       {"ReadThreads", NULL, "5"},
+       {"WriteThreads", NULL, "5"},
+       {"WriteQueueLimitHigh", NULL, NULL},
+       {"WriteQueueLimitLow", NULL, NULL},
+       {"Timeout",     NULL, "2"},
+       {"AutoLoadPlugin", NULL, "false"},
+       {"CollectInternalStats", NULL, "false"},
+       {"PreCacheChain",  NULL, "PreCache"},
+       {"PostCacheChain", NULL, "PostCache"},
+       {"MaxReadInterval", NULL, "86400"}
+};
+static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
+
+static int cf_default_typesdb = 1;
+
+/*
+ * Functions to handle register/unregister, search, and other plugin related
+ * stuff
+ */
+static cf_callback_t *cf_search (const char *type)
+{
+       cf_callback_t *cf_cb;
+
+       if (type == NULL)
+               return (NULL);
+
+       for (cf_cb = first_callback; cf_cb != NULL; cf_cb = cf_cb->next)
+               if (strcasecmp (cf_cb->type, type) == 0)
+                       break;
+
+       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;
+
+       DEBUG ("type = %s, key = %s, value = %s",
+                       ESCAPE_NULL(type),
+                       ESCAPE_NULL(orig_key),
+                       ESCAPE_NULL(orig_value));
+
+       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);
+       }
+
+       if ((key = strdup (orig_key)) == NULL)
+               return (1);
+       if ((value = strdup (orig_value)) == NULL)
+       {
+               free (key);
+               return (2);
+       }
+
+       ret = -1;
+
+       old_ctx = plugin_set_ctx (cf_cb->ctx);
+
+       for (i = 0; i < cf_cb->keys_num; i++)
+       {
+               if ((cf_cb->keys[i] != NULL)
+                               && (strcasecmp (cf_cb->keys[i], key) == 0))
+               {
+                       ret = (*cf_cb->callback) (key, value);
+                       break;
+               }
+       }
+
+       plugin_set_ctx (old_ctx);
+
+       if (i >= cf_cb->keys_num)
+               WARNING ("Plugin `%s' did not register for value `%s'.", type, key);
+
+       free (key);
+       free (value);
+
+       DEBUG ("cf_dispatch: return (%i)", ret);
+
+       return (ret);
+} /* int cf_dispatch */
+
+static int dispatch_global_option (const oconfig_item_t *ci)
+{
+       if (ci->values_num != 1)
+               return (-1);
+       if (ci->values[0].type == OCONFIG_TYPE_STRING)
+               return (global_option_set (ci->key, ci->values[0].value.string));
+       else if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
+       {
+               char tmp[128];
+               ssnprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number);
+               return (global_option_set (ci->key, tmp));
+       }
+       else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
+       {
+               if (ci->values[0].value.boolean)
+                       return (global_option_set (ci->key, "true"));
+               else
+                       return (global_option_set (ci->key, "false"));
+       }
+
+       return (-1);
+} /* int dispatch_global_option */
+
+static int dispatch_value_typesdb (const oconfig_item_t *ci)
+{
+       int i = 0;
+
+       assert (strcasecmp (ci->key, "TypesDB") == 0);
+
+       cf_default_typesdb = 0;
+
+       if (ci->values_num < 1) {
+               ERROR ("configfile: `TypesDB' needs at least one argument.");
+               return (-1);
+       }
+
+       for (i = 0; i < ci->values_num; ++i)
+       {
+               if (OCONFIG_TYPE_STRING != ci->values[i].type) {
+                       WARNING ("configfile: TypesDB: Skipping %i. argument which "
+                                       "is not a string.", i + 1);
+                       continue;
+               }
+
+               read_types_list (ci->values[i].value.string);
+       }
+       return (0);
+} /* int dispatch_value_typesdb */
+
+static int dispatch_value_plugindir (const oconfig_item_t *ci)
+{
+       assert (strcasecmp (ci->key, "PluginDir") == 0);
+       
+       if (ci->values_num != 1)
+               return (-1);
+       if (ci->values[0].type != OCONFIG_TYPE_STRING)
+               return (-1);
+
+       plugin_set_dir (ci->values[0].value.string);
+       return (0);
+}
+
+static int dispatch_loadplugin (const oconfig_item_t *ci)
+{
+       int i;
+       const char *name;
+       unsigned int flags = 0;
+       plugin_ctx_t ctx;
+       plugin_ctx_t old_ctx;
+       int ret_val;
+
+       assert (strcasecmp (ci->key, "LoadPlugin") == 0);
+
+       if (ci->values_num != 1)
+               return (-1);
+       if (ci->values[0].type != OCONFIG_TYPE_STRING)
+               return (-1);
+
+       name = ci->values[0].value.string;
+       if (strcmp ("libvirt", name) == 0)
+               name = "virt";
+
+       /* default to the global interval set before loading this plugin */
+       memset (&ctx, 0, sizeof (ctx));
+       ctx.interval = cf_get_default_interval ();
+
+       for (i = 0; i < ci->children_num; ++i) {
+               if (strcasecmp("Globals", ci->children[i].key) == 0)
+                       cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
+               else if (strcasecmp ("Interval", ci->children[i].key) == 0) {
+                       if (cf_util_get_cdtime (ci->children + i, &ctx.interval) != 0) {
+                               /* cf_util_get_cdtime will log an error */
+                               continue;
+                       }
+               }
+               else {
+                       WARNING("Ignoring unknown LoadPlugin option \"%s\" "
+                                       "for plugin \"%s\"",
+                                       ci->children[i].key, ci->values[0].value.string);
+               }
+       }
+
+       old_ctx = plugin_set_ctx (ctx);
+       ret_val = plugin_load (name, (uint32_t) flags);
+       /* reset to the "global" context */
+       plugin_set_ctx (old_ctx);
+
+       return (ret_val);
+} /* int dispatch_value_loadplugin */
+
+static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci)
+{
+       char  buffer[4096];
+       char *buffer_ptr;
+       int   buffer_free;
+       int i;
+
+       buffer_ptr = buffer;
+       buffer_free = sizeof (buffer);
+
+       for (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;
+       }
+       /* skip the initial space */
+       buffer_ptr = buffer + 1;
+
+       return (cf_dispatch (plugin, ci->key, buffer_ptr));
+} /* int dispatch_value_plugin */
+
+static int dispatch_value (const oconfig_item_t *ci)
+{
+       int ret = -2;
+       int i;
+
+       for (i = 0; i < cf_value_map_num; i++)
+               if (strcasecmp (cf_value_map[i].key, ci->key) == 0)
+               {
+                       ret = cf_value_map[i].func (ci);
+                       break;
+               }
+
+       for (i = 0; i < cf_global_options_num; i++)
+               if (strcasecmp (cf_global_options[i].key, ci->key) == 0)
+               {
+                       ret = dispatch_global_option (ci);
+                       break;
+               }
+
+       return (ret);
+} /* int dispatch_value */
+
+static int dispatch_block_plugin (oconfig_item_t *ci)
+{
+       int i;
+       char *name;
+
+       cf_complex_callback_t *cb;
+
+       if (strcasecmp (ci->key, "Plugin") != 0)
+               return (-1);
+       if (ci->values_num < 1)
+               return (-1);
+       if (ci->values[0].type != OCONFIG_TYPE_STRING)
+               return (-1);
+
+       name = ci->values[0].value.string;
+       if (strcmp ("libvirt", 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";
+       }
+
+       if (IS_TRUE (global_option_get ("AutoLoadPlugin")))
+       {
+               int status;
+
+               status = plugin_load (name, /* flags = */ 0);
+               if (status != 0)
+               {
+                       ERROR ("Automatically loading plugin \"%s\" failed "
+                                       "with status %i.", name, status);
+                       return (status);
+               }
+       }
+
+       /* Check for a complex callback first */
+       for (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));
+                       plugin_set_ctx (old_ctx);
+                       return (ret_val);
+               }
+       }
+
+       /* Hm, no complex plugin found. Dispatch the values one by one */
+       for (i = 0; i < ci->children_num; i++)
+       {
+               if (ci->children[i].children == NULL)
+                       dispatch_value_plugin (name, ci->children + i);
+               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);
+               }
+       }
+
+       return (0);
+}
+
+
+static int dispatch_block (oconfig_item_t *ci)
+{
+       if (strcasecmp (ci->key, "LoadPlugin") == 0)
+               return (dispatch_loadplugin (ci));
+       else if (strcasecmp (ci->key, "Plugin") == 0)
+               return (dispatch_block_plugin (ci));
+       else if (strcasecmp (ci->key, "Chain") == 0)
+               return (fc_configure (ci));
+
+       return (0);
+}
+
+static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src,
+               int offset)
+{
+       oconfig_item_t *temp;
+       int i;
+
+       assert (offset >= 0);
+       assert (dst->children_num > offset);
+
+       /* Free the memory used by the replaced child. Usually that's the
+        * `Include "blah"' statement. */
+       temp = dst->children + offset;
+       for (i = 0; i < temp->values_num; i++)
+       {
+               if (temp->values[i].type == OCONFIG_TYPE_STRING)
+               {
+                       sfree (temp->values[i].value.string);
+               }
+       }
+       sfree (temp->values);
+       temp = NULL;
+
+       /* If (src->children_num == 0) the array size is decreased. If offset
+        * is _not_ the last element, (offset < (dst->children_num - 1)), then
+        * we need to move the trailing elements before resizing the array. */
+       if ((src->children_num == 0) && (offset < (dst->children_num - 1)))
+       {
+               int nmemb = dst->children_num - (offset + 1);
+               memmove (dst->children + offset, dst->children + offset + 1,
+                               sizeof (oconfig_item_t) * nmemb);
+       }
+
+       /* Resize the memory containing the children to be big enough to hold
+        * all children. */
+       if (dst->children_num + src->children_num - 1 == 0)
+       {
+               dst->children_num = 0;
+               return (0);
+       }
+
+       temp = (oconfig_item_t *) realloc (dst->children,
+                       sizeof (oconfig_item_t)
+                       * (dst->children_num + src->children_num - 1));
+       if (temp == NULL)
+       {
+               ERROR ("configfile: realloc failed.");
+               return (-1);
+       }
+       dst->children = temp;
+
+       /* If there are children behind the include statement, and they have
+        * not yet been moved because (src->children_num == 0), then move them
+        * to the end of the list, so that the new children have room before
+        * them. */
+       if ((src->children_num > 0)
+                       && ((dst->children_num - (offset + 1)) > 0))
+       {
+               int nmemb = dst->children_num - (offset + 1);
+               int old_offset = offset + 1;
+               int new_offset = offset + src->children_num;
+
+               memmove (dst->children + new_offset,
+                               dst->children + old_offset,
+                               sizeof (oconfig_item_t) * nmemb);
+       }
+
+       /* Last but not least: If there are new children, copy them to the
+        * memory reserved for them. */
+       if (src->children_num > 0)
+       {
+               memcpy (dst->children + offset,
+                               src->children,
+                               sizeof (oconfig_item_t) * src->children_num);
+       }
+
+       /* Update the number of children. */
+       dst->children_num += (src->children_num - 1);
+
+       return (0);
+} /* int cf_ci_replace_child */
+
+static int cf_ci_append_children (oconfig_item_t *dst, oconfig_item_t *src)
+{
+       oconfig_item_t *temp;
+
+       if ((src == NULL) || (src->children_num == 0))
+               return (0);
+
+       temp = (oconfig_item_t *) realloc (dst->children,
+                       sizeof (oconfig_item_t)
+                       * (dst->children_num + src->children_num));
+       if (temp == NULL)
+       {
+               ERROR ("configfile: realloc failed.");
+               return (-1);
+       }
+       dst->children = temp;
+
+       memcpy (dst->children + dst->children_num,
+                       src->children,
+                       sizeof (oconfig_item_t)
+                       * src->children_num);
+       dst->children_num += src->children_num;
+
+       return (0);
+} /* int cf_ci_append_children */
+
+#define CF_MAX_DEPTH 8
+static oconfig_item_t *cf_read_generic (const char *path,
+               const char *pattern, int depth);
+
+static int cf_include_all (oconfig_item_t *root, int depth)
+{
+       int i;
+
+       for (i = 0; i < root->children_num; i++)
+       {
+               oconfig_item_t *new;
+               oconfig_item_t *old;
+
+               char *pattern = NULL;
+
+               int j;
+
+               if (strcasecmp (root->children[i].key, "Include") != 0)
+                       continue;
+
+               old = root->children + i;
+
+               if ((old->values_num != 1)
+                               || (old->values[0].type != OCONFIG_TYPE_STRING))
+               {
+                       ERROR ("configfile: `Include' needs exactly one string argument.");
+                       continue;
+               }
+
+               for (j = 0; j < old->children_num; ++j)
+               {
+                       oconfig_item_t *child = old->children + j;
+
+                       if (strcasecmp (child->key, "Filter") == 0)
+                               cf_util_get_string (child, &pattern);
+                       else
+                               ERROR ("configfile: Option `%s' not allowed in <Include> block.",
+                                               child->key);
+               }
+
+               new = cf_read_generic (old->values[0].value.string, pattern, depth + 1);
+               sfree (pattern);
+
+               if (new == NULL)
+                       return (-1);
+
+               /* Now replace the i'th child in `root' with `new'. */
+               if (cf_ci_replace_child (root, new, i) < 0)
+                       return (-1);
+
+               /* ... and go back to the new i'th child. */
+               --i;
+
+               sfree (new->values);
+               sfree (new);
+       } /* for (i = 0; i < root->children_num; i++) */
+
+       return (0);
+} /* int cf_include_all */
+
+static oconfig_item_t *cf_read_file (const char *file,
+               const char *pattern, int depth)
+{
+       oconfig_item_t *root;
+       int status;
+
+       assert (depth < CF_MAX_DEPTH);
+
+       if (pattern != NULL) {
+#if HAVE_FNMATCH_H && HAVE_LIBGEN_H
+               char *tmp = sstrdup (file);
+               char *filename = basename (tmp);
+
+               if ((filename != NULL) && (fnmatch (pattern, filename, 0) != 0)) {
+                       DEBUG ("configfile: Not including `%s' because it "
+                                       "does not match pattern `%s'.",
+                                       filename, pattern);
+                       free (tmp);
+                       return (NULL);
+               }
+
+               free (tmp);
+#else
+               ERROR ("configfile: Cannot apply pattern filter '%s' "
+                               "to file '%s': functions basename() and / or "
+                               "fnmatch() not available.", pattern, file);
+#endif /* HAVE_FNMATCH_H && HAVE_LIBGEN_H */
+       }
+
+       root = oconfig_parse_file (file);
+       if (root == NULL)
+       {
+               ERROR ("configfile: Cannot read file `%s'.", file);
+               return (NULL);
+       }
+
+       status = cf_include_all (root, depth);
+       if (status != 0)
+       {
+               oconfig_free (root);
+               return (NULL);
+       }
+
+       return (root);
+} /* oconfig_item_t *cf_read_file */
+
+static int cf_compare_string (const void *p1, const void *p2)
+{
+       return strcmp (*(const char **) p1, *(const char **) p2);
+}
+
+static oconfig_item_t *cf_read_dir (const char *dir,
+               const char *pattern, int depth)
+{
+       oconfig_item_t *root = NULL;
+       DIR *dh;
+       struct dirent *de;
+       char **filenames = NULL;
+       int filenames_num = 0;
+       int status;
+       int i;
+
+       assert (depth < CF_MAX_DEPTH);
+
+       dh = opendir (dir);
+       if (dh == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("configfile: opendir failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (NULL);
+       }
+
+       root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t));
+       if (root == NULL)
+       {
+               ERROR ("configfile: malloc failed.");
+               return (NULL);
+       }
+       memset (root, 0, sizeof (oconfig_item_t));
+
+       while ((de = readdir (dh)) != NULL)
+       {
+               char   name[1024];
+               char **tmp;
+
+               if ((de->d_name[0] == '.') || (de->d_name[0] == 0))
+                       continue;
+
+               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.",
+                                       dir, de->d_name);
+                       for (i = 0; i < filenames_num; ++i)
+                               free (filenames[i]);
+                       free (filenames);
+                       free (root);
+                       return (NULL);
+               }
+
+               ++filenames_num;
+               tmp = (char **) realloc (filenames,
+                               filenames_num * sizeof (*filenames));
+               if (tmp == NULL) {
+                       ERROR ("configfile: realloc failed.");
+                       for (i = 0; i < filenames_num - 1; ++i)
+                               free (filenames[i]);
+                       free (filenames);
+                       free (root);
+                       return (NULL);
+               }
+               filenames = tmp;
+
+               filenames[filenames_num - 1] = sstrdup (name);
+       }
+
+       qsort ((void *) filenames, filenames_num, sizeof (*filenames),
+                       cf_compare_string);
+
+       for (i = 0; i < filenames_num; ++i)
+       {
+               oconfig_item_t *temp;
+               char *name = filenames[i];
+
+               temp = cf_read_generic (name, pattern, depth);
+               if (temp == NULL)
+               {
+                       /* An error should already have been reported. */
+                       sfree (name);
+                       continue;
+               }
+
+               cf_ci_append_children (root, temp);
+               sfree (temp->children);
+               sfree (temp);
+
+               free (name);
+       }
+
+       free(filenames);
+       return (root);
+} /* oconfig_item_t *cf_read_dir */
+
+/* 
+ * cf_read_generic
+ *
+ * Path is stat'ed and either cf_read_file or cf_read_dir is called
+ * accordingly.
+ *
+ * There are two versions of this function: If `wordexp' exists shell wildcards
+ * will be expanded and the function will include all matches found. If
+ * `wordexp' (or, more precisely, it's header file) is not available the
+ * simpler function is used which does not do any such expansion.
+ */
+#if HAVE_WORDEXP_H
+static oconfig_item_t *cf_read_generic (const char *path,
+               const char *pattern, int depth)
+{
+       oconfig_item_t *root = NULL;
+       int status;
+       const char *path_ptr;
+       wordexp_t we;
+       size_t i;
+
+       if (depth >= CF_MAX_DEPTH)
+       {
+               ERROR ("configfile: Not including `%s' because the maximum "
+                               "nesting depth has been reached.", path);
+               return (NULL);
+       }
+
+       status = wordexp (path, &we, WRDE_NOCMD);
+       if (status != 0)
+       {
+               ERROR ("configfile: wordexp (%s) failed.", path);
+               return (NULL);
+       }
+
+       root = (oconfig_item_t *) malloc (sizeof (oconfig_item_t));
+       if (root == NULL)
+       {
+               ERROR ("configfile: malloc failed.");
+               return (NULL);
+       }
+       memset (root, '\0', sizeof (oconfig_item_t));
+
+       /* wordexp() might return a sorted list already. That's not
+        * documented though, so let's make sure we get what we want. */
+       qsort ((void *) we.we_wordv, we.we_wordc, sizeof (*we.we_wordv),
+                       cf_compare_string);
+
+       for (i = 0; i < we.we_wordc; i++)
+       {
+               oconfig_item_t *temp;
+               struct stat statbuf;
+
+               path_ptr = we.we_wordv[i];
+
+               status = stat (path_ptr, &statbuf);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       WARNING ("configfile: stat (%s) failed: %s",
+                                       path_ptr,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       continue;
+               }
+
+               if (S_ISREG (statbuf.st_mode))
+                       temp = cf_read_file (path_ptr, pattern, depth);
+               else if (S_ISDIR (statbuf.st_mode))
+                       temp = cf_read_dir (path_ptr, pattern, depth);
+               else
+               {
+                       WARNING ("configfile: %s is neither a file nor a "
+                                       "directory.", path);
+                       continue;
+               }
+
+               if (temp == NULL) {
+                       oconfig_free (root);
+                       return (NULL);
+               }
+
+               cf_ci_append_children (root, temp);
+               sfree (temp->children);
+               sfree (temp);
+       }
+
+       wordfree (&we);
+
+       return (root);
+} /* oconfig_item_t *cf_read_generic */
+/* #endif HAVE_WORDEXP_H */
+
+#else /* if !HAVE_WORDEXP_H */
+static oconfig_item_t *cf_read_generic (const char *path,
+               const char *pattern, int depth)
+{
+       struct stat statbuf;
+       int status;
+
+       if (depth >= CF_MAX_DEPTH)
+       {
+               ERROR ("configfile: Not including `%s' because the maximum "
+                               "nesting depth has been reached.", path);
+               return (NULL);
+       }
+
+       status = stat (path, &statbuf);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("configfile: stat (%s) failed: %s",
+                               path,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (NULL);
+       }
+
+       if (S_ISREG (statbuf.st_mode))
+               return (cf_read_file (path, pattern, depth));
+       else if (S_ISDIR (statbuf.st_mode))
+               return (cf_read_dir (path, pattern, depth));
+
+       ERROR ("configfile: %s is neither a file nor a directory.", path);
+       return (NULL);
+} /* oconfig_item_t *cf_read_generic */
+#endif /* !HAVE_WORDEXP_H */
+
+/* 
+ * Public functions
+ */
+int global_option_set (const char *option, const char *value)
+{
+       int i;
+
+       DEBUG ("option = %s; value = %s;", option, value);
+
+       for (i = 0; i < cf_global_options_num; i++)
+               if (strcasecmp (cf_global_options[i].key, option) == 0)
+                       break;
+
+       if (i >= cf_global_options_num)
+               return (-1);
+
+       if (strcasecmp (option, "PIDFile") == 0 && pidfile_from_cli == 1)
+       {
+               DEBUG ("Configfile: Ignoring `PIDFILE' option because "
+                       "command-line option `-P' take precedence.");
+               return (0);
+       }
+
+       sfree (cf_global_options[i].value);
+
+       if (value != NULL)
+               cf_global_options[i].value = strdup (value);
+       else
+               cf_global_options[i].value = NULL;
+
+       return (0);
+}
+
+const char *global_option_get (const char *option)
+{
+       int i;
+
+       for (i = 0; i < cf_global_options_num; i++)
+               if (strcasecmp (cf_global_options[i].key, option) == 0)
+                       break;
+
+       if (i >= cf_global_options_num)
+               return (NULL);
+       
+       return ((cf_global_options[i].value != NULL)
+                       ? cf_global_options[i].value
+                       : cf_global_options[i].def);
+} /* char *global_option_get */
+
+long global_option_get_long (const char *option, long default_value)
+{
+       const char *str;
+       long value;
+
+       str = global_option_get (option);
+       if (NULL == str)
+               return (default_value);
+
+       errno = 0;
+       value = strtol (str, /* endptr = */ NULL, /* base = */ 0);
+       if (errno != 0)
+               return (default_value);
+
+       return (value);
+} /* char *global_option_get_long */
+
+cdtime_t global_option_get_time (const char *name, cdtime_t def) /* {{{ */
+{
+       char const *optstr;
+       char *endptr = NULL;
+       double v;
+
+       optstr = global_option_get (name);
+       if (optstr == NULL)
+               return (def);
+
+       errno = 0;
+       v = strtod (optstr, &endptr);
+       if ((endptr == NULL) || (*endptr != 0) || (errno != 0))
+               return (def);
+       else if (v <= 0.0)
+               return (def);
+
+       return (DOUBLE_TO_CDTIME_T (v));
+} /* }}} cdtime_t global_option_get_time */
+
+cdtime_t cf_get_default_interval (void)
+{
+       return (global_option_get_time ("Interval",
+                              DOUBLE_TO_CDTIME_T (COLLECTD_DEFAULT_INTERVAL)));
+}
+
+void cf_unregister (const char *type)
+{
+       cf_callback_t *this, *prev;
+
+       for (prev = NULL, this = first_callback;
+                       this != NULL;
+                       prev = this, this = this->next)
+               if (strcasecmp (this->type, type) == 0)
+               {
+                       if (prev == NULL)
+                               first_callback = this->next;
+                       else
+                               prev->next = this->next;
+
+                       free (this);
+                       break;
+               }
+} /* void cf_unregister */
+
+void cf_unregister_complex (const char *type)
+{
+       cf_complex_callback_t *this, *prev;
+
+       for (prev = NULL, this = complex_callback_head;
+                       this != NULL;
+                       prev = this, this = this->next)
+               if (strcasecmp (this->type, type) == 0)
+               {
+                       if (prev == NULL)
+                               complex_callback_head = this->next;
+                       else
+                               prev->next = this->next;
+
+                       sfree (this->type);
+                       sfree (this);
+                       break;
+               }
+} /* void cf_unregister */
+
+void cf_register (const char *type,
+               int (*callback) (const char *, const char *),
+               const char **keys, int keys_num)
+{
+       cf_callback_t *cf_cb;
+
+       /* Remove this module from the list, if it already exists */
+       cf_unregister (type);
+
+       /* This pointer will be free'd in `cf_unregister' */
+       if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL)
+               return;
+
+       cf_cb->type     = type;
+       cf_cb->callback = callback;
+       cf_cb->keys     = keys;
+       cf_cb->keys_num = keys_num;
+       cf_cb->ctx      = plugin_get_ctx ();
+
+       cf_cb->next = first_callback;
+       first_callback = cf_cb;
+} /* void cf_register */
+
+int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
+{
+       cf_complex_callback_t *new;
+
+       new = (cf_complex_callback_t *) malloc (sizeof (cf_complex_callback_t));
+       if (new == NULL)
+               return (-1);
+
+       new->type = strdup (type);
+       if (new->type == NULL)
+       {
+               sfree (new);
+               return (-1);
+       }
+
+       new->callback = callback;
+       new->next = NULL;
+
+       new->ctx = plugin_get_ctx ();
+
+       if (complex_callback_head == NULL)
+       {
+               complex_callback_head = new;
+       }
+       else
+       {
+               cf_complex_callback_t *last = complex_callback_head;
+               while (last->next != NULL)
+                       last = last->next;
+               last->next = new;
+       }
+
+       return (0);
+} /* int cf_register_complex */
+
+int cf_read (char *filename)
+{
+       oconfig_item_t *conf;
+       int i;
+
+       conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0);
+       if (conf == NULL)
+       {
+               ERROR ("Unable to read config file %s.", filename);
+               return (-1);
+       }
+       else if (conf->children_num == 0)
+       {
+               ERROR ("Configuration file %s is empty.", filename);
+               oconfig_free (conf);
+               return (-1);
+       }
+
+       for (i = 0; i < conf->children_num; i++)
+       {
+               if (conf->children[i].children == NULL)
+                       dispatch_value (conf->children + i);
+               else
+                       dispatch_block (conf->children + i);
+       }
+
+       oconfig_free (conf);
+
+       /* Read the default types.db if no `TypesDB' option was given. */
+       if (cf_default_typesdb)
+               read_types_list (PKGDATADIR"/types.db");
+
+       return (0);
+} /* int cf_read */
+
+/* Assures the config option is a string, duplicates it and returns the copy in
+ * "ret_string". If necessary "*ret_string" is freed first. Returns zero upon
+ * success. */
+int cf_util_get_string (const oconfig_item_t *ci, char **ret_string) /* {{{ */
+{
+       char *string;
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+       {
+               ERROR ("cf_util_get_string: The %s option requires "
+                               "exactly one string argument.", ci->key);
+               return (-1);
+       }
+
+       string = strdup (ci->values[0].value.string);
+       if (string == NULL)
+               return (-1);
+
+       if (*ret_string != NULL)
+               sfree (*ret_string);
+       *ret_string = string;
+
+       return (0);
+} /* }}} int cf_util_get_string */
+
+/* Assures the config option is a string and copies it to the provided buffer.
+ * Assures null-termination. */
+int cf_util_get_string_buffer (const oconfig_item_t *ci, char *buffer, /* {{{ */
+               size_t buffer_size)
+{
+       if ((ci == NULL) || (buffer == NULL) || (buffer_size < 1))
+               return (EINVAL);
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+       {
+               ERROR ("cf_util_get_string_buffer: The %s option requires "
+                               "exactly one string argument.", ci->key);
+               return (-1);
+       }
+
+       strncpy (buffer, ci->values[0].value.string, buffer_size);
+       buffer[buffer_size - 1] = 0;
+
+       return (0);
+} /* }}} int cf_util_get_string_buffer */
+
+/* Assures the config option is a number and returns it as an int. */
+int cf_util_get_int (const oconfig_item_t *ci, int *ret_value) /* {{{ */
+{
+       if ((ci == NULL) || (ret_value == NULL))
+               return (EINVAL);
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+       {
+               ERROR ("cf_util_get_int: The %s option requires "
+                               "exactly one numeric argument.", ci->key);
+               return (-1);
+       }
+
+       *ret_value = (int) ci->values[0].value.number;
+
+       return (0);
+} /* }}} int cf_util_get_int */
+
+int cf_util_get_double (const oconfig_item_t *ci, double *ret_value) /* {{{ */
+{
+       if ((ci == NULL) || (ret_value == NULL))
+               return (EINVAL);
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+       {
+               ERROR ("cf_util_get_double: The %s option requires "
+                               "exactly one numeric argument.", ci->key);
+               return (-1);
+       }
+
+       *ret_value = ci->values[0].value.number;
+
+       return (0);
+} /* }}} int cf_util_get_double */
+
+int cf_util_get_boolean (const oconfig_item_t *ci, _Bool *ret_bool) /* {{{ */
+{
+       if ((ci == NULL) || (ret_bool == NULL))
+               return (EINVAL);
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+       {
+               ERROR ("cf_util_get_boolean: The %s option requires "
+                               "exactly one boolean argument.", ci->key);
+               return (-1);
+       }
+
+       *ret_bool = ci->values[0].value.boolean ? 1 : 0;
+
+       return (0);
+} /* }}} int cf_util_get_boolean */
+
+int cf_util_get_flag (const oconfig_item_t *ci, /* {{{ */
+               unsigned int *ret_value, unsigned int flag)
+{
+       int status;
+       _Bool b;
+
+       if (ret_value == NULL)
+               return (EINVAL);
+
+       b = 0;
+       status = cf_util_get_boolean (ci, &b);
+       if (status != 0)
+               return (status);
+
+       if (b)
+       {
+               *ret_value |= flag;
+       }
+       else
+       {
+               *ret_value &= ~flag;
+       }
+
+       return (0);
+} /* }}} int cf_util_get_flag */
+
+/* Assures that the config option is a string or a number if the correct range
+ * of 1-65535. The string is then converted to a port number using
+ * `service_name_to_port_number' and returned.
+ * Returns the port number in the range [1-65535] or less than zero upon
+ * failure. */
+int cf_util_get_port_number (const oconfig_item_t *ci) /* {{{ */
+{
+       int tmp;
+
+       if ((ci->values_num != 1)
+                       || ((ci->values[0].type != OCONFIG_TYPE_STRING)
+                               && (ci->values[0].type != OCONFIG_TYPE_NUMBER)))
+       {
+               ERROR ("cf_util_get_port_number: The \"%s\" option requires "
+                               "exactly one string argument.", ci->key);
+               return (-1);
+       }
+
+       if (ci->values[0].type == OCONFIG_TYPE_STRING)
+               return (service_name_to_port_number (ci->values[0].value.string));
+
+       assert (ci->values[0].type == OCONFIG_TYPE_NUMBER);
+       tmp = (int) (ci->values[0].value.number + 0.5);
+       if ((tmp < 1) || (tmp > 65535))
+       {
+               ERROR ("cf_util_get_port_number: The \"%s\" option requires "
+                               "a service name or a port number. The number "
+                               "you specified, %i, is not in the valid "
+                               "range of 1-65535.",
+                               ci->key, tmp);
+               return (-1);
+       }
+
+       return (tmp);
+} /* }}} int cf_util_get_port_number */
+
+int cf_util_get_service (const oconfig_item_t *ci, char **ret_string) /* {{{ */
+{
+       int port;
+       char *service;
+       int status;
+
+       if (ci->values_num != 1)
+       {
+               ERROR ("cf_util_get_service: The %s option requires exactly "
+                               "one argument.", ci->key);
+               return (-1);
+       }
+
+       if (ci->values[0].type == OCONFIG_TYPE_STRING)
+               return (cf_util_get_string (ci, ret_string));
+       if (ci->values[0].type != OCONFIG_TYPE_NUMBER)
+       {
+               ERROR ("cf_util_get_service: The %s option requires "
+                               "exactly one string or numeric argument.",
+                               ci->key);
+       }
+
+       port = 0;
+       status = cf_util_get_int (ci, &port);
+       if (status != 0)
+               return (status);
+       else if ((port < 1) || (port > 65535))
+       {
+               ERROR ("cf_util_get_service: The port number given "
+                               "for the %s option is out of "
+                               "range (%i).", ci->key, port);
+               return (-1);
+       }
+
+       service = malloc (6);
+       if (service == NULL)
+       {
+               ERROR ("cf_util_get_service: Out of memory.");
+               return (-1);
+       }
+       ssnprintf (service, 6, "%i", port);
+
+       sfree (*ret_string);
+       *ret_string = service;
+
+       return (0);
+} /* }}} int cf_util_get_service */
+
+int cf_util_get_cdtime (const oconfig_item_t *ci, cdtime_t *ret_value) /* {{{ */
+{
+       if ((ci == NULL) || (ret_value == NULL))
+               return (EINVAL);
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+       {
+               ERROR ("cf_util_get_cdtime: The %s option requires "
+                               "exactly one numeric argument.", ci->key);
+               return (-1);
+       }
+
+       if (ci->values[0].value.number < 0.0)
+       {
+               ERROR ("cf_util_get_cdtime: The numeric argument of the %s "
+                               "option must not be negative.", ci->key);
+               return (-1);
+       }
+
+       *ret_value = DOUBLE_TO_CDTIME_T (ci->values[0].value.number);
+
+       return (0);
+} /* }}} int cf_util_get_cdtime */
+
diff --git a/src/daemon/configfile.h b/src/daemon/configfile.h
new file mode 100644 (file)
index 0000000..5bc9b30
--- /dev/null
@@ -0,0 +1,141 @@
+/**
+ * collectd - src/configfile.h
+ * Copyright (C) 2005-2011  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef CONFIGFILE_H
+#define CONFIGFILE_H
+
+#include "collectd.h"
+#include "utils_time.h"
+#include "liboconfig/oconfig.h"
+
+/*
+ * DESCRIPTION
+ *  Remove a registered plugin from the internal data structures.
+ * 
+ * PARAMETERS
+ *  `type'      Name of the plugin (must be the same as passed to
+ *              `plugin_register'
+ */
+void cf_unregister (const char *type);
+void cf_unregister_complex (const char *type);
+
+/*
+ * DESCRIPTION
+ *  `cf_register' is called by plugins that wish to receive config keys. The
+ *  plugin will then receive all keys it registered for if they're found in a
+ *  `<Plugin $type>' section.
+ *
+ * PARAMETERS
+ *  `type'      Name of the plugin (must be the same as passed to
+ *              `plugin_register'
+ *  `callback'  Pointer to the callback function. The callback must return zero
+ *              upon success, a value smaller than zero if it doesn't know how
+ *              to handle the `key' passed to it (the first argument) or a
+ *              value greater than zero if it knows how to handle the key but
+ *              failed.
+ *  `keys'      Array of key values this plugin wished to receive. The last
+ *              element must be a NULL-pointer.
+ *  `keys_num'  Number of elements in the array (not counting the last NULL-
+ *              pointer.
+ *
+ * NOTES
+ *  `cf_unregister' will be called for `type' to make sure only one record
+ *  exists for each `type' at any time. This means that `cf_register' may be
+ *  called multiple times, but only the last call will have an effect.
+ */
+void cf_register (const char *type,
+               int (*callback) (const char *, const char *),
+               const char **keys, int keys_num);
+
+int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *));
+
+/*
+ * DESCRIPTION
+ *  `cf_read' reads the config file `filename' and dispatches the read
+ *  information to functions/variables. Most important: Is calls `plugin_load'
+ *  to load specific plugins, depending on the current mode of operation.
+ *
+ * PARAMETERS
+ *  `filename'  An additional filename to look for. This function calls
+ *              `lc_process' which already searches many standard locations..
+ *              If set to NULL will use the `CONFIGFILE' define.
+ *
+ * RETURN VALUE
+ *  Returns zero upon success and non-zero otherwise. A error-message will have
+ *  been printed in this case.
+ */
+int cf_read (char *filename);
+
+int global_option_set (const char *option, const char *value);
+const char *global_option_get (const char *option);
+long global_option_get_long (const char *option, long default_value);
+long global_option_get_long_in_range (const char *option, long default_value, long min, long max);
+
+cdtime_t global_option_get_time (char const *option, cdtime_t default_value);
+
+cdtime_t cf_get_default_interval (void);
+
+/* Assures the config option is a string, duplicates it and returns the copy in
+ * "ret_string". If necessary "*ret_string" is freed first. Returns zero upon
+ * success. */
+int cf_util_get_string (const oconfig_item_t *ci, char **ret_string);
+
+/* Assures the config option is a string and copies it to the provided buffer.
+ * Assures null-termination. */
+int cf_util_get_string_buffer (const oconfig_item_t *ci, char *buffer,
+               size_t buffer_size);
+
+/* Assures the config option is a number and returns it as an int. */
+int cf_util_get_int (const oconfig_item_t *ci, int *ret_value);
+
+/* Assures the config option is a number and returns it as a double. */
+int cf_util_get_double (const oconfig_item_t *ci, double *ret_value);
+
+/* Assures the config option is a boolean and assignes it to `ret_bool'.
+ * Otherwise, `ret_bool' is not changed and non-zero is returned. */
+int cf_util_get_boolean (const oconfig_item_t *ci, _Bool *ret_bool);
+
+/* Assures the config option is a boolean and set or unset the given flag in
+ * `ret_value' as appropriate. Returns non-zero on error. */
+int cf_util_get_flag (const oconfig_item_t *ci,
+               unsigned int *ret_value, unsigned int flag);
+
+/* Assures that the config option is a string or a number if the correct range
+ * of 1-65535. The string is then converted to a port number using
+ * `service_name_to_port_number' and returned.
+ * Returns the port number in the range [1-65535] or less than zero upon
+ * failure. */
+int cf_util_get_port_number (const oconfig_item_t *ci);
+
+/* Assures that the config option is either a service name (a string) or a port
+ * number (an integer in the appropriate range) and returns a newly allocated
+ * string. If ret_string points to a non-NULL pointer, it is freed before
+ * assigning a new value. */
+int cf_util_get_service (const oconfig_item_t *ci, char **ret_string);
+
+int cf_util_get_cdtime (const oconfig_item_t *ci, cdtime_t *ret_value);
+
+#endif /* defined(CONFIGFILE_H) */
diff --git a/src/daemon/filter_chain.c b/src/daemon/filter_chain.c
new file mode 100644 (file)
index 0000000..0fd4a73
--- /dev/null
@@ -0,0 +1,1083 @@
+/**
+ * collectd - src/filter_chain.c
+ * Copyright (C) 2008-2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "configfile.h"
+#include "plugin.h"
+#include "utils_complain.h"
+#include "common.h"
+#include "filter_chain.h"
+
+/*
+ * Data types
+ */
+/* List of matches, used in fc_rule_t and for the global `match_list_head'
+ * variable. */
+struct fc_match_s;
+typedef struct fc_match_s fc_match_t; /* {{{ */
+struct fc_match_s
+{
+  char name[DATA_MAX_NAME_LEN];
+  match_proc_t proc;
+  void *user_data;
+  fc_match_t *next;
+}; /* }}} */
+
+/* List of targets, used in fc_rule_t and for the global `target_list_head'
+ * variable. */
+struct fc_target_s;
+typedef struct fc_target_s fc_target_t; /* {{{ */
+struct fc_target_s
+{
+  char name[DATA_MAX_NAME_LEN];
+  void *user_data;
+  target_proc_t proc;
+  fc_target_t *next;
+}; /* }}} */
+
+/* List of rules, used in fc_chain_t */
+struct fc_rule_s;
+typedef struct fc_rule_s fc_rule_t; /* {{{ */
+struct fc_rule_s
+{
+  char name[DATA_MAX_NAME_LEN];
+  fc_match_t  *matches;
+  fc_target_t *targets;
+  fc_rule_t *next;
+}; /* }}} */
+
+/* List of chains, used for `chain_list_head' */
+struct fc_chain_s /* {{{ */
+{
+  char name[DATA_MAX_NAME_LEN];
+  fc_rule_t   *rules;
+  fc_target_t *targets;
+  fc_chain_t  *next;
+}; /* }}} */
+
+/* Writer configuration. */
+struct fc_writer_s;
+typedef struct fc_writer_s fc_writer_t; /* {{{ */
+struct fc_writer_s
+{
+  char *plugin;
+  c_complain_t complaint;
+}; /* }}} */
+
+/*
+ * Global variables
+ */
+static fc_match_t  *match_list_head;
+static fc_target_t *target_list_head;
+static fc_chain_t  *chain_list_head;
+
+/*
+ * Private functions
+ */
+static void fc_free_matches (fc_match_t *m) /* {{{ */
+{
+  if (m == NULL)
+    return;
+
+  if (m->proc.destroy != NULL)
+    (*m->proc.destroy) (&m->user_data);
+  else if (m->user_data != NULL)
+  {
+    ERROR ("Filter subsystem: fc_free_matches: There is user data, but no "
+        "destroy functions has been specified. "
+        "Memory will probably be lost!");
+  }
+
+  if (m->next != NULL)
+    fc_free_matches (m->next);
+
+  free (m);
+} /* }}} void fc_free_matches */
+
+static void fc_free_targets (fc_target_t *t) /* {{{ */
+{
+  if (t == NULL)
+    return;
+
+  if (t->proc.destroy != NULL)
+    (*t->proc.destroy) (&t->user_data);
+  else if (t->user_data != NULL)
+  {
+    ERROR ("Filter subsystem: fc_free_targets: There is user data, but no "
+        "destroy functions has been specified. "
+        "Memory will probably be lost!");
+  }
+
+  if (t->next != NULL)
+    fc_free_targets (t->next);
+
+  free (t);
+} /* }}} void fc_free_targets */
+
+static void fc_free_rules (fc_rule_t *r) /* {{{ */
+{
+  if (r == NULL)
+    return;
+
+  fc_free_matches (r->matches);
+  fc_free_targets (r->targets);
+
+  if (r->next != NULL)
+    fc_free_rules (r->next);
+
+  free (r);
+} /* }}} void fc_free_rules */
+
+static void fc_free_chains (fc_chain_t *c) /* {{{ */
+{
+  if (c == NULL)
+    return;
+
+  fc_free_rules (c->rules);
+  fc_free_targets (c->targets);
+
+  if (c->next != NULL)
+    fc_free_chains (c->next);
+
+  free (c);
+} /* }}} void fc_free_chains */
+
+static char *fc_strdup (const char *orig) /* {{{ */
+{
+  size_t sz;
+  char *dest;
+
+  if (orig == NULL)
+    return (NULL);
+
+  sz = strlen (orig) + 1;
+  dest = (char *) malloc (sz);
+  if (dest == NULL)
+    return (NULL);
+
+  memcpy (dest, orig, sz);
+
+  return (dest);
+} /* }}} char *fc_strdup */
+
+/*
+ * Configuration.
+ *
+ * The configuration looks somewhat like this:
+ *
+ *  <Chain "PreCache">
+ *    <Rule>
+ *      <Match "regex">
+ *        Plugin "^mysql$"
+ *        Type "^mysql_command$"
+ *        TypeInstance "^show_"
+ *      </Match>
+ *      <Target "drop">
+ *      </Target>
+ *    </Rule>
+ *
+ *    <Target "write">
+ *      Plugin "rrdtool"
+ *    </Target>
+ *  </Chain>
+ */
+static int fc_config_add_match (fc_match_t **matches_head, /* {{{ */
+    oconfig_item_t *ci)
+{
+  fc_match_t *m;
+  fc_match_t *ptr;
+  int status;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("Filter subsystem: `Match' blocks require "
+        "exactly one string argument.");
+    return (-1);
+  }
+
+  ptr = match_list_head;
+  while (ptr != NULL)
+  {
+    if (strcasecmp (ptr->name, ci->values[0].value.string) == 0)
+      break;
+    ptr = ptr->next;
+  }
+
+  if (ptr == NULL)
+  {
+    WARNING ("Filter subsystem: Cannot find a \"%s\" match. "
+        "Did you load the appropriate plugin?",
+        ci->values[0].value.string);
+    return (-1);
+  }
+
+  m = (fc_match_t *) malloc (sizeof (*m));
+  if (m == NULL)
+  {
+    ERROR ("fc_config_add_match: malloc failed.");
+    return (-1);
+  }
+  memset (m, 0, sizeof (*m));
+
+  sstrncpy (m->name, ptr->name, sizeof (m->name));
+  memcpy (&m->proc, &ptr->proc, sizeof (m->proc));
+  m->user_data = NULL;
+  m->next = NULL;
+
+  if (m->proc.create != NULL)
+  {
+    status = (*m->proc.create) (ci, &m->user_data);
+    if (status != 0)
+    {
+      WARNING ("Filter subsystem: Failed to create a %s match.",
+          m->name);
+      fc_free_matches (m);
+      return (-1);
+    }
+  }
+
+  if (*matches_head != NULL)
+  {
+    ptr = *matches_head;
+    while (ptr->next != NULL)
+      ptr = ptr->next;
+
+    ptr->next = m;
+  }
+  else
+  {
+    *matches_head = m;
+  }
+
+  return (0);
+} /* }}} int fc_config_add_match */
+
+static int fc_config_add_target (fc_target_t **targets_head, /* {{{ */
+    oconfig_item_t *ci)
+{
+  fc_target_t *t;
+  fc_target_t *ptr;
+  int status;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("Filter subsystem: `Target' blocks require "
+        "exactly one string argument.");
+    return (-1);
+  }
+
+  ptr = target_list_head;
+  while (ptr != NULL)
+  {
+    if (strcasecmp (ptr->name, ci->values[0].value.string) == 0)
+      break;
+    ptr = ptr->next;
+  }
+
+  if (ptr == NULL)
+  {
+    WARNING ("Filter subsystem: Cannot find a \"%s\" target. "
+        "Did you load the appropriate plugin?",
+        ci->values[0].value.string);
+    return (-1);
+  }
+
+  t = (fc_target_t *) malloc (sizeof (*t));
+  if (t == NULL)
+  {
+    ERROR ("fc_config_add_target: malloc failed.");
+    return (-1);
+  }
+  memset (t, 0, sizeof (*t));
+
+  sstrncpy (t->name, ptr->name, sizeof (t->name));
+  memcpy (&t->proc, &ptr->proc, sizeof (t->proc));
+  t->user_data = NULL;
+  t->next = NULL;
+
+  if (t->proc.create != NULL)
+  {
+    status = (*t->proc.create) (ci, &t->user_data);
+    if (status != 0)
+    {
+      WARNING ("Filter subsystem: Failed to create a %s target.",
+          t->name);
+      fc_free_targets (t);
+      return (-1);
+    }
+  }
+  else
+  {
+    t->user_data = NULL;
+  }
+  
+  if (*targets_head != NULL)
+  {
+    ptr = *targets_head;
+    while (ptr->next != NULL)
+      ptr = ptr->next;
+
+    ptr->next = t;
+  }
+  else
+  {
+    *targets_head = t;
+  }
+
+  return (0);
+} /* }}} int fc_config_add_target */
+
+static int fc_config_add_rule (fc_chain_t *chain, /* {{{ */
+    oconfig_item_t *ci)
+{
+  fc_rule_t *rule;
+  char rule_name[2*DATA_MAX_NAME_LEN] = "Unnamed rule";
+  int status = 0;
+  int i;
+
+  if (ci->values_num > 1)
+  {
+    WARNING ("Filter subsystem: `Rule' blocks have at most one argument.");
+    return (-1);
+  }
+  else if ((ci->values_num == 1)
+      && (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("Filter subsystem: `Rule' blocks expect one string argument "
+        "or no argument at all.");
+    return (-1);
+  }
+
+  rule = (fc_rule_t *) malloc (sizeof (*rule));
+  if (rule == NULL)
+  {
+    ERROR ("fc_config_add_rule: malloc failed.");
+    return (-1);
+  }
+  memset (rule, 0, sizeof (*rule));
+  rule->next = NULL;
+
+  if (ci->values_num == 1)
+  {
+    sstrncpy (rule->name, ci->values[0].value.string, sizeof (rule->name));
+    ssnprintf (rule_name, sizeof (rule_name), "Rule \"%s\"",
+        ci->values[0].value.string);
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Match", option->key) == 0)
+      status = fc_config_add_match (&rule->matches, option);
+    else if (strcasecmp ("Target", option->key) == 0)
+      status = fc_config_add_target (&rule->targets, option);
+    else
+    {
+      WARNING ("Filter subsystem: %s: Option `%s' not allowed "
+          "inside a <Rule> block.", rule_name, option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (ci->children) */
+
+  /* Additional sanity checking. */
+  while (status == 0)
+  {
+    if (rule->targets == NULL)
+    {
+      WARNING ("Filter subsystem: %s: No target has been specified.",
+          rule_name);
+      status = -1;
+      break;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+  {
+    fc_free_rules (rule);
+    return (-1);
+  }
+
+  if (chain->rules != NULL)
+  {
+    fc_rule_t *ptr;
+
+    ptr = chain->rules;
+    while (ptr->next != NULL)
+      ptr = ptr->next;
+
+    ptr->next = rule;
+  }
+  else
+  {
+    chain->rules = rule;
+  }
+
+  return (0);
+} /* }}} int fc_config_add_rule */
+
+static int fc_config_add_chain (const oconfig_item_t *ci) /* {{{ */
+{
+  fc_chain_t *chain = NULL;
+  int status = 0;
+  int i;
+  int new_chain = 1;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("Filter subsystem: <Chain> blocks require exactly one "
+        "string argument.");
+    return (-1);
+  }
+
+  if (chain_list_head != NULL)
+  {
+    if ((chain = fc_chain_get_by_name (ci->values[0].value.string)) != NULL)
+      new_chain = 0;
+  }
+
+  if (chain == NULL)
+  {
+    chain = (fc_chain_t *) malloc (sizeof (*chain));
+    if (chain == NULL)
+    {
+      ERROR ("fc_config_add_chain: malloc failed.");
+      return (-1);
+    }
+    memset (chain, 0, sizeof (*chain));
+    sstrncpy (chain->name, ci->values[0].value.string, sizeof (chain->name));
+    chain->rules = NULL;
+    chain->targets = NULL;
+    chain->next = NULL;
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Rule", option->key) == 0)
+      status = fc_config_add_rule (chain, option);
+    else if (strcasecmp ("Target", option->key) == 0)
+      status = fc_config_add_target (&chain->targets, option);
+    else
+    {
+      WARNING ("Filter subsystem: Chain %s: Option `%s' not allowed "
+          "inside a <Chain> block.", chain->name, option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (ci->children) */
+
+  if (status != 0)
+  {
+    fc_free_chains (chain);
+    return (-1);
+  }
+
+  if (chain_list_head != NULL)
+  {
+    if (!new_chain)
+      return (0);
+
+    fc_chain_t *ptr;
+
+    ptr = chain_list_head;
+    while (ptr->next != NULL)
+      ptr = ptr->next;
+
+    ptr->next = chain;
+  }
+  else
+  {
+    chain_list_head = chain;
+  }
+
+  return (0);
+} /* }}} int fc_config_add_chain */
+
+/*
+ * Built-in target "jump"
+ *
+ * Prefix `bit' like `_b_uilt-_i_n _t_arget'
+ */
+static int fc_bit_jump_create (const oconfig_item_t *ci, /* {{{ */
+    void **user_data)
+{
+  oconfig_item_t *ci_chain;
+
+  if (ci->children_num != 1)
+  {
+    ERROR ("Filter subsystem: The built-in target `jump' needs exactly "
+        "one `Chain' argument!");
+    return (-1);
+  }
+
+  ci_chain = ci->children;
+  if (strcasecmp ("Chain", ci_chain->key) != 0)
+  {
+    ERROR ("Filter subsystem: The built-in target `jump' does not "
+        "support the configuration option `%s'.",
+        ci_chain->key);
+    return (-1);
+  }
+
+  if ((ci_chain->values_num != 1)
+      || (ci_chain->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("Filter subsystem: Built-in target `jump': The `Chain' option "
+        "needs exactly one string argument.");
+    return (-1);
+  }
+
+  *user_data = fc_strdup (ci_chain->values[0].value.string);
+  if (*user_data == NULL)
+  {
+    ERROR ("fc_bit_jump_create: fc_strdup failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int fc_bit_jump_create */
+
+static int fc_bit_jump_destroy (void **user_data) /* {{{ */
+{
+  if (user_data != NULL)
+  {
+    free (*user_data);
+    *user_data = NULL;
+  }
+
+  return (0);
+} /* }}} int fc_bit_jump_destroy */
+
+static int fc_bit_jump_invoke (const data_set_t *ds, /* {{{ */
+    value_list_t *vl, notification_meta_t __attribute__((unused)) **meta,
+    void **user_data)
+{
+  char *chain_name;
+  fc_chain_t *chain;
+  int status;
+
+  chain_name = *user_data;
+
+  for (chain = chain_list_head; chain != NULL; chain = chain->next)
+    if (strcasecmp (chain_name, chain->name) == 0)
+      break;
+
+  if (chain == NULL)
+  {
+    ERROR ("Filter subsystem: Built-in target `jump': There is no chain "
+        "named `%s'.", chain_name);
+    return (-1);
+  }
+
+  status = fc_process_chain (ds, vl, chain);
+  if (status < 0)
+    return (status);
+  else if (status == FC_TARGET_STOP)
+    return (FC_TARGET_STOP);
+  else
+    return (FC_TARGET_CONTINUE);
+} /* }}} int fc_bit_jump_invoke */
+
+static int fc_bit_stop_invoke (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+    value_list_t __attribute__((unused)) *vl,
+    notification_meta_t __attribute__((unused)) **meta,
+    void __attribute__((unused)) **user_data)
+{
+  return (FC_TARGET_STOP);
+} /* }}} int fc_bit_stop_invoke */
+
+static int fc_bit_return_invoke (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+    value_list_t __attribute__((unused)) *vl,
+    notification_meta_t __attribute__((unused)) **meta,
+    void __attribute__((unused)) **user_data)
+{
+  return (FC_TARGET_RETURN);
+} /* }}} int fc_bit_return_invoke */
+
+static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
+    void **user_data)
+{
+  int i;
+
+  fc_writer_t *plugin_list = NULL;
+  size_t plugin_list_len = 0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    fc_writer_t *temp;
+    int j;
+
+    if (strcasecmp ("Plugin", child->key) != 0)
+    {
+      ERROR ("Filter subsystem: The built-in target `write' does not "
+          "support the configuration option `%s'.",
+          child->key);
+      continue;
+    }
+
+    for (j = 0; j < child->values_num; j++)
+    {
+      char *plugin;
+
+      if (child->values[j].type != OCONFIG_TYPE_STRING)
+      {
+        ERROR ("Filter subsystem: Built-in target `write': "
+            "The `Plugin' option accepts only string arguments.");
+        continue;
+      }
+      plugin = child->values[j].value.string;
+
+      temp = (fc_writer_t *) realloc (plugin_list, (plugin_list_len + 2)
+          * (sizeof (*plugin_list)));
+      if (temp == NULL)
+      {
+        ERROR ("fc_bit_write_create: realloc failed.");
+        continue;
+      }
+      plugin_list = temp;
+
+      plugin_list[plugin_list_len].plugin = fc_strdup (plugin);
+      if (plugin_list[plugin_list_len].plugin == NULL)
+      {
+        ERROR ("fc_bit_write_create: fc_strdup failed.");
+        continue;
+      }
+      C_COMPLAIN_INIT (&plugin_list[plugin_list_len].complaint);
+      plugin_list_len++;
+      plugin_list[plugin_list_len].plugin = NULL;
+    } /* for (j = 0; j < child->values_num; j++) */
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  *user_data = plugin_list;
+
+  return (0);
+} /* }}} int fc_bit_write_create */
+
+static int fc_bit_write_destroy (void **user_data) /* {{{ */
+{
+  fc_writer_t *plugin_list;
+  size_t i;
+
+  if ((user_data == NULL) || (*user_data == NULL))
+    return (0);
+
+  plugin_list = *user_data;
+
+  for (i = 0; plugin_list[i].plugin != NULL; i++)
+    free (plugin_list[i].plugin);
+  free (plugin_list);
+
+  return (0);
+} /* }}} int fc_bit_write_destroy */
+
+static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
+    value_list_t *vl, notification_meta_t __attribute__((unused)) **meta,
+    void **user_data)
+{
+  fc_writer_t *plugin_list;
+  int status;
+
+  plugin_list = NULL;
+  if (user_data != NULL)
+    plugin_list = *user_data;
+
+  if ((plugin_list == NULL) || (plugin_list[0].plugin == NULL))
+  {
+    static c_complain_t write_complaint = C_COMPLAIN_INIT_STATIC;
+
+    status = plugin_write (/* plugin = */ NULL, ds, vl);
+    if (status == ENOENT)
+    {
+      /* in most cases this is a permanent error, so use the complain
+       * mechanism rather than spamming the logs */
+      c_complain (LOG_INFO, &write_complaint,
+          "Filter subsystem: Built-in target `write': Dispatching value to "
+          "all write plugins failed with status %i (ENOENT). "
+          "Most likely this means you didn't load any write plugins.",
+          status);
+
+      plugin_log_available_writers ();
+    }
+    else if (status != 0)
+    {
+      /* often, this is a permanent error (e.g. target system unavailable),
+       * so use the complain mechanism rather than spamming the logs */
+      c_complain (LOG_INFO, &write_complaint,
+          "Filter subsystem: Built-in target `write': Dispatching value to "
+          "all write plugins failed with status %i.", status);
+    }
+    else
+    {
+      assert (status == 0);
+      c_release (LOG_INFO, &write_complaint, "Filter subsystem: "
+          "Built-in target `write': Some write plugin is back to normal "
+          "operation. `write' succeeded.");
+    }
+  }
+  else
+  {
+    size_t i;
+
+    for (i = 0; plugin_list[i].plugin != NULL; i++)
+    {
+      status = plugin_write (plugin_list[i].plugin, ds, vl);
+      if (status != 0)
+      {
+        c_complain (LOG_INFO, &plugin_list[i].complaint,
+            "Filter subsystem: Built-in target `write': Dispatching value to "
+            "the `%s' plugin failed with status %i.",
+            plugin_list[i].plugin, status);
+
+        plugin_log_available_writers ();
+      }
+      else
+      {
+        c_release (LOG_INFO, &plugin_list[i].complaint,
+            "Filter subsystem: Built-in target `write': Plugin `%s' is back "
+            "to normal operation. `write' succeeded.", plugin_list[i].plugin);
+      }
+    } /* for (i = 0; plugin_list[i] != NULL; i++) */
+  }
+
+  return (FC_TARGET_CONTINUE);
+} /* }}} int fc_bit_write_invoke */
+
+static int fc_init_once (void) /* {{{ */
+{
+  static int done = 0;
+  target_proc_t tproc;
+
+  if (done != 0)
+    return (0);
+
+  memset (&tproc, 0, sizeof (tproc));
+  tproc.create  = fc_bit_jump_create;
+  tproc.destroy = fc_bit_jump_destroy;
+  tproc.invoke  = fc_bit_jump_invoke;
+  fc_register_target ("jump", tproc);
+
+  memset (&tproc, 0, sizeof (tproc));
+  tproc.create  = NULL;
+  tproc.destroy = NULL;
+  tproc.invoke  = fc_bit_stop_invoke;
+  fc_register_target ("stop", tproc);
+
+  memset (&tproc, 0, sizeof (tproc));
+  tproc.create  = NULL;
+  tproc.destroy = NULL;
+  tproc.invoke  = fc_bit_return_invoke;
+  fc_register_target ("return", tproc);
+
+  memset (&tproc, 0, sizeof (tproc));
+  tproc.create  = fc_bit_write_create;
+  tproc.destroy = fc_bit_write_destroy;
+  tproc.invoke  = fc_bit_write_invoke;
+  fc_register_target ("write", tproc);
+
+  done++;
+  return (0);
+} /* }}} int fc_init_once */
+
+/*
+ * Public functions
+ */
+/* Add a match to list of available matches. */
+int fc_register_match (const char *name, match_proc_t proc) /* {{{ */
+{
+  fc_match_t *m;
+
+  DEBUG ("fc_register_match (%s);", name);
+
+  m = (fc_match_t *) malloc (sizeof (*m));
+  if (m == NULL)
+    return (-ENOMEM);
+  memset (m, 0, sizeof (*m));
+
+  sstrncpy (m->name, name, sizeof (m->name));
+  memcpy (&m->proc, &proc, sizeof (m->proc));
+  m->next = NULL;
+
+  if (match_list_head == NULL)
+  {
+    match_list_head = m;
+  }
+  else
+  {
+    fc_match_t *ptr;
+
+    ptr = match_list_head;
+    while (ptr->next != NULL)
+      ptr = ptr->next;
+
+    ptr->next = m;
+  }
+
+  return (0);
+} /* }}} int fc_register_match */
+
+/* Add a target to list of available targets. */
+int fc_register_target (const char *name, target_proc_t proc) /* {{{ */
+{
+  fc_target_t *t;
+
+  DEBUG ("fc_register_target (%s);", name);
+
+  t = (fc_target_t *) malloc (sizeof (*t));
+  if (t == NULL)
+    return (-ENOMEM);
+  memset (t, 0, sizeof (*t));
+
+  sstrncpy (t->name, name, sizeof (t->name));
+  memcpy (&t->proc, &proc, sizeof (t->proc));
+  t->next = NULL;
+
+  if (target_list_head == NULL)
+  {
+    target_list_head = t;
+  }
+  else
+  {
+    fc_target_t *ptr;
+
+    ptr = target_list_head;
+    while (ptr->next != NULL)
+      ptr = ptr->next;
+
+    ptr->next = t;
+  }
+
+  return (0);
+} /* }}} int fc_register_target */
+
+fc_chain_t *fc_chain_get_by_name (const char *chain_name) /* {{{ */
+{
+  fc_chain_t *chain;
+
+  if (chain_name == NULL)
+    return (NULL);
+
+  for (chain = chain_list_head; chain != NULL; chain = chain->next)
+    if (strcasecmp (chain_name, chain->name) == 0)
+      return (chain);
+
+  return (NULL);
+} /* }}} int fc_chain_get_by_name */
+
+int fc_process_chain (const data_set_t *ds, value_list_t *vl, /* {{{ */
+    fc_chain_t *chain)
+{
+  fc_rule_t *rule;
+  fc_target_t *target;
+  int status;
+
+  if (chain == NULL)
+    return (-1);
+
+  DEBUG ("fc_process_chain (chain = %s);", chain->name);
+
+  status = FC_TARGET_CONTINUE;
+  for (rule = chain->rules; rule != NULL; rule = rule->next)
+  {
+    fc_match_t *match;
+
+    if (rule->name[0] != 0)
+    {
+      DEBUG ("fc_process_chain (%s): Testing the `%s' rule.",
+          chain->name, rule->name);
+    }
+
+    /* N. B.: rule->matches may be NULL. */
+    for (match = rule->matches; match != NULL; match = match->next)
+    {
+      /* FIXME: Pass the meta-data to match targets here (when implemented). */
+      status = (*match->proc.match) (ds, vl, /* meta = */ NULL,
+          &match->user_data);
+      if (status < 0)
+      {
+        WARNING ("fc_process_chain (%s): A match failed.", chain->name);
+        break;
+      }
+      else if (status != FC_MATCH_MATCHES)
+        break;
+    }
+
+    /* for-loop has been aborted: Either error or no match. */
+    if (match != NULL)
+    {
+      status = FC_TARGET_CONTINUE;
+      continue;
+    }
+
+    if (rule->name[0] != 0)
+    {
+      DEBUG ("fc_process_chain (%s): Rule `%s' matches.",
+          chain->name, rule->name);
+    }
+
+    for (target = rule->targets; target != NULL; target = target->next)
+    {
+      /* If we get here, all matches have matched the value. Execute the
+       * target. */
+      /* FIXME: Pass the meta-data to match targets here (when implemented). */
+      status = (*target->proc.invoke) (ds, vl, /* meta = */ NULL,
+          &target->user_data);
+      if (status < 0)
+      {
+        WARNING ("fc_process_chain (%s): A target failed.", chain->name);
+        continue;
+      }
+      else if (status == FC_TARGET_CONTINUE)
+        continue;
+      else if (status == FC_TARGET_STOP)
+        break;
+      else if (status == FC_TARGET_RETURN)
+        break;
+      else
+      {
+        WARNING ("fc_process_chain (%s): Unknown return value "
+            "from target `%s': %i",
+            chain->name, target->name, status);
+      }
+    }
+
+    if ((status == FC_TARGET_STOP)
+        || (status == FC_TARGET_RETURN))
+    {
+      if (rule->name[0] != 0)
+      {
+        DEBUG ("fc_process_chain (%s): Rule `%s' signaled "
+            "the %s condition.",
+            chain->name, rule->name,
+            (status == FC_TARGET_STOP) ? "stop" : "return");
+      }
+      break;
+    }
+    else
+    {
+      status = FC_TARGET_CONTINUE;
+    }
+  } /* for (rule) */
+
+  if (status == FC_TARGET_STOP)
+    return (FC_TARGET_STOP);
+  else if (status == FC_TARGET_RETURN)
+    return (FC_TARGET_CONTINUE);
+
+  /* for-loop has been aborted: A target returned `FC_TARGET_STOP' */
+  if (rule != NULL)
+    return (FC_TARGET_CONTINUE);
+
+  DEBUG ("fc_process_chain (%s): Executing the default targets.",
+      chain->name);
+
+  status = FC_TARGET_CONTINUE;
+  for (target = chain->targets; target != NULL; target = target->next)
+  {
+    /* If we get here, all matches have matched the value. Execute the
+     * target. */
+    /* FIXME: Pass the meta-data to match targets here (when implemented). */
+    status = (*target->proc.invoke) (ds, vl, /* meta = */ NULL,
+        &target->user_data);
+    if (status < 0)
+    {
+      WARNING ("fc_process_chain (%s): The default target failed.",
+          chain->name);
+    }
+    else if (status == FC_TARGET_CONTINUE)
+      continue;
+    else if (status == FC_TARGET_STOP)
+      break;
+    else if (status == FC_TARGET_RETURN)
+      break;
+    else
+    {
+      WARNING ("fc_process_chain (%s): Unknown return value "
+          "from target `%s': %i",
+          chain->name, target->name, status);
+    }
+  }
+
+  if ((status == FC_TARGET_STOP)
+      || (status == FC_TARGET_RETURN))
+  {
+    assert (target != NULL);
+    DEBUG ("fc_process_chain (%s): Default target `%s' signaled "
+        "the %s condition.",
+        chain->name, target->name,
+        (status == FC_TARGET_STOP) ? "stop" : "return");
+    if (status == FC_TARGET_STOP)
+      return (FC_TARGET_STOP);
+    else
+      return (FC_TARGET_CONTINUE);
+  }
+
+  DEBUG ("fc_process_chain (%s): Signaling `continue' at end of chain.",
+      chain->name);
+
+  return (FC_TARGET_CONTINUE);
+} /* }}} int fc_process_chain */
+
+/* Iterate over all rules in the chain and execute all targets for which all
+ * matches match. */
+int fc_default_action (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  /* FIXME: Pass the meta-data to match targets here (when implemented). */
+  return (fc_bit_write_invoke (ds, vl,
+        /* meta = */ NULL, /* user_data = */ NULL));
+} /* }}} int fc_default_action */
+
+int fc_configure (const oconfig_item_t *ci) /* {{{ */
+{
+  fc_init_once ();
+
+  if (ci == NULL)
+    return (-EINVAL);
+
+  if (strcasecmp ("Chain", ci->key) == 0)
+    return (fc_config_add_chain (ci));
+
+  WARNING ("Filter subsystem: Unknown top level config option `%s'.",
+      ci->key);
+
+  return (-1);
+} /* }}} int fc_configure */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/daemon/filter_chain.h b/src/daemon/filter_chain.h
new file mode 100644 (file)
index 0000000..2db90db
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * collectd - src/filter_chain.h
+ * Copyright (C) 2008,2009  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef FILTER_CHAIN_H
+#define FILTER_CHAIN_H 1
+
+#include "collectd.h"
+#include "plugin.h"
+
+#define FC_MATCH_NO_MATCH  0
+#define FC_MATCH_MATCHES   1
+
+#define FC_TARGET_CONTINUE 0
+#define FC_TARGET_STOP     1
+#define FC_TARGET_RETURN   2
+
+/*
+ * Match functions
+ */
+struct match_proc_s
+{
+  int (*create) (const oconfig_item_t *ci, void **user_data);
+  int (*destroy) (void **user_data);
+  int (*match) (const data_set_t *ds, const value_list_t *vl,
+      notification_meta_t **meta, void **user_data);
+};
+typedef struct match_proc_s match_proc_t;
+
+int fc_register_match (const char *name, match_proc_t proc);
+
+/*
+ * Target functions
+ */
+struct target_proc_s
+{
+  int (*create) (const oconfig_item_t *ci, void **user_data);
+  int (*destroy) (void **user_data);
+  int (*invoke) (const data_set_t *ds, value_list_t *vl,
+      notification_meta_t **meta, void **user_data);
+};
+typedef struct target_proc_s target_proc_t;
+
+struct fc_chain_s;
+typedef struct fc_chain_s fc_chain_t;
+
+int fc_register_target (const char *name, target_proc_t proc);
+
+/*
+ * TODO: Chain management
+ */
+#if 0
+int fc_chain_add (const char *chain_name,
+    const char *target_name, int target_argc, char **target_argv);
+int fc_chain_delete (const char *chain_name);
+#endif
+
+/*
+ * TODO: Rule management
+ */
+#if 0
+int fc_rule_add (const char *chain_name, int position,
+    int match_num, const char **match_name, int *match_argc, char ***match_argv,
+    const char *target_name, int target_argc, char **target_argv);
+int fc_rule_delete (const char *chain_name, int position);
+#endif
+
+/*
+ * Processing function
+ */
+fc_chain_t *fc_chain_get_by_name (const char *chain_name);
+
+int fc_process_chain (const data_set_t *ds, value_list_t *vl,
+    fc_chain_t *chain);
+
+int fc_default_action (const data_set_t *ds, value_list_t *vl);
+
+/* 
+ * Shortcut for global configuration
+ */
+int fc_configure (const oconfig_item_t *ci);
+
+#endif /* FILTER_CHAIN_H */
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/meta_data.c b/src/daemon/meta_data.c
new file mode 100644 (file)
index 0000000..6ee8446
--- /dev/null
@@ -0,0 +1,637 @@
+/**
+ * collectd - src/meta_data.c
+ * Copyright (C) 2008-2011  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "meta_data.h"
+
+#include <pthread.h>
+
+/*
+ * Data types
+ */
+union meta_value_u
+{
+  char    *mv_string;
+  int64_t  mv_signed_int;
+  uint64_t mv_unsigned_int;
+  double   mv_double;
+  _Bool    mv_boolean;
+};
+typedef union meta_value_u meta_value_t;
+
+struct meta_entry_s;
+typedef struct meta_entry_s meta_entry_t;
+struct meta_entry_s
+{
+  char         *key;
+  meta_value_t  value;
+  int           type;
+  meta_entry_t *next;
+};
+
+struct meta_data_s
+{
+  meta_entry_t   *head;
+  pthread_mutex_t lock;
+};
+
+/*
+ * Private functions
+ */
+static char *md_strdup (const char *orig) /* {{{ */
+{
+  size_t sz;
+  char *dest;
+
+  if (orig == NULL)
+    return (NULL);
+
+  sz = strlen (orig) + 1;
+  dest = (char *) malloc (sz);
+  if (dest == NULL)
+    return (NULL);
+
+  memcpy (dest, orig, sz);
+
+  return (dest);
+} /* }}} char *md_strdup */
+
+static meta_entry_t *md_entry_alloc (const char *key) /* {{{ */
+{
+  meta_entry_t *e;
+
+  e = (meta_entry_t *) malloc (sizeof (*e));
+  if (e == NULL)
+  {
+    ERROR ("md_entry_alloc: malloc failed.");
+    return (NULL);
+  }
+  memset (e, 0, sizeof (*e));
+
+  e->key = md_strdup (key);
+  if (e->key == NULL)
+  {
+    free (e);
+    ERROR ("md_entry_alloc: md_strdup failed.");
+    return (NULL);
+  }
+
+  e->type = 0;
+  e->next = NULL;
+
+  return (e);
+} /* }}} meta_entry_t *md_entry_alloc */
+
+static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+{
+  meta_entry_t *copy;
+
+  if (orig == NULL)
+    return (NULL);
+
+  copy = md_entry_alloc (orig->key);
+  copy->type = orig->type;
+  if (copy->type == MD_TYPE_STRING)
+    copy->value.mv_string = strdup (orig->value.mv_string);
+  else
+    copy->value = orig->value;
+
+  copy->next = md_entry_clone (orig->next);
+  return (copy);
+} /* }}} meta_entry_t *md_entry_clone */
+
+static void md_entry_free (meta_entry_t *e) /* {{{ */
+{
+  if (e == NULL)
+    return;
+
+  free (e->key);
+
+  if (e->type == MD_TYPE_STRING)
+    free (e->value.mv_string);
+
+  if (e->next != NULL)
+    md_entry_free (e->next);
+
+  free (e);
+} /* }}} void md_entry_free */
+
+static int md_entry_insert (meta_data_t *md, meta_entry_t *e) /* {{{ */
+{
+  meta_entry_t *this;
+  meta_entry_t *prev;
+
+  if ((md == NULL) || (e == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  prev = NULL;
+  this = md->head;
+  while (this != NULL)
+  {
+    if (strcasecmp (e->key, this->key) == 0)
+      break;
+
+    prev = this;
+    this = this->next;
+  }
+
+  if (this == NULL)
+  {
+    /* This key does not exist yet. */
+    if (md->head == NULL)
+      md->head = e;
+    else
+    {
+      assert (prev != NULL);
+      prev->next = e;
+    }
+
+    e->next = NULL;
+  }
+  else /* (this != NULL) */
+  {
+    if (prev == NULL)
+      md->head = e;
+    else
+      prev->next = e;
+
+    e->next = this->next;
+  }
+
+  pthread_mutex_unlock (&md->lock);
+
+  if (this != NULL)
+  {
+    this->next = NULL;
+    md_entry_free (this);
+  }
+
+  return (0);
+} /* }}} int md_entry_insert */
+
+/* XXX: The lock on md must be held while calling this function! */
+static meta_entry_t *md_entry_lookup (meta_data_t *md, /* {{{ */
+    const char *key)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL))
+    return (NULL);
+
+  for (e = md->head; e != NULL; e = e->next)
+    if (strcasecmp (key, e->key) == 0)
+      break;
+
+  return (e);
+} /* }}} meta_entry_t *md_entry_lookup */
+
+/*
+ * Public functions
+ */
+meta_data_t *meta_data_create (void) /* {{{ */
+{
+  meta_data_t *md;
+
+  md = (meta_data_t *) malloc (sizeof (*md));
+  if (md == NULL)
+  {
+    ERROR ("meta_data_create: malloc failed.");
+    return (NULL);
+  }
+  memset (md, 0, sizeof (*md));
+
+  md->head = NULL;
+  pthread_mutex_init (&md->lock, /* attr = */ NULL);
+
+  return (md);
+} /* }}} meta_data_t *meta_data_create */
+
+meta_data_t *meta_data_clone (meta_data_t *orig) /* {{{ */
+{
+  meta_data_t *copy;
+
+  if (orig == NULL)
+    return (NULL);
+
+  copy = meta_data_create ();
+  if (copy == NULL)
+    return (NULL);
+
+  pthread_mutex_lock (&orig->lock);
+  copy->head = md_entry_clone (orig->head);
+  pthread_mutex_unlock (&orig->lock);
+
+  return (copy);
+} /* }}} meta_data_t *meta_data_clone */
+
+void meta_data_destroy (meta_data_t *md) /* {{{ */
+{
+  if (md == NULL)
+    return;
+
+  pthread_mutex_destroy(&md->lock);
+  md_entry_free (md->head);
+  pthread_mutex_destroy (&md->lock);
+  free (md);
+} /* }}} void meta_data_destroy */
+
+int meta_data_exists (meta_data_t *md, const char *key) /* {{{ */
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  for (e = md->head; e != NULL; e = e->next)
+  {
+    if (strcasecmp (key, e->key) == 0)
+    {
+      pthread_mutex_unlock (&md->lock);
+      return (1);
+    }
+  }
+
+  pthread_mutex_unlock (&md->lock);
+  return (0);
+} /* }}} int meta_data_exists */
+
+int meta_data_type (meta_data_t *md, const char *key) /* {{{ */
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL))
+    return -EINVAL;
+
+  pthread_mutex_lock (&md->lock);
+
+  for (e = md->head; e != NULL; e = e->next)
+  {
+    if (strcasecmp (key, e->key) == 0)
+    {
+      pthread_mutex_unlock (&md->lock);
+      return e->type;
+    }
+  }
+
+  pthread_mutex_unlock (&md->lock);
+  return 0;
+} /* }}} int meta_data_type */
+
+int meta_data_toc (meta_data_t *md, char ***toc) /* {{{ */
+{
+  int i = 0, count = 0;
+  meta_entry_t *e;
+
+  if ((md == NULL) || (toc == NULL))
+    return -EINVAL;
+
+  pthread_mutex_lock (&md->lock);
+
+  for (e = md->head; e != NULL; e = e->next)
+    ++count;    
+
+  if (count == 0)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (count);
+  }
+
+  *toc = calloc(count, sizeof(**toc));
+  for (e = md->head; e != NULL; e = e->next)
+    (*toc)[i++] = strdup(e->key);
+  
+  pthread_mutex_unlock (&md->lock);
+  return count;
+} /* }}} int meta_data_toc */
+
+int meta_data_delete (meta_data_t *md, const char *key) /* {{{ */
+{
+  meta_entry_t *this;
+  meta_entry_t *prev;
+
+  if ((md == NULL) || (key == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  prev = NULL;
+  this = md->head;
+  while (this != NULL)
+  {
+    if (strcasecmp (key, this->key) == 0)
+      break;
+
+    prev = this;
+    this = this->next;
+  }
+
+  if (this == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  if (prev == NULL)
+    md->head = this->next;
+  else
+    prev->next = this->next;
+
+  pthread_mutex_unlock (&md->lock);
+
+  this->next = NULL;
+  md_entry_free (this);
+
+  return (0);
+} /* }}} int meta_data_delete */
+
+/*
+ * Add functions
+ */
+int meta_data_add_string (meta_data_t *md, /* {{{ */
+    const char *key, const char *value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL) || (value == NULL))
+    return (-EINVAL);
+
+  e = md_entry_alloc (key);
+  if (e == NULL)
+    return (-ENOMEM);
+
+  e->value.mv_string = md_strdup (value);
+  if (e->value.mv_string == NULL)
+  {
+    ERROR ("meta_data_add_string: md_strdup failed.");
+    md_entry_free (e);
+    return (-ENOMEM);
+  }
+  e->type = MD_TYPE_STRING;
+
+  return (md_entry_insert (md, e));
+} /* }}} int meta_data_add_string */
+
+int meta_data_add_signed_int (meta_data_t *md, /* {{{ */
+    const char *key, int64_t value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL))
+    return (-EINVAL);
+
+  e = md_entry_alloc (key);
+  if (e == NULL)
+    return (-ENOMEM);
+
+  e->value.mv_signed_int = value;
+  e->type = MD_TYPE_SIGNED_INT;
+
+  return (md_entry_insert (md, e));
+} /* }}} int meta_data_add_signed_int */
+
+int meta_data_add_unsigned_int (meta_data_t *md, /* {{{ */
+    const char *key, uint64_t value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL))
+    return (-EINVAL);
+
+  e = md_entry_alloc (key);
+  if (e == NULL)
+    return (-ENOMEM);
+
+  e->value.mv_unsigned_int = value;
+  e->type = MD_TYPE_UNSIGNED_INT;
+
+  return (md_entry_insert (md, e));
+} /* }}} int meta_data_add_unsigned_int */
+
+int meta_data_add_double (meta_data_t *md, /* {{{ */
+    const char *key, double value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL))
+    return (-EINVAL);
+
+  e = md_entry_alloc (key);
+  if (e == NULL)
+    return (-ENOMEM);
+
+  e->value.mv_double = value;
+  e->type = MD_TYPE_DOUBLE;
+
+  return (md_entry_insert (md, e));
+} /* }}} int meta_data_add_double */
+
+int meta_data_add_boolean (meta_data_t *md, /* {{{ */
+    const char *key, _Bool value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL))
+    return (-EINVAL);
+
+  e = md_entry_alloc (key);
+  if (e == NULL)
+    return (-ENOMEM);
+
+  e->value.mv_boolean = value;
+  e->type = MD_TYPE_BOOLEAN;
+
+  return (md_entry_insert (md, e));
+} /* }}} int meta_data_add_boolean */
+
+/*
+ * Get functions
+ */
+int meta_data_get_string (meta_data_t *md, /* {{{ */
+    const char *key, char **value)
+{
+  meta_entry_t *e;
+  char *temp;
+
+  if ((md == NULL) || (key == NULL) || (value == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  e = md_entry_lookup (md, key);
+  if (e == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  if (e->type != MD_TYPE_STRING)
+  {
+    ERROR ("meta_data_get_string: Type mismatch for key `%s'", e->key);
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  temp = md_strdup (e->value.mv_string);
+  if (temp == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    ERROR ("meta_data_get_string: md_strdup failed.");
+    return (-ENOMEM);
+  }
+  pthread_mutex_unlock (&md->lock);
+
+  *value = temp;
+
+  return (0);
+} /* }}} int meta_data_get_string */
+
+int meta_data_get_signed_int (meta_data_t *md, /* {{{ */
+    const char *key, int64_t *value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL) || (value == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  e = md_entry_lookup (md, key);
+  if (e == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  if (e->type != MD_TYPE_SIGNED_INT)
+  {
+    ERROR ("meta_data_get_signed_int: Type mismatch for key `%s'", e->key);
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  *value = e->value.mv_signed_int;
+
+  pthread_mutex_unlock (&md->lock);
+  return (0);
+} /* }}} int meta_data_get_signed_int */
+
+int meta_data_get_unsigned_int (meta_data_t *md, /* {{{ */
+    const char *key, uint64_t *value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL) || (value == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  e = md_entry_lookup (md, key);
+  if (e == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  if (e->type != MD_TYPE_UNSIGNED_INT)
+  {
+    ERROR ("meta_data_get_unsigned_int: Type mismatch for key `%s'", e->key);
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  *value = e->value.mv_unsigned_int;
+
+  pthread_mutex_unlock (&md->lock);
+  return (0);
+} /* }}} int meta_data_get_unsigned_int */
+
+int meta_data_get_double (meta_data_t *md, /* {{{ */
+    const char *key, double *value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL) || (value == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  e = md_entry_lookup (md, key);
+  if (e == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  if (e->type != MD_TYPE_DOUBLE)
+  {
+    ERROR ("meta_data_get_double: Type mismatch for key `%s'", e->key);
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  *value = e->value.mv_double;
+
+  pthread_mutex_unlock (&md->lock);
+  return (0);
+} /* }}} int meta_data_get_double */
+
+int meta_data_get_boolean (meta_data_t *md, /* {{{ */
+    const char *key, _Bool *value)
+{
+  meta_entry_t *e;
+
+  if ((md == NULL) || (key == NULL) || (value == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&md->lock);
+
+  e = md_entry_lookup (md, key);
+  if (e == NULL)
+  {
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  if (e->type != MD_TYPE_BOOLEAN)
+  {
+    ERROR ("meta_data_get_boolean: Type mismatch for key `%s'", e->key);
+    pthread_mutex_unlock (&md->lock);
+    return (-ENOENT);
+  }
+
+  *value = e->value.mv_boolean;
+
+  pthread_mutex_unlock (&md->lock);
+  return (0);
+} /* }}} int meta_data_get_boolean */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/daemon/meta_data.h b/src/daemon/meta_data.h
new file mode 100644 (file)
index 0000000..fa48df3
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+ * collectd - src/meta_data.h
+ * Copyright (C) 2008-2011  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef META_DATA_H
+#define META_DATA_H
+
+#include "collectd.h"
+
+/*
+ * Defines
+ */
+#define MD_TYPE_STRING       1
+#define MD_TYPE_SIGNED_INT   2
+#define MD_TYPE_UNSIGNED_INT 3
+#define MD_TYPE_DOUBLE       4
+#define MD_TYPE_BOOLEAN      5
+
+struct meta_data_s;
+typedef struct meta_data_s meta_data_t;
+
+meta_data_t *meta_data_create (void);
+meta_data_t *meta_data_clone (meta_data_t *orig);
+void meta_data_destroy (meta_data_t *md);
+
+int meta_data_exists (meta_data_t *md, const char *key);
+int meta_data_type (meta_data_t *md, const char *key);
+int meta_data_toc (meta_data_t *md, char ***toc);
+int meta_data_delete (meta_data_t *md, const char *key);
+
+int meta_data_add_string (meta_data_t *md,
+    const char *key,
+    const char *value);
+int meta_data_add_signed_int (meta_data_t *md,
+    const char *key,
+    int64_t value);
+int meta_data_add_unsigned_int (meta_data_t *md,
+    const char *key,
+    uint64_t value);
+int meta_data_add_double (meta_data_t *md,
+    const char *key,
+    double value);
+int meta_data_add_boolean (meta_data_t *md,
+    const char *key,
+    _Bool value);
+
+int meta_data_get_string (meta_data_t *md,
+    const char *key,
+    char **value);
+int meta_data_get_signed_int (meta_data_t *md,
+    const char *key,
+    int64_t *value);
+int meta_data_get_unsigned_int (meta_data_t *md,
+    const char *key,
+    uint64_t *value);
+int meta_data_get_double (meta_data_t *md,
+    const char *key,
+    double *value);
+int meta_data_get_boolean (meta_data_t *md,
+    const char *key,
+    _Bool *value);
+
+#endif /* META_DATA_H */
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c
new file mode 100644 (file)
index 0000000..3d36445
--- /dev/null
@@ -0,0 +1,2727 @@
+/**
+ * collectd - src/plugin.c
+ * Copyright (C) 2005-2014  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "filter_chain.h"
+#include "utils_avltree.h"
+#include "utils_cache.h"
+#include "utils_complain.h"
+#include "utils_llist.h"
+#include "utils_heap.h"
+#include "utils_time.h"
+#include "utils_random.h"
+
+#include <ltdl.h>
+
+/*
+ * Private structures
+ */
+struct callback_func_s
+{
+       void *cf_callback;
+       user_data_t cf_udata;
+       plugin_ctx_t cf_ctx;
+};
+typedef struct callback_func_s callback_func_t;
+
+#define RF_SIMPLE  0
+#define RF_COMPLEX 1
+#define RF_REMOVE  65535
+struct read_func_s
+{
+       /* `read_func_t' "inherits" from `callback_func_t'.
+        * The `rf_super' member MUST be the first one in this structure! */
+#define rf_callback rf_super.cf_callback
+#define rf_udata rf_super.cf_udata
+#define rf_ctx rf_super.cf_ctx
+       callback_func_t rf_super;
+       char rf_group[DATA_MAX_NAME_LEN];
+       char *rf_name;
+       int rf_type;
+       cdtime_t rf_interval;
+       cdtime_t rf_effective_interval;
+       cdtime_t rf_next_read;
+};
+typedef struct read_func_s read_func_t;
+
+struct write_queue_s;
+typedef struct write_queue_s write_queue_t;
+struct write_queue_s
+{
+       value_list_t *vl;
+       plugin_ctx_t ctx;
+       write_queue_t *next;
+};
+
+/*
+ * Private variables
+ */
+static c_avl_tree_t *plugins_loaded = NULL;
+
+static llist_t *list_init;
+static llist_t *list_write;
+static llist_t *list_flush;
+static llist_t *list_missing;
+static llist_t *list_shutdown;
+static llist_t *list_log;
+static llist_t *list_notification;
+
+static fc_chain_t *pre_cache_chain = NULL;
+static fc_chain_t *post_cache_chain = NULL;
+
+static c_avl_tree_t *data_sets;
+
+static char *plugindir = NULL;
+
+#ifndef DEFAULT_MAX_READ_INTERVAL
+# define DEFAULT_MAX_READ_INTERVAL TIME_T_TO_CDTIME_T (86400)
+#endif
+static c_heap_t       *read_heap = NULL;
+static llist_t        *read_list;
+static int             read_loop = 1;
+static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  read_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t      *read_threads = NULL;
+static int             read_threads_num = 0;
+static cdtime_t        max_read_interval = DEFAULT_MAX_READ_INTERVAL;
+
+static write_queue_t  *write_queue_head;
+static write_queue_t  *write_queue_tail;
+static long            write_queue_length = 0;
+static _Bool           write_loop = 1;
+static pthread_mutex_t write_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  write_cond = PTHREAD_COND_INITIALIZER;
+static pthread_t      *write_threads = NULL;
+static size_t          write_threads_num = 0;
+
+static pthread_key_t   plugin_ctx_key;
+static _Bool           plugin_ctx_key_initialized = 0;
+
+static long            write_limit_high = 0;
+static long            write_limit_low = 0;
+
+static derive_t        stats_values_dropped = 0;
+static _Bool           record_statistics = 0;
+
+/*
+ * Static functions
+ */
+static int plugin_dispatch_values_internal (value_list_t *vl);
+
+static const char *plugin_get_dir (void)
+{
+       if (plugindir == NULL)
+               return (PLUGINDIR);
+       else
+               return (plugindir);
+}
+
+static void plugin_update_internal_statistics (void) { /* {{{ */
+       derive_t copy_write_queue_length;
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t values[2];
+
+       copy_write_queue_length = write_queue_length;
+
+       /* Initialize `vl' */
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = 0;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "collectd", sizeof (vl.plugin));
+
+       vl.type_instance[0] = 0;
+       vl.values_len = 1;
+
+       /* Write queue */
+       sstrncpy (vl.plugin_instance, "write_queue",
+                       sizeof (vl.plugin_instance));
+
+       /* Write queue : queue length */
+       vl.values[0].gauge = (gauge_t) copy_write_queue_length;
+       sstrncpy (vl.type, "queue_length", sizeof (vl.type));
+       vl.type_instance[0] = 0;
+       plugin_dispatch_values (&vl);
+
+       /* Write queue : Values dropped (queue length > low limit) */
+       vl.values[0].derive = (derive_t) stats_values_dropped;
+       sstrncpy (vl.type, "derive", sizeof (vl.type));
+       sstrncpy (vl.type_instance, "dropped", sizeof (vl.type_instance));
+       plugin_dispatch_values (&vl);
+
+       /* Cache */
+       sstrncpy (vl.plugin_instance, "cache",
+                       sizeof (vl.plugin_instance));
+
+       /* Cache : Nb entry in cache tree */
+       vl.values[0].gauge = (gauge_t) uc_get_size();
+       sstrncpy (vl.type, "cache_size", sizeof (vl.type));
+       vl.type_instance[0] = 0;
+       plugin_dispatch_values (&vl);
+
+       return;
+} /* }}} void plugin_update_internal_statistics */
+
+static void destroy_callback (callback_func_t *cf) /* {{{ */
+{
+       if (cf == NULL)
+               return;
+
+       if ((cf->cf_udata.data != NULL) && (cf->cf_udata.free_func != NULL))
+       {
+               cf->cf_udata.free_func (cf->cf_udata.data);
+               cf->cf_udata.data = NULL;
+               cf->cf_udata.free_func = NULL;
+       }
+       sfree (cf);
+} /* }}} void destroy_callback */
+
+static void destroy_all_callbacks (llist_t **list) /* {{{ */
+{
+       llentry_t *le;
+
+       if (*list == NULL)
+               return;
+
+       le = llist_head (*list);
+       while (le != NULL)
+       {
+               llentry_t *le_next;
+
+               le_next = le->next;
+
+               sfree (le->key);
+               destroy_callback (le->value);
+               le->value = NULL;
+
+               le = le_next;
+       }
+
+       llist_destroy (*list);
+       *list = NULL;
+} /* }}} void destroy_all_callbacks */
+
+static void destroy_read_heap (void) /* {{{ */
+{
+       if (read_heap == NULL)
+               return;
+
+       while (42)
+       {
+               callback_func_t *cf;
+
+               cf = c_heap_get_root (read_heap);
+               if (cf == NULL)
+                       break;
+
+               destroy_callback (cf);
+       }
+
+       c_heap_destroy (read_heap);
+       read_heap = NULL;
+} /* }}} void destroy_read_heap */
+
+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 ();
+               if (*list == NULL)
+               {
+                       ERROR ("plugin: register_callback: "
+                                       "llist_create failed.");
+                       destroy_callback (cf);
+                       return (-1);
+               }
+       }
+
+       key = strdup (name);
+       if (key == NULL)
+       {
+               ERROR ("plugin: register_callback: strdup failed.");
+               destroy_callback (cf);
+               return (-1);
+       }
+
+       le = llist_search (*list, name);
+       if (le == NULL)
+       {
+               le = llentry_create (key, cf);
+               if (le == NULL)
+               {
+                       ERROR ("plugin: register_callback: "
+                                       "llentry_create failed.");
+                       free (key);
+                       destroy_callback (cf);
+                       return (-1);
+               }
+
+               llist_append (*list, le);
+       }
+       else
+       {
+               callback_func_t *old_cf;
+
+               old_cf = le->value;
+               le->value = cf;
+
+               WARNING ("plugin: register_callback: "
+                               "a callback named `%s' already exists - "
+                               "overwriting the old entry!", name);
+
+               destroy_callback (old_cf);
+               sfree (key);
+       }
+
+       return (0);
+} /* }}} int register_callback */
+
+static void log_list_callbacks (llist_t **list, /* {{{ */
+                               const char *comment)
+{
+       char *str;
+       int len;
+       llentry_t *le;
+       int i;
+       int n;
+       char **keys;
+
+       n = llist_size(*list);
+       if (n == 0)
+       {
+               INFO("%s [none]", comment);
+               return;
+       }
+
+       keys = calloc(n, sizeof(char*));
+
+       if (keys == NULL)
+       {
+               ERROR("%s: failed to allocate memory for list of callbacks",
+                     comment);
+
+               return;
+       }
+
+       for (le = llist_head (*list), i = 0, len = 0;
+            le != NULL;
+            le = le->next, i++)
+       {
+               keys[i] = le->key;
+               len += strlen(le->key) + 6;
+       }
+       str = malloc(len + 10);
+       if (str == NULL)
+       {
+               ERROR("%s: failed to allocate memory for list of callbacks",
+                     comment);
+       }
+       else
+       {
+               *str = '\0';
+               strjoin(str, len, keys, n, "', '");
+               INFO("%s ['%s']", comment, str);
+               free(str);
+       }
+       free(keys);
+} /* }}} void log_list_callbacks */
+
+static int create_register_callback (llist_t **list, /* {{{ */
+               const char *name, void *callback, user_data_t *ud)
+{
+       callback_func_t *cf;
+
+       cf = (callback_func_t *) malloc (sizeof (*cf));
+       if (cf == NULL)
+       {
+               ERROR ("plugin: create_register_callback: malloc failed.");
+               return (-1);
+       }
+       memset (cf, 0, sizeof (*cf));
+
+       cf->cf_callback = callback;
+       if (ud == NULL)
+       {
+               cf->cf_udata.data = NULL;
+               cf->cf_udata.free_func = NULL;
+       }
+       else
+       {
+               cf->cf_udata = *ud;
+       }
+
+       cf->cf_ctx = plugin_get_ctx ();
+
+       return (register_callback (list, name, cf));
+} /* }}} int create_register_callback */
+
+static int plugin_unregister (llist_t *list, const char *name) /* {{{ */
+{
+       llentry_t *e;
+
+       if (list == NULL)
+               return (-1);
+
+       e = llist_search (list, name);
+       if (e == NULL)
+               return (-1);
+
+       llist_remove (list, e);
+
+       sfree (e->key);
+       destroy_callback (e->value);
+
+       llentry_destroy (e);
+
+       return (0);
+} /* }}} int plugin_unregister */
+
+/*
+ * (Try to) load the shared object `file'. Won't complain if it isn't a shared
+ * object, but it will bitch about a shared object not having a
+ * ``module_register'' symbol..
+ */
+static int plugin_load_file (char *file, uint32_t flags)
+{
+       lt_dlhandle dlh;
+       void (*reg_handle) (void);
+
+       lt_dlinit ();
+       lt_dlerror (); /* clear errors */
+
+#if LIBTOOL_VERSION == 2
+       if (flags & PLUGIN_FLAGS_GLOBAL) {
+               lt_dladvise advise;
+               lt_dladvise_init(&advise);
+               lt_dladvise_global(&advise);
+               dlh = lt_dlopenadvise(file, advise);
+               lt_dladvise_destroy(&advise);
+       } else {
+               dlh = lt_dlopen (file);
+       }
+#else /* if LIBTOOL_VERSION == 1 */
+       if (flags & PLUGIN_FLAGS_GLOBAL)
+               WARNING ("plugin_load_file: The global flag is not supported, "
+                               "libtool 2 is required for this.");
+       dlh = lt_dlopen (file);
+#endif
+
+       if (dlh == NULL)
+       {
+               char errbuf[1024] = "";
+
+               ssnprintf (errbuf, sizeof (errbuf),
+                               "lt_dlopen (\"%s\") failed: %s. "
+                               "The most common cause for this problem is "
+                               "missing dependencies. Use ldd(1) to check "
+                               "the dependencies of the plugin "
+                               "/ shared object.",
+                               file, lt_dlerror ());
+
+               ERROR ("%s", errbuf);
+               /* Make sure this is printed to STDERR in any case, but also
+                * make sure it's printed only once. */
+               if (list_log != NULL)
+                       fprintf (stderr, "ERROR: %s\n", errbuf);
+
+               return (1);
+       }
+
+       if ((reg_handle = (void (*) (void)) lt_dlsym (dlh, "module_register")) == NULL)
+       {
+               WARNING ("Couldn't find symbol \"module_register\" in \"%s\": %s\n",
+                               file, lt_dlerror ());
+               lt_dlclose (dlh);
+               return (-1);
+       }
+
+       (*reg_handle) ();
+
+       return (0);
+}
+
+static void *plugin_read_thread (void __attribute__((unused)) *args)
+{
+       while (read_loop != 0)
+       {
+               read_func_t *rf;
+               plugin_ctx_t old_ctx;
+               cdtime_t now;
+               int status;
+               int rf_type;
+               int rc;
+
+               /* Get the read function that needs to be read next.
+                * We don't need to hold "read_lock" for the heap, but we need
+                * to call c_heap_get_root() and pthread_cond_wait() in the
+                * same protected block. */
+               pthread_mutex_lock (&read_lock);
+               rf = c_heap_get_root (read_heap);
+               if (rf == NULL)
+               {
+                       pthread_cond_wait (&read_cond, &read_lock);
+                        pthread_mutex_unlock (&read_lock);
+                       continue;
+               }
+               pthread_mutex_unlock (&read_lock);
+
+               if (rf->rf_interval == 0)
+               {
+                       /* this should not happen, because the interval is set
+                        * for each plugin when loading it
+                        * XXX: issue a warning? */
+                       rf->rf_interval = plugin_get_interval ();
+                       rf->rf_effective_interval = rf->rf_interval;
+
+                       rf->rf_next_read = cdtime ();
+               }
+
+               /* sleep until this entry is due,
+                * using pthread_cond_timedwait */
+               pthread_mutex_lock (&read_lock);
+               /* In pthread_cond_timedwait, spurious wakeups are possible
+                * (and really happen, at least on NetBSD with > 1 CPU), thus
+                * we need to re-evaluate the condition every time
+                * pthread_cond_timedwait returns. */
+               rc = 0;
+               while ((read_loop != 0)
+                               && (cdtime () < rf->rf_next_read)
+                               && rc == 0)
+               {
+                       struct timespec ts = { 0 };
+
+                       CDTIME_T_TO_TIMESPEC (rf->rf_next_read, &ts);
+
+                       rc = pthread_cond_timedwait (&read_cond, &read_lock,
+                               &ts);
+               }
+
+               /* Must hold `read_lock' when accessing `rf->rf_type'. */
+               rf_type = rf->rf_type;
+               pthread_mutex_unlock (&read_lock);
+
+               /* Check if we're supposed to stop.. This may have interrupted
+                * the sleep, too. */
+               if (read_loop == 0)
+               {
+                       /* Insert `rf' again, so it can be free'd correctly */
+                       c_heap_insert (read_heap, rf);
+                       break;
+               }
+
+               /* The entry has been marked for deletion. The linked list
+                * entry has already been removed by `plugin_unregister_read'.
+                * All we have to do here is free the `read_func_t' and
+                * continue. */
+               if (rf_type == RF_REMOVE)
+               {
+                       DEBUG ("plugin_read_thread: Destroying the `%s' "
+                                       "callback.", rf->rf_name);
+                       sfree (rf->rf_name);
+                       destroy_callback ((callback_func_t *) rf);
+                       rf = NULL;
+                       continue;
+               }
+
+               DEBUG ("plugin_read_thread: Handling `%s'.", rf->rf_name);
+
+               old_ctx = plugin_set_ctx (rf->rf_ctx);
+
+               if (rf_type == RF_SIMPLE)
+               {
+                       int (*callback) (void);
+
+                       callback = rf->rf_callback;
+                       status = (*callback) ();
+               }
+               else
+               {
+                       plugin_read_cb callback;
+
+                       assert (rf_type == RF_COMPLEX);
+
+                       callback = rf->rf_callback;
+                       status = (*callback) (&rf->rf_udata);
+               }
+
+               plugin_set_ctx (old_ctx);
+
+               /* If the function signals failure, we will increase the
+                * intervals in which it will be called. */
+               if (status != 0)
+               {
+                       rf->rf_effective_interval *= 2;
+                       if (rf->rf_effective_interval > max_read_interval)
+                               rf->rf_effective_interval = max_read_interval;
+
+                       NOTICE ("read-function of plugin `%s' failed. "
+                                       "Will suspend it for %.3f seconds.",
+                                       rf->rf_name,
+                                       CDTIME_T_TO_DOUBLE (rf->rf_effective_interval));
+               }
+               else
+               {
+                       /* Success: Restore the interval, if it was changed. */
+                       rf->rf_effective_interval = rf->rf_interval;
+               }
+
+               /* update the ``next read due'' field */
+               now = cdtime ();
+
+               DEBUG ("plugin_read_thread: Effective interval of the "
+                               "%s plugin is %.3f seconds.",
+                               rf->rf_name,
+                               CDTIME_T_TO_DOUBLE (rf->rf_effective_interval));
+
+               /* Calculate the next (absolute) time at which this function
+                * should be called. */
+               rf->rf_next_read += rf->rf_effective_interval;
+
+               /* Check, if `rf_next_read' is in the past. */
+               if (rf->rf_next_read < now)
+               {
+                       /* `rf_next_read' is in the past. Insert `now'
+                        * so this value doesn't trail off into the
+                        * past too much. */
+                       rf->rf_next_read = now;
+               }
+
+               DEBUG ("plugin_read_thread: Next read of the %s plugin at %.3f.",
+                               rf->rf_name,
+                               CDTIME_T_TO_DOUBLE (rf->rf_next_read));
+
+               /* Re-insert this read function into the heap again. */
+               c_heap_insert (read_heap, rf);
+       } /* while (read_loop) */
+
+       pthread_exit (NULL);
+       return ((void *) 0);
+} /* void *plugin_read_thread */
+
+static void start_read_threads (int num)
+{
+       int i;
+
+       if (read_threads != NULL)
+               return;
+
+       read_threads = (pthread_t *) calloc (num, sizeof (pthread_t));
+       if (read_threads == NULL)
+       {
+               ERROR ("plugin: start_read_threads: calloc failed.");
+               return;
+       }
+
+       read_threads_num = 0;
+       for (i = 0; i < num; i++)
+       {
+               if (pthread_create (read_threads + read_threads_num, NULL,
+                                       plugin_read_thread, NULL) == 0)
+               {
+                       read_threads_num++;
+               }
+               else
+               {
+                       ERROR ("plugin: start_read_threads: pthread_create failed.");
+                       return;
+               }
+       } /* for (i) */
+} /* void start_read_threads */
+
+static void stop_read_threads (void)
+{
+       int i;
+
+       if (read_threads == NULL)
+               return;
+
+       INFO ("collectd: Stopping %i read threads.", read_threads_num);
+
+       pthread_mutex_lock (&read_lock);
+       read_loop = 0;
+       DEBUG ("plugin: stop_read_threads: Signalling `read_cond'");
+       pthread_cond_broadcast (&read_cond);
+       pthread_mutex_unlock (&read_lock);
+
+       for (i = 0; i < read_threads_num; i++)
+       {
+               if (pthread_join (read_threads[i], NULL) != 0)
+               {
+                       ERROR ("plugin: stop_read_threads: pthread_join failed.");
+               }
+               read_threads[i] = (pthread_t) 0;
+       }
+       sfree (read_threads);
+       read_threads_num = 0;
+} /* void stop_read_threads */
+
+static void plugin_value_list_free (value_list_t *vl) /* {{{ */
+{
+       if (vl == NULL)
+               return;
+
+       meta_data_destroy (vl->meta);
+       sfree (vl->values);
+       sfree (vl);
+} /* }}} void plugin_value_list_free */
+
+static value_list_t *plugin_value_list_clone (value_list_t const *vl_orig) /* {{{ */
+{
+       value_list_t *vl;
+
+       if (vl_orig == NULL)
+               return (NULL);
+
+       vl = malloc (sizeof (*vl));
+       if (vl == NULL)
+               return (NULL);
+       memcpy (vl, vl_orig, sizeof (*vl));
+
+       vl->values = calloc (vl_orig->values_len, sizeof (*vl->values));
+       if (vl->values == NULL)
+       {
+               plugin_value_list_free (vl);
+               return (NULL);
+       }
+       memcpy (vl->values, vl_orig->values,
+                       vl_orig->values_len * sizeof (*vl->values));
+
+       vl->meta = meta_data_clone (vl->meta);
+       if ((vl_orig->meta != NULL) && (vl->meta == NULL))
+       {
+               plugin_value_list_free (vl);
+               return (NULL);
+       }
+
+       if (vl->time == 0)
+               vl->time = cdtime ();
+
+       /* Fill in the interval from the thread context, if it is zero. */
+       if (vl->interval == 0)
+       {
+               plugin_ctx_t ctx = plugin_get_ctx ();
+
+               if (ctx.interval != 0)
+                       vl->interval = ctx.interval;
+               else
+               {
+                       char name[6 * DATA_MAX_NAME_LEN];
+                       FORMAT_VL (name, sizeof (name), vl);
+                       ERROR ("plugin_value_list_clone: Unable to determine "
+                                       "interval from context for "
+                                       "value list \"%s\". "
+                                       "This indicates a broken plugin. "
+                                       "Please report this problem to the "
+                                       "collectd mailing list or at "
+                                       "<http://collectd.org/bugs/>.", name);
+                       vl->interval = cf_get_default_interval ();
+               }
+       }
+
+       return (vl);
+} /* }}} value_list_t *plugin_value_list_clone */
+
+static int plugin_write_enqueue (value_list_t const *vl) /* {{{ */
+{
+       write_queue_t *q;
+
+       q = malloc (sizeof (*q));
+       if (q == NULL)
+               return (ENOMEM);
+       q->next = NULL;
+
+       q->vl = plugin_value_list_clone (vl);
+       if (q->vl == NULL)
+       {
+               sfree (q);
+               return (ENOMEM);
+       }
+
+       /* Store context of caller (read plugin); otherwise, it would not be
+        * available to the write plugins when actually dispatching the
+        * value-list later on. */
+       q->ctx = plugin_get_ctx ();
+
+       pthread_mutex_lock (&write_lock);
+
+       if (write_queue_tail == NULL)
+       {
+               write_queue_head = q;
+               write_queue_tail = q;
+               write_queue_length = 1;
+       }
+       else
+       {
+               write_queue_tail->next = q;
+               write_queue_tail = q;
+               write_queue_length += 1;
+       }
+
+       pthread_cond_signal (&write_cond);
+       pthread_mutex_unlock (&write_lock);
+
+       return (0);
+} /* }}} int plugin_write_enqueue */
+
+static value_list_t *plugin_write_dequeue (void) /* {{{ */
+{
+       write_queue_t *q;
+       value_list_t *vl;
+
+       pthread_mutex_lock (&write_lock);
+
+       while (write_loop && (write_queue_head == NULL))
+               pthread_cond_wait (&write_cond, &write_lock);
+
+       if (write_queue_head == NULL)
+       {
+               pthread_mutex_unlock (&write_lock);
+               return (NULL);
+       }
+
+       q = write_queue_head;
+       write_queue_head = q->next;
+       write_queue_length -= 1;
+       if (write_queue_head == NULL) {
+               write_queue_tail = NULL;
+               assert(0 == write_queue_length);
+               }
+
+       pthread_mutex_unlock (&write_lock);
+
+       (void) plugin_set_ctx (q->ctx);
+
+       vl = q->vl;
+       sfree (q);
+       return (vl);
+} /* }}} value_list_t *plugin_write_dequeue */
+
+static void *plugin_write_thread (void __attribute__((unused)) *args) /* {{{ */
+{
+       while (write_loop)
+       {
+               value_list_t *vl = plugin_write_dequeue ();
+               if (vl == NULL)
+                       continue;
+
+               plugin_dispatch_values_internal (vl);
+
+               plugin_value_list_free (vl);
+       }
+
+       pthread_exit (NULL);
+       return ((void *) 0);
+} /* }}} void *plugin_write_thread */
+
+static void start_write_threads (size_t num) /* {{{ */
+{
+       size_t i;
+
+       if (write_threads != NULL)
+               return;
+
+       write_threads = (pthread_t *) calloc (num, sizeof (pthread_t));
+       if (write_threads == NULL)
+       {
+               ERROR ("plugin: start_write_threads: calloc failed.");
+               return;
+       }
+
+       write_threads_num = 0;
+       for (i = 0; i < num; i++)
+       {
+               int status;
+
+               status = pthread_create (write_threads + write_threads_num,
+                               /* attr = */ NULL,
+                               plugin_write_thread,
+                               /* arg = */ NULL);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("plugin: start_write_threads: pthread_create failed "
+                                       "with status %i (%s).", status,
+                                       sstrerror (status, errbuf, sizeof (errbuf)));
+                       return;
+               }
+
+               write_threads_num++;
+       } /* for (i) */
+} /* }}} void start_write_threads */
+
+static void stop_write_threads (void) /* {{{ */
+{
+       write_queue_t *q;
+       int i;
+
+       if (write_threads == NULL)
+               return;
+
+       INFO ("collectd: Stopping %zu write threads.", write_threads_num);
+
+       pthread_mutex_lock (&write_lock);
+       write_loop = 0;
+       DEBUG ("plugin: stop_write_threads: Signalling `write_cond'");
+       pthread_cond_broadcast (&write_cond);
+       pthread_mutex_unlock (&write_lock);
+
+       for (i = 0; i < write_threads_num; i++)
+       {
+               if (pthread_join (write_threads[i], NULL) != 0)
+               {
+                       ERROR ("plugin: stop_write_threads: pthread_join failed.");
+               }
+               write_threads[i] = (pthread_t) 0;
+       }
+       sfree (write_threads);
+       write_threads_num = 0;
+
+       pthread_mutex_lock (&write_lock);
+       i = 0;
+       for (q = write_queue_head; q != NULL; )
+       {
+               write_queue_t *q1 = q;
+               plugin_value_list_free (q->vl);
+               q = q->next;
+               sfree (q1);
+               i++;
+       }
+       write_queue_head = NULL;
+       write_queue_tail = NULL;
+       write_queue_length = 0;
+       pthread_mutex_unlock (&write_lock);
+
+       if (i > 0)
+       {
+               WARNING ("plugin: %i value list%s left after shutting down "
+                               "the write threads.",
+                               i, (i == 1) ? " was" : "s were");
+       }
+} /* }}} void stop_write_threads */
+
+/*
+ * Public functions
+ */
+void plugin_set_dir (const char *dir)
+{
+       if (plugindir != NULL)
+               free (plugindir);
+
+       if (dir == NULL)
+               plugindir = NULL;
+       else if ((plugindir = strdup (dir)) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("strdup failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+}
+
+static _Bool plugin_is_loaded (char const *name)
+{
+       int status;
+
+       if (plugins_loaded == NULL)
+               plugins_loaded = c_avl_create ((void *) strcasecmp);
+       assert (plugins_loaded != NULL);
+
+       status = c_avl_get (plugins_loaded, name, /* ret_value = */ NULL);
+       return (status == 0);
+}
+
+static int plugin_mark_loaded (char const *name)
+{
+       char *name_copy;
+       int status;
+
+       name_copy = strdup (name);
+       if (name_copy == NULL)
+               return (ENOMEM);
+
+       status = c_avl_insert (plugins_loaded,
+                       /* key = */ name_copy, /* value = */ NULL);
+       return (status);
+}
+
+static void plugin_free_loaded ()
+{
+       void *key;
+       void *value;
+
+       if (plugins_loaded == NULL)
+               return;
+
+       while (c_avl_pick (plugins_loaded, &key, &value) == 0)
+       {
+               sfree (key);
+               assert (value == NULL);
+       }
+
+       c_avl_destroy (plugins_loaded);
+       plugins_loaded = NULL;
+}
+
+#define BUFSIZE 512
+int plugin_load (char const *plugin_name, uint32_t flags)
+{
+       DIR  *dh;
+       const char *dir;
+       char  filename[BUFSIZE] = "";
+       char  typename[BUFSIZE];
+       int   ret;
+       struct stat    statbuf;
+       struct dirent *de;
+       int status;
+
+       if (plugin_name == NULL)
+               return (EINVAL);
+
+       /* Check if plugin is already loaded and don't do anything in this
+        * case. */
+       if (plugin_is_loaded (plugin_name))
+               return (0);
+
+       dir = plugin_get_dir ();
+       ret = 1;
+
+       /*
+        * XXX: Magic at work:
+        *
+        * Some of the language bindings, for example the Python and Perl
+        * plugins, need to be able to export symbols to the scripts they run.
+        * For this to happen, the "Globals" flag needs to be set.
+        * Unfortunately, this technical detail is hard to explain to the
+        * average user and she shouldn't have to worry about this, ideally.
+        * So in order to save everyone's sanity use a different default for a
+        * handful of special plugins. --octo
+        */
+       if ((strcasecmp ("perl", plugin_name) == 0)
+                       || (strcasecmp ("python", plugin_name) == 0))
+               flags |= PLUGIN_FLAGS_GLOBAL;
+
+       /* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
+        * type when matching the filename */
+       status = ssnprintf (typename, sizeof (typename), "%s.so", plugin_name);
+       if ((status < 0) || ((size_t) status >= sizeof (typename)))
+       {
+               WARNING ("plugin_load: Filename too long: \"%s.so\"", plugin_name);
+               return (-1);
+       }
+
+       if ((dh = opendir (dir)) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("plugin_load: opendir (%s) failed: %s", dir,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while ((de = readdir (dh)) != NULL)
+       {
+               if (strcasecmp (de->d_name, typename))
+                       continue;
+
+               status = ssnprintf (filename, sizeof (filename),
+                               "%s/%s", dir, de->d_name);
+               if ((status < 0) || ((size_t) status >= sizeof (filename)))
+               {
+                       WARNING ("plugin_load: Filename too long: \"%s/%s\"",
+                                       dir, de->d_name);
+                       continue;
+               }
+
+               if (lstat (filename, &statbuf) == -1)
+               {
+                       char errbuf[1024];
+                       WARNING ("plugin_load: stat (\"%s\") failed: %s",
+                                       filename,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       continue;
+               }
+               else if (!S_ISREG (statbuf.st_mode))
+               {
+                       /* don't follow symlinks */
+                       WARNING ("plugin_load: %s is not a regular file.",
+                                       filename);
+                       continue;
+               }
+
+               status = plugin_load_file (filename, flags);
+               if (status == 0)
+               {
+                       /* success */
+                       plugin_mark_loaded (plugin_name);
+                       ret = 0;
+                       break;
+               }
+               else
+               {
+                       ERROR ("plugin_load: Load plugin \"%s\" failed with "
+                                       "status %i.", plugin_name, status);
+               }
+       }
+
+       closedir (dh);
+
+       if (filename[0] == 0)
+               ERROR ("plugin_load: Could not find plugin \"%s\" in %s",
+                               plugin_name, dir);
+
+       return (ret);
+}
+
+/*
+ * The `register_*' functions follow
+ */
+int plugin_register_config (const char *name,
+               int (*callback) (const char *key, const char *val),
+               const char **keys, int keys_num)
+{
+       cf_register (name, callback, keys, keys_num);
+       return (0);
+} /* int plugin_register_config */
+
+int plugin_register_complex_config (const char *type,
+               int (*callback) (oconfig_item_t *))
+{
+       return (cf_register_complex (type, callback));
+} /* int plugin_register_complex_config */
+
+int plugin_register_init (const char *name,
+               int (*callback) (void))
+{
+       return (create_register_callback (&list_init, name, (void *) callback,
+                               /* user_data = */ NULL));
+} /* plugin_register_init */
+
+static int plugin_compare_read_func (const void *arg0, const void *arg1)
+{
+       const read_func_t *rf0;
+       const read_func_t *rf1;
+
+       rf0 = arg0;
+       rf1 = arg1;
+
+       if (rf0->rf_next_read < rf1->rf_next_read)
+               return (-1);
+       else if (rf0->rf_next_read > rf1->rf_next_read)
+               return (1);
+       else
+               return (0);
+} /* int plugin_compare_read_func */
+
+/* Add a read function to both, the heap and a linked list. The linked list if
+ * used to look-up read functions, especially for the remove function. The heap
+ * is used to determine which plugin to read next. */
+static int plugin_insert_read (read_func_t *rf)
+{
+       int status;
+       llentry_t *le;
+
+       rf->rf_next_read = cdtime ();
+       rf->rf_effective_interval = rf->rf_interval;
+
+       pthread_mutex_lock (&read_lock);
+
+       if (read_list == NULL)
+       {
+               read_list = llist_create ();
+               if (read_list == NULL)
+               {
+                       pthread_mutex_unlock (&read_lock);
+                       ERROR ("plugin_insert_read: read_list failed.");
+                       return (-1);
+               }
+       }
+
+       if (read_heap == NULL)
+       {
+               read_heap = c_heap_create (plugin_compare_read_func);
+               if (read_heap == NULL)
+               {
+                       pthread_mutex_unlock (&read_lock);
+                       ERROR ("plugin_insert_read: c_heap_create failed.");
+                       return (-1);
+               }
+       }
+
+       le = llist_search (read_list, rf->rf_name);
+       if (le != NULL)
+       {
+               pthread_mutex_unlock (&read_lock);
+               WARNING ("The read function \"%s\" is already registered. "
+                               "Check for duplicate \"LoadPlugin\" lines "
+                               "in your configuration!",
+                               rf->rf_name);
+               return (EINVAL);
+       }
+
+       le = llentry_create (rf->rf_name, rf);
+       if (le == NULL)
+       {
+               pthread_mutex_unlock (&read_lock);
+               ERROR ("plugin_insert_read: llentry_create failed.");
+               return (-1);
+       }
+
+       status = c_heap_insert (read_heap, rf);
+       if (status != 0)
+       {
+               pthread_mutex_unlock (&read_lock);
+               ERROR ("plugin_insert_read: c_heap_insert failed.");
+               llentry_destroy (le);
+               return (-1);
+       }
+
+       /* This does not fail. */
+       llist_append (read_list, le);
+
+       /* Wake up all the read threads. */
+       pthread_cond_broadcast (&read_cond);
+       pthread_mutex_unlock (&read_lock);
+       return (0);
+} /* int plugin_insert_read */
+
+int plugin_register_read (const char *name,
+               int (*callback) (void))
+{
+       read_func_t *rf;
+       int status;
+
+       rf = malloc (sizeof (*rf));
+       if (rf == NULL)
+       {
+               ERROR ("plugin_register_read: malloc failed.");
+               return (ENOMEM);
+       }
+
+       memset (rf, 0, sizeof (read_func_t));
+       rf->rf_callback = (void *) callback;
+       rf->rf_udata.data = NULL;
+       rf->rf_udata.free_func = NULL;
+       rf->rf_ctx = plugin_get_ctx ();
+       rf->rf_group[0] = '\0';
+       rf->rf_name = strdup (name);
+       rf->rf_type = RF_SIMPLE;
+       rf->rf_interval = plugin_get_interval ();
+
+       status = plugin_insert_read (rf);
+       if (status != 0)
+               sfree (rf);
+
+       return (status);
+} /* int plugin_register_read */
+
+int plugin_register_complex_read (const char *group, const char *name,
+               plugin_read_cb callback,
+               const struct timespec *interval,
+               user_data_t *user_data)
+{
+       read_func_t *rf;
+       int status;
+
+       rf = malloc (sizeof (*rf));
+       if (rf == NULL)
+       {
+               ERROR ("plugin_register_complex_read: malloc failed.");
+               return (ENOMEM);
+       }
+
+       memset (rf, 0, sizeof (read_func_t));
+       rf->rf_callback = (void *) callback;
+       if (group != NULL)
+               sstrncpy (rf->rf_group, group, sizeof (rf->rf_group));
+       else
+               rf->rf_group[0] = '\0';
+       rf->rf_name = strdup (name);
+       rf->rf_type = RF_COMPLEX;
+       if (interval != NULL)
+               rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
+       else
+               rf->rf_interval = plugin_get_interval ();
+
+       /* Set user data */
+       if (user_data == NULL)
+       {
+               rf->rf_udata.data = NULL;
+               rf->rf_udata.free_func = NULL;
+       }
+       else
+       {
+               rf->rf_udata = *user_data;
+       }
+
+       rf->rf_ctx = plugin_get_ctx ();
+
+       status = plugin_insert_read (rf);
+       if (status != 0)
+               sfree (rf);
+
+       return (status);
+} /* int plugin_register_complex_read */
+
+int plugin_register_write (const char *name,
+               plugin_write_cb callback, user_data_t *ud)
+{
+       return (create_register_callback (&list_write, name,
+                               (void *) callback, ud));
+} /* int plugin_register_write */
+
+int plugin_register_flush (const char *name,
+               plugin_flush_cb callback, user_data_t *ud)
+{
+       return (create_register_callback (&list_flush, name,
+                               (void *) callback, ud));
+} /* int plugin_register_flush */
+
+int plugin_register_missing (const char *name,
+               plugin_missing_cb callback, user_data_t *ud)
+{
+       return (create_register_callback (&list_missing, name,
+                               (void *) callback, ud));
+} /* int plugin_register_missing */
+
+int plugin_register_shutdown (const char *name,
+               int (*callback) (void))
+{
+       return (create_register_callback (&list_shutdown, name,
+                               (void *) callback, /* user_data = */ NULL));
+} /* int plugin_register_shutdown */
+
+static void plugin_free_data_sets (void)
+{
+       void *key;
+       void *value;
+
+       if (data_sets == NULL)
+               return;
+
+       while (c_avl_pick (data_sets, &key, &value) == 0)
+       {
+               data_set_t *ds = value;
+               /* key is a pointer to ds->type */
+
+               sfree (ds->ds);
+               sfree (ds);
+       }
+
+       c_avl_destroy (data_sets);
+       data_sets = NULL;
+} /* void plugin_free_data_sets */
+
+int plugin_register_data_set (const data_set_t *ds)
+{
+       data_set_t *ds_copy;
+       int i;
+
+       if ((data_sets != NULL)
+                       && (c_avl_get (data_sets, ds->type, NULL) == 0))
+       {
+               NOTICE ("Replacing DS `%s' with another version.", ds->type);
+               plugin_unregister_data_set (ds->type);
+       }
+       else if (data_sets == NULL)
+       {
+               data_sets = c_avl_create ((int (*) (const void *, const void *)) strcmp);
+               if (data_sets == NULL)
+                       return (-1);
+       }
+
+       ds_copy = (data_set_t *) malloc (sizeof (data_set_t));
+       if (ds_copy == NULL)
+               return (-1);
+       memcpy(ds_copy, ds, sizeof (data_set_t));
+
+       ds_copy->ds = (data_source_t *) malloc (sizeof (data_source_t)
+                       * ds->ds_num);
+       if (ds_copy->ds == NULL)
+       {
+               free (ds_copy);
+               return (-1);
+       }
+
+       for (i = 0; i < ds->ds_num; i++)
+               memcpy (ds_copy->ds + i, ds->ds + i, sizeof (data_source_t));
+
+       return (c_avl_insert (data_sets, (void *) ds_copy->type, (void *) ds_copy));
+} /* int plugin_register_data_set */
+
+int plugin_register_log (const char *name,
+               plugin_log_cb callback, user_data_t *ud)
+{
+       return (create_register_callback (&list_log, name,
+                               (void *) callback, ud));
+} /* int plugin_register_log */
+
+int plugin_register_notification (const char *name,
+               plugin_notification_cb callback, user_data_t *ud)
+{
+       return (create_register_callback (&list_notification, name,
+                               (void *) callback, ud));
+} /* int plugin_register_log */
+
+int plugin_unregister_config (const char *name)
+{
+       cf_unregister (name);
+       return (0);
+} /* int plugin_unregister_config */
+
+int plugin_unregister_complex_config (const char *name)
+{
+       cf_unregister_complex (name);
+       return (0);
+} /* int plugin_unregister_complex_config */
+
+int plugin_unregister_init (const char *name)
+{
+       return (plugin_unregister (list_init, name));
+}
+
+int plugin_unregister_read (const char *name) /* {{{ */
+{
+       llentry_t *le;
+       read_func_t *rf;
+
+       if (name == NULL)
+               return (-ENOENT);
+
+       pthread_mutex_lock (&read_lock);
+
+       if (read_list == NULL)
+       {
+               pthread_mutex_unlock (&read_lock);
+               return (-ENOENT);
+       }
+
+       le = llist_search (read_list, name);
+       if (le == NULL)
+       {
+               pthread_mutex_unlock (&read_lock);
+               WARNING ("plugin_unregister_read: No such read function: %s",
+                               name);
+               return (-ENOENT);
+       }
+
+       llist_remove (read_list, le);
+
+       rf = le->value;
+       assert (rf != NULL);
+       rf->rf_type = RF_REMOVE;
+
+       pthread_mutex_unlock (&read_lock);
+
+       llentry_destroy (le);
+
+       DEBUG ("plugin_unregister_read: Marked `%s' for removal.", name);
+
+       return (0);
+} /* }}} int plugin_unregister_read */
+
+void plugin_log_available_writers (void)
+{
+       log_list_callbacks (&list_write, "Available write targets:");
+}
+
+static int compare_read_func_group (llentry_t *e, void *ud) /* {{{ */
+{
+       read_func_t *rf    = e->value;
+       char        *group = ud;
+
+       return strcmp (rf->rf_group, (const char *)group);
+} /* }}} int compare_read_func_group */
+
+int plugin_unregister_read_group (const char *group) /* {{{ */
+{
+       llentry_t *le;
+       read_func_t *rf;
+
+       int found = 0;
+
+       if (group == NULL)
+               return (-ENOENT);
+
+       pthread_mutex_lock (&read_lock);
+
+       if (read_list == NULL)
+       {
+               pthread_mutex_unlock (&read_lock);
+               return (-ENOENT);
+       }
+
+       while (42)
+       {
+               le = llist_search_custom (read_list,
+                               compare_read_func_group, (void *)group);
+
+               if (le == NULL)
+                       break;
+
+               ++found;
+
+               llist_remove (read_list, le);
+
+               rf = le->value;
+               assert (rf != NULL);
+               rf->rf_type = RF_REMOVE;
+
+               llentry_destroy (le);
+
+               DEBUG ("plugin_unregister_read_group: "
+                               "Marked `%s' (group `%s') for removal.",
+                               rf->rf_name, group);
+       }
+
+       pthread_mutex_unlock (&read_lock);
+
+       if (found == 0)
+       {
+               WARNING ("plugin_unregister_read_group: No such "
+                               "group of read function: %s", group);
+               return (-ENOENT);
+       }
+
+       return (0);
+} /* }}} int plugin_unregister_read_group */
+
+int plugin_unregister_write (const char *name)
+{
+       return (plugin_unregister (list_write, name));
+}
+
+int plugin_unregister_flush (const char *name)
+{
+       return (plugin_unregister (list_flush, name));
+}
+
+int plugin_unregister_missing (const char *name)
+{
+       return (plugin_unregister (list_missing, name));
+}
+
+int plugin_unregister_shutdown (const char *name)
+{
+       return (plugin_unregister (list_shutdown, name));
+}
+
+int plugin_unregister_data_set (const char *name)
+{
+       data_set_t *ds;
+
+       if (data_sets == NULL)
+               return (-1);
+
+       if (c_avl_remove (data_sets, name, NULL, (void *) &ds) != 0)
+               return (-1);
+
+       sfree (ds->ds);
+       sfree (ds);
+
+       return (0);
+} /* int plugin_unregister_data_set */
+
+int plugin_unregister_log (const char *name)
+{
+       return (plugin_unregister (list_log, name));
+}
+
+int plugin_unregister_notification (const char *name)
+{
+       return (plugin_unregister (list_notification, name));
+}
+
+void plugin_init_all (void)
+{
+       char const *chain_name;
+       long write_threads_num;
+       llentry_t *le;
+       int status;
+
+       /* Init the value cache */
+       uc_init ();
+
+       if (IS_TRUE (global_option_get ("CollectInternalStats")))
+               record_statistics = 1;
+
+       chain_name = global_option_get ("PreCacheChain");
+       pre_cache_chain = fc_chain_get_by_name (chain_name);
+
+       chain_name = global_option_get ("PostCacheChain");
+       post_cache_chain = fc_chain_get_by_name (chain_name);
+
+       write_limit_high = global_option_get_long ("WriteQueueLimitHigh",
+                       /* default = */ 0);
+       if (write_limit_high < 0)
+       {
+               ERROR ("WriteQueueLimitHigh must be positive or zero.");
+               write_limit_high = 0;
+       }
+
+       write_limit_low = global_option_get_long ("WriteQueueLimitLow",
+                       /* default = */ write_limit_high / 2);
+       if (write_limit_low < 0)
+       {
+               ERROR ("WriteQueueLimitLow must be positive or zero.");
+               write_limit_low = write_limit_high / 2;
+       }
+       else if (write_limit_low > write_limit_high)
+       {
+               ERROR ("WriteQueueLimitLow must not be larger than "
+                               "WriteQueueLimitHigh.");
+               write_limit_low = write_limit_high;
+       }
+
+       write_threads_num = global_option_get_long ("WriteThreads",
+                       /* default = */ 5);
+       if (write_threads_num < 1)
+       {
+               ERROR ("WriteThreads must be positive.");
+               write_threads_num = 5;
+       }
+
+       start_write_threads ((size_t) write_threads_num);
+
+       if ((list_init == NULL) && (read_heap == NULL))
+               return;
+
+       /* Calling all init callbacks before checking if read callbacks
+        * are available allows the init callbacks to register the read
+        * callback. */
+       le = llist_head (list_init);
+       while (le != NULL)
+       {
+               callback_func_t *cf;
+               plugin_init_cb callback;
+               plugin_ctx_t old_ctx;
+
+               cf = le->value;
+               old_ctx = plugin_set_ctx (cf->cf_ctx);
+               callback = cf->cf_callback;
+               status = (*callback) ();
+               plugin_set_ctx (old_ctx);
+
+               if (status != 0)
+               {
+                       ERROR ("Initialization of plugin `%s' "
+                                       "failed with status %i. "
+                                       "Plugin will be unloaded.",
+                                       le->key, status);
+                       /* Plugins that register read callbacks from the init
+                        * callback should take care of appropriate error
+                        * handling themselves. */
+                       /* FIXME: Unload _all_ functions */
+                       plugin_unregister_read (le->key);
+               }
+
+               le = le->next;
+       }
+
+       max_read_interval = global_option_get_time ("MaxReadInterval",
+                       DEFAULT_MAX_READ_INTERVAL);
+
+       /* Start read-threads */
+       if (read_heap != NULL)
+       {
+               const char *rt;
+               int num;
+
+               rt = global_option_get ("ReadThreads");
+               num = atoi (rt);
+               if (num != -1)
+                       start_read_threads ((num > 0) ? num : 5);
+       }
+} /* void plugin_init_all */
+
+/* TODO: Rename this function. */
+void plugin_read_all (void)
+{
+       if(record_statistics) {
+               plugin_update_internal_statistics ();
+       }
+       uc_check_timeout ();
+
+       return;
+} /* void plugin_read_all */
+
+/* Read function called when the `-T' command line argument is given. */
+int plugin_read_all_once (void)
+{
+       int status;
+       int return_status = 0;
+
+       if (read_heap == NULL)
+       {
+               NOTICE ("No read-functions are registered.");
+               return (0);
+       }
+
+       while (42)
+       {
+               read_func_t *rf;
+               plugin_ctx_t old_ctx;
+
+               rf = c_heap_get_root (read_heap);
+               if (rf == NULL)
+                       break;
+
+               old_ctx = plugin_set_ctx (rf->rf_ctx);
+
+               if (rf->rf_type == RF_SIMPLE)
+               {
+                       int (*callback) (void);
+
+                       callback = rf->rf_callback;
+                       status = (*callback) ();
+               }
+               else
+               {
+                       plugin_read_cb callback;
+
+                       callback = rf->rf_callback;
+                       status = (*callback) (&rf->rf_udata);
+               }
+
+               plugin_set_ctx (old_ctx);
+
+               if (status != 0)
+               {
+                       NOTICE ("read-function of plugin `%s' failed.",
+                                       rf->rf_name);
+                       return_status = -1;
+               }
+
+               destroy_callback ((void *) rf);
+       }
+
+       return (return_status);
+} /* int plugin_read_all_once */
+
+int plugin_write (const char *plugin, /* {{{ */
+               const data_set_t *ds, const value_list_t *vl)
+{
+  llentry_t *le;
+  int status;
+
+  if (vl == NULL)
+    return (EINVAL);
+
+  if (list_write == NULL)
+    return (ENOENT);
+
+  if (ds == NULL)
+  {
+    ds = plugin_get_ds (vl->type);
+    if (ds == NULL)
+    {
+      ERROR ("plugin_write: Unable to lookup type `%s'.", vl->type);
+      return (ENOENT);
+    }
+  }
+
+  if (plugin == NULL)
+  {
+    int success = 0;
+    int failure = 0;
+
+    le = llist_head (list_write);
+    while (le != NULL)
+    {
+      callback_func_t *cf = le->value;
+      plugin_write_cb callback;
+
+      /* do not switch plugin context; rather keep the context (interval)
+       * information of the calling read plugin */
+
+      DEBUG ("plugin: plugin_write: Writing values via %s.", le->key);
+      callback = cf->cf_callback;
+      status = (*callback) (ds, vl, &cf->cf_udata);
+      if (status != 0)
+        failure++;
+      else
+        success++;
+
+      le = le->next;
+    }
+
+    if ((success == 0) && (failure != 0))
+      status = -1;
+    else
+      status = 0;
+  }
+  else /* plugin != NULL */
+  {
+    callback_func_t *cf;
+    plugin_write_cb callback;
+
+    le = llist_head (list_write);
+    while (le != NULL)
+    {
+      if (strcasecmp (plugin, le->key) == 0)
+        break;
+
+      le = le->next;
+    }
+
+    if (le == NULL)
+      return (ENOENT);
+
+    cf = le->value;
+
+    /* do not switch plugin context; rather keep the context (interval)
+     * information of the calling read plugin */
+
+    DEBUG ("plugin: plugin_write: Writing values via %s.", le->key);
+    callback = cf->cf_callback;
+    status = (*callback) (ds, vl, &cf->cf_udata);
+  }
+
+  return (status);
+} /* }}} int plugin_write */
+
+int plugin_flush (const char *plugin, cdtime_t timeout, const char *identifier)
+{
+  llentry_t *le;
+
+  if (list_flush == NULL)
+    return (0);
+
+  le = llist_head (list_flush);
+  while (le != NULL)
+  {
+    callback_func_t *cf;
+    plugin_flush_cb callback;
+    plugin_ctx_t old_ctx;
+
+    if ((plugin != NULL)
+        && (strcmp (plugin, le->key) != 0))
+    {
+      le = le->next;
+      continue;
+    }
+
+    cf = le->value;
+    old_ctx = plugin_set_ctx (cf->cf_ctx);
+    callback = cf->cf_callback;
+
+    (*callback) (timeout, identifier, &cf->cf_udata);
+
+    plugin_set_ctx (old_ctx);
+
+    le = le->next;
+  }
+  return (0);
+} /* int plugin_flush */
+
+void plugin_shutdown_all (void)
+{
+       llentry_t *le;
+
+       stop_read_threads ();
+
+       destroy_all_callbacks (&list_init);
+
+       pthread_mutex_lock (&read_lock);
+       llist_destroy (read_list);
+       read_list = NULL;
+       pthread_mutex_unlock (&read_lock);
+
+       destroy_read_heap ();
+
+       plugin_flush (/* plugin = */ NULL,
+                       /* timeout = */ 0,
+                       /* identifier = */ NULL);
+
+       le = NULL;
+       if (list_shutdown != NULL)
+               le = llist_head (list_shutdown);
+
+       while (le != NULL)
+       {
+               callback_func_t *cf;
+               plugin_shutdown_cb callback;
+               plugin_ctx_t old_ctx;
+
+               cf = le->value;
+               old_ctx = plugin_set_ctx (cf->cf_ctx);
+               callback = cf->cf_callback;
+
+               /* Advance the pointer before calling the callback allows
+                * shutdown functions to unregister themselves. If done the
+                * other way around the memory `le' points to will be freed
+                * after callback returns. */
+               le = le->next;
+
+               (*callback) ();
+
+               plugin_set_ctx (old_ctx);
+       }
+
+       stop_write_threads ();
+
+       /* Write plugins which use the `user_data' pointer usually need the
+        * same data available to the flush callback. If this is the case, set
+        * the free_function to NULL when registering the flush callback and to
+        * the real free function when registering the write callback. This way
+        * the data isn't freed twice. */
+       destroy_all_callbacks (&list_flush);
+       destroy_all_callbacks (&list_missing);
+       destroy_all_callbacks (&list_write);
+
+       destroy_all_callbacks (&list_notification);
+       destroy_all_callbacks (&list_shutdown);
+       destroy_all_callbacks (&list_log);
+
+       plugin_free_loaded ();
+       plugin_free_data_sets ();
+} /* void plugin_shutdown_all */
+
+int plugin_dispatch_missing (const value_list_t *vl) /* {{{ */
+{
+  llentry_t *le;
+
+  if (list_missing == NULL)
+    return (0);
+
+  le = llist_head (list_missing);
+  while (le != NULL)
+  {
+    callback_func_t *cf;
+    plugin_missing_cb callback;
+    plugin_ctx_t old_ctx;
+    int status;
+
+    cf = le->value;
+    old_ctx = plugin_set_ctx (cf->cf_ctx);
+    callback = cf->cf_callback;
+
+    status = (*callback) (vl, &cf->cf_udata);
+    plugin_set_ctx (old_ctx);
+    if (status != 0)
+    {
+      if (status < 0)
+      {
+        ERROR ("plugin_dispatch_missing: Callback function \"%s\" "
+            "failed with status %i.",
+            le->key, status);
+        return (status);
+      }
+      else
+      {
+        return (0);
+      }
+    }
+
+    le = le->next;
+  }
+  return (0);
+} /* int }}} plugin_dispatch_missing */
+
+static int plugin_dispatch_values_internal (value_list_t *vl)
+{
+       int status;
+       static c_complain_t no_write_complaint = C_COMPLAIN_INIT_STATIC;
+
+       value_t *saved_values;
+       int      saved_values_len;
+
+       data_set_t *ds;
+
+       int free_meta_data = 0;
+
+       if ((vl == NULL) || (vl->type[0] == 0)
+                       || (vl->values == NULL) || (vl->values_len < 1))
+       {
+               ERROR ("plugin_dispatch_values: Invalid value list "
+                               "from plugin %s.", vl->plugin);
+               return (-1);
+       }
+
+       /* Free meta data only if the calling function didn't specify any. In
+        * this case matches and targets may add some and the calling function
+        * may not expect (and therefore free) that data. */
+       if (vl->meta == NULL)
+               free_meta_data = 1;
+
+       if (list_write == NULL)
+               c_complain_once (LOG_WARNING, &no_write_complaint,
+                               "plugin_dispatch_values: No write callback has been "
+                               "registered. Please load at least one output plugin, "
+                               "if you want the collected data to be stored.");
+
+       if (data_sets == NULL)
+       {
+               ERROR ("plugin_dispatch_values: No data sets registered. "
+                               "Could the types database be read? Check "
+                               "your `TypesDB' setting!");
+               return (-1);
+       }
+
+       if (c_avl_get (data_sets, vl->type, (void *) &ds) != 0)
+       {
+               char ident[6 * DATA_MAX_NAME_LEN];
+
+               FORMAT_VL (ident, sizeof (ident), vl);
+               INFO ("plugin_dispatch_values: Dataset not found: %s "
+                               "(from \"%s\"), check your types.db!",
+                               vl->type, ident);
+               return (-1);
+       }
+
+       /* Assured by plugin_value_list_clone(). The time is determined at
+        * _enqueue_ time. */
+       assert (vl->time != 0);
+       assert (vl->interval != 0);
+
+       DEBUG ("plugin_dispatch_values: time = %.3f; interval = %.3f; "
+                       "host = %s; "
+                       "plugin = %s; plugin_instance = %s; "
+                       "type = %s; type_instance = %s;",
+                       CDTIME_T_TO_DOUBLE (vl->time),
+                       CDTIME_T_TO_DOUBLE (vl->interval),
+                       vl->host,
+                       vl->plugin, vl->plugin_instance,
+                       vl->type, vl->type_instance);
+
+#if COLLECT_DEBUG
+       assert (0 == strcmp (ds->type, vl->type));
+#else
+       if (0 != strcmp (ds->type, vl->type))
+               WARNING ("plugin_dispatch_values: (ds->type = %s) != (vl->type = %s)",
+                               ds->type, vl->type);
+#endif
+
+#if COLLECT_DEBUG
+       assert (ds->ds_num == vl->values_len);
+#else
+       if (ds->ds_num != vl->values_len)
+       {
+               ERROR ("plugin_dispatch_values: ds->type = %s: "
+                               "(ds->ds_num = %i) != "
+                               "(vl->values_len = %i)",
+                               ds->type, ds->ds_num, vl->values_len);
+               return (-1);
+       }
+#endif
+
+       escape_slashes (vl->host, sizeof (vl->host));
+       escape_slashes (vl->plugin, sizeof (vl->plugin));
+       escape_slashes (vl->plugin_instance, sizeof (vl->plugin_instance));
+       escape_slashes (vl->type, sizeof (vl->type));
+       escape_slashes (vl->type_instance, sizeof (vl->type_instance));
+
+       /* Copy the values. This way, we can assure `targets' that they get
+        * dynamically allocated values, which they can free and replace if
+        * they like. */
+       if ((pre_cache_chain != NULL) || (post_cache_chain != NULL))
+       {
+               saved_values     = vl->values;
+               saved_values_len = vl->values_len;
+
+               vl->values = (value_t *) calloc (vl->values_len,
+                               sizeof (*vl->values));
+               if (vl->values == NULL)
+               {
+                       ERROR ("plugin_dispatch_values: calloc failed.");
+                       vl->values = saved_values;
+                       return (-1);
+               }
+               memcpy (vl->values, saved_values,
+                               vl->values_len * sizeof (*vl->values));
+       }
+       else /* if ((pre == NULL) && (post == NULL)) */
+       {
+               saved_values     = NULL;
+               saved_values_len = 0;
+       }
+
+       if (pre_cache_chain != NULL)
+       {
+               status = fc_process_chain (ds, vl, pre_cache_chain);
+               if (status < 0)
+               {
+                       WARNING ("plugin_dispatch_values: Running the "
+                                       "pre-cache chain failed with "
+                                       "status %i (%#x).",
+                                       status, status);
+               }
+               else if (status == FC_TARGET_STOP)
+               {
+                       /* Restore the state of the value_list so that plugins
+                        * don't get confused.. */
+                       if (saved_values != NULL)
+                       {
+                               free (vl->values);
+                               vl->values     = saved_values;
+                               vl->values_len = saved_values_len;
+                       }
+                       return (0);
+               }
+       }
+
+       /* Update the value cache */
+       uc_update (ds, vl);
+
+       if (post_cache_chain != NULL)
+       {
+               status = fc_process_chain (ds, vl, post_cache_chain);
+               if (status < 0)
+               {
+                       WARNING ("plugin_dispatch_values: Running the "
+                                       "post-cache chain failed with "
+                                       "status %i (%#x).",
+                                       status, status);
+               }
+       }
+       else
+               fc_default_action (ds, vl);
+
+       /* Restore the state of the value_list so that plugins don't get
+        * confused.. */
+       if (saved_values != NULL)
+       {
+               free (vl->values);
+               vl->values     = saved_values;
+               vl->values_len = saved_values_len;
+       }
+
+       if ((free_meta_data != 0) && (vl->meta != NULL))
+       {
+               meta_data_destroy (vl->meta);
+               vl->meta = NULL;
+       }
+
+       return (0);
+} /* int plugin_dispatch_values_internal */
+
+static double get_drop_probability (void) /* {{{ */
+{
+       long pos;
+       long size;
+       long wql;
+
+       pthread_mutex_lock (&write_lock);
+       wql = write_queue_length;
+       pthread_mutex_unlock (&write_lock);
+
+       if (wql < write_limit_low)
+               return (0.0);
+       if (wql >= write_limit_high)
+               return (1.0);
+
+       pos = 1 + wql - write_limit_low;
+       size = 1 + write_limit_high - write_limit_low;
+
+       return (((double) pos) / ((double) size));
+} /* }}} double get_drop_probability */
+
+static _Bool check_drop_value (void) /* {{{ */
+{
+       static cdtime_t last_message_time = 0;
+       static pthread_mutex_t last_message_lock = PTHREAD_MUTEX_INITIALIZER;
+
+       double p;
+       double q;
+       int status;
+
+       if (write_limit_high == 0)
+               return (0);
+
+       p = get_drop_probability ();
+       if (p == 0.0)
+               return (0);
+
+       status = pthread_mutex_trylock (&last_message_lock);
+       if (status == 0)
+       {
+               cdtime_t now;
+
+               now = cdtime ();
+               if ((now - last_message_time) > TIME_T_TO_CDTIME_T (1))
+               {
+                       last_message_time = now;
+                       ERROR ("plugin_dispatch_values: Low water mark "
+                                       "reached. Dropping %.0f%% of metrics.",
+                                       100.0 * p);
+               }
+               pthread_mutex_unlock (&last_message_lock);
+       }
+
+       if (p == 1.0)
+               return (1);
+
+       q = cdrand_d ();
+       if (q > p)
+               return (1);
+       else
+               return (0);
+} /* }}} _Bool check_drop_value */
+
+int plugin_dispatch_values (value_list_t const *vl)
+{
+       int status;
+       static pthread_mutex_t statistics_lock = PTHREAD_MUTEX_INITIALIZER;
+
+       if (check_drop_value ()) {
+               if(record_statistics) {
+                       pthread_mutex_lock(&statistics_lock);
+                       stats_values_dropped++;
+                       pthread_mutex_unlock(&statistics_lock);
+               }
+               return (0);
+       }
+
+       status = plugin_write_enqueue (vl);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("plugin_dispatch_values: plugin_write_enqueue failed "
+                               "with status %i (%s).", status,
+                               sstrerror (status, errbuf, sizeof (errbuf)));
+               return (status);
+       }
+
+       return (0);
+}
+
+__attribute__((sentinel))
+int plugin_dispatch_multivalue (value_list_t const *template, /* {{{ */
+               _Bool store_percentage, int store_type, ...)
+{
+       value_list_t *vl;
+       int failed = 0;
+       gauge_t sum = 0.0;
+       va_list ap;
+
+       assert (template->values_len == 1);
+
+  /* Calculate sum for Gauge to calculate percent if needed */
+       if (DS_TYPE_GAUGE == store_type)        {
+               va_start (ap, store_type);
+               while (42)
+               {
+                       char const *name;
+                       gauge_t value;
+
+                       name = va_arg (ap, char const *);
+                       if (name == NULL)
+                               break;
+
+                       value = va_arg (ap, gauge_t);
+                       if (!isnan (value))
+                               sum += value;
+               }
+               va_end (ap);
+       }
+
+
+       vl = plugin_value_list_clone (template);
+       /* plugin_value_list_clone makes sure vl->time is set to non-zero. */
+       if (store_percentage)
+               sstrncpy (vl->type, "percent", sizeof (vl->type));
+
+       va_start (ap, store_type);
+       while (42)
+       {
+               char const *name;
+               int status;
+
+               /* Set the type instance. */
+               name = va_arg (ap, char const *);
+               if (name == NULL)
+                       break;
+               sstrncpy (vl->type_instance, name, sizeof (vl->type_instance));
+
+               /* Set the value. */
+               switch (store_type)
+               {
+               case DS_TYPE_GAUGE:
+                       vl->values[0].gauge = va_arg (ap, gauge_t);
+                       if (store_percentage)
+                               vl->values[0].gauge *= 100.0 / sum;
+                       break;
+               case DS_TYPE_ABSOLUTE:
+                       vl->values[0].absolute = va_arg (ap, absolute_t);
+                       break;
+               case DS_TYPE_COUNTER:
+                       vl->values[0].counter  = va_arg (ap, counter_t);
+                       break;
+               case DS_TYPE_DERIVE:
+                       vl->values[0].derive   = va_arg (ap, derive_t);
+                       break;
+               default:
+                       ERROR ("plugin_dispatch_multivalue: given store_type is incorrect.");
+                       failed++;
+               }
+
+
+               status = plugin_write_enqueue (vl);
+               if (status != 0)
+                       failed++;
+       }
+       va_end (ap);
+
+       plugin_value_list_free (vl);
+       return (failed);
+} /* }}} int plugin_dispatch_multivalue */
+
+int plugin_dispatch_notification (const notification_t *notif)
+{
+       llentry_t *le;
+       /* Possible TODO: Add flap detection here */
+
+       DEBUG ("plugin_dispatch_notification: severity = %i; message = %s; "
+                       "time = %.3f; host = %s;",
+                       notif->severity, notif->message,
+                       CDTIME_T_TO_DOUBLE (notif->time), notif->host);
+
+       /* Nobody cares for notifications */
+       if (list_notification == NULL)
+               return (-1);
+
+       le = llist_head (list_notification);
+       while (le != NULL)
+       {
+               callback_func_t *cf;
+               plugin_notification_cb callback;
+               int status;
+
+               /* do not switch plugin context; rather keep the context
+                * (interval) information of the calling plugin */
+
+               cf = le->value;
+               callback = cf->cf_callback;
+               status = (*callback) (notif, &cf->cf_udata);
+               if (status != 0)
+               {
+                       WARNING ("plugin_dispatch_notification: Notification "
+                                       "callback %s returned %i.",
+                                       le->key, status);
+               }
+
+               le = le->next;
+       }
+
+       return (0);
+} /* int plugin_dispatch_notification */
+
+void plugin_log (int level, const char *format, ...)
+{
+       char msg[1024];
+       va_list ap;
+       llentry_t *le;
+
+#if !COLLECT_DEBUG
+       if (level >= LOG_DEBUG)
+               return;
+#endif
+
+       va_start (ap, format);
+       vsnprintf (msg, sizeof (msg), format, ap);
+       msg[sizeof (msg) - 1] = '\0';
+       va_end (ap);
+
+       if (list_log == NULL)
+       {
+               fprintf (stderr, "%s\n", msg);
+               return;
+       }
+
+       le = llist_head (list_log);
+       while (le != NULL)
+       {
+               callback_func_t *cf;
+               plugin_log_cb callback;
+
+               cf = le->value;
+               callback = cf->cf_callback;
+
+               /* do not switch plugin context; rather keep the context
+                * (interval) information of the calling plugin */
+
+               (*callback) (level, msg, &cf->cf_udata);
+
+               le = le->next;
+       }
+} /* void plugin_log */
+
+int parse_log_severity (const char *severity)
+{
+       int log_level = -1;
+
+       if ((0 == strcasecmp (severity, "emerg"))
+                       || (0 == strcasecmp (severity, "alert"))
+                       || (0 == strcasecmp (severity, "crit"))
+                       || (0 == strcasecmp (severity, "err")))
+               log_level = LOG_ERR;
+       else if (0 == strcasecmp (severity, "warning"))
+               log_level = LOG_WARNING;
+       else if (0 == strcasecmp (severity, "notice"))
+               log_level = LOG_NOTICE;
+       else if (0 == strcasecmp (severity, "info"))
+               log_level = LOG_INFO;
+#if COLLECT_DEBUG
+       else if (0 == strcasecmp (severity, "debug"))
+               log_level = LOG_DEBUG;
+#endif /* COLLECT_DEBUG */
+
+       return (log_level);
+} /* int parse_log_severity */
+
+int parse_notif_severity (const char *severity)
+{
+       int notif_severity = -1;
+
+       if (strcasecmp (severity, "FAILURE") == 0)
+               notif_severity = NOTIF_FAILURE;
+       else if (strcmp (severity, "OKAY") == 0)
+               notif_severity = NOTIF_OKAY;
+       else if ((strcmp (severity, "WARNING") == 0)
+                       || (strcmp (severity, "WARN") == 0))
+               notif_severity = NOTIF_WARNING;
+
+       return (notif_severity);
+} /* int parse_notif_severity */
+
+const data_set_t *plugin_get_ds (const char *name)
+{
+       data_set_t *ds;
+
+       if (data_sets == NULL)
+       {
+               ERROR ("plugin_get_ds: No data sets are defined yet.");
+               return (NULL);
+       }
+
+       if (c_avl_get (data_sets, name, (void *) &ds) != 0)
+       {
+               DEBUG ("No such dataset registered: %s", name);
+               return (NULL);
+       }
+
+       return (ds);
+} /* data_set_t *plugin_get_ds */
+
+static int plugin_notification_meta_add (notification_t *n,
+    const char *name,
+    enum notification_meta_type_e type,
+    const void *value)
+{
+  notification_meta_t *meta;
+  notification_meta_t *tail;
+
+  if ((n == NULL) || (name == NULL) || (value == NULL))
+  {
+    ERROR ("plugin_notification_meta_add: A pointer is NULL!");
+    return (-1);
+  }
+
+  meta = (notification_meta_t *) malloc (sizeof (notification_meta_t));
+  if (meta == NULL)
+  {
+    ERROR ("plugin_notification_meta_add: malloc failed.");
+    return (-1);
+  }
+  memset (meta, 0, sizeof (notification_meta_t));
+
+  sstrncpy (meta->name, name, sizeof (meta->name));
+  meta->type = type;
+
+  switch (type)
+  {
+    case NM_TYPE_STRING:
+    {
+      meta->nm_value.nm_string = strdup ((const char *) value);
+      if (meta->nm_value.nm_string == NULL)
+      {
+        ERROR ("plugin_notification_meta_add: strdup failed.");
+        sfree (meta);
+        return (-1);
+      }
+      break;
+    }
+    case NM_TYPE_SIGNED_INT:
+    {
+      meta->nm_value.nm_signed_int = *((int64_t *) value);
+      break;
+    }
+    case NM_TYPE_UNSIGNED_INT:
+    {
+      meta->nm_value.nm_unsigned_int = *((uint64_t *) value);
+      break;
+    }
+    case NM_TYPE_DOUBLE:
+    {
+      meta->nm_value.nm_double = *((double *) value);
+      break;
+    }
+    case NM_TYPE_BOOLEAN:
+    {
+      meta->nm_value.nm_boolean = *((_Bool *) value);
+      break;
+    }
+    default:
+    {
+      ERROR ("plugin_notification_meta_add: Unknown type: %i", type);
+      sfree (meta);
+      return (-1);
+    }
+  } /* switch (type) */
+
+  meta->next = NULL;
+  tail = n->meta;
+  while ((tail != NULL) && (tail->next != NULL))
+    tail = tail->next;
+
+  if (tail == NULL)
+    n->meta = meta;
+  else
+    tail->next = meta;
+
+  return (0);
+} /* int plugin_notification_meta_add */
+
+int plugin_notification_meta_add_string (notification_t *n,
+    const char *name,
+    const char *value)
+{
+  return (plugin_notification_meta_add (n, name, NM_TYPE_STRING, value));
+}
+
+int plugin_notification_meta_add_signed_int (notification_t *n,
+    const char *name,
+    int64_t value)
+{
+  return (plugin_notification_meta_add (n, name, NM_TYPE_SIGNED_INT, &value));
+}
+
+int plugin_notification_meta_add_unsigned_int (notification_t *n,
+    const char *name,
+    uint64_t value)
+{
+  return (plugin_notification_meta_add (n, name, NM_TYPE_UNSIGNED_INT, &value));
+}
+
+int plugin_notification_meta_add_double (notification_t *n,
+    const char *name,
+    double value)
+{
+  return (plugin_notification_meta_add (n, name, NM_TYPE_DOUBLE, &value));
+}
+
+int plugin_notification_meta_add_boolean (notification_t *n,
+    const char *name,
+    _Bool value)
+{
+  return (plugin_notification_meta_add (n, name, NM_TYPE_BOOLEAN, &value));
+}
+
+int plugin_notification_meta_copy (notification_t *dst,
+    const notification_t *src)
+{
+  notification_meta_t *meta;
+
+  assert (dst != NULL);
+  assert (src != NULL);
+  assert (dst != src);
+  assert ((src->meta == NULL) || (src->meta != dst->meta));
+
+  for (meta = src->meta; meta != NULL; meta = meta->next)
+  {
+    if (meta->type == NM_TYPE_STRING)
+      plugin_notification_meta_add_string (dst, meta->name,
+          meta->nm_value.nm_string);
+    else if (meta->type == NM_TYPE_SIGNED_INT)
+      plugin_notification_meta_add_signed_int (dst, meta->name,
+          meta->nm_value.nm_signed_int);
+    else if (meta->type == NM_TYPE_UNSIGNED_INT)
+      plugin_notification_meta_add_unsigned_int (dst, meta->name,
+          meta->nm_value.nm_unsigned_int);
+    else if (meta->type == NM_TYPE_DOUBLE)
+      plugin_notification_meta_add_double (dst, meta->name,
+          meta->nm_value.nm_double);
+    else if (meta->type == NM_TYPE_BOOLEAN)
+      plugin_notification_meta_add_boolean (dst, meta->name,
+          meta->nm_value.nm_boolean);
+  }
+
+  return (0);
+} /* int plugin_notification_meta_copy */
+
+int plugin_notification_meta_free (notification_meta_t *n)
+{
+  notification_meta_t *this;
+  notification_meta_t *next;
+
+  if (n == NULL)
+  {
+    ERROR ("plugin_notification_meta_free: n == NULL!");
+    return (-1);
+  }
+
+  this = n;
+  while (this != NULL)
+  {
+    next = this->next;
+
+    if (this->type == NM_TYPE_STRING)
+    {
+      free ((char *)this->nm_value.nm_string);
+      this->nm_value.nm_string = NULL;
+    }
+    sfree (this);
+
+    this = next;
+  }
+
+  return (0);
+} /* int plugin_notification_meta_free */
+
+static void plugin_ctx_destructor (void *ctx)
+{
+       sfree (ctx);
+} /* void plugin_ctx_destructor */
+
+static plugin_ctx_t ctx_init = { /* interval = */ 0 };
+
+static plugin_ctx_t *plugin_ctx_create (void)
+{
+       plugin_ctx_t *ctx;
+
+       ctx = malloc (sizeof (*ctx));
+       if (ctx == NULL) {
+               char errbuf[1024];
+               ERROR ("Failed to allocate plugin context: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return NULL;
+       }
+
+       *ctx = ctx_init;
+       assert (plugin_ctx_key_initialized);
+       pthread_setspecific (plugin_ctx_key, ctx);
+       DEBUG("Created new plugin context.");
+       return (ctx);
+} /* int plugin_ctx_create */
+
+void plugin_init_ctx (void)
+{
+       pthread_key_create (&plugin_ctx_key, plugin_ctx_destructor);
+       plugin_ctx_key_initialized = 1;
+} /* void plugin_init_ctx */
+
+plugin_ctx_t plugin_get_ctx (void)
+{
+       plugin_ctx_t *ctx;
+
+       assert (plugin_ctx_key_initialized);
+       ctx = pthread_getspecific (plugin_ctx_key);
+
+       if (ctx == NULL) {
+               ctx = plugin_ctx_create ();
+               /* this must no happen -- exit() instead? */
+               if (ctx == NULL)
+                       return ctx_init;
+       }
+
+       return (*ctx);
+} /* plugin_ctx_t plugin_get_ctx */
+
+plugin_ctx_t plugin_set_ctx (plugin_ctx_t ctx)
+{
+       plugin_ctx_t *c;
+       plugin_ctx_t old;
+
+       assert (plugin_ctx_key_initialized);
+       c = pthread_getspecific (plugin_ctx_key);
+
+       if (c == NULL) {
+               c = plugin_ctx_create ();
+               /* this must no happen -- exit() instead? */
+               if (c == NULL)
+                       return ctx_init;
+       }
+
+       old = *c;
+       *c = ctx;
+
+       return (old);
+} /* void plugin_set_ctx */
+
+cdtime_t plugin_get_interval (void)
+{
+       cdtime_t interval;
+
+       interval = plugin_get_ctx().interval;
+       if (interval > 0)
+               return interval;
+
+       return cf_get_default_interval ();
+} /* cdtime_t plugin_get_interval */
+
+typedef struct {
+       plugin_ctx_t ctx;
+       void *(*start_routine) (void *);
+       void *arg;
+} plugin_thread_t;
+
+static void *plugin_thread_start (void *arg)
+{
+       plugin_thread_t *plugin_thread = arg;
+
+       void *(*start_routine) (void *) = plugin_thread->start_routine;
+       void *plugin_arg = plugin_thread->arg;
+
+       plugin_set_ctx (plugin_thread->ctx);
+
+       free (plugin_thread);
+
+       return start_routine (plugin_arg);
+} /* void *plugin_thread_start */
+
+int plugin_thread_create (pthread_t *thread, const pthread_attr_t *attr,
+               void *(*start_routine) (void *), void *arg)
+{
+       plugin_thread_t *plugin_thread;
+
+       plugin_thread = malloc (sizeof (*plugin_thread));
+       if (plugin_thread == NULL)
+               return -1;
+
+       plugin_thread->ctx           = plugin_get_ctx ();
+       plugin_thread->start_routine = start_routine;
+       plugin_thread->arg           = arg;
+
+       return pthread_create (thread, attr,
+                       plugin_thread_start, plugin_thread);
+} /* int plugin_thread_create */
+
+/* vim: set sw=8 ts=8 noet fdm=marker : */
diff --git a/src/daemon/plugin.h b/src/daemon/plugin.h
new file mode 100644 (file)
index 0000000..70a2232
--- /dev/null
@@ -0,0 +1,460 @@
+/**
+ * collectd - src/plugin.h
+ * Copyright (C) 2005-2014  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include "collectd.h"
+#include "configfile.h"
+#include "meta_data.h"
+#include "utils_time.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+#define PLUGIN_FLAGS_GLOBAL 0x0001
+
+#define DATA_MAX_NAME_LEN 64
+
+#define DS_TYPE_COUNTER  0
+#define DS_TYPE_GAUGE    1
+#define DS_TYPE_DERIVE   2
+#define DS_TYPE_ABSOLUTE 3
+
+#define DS_TYPE_TO_STRING(t) (t == DS_TYPE_COUNTER)     ? "counter"  : \
+                               (t == DS_TYPE_GAUGE)    ? "gauge"    : \
+                               (t == DS_TYPE_DERIVE)   ? "derive"   : \
+                               (t == DS_TYPE_ABSOLUTE) ? "absolute" : \
+                               "unknown"
+
+
+#ifndef LOG_ERR
+# define LOG_ERR 3
+#endif
+#ifndef LOG_WARNING
+# define LOG_WARNING 4
+#endif
+#ifndef LOG_NOTICE
+# define LOG_NOTICE 5
+#endif
+#ifndef LOG_INFO
+# define LOG_INFO 6
+#endif
+#ifndef LOG_DEBUG
+# define LOG_DEBUG 7
+#endif
+
+#define NOTIF_MAX_MSG_LEN 256
+
+#define NOTIF_FAILURE 1
+#define NOTIF_WARNING 2
+#define NOTIF_OKAY    4
+
+#define plugin_interval (plugin_get_ctx().interval)
+
+/*
+ * Public data types
+ */
+typedef unsigned long long counter_t;
+typedef double gauge_t;
+typedef int64_t derive_t;
+typedef uint64_t absolute_t;
+
+union value_u
+{
+       counter_t  counter;
+       gauge_t    gauge;
+       derive_t   derive;
+       absolute_t absolute;
+};
+typedef union value_u value_t;
+
+struct value_list_s
+{
+       value_t *values;
+       int      values_len;
+       cdtime_t time;
+       cdtime_t interval;
+       char     host[DATA_MAX_NAME_LEN];
+       char     plugin[DATA_MAX_NAME_LEN];
+       char     plugin_instance[DATA_MAX_NAME_LEN];
+       char     type[DATA_MAX_NAME_LEN];
+       char     type_instance[DATA_MAX_NAME_LEN];
+       meta_data_t *meta;
+};
+typedef struct value_list_s value_list_t;
+
+#define VALUE_LIST_INIT { NULL, 0, 0, plugin_get_interval (), \
+       "localhost", "", "", "", "", NULL }
+#define VALUE_LIST_STATIC { NULL, 0, 0, 0, "localhost", "", "", "", "", NULL }
+
+struct data_source_s
+{
+       char   name[DATA_MAX_NAME_LEN];
+       int    type;
+       double min;
+       double max;
+};
+typedef struct data_source_s data_source_t;
+
+struct data_set_s
+{
+       char           type[DATA_MAX_NAME_LEN];
+       int            ds_num;
+       data_source_t *ds;
+};
+typedef struct data_set_s data_set_t;
+
+enum notification_meta_type_e
+{
+       NM_TYPE_STRING,
+       NM_TYPE_SIGNED_INT,
+       NM_TYPE_UNSIGNED_INT,
+       NM_TYPE_DOUBLE,
+       NM_TYPE_BOOLEAN
+};
+
+typedef struct notification_meta_s
+{
+       char name[DATA_MAX_NAME_LEN];
+       enum notification_meta_type_e type;
+       union
+       {
+               const char *nm_string;
+               int64_t nm_signed_int;
+               uint64_t nm_unsigned_int;
+               double nm_double;
+               _Bool nm_boolean;
+       } nm_value;
+       struct notification_meta_s *next;
+} notification_meta_t;
+
+typedef struct notification_s
+{
+       int    severity;
+       cdtime_t time;
+       char   message[NOTIF_MAX_MSG_LEN];
+       char   host[DATA_MAX_NAME_LEN];
+       char   plugin[DATA_MAX_NAME_LEN];
+       char   plugin_instance[DATA_MAX_NAME_LEN];
+       char   type[DATA_MAX_NAME_LEN];
+       char   type_instance[DATA_MAX_NAME_LEN];
+       notification_meta_t *meta;
+} notification_t;
+
+struct user_data_s
+{
+       void *data;
+       void (*free_func) (void *);
+};
+typedef struct user_data_s user_data_t;
+
+struct plugin_ctx_s
+{
+       cdtime_t interval;
+};
+typedef struct plugin_ctx_s plugin_ctx_t;
+
+/*
+ * Callback types
+ */
+typedef int (*plugin_init_cb) (void);
+typedef int (*plugin_read_cb) (user_data_t *);
+typedef int (*plugin_write_cb) (const data_set_t *, const value_list_t *,
+               user_data_t *);
+typedef int (*plugin_flush_cb) (cdtime_t timeout, const char *identifier,
+               user_data_t *);
+/* "missing" callback. Returns less than zero on failure, zero if other
+ * 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 *);
+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 *);
+
+/*
+ * NAME
+ *  plugin_set_dir
+ *
+ * DESCRIPTION
+ *  Sets the current `plugindir'
+ *
+ * ARGUMENTS
+ *  `dir'       Path to the plugin directory
+ *
+ * NOTES
+ *  If `dir' is NULL the compiled in default `PLUGINDIR' is used.
+ */
+void plugin_set_dir (const char *dir);
+
+/*
+ * NAME
+ *  plugin_load
+ *
+ * DESCRIPTION
+ *  Searches the current `plugindir' (see `plugin_set_dir') for the plugin
+ *  named $type and loads it. Afterwards the plugin's `module_register'
+ *  function is called, which then calls `plugin_register' to register callback
+ *  functions.
+ *
+ * ARGUMENTS
+ *  `name'      Name of the plugin to load.
+ *  `flags'     Hints on how to handle this plugin.
+ *
+ * RETURN VALUE
+ *  Returns zero upon success, a value greater than zero if no plugin was found
+ *  and a value below zero if an error occurs.
+ *
+ * NOTES
+ *  Re-loading an already loaded module is detected and zero is returned in
+ *  this case.
+ */
+int plugin_load (const char *name, uint32_t flags);
+
+void plugin_init_all (void);
+void plugin_read_all (void);
+int plugin_read_all_once (void);
+void plugin_shutdown_all (void);
+
+/*
+ * NAME
+ *  plugin_write
+ *
+ * DESCRIPTION
+ *  Calls the write function of the given plugin with the provided data set and
+ *  value list. It differs from `plugin_dispatch_value' in that it does not
+ *  update the cache, does not do threshold checking, call the chain subsystem
+ *  and so on. It looks up the requested plugin and invokes the function, end
+ *  of story.
+ *
+ * ARGUMENTS
+ *  plugin     Name of the plugin. If NULL, the value is sent to all registered
+ *             write functions.
+ *  ds         Pointer to the data_set_t structure. If NULL, the data set is
+ *             looked up according to the `type' member in the `vl' argument.
+ *  vl         The actual value to be processed. Must not be NULL.
+ *
+ * RETURN VALUE
+ *  Returns zero upon success or non-zero if an error occurred. If `plugin' is
+ *  NULL and more than one plugin is called, an error is only returned if *all*
+ *  plugins fail.
+ *
+ * NOTES
+ *  This is the function used by the `write' built-in target. May be used by
+ *  other target plugins.
+ */
+int plugin_write (const char *plugin,
+    const data_set_t *ds, const value_list_t *vl);
+
+int plugin_flush (const char *plugin, cdtime_t timeout, const char *identifier);
+
+/*
+ * The `plugin_register_*' functions are used to make `config', `init',
+ * `read', `write' and `shutdown' functions known to the plugin
+ * infrastructure. Also, the data-formats are made public like this.
+ */
+int plugin_register_config (const char *name,
+               int (*callback) (const char *key, const char *val),
+               const char **keys, int keys_num);
+int plugin_register_complex_config (const char *type,
+               int (*callback) (oconfig_item_t *));
+int plugin_register_init (const char *name,
+               plugin_init_cb callback);
+int plugin_register_read (const char *name,
+               int (*callback) (void));
+/* "user_data" will be freed automatically, unless
+ * "plugin_register_complex_read" returns an error (non-zero). */
+int plugin_register_complex_read (const char *group, const char *name,
+               plugin_read_cb callback,
+               const struct timespec *interval,
+               user_data_t *user_data);
+int plugin_register_write (const char *name,
+               plugin_write_cb callback, user_data_t *user_data);
+int plugin_register_flush (const char *name,
+               plugin_flush_cb callback, user_data_t *user_data);
+int plugin_register_missing (const char *name,
+               plugin_missing_cb callback, user_data_t *user_data);
+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, user_data_t *user_data);
+int plugin_register_notification (const char *name,
+               plugin_notification_cb callback, user_data_t *user_data);
+
+int plugin_unregister_config (const char *name);
+int plugin_unregister_complex_config (const char *name);
+int plugin_unregister_init (const char *name);
+int plugin_unregister_read (const char *name);
+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_shutdown (const char *name);
+int plugin_unregister_data_set (const char *name);
+int plugin_unregister_log (const char *name);
+int plugin_unregister_notification (const char *name);
+
+/*
+ * NAME
+ *  plugin_log_available_writers
+ *
+ * DESCRIPTION
+ *  This function can be called to output a list of _all_ registered
+ *  writers to the logfacility.
+ *  Since some writers dynamically build their name it can be hard for
+ *  the configuring person to know it. This function will fill this gap.
+ */
+void plugin_log_available_writers ();
+
+/*
+ * NAME
+ *  plugin_dispatch_values
+ *
+ * DESCRIPTION
+ *  This function is called by reading processes with the values they've
+ *  aquired. The function fetches the data-set definition (that has been
+ *  registered using `plugin_register_data_set') and calls _all_ registered
+ *  write-functions.
+ *
+ * ARGUMENTS
+ *  `vl'        Value list of the values that have been read by a `read'
+ *              function.
+ */
+int plugin_dispatch_values (value_list_t const *vl);
+
+/*
+ * NAME
+ *  plugin_dispatch_multivalue
+ *
+ * SYNOPSIS
+ *  plugin_dispatch_multivalue (vl, 1, DS_TYPE_GAUGE,
+ *                              "free", 42.0,
+ *                              "used", 58.0,
+ *                              NULL);
+ *
+ * DESCRIPTION
+ *  Takes a list of type instances and values and dispatches that in a batch,
+ *  making sure that all values have the same time stamp. If "store_percentage"
+ *  is set to true, the "type" is set to "percent" and a percentage is
+ *  calculated and dispatched, rather than the absolute values. Values that are
+ *  NaN are dispatched as NaN and will not influence the total.
+ *
+ *  The variadic arguments is a list of type_instance / type pairs, that are
+ *  interpreted as type "char const *" and type, encoded by their corresponding
+ *  "store_type":
+ *
+ *     - "gauge_t"    when "DS_TYPE_GAUGE"
+ *     - "absolute_t" when "DS_TYPE_ABSOLUTE"
+ *     - "derive_t"   when "DS_TYPE_DERIVE"
+ *     - "counter_t"  when "DS_TYPE_COUNTER"
+ *
+ *  The last argument must be
+ *  a NULL pointer to signal end-of-list.
+ *
+ * RETURNS
+ *  The number of values it failed to dispatch (zero on success).
+ */
+__attribute__((sentinel))
+int plugin_dispatch_multivalue (value_list_t const *vl,
+               _Bool store_percentage, int store_type, ...);
+
+int plugin_dispatch_missing (const value_list_t *vl);
+
+int plugin_dispatch_notification (const notification_t *notif);
+
+void plugin_log (int level, const char *format, ...)
+       __attribute__ ((format(printf,2,3)));
+
+/* These functions return the parsed severity or less than zero on failure. */
+int parse_log_severity (const char *severity);
+int parse_notif_severity (const char *severity);
+
+#define ERROR(...)   plugin_log (LOG_ERR,     __VA_ARGS__)
+#define WARNING(...) plugin_log (LOG_WARNING, __VA_ARGS__)
+#define NOTICE(...)  plugin_log (LOG_NOTICE,  __VA_ARGS__)
+#define INFO(...)    plugin_log (LOG_INFO,    __VA_ARGS__)
+#if COLLECT_DEBUG
+# define DEBUG(...)  plugin_log (LOG_DEBUG,   __VA_ARGS__)
+#else /* COLLECT_DEBUG */
+# define DEBUG(...)  /* noop */
+#endif /* ! COLLECT_DEBUG */
+
+const data_set_t *plugin_get_ds (const char *name);
+
+int plugin_notification_meta_add_string (notification_t *n,
+    const char *name,
+    const char *value);
+int plugin_notification_meta_add_signed_int (notification_t *n,
+    const char *name,
+    int64_t value);
+int plugin_notification_meta_add_unsigned_int (notification_t *n,
+    const char *name,
+    uint64_t value);
+int plugin_notification_meta_add_double (notification_t *n,
+    const char *name,
+    double value);
+int plugin_notification_meta_add_boolean (notification_t *n,
+    const char *name,
+    _Bool value);
+
+int plugin_notification_meta_copy (notification_t *dst,
+    const notification_t *src);
+
+int plugin_notification_meta_free (notification_meta_t *n);
+
+/*
+ * Plugin context management.
+ */
+
+void plugin_init_ctx (void);
+
+plugin_ctx_t plugin_get_ctx (void);
+plugin_ctx_t plugin_set_ctx (plugin_ctx_t ctx);
+
+/*
+ * NAME
+ *  plugin_get_interval
+ *
+ * DESCRIPTION
+ *  This function returns the current value of the plugin's interval. The
+ *  return value will be strictly greater than zero in all cases. If
+ *  everything else fails, it will fall back to 10 seconds.
+ */
+cdtime_t plugin_get_interval (void);
+
+/*
+ * Context-aware thread management.
+ */
+
+int plugin_thread_create (pthread_t *thread, const pthread_attr_t *attr,
+               void *(*start_routine) (void *), void *arg);
+
+#endif /* PLUGIN_H */
diff --git a/src/daemon/plugin_mock.c b/src/daemon/plugin_mock.c
new file mode 100644 (file)
index 0000000..8652880
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * collectd - src/tests/mock/plugin.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "plugin.h"
+
+void plugin_log (int level, char const *format, ...)
+{
+  char buffer[1024];
+  va_list ap;
+
+  va_start (ap, format);
+  vsnprintf (buffer, sizeof (buffer), format, ap);
+  va_end (ap);
+
+  printf ("plugin_log (%i, \"%s\");\n", level, buffer);
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/types_list.c b/src/daemon/types_list.c
new file mode 100644 (file)
index 0000000..c0e61c5
--- /dev/null
@@ -0,0 +1,207 @@
+/**
+ * collectd - src/types_list.c
+ * Copyright (C) 2007       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+
+#include "plugin.h"
+#include "configfile.h"
+
+static int parse_ds (data_source_t *dsrc, char *buf, size_t buf_len)
+{
+  char *dummy;
+  char *saveptr;
+  char *fields[8];
+  int   fields_num;
+
+  if (buf_len < 11)
+  {
+    ERROR ("parse_ds: (buf_len = %zu) < 11", buf_len);
+    return (-1);
+  }
+
+  if (buf[buf_len - 1] == ',')
+  {
+    buf_len--;
+    buf[buf_len] = '\0';
+  }
+
+  dummy = buf;
+  saveptr = NULL;
+
+  fields_num = 0;
+  while (fields_num < 8)
+  {
+    if ((fields[fields_num] = strtok_r (dummy, ":", &saveptr)) == NULL)
+      break;
+    dummy = NULL;
+    fields_num++;
+  }
+
+  if (fields_num != 4)
+  {
+    ERROR ("parse_ds: (fields_num = %i) != 4", fields_num);
+    return (-1);
+  }
+
+  sstrncpy (dsrc->name, fields[0], sizeof (dsrc->name));
+
+  if (strcasecmp (fields[1], "GAUGE") == 0)
+    dsrc->type = DS_TYPE_GAUGE;
+  else if (strcasecmp (fields[1], "COUNTER") == 0)
+    dsrc->type = DS_TYPE_COUNTER;
+  else if (strcasecmp (fields[1], "DERIVE") == 0)
+    dsrc->type = DS_TYPE_DERIVE;
+  else if (strcasecmp (fields[1], "ABSOLUTE") == 0)
+    dsrc->type = DS_TYPE_ABSOLUTE;
+  else
+  {
+    ERROR ("(fields[1] = %s) != (GAUGE || COUNTER || DERIVE || ABSOLUTE)", fields[1]);
+    return (-1);
+  }
+
+  if (strcasecmp (fields[2], "U") == 0)
+    dsrc->min = NAN;
+  else
+    dsrc->min = atof (fields[2]);
+
+  if (strcasecmp (fields[3], "U") == 0)
+    dsrc->max = NAN;
+  else
+    dsrc->max = atof (fields[3]);
+
+  return (0);
+} /* int parse_ds */
+
+static void parse_line (char *buf)
+{
+  char  *fields[64];
+  size_t fields_num;
+  data_set_t *ds;
+  int i;
+
+  fields_num = strsplit (buf, fields, 64);
+  if (fields_num < 2)
+    return;
+
+  /* Ignore lines which begin with a hash sign. */
+  if (fields[0][0] == '#')
+    return;
+
+  ds = (data_set_t *) malloc (sizeof (data_set_t));
+  if (ds == NULL)
+    return;
+
+  memset (ds, '\0', sizeof (data_set_t));
+
+  sstrncpy (ds->type, fields[0], sizeof (ds->type));
+
+  ds->ds_num = fields_num - 1;
+  ds->ds = (data_source_t *) calloc (ds->ds_num, sizeof (data_source_t));
+  if (ds->ds == NULL)
+    return;
+
+  for (i = 0; i < ds->ds_num; i++)
+    if (parse_ds (ds->ds + i, fields[i + 1], strlen (fields[i + 1])) != 0)
+    {
+      sfree (ds->ds);
+      ERROR ("types_list: parse_line: Cannot parse data source #%i "
+         "of data set %s", i, ds->type);
+      return;
+    }
+
+  plugin_register_data_set (ds);
+
+  sfree (ds->ds);
+  sfree (ds);
+} /* void parse_line */
+
+static void parse_file (FILE *fh)
+{
+  char buf[4096];
+  size_t buf_len;
+
+  while (fgets (buf, sizeof (buf), fh) != NULL)
+  {
+    buf_len = strlen (buf);
+
+    if (buf_len >= 4095)
+    {
+      NOTICE ("Skipping line with more than 4095 characters.");
+      do
+      {
+       if (fgets (buf, sizeof (buf), fh) == NULL)
+         break;
+       buf_len = strlen (buf);
+      } while (buf_len >= 4095);
+      continue;
+    } /* if (buf_len >= 4095) */
+
+    if ((buf_len == 0) || (buf[0] == '#'))
+      continue;
+
+    while ((buf_len > 0) && ((buf[buf_len - 1] == '\n')
+         || (buf[buf_len - 1] == '\r')))
+      buf[--buf_len] = '\0';
+
+    if (buf_len == 0)
+      continue;
+
+    parse_line (buf);
+  } /* while (fgets) */
+} /* void parse_file */
+
+int read_types_list (const char *file)
+{
+  FILE *fh;
+
+  if (file == NULL)
+    return (-1);
+
+  fh = fopen (file, "r");
+  if (fh == NULL)
+  {
+    char errbuf[1024];
+    fprintf (stderr, "Failed to open types database `%s': %s.\n",
+       file, sstrerror (errno, errbuf, sizeof (errbuf)));
+    ERROR ("Failed to open types database `%s': %s",
+       file, sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  parse_file (fh);
+
+  fclose (fh);
+  fh = NULL;
+
+  DEBUG ("Done parsing `%s'", file);
+
+  return (0);
+} /* int read_types_list */
+
+/*
+ * vim: shiftwidth=2:softtabstop=2:tabstop=8
+ */
diff --git a/src/daemon/types_list.h b/src/daemon/types_list.h
new file mode 100644 (file)
index 0000000..f375a2f
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * collectd - src/types_list.h
+ * Copyright (C) 2007       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef TYPES_LIST_H
+#define TYPES_LIST_H 1
+
+int read_types_list (const char *file);
+
+#endif /* TYPES_LIST_H */
diff --git a/src/daemon/utils_avltree.c b/src/daemon/utils_avltree.c
new file mode 100644 (file)
index 0000000..04e5403
--- /dev/null
@@ -0,0 +1,730 @@
+/**
+ * collectd - src/utils_avltree.c
+ * Copyright (C) 2006,2007  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "utils_avltree.h"
+
+#define BALANCE(n) ((((n)->left == NULL) ? 0 : (n)->left->height) \
+               - (((n)->right == NULL) ? 0 : (n)->right->height))
+
+/*
+ * private data types
+ */
+struct c_avl_node_s
+{
+       void *key;
+       void *value;
+
+       int height;
+       struct c_avl_node_s *left;
+       struct c_avl_node_s *right;
+       struct c_avl_node_s *parent;
+};
+typedef struct c_avl_node_s c_avl_node_t;
+
+struct c_avl_tree_s
+{
+       c_avl_node_t *root;
+       int (*compare) (const void *, const void *);
+       int size;
+};
+
+struct c_avl_iterator_s
+{
+       c_avl_tree_t *tree;
+       c_avl_node_t *node;
+};
+
+/*
+ * private functions
+ */
+#if 0
+static void verify_tree (c_avl_node_t *n)
+{
+       if (n == NULL)
+               return;
+
+       verify_tree (n->left);
+       verify_tree (n->right);
+
+       assert ((BALANCE (n) >= -1) && (BALANCE (n) <= 1));
+       assert ((n->parent == NULL) || (n->parent->right == n) || (n->parent->left == n));
+} /* void verify_tree */
+#else
+# define verify_tree(n) /**/
+#endif
+
+static void free_node (c_avl_node_t *n)
+{
+       if (n == NULL)
+               return;
+
+       if (n->left != NULL)
+               free_node (n->left);
+       if (n->right != NULL)
+               free_node (n->right);
+
+       free (n);
+}
+
+static int calc_height (c_avl_node_t *n)
+{
+       int height_left;
+       int height_right;
+
+       if (n == NULL)
+               return (0);
+
+       height_left  = (n->left == NULL)  ? 0 : n->left->height;
+       height_right = (n->right == NULL) ? 0 : n->right->height;
+
+       return (((height_left > height_right)
+                               ? height_left
+                               : height_right) + 1);
+} /* int calc_height */
+
+static c_avl_node_t *search (c_avl_tree_t *t, const void *key)
+{
+       c_avl_node_t *n;
+       int cmp;
+
+       n = t->root;
+       while (n != NULL)
+       {
+               cmp = t->compare (key, n->key);
+               if (cmp == 0)
+                       return (n);
+               else if (cmp < 0)
+                       n = n->left;
+               else
+                       n = n->right;
+       }
+
+       return (NULL);
+}
+
+/*         (x)             (y)
+ *        /   \           /   \
+ *     (y)    /\         /\    (x)
+ *    /   \  /_c\  ==>  / a\  /   \
+ *   /\   /\           /____\/\   /\
+ *  / a\ /_b\               /_b\ /_c\
+ * /____\
+ */
+static c_avl_node_t *rotate_right (c_avl_tree_t *t, c_avl_node_t *x)
+{
+       c_avl_node_t *p;
+       c_avl_node_t *y;
+       c_avl_node_t *b;
+
+       p = x->parent;
+       y = x->left;
+       b = y->right;
+
+       x->left = b;
+       if (b != NULL)
+               b->parent = x;
+
+       x->parent = y;
+       y->right = x;
+
+       y->parent = p;
+       assert ((p == NULL) || (p->left == x) || (p->right == x));
+       if (p == NULL)
+               t->root = y;
+       else if (p->left == x)
+               p->left = y;
+       else
+               p->right = y;
+
+       x->height = calc_height (x);
+       y->height = calc_height (y);
+
+       return (y);
+} /* void rotate_left */
+
+/*
+ *    (x)                   (y)
+ *   /   \                 /   \
+ *  /\    (y)           (x)    /\
+ * /_a\  /   \   ==>   /   \  / c\
+ *      /\   /\       /\   /\/____\
+ *     /_b\ / c\     /_a\ /_b\
+ *         /____\
+ */
+static c_avl_node_t *rotate_left (c_avl_tree_t *t, c_avl_node_t *x)
+{
+       c_avl_node_t *p;
+       c_avl_node_t *y;
+       c_avl_node_t *b;
+
+       p = x->parent;
+       y = x->right;
+       b = y->left;
+
+       x->right = b;
+       if (b != NULL)
+               b->parent = x;
+
+       x->parent = y;
+       y->left = x;
+
+       y->parent = p;
+       assert ((p == NULL) || (p->left == x) || (p->right == x));
+       if (p == NULL)
+               t->root = y;
+       else if (p->left == x)
+               p->left = y;
+       else
+               p->right = y;
+
+       x->height = calc_height (x);
+       y->height = calc_height (y);
+
+       return (y);
+} /* void rotate_left */
+
+static c_avl_node_t *rotate_left_right (c_avl_tree_t *t, c_avl_node_t *x)
+{
+       rotate_left (t, x->left);
+       return (rotate_right (t, x));
+} /* void rotate_left_right */
+
+static c_avl_node_t *rotate_right_left (c_avl_tree_t *t, c_avl_node_t *x)
+{
+       rotate_right (t, x->right);
+       return (rotate_left (t, x));
+} /* void rotate_right_left */
+
+static void rebalance (c_avl_tree_t *t, c_avl_node_t *n)
+{
+       int b_top;
+       int b_bottom;
+
+       while (n != NULL)
+       {
+               b_top = BALANCE (n);
+               assert ((b_top >= -2) && (b_top <= 2));
+
+               if (b_top == -2)
+               {
+                       assert (n->right != NULL);
+                       b_bottom = BALANCE (n->right);
+                       assert ((b_bottom >= -1) || (b_bottom <= 1));
+                       if (b_bottom == 1)
+                               n = rotate_right_left (t, n);
+                       else
+                               n = rotate_left (t, n);
+               }
+               else if (b_top == 2)
+               {
+                       assert (n->left != NULL);
+                       b_bottom = BALANCE (n->left);
+                       assert ((b_bottom >= -1) || (b_bottom <= 1));
+                       if (b_bottom == -1)
+                               n = rotate_left_right (t, n);
+                       else
+                               n = rotate_right (t, n);
+               }
+               else
+               {
+                       int height = calc_height (n);
+                       if (height == n->height)
+                               break;
+                       n->height = height;
+               }
+
+               assert (n->height == calc_height (n));
+
+               n = n->parent;
+       } /* while (n != NULL) */
+} /* void rebalance */
+
+static c_avl_node_t *c_avl_node_next (c_avl_node_t *n)
+{
+       c_avl_node_t *r; /* return node */
+
+       if (n == NULL)
+       {
+               return (NULL);
+       }
+
+       /* If we can't descent any further, we have to backtrack to the first
+        * parent that's bigger than we, i. e. who's _left_ child we are. */
+       if (n->right == NULL)
+       {
+               r = n->parent;
+               while ((r != NULL) && (r->parent != NULL))
+               {
+                       if (r->left == n)
+                               break;
+                       n = r;
+                       r = n->parent;
+               }
+
+               /* n->right == NULL && r == NULL => t is root and has no next
+                * r->left != n => r->right = n => r->parent == NULL */
+               if ((r == NULL) || (r->left != n))
+               {
+                       assert ((r == NULL) || (r->parent == NULL));
+                       return (NULL);
+               }
+               else
+               {
+                       assert (r->left == n);
+                       return (r);
+               }
+       }
+       else
+       {
+               r = n->right;
+               while (r->left != NULL)
+                       r = r->left;
+       }
+
+       return (r);
+} /* c_avl_node_t *c_avl_node_next */
+
+static c_avl_node_t *c_avl_node_prev (c_avl_node_t *n)
+{
+       c_avl_node_t *r; /* return node */
+
+       if (n == NULL)
+       {
+               return (NULL);
+       }
+
+       /* If we can't descent any further, we have to backtrack to the first
+        * parent that's smaller than we, i. e. who's _right_ child we are. */
+       if (n->left == NULL)
+       {
+               r = n->parent;
+               while ((r != NULL) && (r->parent != NULL))
+               {
+                       if (r->right == n)
+                               break;
+                       n = r;
+                       r = n->parent;
+               }
+
+               /* n->left == NULL && r == NULL => t is root and has no next
+                * r->right != n => r->left = n => r->parent == NULL */
+               if ((r == NULL) || (r->right != n))
+               {
+                       assert ((r == NULL) || (r->parent == NULL));
+                       return (NULL);
+               }
+               else
+               {
+                       assert (r->right == n);
+                       return (r);
+               }
+       }
+       else
+       {
+               r = n->left;
+               while (r->right != NULL)
+                       r = r->right;
+       }
+
+       return (r);
+} /* c_avl_node_t *c_avl_node_prev */
+
+static int _remove (c_avl_tree_t *t, c_avl_node_t *n)
+{
+       assert ((t != NULL) && (n != NULL));
+
+       if ((n->left != NULL) && (n->right != NULL))
+       {
+               c_avl_node_t *r; /* replacement node */
+               if (BALANCE (n) > 0) /* left subtree is higher */
+               {
+                       assert (n->left != NULL);
+                       r = c_avl_node_prev (n);
+                       
+               }
+               else /* right subtree is higher */
+               {
+                       assert (n->right != NULL);
+                       r = c_avl_node_next (n);
+               }
+
+               assert ((r->left == NULL) || (r->right == NULL));
+
+               /* copy content */
+               n->key   = r->key;
+               n->value = r->value;
+
+               n = r;
+       }
+
+       assert ((n->left == NULL) || (n->right == NULL));
+
+       if ((n->left == NULL) && (n->right == NULL))
+       {
+               /* Deleting a leave is easy */
+               if (n->parent == NULL)
+               {
+                       assert (t->root == n);
+                       t->root = NULL;
+               }
+               else
+               {
+                       assert ((n->parent->left == n)
+                                       || (n->parent->right == n));
+                       if (n->parent->left == n)
+                               n->parent->left = NULL;
+                       else
+                               n->parent->right = NULL;
+
+                       rebalance (t, n->parent);
+               }
+
+               free_node (n);
+       }
+       else if (n->left == NULL)
+       {
+               assert (BALANCE (n) == -1);
+               assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
+               if (n->parent == NULL)
+               {
+                       assert (t->root == n);
+                       t->root = n->right;
+               }
+               else if (n->parent->left == n)
+               {
+                       n->parent->left = n->right;
+               }
+               else
+               {
+                       n->parent->right = n->right;
+               }
+               n->right->parent = n->parent;
+
+               if (n->parent != NULL)
+                       rebalance (t, n->parent);
+
+               n->right = NULL;
+               free_node (n);
+       }
+       else if (n->right == NULL)
+       {
+               assert (BALANCE (n) == 1);
+               assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
+               if (n->parent == NULL)
+               {
+                       assert (t->root == n);
+                       t->root = n->left;
+               }
+               else if (n->parent->left == n)
+               {
+                       n->parent->left = n->left;
+               }
+               else
+               {
+                       n->parent->right = n->left;
+               }
+               n->left->parent = n->parent;
+
+               if (n->parent != NULL)
+                       rebalance (t, n->parent);
+
+               n->left = NULL;
+               free_node (n);
+       }
+       else
+       {
+               assert (0);
+       }
+
+       return (0);
+} /* void *_remove */
+
+/*
+ * public functions
+ */
+c_avl_tree_t *c_avl_create (int (*compare) (const void *, const void *))
+{
+       c_avl_tree_t *t;
+
+       if (compare == NULL)
+               return (NULL);
+
+       if ((t = (c_avl_tree_t *) malloc (sizeof (c_avl_tree_t))) == NULL)
+               return (NULL);
+
+       t->root = NULL;
+       t->compare = compare;
+       t->size = 0;
+
+       return (t);
+}
+
+void c_avl_destroy (c_avl_tree_t *t)
+{
+       if (t == NULL)
+               return;
+       free_node (t->root);
+       free (t);
+}
+
+int c_avl_insert (c_avl_tree_t *t, void *key, void *value)
+{
+       c_avl_node_t *new;
+       c_avl_node_t *nptr;
+       int cmp;
+
+       if ((new = (c_avl_node_t *) malloc (sizeof (c_avl_node_t))) == NULL)
+               return (-1);
+
+       new->key = key;
+       new->value = value;
+       new->height = 1;
+       new->left = NULL;
+       new->right = NULL;
+
+       if (t->root == NULL)
+       {
+               new->parent = NULL;
+               t->root = new;
+               t->size = 1;
+               return (0);
+       }
+
+       nptr = t->root;
+       while (42)
+       {
+               cmp = t->compare (nptr->key, new->key);
+               if (cmp == 0)
+               {
+                       free_node (new);
+                       return (1);
+               }
+               else if (cmp < 0)
+               {
+                       /* nptr < new */
+                       if (nptr->right == NULL)
+                       {
+                               nptr->right = new;
+                               new->parent = nptr;
+                               rebalance (t, nptr);
+                               break;
+                       }
+                       else
+                       {
+                               nptr = nptr->right;
+                       }
+               }
+               else /* if (cmp > 0) */
+               {
+                       /* nptr > new */
+                       if (nptr->left == NULL)
+                       {
+                               nptr->left = new;
+                               new->parent = nptr;
+                               rebalance (t, nptr);
+                               break;
+                       }
+                       else
+                       {
+                               nptr = nptr->left;
+                       }
+               }
+       } /* while (42) */
+
+       verify_tree (t->root);
+       ++t->size;
+       return (0);
+} /* int c_avl_insert */
+
+int c_avl_remove (c_avl_tree_t *t, const void *key, void **rkey, void **rvalue)
+{
+       c_avl_node_t *n;
+       int status;
+
+       assert (t != NULL);
+
+       n = search (t, key);
+       if (n == NULL)
+               return (-1);
+
+       if (rkey != NULL)
+               *rkey = n->key;
+       if (rvalue != NULL)
+               *rvalue = n->value;
+
+       status = _remove (t, n);
+       verify_tree (t->root);
+       --t->size;
+       return (status);
+} /* void *c_avl_remove */
+
+int c_avl_get (c_avl_tree_t *t, const void *key, void **value)
+{
+       c_avl_node_t *n;
+
+       assert (t != NULL);
+
+       n = search (t, key);
+       if (n == NULL)
+               return (-1);
+
+       if (value != NULL)
+               *value = n->value;
+
+       return (0);
+}
+
+int c_avl_pick (c_avl_tree_t *t, void **key, void **value)
+{
+       c_avl_node_t *n;
+       c_avl_node_t *p;
+
+       if ((key == NULL) || (value == NULL))
+               return (-1);
+       if (t->root == NULL)
+               return (-1);
+
+       n = t->root;
+       while ((n->left != NULL) || (n->right != NULL))
+       {
+               int height_left  = (n->left  == NULL) ? 0 : n->left->height;
+               int height_right = (n->right == NULL) ? 0 : n->right->height;
+
+               if (height_left > height_right)
+                       n = n->left;
+               else
+                       n = n->right;
+       }
+
+       p = n->parent;
+       if (p == NULL)
+               t->root = NULL;
+       else if (p->left == n)
+               p->left = NULL;
+       else
+               p->right = NULL;
+
+       *key   = n->key;
+       *value = n->value;
+
+       free_node (n);
+       rebalance (t, p);
+
+       return (0);
+} /* int c_avl_pick */
+
+c_avl_iterator_t *c_avl_get_iterator (c_avl_tree_t *t)
+{
+       c_avl_iterator_t *iter;
+
+       if (t == NULL)
+               return (NULL);
+
+       iter = (c_avl_iterator_t *) malloc (sizeof (c_avl_iterator_t));
+       if (iter == NULL)
+               return (NULL);
+       memset (iter, '\0', sizeof (c_avl_iterator_t));
+       iter->tree = t;
+
+       return (iter);
+} /* c_avl_iterator_t *c_avl_get_iterator */
+
+int c_avl_iterator_next (c_avl_iterator_t *iter, void **key, void **value)
+{
+       c_avl_node_t *n;
+
+       if ((iter == NULL) || (key == NULL) || (value == NULL))
+               return (-1);
+
+       if (iter->node == NULL)
+       {
+               for (n = iter->tree->root; n != NULL; n = n->left)
+                       if (n->left == NULL)
+                               break;
+               iter->node = n;
+       }
+       else
+       {
+               n = c_avl_node_next (iter->node);
+       }
+
+       if (n == NULL)
+               return (-1);
+
+       iter->node = n;
+       *key = n->key;
+       *value = n->value;
+
+       return (0);
+} /* int c_avl_iterator_next */
+
+int c_avl_iterator_prev (c_avl_iterator_t *iter, void **key, void **value)
+{
+       c_avl_node_t *n;
+
+       if ((iter == NULL) || (key == NULL) || (value == NULL))
+               return (-1);
+
+       if (iter->node == NULL)
+       {
+               for (n = iter->tree->root; n != NULL; n = n->left)
+                       if (n->right == NULL)
+                               break;
+               iter->node = n;
+       }
+       else
+       {
+               n = c_avl_node_prev (iter->node);
+       }
+
+       if (n == NULL)
+               return (-1);
+
+       iter->node = n;
+       *key = n->key;
+       *value = n->value;
+
+       return (0);
+} /* int c_avl_iterator_prev */
+
+void c_avl_iterator_destroy (c_avl_iterator_t *iter)
+{
+       free (iter);
+}
+
+int c_avl_size (c_avl_tree_t *t)
+{
+       if (t == NULL)
+               return (0);
+       return (t->size);
+}
diff --git a/src/daemon/utils_avltree.h b/src/daemon/utils_avltree.h
new file mode 100644 (file)
index 0000000..1e0f271
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * collectd - src/utils_avltree.h
+ * Copyright (C) 2006,2007  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_AVLTREE_H
+#define UTILS_AVLTREE_H 1
+
+struct c_avl_tree_s;
+typedef struct c_avl_tree_s c_avl_tree_t;
+
+struct c_avl_iterator_s;
+typedef struct c_avl_iterator_s c_avl_iterator_t;
+
+/*
+ * NAME
+ *   c_avl_create
+ *
+ * DESCRIPTION
+ *   Allocates a new AVL-tree.
+ *
+ * PARAMETERS
+ *   `compare'  The function-pointer `compare' is used to compare two keys. It
+ *              has to return less than zero if it's first argument is smaller
+ *              then the second argument, more than zero if the first argument
+ *              is bigger than the second argument and zero if they are equal.
+ *              If your keys are char-pointers, you can use the `strcmp'
+ *              function from the libc here.
+ *
+ * RETURN VALUE
+ *   A c_avl_tree_t-pointer upon success or NULL upon failure.
+ */
+c_avl_tree_t *c_avl_create (int (*compare) (const void *, const void *));
+
+
+/*
+ * NAME
+ *   c_avl_destroy
+ *
+ * DESCRIPTION
+ *   Deallocates an AVL-tree. Stored value- and key-pointer are lost, but of
+ *   course not freed.
+ */
+void c_avl_destroy (c_avl_tree_t *t);
+
+/*
+ * NAME
+ *   c_avl_insert
+ *
+ * DESCRIPTION
+ *   Stores the key-value-pair in the AVL-tree pointed to by `t'.
+ *
+ * PARAMETERS
+ *   `t'        AVL-tree to store the data in.
+ *   `key'      Key used to store the value under. This is used to get back to
+ *              the value again. The pointer is stored in an internal structure
+ *              and _not_ copied. So the memory pointed to may _not_ be freed
+ *              before this entry is removed. You can use the `rkey' argument
+ *              to `avl_remove' to get the original pointer back and free it.
+ *   `value'    Value to be stored.
+ *
+ * RETURN VALUE
+ *   Zero upon success, non-zero otherwise. It's less than zero if an error
+ *   occurred or greater than zero if the key is already stored in the tree.
+ */
+int c_avl_insert (c_avl_tree_t *t, void *key, void *value);
+
+/*
+ * NAME
+ *   c_avl_remove
+ *
+ * DESCRIPTION
+ *   Removes a key-value-pair from the tree t. The stored key and value may be
+ *   returned in `rkey' and `rvalue'.
+ *
+ * PARAMETERS
+ *   `t'       AVL-tree to remove key-value-pair from.
+ *   `key'      Key to identify the entry.
+ *   `rkey'     Pointer to a pointer in which to store the key. May be NULL.
+ *              Since the `key' pointer is not copied when creating an entry,
+ *              the pointer may not be available anymore from outside the tree.
+ *              You can use this argument to get the actual pointer back and
+ *              free the memory pointed to by it.
+ *   `rvalue'   Pointer to a pointer in which to store the value. May be NULL.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if the key isn't found in the tree.
+ */
+int c_avl_remove (c_avl_tree_t *t, const void *key, void **rkey, void **rvalue);
+
+/*
+ * NAME
+ *   c_avl_get
+ *
+ * DESCRIPTION
+ *   Retrieve the `value' belonging to `key'.
+ *
+ * PARAMETERS
+ *   `t'       AVL-tree to get the value from.
+ *   `key'      Key to identify the entry.
+ *   `value'    Pointer to a pointer in which to store the value. May be NULL.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if the key isn't found in the tree.
+ */
+int c_avl_get (c_avl_tree_t *t, const void *key, void **value);
+
+/*
+ * NAME
+ *   c_avl_pick
+ *
+ * DESCRIPTION
+ *   Remove a (pseudo-)random element from the tree and return it's `key' and
+ *   `value'. Entries are not returned in any particular order. This function
+ *   is intended for cache-flushes that don't care about the order but simply
+ *   want to remove all elements, one at a time.
+ *
+ * PARAMETERS
+ *   `t'       AVL-tree to get the value from.
+ *   `key'      Pointer to a pointer in which to store the key.
+ *   `value'    Pointer to a pointer in which to store the value.
+ *
+ * RETURN VALUE
+ *   Zero upon success or non-zero if the tree is empty or key or value is
+ *   NULL.
+ */
+int c_avl_pick (c_avl_tree_t *t, void **key, void **value);
+
+c_avl_iterator_t *c_avl_get_iterator (c_avl_tree_t *t);
+int c_avl_iterator_next (c_avl_iterator_t *iter, void **key, void **value);
+int c_avl_iterator_prev (c_avl_iterator_t *iter, void **key, void **value);
+void c_avl_iterator_destroy (c_avl_iterator_t *iter);
+
+/*
+ * NAME
+ *   c_avl_size
+ *
+ * DESCRIPTION
+ *   Return the size (number of nodes) of the specified tree.
+ *
+ * PARAMETERS
+ *   `t'        AVL-tree to get the size of.
+ *
+ * RETURN VALUE
+ *   Number of nodes in the tree, 0 if the tree is empty or NULL.
+ */
+int c_avl_size (c_avl_tree_t *t);
+
+#endif /* UTILS_AVLTREE_H */
diff --git a/src/daemon/utils_avltree_test.c b/src/daemon/utils_avltree_test.c
new file mode 100644 (file)
index 0000000..2a8244c
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * collectd - src/tests/test_utils_avltree.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "testing.h"
+#include "collectd.h"
+#include "utils_avltree.h"
+
+static int compare_total_count = 0;
+#define RESET_COUNTS() do { compare_total_count = 0; } while (0)
+
+static int compare_callback (void const *v0, void const *v1)
+{
+  assert (v0 != NULL);
+  assert (v1 != NULL);
+
+  compare_total_count++;
+  return (strcmp (v0, v1));
+}
+
+DEF_TEST(success)
+{
+  c_avl_tree_t *t;
+  char key_orig[] = "foo";
+  char value_orig[] = "bar";
+  char *key_ret = NULL;
+  char *value_ret = NULL;
+
+  RESET_COUNTS ();
+  t = c_avl_create (compare_callback);
+  OK (t != NULL);
+
+  OK (c_avl_insert (t, key_orig, value_orig) == 0);
+  OK (c_avl_size (t) == 1);
+
+  /* Key already exists. */
+  OK (c_avl_insert (t, "foo", "qux") > 0);
+
+  OK (c_avl_get (t, "foo", (void *) &value_ret) == 0);
+  OK (value_ret == &value_orig[0]);
+
+  key_ret = value_ret = NULL;
+  OK (c_avl_remove (t, "foo", (void *) &key_ret, (void *) &value_ret) == 0);
+  OK (key_ret == &key_orig[0]);
+  OK (value_ret == &value_orig[0]);
+  OK (c_avl_size (t) == 0);
+
+  c_avl_destroy (t);
+
+  return (0);
+}
+
+int main (void)
+{
+  RUN_TEST(success);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/utils_cache.c b/src/daemon/utils_cache.c
new file mode 100644 (file)
index 0000000..fe22f21
--- /dev/null
@@ -0,0 +1,988 @@
+/**
+ * collectd - src/utils_cache.c
+ * Copyright (C) 2007-2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_avltree.h"
+#include "utils_cache.h"
+#include "meta_data.h"
+
+#include <assert.h>
+#include <pthread.h>
+
+typedef struct cache_entry_s
+{
+       char name[6 * DATA_MAX_NAME_LEN];
+       int        values_num;
+       gauge_t   *values_gauge;
+       value_t   *values_raw;
+       /* Time contained in the package
+        * (for calculating rates) */
+       cdtime_t last_time;
+       /* Time according to the local clock
+        * (for purging old entries) */
+       cdtime_t last_update;
+       /* Interval in which the data is collected
+        * (for purding old entries) */
+       cdtime_t interval;
+       int state;
+       int hits;
+
+       /*
+        * +-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+        * !  0  !  1  !  2  !  3  !  4  !  5  !  6  !  7  !  8  ! ...
+        * +-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+        * ! ds0 ! ds1 ! ds2 ! ds0 ! ds1 ! ds2 ! ds0 ! ds1 ! ds2 ! ...
+        * +-----+-----+-----+-----+-----+-----+-----+-----+-----+----
+        * !      t = 0      !      t = 1      !      t = 2      ! ...
+        * +-----------------+-----------------+-----------------+----
+        */
+       gauge_t *history;
+       size_t   history_index; /* points to the next position to write to. */
+       size_t   history_length;
+
+       meta_data_t *meta;
+} cache_entry_t;
+
+static c_avl_tree_t   *cache_tree = NULL;
+static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int cache_compare (const cache_entry_t *a, const cache_entry_t *b)
+{
+#if COLLECT_DEBUG
+  assert ((a != NULL) && (b != NULL));
+#endif
+  return (strcmp (a->name, b->name));
+} /* int cache_compare */
+
+static cache_entry_t *cache_alloc (int values_num)
+{
+  cache_entry_t *ce;
+
+  ce = (cache_entry_t *) malloc (sizeof (cache_entry_t));
+  if (ce == NULL)
+  {
+    ERROR ("utils_cache: cache_alloc: malloc failed.");
+    return (NULL);
+  }
+  memset (ce, '\0', sizeof (cache_entry_t));
+  ce->values_num = values_num;
+
+  ce->values_gauge = calloc (values_num, sizeof (*ce->values_gauge));
+  ce->values_raw   = calloc (values_num, sizeof (*ce->values_raw));
+  if ((ce->values_gauge == NULL) || (ce->values_raw == NULL))
+  {
+    sfree (ce->values_gauge);
+    sfree (ce->values_raw);
+    sfree (ce);
+    ERROR ("utils_cache: cache_alloc: calloc failed.");
+    return (NULL);
+  }
+
+  ce->history = NULL;
+  ce->history_length = 0;
+  ce->meta = NULL;
+
+  return (ce);
+} /* cache_entry_t *cache_alloc */
+
+static void cache_free (cache_entry_t *ce)
+{
+  if (ce == NULL)
+    return;
+
+  sfree (ce->values_gauge);
+  sfree (ce->values_raw);
+  sfree (ce->history);
+  if (ce->meta != NULL)
+  {
+    meta_data_destroy (ce->meta);
+    ce->meta = NULL;
+  }
+  sfree (ce);
+} /* void cache_free */
+
+static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
+{
+  int i;
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if (isnan (ce->values_gauge[i]))
+      continue;
+    else if (ce->values_gauge[i] < ds->ds[i].min)
+      ce->values_gauge[i] = NAN;
+    else if (ce->values_gauge[i] > ds->ds[i].max)
+      ce->values_gauge[i] = NAN;
+  }
+} /* void uc_check_range */
+
+static int uc_insert (const data_set_t *ds, const value_list_t *vl,
+    const char *key)
+{
+  int i;
+  char *key_copy;
+  cache_entry_t *ce;
+
+  /* `cache_lock' has been locked by `uc_update' */
+
+  key_copy = strdup (key);
+  if (key_copy == NULL)
+  {
+    ERROR ("uc_insert: strdup failed.");
+    return (-1);
+  }
+
+  ce = cache_alloc (ds->ds_num);
+  if (ce == NULL)
+  {
+    sfree (key_copy);
+    ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
+    return (-1);
+  }
+
+  sstrncpy (ce->name, key, sizeof (ce->name));
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    switch (ds->ds[i].type)
+    {
+      case DS_TYPE_COUNTER:
+       ce->values_gauge[i] = NAN;
+       ce->values_raw[i].counter = vl->values[i].counter;
+       break;
+
+      case DS_TYPE_GAUGE:
+       ce->values_gauge[i] = vl->values[i].gauge;
+       ce->values_raw[i].gauge = vl->values[i].gauge;
+       break;
+
+      case DS_TYPE_DERIVE:
+       ce->values_gauge[i] = NAN;
+       ce->values_raw[i].derive = vl->values[i].derive;
+       break;
+
+      case DS_TYPE_ABSOLUTE:
+       ce->values_gauge[i] = NAN;
+       if (vl->interval > 0)
+         ce->values_gauge[i] = ((double) vl->values[i].absolute)
+           / CDTIME_T_TO_DOUBLE (vl->interval);
+       ce->values_raw[i].absolute = vl->values[i].absolute;
+       break;
+       
+      default:
+       /* This shouldn't happen. */
+       ERROR ("uc_insert: Don't know how to handle data source type %i.",
+           ds->ds[i].type);
+       return (-1);
+    } /* switch (ds->ds[i].type) */
+  } /* for (i) */
+
+  /* Prune invalid gauge data */
+  uc_check_range (ds, ce);
+
+  ce->last_time = vl->time;
+  ce->last_update = cdtime ();
+  ce->interval = vl->interval;
+  ce->state = STATE_OKAY;
+
+  if (c_avl_insert (cache_tree, key_copy, ce) != 0)
+  {
+    sfree (key_copy);
+    ERROR ("uc_insert: c_avl_insert failed.");
+    return (-1);
+  }
+
+  DEBUG ("uc_insert: Added %s to the cache.", key);
+  return (0);
+} /* int uc_insert */
+
+int uc_init (void)
+{
+  if (cache_tree == NULL)
+    cache_tree = c_avl_create ((int (*) (const void *, const void *))
+       cache_compare);
+
+  return (0);
+} /* int uc_init */
+
+int uc_check_timeout (void)
+{
+  cdtime_t now;
+  cache_entry_t *ce;
+
+  char **keys = NULL;
+  cdtime_t *keys_time = NULL;
+  cdtime_t *keys_interval = NULL;
+  int keys_len = 0;
+
+  char *key;
+  c_avl_iterator_t *iter;
+
+  int status;
+  int i;
+  
+  pthread_mutex_lock (&cache_lock);
+
+  now = cdtime ();
+
+  /* Build a list of entries to be flushed */
+  iter = c_avl_get_iterator (cache_tree);
+  while (c_avl_iterator_next (iter, (void *) &key, (void *) &ce) == 0)
+  {
+    char **tmp;
+    cdtime_t *tmp_time;
+
+    /* If the entry is fresh enough, continue. */
+    if ((now - ce->last_update) < (ce->interval * timeout_g))
+      continue;
+
+    /* If entry has not been updated, add to `keys' array */
+    tmp = (char **) realloc ((void *) keys,
+       (keys_len + 1) * sizeof (char *));
+    if (tmp == NULL)
+    {
+      ERROR ("uc_check_timeout: realloc failed.");
+      continue;
+    }
+    keys = tmp;
+
+    tmp_time = realloc (keys_time, (keys_len + 1) * sizeof (*keys_time));
+    if (tmp_time == NULL)
+    {
+      ERROR ("uc_check_timeout: realloc failed.");
+      continue;
+    }
+    keys_time = tmp_time;
+
+    tmp_time = realloc (keys_interval, (keys_len + 1) * sizeof (*keys_interval));
+    if (tmp_time == NULL)
+    {
+      ERROR ("uc_check_timeout: realloc failed.");
+      continue;
+    }
+    keys_interval = tmp_time;
+
+    keys[keys_len] = strdup (key);
+    if (keys[keys_len] == NULL)
+    {
+      ERROR ("uc_check_timeout: strdup failed.");
+      continue;
+    }
+    keys_time[keys_len] = ce->last_time;
+    keys_interval[keys_len] = ce->interval;
+
+    keys_len++;
+  } /* while (c_avl_iterator_next) */
+
+  c_avl_iterator_destroy (iter);
+  pthread_mutex_unlock (&cache_lock);
+
+  if (keys_len == 0)
+    return (0);
+
+  /* Call the "missing" callback for each value. Do this before removing the
+   * value from the cache, so that callbacks can still access the data stored,
+   * including plugin specific meta data, rates, history, …. This must be done
+   * without holding the lock, otherwise we will run into a deadlock if a
+   * plugin calls the cache interface. */
+  for (i = 0; i < keys_len; i++)
+  {
+    value_list_t vl = VALUE_LIST_INIT;
+
+    vl.values = NULL;
+    vl.values_len = 0;
+    vl.meta = NULL;
+
+    status = parse_identifier_vl (keys[i], &vl);
+    if (status != 0)
+    {
+      ERROR ("uc_check_timeout: parse_identifier_vl (\"%s\") failed.", keys[i]);
+      cache_free (ce);
+      continue;
+    }
+
+    vl.time = keys_time[i];
+    vl.interval = keys_interval[i];
+
+    plugin_dispatch_missing (&vl);
+  } /* for (i = 0; i < keys_len; i++) */
+
+  /* Now actually remove all the values from the cache. We don't re-evaluate
+   * the timestamp again, so in theory it is possible we remove a value after
+   * it is updated here. */
+  pthread_mutex_lock (&cache_lock);
+  for (i = 0; i < keys_len; i++)
+  {
+    key = NULL;
+    ce = NULL;
+
+    status = c_avl_remove (cache_tree, keys[i],
+       (void *) &key, (void *) &ce);
+    if (status != 0)
+    {
+      ERROR ("uc_check_timeout: c_avl_remove (\"%s\") failed.", keys[i]);
+      sfree (keys[i]);
+      continue;
+    }
+
+    sfree (keys[i]);
+    sfree (key);
+    cache_free (ce);
+  } /* for (i = 0; i < keys_len; i++) */
+  pthread_mutex_unlock (&cache_lock);
+
+  sfree (keys);
+  sfree (keys_time);
+  sfree (keys_interval);
+
+  return (0);
+} /* int uc_check_timeout */
+
+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;
+  int i;
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("uc_update: FORMAT_VL failed.");
+    return (-1);
+  }
+
+  pthread_mutex_lock (&cache_lock);
+
+  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);
+    return (status);
+  }
+
+  assert (ce != NULL);
+  assert (ce->values_num == ds->ds_num);
+
+  if (ce->last_time >= vl->time)
+  {
+    pthread_mutex_unlock (&cache_lock);
+    NOTICE ("uc_update: Value too old: name = %s; value time = %.3f; "
+       "last cache update = %.3f;",
+       name,
+       CDTIME_T_TO_DOUBLE (vl->time),
+       CDTIME_T_TO_DOUBLE (ce->last_time));
+    return (-1);
+  }
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    switch (ds->ds[i].type)
+    {
+      case DS_TYPE_COUNTER:
+       {
+         counter_t diff;
+
+         /* check if the counter has wrapped around */
+         if (vl->values[i].counter < ce->values_raw[i].counter)
+         {
+           if (ce->values_raw[i].counter <= 4294967295U)
+             diff = (4294967295U - ce->values_raw[i].counter)
+               + vl->values[i].counter;
+           else
+             diff = (18446744073709551615ULL - ce->values_raw[i].counter)
+               + vl->values[i].counter;
+         }
+         else /* counter has NOT wrapped around */
+         {
+           diff = vl->values[i].counter - ce->values_raw[i].counter;
+         }
+
+         ce->values_gauge[i] = ((double) diff)
+           / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
+         ce->values_raw[i].counter = vl->values[i].counter;
+       }
+       break;
+
+      case DS_TYPE_GAUGE:
+       ce->values_raw[i].gauge = vl->values[i].gauge;
+       ce->values_gauge[i] = vl->values[i].gauge;
+       break;
+
+      case DS_TYPE_DERIVE:
+       {
+         derive_t diff;
+
+         diff = vl->values[i].derive - ce->values_raw[i].derive;
+
+         ce->values_gauge[i] = ((double) diff)
+           / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
+         ce->values_raw[i].derive = vl->values[i].derive;
+       }
+       break;
+
+      case DS_TYPE_ABSOLUTE:
+       ce->values_gauge[i] = ((double) vl->values[i].absolute)
+         / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
+       ce->values_raw[i].absolute = vl->values[i].absolute;
+       break;
+
+      default:
+       /* This shouldn't happen. */
+       pthread_mutex_unlock (&cache_lock);
+       ERROR ("uc_update: Don't know how to handle data source type %i.",
+           ds->ds[i].type);
+       return (-1);
+    } /* switch (ds->ds[i].type) */
+
+    DEBUG ("uc_update: %s: ds[%i] = %lf", name, i, ce->values_gauge[i]);
+  } /* for (i) */
+
+  /* Update the history if it exists. */
+  if (ce->history != NULL)
+  {
+    assert (ce->history_index < ce->history_length);
+    for (i = 0; i < ce->values_num; i++)
+    {
+      size_t hist_idx = (ce->values_num * ce->history_index) + i;
+      ce->history[hist_idx] = ce->values_gauge[i];
+    }
+
+    assert (ce->history_length > 0);
+    ce->history_index = (ce->history_index + 1) % ce->history_length;
+  }
+
+  /* Prune invalid gauge data */
+  uc_check_range (ds, ce);
+
+  ce->last_time = vl->time;
+  ce->last_update = cdtime ();
+  ce->interval = vl->interval;
+
+  pthread_mutex_unlock (&cache_lock);
+
+  return (0);
+} /* int uc_update */
+
+int uc_get_rate_by_name (const char *name, gauge_t **ret_values, size_t *ret_values_num)
+{
+  gauge_t *ret = NULL;
+  size_t ret_num = 0;
+  cache_entry_t *ce = NULL;
+  int status = 0;
+
+  pthread_mutex_lock (&cache_lock);
+
+  if (c_avl_get (cache_tree, name, (void *) &ce) == 0)
+  {
+    assert (ce != NULL);
+
+    /* remove missing values from getval */
+    if (ce->state == STATE_MISSING)
+    {
+      status = -1;
+    }
+    else
+    {
+      ret_num = ce->values_num;
+      ret = (gauge_t *) malloc (ret_num * sizeof (gauge_t));
+      if (ret == NULL)
+      {
+        ERROR ("utils_cache: uc_get_rate_by_name: malloc failed.");
+        status = -1;
+      }
+      else
+      {
+        memcpy (ret, ce->values_gauge, ret_num * sizeof (gauge_t));
+      }
+    }
+  }
+  else
+  {
+    DEBUG ("utils_cache: uc_get_rate_by_name: No such value: %s", name);
+    status = -1;
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+
+  if (status == 0)
+  {
+    *ret_values = ret;
+    *ret_values_num = ret_num;
+  }
+
+  return (status);
+} /* gauge_t *uc_get_rate_by_name */
+
+gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  gauge_t *ret = NULL;
+  size_t ret_num = 0;
+  int status;
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("utils_cache: uc_get_rate: FORMAT_VL failed.");
+    return (NULL);
+  }
+
+  status = uc_get_rate_by_name (name, &ret, &ret_num);
+  if (status != 0)
+    return (NULL);
+
+  /* This is important - the caller has no other way of knowing how many
+   * values are returned. */
+  if (ret_num != (size_t) ds->ds_num)
+  {
+    ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
+       "but uc_get_rate_by_name returned %zu.",
+       ds->type, ds->ds_num, ret_num);
+    sfree (ret);
+    return (NULL);
+  }
+
+  return (ret);
+} /* gauge_t *uc_get_rate */
+
+size_t uc_get_size() {
+  size_t size_arrays = 0;
+
+  pthread_mutex_lock (&cache_lock);
+  size_arrays = (size_t) c_avl_size (cache_tree);
+  pthread_mutex_unlock (&cache_lock);
+
+  return (size_arrays);
+}
+
+int uc_get_names (char ***ret_names, cdtime_t **ret_times, size_t *ret_number)
+{
+  c_avl_iterator_t *iter;
+  char *key;
+  cache_entry_t *value;
+
+  char **names = NULL;
+  cdtime_t *times = NULL;
+  size_t number = 0;
+  size_t size_arrays = 0;
+
+  int status = 0;
+
+  if ((ret_names == NULL) || (ret_number == NULL))
+    return (-1);
+
+  pthread_mutex_lock (&cache_lock);
+
+  size_arrays = (size_t) c_avl_size (cache_tree);
+  if (size_arrays < 1)
+  {
+    /* Handle the "no values" case here, to avoid the error message when
+     * calloc() returns NULL. */
+    pthread_mutex_unlock (&cache_lock);
+    return (0);
+  }
+
+  names = calloc (size_arrays, sizeof (*names));
+  times = calloc (size_arrays, sizeof (*times));
+  if ((names == NULL) || (times == NULL))
+  {
+    ERROR ("uc_get_names: calloc failed.");
+    sfree (names);
+    sfree (times);
+    pthread_mutex_unlock (&cache_lock);
+    return (ENOMEM);
+  }
+
+  iter = c_avl_get_iterator (cache_tree);
+  while (c_avl_iterator_next (iter, (void *) &key, (void *) &value) == 0)
+  {
+    /* remove missing values when list values */
+    if (value->state == STATE_MISSING)
+      continue;
+
+    /* c_avl_size does not return a number smaller than the number of elements
+     * returned by c_avl_iterator_next. */
+    assert (number < size_arrays);
+
+    if (ret_times != NULL)
+      times[number] = value->last_time;
+
+    names[number] = strdup (key);
+    if (names[number] == NULL)
+    {
+      status = -1;
+      break;
+    }
+
+    number++;
+  } /* while (c_avl_iterator_next) */
+
+  c_avl_iterator_destroy (iter);
+  pthread_mutex_unlock (&cache_lock);
+
+  if (status != 0)
+  {
+    size_t i;
+    
+    for (i = 0; i < number; i++)
+    {
+      sfree (names[i]);
+    }
+    sfree (names);
+
+    return (-1);
+  }
+
+  *ret_names = names;
+  if (ret_times != NULL)
+    *ret_times = times;
+  *ret_number = number;
+
+  return (0);
+} /* int uc_get_names */
+
+int uc_get_state (const data_set_t *ds, const value_list_t *vl)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  cache_entry_t *ce = NULL;
+  int ret = STATE_ERROR;
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("uc_get_state: FORMAT_VL failed.");
+    return (STATE_ERROR);
+  }
+
+  pthread_mutex_lock (&cache_lock);
+
+  if (c_avl_get (cache_tree, name, (void *) &ce) == 0)
+  {
+    assert (ce != NULL);
+    ret = ce->state;
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+
+  return (ret);
+} /* int uc_get_state */
+
+int uc_set_state (const data_set_t *ds, const value_list_t *vl, int state)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  cache_entry_t *ce = NULL;
+  int ret = -1;
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("uc_get_state: FORMAT_VL failed.");
+    return (STATE_ERROR);
+  }
+
+  pthread_mutex_lock (&cache_lock);
+
+  if (c_avl_get (cache_tree, name, (void *) &ce) == 0)
+  {
+    assert (ce != NULL);
+    ret = ce->state;
+    ce->state = state;
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+
+  return (ret);
+} /* int uc_set_state */
+
+int uc_get_history_by_name (const char *name,
+    gauge_t *ret_history, size_t num_steps, size_t num_ds)
+{
+  cache_entry_t *ce = NULL;
+  size_t i;
+  int status = 0;
+
+  pthread_mutex_lock (&cache_lock);
+
+  status = c_avl_get (cache_tree, name, (void *) &ce);
+  if (status != 0)
+  {
+    pthread_mutex_unlock (&cache_lock);
+    return (-ENOENT);
+  }
+
+  if (((size_t) ce->values_num) != num_ds)
+  {
+    pthread_mutex_unlock (&cache_lock);
+    return (-EINVAL);
+  }
+
+  /* Check if there are enough values available. If not, increase the buffer
+   * size. */
+  if (ce->history_length < num_steps)
+  {
+    gauge_t *tmp;
+    size_t i;
+
+    tmp = realloc (ce->history, sizeof (*ce->history)
+       * num_steps * ce->values_num);
+    if (tmp == NULL)
+    {
+      pthread_mutex_unlock (&cache_lock);
+      return (-ENOMEM);
+    }
+
+    for (i = ce->history_length * ce->values_num;
+       i < (num_steps * ce->values_num);
+       i++)
+      tmp[i] = NAN;
+
+    ce->history = tmp;
+    ce->history_length = num_steps;
+  } /* if (ce->history_length < num_steps) */
+
+  /* Copy the values to the output buffer. */
+  for (i = 0; i < num_steps; i++)
+  {
+    size_t src_index;
+    size_t dst_index;
+
+    if (i < ce->history_index)
+      src_index = ce->history_index - (i + 1);
+    else
+      src_index = ce->history_length + ce->history_index - (i + 1);
+    src_index = src_index * num_ds;
+
+    dst_index = i * num_ds;
+
+    memcpy (ret_history + dst_index, ce->history + src_index,
+       sizeof (*ret_history) * num_ds);
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+
+  return (0);
+} /* int uc_get_history_by_name */
+
+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)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("utils_cache: uc_get_history: FORMAT_VL failed.");
+    return (-1);
+  }
+
+  return (uc_get_history_by_name (name, ret_history, num_steps, num_ds));
+} /* int uc_get_history */
+
+int uc_get_hits (const data_set_t *ds, const value_list_t *vl)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  cache_entry_t *ce = NULL;
+  int ret = STATE_ERROR;
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("uc_get_state: FORMAT_VL failed.");
+    return (STATE_ERROR);
+  }
+
+  pthread_mutex_lock (&cache_lock);
+
+  if (c_avl_get (cache_tree, name, (void *) &ce) == 0)
+  {
+    assert (ce != NULL);
+    ret = ce->hits;
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+
+  return (ret);
+} /* int uc_get_hits */
+
+int uc_set_hits (const data_set_t *ds, const value_list_t *vl, int hits)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  cache_entry_t *ce = NULL;
+  int ret = -1;
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("uc_get_state: FORMAT_VL failed.");
+    return (STATE_ERROR);
+  }
+
+  pthread_mutex_lock (&cache_lock);
+
+  if (c_avl_get (cache_tree, name, (void *) &ce) == 0)
+  {
+    assert (ce != NULL);
+    ret = ce->hits;
+    ce->hits = hits;
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+
+  return (ret);
+} /* int uc_set_hits */
+
+int uc_inc_hits (const data_set_t *ds, const value_list_t *vl, int step)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  cache_entry_t *ce = NULL;
+  int ret = -1;
+
+  if (FORMAT_VL (name, sizeof (name), vl) != 0)
+  {
+    ERROR ("uc_get_state: FORMAT_VL failed.");
+    return (STATE_ERROR);
+  }
+
+  pthread_mutex_lock (&cache_lock);
+
+  if (c_avl_get (cache_tree, name, (void *) &ce) == 0)
+  {
+    assert (ce != NULL);
+    ret = ce->hits;
+    ce->hits = ret + step;
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+
+  return (ret);
+} /* int uc_inc_hits */
+
+/*
+ * Meta data interface
+ */
+/* XXX: This function will acquire `cache_lock' but will not free it! */
+static meta_data_t *uc_get_meta (const value_list_t *vl) /* {{{ */
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  cache_entry_t *ce = NULL;
+  int status;
+
+  status = FORMAT_VL (name, sizeof (name), vl);
+  if (status != 0)
+  {
+    ERROR ("utils_cache: uc_get_meta: FORMAT_VL failed.");
+    return (NULL);
+  }
+
+  pthread_mutex_lock (&cache_lock);
+
+  status = c_avl_get (cache_tree, name, (void *) &ce);
+  if (status != 0)
+  {
+    pthread_mutex_unlock (&cache_lock);
+    return (NULL);
+  }
+  assert (ce != NULL);
+
+  if (ce->meta == NULL)
+    ce->meta = meta_data_create ();
+
+  if (ce->meta == NULL)
+    pthread_mutex_unlock (&cache_lock);
+
+  return (ce->meta);
+} /* }}} meta_data_t *uc_get_meta */
+
+/* Sorry about this preprocessor magic, but it really makes this file much
+ * shorter.. */
+#define UC_WRAP(wrap_function) { \
+  meta_data_t *meta; \
+  int status; \
+  meta = uc_get_meta (vl); \
+  if (meta == NULL) return (-1); \
+  status = wrap_function (meta, key); \
+  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_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
+ * two argumetns. */
+#define UC_WRAP(wrap_function) { \
+  meta_data_t *meta; \
+  int status; \
+  meta = uc_get_meta (vl); \
+  if (meta == NULL) return (-1); \
+  status = wrap_function (meta, key, value); \
+  pthread_mutex_unlock (&cache_lock); \
+  return (status); \
+}
+int uc_meta_data_add_string (const value_list_t *vl,
+    const char *key,
+    const char *value)
+  UC_WRAP(meta_data_add_string)
+int uc_meta_data_add_signed_int (const value_list_t *vl,
+    const char *key,
+    int64_t value)
+  UC_WRAP(meta_data_add_signed_int)
+int uc_meta_data_add_unsigned_int (const value_list_t *vl,
+    const char *key,
+    uint64_t value)
+  UC_WRAP(meta_data_add_unsigned_int)
+int uc_meta_data_add_double (const value_list_t *vl,
+    const char *key,
+    double value)
+  UC_WRAP(meta_data_add_double)
+int uc_meta_data_add_boolean (const value_list_t *vl,
+    const char *key,
+    _Bool value)
+  UC_WRAP(meta_data_add_boolean)
+
+int uc_meta_data_get_string (const value_list_t *vl,
+    const char *key,
+    char **value)
+  UC_WRAP(meta_data_get_string)
+int uc_meta_data_get_signed_int (const value_list_t *vl,
+    const char *key,
+    int64_t *value)
+  UC_WRAP(meta_data_get_signed_int)
+int uc_meta_data_get_unsigned_int (const value_list_t *vl,
+    const char *key,
+    uint64_t *value)
+  UC_WRAP(meta_data_get_unsigned_int)
+int uc_meta_data_get_double (const value_list_t *vl,
+    const char *key,
+    double *value)
+  UC_WRAP(meta_data_get_double)
+int uc_meta_data_get_boolean (const value_list_t *vl,
+    const char *key,
+    _Bool *value)
+  UC_WRAP(meta_data_get_boolean)
+#undef UC_WRAP
+
+/* vim: set sw=2 ts=8 sts=2 tw=78 : */
diff --git a/src/daemon/utils_cache.h b/src/daemon/utils_cache.h
new file mode 100644 (file)
index 0000000..ea3eb2f
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * collectd - src/utils_cache.h
+ * Copyright (C) 2007       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_CACHE_H
+#define UTILS_CACHE_H 1
+
+#include "plugin.h"
+
+#define STATE_OKAY     0
+#define STATE_WARNING  1
+#define STATE_ERROR    2
+#define STATE_MISSING 15
+
+int uc_init (void);
+int uc_check_timeout (void);
+int uc_update (const data_set_t *ds, const value_list_t *vl);
+int uc_get_rate_by_name (const char *name, gauge_t **ret_values, size_t *ret_values_num);
+gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl);
+
+size_t uc_get_size();
+int uc_get_names (char ***ret_names, cdtime_t **ret_times, size_t *ret_number);
+
+int uc_get_state (const data_set_t *ds, const value_list_t *vl);
+int uc_set_state (const data_set_t *ds, const value_list_t *vl, int state);
+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_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, size_t num_steps, size_t num_ds);
+
+/*
+ * Meta data interface
+ */
+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);
+
+int uc_meta_data_add_string (const value_list_t *vl,
+    const char *key,
+    const char *value);
+int uc_meta_data_add_signed_int (const value_list_t *vl,
+    const char *key,
+    int64_t value);
+int uc_meta_data_add_unsigned_int (const value_list_t *vl,
+    const char *key,
+    uint64_t value);
+int uc_meta_data_add_double (const value_list_t *vl,
+    const char *key,
+    double value);
+int uc_meta_data_add_boolean (const value_list_t *vl,
+    const char *key,
+    _Bool value);
+
+int uc_meta_data_get_string (const value_list_t *vl,
+    const char *key,
+    char **value);
+int uc_meta_data_get_signed_int (const value_list_t *vl,
+    const char *key,
+    int64_t *value);
+int uc_meta_data_get_unsigned_int (const value_list_t *vl,
+    const char *key,
+    uint64_t *value);
+int uc_meta_data_get_double (const value_list_t *vl,
+    const char *key,
+    double *value);
+int uc_meta_data_get_boolean (const value_list_t *vl,
+    const char *key,
+    _Bool *value);
+
+/* vim: set shiftwidth=2 softtabstop=2 tabstop=8 : */
+#endif /* !UTILS_CACHE_H */
diff --git a/src/daemon/utils_cache_mock.c b/src/daemon/utils_cache_mock.c
new file mode 100644 (file)
index 0000000..6c78d64
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * collectd - src/tests/mock/utils_cache.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "utils_cache.h"
+
+gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+{
+  return (NULL);
+}
diff --git a/src/daemon/utils_complain.c b/src/daemon/utils_complain.c
new file mode 100644 (file)
index 0000000..6193614
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * collectd - src/utils_complain.c
+ * Copyright (C) 2006-2013  Florian octo Forster
+ * Copyright (C) 2008       Sebastian tokkee Harl
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
+ **/
+
+#include "collectd.h"
+#include "utils_complain.h"
+#include "plugin.h"
+
+/* vcomplain returns 0 if it did not report, 1 else */
+static int vcomplain (int level, c_complain_t *c,
+               const char *format, va_list ap)
+{
+       cdtime_t now;
+       char   message[512];
+
+       now = cdtime ();
+
+       if (c->last + c->interval > now)
+               return 0;
+
+       c->last = now;
+
+       if (c->interval < plugin_get_interval ())
+               c->interval = plugin_get_interval ();
+       else
+               c->interval *= 2;
+
+       if (c->interval > TIME_T_TO_CDTIME_T (86400))
+               c->interval = TIME_T_TO_CDTIME_T (86400);
+
+       vsnprintf (message, sizeof (message), format, ap);
+       message[sizeof (message) - 1] = '\0';
+
+       plugin_log (level, "%s", message);
+       return 1;
+} /* vcomplain */
+
+void c_complain (int level, c_complain_t *c, const char *format, ...)
+{
+       va_list ap;
+
+       va_start (ap, format);
+       if (vcomplain (level, c, format, ap))
+               c->complained_once = 1;
+       va_end (ap);
+} /* c_complain */
+
+void c_complain_once (int level, c_complain_t *c, const char *format, ...)
+{
+       va_list ap;
+
+       if (c->complained_once)
+               return;
+
+       va_start (ap, format);
+       if (vcomplain (level, c, format, ap))
+               c->complained_once = 1;
+       va_end (ap);
+} /* c_complain_once */
+
+void c_do_release (int level, c_complain_t *c, const char *format, ...)
+{
+       char message[512];
+       va_list ap;
+
+       if (c->interval == 0)
+               return;
+
+       c->interval = 0;
+       c->complained_once = 0;
+
+       va_start (ap, format);
+       vsnprintf (message, sizeof (message), format, ap);
+       message[sizeof (message) - 1] = '\0';
+       va_end (ap);
+
+       plugin_log (level, "%s", message);
+} /* c_release */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/daemon/utils_complain.h b/src/daemon/utils_complain.h
new file mode 100644 (file)
index 0000000..390f961
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * collectd - src/utils_complain.h
+ * Copyright (C) 2006-2013  Florian octo Forster
+ * Copyright (C) 2008       Sebastian tokkee Harl
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
+ **/
+
+#ifndef UTILS_COMPLAIN_H
+#define UTILS_COMPLAIN_H 1
+
+#include "utils_time.h"
+
+typedef struct
+{
+       /* time of the last report */
+       cdtime_t last;
+
+       /* How long to wait until reporting again.
+        * 0 indicates that the complaint is no longer valid. */
+       cdtime_t interval;
+
+       _Bool complained_once;
+} c_complain_t;
+
+#define C_COMPLAIN_INIT_STATIC { 0, 0, 0 }
+#define C_COMPLAIN_INIT(c) do { \
+       (c)->last = 0; \
+       (c)->interval = 0; \
+       (c)->complained_once = 0; \
+} while (0)
+
+/*
+ * NAME
+ *   c_complain
+ *
+ * DESCRIPTION
+ *   Complain about something. This function will report a message (usually
+ *   indicating some error condition) using the collectd logging mechanism.
+ *   When this function is called again, reporting the message again will be
+ *   deferred by an increasing interval (up to one day) to prevent flooding
+ *   the logs. A call to `c_release' resets the counter.
+ *
+ * PARAMETERS
+ *   `level'  The log level passed to `plugin_log'.
+ *   `c'      Identifier for the complaint.
+ *   `format' Message format - see the documentation of printf(3).
+ */
+void c_complain (int level, c_complain_t *c, const char *format, ...);
+
+/*
+ * NAME
+ *   c_complain_once
+ *
+ * DESCRIPTION
+ *   Complain about something once. This function will not report anything
+ *   again, unless `c_release' has been called in between. If used after some
+ *   calls to `c_complain', it will report again on the next interval and stop
+ *   after that.
+ *
+ *   See `c_complain' for further details and a description of the parameters.
+ */
+void c_complain_once (int level, c_complain_t *c, const char *format, ...);
+
+/*
+ * NAME
+ *   c_would_release
+ *
+ * DESCRIPTION
+ *   Returns true if the specified complaint would be released, false else.
+ */
+#define c_would_release(c) ((c)->interval != 0)
+
+/*
+ * NAME
+ *   c_release
+ *
+ * DESCRIPTION
+ *   Release a complaint. This will report a message once, marking the
+ *   complaint as released.
+ *
+ *   See `c_complain' for a description of the parameters.
+ */
+void c_do_release (int level, c_complain_t *c, const char *format, ...);
+#define c_release(level, c, ...) \
+       do { \
+               if (c_would_release (c)) \
+                       c_do_release(level, c, __VA_ARGS__); \
+       } while (0)
+
+#endif /* UTILS_COMPLAIN_H */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/daemon/utils_heap.c b/src/daemon/utils_heap.c
new file mode 100644 (file)
index 0000000..1b5dca7
--- /dev/null
@@ -0,0 +1,230 @@
+/**
+ * collectd - src/utils_heap.c
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <pthread.h>
+
+#include "utils_heap.h"
+
+struct c_heap_s
+{
+  pthread_mutex_t lock;
+  int (*compare) (const void *, const void *);
+
+  void **list;
+  size_t list_len; /* # entries used */
+  size_t list_size; /* # entries allocated */
+};
+
+enum reheap_direction
+{
+  DIR_UP,
+  DIR_DOWN
+};
+
+static void reheap (c_heap_t *h, size_t root, enum reheap_direction dir)
+{
+  size_t left;
+  size_t right;
+  size_t min;
+  int status;
+
+  /* Calculate the positions of the children */
+  left = (2 * root) + 1;
+  if (left >= h->list_len)
+    left = 0;
+
+  right = (2 * root) + 2;
+  if (right >= h->list_len)
+    right = 0;
+
+  /* Check which one of the children is smaller. */
+  if ((left == 0) && (right == 0))
+    return;
+  else if (left == 0)
+    min = right;
+  else if (right == 0)
+    min = left;
+  else
+  {
+    status = h->compare (h->list[left], h->list[right]);
+    if (status > 0)
+      min = right;
+    else
+      min = left;
+  }
+
+  status = h->compare (h->list[root], h->list[min]);
+  if (status <= 0)
+  {
+    /* We didn't need to change anything, so the rest of the tree should be
+     * okay now. */
+    return;
+  }
+  else /* if (status > 0) */
+  {
+    void *tmp;
+
+    tmp = h->list[root];
+    h->list[root] = h->list[min];
+    h->list[min] = tmp;
+  }
+
+  if ((dir == DIR_UP) && (root == 0))
+    return;
+
+  if (dir == DIR_UP)
+    reheap (h, (root - 1) / 2, dir);
+  else if (dir == DIR_DOWN)
+    reheap (h, min, dir);
+} /* void reheap */
+
+c_heap_t *c_heap_create (int (*compare) (const void *, const void *))
+{
+  c_heap_t *h;
+
+  if (compare == NULL)
+    return (NULL);
+
+  h = malloc (sizeof (*h));
+  if (h == NULL)
+    return (NULL);
+
+  memset (h, 0, sizeof (*h));
+  pthread_mutex_init (&h->lock, /* attr = */ NULL);
+  h->compare = compare;
+  
+  h->list = NULL;
+  h->list_len = 0;
+  h->list_size = 0;
+
+  return (h);
+} /* c_heap_t *c_heap_create */
+
+void c_heap_destroy (c_heap_t *h)
+{
+  if (h == NULL)
+    return;
+
+  h->list_len = 0;
+  h->list_size = 0;
+  free (h->list);
+  h->list = NULL;
+
+  pthread_mutex_destroy (&h->lock);
+
+  free (h);
+} /* void c_heap_destroy */
+
+int c_heap_insert (c_heap_t *h, void *ptr)
+{
+  size_t index;
+
+  if ((h == NULL) || (ptr == NULL))
+    return (-EINVAL);
+
+  pthread_mutex_lock (&h->lock);
+
+  assert (h->list_len <= h->list_size);
+  if (h->list_len == h->list_size)
+  {
+    void **tmp;
+
+    tmp = realloc (h->list, (h->list_size + 16) * sizeof (*h->list));
+    if (tmp == NULL)
+    {
+      pthread_mutex_unlock (&h->lock);
+      return (-ENOMEM);
+    }
+
+    h->list = tmp;
+    h->list_size += 16;
+  }
+
+  /* Insert the new node as a leaf. */
+  index = h->list_len;
+  h->list[index] = ptr;
+  h->list_len++;
+
+  /* Reorganize the heap from bottom up. */
+  reheap (h, /* parent of this node = */ (index - 1) / 2, DIR_UP);
+  
+  pthread_mutex_unlock (&h->lock);
+  return (0);
+} /* int c_heap_insert */
+
+void *c_heap_get_root (c_heap_t *h)
+{
+  void *ret = NULL;
+
+  if (h == NULL)
+    return (NULL);
+
+  pthread_mutex_lock (&h->lock);
+
+  if (h->list_len == 0)
+  {
+    pthread_mutex_unlock (&h->lock);
+    return (NULL);
+  }
+  else if (h->list_len == 1)
+  {
+    ret = h->list[0];
+    h->list[0] = NULL;
+    h->list_len = 0;
+  }
+  else /* if (h->list_len > 1) */
+  {
+    ret = h->list[0];
+    h->list[0] = h->list[h->list_len - 1];
+    h->list[h->list_len - 1] = NULL;
+    h->list_len--;
+
+    reheap (h, /* root = */ 0, DIR_DOWN);
+  }
+
+  /* free some memory */
+  if ((h->list_len + 32) < h->list_size)
+  {
+    void **tmp;
+
+    tmp = realloc (h->list, (h->list_len + 16) * sizeof (*h->list));
+    if (tmp != NULL)
+    {
+      h->list = tmp;
+      h->list_size = h->list_len + 16;
+    }
+  }
+
+  pthread_mutex_unlock (&h->lock);
+
+  return (ret);
+} /* void *c_heap_get_root */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/daemon/utils_heap.h b/src/daemon/utils_heap.h
new file mode 100644 (file)
index 0000000..6d71c43
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+ * collectd - src/utils_heap.h
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_HEAP_H
+#define UTILS_HEAP_H 1
+
+struct c_heap_s;
+typedef struct c_heap_s c_heap_t;
+
+/*
+ * NAME
+ *   c_heap_create
+ *
+ * DESCRIPTION
+ *   Allocates a new heap.
+ *
+ * PARAMETERS
+ *   `compare'  The function-pointer `compare' is used to compare two keys. It
+ *              has to return less than zero if it's first argument is smaller
+ *              then the second argument, more than zero if the first argument
+ *              is bigger than the second argument and zero if they are equal.
+ *              If your keys are char-pointers, you can use the `strcmp'
+ *              function from the libc here.
+ *
+ * RETURN VALUE
+ *   A c_heap_t-pointer upon success or NULL upon failure.
+ */
+c_heap_t *c_heap_create (int (*compare) (const void *, const void *));
+
+/*
+ * NAME
+ *   c_heap_destroy
+ *
+ * DESCRIPTION
+ *   Deallocates a heap. Stored value- and key-pointer are lost, but of course
+ *   not freed.
+ */
+void c_heap_destroy (c_heap_t *h);
+
+/*
+ * NAME
+ *   c_heap_insert
+ *
+ * DESCRIPTION
+ *   Stores the key-value-pair in the heap pointed to by `h'.
+ *
+ * PARAMETERS
+ *   `h'        Heap to store the data in.
+ *   `ptr'      Value to be stored. This is typically a pointer to a data
+ *              structure. The data structure is of course *not* copied and may
+ *              not be free'd before the pointer has been removed from the heap
+ *              again.
+ *
+ * RETURN VALUE
+ *   Zero upon success, non-zero otherwise. It's less than zero if an error
+ *   occurred or greater than zero if the key is already stored in the tree.
+ */
+int c_heap_insert (c_heap_t *h, void *ptr);
+
+/*
+ * NAME
+ *   c_heap_get_root
+ *
+ * DESCRIPTION
+ *   Removes the value at the root of the heap and returns both, key and value.
+ *
+ * PARAMETERS
+ *   `h'           Heap to remove key-value-pair from.
+ *
+ * RETURN VALUE
+ *   The pointer passed to `c_heap_insert' or NULL if there are no more
+ *   elements in the heap (or an error occurred).
+ */
+void *c_heap_get_root (c_heap_t *h);
+
+#endif /* UTILS_HEAP_H */
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/utils_heap_test.c b/src/daemon/utils_heap_test.c
new file mode 100644 (file)
index 0000000..53d0fba
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ * collectd - src/tests/test_utils_heap.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "testing.h"
+#include "collectd.h"
+#include "utils_heap.h"
+
+static int compare (void const *v0, void const *v1)
+{
+  int const *i0 = v0;
+  int const *i1 = v1;
+
+  if ((*i0) < (*i1))
+    return -1;
+  else if ((*i0) > (*i1))
+    return 1;
+  else
+    return 0;
+}
+
+DEF_TEST(simple)
+{
+  int values[] = { 9, 5, 6, 1, 3, 4, 0, 8, 2, 7 };
+  int i;
+  c_heap_t *h;
+
+  CHECK_NOT_NULL(h = c_heap_create (compare));
+  for (i = 0; i < 10; i++)
+    CHECK_ZERO(c_heap_insert (h, &values[i]));
+
+  for (i = 0; i < 5; i++)
+  {
+    int *ret = NULL;
+    CHECK_NOT_NULL(ret = c_heap_get_root(h));
+    OK(*ret == i);
+  }
+
+  CHECK_ZERO(c_heap_insert (h, &values[6] /* = 0 */));
+  CHECK_ZERO(c_heap_insert (h, &values[3] /* = 1 */));
+  CHECK_ZERO(c_heap_insert (h, &values[8] /* = 2 */));
+  CHECK_ZERO(c_heap_insert (h, &values[4] /* = 3 */));
+  CHECK_ZERO(c_heap_insert (h, &values[5] /* = 4 */));
+
+  for (i = 0; i < 10; i++)
+  {
+    int *ret = NULL;
+    CHECK_NOT_NULL(ret = c_heap_get_root(h));
+    OK(*ret == i);
+  }
+
+  c_heap_destroy(h);
+  return (0);
+}
+
+int main (void)
+{
+  RUN_TEST(simple);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/utils_llist.c b/src/daemon/utils_llist.c
new file mode 100644 (file)
index 0000000..09c9834
--- /dev/null
@@ -0,0 +1,190 @@
+/**
+ * collectd - src/utils_llist.c
+ * Copyright (C) 2006       Florian Forster <octo at collectd.org>
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils_llist.h"
+
+/*
+ * Private data types
+ */
+struct llist_s
+{
+       llentry_t *head;
+       llentry_t *tail;
+       int size;
+};
+
+/*
+ * Public functions
+ */
+llist_t *llist_create (void)
+{
+       llist_t *ret;
+
+       ret = (llist_t *) malloc (sizeof (llist_t));
+       if (ret == NULL)
+               return (NULL);
+
+       memset (ret, '\0', sizeof (llist_t));
+
+       return (ret);
+}
+
+void llist_destroy (llist_t *l)
+{
+       llentry_t *e_this;
+       llentry_t *e_next;
+
+       if (l == NULL)
+               return;
+
+       for (e_this = l->head; e_this != NULL; e_this = e_next)
+       {
+               e_next = e_this->next;
+               llentry_destroy (e_this);
+       }
+
+       free (l);
+}
+
+llentry_t *llentry_create (char *key, void *value)
+{
+       llentry_t *e;
+
+       e = (llentry_t *) malloc (sizeof (llentry_t));
+       if (e)
+       {
+               e->key   = key;
+               e->value = value;
+               e->next  = NULL;
+       }
+
+       return (e);
+}
+
+void llentry_destroy (llentry_t *e)
+{
+       free (e);
+}
+
+void llist_append (llist_t *l, llentry_t *e)
+{
+       e->next = NULL;
+
+       if (l->tail == NULL)
+               l->head = e;
+       else
+               l->tail->next = e;
+
+       l->tail = e;
+
+       ++(l->size);
+}
+
+void llist_prepend (llist_t *l, llentry_t *e)
+{
+       e->next = l->head;
+       l->head = e;
+
+       if (l->tail == NULL)
+               l->tail = e;
+
+       ++(l->size);
+}
+
+void llist_remove (llist_t *l, llentry_t *e)
+{
+       llentry_t *prev;
+
+       prev = l->head;
+       while ((prev != NULL) && (prev->next != e))
+               prev = prev->next;
+
+       if (prev != NULL)
+               prev->next = e->next;
+       if (l->head == e)
+               l->head = e->next;
+       if (l->tail == e)
+               l->tail = prev;
+
+       --(l->size);
+}
+
+int llist_size (llist_t *l)
+{
+       return (l ? l->size : 0);
+}
+
+static int llist_strcmp (llentry_t *e, void *ud)
+{
+       if ((e == NULL) || (ud == NULL))
+               return (-1);
+       return (strcmp (e->key, (const char *)ud));
+}
+
+llentry_t *llist_search (llist_t *l, const char *key)
+{
+       return (llist_search_custom (l, llist_strcmp, (void *)key));
+}
+
+llentry_t *llist_search_custom (llist_t *l,
+               int (*compare) (llentry_t *, void *), void *user_data)
+{
+       llentry_t *e;
+
+       if (l == NULL)
+               return (NULL);
+
+       e = l->head;
+       while (e != NULL) {
+               llentry_t *next = e->next;
+
+               if (compare (e, user_data) == 0)
+                       break;
+
+               e = next;
+       }
+
+       return (e);
+}
+
+llentry_t *llist_head (llist_t *l)
+{
+       if (l == NULL)
+               return (NULL);
+       return (l->head);
+}
+
+llentry_t *llist_tail (llist_t *l)
+{
+       if (l == NULL)
+               return (NULL);
+       return (l->tail);
+}
diff --git a/src/daemon/utils_llist.h b/src/daemon/utils_llist.h
new file mode 100644 (file)
index 0000000..59bf2e4
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * collectd - src/utils_llist.h
+ * Copyright (C) 2006       Florian Forster <octo at collectd.org>
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ */
+
+#ifndef UTILS_LLIST_H
+#define UTILS_LLIST_H 1
+
+/*
+ * Data types
+ */
+struct llentry_s
+{
+       char *key;
+       void *value;
+       struct llentry_s *next;
+};
+typedef struct llentry_s llentry_t;
+
+struct llist_s;
+typedef struct llist_s llist_t;
+
+/*
+ * Functions
+ */
+llist_t *llist_create (void);
+void llist_destroy (llist_t *l);
+
+llentry_t *llentry_create (char *key, void *value);
+void llentry_destroy (llentry_t *e);
+
+void llist_append (llist_t *l, llentry_t *e);
+void llist_prepend (llist_t *l, llentry_t *e);
+void llist_remove (llist_t *l, llentry_t *e);
+
+int llist_size (llist_t *l);
+
+llentry_t *llist_search (llist_t *l, const char *key);
+llentry_t *llist_search_custom (llist_t *l,
+               int (*compare) (llentry_t *, void *), void *user_data);
+
+llentry_t *llist_head (llist_t *l);
+llentry_t *llist_tail (llist_t *l);
+
+#endif /* UTILS_LLIST_H */
diff --git a/src/daemon/utils_match.c b/src/daemon/utils_match.c
new file mode 100644 (file)
index 0000000..5083b05
--- /dev/null
@@ -0,0 +1,396 @@
+/**
+ * collectd - src/utils_match.c
+ * Copyright (C) 2008-2014  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_match.h"
+
+#include <regex.h>
+
+#define UTILS_MATCH_FLAGS_FREE_USER_DATA 0x01
+#define UTILS_MATCH_FLAGS_EXCLUDE_REGEX 0x02
+
+struct cu_match_s
+{
+  regex_t regex;
+  regex_t excluderegex;
+  int flags;
+
+  int (*callback) (const char *str, char * const *matches, size_t matches_num,
+      void *user_data);
+  void *user_data;
+};
+
+/*
+ * Private functions
+ */
+static char *match_substr (const char *str, int begin, int end)
+{
+  char *ret;
+  size_t ret_len;
+
+  if ((begin < 0) || (end < 0) || (begin >= end))
+    return (NULL);
+  if ((size_t) end > (strlen (str) + 1))
+  {
+    ERROR ("utils_match: match_substr: `end' points after end of string.");
+    return (NULL);
+  }
+
+  ret_len = end - begin;
+  ret = (char *) malloc (sizeof (char) * (ret_len + 1));
+  if (ret == NULL)
+  {
+    ERROR ("utils_match: match_substr: malloc failed.");
+    return (NULL);
+  }
+
+  sstrncpy (ret, str + begin, ret_len + 1);
+  return (ret);
+} /* char *match_substr */
+
+static int default_callback (const char __attribute__((unused)) *str,
+    char * const *matches, size_t matches_num, void *user_data)
+{
+  cu_match_value_t *data = (cu_match_value_t *) user_data;
+
+  if (data->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
+  {
+    gauge_t value;
+    char *endptr = NULL;
+
+    if (data->ds_type & UTILS_MATCH_CF_GAUGE_INC)
+    {
+      data->value.gauge = isnan (data->value.gauge) ? 1 : data->value.gauge + 1;
+      data->values_num++;
+      return(0);
+    }
+
+    if (matches_num < 2)
+      return (-1);
+
+    value = (gauge_t) strtod (matches[1], &endptr);
+    if (matches[1] == endptr)
+      return (-1);
+
+    if ((data->values_num == 0)
+       || (data->ds_type & UTILS_MATCH_CF_GAUGE_LAST))
+    {
+      data->value.gauge = value;
+    }
+    else if (data->ds_type & UTILS_MATCH_CF_GAUGE_AVERAGE)
+    {
+      double f = ((double) data->values_num)
+       / ((double) (data->values_num + 1));
+      data->value.gauge = (data->value.gauge * f) + (value * (1.0 - f));
+    }
+    else if (data->ds_type & UTILS_MATCH_CF_GAUGE_MIN)
+    {
+      if (data->value.gauge > value)
+       data->value.gauge = value;
+    }
+    else if (data->ds_type & UTILS_MATCH_CF_GAUGE_MAX)
+    {
+      if (data->value.gauge < value)
+       data->value.gauge = value;
+    }
+    else if (data->ds_type & UTILS_MATCH_CF_GAUGE_ADD)
+    {
+      data->value.gauge += value;
+    }
+    else
+    {
+      ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+      return (-1);
+    }
+
+    data->values_num++;
+  }
+  else if (data->ds_type & UTILS_MATCH_DS_TYPE_COUNTER)
+  {
+    counter_t value;
+    char *endptr = NULL;
+
+    if (data->ds_type & UTILS_MATCH_CF_COUNTER_INC)
+    {
+      data->value.counter++;
+      data->values_num++;
+      return (0);
+    }
+
+    if (matches_num < 2)
+      return (-1);
+
+    value = (counter_t) strtoull (matches[1], &endptr, 0);
+    if (matches[1] == endptr)
+      return (-1);
+
+    if (data->ds_type & UTILS_MATCH_CF_COUNTER_SET)
+      data->value.counter = value;
+    else if (data->ds_type & UTILS_MATCH_CF_COUNTER_ADD)
+      data->value.counter += value;
+    else
+    {
+      ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+      return (-1);
+    }
+
+    data->values_num++;
+  }
+  else if (data->ds_type & UTILS_MATCH_DS_TYPE_DERIVE)
+  {
+    derive_t value;
+    char *endptr = NULL;
+
+    if (data->ds_type & UTILS_MATCH_CF_DERIVE_INC)
+    {
+      data->value.counter++;
+      data->values_num++;
+      return (0);
+    }
+
+    if (matches_num < 2)
+      return (-1);
+
+    value = (derive_t) strtoll (matches[1], &endptr, 0);
+    if (matches[1] == endptr)
+      return (-1);
+
+    if (data->ds_type & UTILS_MATCH_CF_DERIVE_SET)
+      data->value.derive = value;
+    else if (data->ds_type & UTILS_MATCH_CF_DERIVE_ADD)
+      data->value.derive += value;
+    else
+    {
+      ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+      return (-1);
+    }
+
+    data->values_num++;
+  }
+  else if (data->ds_type & UTILS_MATCH_DS_TYPE_ABSOLUTE)
+  {
+    absolute_t value;
+    char *endptr = NULL;
+
+    if (matches_num < 2)
+      return (-1);
+
+    value = (absolute_t) strtoull (matches[1], &endptr, 0);
+    if (matches[1] == endptr)
+      return (-1);
+
+    if (data->ds_type & UTILS_MATCH_CF_ABSOLUTE_SET)
+      data->value.absolute = value;
+    else
+    {
+      ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+      return (-1);
+    }
+
+    data->values_num++;
+  }
+  else
+  {
+    ERROR ("utils_match: default_callback: obj->ds_type is invalid!");
+    return (-1);
+  }
+
+  return (0);
+} /* int default_callback */
+
+/*
+ * Public functions
+ */
+cu_match_t *match_create_callback (const char *regex, const char *excluderegex,
+               int (*callback) (const char *str,
+                 char * const *matches, size_t matches_num, void *user_data),
+               void *user_data)
+{
+  cu_match_t *obj;
+  int status;
+
+  DEBUG ("utils_match: match_create_callback: regex = %s, excluderegex = %s",
+        regex, excluderegex);
+
+  obj = (cu_match_t *) malloc (sizeof (cu_match_t));
+  if (obj == NULL)
+    return (NULL);
+  memset (obj, '\0', sizeof (cu_match_t));
+
+  status = regcomp (&obj->regex, regex, REG_EXTENDED | REG_NEWLINE);
+  if (status != 0)
+  {
+    ERROR ("Compiling the regular expression \"%s\" failed.", regex);
+    sfree (obj);
+    return (NULL);
+  }
+
+  if (excluderegex && strcmp(excluderegex, "") != 0) {
+    status = regcomp (&obj->excluderegex, excluderegex, REG_EXTENDED);
+    if (status != 0)
+    {
+       ERROR ("Compiling the excluding regular expression \"%s\" failed.",
+              excluderegex);
+       sfree (obj);
+       return (NULL);
+    }
+    obj->flags |= UTILS_MATCH_FLAGS_EXCLUDE_REGEX;
+  }
+
+  obj->callback = callback;
+  obj->user_data = user_data;
+
+  return (obj);
+} /* cu_match_t *match_create_callback */
+
+cu_match_t *match_create_simple (const char *regex,
+                                const char *excluderegex, int match_ds_type)
+{
+  cu_match_value_t *user_data;
+  cu_match_t *obj;
+
+  user_data = (cu_match_value_t *) malloc (sizeof (cu_match_value_t));
+  if (user_data == NULL)
+    return (NULL);
+  memset (user_data, '\0', sizeof (cu_match_value_t));
+  user_data->ds_type = match_ds_type;
+
+  obj = match_create_callback (regex, excluderegex,
+                              default_callback, user_data);
+  if (obj == NULL)
+  {
+    sfree (user_data);
+    return (NULL);
+  }
+
+  obj->flags |= UTILS_MATCH_FLAGS_FREE_USER_DATA;
+
+  return (obj);
+} /* cu_match_t *match_create_simple */
+
+void match_value_reset (cu_match_value_t *mv)
+{
+  if (mv == NULL)
+    return;
+
+  if (mv->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
+  {
+    mv->value.gauge = NAN;
+    mv->values_num = 0;
+  }
+} /* }}} void match_value_reset */
+
+void match_destroy (cu_match_t *obj)
+{
+  if (obj == NULL)
+    return;
+
+  if (obj->flags & UTILS_MATCH_FLAGS_FREE_USER_DATA)
+  {
+    sfree (obj->user_data);
+  }
+
+  sfree (obj);
+} /* void match_destroy */
+
+int match_apply (cu_match_t *obj, const char *str)
+{
+  int status;
+  regmatch_t re_match[32];
+  char *matches[32];
+  size_t matches_num;
+  size_t i;
+
+  if ((obj == NULL) || (str == NULL))
+    return (-1);
+
+  if (obj->flags & UTILS_MATCH_FLAGS_EXCLUDE_REGEX) {
+    status = regexec (&obj->excluderegex, str,
+                     STATIC_ARRAY_SIZE (re_match), re_match,
+                     /* eflags = */ 0);
+    /* Regex did match, so exclude this line */
+    if (status == 0) {
+      DEBUG("ExludeRegex matched, don't count that line\n");
+      return (0);
+    }
+  }
+
+  status = regexec (&obj->regex, str,
+      STATIC_ARRAY_SIZE (re_match), re_match,
+      /* eflags = */ 0);
+
+  /* Regex did not match */
+  if (status != 0)
+    return (0);
+
+  memset (matches, '\0', sizeof (matches));
+  for (matches_num = 0; matches_num < STATIC_ARRAY_SIZE (matches); matches_num++)
+  {
+    if ((re_match[matches_num].rm_so < 0)
+       || (re_match[matches_num].rm_eo < 0))
+      break;
+
+    matches[matches_num] = match_substr (str,
+       re_match[matches_num].rm_so, re_match[matches_num].rm_eo);
+    if (matches[matches_num] == NULL)
+    {
+      status = -1;
+      break;
+    }
+  }
+
+  if (status != 0)
+  {
+    ERROR ("utils_match: match_apply: match_substr failed.");
+  }
+  else
+  {
+    status = obj->callback (str, matches, matches_num, obj->user_data);
+    if (status != 0)
+    {
+      ERROR ("utils_match: match_apply: callback failed.");
+    }
+  }
+
+  for (i = 0; i < matches_num; i++)
+  {
+    sfree (matches[i]);
+  }
+
+  return (status);
+} /* int match_apply */
+
+void *match_get_user_data (cu_match_t *obj)
+{
+  if (obj == NULL)
+    return (NULL);
+  return (obj->user_data);
+} /* void *match_get_user_data */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/daemon/utils_match.h b/src/daemon/utils_match.h
new file mode 100644 (file)
index 0000000..a1d1002
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+ * collectd - src/utils_match.h
+ * Copyright (C) 2008-2014  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_MATCH_H
+#define UTILS_MATCH_H 1
+
+#include "plugin.h"
+
+/*
+ * Each type may have 12 sub-types
+ * 0x1000 = 1000000000000
+ *          ^             <- Type bit
+ *           ^^^^^^^^^^^^ <- Subtype bits
+ */
+#define UTILS_MATCH_DS_TYPE_GAUGE    0x1000
+#define UTILS_MATCH_DS_TYPE_COUNTER  0x2000
+#define UTILS_MATCH_DS_TYPE_DERIVE   0x4000
+#define UTILS_MATCH_DS_TYPE_ABSOLUTE 0x8000
+
+#define UTILS_MATCH_CF_GAUGE_AVERAGE 0x01
+#define UTILS_MATCH_CF_GAUGE_MIN     0x02
+#define UTILS_MATCH_CF_GAUGE_MAX     0x04
+#define UTILS_MATCH_CF_GAUGE_LAST    0x08
+#define UTILS_MATCH_CF_GAUGE_INC     0x10
+#define UTILS_MATCH_CF_GAUGE_ADD     0x20
+
+#define UTILS_MATCH_CF_COUNTER_SET   0x01
+#define UTILS_MATCH_CF_COUNTER_ADD   0x02
+#define UTILS_MATCH_CF_COUNTER_INC   0x04
+
+#define UTILS_MATCH_CF_DERIVE_SET   0x01
+#define UTILS_MATCH_CF_DERIVE_ADD   0x02
+#define UTILS_MATCH_CF_DERIVE_INC   0x04
+
+#define UTILS_MATCH_CF_ABSOLUTE_SET   0x01
+#define UTILS_MATCH_CF_ABSOLUTE_ADD   0x02
+#define UTILS_MATCH_CF_ABSOLUTE_INC   0x04
+
+/*
+ * Data types
+ */
+struct cu_match_s;
+typedef struct cu_match_s cu_match_t;
+
+struct cu_match_value_s
+{
+  int ds_type;
+  value_t value;
+  unsigned int values_num;
+};
+typedef struct cu_match_value_s cu_match_value_t;
+
+/*
+ * Prototypes
+ */
+/*
+ * NAME
+ *  match_create_callback
+ *
+ * DESCRIPTION
+ *  Creates a new `cu_match_t' object which will use the regular expression
+ *  `regex' to match lines, see the `match_apply' method below. If the line
+ *  matches, the callback passed in `callback' will be called along with the
+ *  pointer `user_pointer'.
+ *  The string that's passed to the callback depends on the regular expression:
+ *  If the regular expression includes a sub-match, i. e. something like
+ *    "value=([0-9][0-9]*)"
+ *  then only the submatch (the part in the parenthesis) will be passed to the
+ *  callback. If there is no submatch, then the entire string is passed to the
+ *  callback.
+ *  The optional `excluderegex' allows to exclude the line from the match, if
+ *  the excluderegex matches.
+ */
+cu_match_t *match_create_callback (const char *regex, const char *excluderegex,
+               int (*callback) (const char *str,
+                 char * const *matches, size_t matches_num, void *user_data),
+               void *user_data);
+
+/*
+ * NAME
+ *  match_create_simple
+ *
+ * DESCRIPTION
+ *  Creates a new `cu_match_t' with a default callback. The user data for that
+ *  default callback will be a `cu_match_value_t' structure, with
+ *  `ds_type' copied to the structure. The default callback will handle the
+ *  string as containing a number (see strtoll(3) and strtod(3)) and store that
+ *  number in the `value' member. How that is done depends on `ds_type':
+ *
+ *  UTILS_MATCH_DS_TYPE_GAUGE
+ *    The function will search for a floating point number in the string and
+ *    store it in value.gauge.
+ *  UTILS_MATCH_DS_TYPE_COUNTER_SET
+ *    The function will search for an integer in the string and store it in
+ *    value.counter.
+ *  UTILS_MATCH_DS_TYPE_COUNTER_ADD
+ *    The function will search for an integer in the string and add it to the
+ *    value in value.counter.
+ *  UTILS_MATCH_DS_TYPE_COUNTER_INC
+ *    The function will not search for anything in the string and increase
+ *    value.counter by one.
+ */
+cu_match_t *match_create_simple (const char *regex,
+                                const char *excluderegex, int ds_type);
+
+/*
+ * NAME
+ *  match_value_reset
+ *
+ * DESCRIPTION
+ *   Resets the internal state, if applicable. This function must be called
+ *   after each iteration for "simple" matches, usually after dispatching the
+ *   metrics.
+ */
+void match_value_reset (cu_match_value_t *mv);
+
+/*
+ * NAME
+ *  match_destroy
+ *
+ * DESCRIPTION
+ *  Destroys the object and frees all internal resources.
+ */
+void match_destroy (cu_match_t *obj);
+
+/*
+ * NAME
+ *  match_apply
+ *
+ * DESCRIPTION
+ *  Tries to match the string `str' with the regular expression of `obj'. If
+ *  the string matches, calls the callback in `obj' with the (sub-)match.
+ *
+ *  The user_data pointer passed to `match_create_callback' is NOT freed
+ *  automatically. The `cu_match_value_t' structure allocated by
+ *  `match_create_callback' is freed automatically.
+ */
+int match_apply (cu_match_t *obj, const char *str);
+
+/*
+ * NAME
+ *  match_get_user_data
+ *
+ * DESCRIPTION
+ *  Returns the pointer passed to `match_create_callback' or a pointer to the
+ *  `cu_match_value_t' structure allocated by `match_create_simple'.
+ */
+void *match_get_user_data (cu_match_t *obj);
+
+#endif /* UTILS_MATCH_H */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/daemon/utils_random.c b/src/daemon/utils_random.c
new file mode 100644 (file)
index 0000000..b873845
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * collectd - src/utils_random.c
+ * Copyright (C) 2013       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "utils_time.h"
+
+#include <pthread.h>
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static _Bool have_seed = 0;
+static unsigned short seed[3];
+
+static void cdrand_seed (void)
+{
+  cdtime_t t;
+
+  if (have_seed)
+    return;
+
+  t = cdtime();
+
+  seed[0] = (unsigned short) t;
+  seed[1] = (unsigned short) (t >> 16);
+  seed[2] = (unsigned short) (t >> 32);
+
+  have_seed = 1;
+}
+
+double cdrand_d (void)
+{
+  double r;
+
+  pthread_mutex_lock (&lock);
+  cdrand_seed ();
+  r = erand48 (seed);
+  pthread_mutex_unlock (&lock);
+
+  return (r);
+}
+
+long cdrand_range (long min, long max)
+{
+  long range;
+  long r;
+
+  range = 1 + max - min;
+
+  r = (long) (0.5 + (cdrand_d () * range));
+  r += min;
+
+  return (r);
+}
diff --git a/src/daemon/utils_random.h b/src/daemon/utils_random.h
new file mode 100644 (file)
index 0000000..b05f4c8
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * collectd - src/utils_random.h
+ * Copyright (C) 2013       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+/**
+ * Returns a random double value in the range [0..1), i.e. excluding 1.
+ *
+ * This function is thread- and reentrant-safe.
+ */
+double cdrand_d (void);
+
+/**
+ * Returns a random long between min and max, inclusively.
+ *
+ * If min is larger than max, the result may be rounded incorrectly and may be
+ * outside the intended range. This function is thread- and reentrant-safe.
+ */
+long cdrand_range (long min, long max);
diff --git a/src/daemon/utils_subst.c b/src/daemon/utils_subst.c
new file mode 100644 (file)
index 0000000..2f28eb9
--- /dev/null
@@ -0,0 +1,149 @@
+/**
+ * collectd - src/utils_subst.c
+ * Copyright (C) 2008       Sebastian Harl
+ *
+ * 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:
+ *   Sebastian "tokkee" Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This module provides functions for string substitution.
+ */
+
+#include "collectd.h"
+#include "common.h"
+
+char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+               const char *replacement)
+{
+       char  *buf_ptr = buf;
+       size_t len     = buflen;
+
+       if ((NULL == buf) || (0 >= buflen) || (NULL == string)
+                       || (0 > off1) || (0 > off2) || (off1 > off2)
+                       || (NULL == replacement))
+               return NULL;
+
+       sstrncpy (buf_ptr, string,
+                       ((size_t)off1 + 1 > buflen) ? buflen : (size_t)off1 + 1);
+       buf_ptr += off1;
+       len     -= off1;
+
+       if (0 >= len)
+               return buf;
+
+       sstrncpy (buf_ptr, replacement, len);
+       buf_ptr += strlen (replacement);
+       len     -= strlen (replacement);
+
+       if (0 >= len)
+               return buf;
+
+       sstrncpy (buf_ptr, string + off2, len);
+       return buf;
+} /* subst */
+
+char *asubst (const char *string, int off1, int off2, const char *replacement)
+{
+       char *buf;
+       int   len;
+
+       char *ret;
+
+       if ((NULL == string) || (0 > off1) || (0 > off2) || (off1 > off2)
+                       || (NULL ==replacement))
+               return NULL;
+
+       len = off1 + strlen (replacement) + strlen (string) - off2 + 1;
+
+       buf = (char *)malloc (len);
+       if (NULL == buf)
+               return NULL;
+
+       ret = subst (buf, len, string, off1, off2, replacement);
+       if (NULL == ret)
+               free (buf);
+       return ret;
+} /* asubst */
+
+char *subst_string (char *buf, size_t buflen, const char *string,
+               const char *needle, const char *replacement)
+{
+       char *temp;
+       size_t needle_len;
+       size_t i;
+
+       if ((buf == NULL) || (string == NULL)
+                       || (needle == NULL) || (replacement == NULL))
+               return (NULL);
+
+       temp = (char *) malloc (buflen);
+       if (temp == NULL)
+       {
+               ERROR ("subst_string: malloc failed.");
+               return (NULL);
+       }
+
+       needle_len = strlen (needle);
+       strncpy (buf, string, buflen);
+
+       /* Limit the loop to prevent endless loops. */
+       for (i = 0; i < buflen; i++)
+       {
+               char *begin_ptr;
+               size_t begin;
+
+               /* Find `needle' in `buf'. */
+               begin_ptr = strstr (buf, needle);
+               if (begin_ptr == NULL)
+                       break;
+
+               /* Calculate the start offset. */
+               begin = begin_ptr - buf;
+
+               /* Substitute the region using `subst'. The result is stored in
+                * `temp'. */
+               begin_ptr = subst (temp, buflen, buf,
+                               begin, begin + needle_len,
+                               replacement);
+               if (begin_ptr == NULL)
+               {
+                       WARNING ("subst_string: subst failed.");
+                       break;
+               }
+
+               /* Copy the new string in `temp' to `buf' for the next round. */
+               strncpy (buf, temp, buflen);
+       }
+
+       if (i >= buflen)
+       {
+               WARNING ("subst_string: Loop exited after %zu iterations: "
+                               "string = %s; needle = %s; replacement = %s;",
+                               i, string, needle, replacement);
+       }
+
+       sfree (temp);
+       return (buf);
+} /* char *subst_string */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/daemon/utils_subst.h b/src/daemon/utils_subst.h
new file mode 100644 (file)
index 0000000..9085286
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * collectd - src/utils_subst.h
+ * Copyright (C) 2008       Sebastian Harl
+ *
+ * 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:
+ *   Sebastian "tokkee" Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This module provides functions for string substitution.
+ */
+
+#ifndef UTILS_SUBST_H
+#define UTILS_SUBST_H 1
+
+#include <stddef.h>
+
+/*
+ * subst:
+ *
+ * Replace a substring of a string with the specified replacement text. The
+ * resulting string is stored in the buffer pointed to by 'buf' of length
+ * 'buflen'. Upon success, the buffer will always be null-terminated. The
+ * result may be truncated if the buffer is too small.
+ *
+ * The substring to be replaces is identified by the two offsets 'off1' and
+ * 'off2' where 'off1' specifies the offset to the beginning of the substring
+ * and 'off2' specifies the offset to the first byte after the substring.
+ *
+ * The minimum buffer size to store the complete return value (including the
+ * terminating '\0' character) thus has to be:
+ * off1 + strlen(replacement) + strlen(string) - off2 + 1
+ *
+ * Example:
+ *
+ *             01234567890
+ *   string = "foo_____bar"
+ *                ^    ^
+ *                |    |
+ *              off1  off2
+ *
+ *   off1 = 3
+ *   off2 = 8
+ *
+ *   replacement = " - "
+ *
+ *   -> "foo - bar"
+ *
+ * The function returns 'buf' on success, NULL else.
+ */
+char *subst (char *buf, size_t buflen, const char *string, int off1, int off2,
+               const char *replacement);
+
+/*
+ * asubst:
+ *
+ * This function is very similar to subst(). It differs in that it
+ * automatically allocates the memory required for the return value which the
+ * user then has to free himself.
+ *
+ * Returns the newly allocated result string on success, NULL else.
+ */
+char *asubst (const char *string, int off1, int off2, const char *replacement);
+
+/*
+ * subst_string:
+ *
+ * Works like `subst', but instead of specifying start and end offsets you
+ * specify `needle', the string that is to be replaced. If `needle' is found
+ * in `string' (using strstr(3)), the offset is calculated and `subst' is
+ * called with the determined parameters.
+ *
+ * If the substring is not found, no error will be indicated and
+ * `subst_string' works mostly like `strncpy'.
+ *
+ * If the substring appears multiple times, all appearances will be replaced.
+ * If the substring has been found `buflen' times, an endless loop is assumed
+ * and the loop is broken. A warning is printed and the function returns
+ * success.
+ */
+char *subst_string (char *buf, size_t buflen, const char *string,
+               const char *needle, const char *replacement);
+
+#endif /* UTILS_SUBST_H */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/daemon/utils_tail.c b/src/daemon/utils_tail.c
new file mode 100644 (file)
index 0000000..fe5dca8
--- /dev/null
@@ -0,0 +1,260 @@
+/**
+ * collectd - src/utils_tail.c
+ * Copyright (C) 2007-2008  C-Ware, Inc.
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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.
+ *
+ * Author:
+ *   Luke Heberling <lukeh at c-ware.com>
+ *   Florian Forster <octo at collectd.org>
+ *
+ * Description:
+ *   Encapsulates useful code for plugins which must watch for appends to
+ *   the end of a file.
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_tail.h"
+
+struct cu_tail_s
+{
+       char  *file;
+       FILE  *fh;
+       struct stat stat;
+};
+
+static int cu_tail_reopen (cu_tail_t *obj)
+{
+  int seek_end = 0;
+  FILE *fh;
+  struct stat stat_buf;
+  int status;
+
+  memset (&stat_buf, 0, sizeof (stat_buf));
+  status = stat (obj->file, &stat_buf);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("utils_tail: stat (%s) failed: %s", obj->file,
+       sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  /* The file is already open.. */
+  if ((obj->fh != NULL) && (stat_buf.st_ino == obj->stat.st_ino))
+  {
+    /* Seek to the beginning if file was truncated */
+    if (stat_buf.st_size < obj->stat.st_size)
+    {
+      INFO ("utils_tail: File `%s' was truncated.", obj->file);
+      status = fseek (obj->fh, 0, SEEK_SET);
+      if (status != 0)
+      {
+       char errbuf[1024];
+       ERROR ("utils_tail: fseek (%s) failed: %s", obj->file,
+           sstrerror (errno, errbuf, sizeof (errbuf)));
+       fclose (obj->fh);
+       obj->fh = NULL;
+       return (-1);
+      }
+    }
+    memcpy (&obj->stat, &stat_buf, sizeof (struct stat));
+    return (1);
+  }
+
+  /* Seek to the end if we re-open the same file again or the file opened
+   * is the first at all or the first after an error */
+  if ((obj->stat.st_ino == 0) || (obj->stat.st_ino == stat_buf.st_ino))
+    seek_end = 1;
+
+  fh = fopen (obj->file, "r");
+  if (fh == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("utils_tail: fopen (%s) failed: %s", obj->file,
+       sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  if (seek_end != 0)
+  {
+    status = fseek (fh, 0, SEEK_END);
+    if (status != 0)
+    {
+      char errbuf[1024];
+      ERROR ("utils_tail: fseek (%s) failed: %s", obj->file,
+         sstrerror (errno, errbuf, sizeof (errbuf)));
+      fclose (fh);
+      return (-1);
+    }
+  }
+
+  if (obj->fh != NULL)
+    fclose (obj->fh);
+  obj->fh = fh;
+  memcpy (&obj->stat, &stat_buf, sizeof (struct stat));
+
+  return (0);
+} /* int cu_tail_reopen */
+
+cu_tail_t *cu_tail_create (const char *file)
+{
+       cu_tail_t *obj;
+
+       obj = (cu_tail_t *) malloc (sizeof (cu_tail_t));
+       if (obj == NULL)
+               return (NULL);
+       memset (obj, '\0', sizeof (cu_tail_t));
+
+       obj->file = strdup (file);
+       if (obj->file == NULL)
+       {
+               free (obj);
+               return (NULL);
+       }
+
+       obj->fh = NULL;
+
+       return (obj);
+} /* cu_tail_t *cu_tail_create */
+
+int cu_tail_destroy (cu_tail_t *obj)
+{
+       if (obj->fh != NULL)
+               fclose (obj->fh);
+       free (obj->file);
+       free (obj);
+
+       return (0);
+} /* int cu_tail_destroy */
+
+int cu_tail_readline (cu_tail_t *obj, char *buf, int buflen)
+{
+  int status;
+
+  if (buflen < 1)
+  {
+    ERROR ("utils_tail: cu_tail_readline: buflen too small: %i bytes.",
+       buflen);
+    return (-1);
+  }
+
+  if (obj->fh == NULL)
+  {
+    status = cu_tail_reopen (obj);
+    if (status < 0)
+      return (status);
+  }
+  assert (obj->fh != NULL);
+
+  /* Try to read from the filehandle. If that succeeds, everything appears to
+   * be fine and we can return. */
+  clearerr (obj->fh);
+  if (fgets (buf, buflen, obj->fh) != NULL)
+  {
+    buf[buflen - 1] = 0;
+    return (0);
+  }
+
+  /* Check if we encountered an error */
+  if (ferror (obj->fh) != 0)
+  {
+    /* Jupp, error. Force `cu_tail_reopen' to reopen the file.. */
+    fclose (obj->fh);
+    obj->fh = NULL;
+  }
+  /* else: eof -> check if the file was moved away and reopen the new file if
+   * so.. */
+
+  status = cu_tail_reopen (obj);
+  /* error -> return with error */
+  if (status < 0)
+    return (status);
+  /* file end reached and file not reopened -> nothing more to read */
+  else if (status > 0)
+  {
+    buf[0] = 0;
+    return (0);
+  }
+
+  /* If we get here: file was re-opened and there may be more to read.. Let's
+   * try again. */
+  if (fgets (buf, buflen, obj->fh) != NULL)
+  {
+    buf[buflen - 1] = 0;
+    return (0);
+  }
+
+  if (ferror (obj->fh) != 0)
+  {
+    char errbuf[1024];
+    WARNING ("utils_tail: fgets (%s) returned an error: %s", obj->file,
+       sstrerror (errno, errbuf, sizeof (errbuf)));
+    fclose (obj->fh);
+    obj->fh = NULL;
+    return (-1);
+  }
+
+  /* EOf, well, apparently the new file is empty.. */
+  buf[0] = 0;
+  return (0);
+} /* int cu_tail_readline */
+
+int cu_tail_read (cu_tail_t *obj, char *buf, int buflen, tailfunc_t *callback,
+               void *data)
+{
+       int status;
+
+       while (42)
+       {
+               size_t len;
+
+               status = cu_tail_readline (obj, buf, buflen);
+               if (status != 0)
+               {
+                       ERROR ("utils_tail: cu_tail_read: cu_tail_readline "
+                                       "failed.");
+                       break;
+               }
+
+               /* check for EOF */
+               if (buf[0] == 0)
+                       break;
+
+               len = strlen (buf);
+               while (len > 0) {
+                       if (buf[len - 1] != '\n')
+                               break;
+                       buf[len - 1] = '\0';
+                       len--;
+               }
+
+               status = callback (data, buf, buflen);
+               if (status != 0)
+               {
+                       ERROR ("utils_tail: cu_tail_read: callback returned "
+                                       "status %i.", status);
+                       break;
+               }
+       }
+
+       return status;
+} /* int cu_tail_read */
diff --git a/src/daemon/utils_tail.h b/src/daemon/utils_tail.h
new file mode 100644 (file)
index 0000000..6fb7013
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * collectd - src/utils_tail.h
+ * Copyright (C) 2007-2008  C-Ware, Inc.
+ *
+ * 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.
+ *
+ * Author:
+ *   Luke Heberling <lukeh at c-ware.com>
+ *
+ * DESCRIPTION
+ *   Facilitates reading information that is appended to a file, taking into
+ *   account that the file may be rotated and a new file created under the
+ *   same name.
+ **/
+
+#ifndef UTILS_TAIL_H
+#define UTILS_TAIL_H 1
+
+struct cu_tail_s;
+typedef struct cu_tail_s cu_tail_t;
+
+typedef int tailfunc_t(void *data, char *buf, int buflen);
+
+/*
+ * NAME
+ *   cu_tail_create
+ *
+ * DESCRIPTION
+ *   Allocates a new tail object..
+ *
+ * PARAMETERS
+ *   `file'       The name of the file to be tailed.
+ */
+cu_tail_t *cu_tail_create (const char *file);
+
+/*
+ * cu_tail_destroy
+ *
+ * Takes a tail object returned by `cu_tail_create' and destroys it, freeing
+ * all internal memory.
+ *
+ * Returns 0 when successful and non-zero otherwise.
+ */
+int cu_tail_destroy (cu_tail_t *obj);
+
+/*
+ * cu_tail_readline
+ *
+ * Reads from the file until `buflen' characters are read, a newline
+ * character is read, or an eof condition is encountered. `buf' is
+ * always null-terminated on successful return and isn't touched when non-zero
+ * is returned.
+ *
+ * You can check if the EOF condition is reached by looking at the buffer: If
+ * the length of the string stored in the buffer is zero, EOF occurred.
+ * Otherwise at least the newline character will be in the buffer.
+ *
+ * Returns 0 when successful and non-zero otherwise.
+ */
+int cu_tail_readline (cu_tail_t *obj, char *buf, int buflen);
+
+/*
+ * cu_tail_readline
+ *
+ * Reads from the file until eof condition or an error is encountered.
+ *
+ * Returns 0 when successful and non-zero otherwise.
+ */
+int cu_tail_read (cu_tail_t *obj, char *buf, int buflen, tailfunc_t *callback,
+               void *data);
+
+#endif /* UTILS_TAIL_H */
diff --git a/src/daemon/utils_tail_match.c b/src/daemon/utils_tail_match.c
new file mode 100644 (file)
index 0000000..8776ad1
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * collectd - src/utils_tail_match.c
+ * Copyright (C) 2007-2008  C-Ware, Inc.
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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.
+ *
+ * Author:
+ *   Luke Heberling <lukeh at c-ware.com>
+ *   Florian Forster <octo at collectd.org>
+ *
+ * Description:
+ *   Encapsulates useful code to plugins which must parse a log file.
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_match.h"
+#include "utils_tail.h"
+#include "utils_tail_match.h"
+
+struct cu_tail_match_simple_s
+{
+  char plugin[DATA_MAX_NAME_LEN];
+  char plugin_instance[DATA_MAX_NAME_LEN];
+  char type[DATA_MAX_NAME_LEN];
+  char type_instance[DATA_MAX_NAME_LEN];
+  cdtime_t interval;
+};
+typedef struct cu_tail_match_simple_s cu_tail_match_simple_t;
+
+struct cu_tail_match_match_s
+{
+  cu_match_t *match;
+  void *user_data;
+  int (*submit) (cu_match_t *match, void *user_data);
+  void (*free) (void *user_data);
+};
+typedef struct cu_tail_match_match_s cu_tail_match_match_t;
+
+struct cu_tail_match_s
+{
+  int flags;
+  cu_tail_t *tail;
+
+  cdtime_t interval;
+  cu_tail_match_match_t *matches;
+  size_t matches_num;
+};
+
+/*
+ * Private functions
+ */
+static int simple_submit_match (cu_match_t *match, void *user_data)
+{
+  cu_tail_match_simple_t *data = (cu_tail_match_simple_t *) user_data;
+  cu_match_value_t *match_value;
+  value_list_t vl = VALUE_LIST_INIT;
+  value_t values[1];
+
+  match_value = (cu_match_value_t *) match_get_user_data (match);
+  if (match_value == NULL)
+    return (-1);
+
+  if ((match_value->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
+      && (match_value->values_num == 0))
+    values[0].gauge = NAN;
+  else
+    values[0] = match_value->value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, data->plugin, sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, data->plugin_instance,
+      sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, data->type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, data->type_instance,
+      sizeof (vl.type_instance));
+
+  vl.interval = data->interval;
+  plugin_dispatch_values (&vl);
+
+  if (match_value->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
+  {
+    match_value->value.gauge = NAN;
+    match_value->values_num = 0;
+  }
+
+  return (0);
+} /* int simple_submit_match */
+
+static int tail_callback (void *data, char *buf,
+    int __attribute__((unused)) buflen)
+{
+  cu_tail_match_t *obj = (cu_tail_match_t *) data;
+  size_t i;
+
+  for (i = 0; i < obj->matches_num; i++)
+    match_apply (obj->matches[i].match, buf);
+
+  return (0);
+} /* int tail_callback */
+
+/*
+ * Public functions
+ */
+cu_tail_match_t *tail_match_create (const char *filename)
+{
+  cu_tail_match_t *obj;
+
+  obj = (cu_tail_match_t *) malloc (sizeof (cu_tail_match_t));
+  if (obj == NULL)
+    return (NULL);
+  memset (obj, '\0', sizeof (cu_tail_match_t));
+
+  obj->tail = cu_tail_create (filename);
+  if (obj->tail == NULL)
+  {
+    sfree (obj);
+    return (NULL);
+  }
+
+  return (obj);
+} /* cu_tail_match_t *tail_match_create */
+
+void tail_match_destroy (cu_tail_match_t *obj)
+{
+  size_t i;
+
+  if (obj == NULL)
+    return;
+
+  if (obj->tail != NULL)
+  {
+    cu_tail_destroy (obj->tail);
+    obj->tail = NULL;
+  }
+
+  for (i = 0; i < obj->matches_num; i++)
+  {
+    cu_tail_match_match_t *match = obj->matches + i;
+    if (match->match != NULL)
+    {
+      match_destroy (match->match);
+      match->match = NULL;
+    }
+
+    if ((match->user_data != NULL)
+       && (match->free != NULL))
+      (*match->free) (match->user_data);
+    match->user_data = NULL;
+  }
+
+  sfree (obj->matches);
+  sfree (obj);
+} /* void tail_match_destroy */
+
+int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match,
+    int (*submit_match) (cu_match_t *match, void *user_data),
+    void *user_data,
+    void (*free_user_data) (void *user_data))
+{
+  cu_tail_match_match_t *temp;
+
+  temp = (cu_tail_match_match_t *) realloc (obj->matches,
+      sizeof (cu_tail_match_match_t) * (obj->matches_num + 1));
+  if (temp == NULL)
+    return (-1);
+
+  obj->matches = temp;
+  obj->matches_num++;
+
+  DEBUG ("tail_match_add_match interval %lf", CDTIME_T_TO_DOUBLE(((cu_tail_match_simple_t *)user_data)->interval));
+  temp = obj->matches + (obj->matches_num - 1);
+
+  temp->match = match;
+  temp->user_data = user_data;
+  temp->submit = submit_match;
+  temp->free = free_user_data;
+
+  return (0);
+} /* int tail_match_add_match */
+
+int tail_match_add_match_simple (cu_tail_match_t *obj,
+    const char *regex, const char *excluderegex, int ds_type,
+    const char *plugin, const char *plugin_instance,
+    const char *type, const char *type_instance, const cdtime_t interval)
+{
+  cu_match_t *match;
+  cu_tail_match_simple_t *user_data;
+  int status;
+
+  match = match_create_simple (regex, excluderegex, ds_type);
+  if (match == NULL)
+    return (-1);
+
+  user_data = (cu_tail_match_simple_t *) malloc (sizeof (cu_tail_match_simple_t));
+  if (user_data == NULL)
+  {
+    match_destroy (match);
+    return (-1);
+  }
+  memset (user_data, '\0', sizeof (cu_tail_match_simple_t));
+
+  sstrncpy (user_data->plugin, plugin, sizeof (user_data->plugin));
+  if (plugin_instance != NULL)
+    sstrncpy (user_data->plugin_instance, plugin_instance,
+       sizeof (user_data->plugin_instance));
+
+  sstrncpy (user_data->type, type, sizeof (user_data->type));
+  if (type_instance != NULL)
+    sstrncpy (user_data->type_instance, type_instance,
+       sizeof (user_data->type_instance));
+
+  user_data->interval = interval;
+
+  status = tail_match_add_match (obj, match, simple_submit_match,
+      user_data, free);
+
+  if (status != 0)
+  {
+    match_destroy (match);
+    sfree (user_data);
+  }
+
+  return (status);
+} /* int tail_match_add_match_simple */
+
+int tail_match_read (cu_tail_match_t *obj)
+{
+  char buffer[4096];
+  int status;
+  size_t i;
+
+  status = cu_tail_read (obj->tail, buffer, sizeof (buffer), tail_callback,
+      (void *) obj);
+  if (status != 0)
+  {
+    ERROR ("tail_match: cu_tail_read failed.");
+    return (status);
+  }
+
+  for (i = 0; i < obj->matches_num; i++)
+  {
+    cu_tail_match_match_t *lt_match = obj->matches + i;
+
+    if (lt_match->submit == NULL)
+      continue;
+
+    (*lt_match->submit) (lt_match->match, lt_match->user_data);
+  }
+
+  return (0);
+} /* int tail_match_read */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/daemon/utils_tail_match.h b/src/daemon/utils_tail_match.h
new file mode 100644 (file)
index 0000000..0404de2
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * collectd - src/utils_tail_match.h
+ * Copyright (C) 2007-2008  C-Ware, Inc.
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Luke Heberling <lukeh at c-ware.com>
+ *   Florian Forster <octo at collectd.org>
+ *
+ * Description:
+ *   `tail_match' uses `utils_tail' and `utils_match' to tail a file and try to
+ *   match it using several regular expressions. Matches are then passed to
+ *   user-provided callback functions or default handlers. This should keep all
+ *   of the parsing logic out of the actual plugin, which only operate with
+ *   regular expressions.
+ */
+
+#include "utils_match.h"
+
+struct cu_tail_match_s;
+typedef struct cu_tail_match_s cu_tail_match_t;
+
+/*
+ * NAME
+ *   tail_match_create
+ *
+ * DESCRIPTION
+ *   Allocates, initializes and returns a new `cu_tail_match_t' object.
+ *
+ * PARAMETERS
+ *   `filename'  The name to read data from.
+ *
+ * RETURN VALUE
+ *   Returns NULL upon failure, non-NULL otherwise.
+ */
+cu_tail_match_t *tail_match_create (const char *filename);
+
+/*
+ * NAME
+ *   tail_match_destroy
+ *
+ * DESCRIPTION
+ *   Releases resources used by the `cu_tail_match_t' object.
+ *
+ * PARAMETERS
+ *   The object to destroy.
+ */
+void tail_match_destroy (cu_tail_match_t *obj);
+
+/*
+ * NAME
+ *   tail_match_add_match
+ *
+ * DESCRIPTION
+ *   Adds a match, in form of a `cu_match_t' object, to the object.
+ *   After data has been read from the logfile (using utils_tail) the callback
+ *   function `submit_match' is called with the match object and the user
+ *   supplied data.
+ *   Please note that his function is called regardless whether this match
+ *   matched any lines recently or not.
+ *   When `tail_match_destroy' is called the `user_data' pointer is freed using
+ *   the `free_user_data' callback - if it is not NULL.
+ *   When using this interface the `tail_match' module doesn't dispatch any values
+ *   itself - all that has to happen in either the match-callbacks or the
+ *   submit_match callback.
+ *
+ * RETURN VALUE
+ *   Zero upon success, non-zero otherwise.
+ */
+int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match,
+    int (*submit_match) (cu_match_t *match, void *user_data),
+    void *user_data,
+    void (*free_user_data) (void *user_data));
+
+/*
+ * NAME
+ *  tail_match_add_match_simple
+ *
+ * DESCRIPTION
+ *  A simplified version of `tail_match_add_match'. The regular expressen `regex'
+ *  must match a number, which is then dispatched according to `ds_type'. See
+ *  the `match_create_simple' function in utils_match.h for a description how
+ *  this flag effects calculation of a new value.
+ *  The values gathered are dispatched by the tail_match module in this case. The
+ *  passed `plugin', `plugin_instance', `type', and `type_instance' are
+ *  directly used when submitting these values.
+ *  With excluderegex it is possible to exlude lines from the match.
+ *
+ * RETURN VALUE
+ *   Zero upon success, non-zero otherwise.
+ */
+int tail_match_add_match_simple (cu_tail_match_t *obj,
+    const char *regex, const char *excluderegex, int ds_type,
+    const char *plugin, const char *plugin_instance,
+    const char *type, const char *type_instance, const cdtime_t interval);
+
+/*
+ * NAME
+ *   tail_match_read
+ *
+ * DESCRIPTION
+ *   This function should be called periodically by plugins. It reads new lines
+ *   from the logfile using `utils_tail' and tries to match them using all
+ *   added `utils_match' objects.
+ *   After all lines have been read and processed, the submit_match callback is
+ *   called or, in case of tail_match_add_match_simple, the data is dispatched to
+ *   the daemon directly.
+ *
+ * RETURN VALUE
+ *   Zero on success, nonzero on failure.
+*/
+int tail_match_read (cu_tail_match_t *obj);
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/daemon/utils_threshold.c b/src/daemon/utils_threshold.c
new file mode 100644 (file)
index 0000000..4a8df89
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ * collectd - src/utils_threshold.c
+ * Copyright (C) 2014       Pierre-Yves Ritschard
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_avltree.h"
+#include "utils_threshold.h"
+
+#include <pthread.h>
+
+/*
+ * Exported symbols
+ * {{{ */
+c_avl_tree_t   *threshold_tree = NULL;
+pthread_mutex_t threshold_lock = PTHREAD_MUTEX_INITIALIZER;
+/* }}} */
+
+/*
+ * threshold_t *threshold_get
+ *
+ * Retrieve one specific threshold configuration. For looking up a threshold
+ * matching a value_list_t, see "threshold_search" below. Returns NULL if the
+ * specified threshold doesn't exist.
+ */
+threshold_t *threshold_get (const char *hostname,
+    const char *plugin, const char *plugin_instance,
+    const char *type, const char *type_instance)
+{ /* {{{ */
+  char name[6 * DATA_MAX_NAME_LEN];
+  threshold_t *th = NULL;
+
+  format_name (name, sizeof (name),
+      (hostname == NULL) ? "" : hostname,
+      (plugin == NULL) ? "" : plugin, plugin_instance,
+      (type == NULL) ? "" : type, type_instance);
+  name[sizeof (name) - 1] = '\0';
+
+  if (c_avl_get (threshold_tree, name, (void *) &th) == 0)
+    return (th);
+  else
+    return (NULL);
+} /* }}} threshold_t *threshold_get */
+
+/*
+ * threshold_t *threshold_search
+ *
+ * Searches for a threshold configuration using all the possible variations of
+ * "Host", "Plugin" and "Type" blocks. Returns NULL if no threshold could be
+ * found.
+ * XXX: This is likely the least efficient function in collectd.
+ */
+threshold_t *threshold_search (const value_list_t *vl)
+{ /* {{{ */
+  threshold_t *th;
+
+  if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance,
+         vl->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance,
+         vl->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, vl->plugin, NULL,
+         vl->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, vl->plugin, NULL,
+         vl->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, "", NULL,
+         vl->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, "", NULL,
+         vl->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance,
+         vl->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance,
+         vl->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, NULL,
+         vl->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, NULL,
+         vl->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", "", NULL,
+         vl->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", "", NULL,
+         vl->type, NULL)) != NULL)
+    return (th);
+
+  return (NULL);
+} /* }}} threshold_t *threshold_search */
+
+int ut_search_threshold (const value_list_t *vl, /* {{{ */
+    threshold_t *ret_threshold)
+{
+  threshold_t *t;
+
+  if (vl == NULL)
+    return (EINVAL);
+
+       /* Is this lock really necessary? */
+       pthread_mutex_lock (&threshold_lock);
+  t = threshold_search (vl);
+  if (t == NULL) {
+               pthread_mutex_unlock (&threshold_lock);
+    return (ENOENT);
+       }
+
+  memcpy (ret_threshold, t, sizeof (*ret_threshold));
+       pthread_mutex_unlock (&threshold_lock);
+
+  ret_threshold->next = NULL;
+
+  return (0);
+} /* }}} int ut_search_threshold */
+
+
diff --git a/src/daemon/utils_threshold.h b/src/daemon/utils_threshold.h
new file mode 100644 (file)
index 0000000..bf097fa
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * collectd - src/utils_threshold.h
+ * Copyright (C) 2014       Pierre-Yves Ritschard
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ **/
+
+#ifndef UTILS_THRESHOLD_H
+#define UTILS_THRESHOLD_H 1
+
+#define UT_FLAG_INVERT  0x01
+#define UT_FLAG_PERSIST 0x02
+#define UT_FLAG_PERCENTAGE 0x04
+#define UT_FLAG_INTERESTING 0x08
+#define UT_FLAG_PERSIST_OK 0x10
+typedef struct threshold_s
+{
+  char host[DATA_MAX_NAME_LEN];
+  char plugin[DATA_MAX_NAME_LEN];
+  char plugin_instance[DATA_MAX_NAME_LEN];
+  char type[DATA_MAX_NAME_LEN];
+  char type_instance[DATA_MAX_NAME_LEN];
+  char data_source[DATA_MAX_NAME_LEN];
+  gauge_t warning_min;
+  gauge_t warning_max;
+  gauge_t failure_min;
+  gauge_t failure_max;
+  gauge_t hysteresis;
+  unsigned int flags;
+  int hits;
+  struct threshold_s *next;
+} threshold_t;
+
+extern c_avl_tree_t   *threshold_tree;
+extern pthread_mutex_t threshold_lock;
+
+threshold_t *threshold_get (const char *hostname,
+    const char *plugin, const char *plugin_instance,
+    const char *type, const char *type_instance);
+
+threshold_t *threshold_search (const value_list_t *vl);
+
+int ut_search_threshold (const value_list_t *vl, 
+  threshold_t *ret_threshold);
+
+#endif /* UTILS_THRESHOLD_H */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/daemon/utils_time.c b/src/daemon/utils_time.c
new file mode 100644 (file)
index 0000000..6603c15
--- /dev/null
@@ -0,0 +1,104 @@
+/**
+ * collectd - src/utils_time.c
+ * Copyright (C) 2010       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <ff at octo.it>
+ **/
+
+#include "collectd.h"
+#include "utils_time.h"
+#include "plugin.h"
+#include "common.h"
+
+#if HAVE_CLOCK_GETTIME
+cdtime_t cdtime (void) /* {{{ */
+{
+  int status;
+  struct timespec ts = { 0, 0 };
+
+  status = clock_gettime (CLOCK_REALTIME, &ts);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("cdtime: clock_gettime failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (0);
+  }
+
+  return (TIMESPEC_TO_CDTIME_T (&ts));
+} /* }}} cdtime_t cdtime */
+#else
+/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
+cdtime_t cdtime (void) /* {{{ */
+{
+  int status;
+  struct timeval tv = { 0, 0 };
+
+  status = gettimeofday (&tv, /* struct timezone = */ NULL);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("cdtime: gettimeofday failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (0);
+  }
+
+  return (TIMEVAL_TO_CDTIME_T (&tv));
+} /* }}} cdtime_t cdtime */
+#endif
+
+size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t) /* {{{ */
+{
+  struct timespec t_spec;
+  struct tm t_tm;
+
+  size_t len;
+
+  CDTIME_T_TO_TIMESPEC (t, &t_spec);
+  NORMALIZE_TIMESPEC (t_spec);
+
+  if (localtime_r ((time_t *)&t_spec.tv_sec, &t_tm) == NULL) {
+    char errbuf[1024];
+    ERROR ("cdtime_to_iso8601: localtime_r failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (0);
+  }
+
+  len = strftime (s, max, "%Y-%m-%dT%H:%M:%S", &t_tm);
+  if (len == 0)
+    return 0;
+
+  if (max - len > 2) {
+    int n = snprintf (s + len, max - len, ".%09i", (int)t_spec.tv_nsec);
+    len += (n < max - len) ? n : max - len;
+  }
+
+  if (max - len > 3) {
+    int n = strftime (s + len, max - len, "%z", &t_tm);
+    len += (n < max - len) ? n : max - len;
+  }
+
+  s[max - 1] = '\0';
+  return len;
+} /* }}} size_t cdtime_to_iso8601 */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/daemon/utils_time.h b/src/daemon/utils_time.h
new file mode 100644 (file)
index 0000000..9b08e8e
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * collectd - src/utils_time.h
+ * Copyright (C) 2010       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <ff at octo.it>
+ **/
+
+#ifndef UTILS_TIME_H
+#define UTILS_TIME_H 1
+
+#include "collectd.h"
+
+/*
+ * "cdtime_t" is a 64bit unsigned integer. The time is stored at a 2^-30 second
+ * resolution, i.e. the most significant 34 bit are used to store the time in
+ * seconds, the least significant bits store the sub-second part in something
+ * very close to nanoseconds. *The* big advantage of storing time in this
+ * manner is that comparing times and calculating differences is as simple as
+ * it is with "time_t", i.e. a simple integer comparison / subtraction works.
+ */
+/* 
+ * cdtime_t is defined in "collectd.h" */
+/* typedef uint64_t cdtime_t; */
+
+/* 2^30 = 1073741824 */
+#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) * 1073741824)
+#define CDTIME_T_TO_TIME_T(t) ((time_t) ((t) / 1073741824))
+
+#define CDTIME_T_TO_DOUBLE(t) (((double) (t)) / 1073741824.0)
+#define DOUBLE_TO_CDTIME_T(d) ((cdtime_t) ((d) * 1073741824.0))
+
+#define MS_TO_CDTIME_T(ms) ((cdtime_t)    (((double) (ms)) * 1073741.824))
+#define CDTIME_T_TO_MS(t)  ((long)        (((double) (t))  / 1073741.824))
+#define US_TO_CDTIME_T(us) ((cdtime_t)    (((double) (us)) * 1073.741824))
+#define CDTIME_T_TO_US(t)  ((suseconds_t) (((double) (t))  / 1073.741824))
+#define NS_TO_CDTIME_T(ns) ((cdtime_t)    (((double) (ns)) * 1.073741824))
+#define CDTIME_T_TO_NS(t)  ((long)        (((double) (t))  / 1.073741824))
+
+#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do {                                    \
+        (tvp)->tv_sec = CDTIME_T_TO_TIME_T (cdt);                            \
+        (tvp)->tv_usec = CDTIME_T_TO_US ((cdt) % 1073741824);                \
+} while (0)
+#define TIMEVAL_TO_CDTIME_T(tv) (TIME_T_TO_CDTIME_T ((tv)->tv_sec)           \
+    + US_TO_CDTIME_T ((tv)->tv_usec))
+
+#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do {                                   \
+  (tsp)->tv_sec = CDTIME_T_TO_TIME_T (cdt);                                  \
+  (tsp)->tv_nsec = CDTIME_T_TO_NS ((cdt) % 1073741824);                      \
+} while (0)
+#define TIMESPEC_TO_CDTIME_T(ts) (TIME_T_TO_CDTIME_T ((ts)->tv_sec)           \
+    + NS_TO_CDTIME_T ((ts)->tv_nsec))
+
+cdtime_t cdtime (void);
+
+/* format a cdtime_t value in ISO 8601 format:
+ * returns the number of characters written to the string (not including the
+ * terminating null byte or 0 on error; the function ensures that the string
+ * is null terminated */
+size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t);
+
+#endif /* UTILS_TIME_H */
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/daemon/utils_time_mock.c b/src/daemon/utils_time_mock.c
new file mode 100644 (file)
index 0000000..5edfe6f
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * collectd - src/tests/mock/utils_time.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "utils_time.h"
+
+cdtime_t cdtime (void)
+{
+  return (0);
+}
+
diff --git a/src/dbi.c b/src/dbi.c
new file mode 100644 (file)
index 0000000..a7963ea
--- /dev/null
+++ b/src/dbi.c
@@ -0,0 +1,871 @@
+/**
+ * collectd - src/dbi.c
+ * Copyright (C) 2008-2015  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_db_query.h"
+
+#include <dbi/dbi.h>
+
+/* libdbi 0.9.0 introduced a new thread-safe interface and marked the old
+ * functions "deprecated". These macros convert the new functions to their old
+ * counterparts for backwards compatibility. */
+#if !defined(LIBDBI_VERSION) || (LIBDBI_VERSION < 900)
+# define HAVE_LEGACY_LIBDBI 1
+# define dbi_initialize_r(a,inst) dbi_initialize(a)
+# define dbi_shutdown_r(inst) dbi_shutdown()
+# define dbi_set_verbosity_r(a,inst) dbi_set_verbosity(a)
+# define dbi_driver_list_r(a,inst) dbi_driver_list(a)
+# define dbi_driver_open_r(a,inst) dbi_driver_open(a)
+#endif
+
+/*
+ * Data types
+ */
+struct cdbi_driver_option_s /* {{{ */
+{
+  char *key;
+  union
+  {
+    char *string;
+    int numeric;
+  } value;
+  _Bool is_numeric;
+};
+typedef struct cdbi_driver_option_s cdbi_driver_option_t; /* }}} */
+
+struct cdbi_database_s /* {{{ */
+{
+  char *name;
+  char *select_db;
+
+  char *driver;
+  char *host;
+  cdbi_driver_option_t *driver_options;
+  size_t driver_options_num;
+
+  udb_query_preparation_area_t **q_prep_areas;
+  udb_query_t **queries;
+  size_t        queries_num;
+
+  dbi_conn connection;
+};
+typedef struct cdbi_database_s cdbi_database_t; /* }}} */
+
+/*
+ * Global variables
+ */
+#if !defined(HAVE_LEGACY_LIBDBI) || !HAVE_LEGACY_LIBDBI
+static dbi_inst          dbi_instance  = 0;
+#endif
+static udb_query_t     **queries       = NULL;
+static size_t            queries_num   = 0;
+static cdbi_database_t **databases     = NULL;
+static size_t            databases_num = 0;
+
+static int cdbi_read_database (user_data_t *ud);
+
+/*
+ * Functions
+ */
+static const char *cdbi_strerror (dbi_conn conn, /* {{{ */
+    char *buffer, size_t buffer_size)
+{
+  const char *msg;
+  int status;
+
+  if (conn == NULL)
+  {
+    sstrncpy (buffer, "connection is NULL", buffer_size);
+    return (buffer);
+  }
+
+  msg = NULL;
+  status = dbi_conn_error (conn, &msg);
+  if ((status >= 0) && (msg != NULL))
+    ssnprintf (buffer, buffer_size, "%s (status %i)", msg, status);
+  else
+    ssnprintf (buffer, buffer_size, "dbi_conn_error failed with status %i",
+        status);
+
+  return (buffer);
+} /* }}} const char *cdbi_conn_error */
+
+static int cdbi_result_get_field (dbi_result res, /* {{{ */
+    unsigned int index, char *buffer, size_t buffer_size)
+{
+  unsigned short src_type;
+
+  src_type = dbi_result_get_field_type_idx (res, index);
+  if (src_type == DBI_TYPE_ERROR)
+  {
+    ERROR ("dbi plugin: cdbi_result_get: "
+        "dbi_result_get_field_type_idx failed.");
+    return (-1);
+  }
+
+  if (src_type == DBI_TYPE_INTEGER)
+  {
+    long long value;
+
+    value = dbi_result_get_longlong_idx (res, index);
+    ssnprintf (buffer, buffer_size, "%lli", value);
+  }
+  else if (src_type == DBI_TYPE_DECIMAL)
+  {
+    double value;
+
+    value = dbi_result_get_double_idx (res, index);
+    ssnprintf (buffer, buffer_size, "%63.15g", value);
+  }
+  else if (src_type == DBI_TYPE_STRING)
+  {
+    const char *value;
+    
+    value = dbi_result_get_string_idx (res, index);
+    if (value == NULL)
+      sstrncpy (buffer, "", buffer_size);
+    else if (strcmp ("ERROR", value) == 0)
+      return (-1);
+    else
+      sstrncpy (buffer, value, buffer_size);
+  }
+  /* DBI_TYPE_BINARY */
+  /* DBI_TYPE_DATETIME */
+  else
+  {
+    const char *field_name;
+
+    field_name = dbi_result_get_field_name (res, index);
+    if (field_name == NULL)
+      field_name = "<unknown>";
+
+    ERROR ("dbi plugin: Column `%s': Don't know how to handle "
+        "source type %hu.",
+        field_name, src_type);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cdbi_result_get_field */
+
+static void cdbi_database_free (cdbi_database_t *db) /* {{{ */
+{
+  size_t i;
+
+  if (db == NULL)
+    return;
+
+  sfree (db->name);
+  sfree (db->driver);
+
+  for (i = 0; i < db->driver_options_num; i++)
+  {
+    sfree (db->driver_options[i].key);
+    if (!db->driver_options[i].is_numeric)
+      sfree (db->driver_options[i].value.string);
+  }
+  sfree (db->driver_options);
+
+  if (db->q_prep_areas)
+    for (i = 0; i < db->queries_num; ++i)
+      udb_query_delete_preparation_area (db->q_prep_areas[i]);
+  free (db->q_prep_areas);
+
+  sfree (db);
+} /* }}} void cdbi_database_free */
+
+/* Configuration handling functions {{{
+ *
+ * <Plugin dbi>
+ *   <Query "plugin_instance0">
+ *     Statement "SELECT name, value FROM table"
+ *     <Result>
+ *       Type "gauge"
+ *       InstancesFrom "name"
+ *       ValuesFrom "value"
+ *     </Result>
+ *     ...
+ *   </Query>
+ *     
+ *   <Database "plugin_instance1">
+ *     Driver "mysql"
+ *     DriverOption "hostname" "localhost"
+ *     ...
+ *     Query "plugin_instance0"
+ *   </Database>
+ * </Plugin>
+ */
+
+static int cdbi_config_add_database_driver_option (cdbi_database_t *db, /* {{{ */
+    oconfig_item_t *ci)
+{
+  cdbi_driver_option_t *option;
+
+  if ((ci->values_num != 2)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || ((ci->values[1].type != OCONFIG_TYPE_STRING)
+        && (ci->values[1].type != OCONFIG_TYPE_NUMBER)))
+  {
+    WARNING ("dbi plugin: The `DriverOption' config option "
+        "needs exactly two arguments.");
+    return (-1);
+  }
+
+  option = (cdbi_driver_option_t *) realloc (db->driver_options,
+      sizeof (*option) * (db->driver_options_num + 1));
+  if (option == NULL)
+  {
+    ERROR ("dbi plugin: realloc failed");
+    return (-1);
+  }
+
+  db->driver_options = option;
+  option = db->driver_options + db->driver_options_num;
+  memset (option, 0, sizeof (*option));
+
+  option->key = strdup (ci->values[0].value.string);
+  if (option->key == NULL)
+  {
+    ERROR ("dbi plugin: strdup failed.");
+    return (-1);
+  }
+
+  if (ci->values[1].type == OCONFIG_TYPE_STRING)
+  {
+    option->value.string = strdup (ci->values[1].value.string);
+    if (option->value.string == NULL)
+    {
+      ERROR ("dbi plugin: strdup failed.");
+      sfree (option->key);
+      return (-1);
+    }
+  }
+  else
+  {
+    assert (ci->values[1].type == OCONFIG_TYPE_NUMBER);
+    option->value.numeric = (int) (ci->values[1].value.number + .5);
+    option->is_numeric = 1;
+  }
+
+  db->driver_options_num++;
+  return (0);
+} /* }}} int cdbi_config_add_database_driver_option */
+
+static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */
+{
+  cdbi_database_t *db;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("dbi plugin: The `Database' block "
+        "needs exactly one string argument.");
+    return (-1);
+  }
+
+  db = (cdbi_database_t *) malloc (sizeof (*db));
+  if (db == NULL)
+  {
+    ERROR ("dbi plugin: malloc failed.");
+    return (-1);
+  }
+  memset (db, 0, sizeof (*db));
+
+  status = cf_util_get_string (ci, &db->name);
+  if (status != 0)
+  {
+    sfree (db);
+    return (status);
+  }
+
+  /* Fill the `cdbi_database_t' structure.. */
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Driver", child->key) == 0)
+      status = cf_util_get_string (child, &db->driver);
+    else if (strcasecmp ("DriverOption", child->key) == 0)
+      status = cdbi_config_add_database_driver_option (db, child);
+    else if (strcasecmp ("SelectDB", child->key) == 0)
+      status = cf_util_get_string (child, &db->select_db);
+    else if (strcasecmp ("Query", child->key) == 0)
+      status = udb_query_pick_from_list (child, queries, queries_num,
+          &db->queries, &db->queries_num);
+    else if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &db->host);
+    else
+    {
+      WARNING ("dbi plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Check that all necessary options have been given. */
+  while (status == 0)
+  {
+    if (db->driver == NULL)
+    {
+      WARNING ("dbi plugin: `Driver' not given for database `%s'", db->name);
+      status = -1;
+    }
+    if (db->driver_options_num == 0)
+    {
+      WARNING ("dbi plugin: No `DriverOption' given for database `%s'. "
+          "This will likely not work.", db->name);
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  while ((status == 0) && (db->queries_num > 0))
+  {
+    db->q_prep_areas = (udb_query_preparation_area_t **) calloc (
+        db->queries_num, sizeof (*db->q_prep_areas));
+
+    if (db->q_prep_areas == NULL)
+    {
+      WARNING ("dbi plugin: malloc failed");
+      status = -1;
+      break;
+    }
+
+    for (i = 0; i < db->queries_num; ++i)
+    {
+      db->q_prep_areas[i]
+        = udb_query_allocate_preparation_area (db->queries[i]);
+
+      if (db->q_prep_areas[i] == NULL)
+      {
+        WARNING ("dbi plugin: udb_query_allocate_preparation_area failed");
+        status = -1;
+        break;
+      }
+    }
+
+    break;
+  }
+
+  /* If all went well, add this database to the global list of databases. */
+  if (status == 0)
+  {
+    cdbi_database_t **temp;
+
+    temp = (cdbi_database_t **) realloc (databases,
+        sizeof (*databases) * (databases_num + 1));
+    if (temp == NULL)
+    {
+      ERROR ("dbi plugin: realloc failed");
+      status = -1;
+    }
+    else
+    {
+      user_data_t ud;
+      char *name = NULL;
+
+      databases = temp;
+      databases[databases_num] = db;
+      databases_num++;
+
+      memset (&ud, 0, sizeof (ud));
+      ud.data = (void *) db;
+      ud.free_func = NULL;
+      name = ssnprintf_alloc("dbi:%s", db->name);
+
+      plugin_register_complex_read (/* group = */ NULL,
+          /* name = */ name ? name : db->name,
+          /* callback = */ cdbi_read_database,
+          /* interval = */ NULL,
+          /* user_data = */ &ud);
+      free (name);
+    }
+  }
+
+  if (status != 0)
+  {
+    cdbi_database_free (db);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cdbi_config_add_database */
+
+static int cdbi_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp ("Query", child->key) == 0)
+      udb_query_create (&queries, &queries_num, child,
+          /* callback = */ NULL);
+    else if (strcasecmp ("Database", child->key) == 0)
+      cdbi_config_add_database (child);
+    else
+    {
+      WARNING ("dbi plugin: Ignoring unknown config option `%s'.", child->key);
+    }
+  } /* for (ci->children) */
+
+  return (0);
+} /* }}} int cdbi_config */
+
+/* }}} End of configuration handling functions */
+
+static int cdbi_init (void) /* {{{ */
+{
+  static int did_init = 0;
+  int status;
+
+  if (did_init != 0)
+    return (0);
+
+  if (queries_num == 0)
+  {
+    ERROR ("dbi plugin: No <Query> blocks have been found. Without them, "
+        "this plugin can't do anything useful, so we will returns an error.");
+    return (-1);
+  }
+
+  if (databases_num == 0)
+  {
+    ERROR ("dbi plugin: No <Database> blocks have been found. Without them, "
+        "this plugin can't do anything useful, so we will returns an error.");
+    return (-1);
+  }
+
+  status = dbi_initialize_r (/* driverdir = */ NULL, &dbi_instance);
+  if (status < 0)
+  {
+    ERROR ("dbi plugin: cdbi_init: dbi_initialize_r failed with status %i.",
+        status);
+    return (-1);
+  }
+  else if (status == 0)
+  {
+    ERROR ("dbi plugin: `dbi_initialize_r' could not load any drivers. Please "
+        "install at least one `DBD' or check your installation.");
+    return (-1);
+  }
+  DEBUG ("dbi plugin: cdbi_init: dbi_initialize_r reports %i driver%s.",
+      status, (status == 1) ? "" : "s");
+
+  return (0);
+} /* }}} int cdbi_init */
+
+static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */
+    udb_query_t *q, udb_query_preparation_area_t *prep_area)
+{
+  const char *statement;
+  dbi_result res;
+  size_t column_num;
+  char **column_names;
+  char **column_values;
+  int status;
+  size_t i;
+
+  /* Macro that cleans up dynamically allocated memory and returns the
+   * specified status. */
+#define BAIL_OUT(status) \
+  if (column_names != NULL) { sfree (column_names[0]); sfree (column_names); } \
+  if (column_values != NULL) { sfree (column_values[0]); sfree (column_values); } \
+  if (res != NULL) { dbi_result_free (res); res = NULL; } \
+  return (status)
+
+  column_names = NULL;
+  column_values = NULL;
+  res = NULL;
+
+  statement = udb_query_get_statement (q);
+  assert (statement != NULL);
+
+  res = dbi_conn_query (db->connection, statement);
+  if (res == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+        "dbi_conn_query failed: %s",
+        db->name, udb_query_get_name (q),
+        cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+    BAIL_OUT (-1);
+  }
+  else /* Get the number of columns */
+  {
+    unsigned int db_status;
+
+    db_status = dbi_result_get_numfields (res);
+    if (db_status == DBI_FIELD_ERROR)
+    {
+      char errbuf[1024];
+      ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+          "dbi_result_get_numfields failed: %s",
+          db->name, udb_query_get_name (q),
+          cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+      BAIL_OUT (-1);
+    }
+
+    column_num = (size_t) db_status;
+    DEBUG ("cdbi_read_database_query (%s, %s): There are %zu columns.",
+        db->name, udb_query_get_name (q), column_num);
+  }
+
+  /* Allocate `column_names' and `column_values'. {{{ */
+  column_names = (char **) calloc (column_num, sizeof (char *));
+  if (column_names == NULL)
+  {
+    ERROR ("dbi plugin: malloc failed.");
+    BAIL_OUT (-1);
+  }
+
+  column_names[0] = (char *) calloc (column_num,
+      DATA_MAX_NAME_LEN * sizeof (char));
+  if (column_names[0] == NULL)
+  {
+    ERROR ("dbi plugin: malloc failed.");
+    BAIL_OUT (-1);
+  }
+  for (i = 1; i < column_num; i++)
+    column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;
+
+  column_values = (char **) calloc (column_num, sizeof (char *));
+  if (column_values == NULL)
+  {
+    ERROR ("dbi plugin: malloc failed.");
+    BAIL_OUT (-1);
+  }
+
+  column_values[0] = (char *) calloc (column_num,
+      DATA_MAX_NAME_LEN * sizeof (char));
+  if (column_values[0] == NULL)
+  {
+    ERROR ("dbi plugin: malloc failed.");
+    BAIL_OUT (-1);
+  }
+  for (i = 1; i < column_num; i++)
+    column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
+  /* }}} */
+
+  /* Copy the field names to `column_names' */
+  for (i = 0; i < column_num; i++) /* {{{ */
+  {
+    const char *column_name;
+
+    column_name = dbi_result_get_field_name (res, (unsigned int) (i + 1));
+    if (column_name == NULL)
+    {
+      ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+          "Cannot retrieve name of field %zu.",
+          db->name, udb_query_get_name (q), i + 1);
+      BAIL_OUT (-1);
+    }
+
+    sstrncpy (column_names[i], column_name, DATA_MAX_NAME_LEN);
+  } /* }}} for (i = 0; i < column_num; i++) */
+
+  udb_query_prepare_result (q, prep_area, (db->host ? db->host : hostname_g),
+      /* plugin = */ "dbi", db->name,
+      column_names, column_num, /* interval = */ 0);
+
+  /* 0 = error; 1 = success; */
+  status = dbi_result_first_row (res); /* {{{ */
+  if (status != 1)
+  {
+    char errbuf[1024];
+    ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+        "dbi_result_first_row failed: %s. Maybe the statement didn't "
+        "return any rows?",
+        db->name, udb_query_get_name (q),
+        cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+    udb_query_finish_result (q, prep_area);
+    BAIL_OUT (-1);
+  } /* }}} */
+
+  /* Iterate over all rows and call `udb_query_handle_result' with each list of
+   * values. */
+  while (42) /* {{{ */
+  {
+    status = 0;
+    /* Copy the value of the columns to `column_values' */
+    for (i = 0; i < column_num; i++) /* {{{ */
+    {
+      status = cdbi_result_get_field (res, (unsigned int) (i + 1),
+          column_values[i], DATA_MAX_NAME_LEN);
+
+      if (status != 0)
+      {
+        ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+            "cdbi_result_get_field (%zu) failed.",
+            db->name, udb_query_get_name (q), i + 1);
+        status = -1;
+        break;
+      }
+    } /* }}} for (i = 0; i < column_num; i++) */
+
+    /* If all values were copied successfully, call `udb_query_handle_result'
+     * to dispatch the row to the daemon. */
+    if (status == 0) /* {{{ */
+    {
+      status = udb_query_handle_result (q, prep_area, column_values);
+      if (status != 0)
+      {
+        ERROR ("dbi plugin: cdbi_read_database_query (%s, %s): "
+            "udb_query_handle_result failed.",
+            db->name, udb_query_get_name (q));
+      }
+    } /* }}} */
+
+    /* Get the next row from the database. */
+    status = dbi_result_next_row (res); /* {{{ */
+    if (status != 1)
+    {
+      if (dbi_conn_error (db->connection, NULL) != 0)
+      {
+        char errbuf[1024];
+        WARNING ("dbi plugin: cdbi_read_database_query (%s, %s): "
+            "dbi_result_next_row failed: %s.",
+            db->name, udb_query_get_name (q),
+            cdbi_strerror (db->connection, errbuf, sizeof (errbuf)));
+      }
+      break;
+    } /* }}} */
+  } /* }}} while (42) */
+
+  /* Tell the db query interface that we're done with this query. */
+  udb_query_finish_result (q, prep_area);
+
+  /* Clean up and return `status = 0' (success) */
+  BAIL_OUT (0);
+#undef BAIL_OUT
+} /* }}} int cdbi_read_database_query */
+
+static int cdbi_connect_database (cdbi_database_t *db) /* {{{ */
+{
+  dbi_driver driver;
+  dbi_conn connection;
+  size_t i;
+  int status;
+
+  if (db->connection != NULL)
+  {
+    status = dbi_conn_ping (db->connection);
+    if (status != 0) /* connection is alive */
+      return (0);
+
+    dbi_conn_close (db->connection);
+    db->connection = NULL;
+  }
+
+  driver = dbi_driver_open_r (db->driver, dbi_instance);
+  if (driver == NULL)
+  {
+    ERROR ("dbi plugin: cdbi_connect_database: dbi_driver_open_r (%s) failed.",
+        db->driver);
+    INFO ("dbi plugin: Maybe the driver isn't installed? "
+        "Known drivers are:");
+    for (driver = dbi_driver_list_r (NULL, dbi_instance);
+        driver != NULL;
+        driver = dbi_driver_list_r (driver, dbi_instance))
+    {
+      INFO ("dbi plugin: * %s", dbi_driver_get_name (driver));
+    }
+    return (-1);
+  }
+
+  connection = dbi_conn_open (driver);
+  if (connection == NULL)
+  {
+    ERROR ("dbi plugin: cdbi_connect_database: dbi_conn_open (%s) failed.",
+        db->driver);
+    return (-1);
+  }
+
+  /* Set all the driver options. Because this is a very very very generic
+   * interface, the error handling is kind of long. If an invalid option is
+   * encountered, it will get a list of options understood by the driver and
+   * report that as `INFO'. This way, users hopefully don't have too much
+   * trouble finding out how to configure the plugin correctly.. */
+  for (i = 0; i < db->driver_options_num; i++)
+  {
+    if (db->driver_options[i].is_numeric)
+    {
+      status = dbi_conn_set_option_numeric (connection,
+          db->driver_options[i].key, db->driver_options[i].value.numeric);
+      if (status != 0)
+      {
+        char errbuf[1024];
+        ERROR ("dbi plugin: cdbi_connect_database (%s): "
+            "dbi_conn_set_option_numeric (\"%s\", %i) failed: %s.",
+            db->name,
+            db->driver_options[i].key, db->driver_options[i].value.numeric,
+            cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+      }
+    }
+    else
+    {
+      status = dbi_conn_set_option (connection,
+          db->driver_options[i].key, db->driver_options[i].value.string);
+      if (status != 0)
+      {
+        char errbuf[1024];
+        ERROR ("dbi plugin: cdbi_connect_database (%s): "
+            "dbi_conn_set_option (\"%s\", \"%s\") failed: %s.",
+            db->name,
+            db->driver_options[i].key, db->driver_options[i].value.string,
+            cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+      }
+    }
+
+    if (status != 0)
+    {
+      char const *opt;
+
+      INFO ("dbi plugin: This is a list of all options understood "
+          "by the `%s' driver:", db->driver);
+      for (opt = dbi_conn_get_option_list (connection, NULL);
+          opt != NULL;
+          opt = dbi_conn_get_option_list (connection, opt))
+      {
+        INFO ("dbi plugin: * %s", opt);
+      }
+
+      dbi_conn_close (connection);
+      return (-1);
+    }
+  } /* for (i = 0; i < db->driver_options_num; i++) */
+
+  status = dbi_conn_connect (connection);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("dbi plugin: cdbi_connect_database (%s): "
+        "dbi_conn_connect failed: %s",
+        db->name, cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+    dbi_conn_close (connection);
+    return (-1);
+  }
+
+  if (db->select_db != NULL)
+  {
+    status = dbi_conn_select_db (connection, db->select_db);
+    if (status != 0)
+    {
+      char errbuf[1024];
+      WARNING ("dbi plugin: cdbi_connect_database (%s): "
+          "dbi_conn_select_db (%s) failed: %s. Check the `SelectDB' option.",
+          db->name, db->select_db,
+          cdbi_strerror (connection, errbuf, sizeof (errbuf)));
+      dbi_conn_close (connection);
+      return (-1);
+    }
+  }
+
+  db->connection = connection;
+  return (0);
+} /* }}} int cdbi_connect_database */
+
+static int cdbi_read_database (user_data_t *ud) /* {{{ */
+{
+  cdbi_database_t *db = (cdbi_database_t *) ud->data;
+  size_t i;
+  int success;
+  int status;
+
+  unsigned int db_version;
+
+  status = cdbi_connect_database (db);
+  if (status != 0)
+    return (status);
+  assert (db->connection != NULL);
+
+  db_version = dbi_conn_get_engine_version (db->connection);
+  /* TODO: Complain if `db_version == 0' */
+
+  success = 0;
+  for (i = 0; i < db->queries_num; i++)
+  {
+    /* Check if we know the database's version and if so, if this query applies
+     * to that version. */
+    if ((db_version != 0)
+        && (udb_query_check_version (db->queries[i], db_version) == 0))
+      continue;
+
+    status = cdbi_read_database_query (db,
+        db->queries[i], db->q_prep_areas[i]);
+    if (status == 0)
+      success++;
+  }
+
+  if (success == 0)
+  {
+    ERROR ("dbi plugin: All queries failed for database `%s'.", db->name);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cdbi_read_database */
+
+static int cdbi_shutdown (void) /* {{{ */
+{
+  size_t i;
+
+  for (i = 0; i < databases_num; i++)
+  {
+    if (databases[i]->connection != NULL)
+    {
+      dbi_conn_close (databases[i]->connection);
+      databases[i]->connection = NULL;
+    }
+    cdbi_database_free (databases[i]);
+  }
+  sfree (databases);
+  databases_num = 0;
+
+  udb_query_free (queries, queries_num);
+  queries = NULL;
+  queries_num = 0;
+
+  return (0);
+} /* }}} int cdbi_shutdown */
+
+void module_register (void) /* {{{ */
+{
+  plugin_register_complex_config ("dbi", cdbi_config);
+  plugin_register_init ("dbi", cdbi_init);
+  plugin_register_shutdown ("dbi", cdbi_shutdown);
+} /* }}} void module_register */
+
+/*
+ * vim: shiftwidth=2 softtabstop=2 et fdm=marker
+ */
diff --git a/src/df.c b/src/df.c
new file mode 100644 (file)
index 0000000..a6fa526
--- /dev/null
+++ b/src/df.c
@@ -0,0 +1,375 @@
+/**
+ * collectd - src/df.c
+ * Copyright (C) 2005-2009  Florian octo Forster
+ * Copyright (C) 2009       Paul Sadauskas
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Paul Sadauskas <psadauskas at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_mount.h"
+#include "utils_ignorelist.h"
+
+#if HAVE_STATVFS
+# if HAVE_SYS_STATVFS_H
+#  include <sys/statvfs.h>
+# endif
+# define STATANYFS statvfs
+# define STATANYFS_STR "statvfs"
+# define BLOCKSIZE(s) ((s).f_frsize ? (s).f_frsize : (s).f_bsize)
+#elif HAVE_STATFS
+# if HAVE_SYS_STATFS_H
+#  include <sys/statfs.h>
+# endif
+# define STATANYFS statfs
+# define STATANYFS_STR "statfs"
+# define BLOCKSIZE(s) (s).f_bsize
+#else
+# error "No applicable input method."
+#endif
+
+static const char *config_keys[] =
+{
+       "Device",
+       "MountPoint",
+       "FSType",
+       "IgnoreSelected",
+       "ReportByDevice",
+       "ReportReserved",
+       "ReportInodes",
+       "ValuesAbsolute",
+       "ValuesPercentage"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *il_device = NULL;
+static ignorelist_t *il_mountpoint = NULL;
+static ignorelist_t *il_fstype = NULL;
+
+static _Bool by_device = 0;
+static _Bool report_inodes = 0;
+static _Bool values_absolute = 1;
+static _Bool values_percentage = 0;
+
+static int df_init (void)
+{
+       if (il_device == NULL)
+               il_device = ignorelist_create (1);
+       if (il_mountpoint == NULL)
+               il_mountpoint = ignorelist_create (1);
+       if (il_fstype == NULL)
+               il_fstype = ignorelist_create (1);
+
+       return (0);
+}
+
+static int df_config (const char *key, const char *value)
+{
+       df_init ();
+
+       if (strcasecmp (key, "Device") == 0)
+       {
+               if (ignorelist_add (il_device, value))
+                       return (1);
+               return (0);
+       }
+       else if (strcasecmp (key, "MountPoint") == 0)
+       {
+               if (ignorelist_add (il_mountpoint, value))
+                       return (1);
+               return (0);
+       }
+       else if (strcasecmp (key, "FSType") == 0)
+       {
+               if (ignorelist_add (il_fstype, value))
+                       return (1);
+               return (0);
+       }
+       else if (strcasecmp (key, "IgnoreSelected") == 0)
+       {
+               if (IS_TRUE (value))
+               {
+                       ignorelist_set_invert (il_device, 0);
+                       ignorelist_set_invert (il_mountpoint, 0);
+                       ignorelist_set_invert (il_fstype, 0);
+               }
+               else
+               {
+                       ignorelist_set_invert (il_device, 1);
+                       ignorelist_set_invert (il_mountpoint, 1);
+                       ignorelist_set_invert (il_fstype, 1);
+               }
+               return (0);
+       }
+       else if (strcasecmp (key, "ReportByDevice") == 0)
+       {
+               if (IS_TRUE (value))
+                       by_device = 1;
+
+               return (0);
+       }
+       else if (strcasecmp (key, "ReportInodes") == 0)
+       {
+               if (IS_TRUE (value))
+                       report_inodes = 1;
+               else
+                       report_inodes = 0;
+
+               return (0);
+       }
+       else if (strcasecmp (key, "ValuesAbsolute") == 0)
+       {
+               if (IS_TRUE (value))
+                       values_absolute = 1;
+               else
+                       values_absolute = 0;
+
+               return (0);
+       }
+       else if (strcasecmp (key, "ValuesPercentage") == 0)
+       {
+               if (IS_TRUE (value))
+                       values_percentage = 1;
+               else
+                       values_percentage = 0;
+
+               return (0);
+       }
+
+       return (-1);
+}
+
+__attribute__ ((nonnull(2)))
+static void df_submit_one (char *plugin_instance,
+               const char *type, const char *type_instance,
+               gauge_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "df", sizeof (vl.plugin));
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance,
+                               sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance,
+                               sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void df_submit_one */
+
+static int df_read (void)
+{
+#if HAVE_STATVFS
+       struct statvfs statbuf;
+#elif HAVE_STATFS
+       struct statfs statbuf;
+#endif
+       /* struct STATANYFS statbuf; */
+       cu_mount_t *mnt_list;
+       cu_mount_t *mnt_ptr;
+
+       mnt_list = NULL;
+       if (cu_mount_getlist (&mnt_list) == NULL)
+       {
+               ERROR ("df plugin: cu_mount_getlist failed.");
+               return (-1);
+       }
+
+       for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
+       {
+               unsigned long long blocksize;
+               char disk_name[256];
+               uint64_t blk_free;
+               uint64_t blk_reserved;
+               uint64_t blk_used;
+
+               if (ignorelist_match (il_device,
+                                       (mnt_ptr->spec_device != NULL)
+                                       ? mnt_ptr->spec_device
+                                       : mnt_ptr->device))
+                       continue;
+               if (ignorelist_match (il_mountpoint, mnt_ptr->dir))
+                       continue;
+               if (ignorelist_match (il_fstype, mnt_ptr->type))
+                       continue;
+
+               if (STATANYFS (mnt_ptr->dir, &statbuf) < 0)
+               {
+                       char errbuf[1024];
+                       ERROR (STATANYFS_STR"(%s) failed: %s",
+                                       mnt_ptr->dir,
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       continue;
+               }
+
+               if (!statbuf.f_blocks)
+                       continue;
+
+               if (by_device)
+               {
+                       /* eg, /dev/hda1  -- strip off the "/dev/" */
+                       if (strncmp (mnt_ptr->spec_device, "/dev/", strlen ("/dev/")) == 0)
+                               sstrncpy (disk_name, mnt_ptr->spec_device + strlen ("/dev/"), sizeof (disk_name));
+                       else
+                               sstrncpy (disk_name, mnt_ptr->spec_device, sizeof (disk_name));
+
+                       if (strlen(disk_name) < 1)
+                       {
+                               DEBUG("df: no device name for mountpoint %s, skipping", mnt_ptr->dir);
+                               continue;
+                       }
+               }
+               else
+               {
+                       if (strcmp (mnt_ptr->dir, "/") == 0)
+                       {
+                               if (strcmp (mnt_ptr->type, "rootfs") == 0)
+                                       continue;
+                               sstrncpy (disk_name, "root", sizeof (disk_name));
+                       }
+                       else
+                       {
+                               int i, len;
+
+                               sstrncpy (disk_name, mnt_ptr->dir + 1, sizeof (disk_name));
+                               len = strlen (disk_name);
+
+                               for (i = 0; i < len; i++)
+                                       if (disk_name[i] == '/')
+                                               disk_name[i] = '-';
+                       }
+               }
+
+               blocksize = BLOCKSIZE(statbuf);
+
+               /*
+                * Sanity-check for the values in the struct
+                */
+               /* Check for negative "available" byes. For example UFS can
+                * report negative free space for user. Notice. blk_reserved
+                * will start to diminish after this. */
+#if HAVE_STATVFS
+               /* Cast and temporary variable are needed to avoid
+                * compiler warnings.
+                * ((struct statvfs).f_bavail is unsigned (POSIX)) */
+               int64_t signed_bavail = (int64_t) statbuf.f_bavail;
+               if (signed_bavail < 0)
+                       statbuf.f_bavail = 0;
+#elif HAVE_STATFS
+               if (statbuf.f_bavail < 0)
+                       statbuf.f_bavail = 0;
+#endif
+               /* Make sure that f_blocks >= f_bfree >= f_bavail */
+               if (statbuf.f_bfree < statbuf.f_bavail)
+                       statbuf.f_bfree = statbuf.f_bavail;
+               if (statbuf.f_blocks < statbuf.f_bfree)
+                       statbuf.f_blocks = statbuf.f_bfree;
+
+               blk_free     = (uint64_t) statbuf.f_bavail;
+               blk_reserved = (uint64_t) (statbuf.f_bfree - statbuf.f_bavail);
+               blk_used     = (uint64_t) (statbuf.f_blocks - statbuf.f_bfree);
+
+               if (values_absolute)
+               {
+                       df_submit_one (disk_name, "df_complex", "free",
+                               (gauge_t) (blk_free * blocksize));
+                       df_submit_one (disk_name, "df_complex", "reserved",
+                               (gauge_t) (blk_reserved * blocksize));
+                       df_submit_one (disk_name, "df_complex", "used",
+                               (gauge_t) (blk_used * blocksize));
+               }
+
+               if (values_percentage)
+               {
+                       if (statbuf.f_blocks > 0)
+                               {
+                               df_submit_one (disk_name, "percent_bytes", "free",
+                                       (gauge_t) ((float_t)(blk_free) / statbuf.f_blocks * 100));
+                               df_submit_one (disk_name, "percent_bytes", "reserved",
+                                       (gauge_t) ((float_t)(blk_reserved) / statbuf.f_blocks * 100));
+                               df_submit_one (disk_name, "percent_bytes", "used",
+                                       (gauge_t) ((float_t)(blk_used) / statbuf.f_blocks * 100));
+                               }
+                       else return (-1);
+               }
+
+               /* inode handling */
+               if (report_inodes)
+               {
+                       uint64_t inode_free;
+                       uint64_t inode_reserved;
+                       uint64_t inode_used;
+
+                       /* Sanity-check for the values in the struct */
+                       if (statbuf.f_ffree < statbuf.f_favail)
+                               statbuf.f_ffree = statbuf.f_favail;
+                       if (statbuf.f_files < statbuf.f_ffree)
+                               statbuf.f_files = statbuf.f_ffree;
+
+                       inode_free = (uint64_t) statbuf.f_favail;
+                       inode_reserved = (uint64_t) (statbuf.f_ffree - statbuf.f_favail);
+                       inode_used = (uint64_t) (statbuf.f_files - statbuf.f_ffree);
+
+                       if (values_percentage)
+                       {
+                               if (statbuf.f_files > 0)
+                               {
+                                       df_submit_one (disk_name, "percent_inodes", "free",
+                                               (gauge_t) ((float_t)(inode_free) / statbuf.f_files * 100));
+                                       df_submit_one (disk_name, "percent_inodes", "reserved",
+                                               (gauge_t) ((float_t)(inode_reserved) / statbuf.f_files * 100));
+                                       df_submit_one (disk_name, "percent_inodes", "used",
+                                               (gauge_t) ((float_t)(inode_used) / statbuf.f_files * 100));
+                               }
+                               else return (-1);
+                       }
+                       if (values_absolute)
+                       {
+                               df_submit_one (disk_name, "df_inodes", "free",
+                                               (gauge_t) inode_free);
+                               df_submit_one (disk_name, "df_inodes", "reserved",
+                                               (gauge_t) inode_reserved);
+                               df_submit_one (disk_name, "df_inodes", "used",
+                                               (gauge_t) inode_used);
+                       }
+               }
+       }
+
+       cu_mount_freelist (mnt_list);
+
+       return (0);
+} /* int df_read */
+
+void module_register (void)
+{
+       plugin_register_config ("df", df_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("df", df_init);
+       plugin_register_read ("df", df_read);
+} /* void module_register */
diff --git a/src/disk.c b/src/disk.c
new file mode 100644 (file)
index 0000000..8830403
--- /dev/null
@@ -0,0 +1,943 @@
+/**
+ * collectd - src/disk.c
+ * Copyright (C) 2005-2012  Florian octo Forster
+ * Copyright (C) 2009       Manuel Sanmartin
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Manuel Sanmartin
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#if HAVE_MACH_MACH_TYPES_H
+#  include <mach/mach_types.h>
+#endif
+#if HAVE_MACH_MACH_INIT_H
+#  include <mach/mach_init.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#if HAVE_MACH_MACH_PORT_H
+#  include <mach/mach_port.h>
+#endif
+#if HAVE_COREFOUNDATION_COREFOUNDATION_H
+#  include <CoreFoundation/CoreFoundation.h>
+#endif
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+#if HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDRIVER_H
+#  include <IOKit/storage/IOBlockStorageDriver.h>
+#endif
+#if HAVE_IOKIT_IOBSD_H
+#  include <IOKit/IOBSD.h>
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifndef UINT_MAX
+#  define UINT_MAX 4294967295U
+#endif
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
+
+#if HAVE_PERFSTAT
+# ifndef _AIXVERSION_610
+# include <sys/systemcfg.h>
+# endif
+# include <sys/protosw.h>
+# include <libperfstat.h>
+#endif
+
+#if HAVE_IOKIT_IOKITLIB_H
+static mach_port_t io_master_port = MACH_PORT_NULL;
+/* This defaults to false for backwards compatibility. Please fix in the next
+ * major version. */
+static _Bool use_bsd_name = 0;
+/* #endif HAVE_IOKIT_IOKITLIB_H */
+
+#elif KERNEL_LINUX
+typedef struct diskstats
+{
+       char *name;
+
+       /* This overflows in roughly 1361 years */
+       unsigned int poll_count;
+
+       derive_t read_sectors;
+       derive_t write_sectors;
+
+       derive_t read_bytes;
+       derive_t write_bytes;
+
+       derive_t read_ops;
+       derive_t write_ops;
+       derive_t read_time;
+       derive_t write_time;
+
+       derive_t avg_read_time;
+       derive_t avg_write_time;
+
+       struct diskstats *next;
+} diskstats_t;
+
+static diskstats_t *disklist;
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+#define MAX_NUMDISK 1024
+extern kstat_ctl_t *kc;
+static kstat_t *ksp[MAX_NUMDISK];
+static int numdisk = 0;
+/* #endif HAVE_LIBKSTAT */
+
+#elif defined(HAVE_LIBSTATGRAB)
+/* #endif HAVE_LIBKSTATGRAB */
+
+#elif HAVE_PERFSTAT
+static perfstat_disk_t * stat_disk;
+static int numdisk;
+static int pnumdisk;
+/* #endif HAVE_PERFSTAT */
+
+#else
+# error "No applicable input method."
+#endif
+
+#if HAVE_LIBUDEV
+#include <libudev.h>
+
+static char *conf_udev_name_attr = NULL;
+static struct udev *handle_udev;
+#endif
+
+static const char *config_keys[] =
+{
+       "Disk",
+       "UseBSDName",
+       "IgnoreSelected",
+       "UdevNameAttr"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+static int disk_config (const char *key, const char *value)
+{
+  if (ignorelist == NULL)
+    ignorelist = ignorelist_create (/* invert = */ 1);
+  if (ignorelist == NULL)
+    return (1);
+
+  if (strcasecmp ("Disk", key) == 0)
+  {
+    ignorelist_add (ignorelist, value);
+  }
+  else if (strcasecmp ("IgnoreSelected", key) == 0)
+  {
+    int invert = 1;
+    if (IS_TRUE (value))
+      invert = 0;
+    ignorelist_set_invert (ignorelist, invert);
+  }
+  else if (strcasecmp ("UseBSDName", key) == 0)
+  {
+#if HAVE_IOKIT_IOKITLIB_H
+    use_bsd_name = IS_TRUE (value) ? 1 : 0;
+#else
+    WARNING ("disk plugin: The \"UseBSDName\" option is only supported "
+        "on Mach / Mac OS X and will be ignored.");
+#endif
+  }
+  else if (strcasecmp ("UdevNameAttr", key) == 0)
+  {
+#if HAVE_LIBUDEV
+    if (conf_udev_name_attr != NULL)
+    {
+      free (conf_udev_name_attr);
+      conf_udev_name_attr = NULL;
+    }
+    if ((conf_udev_name_attr = strdup (value)) == NULL)
+      return (1);
+#else
+    WARNING ("disk plugin: The \"UdevNameAttr\" option is only supported "
+        "if collectd is built with libudev support");
+#endif
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int disk_config */
+
+static int disk_init (void)
+{
+#if HAVE_IOKIT_IOKITLIB_H
+       kern_return_t status;
+
+       if (io_master_port != MACH_PORT_NULL)
+       {
+               mach_port_deallocate (mach_task_self (),
+                               io_master_port);
+               io_master_port = MACH_PORT_NULL;
+       }
+
+       status = IOMasterPort (MACH_PORT_NULL, &io_master_port);
+       if (status != kIOReturnSuccess)
+       {
+               ERROR ("IOMasterPort failed: %s",
+                               mach_error_string (status));
+               io_master_port = MACH_PORT_NULL;
+               return (-1);
+       }
+/* #endif HAVE_IOKIT_IOKITLIB_H */
+
+#elif KERNEL_LINUX
+       /* do nothing */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+       kstat_t *ksp_chain;
+
+       numdisk = 0;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (numdisk = 0, ksp_chain = kc->kc_chain;
+                       (numdisk < MAX_NUMDISK) && (ksp_chain != NULL);
+                       ksp_chain = ksp_chain->ks_next)
+       {
+               if (strncmp (ksp_chain->ks_class, "disk", 4)
+                               && strncmp (ksp_chain->ks_class, "partition", 9))
+                       continue;
+               if (ksp_chain->ks_type != KSTAT_TYPE_IO)
+                       continue;
+               ksp[numdisk++] = ksp_chain;
+       }
+#endif /* HAVE_LIBKSTAT */
+
+       return (0);
+} /* int disk_init */
+
+static void disk_submit (const char *plugin_instance,
+               const char *type,
+               derive_t read, derive_t write)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       /* Both `ignorelist' and `plugin_instance' may be NULL. */
+       if (ignorelist_match (ignorelist, plugin_instance) != 0)
+         return;
+
+       values[0].derive = read;
+       values[1].derive = write;
+
+       vl.values = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void disk_submit */
+
+#if KERNEL_LINUX
+static void submit_in_progress (char const *disk_name, gauge_t in_progress)
+{
+       value_t v;
+       value_list_t vl = VALUE_LIST_INIT;
+
+       if (ignorelist_match (ignorelist, disk_name) != 0)
+         return;
+
+       v.gauge = in_progress;
+
+       vl.values = &v;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, disk_name, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "pending_operations", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       if (ignorelist_match (ignorelist, plugin_instance) != 0)
+         return;
+
+       values[0].derive = io_time;
+       values[1].derive = weighted_time;
+
+       vl.values = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "disk", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "disk_io_time", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+
+static counter_t disk_calc_time_incr (counter_t delta_time, counter_t delta_ops)
+{
+       double interval = CDTIME_T_TO_DOUBLE (plugin_get_interval ());
+       double avg_time = ((double) delta_time) / ((double) delta_ops);
+       double avg_time_incr = interval * avg_time;
+
+       return ((counter_t) (avg_time_incr + .5));
+}
+#endif
+
+#if HAVE_LIBUDEV
+/**
+ * Attempt to provide an rename disk instance from an assigned udev attribute.
+ *
+ * On success, it returns a strduped char* to the desired attribute value.
+ * Otherwise it returns NULL.
+ */
+
+static char *disk_udev_attr_name (struct udev *udev, char *disk_name, const char *attr)
+{
+       struct udev_device *dev;
+       const char *prop;
+       char *output = NULL;
+
+       dev = udev_device_new_from_subsystem_sysname (udev, "block", disk_name);
+       if (dev != NULL)
+       {
+               prop = udev_device_get_property_value (dev, attr);
+               if (prop) {
+                       output = strdup (prop);
+                       DEBUG ("disk plugin: renaming %s => %s", disk_name, output);
+               }
+               udev_device_unref (dev);
+       }
+       return output;
+}
+#endif
+
+#if HAVE_IOKIT_IOKITLIB_H
+static signed long long dict_get_value (CFDictionaryRef dict, const char *key)
+{
+       signed long long val_int;
+       CFNumberRef      val_obj;
+       CFStringRef      key_obj;
+
+       /* `key_obj' needs to be released. */
+       key_obj = CFStringCreateWithCString (kCFAllocatorDefault, key,
+                       kCFStringEncodingASCII);
+       if (key_obj == NULL)
+       {
+               DEBUG ("CFStringCreateWithCString (%s) failed.", key);
+               return (-1LL);
+       }
+       
+       /* get => we don't need to release (== free) the object */
+       val_obj = (CFNumberRef) CFDictionaryGetValue (dict, key_obj);
+
+       CFRelease (key_obj);
+
+       if (val_obj == NULL)
+       {
+               DEBUG ("CFDictionaryGetValue (%s) failed.", key);
+               return (-1LL);
+       }
+
+       if (!CFNumberGetValue (val_obj, kCFNumberSInt64Type, &val_int))
+       {
+               DEBUG ("CFNumberGetValue (%s) failed.", key);
+               return (-1LL);
+       }
+
+       return (val_int);
+}
+#endif /* HAVE_IOKIT_IOKITLIB_H */
+
+static int disk_read (void)
+{
+#if HAVE_IOKIT_IOKITLIB_H
+       io_registry_entry_t     disk;
+       io_registry_entry_t     disk_child;
+       io_iterator_t           disk_list;
+       CFDictionaryRef         props_dict;
+       CFDictionaryRef         stats_dict;
+       CFDictionaryRef         child_dict;
+       CFStringRef             tmp_cf_string_ref;
+       kern_return_t           status;
+
+       signed long long read_ops;
+       signed long long read_byt;
+       signed long long read_tme;
+       signed long long write_ops;
+       signed long long write_byt;
+       signed long long write_tme;
+
+       int  disk_major;
+       int  disk_minor;
+       char disk_name[DATA_MAX_NAME_LEN];
+       char disk_name_bsd[DATA_MAX_NAME_LEN];
+
+       /* Get the list of all disk objects. */
+       if (IOServiceGetMatchingServices (io_master_port,
+                               IOServiceMatching (kIOBlockStorageDriverClass),
+                               &disk_list) != kIOReturnSuccess)
+       {
+               ERROR ("disk plugin: IOServiceGetMatchingServices failed.");
+               return (-1);
+       }
+
+       while ((disk = IOIteratorNext (disk_list)) != 0)
+       {
+               props_dict = NULL;
+               stats_dict = NULL;
+               child_dict = NULL;
+
+               /* `disk_child' must be released */
+               if ((status = IORegistryEntryGetChildEntry (disk, kIOServicePlane, &disk_child))
+                               != kIOReturnSuccess)
+               {
+                       /* This fails for example for DVD/CD drives.. */
+                       DEBUG ("IORegistryEntryGetChildEntry (disk) failed: 0x%08x", status);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+
+               /* We create `props_dict' => we need to release it later */
+               if (IORegistryEntryCreateCFProperties (disk,
+                                       (CFMutableDictionaryRef *) &props_dict,
+                                       kCFAllocatorDefault,
+                                       kNilOptions)
+                               != kIOReturnSuccess)
+               {
+                       ERROR ("disk-plugin: IORegistryEntryCreateCFProperties failed.");
+                       IOObjectRelease (disk_child);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+
+               if (props_dict == NULL)
+               {
+                       DEBUG ("IORegistryEntryCreateCFProperties (disk) failed.");
+                       IOObjectRelease (disk_child);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+
+               /* tmp_cf_string_ref doesn't need to be released. */
+               tmp_cf_string_ref = (CFStringRef) CFDictionaryGetValue (props_dict,
+                               CFSTR(kIOBSDNameKey));
+               if (!tmp_cf_string_ref)
+               {
+                       DEBUG ("disk plugin: CFDictionaryGetValue("
+                                       "kIOBSDNameKey) failed.");
+                       CFRelease (props_dict);
+                       IOObjectRelease (disk_child);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+               assert (CFGetTypeID (tmp_cf_string_ref) == CFStringGetTypeID ());
+
+               memset (disk_name_bsd, 0, sizeof (disk_name_bsd));
+               CFStringGetCString (tmp_cf_string_ref,
+                               disk_name_bsd, sizeof (disk_name_bsd),
+                               kCFStringEncodingUTF8);
+               if (disk_name_bsd[0] == 0)
+               {
+                       ERROR ("disk plugin: CFStringGetCString() failed.");
+                       CFRelease (props_dict);
+                       IOObjectRelease (disk_child);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+               DEBUG ("disk plugin: disk_name_bsd = \"%s\"", disk_name_bsd);
+
+               stats_dict = (CFDictionaryRef) CFDictionaryGetValue (props_dict,
+                               CFSTR (kIOBlockStorageDriverStatisticsKey));
+
+               if (stats_dict == NULL)
+               {
+                       DEBUG ("disk plugin: CFDictionaryGetValue ("
+                                       "%s) failed.",
+                                       kIOBlockStorageDriverStatisticsKey);
+                       CFRelease (props_dict);
+                       IOObjectRelease (disk_child);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+
+               if (IORegistryEntryCreateCFProperties (disk_child,
+                                       (CFMutableDictionaryRef *) &child_dict,
+                                       kCFAllocatorDefault,
+                                       kNilOptions)
+                               != kIOReturnSuccess)
+               {
+                       DEBUG ("disk plugin: IORegistryEntryCreateCFProperties ("
+                                       "disk_child) failed.");
+                       IOObjectRelease (disk_child);
+                       CFRelease (props_dict);
+                       IOObjectRelease (disk);
+                       continue;
+               }
+
+               /* kIOBSDNameKey */
+               disk_major = (int) dict_get_value (child_dict,
+                               kIOBSDMajorKey);
+               disk_minor = (int) dict_get_value (child_dict,
+                               kIOBSDMinorKey);
+               read_ops  = dict_get_value (stats_dict,
+                               kIOBlockStorageDriverStatisticsReadsKey);
+               read_byt  = dict_get_value (stats_dict,
+                               kIOBlockStorageDriverStatisticsBytesReadKey);
+               read_tme  = dict_get_value (stats_dict,
+                               kIOBlockStorageDriverStatisticsTotalReadTimeKey);
+               write_ops = dict_get_value (stats_dict,
+                               kIOBlockStorageDriverStatisticsWritesKey);
+               write_byt = dict_get_value (stats_dict,
+                               kIOBlockStorageDriverStatisticsBytesWrittenKey);
+               /* This property describes the number of nanoseconds spent
+                * performing writes since the block storage driver was
+                * instantiated. It is one of the statistic entries listed
+                * under the top-level kIOBlockStorageDriverStatisticsKey
+                * property table. It has an OSNumber value. */
+               write_tme = dict_get_value (stats_dict,
+                               kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
+
+               if (use_bsd_name)
+                       sstrncpy (disk_name, disk_name_bsd, sizeof (disk_name));
+               else
+                       ssnprintf (disk_name, sizeof (disk_name), "%i-%i",
+                                       disk_major, disk_minor);
+               DEBUG ("disk plugin: disk_name = \"%s\"", disk_name);
+
+               if ((read_byt != -1LL) || (write_byt != -1LL))
+                       disk_submit (disk_name, "disk_octets", read_byt, write_byt);
+               if ((read_ops != -1LL) || (write_ops != -1LL))
+                       disk_submit (disk_name, "disk_ops", read_ops, write_ops);
+               if ((read_tme != -1LL) || (write_tme != -1LL))
+                       disk_submit (disk_name, "disk_time",
+                                       read_tme / 1000,
+                                       write_tme / 1000);
+
+               CFRelease (child_dict);
+               IOObjectRelease (disk_child);
+               CFRelease (props_dict);
+               IOObjectRelease (disk);
+       }
+       IOObjectRelease (disk_list);
+/* #endif HAVE_IOKIT_IOKITLIB_H */
+
+#elif KERNEL_LINUX
+       FILE *fh;
+       char buffer[1024];
+       
+       char *fields[32];
+       int numfields;
+       int fieldshift = 0;
+
+       int minor = 0;
+
+       derive_t read_sectors  = 0;
+       derive_t write_sectors = 0;
+
+       derive_t read_ops      = 0;
+       derive_t read_merged   = 0;
+       derive_t read_time     = 0;
+       derive_t write_ops     = 0;
+       derive_t write_merged  = 0;
+       derive_t write_time    = 0;
+       gauge_t in_progress    = NAN;
+       derive_t io_time       = 0;
+       derive_t weighted_time = 0;
+       int is_disk = 0;
+
+       diskstats_t *ds, *pre_ds;
+
+       if ((fh = fopen ("/proc/diskstats", "r")) == NULL)
+       {
+               fh = fopen ("/proc/partitions", "r");
+               if (fh == NULL)
+               {
+                       ERROR ("disk plugin: fopen (/proc/{diskstats,partitions}) failed.");
+                       return (-1);
+               }
+
+               /* Kernel is 2.4.* */
+               fieldshift = 1;
+       }
+
+#if HAVE_LIBUDEV
+       handle_udev = udev_new();
+#endif
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               char *disk_name;
+               char *output_name;
+               char *alt_name;
+
+               numfields = strsplit (buffer, fields, 32);
+
+               if ((numfields != (14 + fieldshift)) && (numfields != 7))
+                       continue;
+
+               minor = atoll (fields[1]);
+
+               disk_name = fields[2 + fieldshift];
+
+               for (ds = disklist, pre_ds = disklist; ds != NULL; pre_ds = ds, ds = ds->next)
+                       if (strcmp (disk_name, ds->name) == 0)
+                               break;
+
+               if (ds == NULL)
+               {
+                       if ((ds = (diskstats_t *) calloc (1, sizeof (diskstats_t))) == NULL)
+                               continue;
+
+                       if ((ds->name = strdup (disk_name)) == NULL)
+                       {
+                               free (ds);
+                               continue;
+                       }
+
+                       if (pre_ds == NULL)
+                               disklist = ds;
+                       else
+                               pre_ds->next = ds;
+               }
+
+               is_disk = 0;
+               if (numfields == 7)
+               {
+                       /* Kernel 2.6, Partition */
+                       read_ops      = atoll (fields[3]);
+                       read_sectors  = atoll (fields[4]);
+                       write_ops     = atoll (fields[5]);
+                       write_sectors = atoll (fields[6]);
+               }
+               else if (numfields == (14 + fieldshift))
+               {
+                       read_ops  =  atoll (fields[3 + fieldshift]);
+                       write_ops =  atoll (fields[7 + fieldshift]);
+
+                       read_sectors  = atoll (fields[5 + fieldshift]);
+                       write_sectors = atoll (fields[9 + fieldshift]);
+
+                       if ((fieldshift == 0) || (minor == 0))
+                       {
+                               is_disk = 1;
+                               read_merged  = atoll (fields[4 + fieldshift]);
+                               read_time    = atoll (fields[6 + fieldshift]);
+                               write_merged = atoll (fields[8 + fieldshift]);
+                               write_time   = atoll (fields[10+ fieldshift]);
+
+                               in_progress = atof (fields[11 + fieldshift]);
+
+                               io_time       = atof (fields[12 + fieldshift]);
+                               weighted_time = atof (fields[13 + fieldshift]);
+                       }
+               }
+               else
+               {
+                       DEBUG ("numfields = %i; => unknown file format.", numfields);
+                       continue;
+               }
+
+               {
+                       derive_t diff_read_sectors;
+                       derive_t diff_write_sectors;
+
+               /* If the counter wraps around, it's only 32 bits.. */
+                       if (read_sectors < ds->read_sectors)
+                               diff_read_sectors = 1 + read_sectors
+                                       + (UINT_MAX - ds->read_sectors);
+                       else
+                               diff_read_sectors = read_sectors - ds->read_sectors;
+                       if (write_sectors < ds->write_sectors)
+                               diff_write_sectors = 1 + write_sectors
+                                       + (UINT_MAX - ds->write_sectors);
+                       else
+                               diff_write_sectors = write_sectors - ds->write_sectors;
+
+                       ds->read_bytes += 512 * diff_read_sectors;
+                       ds->write_bytes += 512 * diff_write_sectors;
+                       ds->read_sectors = read_sectors;
+                       ds->write_sectors = write_sectors;
+               }
+
+               /* Calculate the average time an io-op needs to complete */
+               if (is_disk)
+               {
+                       derive_t diff_read_ops;
+                       derive_t diff_write_ops;
+                       derive_t diff_read_time;
+                       derive_t diff_write_time;
+
+                       if (read_ops < ds->read_ops)
+                               diff_read_ops = 1 + read_ops
+                                       + (UINT_MAX - ds->read_ops);
+                       else
+                               diff_read_ops = read_ops - ds->read_ops;
+                       DEBUG ("disk plugin: disk_name = %s; read_ops = %"PRIi64"; "
+                                       "ds->read_ops = %"PRIi64"; diff_read_ops = %"PRIi64";",
+                                       disk_name,
+                                       read_ops, ds->read_ops, diff_read_ops);
+
+                       if (write_ops < ds->write_ops)
+                               diff_write_ops = 1 + write_ops
+                                       + (UINT_MAX - ds->write_ops);
+                       else
+                               diff_write_ops = write_ops - ds->write_ops;
+
+                       if (read_time < ds->read_time)
+                               diff_read_time = 1 + read_time
+                                       + (UINT_MAX - ds->read_time);
+                       else
+                               diff_read_time = read_time - ds->read_time;
+
+                       if (write_time < ds->write_time)
+                               diff_write_time = 1 + write_time
+                                       + (UINT_MAX - ds->write_time);
+                       else
+                               diff_write_time = write_time - ds->write_time;
+
+                       if (diff_read_ops != 0)
+                               ds->avg_read_time += disk_calc_time_incr (
+                                               diff_read_time, diff_read_ops);
+                       if (diff_write_ops != 0)
+                               ds->avg_write_time += disk_calc_time_incr (
+                                               diff_write_time, diff_write_ops);
+
+                       ds->read_ops = read_ops;
+                       ds->read_time = read_time;
+                       ds->write_ops = write_ops;
+                       ds->write_time = write_time;
+               } /* if (is_disk) */
+
+               /* Don't write to the RRDs if we've just started.. */
+               ds->poll_count++;
+               if (ds->poll_count <= 2)
+               {
+                       DEBUG ("disk plugin: (ds->poll_count = %i) <= "
+                                       "(min_poll_count = 2); => Not writing.",
+                                       ds->poll_count);
+                       continue;
+               }
+
+               if ((read_ops == 0) && (write_ops == 0))
+               {
+                       DEBUG ("disk plugin: ((read_ops == 0) && "
+                                       "(write_ops == 0)); => Not writing.");
+                       continue;
+               }
+
+               output_name = disk_name;
+
+#if HAVE_LIBUDEV
+               alt_name = disk_udev_attr_name (handle_udev, disk_name,
+                               conf_udev_name_attr);
+#else
+               alt_name = NULL;
+#endif
+               if (alt_name != NULL)
+                       output_name = alt_name;
+
+               if ((ds->read_bytes != 0) || (ds->write_bytes != 0))
+                       disk_submit (output_name, "disk_octets",
+                                       ds->read_bytes, ds->write_bytes);
+
+               if ((ds->read_ops != 0) || (ds->write_ops != 0))
+                       disk_submit (output_name, "disk_ops",
+                                       read_ops, write_ops);
+
+               if ((ds->avg_read_time != 0) || (ds->avg_write_time != 0))
+                       disk_submit (output_name, "disk_time",
+                                       ds->avg_read_time, ds->avg_write_time);
+
+               if (is_disk)
+               {
+                       disk_submit (output_name, "disk_merged",
+                                       read_merged, write_merged);
+                       submit_in_progress (output_name, in_progress);
+                       submit_io_time (output_name, io_time, weighted_time);
+               } /* if (is_disk) */
+
+               /* release udev-based alternate name, if allocated */
+               free(alt_name);
+       } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
+
+#if HAVE_LIBUDEV
+       udev_unref(handle_udev);
+#endif
+
+       fclose (fh);
+/* #endif defined(KERNEL_LINUX) */
+
+#elif HAVE_LIBKSTAT
+# if HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_NWRITES && HAVE_KSTAT_IO_T_WTIME
+#  define KIO_ROCTETS reads
+#  define KIO_WOCTETS writes
+#  define KIO_ROPS    nreads
+#  define KIO_WOPS    nwrites
+#  define KIO_RTIME   rtime
+#  define KIO_WTIME   wtime
+# elif HAVE_KSTAT_IO_T_NWRITTEN && HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_WTIME
+#  define KIO_ROCTETS nread
+#  define KIO_WOCTETS nwritten
+#  define KIO_ROPS    reads
+#  define KIO_WOPS    writes
+#  define KIO_RTIME   rtime
+#  define KIO_WTIME   wtime
+# else
+#  error "kstat_io_t does not have the required members"
+# endif
+       static kstat_io_t kio;
+       int i;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (i = 0; i < numdisk; i++)
+       {
+               if (kstat_read (kc, ksp[i], &kio) == -1)
+                       continue;
+
+               if (strncmp (ksp[i]->ks_class, "disk", 4) == 0)
+               {
+                       disk_submit (ksp[i]->ks_name, "disk_octets",
+                                       kio.KIO_ROCTETS, kio.KIO_WOCTETS);
+                       disk_submit (ksp[i]->ks_name, "disk_ops",
+                                       kio.KIO_ROPS, kio.KIO_WOPS);
+                       /* FIXME: Convert this to microseconds if necessary */
+                       disk_submit (ksp[i]->ks_name, "disk_time",
+                                       kio.KIO_RTIME, kio.KIO_WTIME);
+               }
+               else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0)
+               {
+                       disk_submit (ksp[i]->ks_name, "disk_octets",
+                                       kio.KIO_ROCTETS, kio.KIO_WOCTETS);
+                       disk_submit (ksp[i]->ks_name, "disk_ops",
+                                       kio.KIO_ROPS, kio.KIO_WOPS);
+               }
+       }
+/* #endif defined(HAVE_LIBKSTAT) */
+
+#elif defined(HAVE_LIBSTATGRAB)
+       sg_disk_io_stats *ds;
+# if HAVE_LIBSTATGRAB_0_90
+       size_t disks;
+# else
+       int disks;
+#endif
+       int counter;
+       char name[DATA_MAX_NAME_LEN];
+       
+       if ((ds = sg_get_disk_io_stats(&disks)) == NULL)
+               return (0);
+               
+       for (counter=0; counter < disks; counter++) {
+               strncpy(name, ds->disk_name, sizeof(name));
+               name[sizeof(name)-1] = '\0'; /* strncpy doesn't terminate longer strings */
+               disk_submit (name, "disk_octets", ds->read_bytes, ds->write_bytes);
+               ds++;
+       }
+/* #endif defined(HAVE_LIBSTATGRAB) */
+
+#elif defined(HAVE_PERFSTAT)
+       derive_t read_sectors;
+       derive_t write_sectors;
+       derive_t read_time;
+       derive_t write_time;
+       derive_t read_ops;
+       derive_t write_ops;
+       perfstat_id_t firstpath;
+       int rnumdisk;
+       int i;
+
+       if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0) 
+       {
+               char errbuf[1024];
+               WARNING ("disk plugin: perfstat_disk: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       if (numdisk != pnumdisk || stat_disk==NULL) {
+               if (stat_disk!=NULL) 
+                       free(stat_disk);
+               stat_disk = (perfstat_disk_t *)calloc(numdisk, sizeof(perfstat_disk_t));
+       } 
+       pnumdisk = numdisk;
+
+       firstpath.name[0]='\0';
+       if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0) 
+       {
+               char errbuf[1024];
+               WARNING ("disk plugin: perfstat_disk : %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       for (i = 0; i < rnumdisk; i++) 
+       {
+               read_sectors = stat_disk[i].rblks*stat_disk[i].bsize;
+               write_sectors = stat_disk[i].wblks*stat_disk[i].bsize;
+               disk_submit (stat_disk[i].name, "disk_octets", read_sectors, write_sectors);
+
+               read_ops = stat_disk[i].xrate;
+               write_ops = stat_disk[i].xfers - stat_disk[i].xrate;
+               disk_submit (stat_disk[i].name, "disk_ops", read_ops, write_ops);
+
+               read_time = stat_disk[i].rserv;
+               read_time *= ((double)(_system_configuration.Xint)/(double)(_system_configuration.Xfrac)) / 1000000.0;
+               write_time = stat_disk[i].wserv;
+               write_time *= ((double)(_system_configuration.Xint)/(double)(_system_configuration.Xfrac)) / 1000000.0;
+               disk_submit (stat_disk[i].name, "disk_time", read_time, write_time);
+       }
+#endif /* defined(HAVE_PERFSTAT) */
+
+       return (0);
+} /* int disk_read */
+
+void module_register (void)
+{
+  plugin_register_config ("disk", disk_config,
+      config_keys, config_keys_num);
+  plugin_register_init ("disk", disk_init);
+  plugin_register_read ("disk", disk_read);
+} /* void module_register */
diff --git a/src/dns.c b/src/dns.c
new file mode 100644 (file)
index 0000000..fd75dc9
--- /dev/null
+++ b/src/dns.c
@@ -0,0 +1,464 @@
+/**
+ * collectd - src/dns.c
+ * Copyright (C) 2006-2011  Florian octo Forster
+ * Copyright (C) 2009       Mirko Buffoni
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Mirko Buffoni <briareos at eswat.org>
+ **/
+
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include "utils_dns.h"
+#include <pthread.h>
+#include <poll.h>
+
+#include <pcap.h>
+#include <pcap-bpf.h>
+
+/*
+ * Private data types
+ */
+struct counter_list_s
+{
+       unsigned int key;
+       unsigned int value;
+       struct counter_list_s *next;
+};
+typedef struct counter_list_s counter_list_t;
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+       "Interface",
+       "IgnoreSource",
+       "SelectNumericQueryTypes"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+static int select_numeric_qtype = 1;
+
+#define PCAP_SNAPLEN 1460
+static char   *pcap_device = NULL;
+
+static derive_t       tr_queries;
+static derive_t       tr_responses;
+static counter_list_t *qtype_list;
+static counter_list_t *opcode_list;
+static counter_list_t *rcode_list;
+
+static pthread_t       listen_thread;
+static int             listen_thread_init = 0;
+/* The `traffic' mutex if for `tr_queries' and `tr_responses' */
+static pthread_mutex_t traffic_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t qtype_mutex   = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t opcode_mutex  = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t rcode_mutex   = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Private functions
+ */
+static counter_list_t *counter_list_search (counter_list_t **list, unsigned int key)
+{
+       counter_list_t *entry;
+
+       for (entry = *list; entry != NULL; entry = entry->next)
+               if (entry->key == key)
+                       break;
+
+       return (entry);
+}
+
+static counter_list_t *counter_list_create (counter_list_t **list,
+               unsigned int key, unsigned int value)
+{
+       counter_list_t *entry;
+
+       entry = (counter_list_t *) malloc (sizeof (counter_list_t));
+       if (entry == NULL)
+               return (NULL);
+
+       memset (entry, 0, sizeof (counter_list_t));
+       entry->key = key;
+       entry->value = value;
+
+       if (*list == NULL)
+       {
+               *list = entry;
+       }
+       else
+       {
+               counter_list_t *last;
+
+               last = *list;
+               while (last->next != NULL)
+                       last = last->next;
+
+               last->next = entry;
+       }
+
+       return (entry);
+}
+
+static void counter_list_add (counter_list_t **list,
+               unsigned int key, unsigned int increment)
+{
+       counter_list_t *entry;
+
+       entry = counter_list_search (list, key);
+
+       if (entry != NULL)
+       {
+               entry->value += increment;
+       }
+       else
+       {
+               counter_list_create (list, key, increment);
+       }
+}
+
+static int dns_config (const char *key, const char *value)
+{
+       if (strcasecmp (key, "Interface") == 0)
+       {
+               if (pcap_device != NULL)
+                       free (pcap_device);
+               if ((pcap_device = strdup (value)) == NULL)
+                       return (1);
+       }
+       else if (strcasecmp (key, "IgnoreSource") == 0)
+       {
+               if (value != NULL)
+                       ignore_list_add_name (value);
+       }
+       else if (strcasecmp (key, "SelectNumericQueryTypes") == 0)
+       {
+               if ((value != NULL) && IS_FALSE (value))
+                       select_numeric_qtype = 0;
+               else
+                       select_numeric_qtype = 1;
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+}
+
+static void dns_child_callback (const rfc1035_header_t *dns)
+{
+       if (dns->qr == 0)
+       {
+               /* This is a query */
+               int skip = 0;
+               if (!select_numeric_qtype)
+               {
+                       const char *str = qtype_str(dns->qtype);
+                       if ((str == NULL) || (str[0] == '#'))
+                               skip = 1;
+               }
+
+               pthread_mutex_lock (&traffic_mutex);
+               tr_queries += dns->length;
+               pthread_mutex_unlock (&traffic_mutex);
+
+               if (skip == 0)
+               {
+                       pthread_mutex_lock (&qtype_mutex);
+                       counter_list_add (&qtype_list, dns->qtype,  1);
+                       pthread_mutex_unlock (&qtype_mutex);
+               }
+       }
+       else
+       {
+               /* This is a reply */
+               pthread_mutex_lock (&traffic_mutex);
+               tr_responses += dns->length;
+               pthread_mutex_unlock (&traffic_mutex);
+
+               pthread_mutex_lock (&rcode_mutex);
+               counter_list_add (&rcode_list,  dns->rcode,  1);
+               pthread_mutex_unlock (&rcode_mutex);
+       }
+
+       /* FIXME: Are queries, replies or both interesting? */
+       pthread_mutex_lock (&opcode_mutex);
+       counter_list_add (&opcode_list, dns->opcode, 1);
+       pthread_mutex_unlock (&opcode_mutex);
+}
+
+static int dns_run_pcap_loop (void)
+{
+       pcap_t *pcap_obj;
+       char    pcap_error[PCAP_ERRBUF_SIZE];
+       struct  bpf_program fp;
+
+       int status;
+
+       /* Don't block any signals */
+       {
+               sigset_t sigmask;
+               sigemptyset (&sigmask);
+               pthread_sigmask (SIG_SETMASK, &sigmask, NULL);
+       }
+
+       /* Passing `pcap_device == NULL' is okay and the same as passign "any" */
+       DEBUG ("dns plugin: Creating PCAP object..");
+       pcap_obj = pcap_open_live ((pcap_device != NULL) ? pcap_device : "any",
+                       PCAP_SNAPLEN,
+                       0 /* Not promiscuous */,
+                       (int) CDTIME_T_TO_MS (plugin_get_interval () / 2),
+                       pcap_error);
+       if (pcap_obj == NULL)
+       {
+               ERROR ("dns plugin: Opening interface `%s' "
+                               "failed: %s",
+                               (pcap_device != NULL) ? pcap_device : "any",
+                               pcap_error);
+               return (PCAP_ERROR);
+       }
+
+       memset (&fp, 0, sizeof (fp));
+       status = pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0);
+       if (status < 0)
+       {
+               ERROR ("dns plugin: pcap_compile failed: %s",
+                               pcap_statustostr (status));
+               return (status);
+       }
+
+       status = pcap_setfilter (pcap_obj, &fp);
+       if (status < 0)
+       {
+               ERROR ("dns plugin: pcap_setfilter failed: %s",
+                               pcap_statustostr (status));
+               return (status);
+       }
+
+       DEBUG ("dns plugin: PCAP object created.");
+
+       dnstop_set_pcap_obj (pcap_obj);
+       dnstop_set_callback (dns_child_callback);
+
+       status = pcap_loop (pcap_obj,
+                       -1 /* loop forever */,
+                       handle_pcap /* callback */,
+                       NULL /* user data */);
+       INFO ("dns plugin: pcap_loop exited with status %i.", status);
+       /* We need to handle "PCAP_ERROR" specially because libpcap currently
+        * doesn't return PCAP_ERROR_IFACE_NOT_UP for compatibility reasons. */
+       if (status == PCAP_ERROR)
+               status = PCAP_ERROR_IFACE_NOT_UP;
+
+       pcap_close (pcap_obj);
+       return (status);
+} /* int dns_run_pcap_loop */
+
+static int dns_sleep_one_interval (void) /* {{{ */
+{
+       cdtime_t interval;
+       struct timespec ts = { 0, 0 };
+       int status = 0;
+
+       interval = plugin_get_interval ();
+       CDTIME_T_TO_TIMESPEC (interval, &ts);
+
+       while (42)
+       {
+               struct timespec rem = { 0, 0 };
+
+               status = nanosleep (&ts, &rem);
+               if (status == 0)
+                       break;
+               else if ((errno == EINTR) || (errno == EAGAIN))
+               {
+                       ts = rem;
+                       continue;
+               }
+               else
+                       break;
+       }
+
+       return (status);
+} /* }}} int dns_sleep_one_interval */
+
+static void *dns_child_loop (__attribute__((unused)) void *dummy) /* {{{ */
+{
+       int status;
+
+       while (42)
+       {
+               status = dns_run_pcap_loop ();
+               if (status != PCAP_ERROR_IFACE_NOT_UP)
+                       break;
+
+               dns_sleep_one_interval ();
+       }
+
+       if (status != PCAP_ERROR_BREAK)
+               ERROR ("dns plugin: PCAP returned error %s.",
+                               pcap_statustostr (status));
+
+       listen_thread_init = 0;
+       return (NULL);
+} /* }}} void *dns_child_loop */
+
+static int dns_init (void)
+{
+       /* clean up an old thread */
+       int status;
+
+       pthread_mutex_lock (&traffic_mutex);
+       tr_queries   = 0;
+       tr_responses = 0;
+       pthread_mutex_unlock (&traffic_mutex);
+
+       if (listen_thread_init != 0)
+               return (-1);
+
+       status = plugin_thread_create (&listen_thread, NULL, dns_child_loop,
+                       (void *) 0);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("dns plugin: pthread_create failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       listen_thread_init = 1;
+
+       return (0);
+} /* int dns_init */
+
+static void submit_derive (const char *type, const char *type_instance,
+               derive_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void submit_derive */
+
+static void submit_octets (derive_t queries, derive_t responses)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = queries;
+       values[1].derive = responses;
+
+       vl.values = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "dns", sizeof (vl.plugin));
+       sstrncpy (vl.type, "dns_octets", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void submit_octets */
+
+static int dns_read (void)
+{
+       unsigned int keys[T_MAX];
+       unsigned int values[T_MAX];
+       int len;
+       int i;
+
+       counter_list_t *ptr;
+
+       pthread_mutex_lock (&traffic_mutex);
+       values[0] = tr_queries;
+       values[1] = tr_responses;
+       pthread_mutex_unlock (&traffic_mutex);
+
+       if ((values[0] != 0) || (values[1] != 0))
+               submit_octets (values[0], values[1]);
+
+       pthread_mutex_lock (&qtype_mutex);
+       for (ptr = qtype_list, len = 0;
+                       (ptr != NULL) && (len < T_MAX);
+                       ptr = ptr->next, len++)
+       {
+               keys[len]   = ptr->key;
+               values[len] = ptr->value;
+       }
+       pthread_mutex_unlock (&qtype_mutex);
+
+       for (i = 0; i < len; i++)
+       {
+               DEBUG ("dns plugin: qtype = %u; counter = %u;", keys[i], values[i]);
+               submit_derive ("dns_qtype", qtype_str (keys[i]), values[i]);
+       }
+
+       pthread_mutex_lock (&opcode_mutex);
+       for (ptr = opcode_list, len = 0;
+                       (ptr != NULL) && (len < T_MAX);
+                       ptr = ptr->next, len++)
+       {
+               keys[len]   = ptr->key;
+               values[len] = ptr->value;
+       }
+       pthread_mutex_unlock (&opcode_mutex);
+
+       for (i = 0; i < len; i++)
+       {
+               DEBUG ("dns plugin: opcode = %u; counter = %u;", keys[i], values[i]);
+               submit_derive ("dns_opcode", opcode_str (keys[i]), values[i]);
+       }
+
+       pthread_mutex_lock (&rcode_mutex);
+       for (ptr = rcode_list, len = 0;
+                       (ptr != NULL) && (len < T_MAX);
+                       ptr = ptr->next, len++)
+       {
+               keys[len]   = ptr->key;
+               values[len] = ptr->value;
+       }
+       pthread_mutex_unlock (&rcode_mutex);
+
+       for (i = 0; i < len; i++)
+       {
+               DEBUG ("dns plugin: rcode = %u; counter = %u;", keys[i], values[i]);
+               submit_derive ("dns_rcode", rcode_str (keys[i]), values[i]);
+       }
+
+       return (0);
+} /* int dns_read */
+
+void module_register (void)
+{
+       plugin_register_config ("dns", dns_config, config_keys, config_keys_num);
+       plugin_register_init ("dns", dns_init);
+       plugin_register_read ("dns", dns_read);
+} /* void module_register */
diff --git a/src/drbd.c b/src/drbd.c
new file mode 100644 (file)
index 0000000..cc306dc
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * collectd - src/drbd.c
+ * Copyright (C) 2014  Tim Laszlo
+ *
+ * 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:
+ *   Tim Laszlo <tim.laszlo at gmail.com>
+ **/
+
+/*
+ See: http://www.drbd.org/users-guide/ch-admin.html#s-performance-indicators
+
+ version: 8.3.11 (api:88/proto:86-96)
+ srcversion: 71955441799F513ACA6DA60 
+  0: cs:Connected ro:Primary/Secondary ds:UpToDate/UpToDate B r-----
+        ns:64363752 nr:0 dw:357799284 dr:846902273 al:34987022 bm:18062 lo:0 \
+                                               pe:0 ua:0 ap:0 ep:1 wo:f oos:0
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+static const char *drbd_stats = "/proc/drbd";
+static const char *drbd_names[] =
+{
+       "network_send",  /* ns (network send) */
+       "network_recv",  /* nr (network receive) */
+       "disk_write",      /* dw (disk write) */
+       "disk_read",            /* dr (disk read) */
+       "activity_log",  /* al (activity log) */
+       "bitmap",                  /* bm (bit map) */
+       "local_count",    /* lo (local count) */
+       "pending",                /* pe (pending) */
+       "unacknowledged",   /* ua (unacknowledged) */
+       "app pending",    /* ap (application pending) */
+       "epochs",                  /* ep (epochs) */
+       NULL,                      /* wo (write order) */
+       "oos"                      /* oos (out of sync) */
+};
+static size_t drbd_names_num = STATIC_ARRAY_SIZE (drbd_names);
+
+static int drbd_init (void)
+{
+       return (0);
+}
+
+
+static int drbd_submit_fields (long int resource,
+               char **fields, size_t fields_num)
+{
+       char plugin_instance[DATA_MAX_NAME_LEN];
+       value_t values[fields_num];
+       value_list_t vl = VALUE_LIST_INIT;
+       size_t i;
+
+       if (resource < 0)
+       {
+               WARNING ("drbd plugin: Unable to parse resource");
+               return (EINVAL);
+       }
+
+       if (fields_num != drbd_names_num)
+       {
+               WARNING ("drbd plugin: Wrong number of fields for "
+                                "r%ld statistics. Expected %zu, got %zu.",
+                                resource, drbd_names_num, fields_num);
+               return (EINVAL);
+       }
+
+       ssnprintf (plugin_instance, sizeof (plugin_instance), "r%ld",
+                       resource);
+
+       for (i = 0; i < drbd_names_num; i++)
+       {
+               char *data;
+               /* skip non numeric wo */
+               if (strncmp(fields[i], "wo", 2) == 0)
+                       continue;
+               data = strchr(fields[i], ':');
+               if (data == NULL)
+                       return (EINVAL);
+               (void) parse_value (++data, &values[i], DS_TYPE_DERIVE);
+       }
+
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "drbd", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "drbd_resource", sizeof (vl.type));
+
+       for (i = 0; i < fields_num; i++)
+       {
+               if (drbd_names[i] == NULL)
+                       continue;
+               vl.values = values + i;
+               sstrncpy (vl.type_instance, drbd_names[i],
+                               sizeof (vl.type_instance));
+               plugin_dispatch_values (&vl);
+       }
+
+       return (0);
+} /* drbd_submit_fields */
+
+static int drbd_read (void)
+{
+       FILE *fh;
+       char buffer[256];
+
+       long int resource = -1;
+       char *fields[16];
+       int fields_num = 0;
+
+       fh = fopen (drbd_stats, "r");
+       if (fh == NULL)
+       {
+               WARNING ("drbd plugin: Unable to open %s", drbd_stats);
+               return (EINVAL);
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               fields_num = strsplit (buffer,
+                               fields, STATIC_ARRAY_SIZE (fields));
+
+               /* ignore headers (first two iterations) */
+               if (fields_num < 4)
+                       continue;
+
+               if (isdigit(fields[0][0]))
+               {
+                       /* parse the resource line, next loop iteration
+                          will submit values for this resource */
+                       resource = strtol(fields[0], NULL, 10);
+               }
+               else
+               {
+                       /* handle stats data for the resource defined in the
+                          previous iteration */
+                       drbd_submit_fields(resource, fields, fields_num);
+               }
+       } /* while (fgets) */
+
+       fclose (fh);
+       return (0);
+} /* void drbd_read */
+
+void module_register (void)
+{
+       plugin_register_init ("drbd", drbd_init);
+       plugin_register_read ("drbd", drbd_read);
+} /* void module_register */
diff --git a/src/email.c b/src/email.c
new file mode 100644 (file)
index 0000000..d1a8719
--- /dev/null
@@ -0,0 +1,779 @@
+/**
+ * collectd - src/email.c
+ * Copyright (C) 2006-2008  Sebastian Harl
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This plugin communicates with a spam filter, a virus scanner or similar
+ * software using a UNIX socket and a very simple protocol:
+ *
+ * e-mail type (e.g. ham, spam, virus, ...) and size
+ * e:<type>:<bytes>
+ *
+ * spam score
+ * s:<value>
+ *
+ * successful spam checks
+ * c:<type1>[,<type2>,...]
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "configfile.h"
+
+#include <stddef.h>
+
+#if HAVE_LIBPTHREAD
+# include <pthread.h>
+#endif
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/select.h>
+
+/* some systems (e.g. Darwin) seem to not define UNIX_PATH_MAX at all */
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
+#endif /* UNIX_PATH_MAX */
+
+#if HAVE_GRP_H
+#      include <grp.h>
+#endif /* HAVE_GRP_H */
+
+#define SOCK_PATH LOCALSTATEDIR"/run/"PACKAGE_NAME"-email"
+#define MAX_CONNS 5
+#define MAX_CONNS_LIMIT 16384
+
+#define log_debug(...) DEBUG ("email: "__VA_ARGS__)
+#define log_err(...) ERROR ("email: "__VA_ARGS__)
+#define log_warn(...) WARNING ("email: "__VA_ARGS__)
+
+/*
+ * Private data structures
+ */
+/* linked list of email and check types */
+typedef struct type {
+       char        *name;
+       int         value;
+       struct type *next;
+} type_t;
+
+typedef struct {
+       type_t *head;
+       type_t *tail;
+} type_list_t;
+
+/* collector thread control information */
+typedef struct collector {
+       pthread_t thread;
+
+       /* socket descriptor of the current/last connection */
+       FILE *socket;
+} collector_t;
+
+/* linked list of pending connections */
+typedef struct conn {
+       /* socket to read data from */
+       FILE *socket;
+
+       /* linked list of connections */
+       struct conn *next;
+} conn_t;
+
+typedef struct {
+       conn_t *head;
+       conn_t *tail;
+} conn_list_t;
+
+/*
+ * Private variables
+ */
+/* valid configuration file keys */
+static const char *config_keys[] =
+{
+       "SocketFile",
+       "SocketGroup",
+       "SocketPerms",
+       "MaxConns"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+/* socket configuration */
+static char *sock_file  = NULL;
+static char *sock_group = NULL;
+static int  sock_perms  = S_IRWXU | S_IRWXG;
+static int  max_conns   = MAX_CONNS;
+
+/* state of the plugin */
+static int disabled = 0;
+
+/* thread managing "client" connections */
+static pthread_t connector = (pthread_t) 0;
+static int connector_socket = -1;
+
+/* tell the collector threads that a new connection is available */
+static pthread_cond_t conn_available = PTHREAD_COND_INITIALIZER;
+
+/* connections that are waiting to be processed */
+static pthread_mutex_t conns_mutex = PTHREAD_MUTEX_INITIALIZER;
+static conn_list_t conns;
+
+/* tell the connector thread that a collector is available */
+static pthread_cond_t collector_available = PTHREAD_COND_INITIALIZER;
+
+/* collector threads */
+static collector_t **collectors = NULL;
+
+static pthread_mutex_t available_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int available_collectors;
+
+static pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
+static type_list_t list_count;
+static type_list_t list_count_copy;
+
+static pthread_mutex_t size_mutex = PTHREAD_MUTEX_INITIALIZER;
+static type_list_t list_size;
+static type_list_t list_size_copy;
+
+static pthread_mutex_t score_mutex = PTHREAD_MUTEX_INITIALIZER;
+static double score;
+static int score_count;
+
+static pthread_mutex_t check_mutex = PTHREAD_MUTEX_INITIALIZER;
+static type_list_t list_check;
+static type_list_t list_check_copy;
+
+/*
+ * Private functions
+ */
+static int email_config (const char *key, const char *value)
+{
+       if (0 == strcasecmp (key, "SocketFile")) {
+               if (NULL != sock_file)
+                       free (sock_file);
+               sock_file = sstrdup (value);
+       }
+       else if (0 == strcasecmp (key, "SocketGroup")) {
+               if (NULL != sock_group)
+                       free (sock_group);
+               sock_group = sstrdup (value);
+       }
+       else if (0 == strcasecmp (key, "SocketPerms")) {
+               /* the user is responsible for providing reasonable values */
+               sock_perms = (int)strtol (value, NULL, 8);
+       }
+       else if (0 == strcasecmp (key, "MaxConns")) {
+               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",
+                                       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",
+                                       tmp, MAX_CONNS_LIMIT);
+                       ERROR ("email plugin: `MaxConns' was set to invalid "
+                                       "value %li, will use hardcoded limit %i.\n",
+                                       tmp, MAX_CONNS_LIMIT);
+                       max_conns = MAX_CONNS_LIMIT;
+               }
+               else {
+                       max_conns = (int)tmp;
+               }
+       }
+       else {
+               return -1;
+       }
+       return 0;
+} /* static int email_config (char *, char *) */
+
+/* Increment the value of the given name in the given list by incr. */
+static void type_list_incr (type_list_t *list, char *name, int incr)
+{
+       if (NULL == list->head) {
+               list->head = (type_t *)smalloc (sizeof (type_t));
+
+               list->head->name  = sstrdup (name);
+               list->head->value = incr;
+               list->head->next  = NULL;
+
+               list->tail = list->head;
+       }
+       else {
+               type_t *ptr;
+
+               for (ptr = list->head; NULL != ptr; ptr = ptr->next) {
+                       if (0 == strcmp (name, ptr->name))
+                               break;
+               }
+
+               if (NULL == ptr) {
+                       list->tail->next = (type_t *)smalloc (sizeof (type_t));
+                       list->tail = list->tail->next;
+
+                       list->tail->name  = sstrdup (name);
+                       list->tail->value = incr;
+                       list->tail->next  = NULL;
+               }
+               else {
+                       ptr->value += incr;
+               }
+       }
+       return;
+} /* static void type_list_incr (type_list_t *, char *) */
+
+static void *collect (void *arg)
+{
+       collector_t *this = (collector_t *)arg;
+
+       while (1) {
+               int loop = 1;
+
+               conn_t *connection;
+
+               pthread_mutex_lock (&conns_mutex);
+
+               while (NULL == conns.head) {
+                       pthread_cond_wait (&conn_available, &conns_mutex);
+               }
+
+               connection = conns.head;
+               conns.head = conns.head->next;
+
+               if (NULL == conns.head) {
+                       conns.tail = NULL;
+               }
+
+               pthread_mutex_unlock (&conns_mutex);
+
+               /* make the socket available to the global
+                * thread and connection management */
+               this->socket = connection->socket;
+
+               log_debug ("collect: handling connection on fd #%i",
+                               fileno (this->socket));
+
+               while (loop) {
+                       /* 256 bytes ought to be enough for anybody ;-) */
+                       char line[256 + 1]; /* line + '\0' */
+                       int  len = 0;
+
+                       errno = 0;
+                       if (NULL == fgets (line, sizeof (line), this->socket)) {
+                               loop = 0;
+
+                               if (0 != errno) {
+                                       char errbuf[1024];
+                                       log_err ("collect: reading from socket (fd #%i) "
+                                                       "failed: %s", fileno (this->socket),
+                                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                               }
+                               break;
+                       }
+
+                       len = strlen (line);
+                       if (('\n' != line[len - 1]) && ('\r' != line[len - 1])) {
+                               log_warn ("collect: line too long (> %zu characters): "
+                                               "'%s' (truncated)", sizeof (line) - 1, line);
+
+                               while (NULL != fgets (line, sizeof (line), this->socket))
+                                       if (('\n' == line[len - 1]) || ('\r' == line[len - 1]))
+                                               break;
+                               continue;
+                       }
+
+                       line[len - 1] = '\0';
+
+                       log_debug ("collect: line = '%s'", line);
+
+                       if (':' != line[1]) {
+                               log_err ("collect: syntax error in line '%s'", line);
+                               continue;
+                       }
+
+                       if ('e' == line[0]) { /* e:<type>:<bytes> */
+                               char *ptr  = NULL;
+                               char *type = strtok_r (line + 2, ":", &ptr);
+                               char *tmp  = strtok_r (NULL, ":", &ptr);
+                               int  bytes = 0;
+
+                               if (NULL == tmp) {
+                                       log_err ("collect: syntax error in line '%s'", line);
+                                       continue;
+                               }
+
+                               bytes = atoi (tmp);
+
+                               pthread_mutex_lock (&count_mutex);
+                               type_list_incr (&list_count, type, 1);
+                               pthread_mutex_unlock (&count_mutex);
+
+                               if (bytes > 0) {
+                                       pthread_mutex_lock (&size_mutex);
+                                       type_list_incr (&list_size, type, bytes);
+                                       pthread_mutex_unlock (&size_mutex);
+                               }
+                       }
+                       else if ('s' == line[0]) { /* s:<value> */
+                               pthread_mutex_lock (&score_mutex);
+                               score = (score * (double)score_count + atof (line + 2))
+                                               / (double)(score_count + 1);
+                               ++score_count;
+                               pthread_mutex_unlock (&score_mutex);
+                       }
+                       else if ('c' == line[0]) { /* c:<type1>[,<type2>,...] */
+                               char *ptr  = NULL;
+                               char *type = strtok_r (line + 2, ",", &ptr);
+
+                               do {
+                                       pthread_mutex_lock (&check_mutex);
+                                       type_list_incr (&list_check, type, 1);
+                                       pthread_mutex_unlock (&check_mutex);
+                               } while (NULL != (type = strtok_r (NULL, ",", &ptr)));
+                       }
+                       else {
+                               log_err ("collect: unknown type '%c'", line[0]);
+                       }
+               } /* while (loop) */
+
+               log_debug ("Shutting down connection on fd #%i",
+                               fileno (this->socket));
+
+               fclose (connection->socket);
+               free (connection);
+
+               this->socket = NULL;
+
+               pthread_mutex_lock (&available_mutex);
+               ++available_collectors;
+               pthread_mutex_unlock (&available_mutex);
+
+               pthread_cond_signal (&collector_available);
+       } /* while (1) */
+
+       pthread_exit ((void *)0);
+       return ((void *) 0);
+} /* static void *collect (void *) */
+
+static void *open_connection (void __attribute__((unused)) *arg)
+{
+       struct sockaddr_un addr;
+
+       char *path  = (NULL == sock_file) ? SOCK_PATH : sock_file;
+       char *group = (NULL == sock_group) ? COLLECTD_GRP_NAME : sock_group;
+
+       /* create UNIX socket */
+       errno = 0;
+       if (-1 == (connector_socket = socket (PF_UNIX, SOCK_STREAM, 0))) {
+               char errbuf[1024];
+               disabled = 1;
+               log_err ("socket() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               pthread_exit ((void *)1);
+       }
+
+       addr.sun_family = AF_UNIX;
+       sstrncpy (addr.sun_path, path, (size_t)(UNIX_PATH_MAX - 1));
+
+       errno = 0;
+       if (-1 == bind (connector_socket, (struct sockaddr *)&addr,
+                               offsetof (struct sockaddr_un, sun_path)
+                                       + strlen(addr.sun_path))) {
+               char errbuf[1024];
+               disabled = 1;
+               close (connector_socket);
+               connector_socket = -1;
+               log_err ("bind() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               pthread_exit ((void *)1);
+       }
+
+       errno = 0;
+       if (-1 == listen (connector_socket, 5)) {
+               char errbuf[1024];
+               disabled = 1;
+               close (connector_socket);
+               connector_socket = -1;
+               log_err ("listen() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               pthread_exit ((void *)1);
+       }
+
+       {
+               struct group sg;
+               struct group *grp;
+               char grbuf[2048];
+               int status;
+
+               grp = NULL;
+               status = getgrnam_r (group, &sg, grbuf, sizeof (grbuf), &grp);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       log_warn ("getgrnam_r (%s) failed: %s", group,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+               else if (grp == NULL)
+               {
+                       log_warn ("No such group: `%s'", group);
+               }
+               else
+               {
+                       status = chown (path, (uid_t) -1, grp->gr_gid);
+                       if (status != 0)
+                       {
+                               char errbuf[1024];
+                               log_warn ("chown (%s, -1, %i) failed: %s",
+                                               path, (int) grp->gr_gid,
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                       }
+               }
+       }
+
+       errno = 0;
+       if (0 != chmod (path, sock_perms)) {
+               char errbuf[1024];
+               log_warn ("chmod() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+
+       { /* initialize collector threads */
+               int i   = 0;
+               int err = 0;
+
+               pthread_attr_t ptattr;
+
+               conns.head = NULL;
+               conns.tail = NULL;
+
+               pthread_attr_init (&ptattr);
+               pthread_attr_setdetachstate (&ptattr, PTHREAD_CREATE_DETACHED);
+
+               available_collectors = max_conns;
+
+               collectors =
+                       (collector_t **)smalloc (max_conns * sizeof (collector_t *));
+
+               for (i = 0; i < max_conns; ++i) {
+                       collectors[i] = (collector_t *)smalloc (sizeof (collector_t));
+                       collectors[i]->socket = NULL;
+
+                       if (0 != (err = plugin_thread_create (&collectors[i]->thread,
+                                                       &ptattr, collect, collectors[i]))) {
+                               char errbuf[1024];
+                               log_err ("pthread_create() failed: %s",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                               collectors[i]->thread = (pthread_t) 0;
+                       }
+               }
+
+               pthread_attr_destroy (&ptattr);
+       }
+
+       while (1) {
+               int remote = 0;
+
+               conn_t *connection;
+
+               pthread_mutex_lock (&available_mutex);
+
+               while (0 == available_collectors) {
+                       pthread_cond_wait (&collector_available, &available_mutex);
+               }
+
+               --available_collectors;
+
+               pthread_mutex_unlock (&available_mutex);
+
+               do {
+                       errno = 0;
+                       if (-1 == (remote = accept (connector_socket, NULL, NULL))) {
+                               if (EINTR != errno) {
+                                       char errbuf[1024];
+                                       disabled = 1;
+                                       close (connector_socket);
+                                       connector_socket = -1;
+                                       log_err ("accept() failed: %s",
+                                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                                       pthread_exit ((void *)1);
+                               }
+                       }
+               } while (EINTR == errno);
+
+               connection = (conn_t *)smalloc (sizeof (conn_t));
+
+               connection->socket = fdopen (remote, "r");
+               connection->next   = NULL;
+
+               if (NULL == connection->socket) {
+                       close (remote);
+                       continue;
+               }
+
+               pthread_mutex_lock (&conns_mutex);
+
+               if (NULL == conns.head) {
+                       conns.head = connection;
+                       conns.tail = connection;
+               }
+               else {
+                       conns.tail->next = connection;
+                       conns.tail = conns.tail->next;
+               }
+
+               pthread_mutex_unlock (&conns_mutex);
+
+               pthread_cond_signal (&conn_available);
+       }
+
+       pthread_exit ((void *) 0);
+       return ((void *) 0);
+} /* static void *open_connection (void *) */
+
+static int email_init (void)
+{
+       int err = 0;
+
+       if (0 != (err = plugin_thread_create (&connector, NULL,
+                               open_connection, NULL))) {
+               char errbuf[1024];
+               disabled = 1;
+               log_err ("pthread_create() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       return (0);
+} /* int email_init */
+
+static int email_shutdown (void)
+{
+       type_t *ptr = NULL;
+
+       int i = 0;
+
+       if (connector != ((pthread_t) 0)) {
+               pthread_kill (connector, SIGTERM);
+               connector = (pthread_t) 0;
+       }
+
+       if (connector_socket >= 0) {
+               close (connector_socket);
+               connector_socket = -1;
+       }
+
+       /* don't allow any more connections to be processed */
+       pthread_mutex_lock (&conns_mutex);
+
+       available_collectors = 0;
+
+       if (collectors != NULL) {
+               for (i = 0; i < max_conns; ++i) {
+                       if (collectors[i] == NULL)
+                               continue;
+
+                       if (collectors[i]->thread != ((pthread_t) 0)) {
+                               pthread_kill (collectors[i]->thread, SIGTERM);
+                               collectors[i]->thread = (pthread_t) 0;
+                       }
+
+                       if (collectors[i]->socket != NULL) {
+                               fclose (collectors[i]->socket);
+                               collectors[i]->socket = NULL;
+                       }
+
+                       sfree (collectors[i]);
+               }
+               sfree (collectors);
+       } /* if (collectors != NULL) */
+
+       pthread_mutex_unlock (&conns_mutex);
+
+       for (ptr = list_count.head; NULL != ptr; ptr = ptr->next) {
+               free (ptr->name);
+               free (ptr);
+       }
+
+       for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
+               free (ptr->name);
+               free (ptr);
+       }
+
+       for (ptr = list_size.head; NULL != ptr; ptr = ptr->next) {
+               free (ptr->name);
+               free (ptr);
+       }
+
+       for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
+               free (ptr->name);
+               free (ptr);
+       }
+
+       for (ptr = list_check.head; NULL != ptr; ptr = ptr->next) {
+               free (ptr->name);
+               free (ptr);
+       }
+
+       for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next) {
+               free (ptr->name);
+               free (ptr);
+       }
+
+       unlink ((NULL == sock_file) ? SOCK_PATH : sock_file);
+
+       sfree (sock_file);
+       sfree (sock_group);
+       return (0);
+} /* static void email_shutdown (void) */
+
+static void email_submit (const char *type, const char *type_instance, gauge_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "email", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void email_submit */
+
+/* Copy list l1 to list l2. l2 may partly exist already, but it is assumed
+ * that neither the order nor the name of any element of either list is
+ * changed and no elements are deleted. The values of l1 are reset to zero
+ * after they have been copied to l2. */
+static void copy_type_list (type_list_t *l1, type_list_t *l2)
+{
+       type_t *ptr1;
+       type_t *ptr2;
+
+       type_t *last = NULL;
+
+       for (ptr1 = l1->head, ptr2 = l2->head; NULL != ptr1;
+                       ptr1 = ptr1->next, last = ptr2, ptr2 = ptr2->next) {
+               if (NULL == ptr2) {
+                       ptr2 = (type_t *)smalloc (sizeof (type_t));
+                       ptr2->name = NULL;
+                       ptr2->next = NULL;
+
+                       if (NULL == last) {
+                               l2->head = ptr2;
+                       }
+                       else {
+                               last->next = ptr2;
+                       }
+
+                       l2->tail = ptr2;
+               }
+
+               if (NULL == ptr2->name) {
+                       ptr2->name = sstrdup (ptr1->name);
+               }
+
+               ptr2->value = ptr1->value;
+               ptr1->value = 0;
+       }
+       return;
+}
+
+static int email_read (void)
+{
+       type_t *ptr;
+
+       double score_old;
+       int score_count_old;
+
+       if (disabled)
+               return (-1);
+
+       /* email count */
+       pthread_mutex_lock (&count_mutex);
+
+       copy_type_list (&list_count, &list_count_copy);
+
+       pthread_mutex_unlock (&count_mutex);
+
+       for (ptr = list_count_copy.head; NULL != ptr; ptr = ptr->next) {
+               email_submit ("email_count", ptr->name, ptr->value);
+       }
+
+       /* email size */
+       pthread_mutex_lock (&size_mutex);
+
+       copy_type_list (&list_size, &list_size_copy);
+
+       pthread_mutex_unlock (&size_mutex);
+
+       for (ptr = list_size_copy.head; NULL != ptr; ptr = ptr->next) {
+               email_submit ("email_size", ptr->name, ptr->value);
+       }
+
+       /* spam score */
+       pthread_mutex_lock (&score_mutex);
+
+       score_old = score;
+       score_count_old = score_count;
+       score = 0.0;
+       score_count = 0;
+
+       pthread_mutex_unlock (&score_mutex);
+
+       if (score_count_old > 0)
+               email_submit ("spam_score", "", score_old);
+
+       /* spam checks */
+       pthread_mutex_lock (&check_mutex);
+
+       copy_type_list (&list_check, &list_check_copy);
+
+       pthread_mutex_unlock (&check_mutex);
+
+       for (ptr = list_check_copy.head; NULL != ptr; ptr = ptr->next)
+               email_submit ("spam_check", ptr->name, ptr->value);
+
+       return (0);
+} /* int email_read */
+
+void module_register (void)
+{
+       plugin_register_config ("email", email_config, config_keys, config_keys_num);
+       plugin_register_init ("email", email_init);
+       plugin_register_read ("email", email_read);
+       plugin_register_shutdown ("email", email_shutdown);
+} /* void module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --git a/src/entropy.c b/src/entropy.c
new file mode 100644 (file)
index 0000000..03de9ef
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * collectd - src/entropy.c
+ * Copyright (C) 2007       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+#define ENTROPY_FILE "/proc/sys/kernel/random/entropy_avail"
+
+static void entropy_submit (double entropy)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = entropy;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "entropy", sizeof (vl.plugin));
+       sstrncpy (vl.type, "entropy", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int entropy_read (void)
+{
+       double entropy;
+       FILE *fh;
+       char buffer[64];
+
+       fh = fopen (ENTROPY_FILE, "r");
+       if (fh == NULL)
+               return (-1);
+
+       if (fgets (buffer, sizeof (buffer), fh) == NULL)
+       {
+               fclose (fh);
+               return (-1);
+       }
+       fclose (fh);
+
+       entropy = atof (buffer);
+       
+       if (entropy > 0.0)
+               entropy_submit (entropy);
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_read ("entropy", entropy_read);
+} /* void module_register */
diff --git a/src/ethstat.c b/src/ethstat.c
new file mode 100644 (file)
index 0000000..dec14f3
--- /dev/null
@@ -0,0 +1,368 @@
+/**
+ * collectd - src/ethstat.c
+ * Copyright (C) 2011       Cyril Feraudet
+ * Copyright (C) 2012       Florian "octo" Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Cyril Feraudet <cyril at feraudet.com>
+ *   Florian "octo" Forster <octo@collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_avltree.h"
+#include "utils_complain.h"
+
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_LINUX_SOCKIOS_H
+# include <linux/sockios.h>
+#endif
+#if HAVE_LINUX_ETHTOOL_H
+# include <linux/ethtool.h>
+#endif
+
+struct value_map_s
+{
+  char type[DATA_MAX_NAME_LEN];
+  char type_instance[DATA_MAX_NAME_LEN];
+};
+typedef struct value_map_s value_map_t;
+
+static char **interfaces = NULL;
+static size_t interfaces_num = 0;
+
+static c_avl_tree_t *value_map = NULL;
+
+static _Bool collect_mapped_only = 0;
+
+static int ethstat_add_interface (const oconfig_item_t *ci) /* {{{ */
+{
+  char **tmp;
+  int status;
+
+  tmp = realloc (interfaces,
+      sizeof (*interfaces) * (interfaces_num + 1));
+  if (tmp == NULL)
+    return (-1);
+  interfaces = tmp;
+  interfaces[interfaces_num] = NULL;
+
+  status = cf_util_get_string (ci, interfaces + interfaces_num);
+  if (status != 0)
+    return (status);
+
+  interfaces_num++;
+  INFO("ethstat plugin: Registered interface %s",
+      interfaces[interfaces_num - 1]);
+
+  return (0);
+} /* }}} int ethstat_add_interface */
+
+static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
+{
+  value_map_t *map;
+  int status;
+  char *key;
+
+  if ((ci->values_num < 2)
+      || (ci->values_num > 3)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || (ci->values[1].type != OCONFIG_TYPE_STRING)
+      || ((ci->values_num == 3)
+        && (ci->values[2].type != OCONFIG_TYPE_STRING)))
+  {
+    ERROR ("ethstat plugin: The %s option requires "
+        "two or three string arguments.", ci->key);
+    return (-1);
+  }
+
+  key = strdup (ci->values[0].value.string);
+  if (key == NULL)
+  {
+    ERROR ("ethstat plugin: strdup(3) failed.");
+    return (ENOMEM);
+  }
+
+  map = malloc (sizeof (*map));
+  if (map == NULL)
+  {
+    sfree (key);
+    ERROR ("ethstat plugin: malloc(3) failed.");
+    return (ENOMEM);
+  }
+  memset (map, 0, sizeof (*map));
+
+  sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
+  if (ci->values_num == 3)
+    sstrncpy (map->type_instance, ci->values[2].value.string,
+        sizeof (map->type_instance));
+
+  if (value_map == NULL)
+  {
+    value_map = c_avl_create ((void *) strcmp);
+    if (value_map == NULL)
+    {
+      sfree (map);
+      sfree (key);
+      ERROR ("ethstat plugin: c_avl_create() failed.");
+      return (-1);
+    }
+  }
+
+  status = c_avl_insert (value_map,
+      /* key = */ key,
+      /* value = */ map);
+  if (status != 0)
+  {
+    if (status > 0)
+      ERROR ("ethstat plugin: Multiple mappings for \"%s\".", key);
+    else
+      ERROR ("ethstat plugin: c_avl_insert(\"%s\") failed.", key);
+
+    sfree (map);
+    sfree (key);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int ethstat_add_map */
+
+static int ethstat_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Interface", child->key) == 0)
+      ethstat_add_interface (child);
+    else if (strcasecmp ("Map", child->key) == 0)
+      ethstat_add_map (child);
+    else if (strcasecmp ("MappedOnly", child->key) == 0)
+      (void) cf_util_get_boolean (child, &collect_mapped_only);
+    else
+      WARNING ("ethstat plugin: The config option \"%s\" is unknown.",
+          child->key);
+  }
+
+  return (0);
+} /* }}} */
+
+static void ethstat_submit_value (const char *device,
+    const char *type_instance, derive_t value)
+{
+  static c_complain_t complain_no_map = C_COMPLAIN_INIT_STATIC;
+
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  value_map_t *map = NULL;
+
+  if (value_map != NULL)
+    c_avl_get (value_map, type_instance, (void *) &map);
+
+  /* If the "MappedOnly" option is specified, ignore unmapped values. */
+  if (collect_mapped_only && (map == NULL))
+  {
+    if (value_map == NULL)
+      c_complain (LOG_WARNING, &complain_no_map,
+          "ethstat plugin: The \"MappedOnly\" option has been set to true, "
+          "but no mapping has been configured. All values will be ignored!");
+    return;
+  }
+
+  values[0].derive = value;
+  vl.values = values;
+  vl.values_len = 1;
+
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "ethstat", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, device, sizeof (vl.plugin_instance));
+  if (map != NULL)
+  {
+    sstrncpy (vl.type, map->type, sizeof (vl.type));
+    sstrncpy (vl.type_instance, map->type_instance,
+        sizeof (vl.type_instance));
+  }
+  else
+  {
+    sstrncpy (vl.type, "derive", sizeof (vl.type));
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+  }
+
+  plugin_dispatch_values (&vl);
+}
+
+static int ethstat_read_interface (char *device)
+{
+  int fd;
+  struct ifreq req;
+  struct ethtool_drvinfo drvinfo;
+  struct ethtool_gstrings *strings;
+  struct ethtool_stats *stats;
+  size_t n_stats;
+  size_t strings_size;
+  size_t stats_size;
+  size_t i;
+  int status;
+
+  memset (&req, 0, sizeof (req));
+  sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
+
+  fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0);
+  if (fd < 0)
+  {
+    char errbuf[1024];
+    ERROR("ethstat plugin: Failed to open control socket: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return 1;
+  }
+
+  memset (&drvinfo, 0, sizeof (drvinfo));
+  drvinfo.cmd = ETHTOOL_GDRVINFO;
+  req.ifr_data = (void *) &drvinfo;
+  status = ioctl (fd, SIOCETHTOOL, &req);
+  if (status < 0)
+  {
+    char errbuf[1024];
+    close (fd);
+    ERROR ("ethstat plugin: Failed to get driver information "
+        "from %s: %s", device,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  n_stats = (size_t) drvinfo.n_stats;
+  if (n_stats < 1)
+  {
+    close (fd);
+    ERROR("ethstat plugin: No stats available for %s", device);
+    return (-1);
+  }
+
+  strings_size = sizeof (struct ethtool_gstrings)
+    + (n_stats * ETH_GSTRING_LEN);
+  stats_size = sizeof (struct ethtool_stats)
+    + (n_stats * sizeof (uint64_t));
+
+  strings = malloc (strings_size);
+  stats = malloc (stats_size);
+  if ((strings == NULL) || (stats == NULL))
+  {
+    close (fd);
+    sfree (strings);
+    sfree (stats);
+    ERROR("ethstat plugin: malloc(3) failed.");
+    return (-1);
+  }
+
+  strings->cmd = ETHTOOL_GSTRINGS;
+  strings->string_set = ETH_SS_STATS;
+  strings->len = n_stats;
+  req.ifr_data = (void *) strings;
+  status = ioctl (fd, SIOCETHTOOL, &req);
+  if (status < 0)
+  {
+    char errbuf[1024];
+    close (fd);
+    free (strings);
+    free (stats);
+    ERROR ("ethstat plugin: Cannot get strings from %s: %s",
+        device,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  stats->cmd = ETHTOOL_GSTATS;
+  stats->n_stats = n_stats;
+  req.ifr_data = (void *) stats;
+  status = ioctl (fd, SIOCETHTOOL, &req);
+  if (status < 0)
+  {
+    char errbuf[1024];
+    close (fd);
+    free(strings);
+    free(stats);
+    ERROR("ethstat plugin: Reading statistics from %s failed: %s",
+        device,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  for (i = 0; i < n_stats; i++)
+  {
+    const char *stat_name;
+
+    stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN];
+    DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64,
+        device, stat_name, (uint64_t) stats->data[i]);
+    ethstat_submit_value (device,
+        stat_name, (derive_t) stats->data[i]);
+  }
+
+  close (fd);
+  sfree (strings);
+  sfree (stats);
+
+  return (0);
+} /* }}} ethstat_read_interface */
+
+static int ethstat_read(void)
+{
+  size_t i;
+
+  for (i = 0; i < interfaces_num; i++)
+    ethstat_read_interface (interfaces[i]);
+
+  return 0;
+}
+
+static int ethstat_shutdown (void)
+{
+  void *key = NULL;
+  void *value = NULL;
+
+  if (value_map == NULL)
+    return (0);
+
+  while (c_avl_pick (value_map, &key, &value) == 0)
+  {
+    sfree (key);
+    sfree (value);
+  }
+
+  c_avl_destroy (value_map);
+  value_map = NULL;
+
+  return (0);
+}
+
+void module_register (void)
+{
+  plugin_register_complex_config ("ethstat", ethstat_config);
+  plugin_register_read ("ethstat", ethstat_read);
+  plugin_register_shutdown ("ethstat", ethstat_shutdown);
+}
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/exec.c b/src/exec.c
new file mode 100644 (file)
index 0000000..3f68e8b
--- /dev/null
@@ -0,0 +1,921 @@
+/**
+ * collectd - src/exec.c
+ * Copyright (C) 2007-2010  Florian octo Forster
+ * Copyright (C) 2007-2009  Sebastian Harl
+ * Copyright (C) 2008       Peter Holik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Peter Holik <peter at holik.at>
+ **/
+
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE /* For setgroups */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_cmd_putval.h"
+#include "utils_cmd_putnotif.h"
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <signal.h>
+
+#include <pthread.h>
+
+#define PL_NORMAL        0x01
+#define PL_NOTIF_ACTION  0x02
+
+#define PL_RUNNING       0x10
+
+/*
+ * Private data types
+ */
+/*
+ * Access to this structure is serialized using the `pl_lock' lock and the
+ * `PL_RUNNING' flag. The execution of notifications is *not* serialized, so
+ * all functions used to handle notifications MUST NOT write to this structure.
+ * The `pid' and `status' fields are thus unused if the `PL_NOTIF_ACTION' flag
+ * is set.
+ * The `PL_RUNNING' flag is set in `exec_read' and unset in `exec_read_one'.
+ */
+struct program_list_s;
+typedef struct program_list_s program_list_t;
+struct program_list_s
+{
+  char           *user;
+  char           *group;
+  char           *exec;
+  char          **argv;
+  int             pid;
+  int             status;
+  int             flags;
+  program_list_t *next;
+};
+
+typedef struct program_list_and_notification_s
+{
+  program_list_t *pl;
+  notification_t n;
+} program_list_and_notification_t;
+
+/*
+ * Private variables
+ */
+static program_list_t *pl_head = NULL;
+static pthread_mutex_t pl_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Functions
+ */
+static void sigchld_handler (int __attribute__((unused)) signal) /* {{{ */
+{
+  pid_t pid;
+  int status;
+  while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
+  {
+    program_list_t *pl;
+    for (pl = pl_head; pl != NULL; pl = pl->next)
+      if (pl->pid == pid)
+        break;
+    if (pl != NULL)
+      pl->status = status;
+  } /* while (waitpid) */
+} /* void sigchld_handler }}} */
+
+static int exec_config_exec (oconfig_item_t *ci) /* {{{ */
+{
+  program_list_t *pl;
+  char buffer[128];
+  int i;
+
+  if (ci->children_num != 0)
+  {
+    WARNING ("exec plugin: The config option `%s' may not be a block.",
+        ci->key);
+    return (-1);
+  }
+  if (ci->values_num < 2)
+  {
+    WARNING ("exec plugin: The config option `%s' needs at least two "
+        "arguments.", ci->key);
+    return (-1);
+  }
+  if ((ci->values[0].type != OCONFIG_TYPE_STRING)
+      || (ci->values[1].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("exec plugin: The first two arguments to the `%s' option must "
+        "be string arguments.", ci->key);
+    return (-1);
+  }
+
+  pl = (program_list_t *) malloc (sizeof (program_list_t));
+  if (pl == NULL)
+  {
+    ERROR ("exec plugin: malloc failed.");
+    return (-1);
+  }
+  memset (pl, '\0', sizeof (program_list_t));
+
+  if (strcasecmp ("NotificationExec", ci->key) == 0)
+    pl->flags |= PL_NOTIF_ACTION;
+  else
+    pl->flags |= PL_NORMAL;
+
+  pl->user = strdup (ci->values[0].value.string);
+  if (pl->user == NULL)
+  {
+    ERROR ("exec plugin: strdup failed.");
+    sfree (pl);
+    return (-1);
+  }
+
+  pl->group = strchr (pl->user, ':');
+  if (pl->group != NULL)
+  {
+    *pl->group = '\0';
+    pl->group++;
+  }
+
+  pl->exec = strdup (ci->values[1].value.string);
+  if (pl->exec == NULL)
+  {
+    ERROR ("exec plugin: strdup failed.");
+    sfree (pl->user);
+    sfree (pl);
+    return (-1);
+  }
+
+  pl->argv = (char **) malloc (ci->values_num * sizeof (char *));
+  if (pl->argv == NULL)
+  {
+    ERROR ("exec plugin: malloc failed.");
+    sfree (pl->exec);
+    sfree (pl->user);
+    sfree (pl);
+    return (-1);
+  }
+  memset (pl->argv, '\0', ci->values_num * sizeof (char *));
+
+  {
+    char *tmp = strrchr (ci->values[1].value.string, '/');
+    if (tmp == NULL)
+      sstrncpy (buffer, ci->values[1].value.string, sizeof (buffer));
+    else
+      sstrncpy (buffer, tmp + 1, sizeof (buffer));
+  }
+  pl->argv[0] = strdup (buffer);
+  if (pl->argv[0] == NULL)
+  {
+    ERROR ("exec plugin: malloc failed.");
+    sfree (pl->argv);
+    sfree (pl->exec);
+    sfree (pl->user);
+    sfree (pl);
+    return (-1);
+  }
+
+  for (i = 1; i < (ci->values_num - 1); i++)
+  {
+    if (ci->values[i + 1].type == OCONFIG_TYPE_STRING)
+    {
+      pl->argv[i] = strdup (ci->values[i + 1].value.string);
+    }
+    else
+    {
+      if (ci->values[i + 1].type == OCONFIG_TYPE_NUMBER)
+      {
+        ssnprintf (buffer, sizeof (buffer), "%lf",
+            ci->values[i + 1].value.number);
+      }
+      else
+      {
+        if (ci->values[i + 1].value.boolean)
+          sstrncpy (buffer, "true", sizeof (buffer));
+        else
+          sstrncpy (buffer, "false", sizeof (buffer));
+      }
+
+      pl->argv[i] = strdup (buffer);
+    }
+
+    if (pl->argv[i] == NULL)
+    {
+      ERROR ("exec plugin: strdup failed.");
+      break;
+    }
+  } /* for (i) */
+
+  if (i < (ci->values_num - 1))
+  {
+    while ((--i) >= 0)
+    {
+      sfree (pl->argv[i]);
+    }
+    sfree (pl->argv);
+    sfree (pl->exec);
+    sfree (pl->user);
+    sfree (pl);
+    return (-1);
+  }
+
+  for (i = 0; pl->argv[i] != NULL; i++)
+  {
+    DEBUG ("exec plugin: argv[%i] = %s", i, pl->argv[i]);
+  }
+
+  pl->next = pl_head;
+  pl_head = pl;
+
+  return (0);
+} /* int exec_config_exec }}} */
+
+static int exec_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if ((strcasecmp ("Exec", child->key) == 0)
+        || (strcasecmp ("NotificationExec", child->key) == 0))
+      exec_config_exec (child);
+    else
+    {
+      WARNING ("exec plugin: Unknown config option `%s'.", child->key);
+    }
+  } /* for (i) */
+
+  return (0);
+} /* int exec_config }}} */
+
+static void set_environment (void) /* {{{ */
+{
+  char buffer[1024];
+
+#ifdef HAVE_SETENV
+  ssnprintf (buffer, sizeof (buffer), "%.3f",
+      CDTIME_T_TO_DOUBLE (plugin_get_interval ()));
+  setenv ("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1);
+
+  ssnprintf (buffer, sizeof (buffer), "%s", hostname_g);
+  setenv ("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1);
+#else
+  ssnprintf (buffer, sizeof (buffer), "COLLECTD_INTERVAL=%.3f",
+      CDTIME_T_TO_DOUBLE (plugin_get_interval ()));
+  putenv (buffer);
+
+  ssnprintf (buffer, sizeof (buffer), "COLLECTD_HOSTNAME=%s", hostname_g);
+  putenv (buffer);
+#endif
+} /* }}} void set_environment */
+
+__attribute__((noreturn))
+static void exec_child (program_list_t *pl, int uid, int gid, int egid) /* {{{ */
+{
+  int status;
+  char errbuf[1024];
+
+#if HAVE_SETGROUPS
+  if (getuid () == 0)
+  {
+    gid_t  glist[2];
+    size_t glist_len;
+
+    glist[0] = gid;
+    glist_len = 1;
+
+    if ((gid != egid) && (egid != -1))
+    {
+      glist[1] = egid;
+      glist_len = 2;
+    }
+
+    setgroups (glist_len, glist);
+  }
+#endif /* HAVE_SETGROUPS */
+
+  status = setgid (gid);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: setgid (%i) failed: %s",
+        gid, sstrerror (errno, errbuf, sizeof (errbuf)));
+    exit (-1);
+  }
+
+  if (egid != -1)
+  {
+    status = setegid (egid);
+    if (status != 0)
+    {
+      ERROR ("exec plugin: setegid (%i) failed: %s",
+          egid, sstrerror (errno, errbuf, sizeof (errbuf)));
+      exit (-1);
+    }
+  }
+
+  status = setuid (uid);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: setuid (%i) failed: %s",
+        uid, sstrerror (errno, errbuf, sizeof (errbuf)));
+    exit (-1);
+  }
+
+  status = execvp (pl->exec, pl->argv);
+
+  ERROR ("exec plugin: Failed to execute ``%s'': %s",
+      pl->exec, sstrerror (errno, errbuf, sizeof (errbuf)));
+  exit (-1);
+} /* void exec_child }}} */
+
+static void reset_signal_mask (void) /* {{{ */
+{
+  sigset_t ss;
+
+  memset (&ss, 0, sizeof (ss));
+  sigemptyset (&ss);
+  sigprocmask (SIG_SETMASK, &ss, /* old mask = */ NULL);
+} /* }}} void reset_signal_mask */
+
+/*
+ * Creates three pipes (one for reading, one for writing and one for errors),
+ * forks a child, sets up the pipes so that fd_in is connected to STDIN of
+ * the child and fd_out is connected to STDOUT and fd_err is connected to STDERR
+ * of the child. Then is calls `exec_child'.
+ */
+static int fork_child (program_list_t *pl, int *fd_in, int *fd_out, int *fd_err) /* {{{ */
+{
+  int fd_pipe_in[2];
+  int fd_pipe_out[2];
+  int fd_pipe_err[2];
+  char errbuf[1024];
+  int status;
+  int pid;
+
+  int uid;
+  int gid;
+  int egid;
+
+  struct passwd *sp_ptr;
+  struct passwd sp;
+  char nambuf[2048];
+
+  if (pl->pid != 0)
+    return (-1);
+
+  status = pipe (fd_pipe_in);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: pipe failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  status = pipe (fd_pipe_out);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: pipe failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  status = pipe (fd_pipe_err);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: pipe failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  sp_ptr = NULL;
+  status = getpwnam_r (pl->user, &sp, nambuf, sizeof (nambuf), &sp_ptr);
+  if (status != 0)
+  {
+    ERROR ("exec plugin: Failed to get user information for user ``%s'': %s",
+        pl->user, sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+  if (sp_ptr == NULL)
+  {
+    ERROR ("exec plugin: No such user: `%s'", pl->user);
+    return (-1);
+  }
+
+  uid = sp.pw_uid;
+  gid = sp.pw_gid;
+  if (uid == 0)
+  {
+    ERROR ("exec plugin: Cowardly refusing to exec program as root.");
+    return (-1);
+  }
+
+  /* The group configured in the configfile is set as effective group, because
+   * this way the forked process can (re-)gain the user's primary group. */
+  egid = -1;
+  if (NULL != pl->group)
+  {
+    if ('\0' != *pl->group) {
+      struct group *gr_ptr = NULL;
+      struct group gr;
+
+      status = getgrnam_r (pl->group, &gr, nambuf, sizeof (nambuf), &gr_ptr);
+      if (0 != status)
+      {
+        ERROR ("exec plugin: Failed to get group information "
+            "for group ``%s'': %s", pl->group,
+            sstrerror (errno, errbuf, sizeof (errbuf)));
+        return (-1);
+      }
+      if (NULL == gr_ptr)
+      {
+        ERROR ("exec plugin: No such group: `%s'", pl->group);
+        return (-1);
+      }
+
+      egid = gr.gr_gid;
+    }
+    else
+    {
+      egid = gid;
+    }
+  } /* if (pl->group == NULL) */
+
+  pid = fork ();
+  if (pid < 0)
+  {
+    ERROR ("exec plugin: fork failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+  else if (pid == 0)
+  {
+    int fd_num;
+    int fd;
+
+    /* Close all file descriptors but the pipe end we need. */
+    fd_num = getdtablesize ();
+    for (fd = 0; fd < fd_num; fd++)
+    {
+      if ((fd == fd_pipe_in[0])
+          || (fd == fd_pipe_out[1])
+          || (fd == fd_pipe_err[1]))
+        continue;
+      close (fd);
+    }
+
+    /* Connect the `in' pipe to STDIN */
+    if (fd_pipe_in[0] != STDIN_FILENO)
+    {
+      dup2 (fd_pipe_in[0], STDIN_FILENO);
+      close (fd_pipe_in[0]);
+    }
+
+    /* Now connect the `out' pipe to STDOUT */
+    if (fd_pipe_out[1] != STDOUT_FILENO)
+    {
+      dup2 (fd_pipe_out[1], STDOUT_FILENO);
+      close (fd_pipe_out[1]);
+    }
+
+    /* Now connect the `err' pipe to STDERR */
+    if (fd_pipe_err[1] != STDERR_FILENO)
+    {
+      dup2 (fd_pipe_err[1], STDERR_FILENO);
+      close (fd_pipe_err[1]);
+    }
+
+    set_environment ();
+
+    /* Unblock all signals */
+    reset_signal_mask ();
+
+    exec_child (pl, uid, gid, egid);
+    /* does not return */
+  }
+
+  close (fd_pipe_in[0]);
+  close (fd_pipe_out[1]);
+  close (fd_pipe_err[1]);
+
+  if (fd_in != NULL)
+    *fd_in = fd_pipe_in[1];
+  else
+    close (fd_pipe_in[1]);
+
+  if (fd_out != NULL)
+    *fd_out = fd_pipe_out[0];
+  else
+    close (fd_pipe_out[0]);
+
+  if (fd_err != NULL)
+    *fd_err = fd_pipe_err[0];
+  else
+    close (fd_pipe_err[0]);
+
+  return (pid);
+} /* int fork_child }}} */
+
+static int parse_line (char *buffer) /* {{{ */
+{
+  if (strncasecmp ("PUTVAL", buffer, strlen ("PUTVAL")) == 0)
+    return (handle_putval (stdout, buffer));
+  else if (strncasecmp ("PUTNOTIF", buffer, strlen ("PUTNOTIF")) == 0)
+    return (handle_putnotif (stdout, buffer));
+  else
+  {
+    ERROR ("exec plugin: Unable to parse command, ignoring line: \"%s\"",
+       buffer);
+    return (-1);
+  }
+} /* int parse_line }}} */
+
+static void *exec_read_one (void *arg) /* {{{ */
+{
+  program_list_t *pl = (program_list_t *) arg;
+  int fd, fd_err, highest_fd;
+  fd_set fdset, copy;
+  int status;
+  char buffer[1200];  /* if not completely read */
+  char buffer_err[1024];
+  char *pbuffer = buffer;
+  char *pbuffer_err = buffer_err;
+
+  status = fork_child (pl, NULL, &fd, &fd_err);
+  if (status < 0)
+  {
+    /* Reset the "running" flag */
+    pthread_mutex_lock (&pl_lock);
+    pl->flags &= ~PL_RUNNING;
+    pthread_mutex_unlock (&pl_lock);
+    pthread_exit ((void *) 1);
+  }
+  pl->pid = status;
+
+  assert (pl->pid != 0);
+
+  FD_ZERO( &fdset );
+  FD_SET(fd, &fdset);
+  FD_SET(fd_err, &fdset);
+
+  /* Determine the highest file descriptor */
+  highest_fd = (fd > fd_err) ? fd : fd_err;
+
+  /* We use a copy of fdset, as select modifies it */
+  copy = fdset;
+
+  while (1)
+  {
+    int len;
+
+    status = select (highest_fd + 1, &copy, NULL, NULL, NULL);
+    if (status < 0)
+    {
+      if (errno == EINTR)
+        continue;
+      break;
+    }
+
+    if (FD_ISSET(fd, &copy))
+    {
+      char *pnl;
+
+      len = read(fd, pbuffer, sizeof(buffer) - 1 - (pbuffer - buffer));
+
+      if (len < 0)
+      {
+        if (errno == EAGAIN || errno == EINTR)  continue;
+        break;
+      }
+      else if (len == 0) break;  /* We've reached EOF */
+
+      pbuffer[len] = '\0';
+
+      len += pbuffer - buffer;
+      pbuffer = buffer;
+
+      while ((pnl = strchr(pbuffer, '\n')))
+      {
+        *pnl = '\0';
+        if (*(pnl-1) == '\r' ) *(pnl-1) = '\0';
+
+        parse_line (pbuffer);
+
+        pbuffer = ++pnl;
+      }
+      /* not completely read ? */
+      if (pbuffer - buffer < len)
+      {
+        len -= pbuffer - buffer;
+        memmove(buffer, pbuffer, len);
+        pbuffer = buffer + len;
+      }
+      else
+        pbuffer = buffer;
+    }
+    else if (FD_ISSET(fd_err, &copy))
+    {
+      char *pnl;
+
+      len = read(fd_err, pbuffer_err, sizeof(buffer_err) - 1 - (pbuffer_err - buffer_err));
+
+      if (len < 0)
+      {
+        if (errno == EAGAIN || errno == EINTR)
+          continue;
+        break;
+      }
+      else if (len == 0)
+      {
+        /* We've reached EOF */
+        NOTICE ("exec plugin: Program `%s' has closed STDERR.", pl->exec);
+
+        /* Remove file descriptor form select() set. */
+        FD_CLR (fd_err, &fdset);
+        copy = fdset;
+        highest_fd = fd;
+
+        /* Clean up file descriptor */
+        close (fd_err);
+        fd_err = -1;
+        continue;
+      }
+
+      pbuffer_err[len] = '\0';
+
+      len += pbuffer_err - buffer_err;
+      pbuffer_err = buffer_err;
+
+      while ((pnl = strchr(pbuffer_err, '\n')))
+      {
+        *pnl = '\0';
+        if (*(pnl-1) == '\r' ) *(pnl-1) = '\0';
+
+        ERROR ("exec plugin: exec_read_one: error = %s", pbuffer_err);
+
+        pbuffer_err = ++pnl;
+      }
+      /* not completely read ? */
+      if (pbuffer_err - buffer_err < len)
+      {
+        len -= pbuffer_err - buffer_err;
+        memmove(buffer_err, pbuffer_err, len);
+        pbuffer_err = buffer_err + len;
+      }
+      else
+        pbuffer_err = buffer_err;
+    }
+    /* reset copy */
+    copy = fdset;
+  }
+
+  DEBUG ("exec plugin: exec_read_one: Waiting for `%s' to exit.", pl->exec);
+  if (waitpid (pl->pid, &status, 0) > 0)
+    pl->status = status;
+
+  DEBUG ("exec plugin: Child %i exited with status %i.",
+      (int) pl->pid, pl->status);
+
+  pl->pid = 0;
+
+  pthread_mutex_lock (&pl_lock);
+  pl->flags &= ~PL_RUNNING;
+  pthread_mutex_unlock (&pl_lock);
+
+  close (fd);
+  if (fd_err >= 0)
+    close (fd_err);
+
+  pthread_exit ((void *) 0);
+  return (NULL);
+} /* void *exec_read_one }}} */
+
+static void *exec_notification_one (void *arg) /* {{{ */
+{
+  program_list_t *pl = ((program_list_and_notification_t *) arg)->pl;
+  notification_t *n = &((program_list_and_notification_t *) arg)->n;
+  notification_meta_t *meta;
+  int fd;
+  FILE *fh;
+  int pid;
+  int status;
+  const char *severity;
+
+  pid = fork_child (pl, &fd, NULL, NULL);
+  if (pid < 0) {
+    sfree (arg);
+    pthread_exit ((void *) 1);
+  }
+
+  fh = fdopen (fd, "w");
+  if (fh == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("exec plugin: fdopen (%i) failed: %s", fd,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    kill (pl->pid, SIGTERM);
+    pl->pid = 0;
+    close (fd);
+    sfree (arg);
+    pthread_exit ((void *) 1);
+  }
+
+  severity = "FAILURE";
+  if (n->severity == NOTIF_WARNING)
+    severity = "WARNING";
+  else if (n->severity == NOTIF_OKAY)
+    severity = "OKAY";
+
+  fprintf (fh,
+      "Severity: %s\n"
+      "Time: %.3f\n",
+      severity, CDTIME_T_TO_DOUBLE (n->time));
+
+  /* Print the optional fields */
+  if (strlen (n->host) > 0)
+    fprintf (fh, "Host: %s\n", n->host);
+  if (strlen (n->plugin) > 0)
+    fprintf (fh, "Plugin: %s\n", n->plugin);
+  if (strlen (n->plugin_instance) > 0)
+    fprintf (fh, "PluginInstance: %s\n", n->plugin_instance);
+  if (strlen (n->type) > 0)
+    fprintf (fh, "Type: %s\n", n->type);
+  if (strlen (n->type_instance) > 0)
+    fprintf (fh, "TypeInstance: %s\n", n->type_instance);
+
+  for (meta = n->meta; meta != NULL; meta = meta->next)
+  {
+    if (meta->type == NM_TYPE_STRING)
+      fprintf (fh, "%s: %s\n", meta->name, meta->nm_value.nm_string);
+    else if (meta->type == NM_TYPE_SIGNED_INT)
+      fprintf (fh, "%s: %"PRIi64"\n", meta->name, meta->nm_value.nm_signed_int);
+    else if (meta->type == NM_TYPE_UNSIGNED_INT)
+      fprintf (fh, "%s: %"PRIu64"\n", meta->name, meta->nm_value.nm_unsigned_int);
+    else if (meta->type == NM_TYPE_DOUBLE)
+      fprintf (fh, "%s: %e\n", meta->name, meta->nm_value.nm_double);
+    else if (meta->type == NM_TYPE_BOOLEAN)
+      fprintf (fh, "%s: %s\n", meta->name,
+          meta->nm_value.nm_boolean ? "true" : "false");
+  }
+
+  fprintf (fh, "\n%s\n", n->message);
+
+  fflush (fh);
+  fclose (fh);
+
+  waitpid (pid, &status, 0);
+
+  DEBUG ("exec plugin: Child %i exited with status %i.",
+      pid, status);
+
+  if (n->meta != NULL)
+    plugin_notification_meta_free (n->meta);
+  n->meta = NULL;
+  sfree (arg);
+  pthread_exit ((void *) 0);
+  return (NULL);
+} /* void *exec_notification_one }}} */
+
+static int exec_init (void) /* {{{ */
+{
+  struct sigaction sa;
+
+  memset (&sa, '\0', sizeof (sa));
+  sa.sa_handler = sigchld_handler;
+  sigaction (SIGCHLD, &sa, NULL);
+
+  return (0);
+} /* int exec_init }}} */
+
+static int exec_read (void) /* {{{ */
+{
+  program_list_t *pl;
+
+  for (pl = pl_head; pl != NULL; pl = pl->next)
+  {
+    pthread_t t;
+    pthread_attr_t attr;
+
+    /* Only execute `normal' style executables here. */
+    if ((pl->flags & PL_NORMAL) == 0)
+      continue;
+
+    pthread_mutex_lock (&pl_lock);
+    /* Skip if a child is already running. */
+    if ((pl->flags & PL_RUNNING) != 0)
+    {
+      pthread_mutex_unlock (&pl_lock);
+      continue;
+    }
+    pl->flags |= PL_RUNNING;
+    pthread_mutex_unlock (&pl_lock);
+
+    pthread_attr_init (&attr);
+    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+    plugin_thread_create (&t, &attr, exec_read_one, (void *) pl);
+    pthread_attr_destroy (&attr);
+  } /* for (pl) */
+
+  return (0);
+} /* int exec_read }}} */
+
+static int exec_notification (const notification_t *n, /* {{{ */
+    user_data_t __attribute__((unused)) *user_data)
+{
+  program_list_t *pl;
+  program_list_and_notification_t *pln;
+
+  for (pl = pl_head; pl != NULL; pl = pl->next)
+  {
+    pthread_t t;
+    pthread_attr_t attr;
+
+    /* Only execute `notification' style executables here. */
+    if ((pl->flags & PL_NOTIF_ACTION) == 0)
+      continue;
+
+    /* Skip if a child is already running. */
+    if (pl->pid != 0)
+      continue;
+
+    pln = (program_list_and_notification_t *) malloc (sizeof
+        (program_list_and_notification_t));
+    if (pln == NULL)
+    {
+      ERROR ("exec plugin: malloc failed.");
+      continue;
+    }
+
+    pln->pl = pl;
+    memcpy (&pln->n, n, sizeof (notification_t));
+
+    /* Set the `meta' member to NULL, otherwise `plugin_notification_meta_copy'
+     * will run into an endless loop. */
+    pln->n.meta = NULL;
+    plugin_notification_meta_copy (&pln->n, n);
+
+    pthread_attr_init (&attr);
+    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+    plugin_thread_create (&t, &attr, exec_notification_one, (void *) pln);
+    pthread_attr_destroy (&attr);
+  } /* for (pl) */
+
+  return (0);
+} /* }}} int exec_notification */
+
+static int exec_shutdown (void) /* {{{ */
+{
+  program_list_t *pl;
+  program_list_t *next;
+
+  pl = pl_head;
+  while (pl != NULL)
+  {
+    next = pl->next;
+
+    if (pl->pid > 0)
+    {
+      kill (pl->pid, SIGTERM);
+      INFO ("exec plugin: Sent SIGTERM to %hu", (unsigned short int) pl->pid);
+    }
+
+    sfree (pl->user);
+    sfree (pl);
+
+    pl = next;
+  } /* while (pl) */
+  pl_head = NULL;
+
+  return (0);
+} /* int exec_shutdown }}} */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("exec", exec_config);
+  plugin_register_init ("exec", exec_init);
+  plugin_register_read ("exec", exec_read);
+  plugin_register_notification ("exec", exec_notification,
+      /* user_data = */ NULL);
+  plugin_register_shutdown ("exec", exec_shutdown);
+} /* void module_register */
+
+/*
+ * vim:shiftwidth=2:softtabstop=2:tabstop=8:fdm=marker
+ */
diff --git a/src/fhcount.c b/src/fhcount.c
new file mode 100644 (file)
index 0000000..4c409b5
--- /dev/null
@@ -0,0 +1,139 @@
+/**
+ *
+ * collectd - src/fhcount.c
+ * Copyright (c) 2015, Jiri Tyr <jiri.tyr at gmail.com>
+ *
+ * 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.
+ *
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+
+static const char *config_keys[] = {
+  "ValuesAbsolute",
+  "ValuesPercentage"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+
+static _Bool values_absolute = 1;
+static _Bool values_percentage = 0;
+
+
+static int fhcount_config(const char *key, const char *value) {
+  int ret = -1;
+
+  if (strcasecmp(key, "ValuesAbsolute") == 0) {
+    if (IS_TRUE(value)) {
+      values_absolute = 1;
+    } else {
+      values_absolute = 0;
+    }
+
+    ret = 0;
+  } else if (strcasecmp(key, "ValuesPercentage") == 0) {
+    if (IS_TRUE(value)) {
+      values_percentage = 1;
+    } else {
+      values_percentage = 0;
+    }
+
+    ret = 0;
+  }
+
+  return(ret);
+}
+
+
+static void fhcount_submit(
+    const char *type, const char *type_instance, gauge_t value) {
+
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+
+  // Compose the metric
+  sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+  sstrncpy(vl.plugin, "fhcount", sizeof(vl.plugin));
+  sstrncpy(vl.type, type, sizeof(vl.type));
+  sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
+
+  // Dispatch the metric
+  plugin_dispatch_values(&vl);
+}
+
+
+static int fhcount_read(void) {
+  int numfields = 0;
+  int buffer_len = 60;
+  gauge_t used, unused, max;
+  int prc_used, prc_unused;
+  char *fields[3];
+  char buffer[buffer_len];
+  char errbuf[1024];
+  FILE *fp;
+
+  // Open file
+  fp = fopen("/proc/sys/fs/file-nr" , "r");
+  if (fp == NULL) {
+    ERROR("fhcount: fopen: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+    return(EXIT_FAILURE);
+  }
+  if (fgets(buffer, buffer_len, fp) == NULL) {
+    ERROR("fhcount: fgets: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+    return(EXIT_FAILURE);
+  }
+  fclose(fp);
+
+  // Tokenize string
+  numfields = strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields));
+
+  if (numfields != 3) {
+    ERROR("fhcount: Line doesn't contain 3 fields");
+    return(EXIT_FAILURE);
+  }
+
+  // Define the values
+  strtogauge(fields[0], &used);
+  strtogauge(fields[1], &unused);
+  strtogauge(fields[2], &max);
+  prc_used = (gauge_t) used/max*100;
+  prc_unused = (gauge_t) unused/max*100;
+
+  // Submit values
+  if (values_absolute) {
+    fhcount_submit("file_handles", "used", (gauge_t) used);
+    fhcount_submit("file_handles", "unused", (gauge_t) unused);
+    fhcount_submit("file_handles", "max", (gauge_t) max);
+  }
+  if (values_percentage) {
+    fhcount_submit("percent", "used", (gauge_t) prc_used);
+    fhcount_submit("percent", "unused", (gauge_t) prc_unused);
+  }
+
+  return(0);
+}
+
+
+void module_register(void) {
+  plugin_register_config(
+    "fhcount", fhcount_config, config_keys, config_keys_num);
+  plugin_register_read("fhcount", fhcount_read);
+}
diff --git a/src/filecount.c b/src/filecount.c
new file mode 100644 (file)
index 0000000..47caf93
--- /dev/null
@@ -0,0 +1,577 @@
+/**
+ * collectd - src/filecount.c
+ * Copyright (C) 2008  Alessandro Iurlano
+ * Copyright (C) 2008  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Alessandro Iurlano <alessandro.iurlano at gmail.com>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"       
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <fnmatch.h>
+
+#define FC_RECURSIVE 1
+#define FC_HIDDEN 2
+
+struct fc_directory_conf_s
+{
+  char *path;
+  char *instance;
+
+  int options;
+
+  /* Data counters */
+  uint64_t files_num;
+  uint64_t files_size;
+
+  /* Selectors */
+  char *name;
+  int64_t mtime;
+  int64_t size;
+
+  /* Helper for the recursive functions */
+  time_t now;
+};
+typedef struct fc_directory_conf_s fc_directory_conf_t;
+
+static fc_directory_conf_t **directories = NULL;
+static size_t directories_num = 0;
+
+static void fc_submit_dir (const fc_directory_conf_t *dir)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = (gauge_t) dir->files_num;
+
+  vl.values = values;
+  vl.values_len = STATIC_ARRAY_SIZE (values);
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "filecount", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, dir->instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, "files", sizeof (vl.type));
+
+  plugin_dispatch_values (&vl);
+
+  values[0].gauge = (gauge_t) dir->files_size;
+  sstrncpy (vl.type, "bytes", sizeof (vl.type));
+
+  plugin_dispatch_values (&vl);
+} /* void fc_submit_dir */
+
+/*
+ * Config:
+ * <Plugin filecount>
+ *   <Directory /path/to/dir>
+ *     Instance "foobar"
+ *     Name "*.conf"
+ *     MTime -3600
+ *     Size "+10M"
+ *   </Directory>
+ * </Plugin>
+ *
+ * Collect:
+ * - Number of files
+ * - Total size
+ */
+
+static int fc_config_set_instance (fc_directory_conf_t *dir, const char *str)
+{
+  char buffer[1024];
+  char *ptr;
+  char *copy;
+
+  sstrncpy (buffer, str, sizeof (buffer));
+  for (ptr = buffer; *ptr != 0; ptr++)
+    if (*ptr == '/')
+      *ptr = '_';
+
+  for (ptr = buffer; *ptr == '_'; ptr++)
+    /* do nothing */;
+
+  if (*ptr == 0)
+    return (-1);
+
+  copy = strdup (ptr);
+  if (copy == NULL)
+    return (-1);
+
+  sfree (dir->instance);
+  dir->instance = copy;
+
+  return (0);
+} /* int fc_config_set_instance */
+
+static int fc_config_add_dir_instance (fc_directory_conf_t *dir,
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("filecount plugin: The `Instance' config option needs exactly "
+        "one string argument.");
+    return (-1);
+  }
+
+  return (fc_config_set_instance (dir, ci->values[0].value.string));
+} /* int fc_config_add_dir_instance */
+
+static int fc_config_add_dir_name (fc_directory_conf_t *dir,
+    oconfig_item_t *ci)
+{
+  char *temp;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("filecount plugin: The `Name' config option needs exactly one "
+        "string argument.");
+    return (-1);
+  }
+
+  temp = strdup (ci->values[0].value.string);
+  if (temp == NULL)
+  {
+    ERROR ("filecount plugin: strdup failed.");
+    return (-1);
+  }
+
+  sfree (dir->name);
+  dir->name = temp;
+
+  return (0);
+} /* int fc_config_add_dir_name */
+
+static int fc_config_add_dir_mtime (fc_directory_conf_t *dir,
+    oconfig_item_t *ci)
+{
+  char *endptr;
+  double temp;
+
+  if ((ci->values_num != 1)
+      || ((ci->values[0].type != OCONFIG_TYPE_STRING)
+        && (ci->values[0].type != OCONFIG_TYPE_NUMBER)))
+  {
+    WARNING ("filecount plugin: The `MTime' config option needs exactly one "
+        "string or numeric argument.");
+    return (-1);
+  }
+
+  if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
+  {
+    dir->mtime = (int64_t) ci->values[0].value.number;
+    return (0);
+  }
+
+  errno = 0;
+  endptr = NULL;
+  temp = strtod (ci->values[0].value.string, &endptr);
+  if ((errno != 0) || (endptr == NULL)
+      || (endptr == ci->values[0].value.string))
+  {
+    WARNING ("filecount plugin: Converting `%s' to a number failed.",
+        ci->values[0].value.string);
+    return (-1);
+  }
+
+  switch (*endptr)
+  {
+    case 0:
+    case 's':
+    case 'S':
+      break;
+
+    case 'm':
+    case 'M':
+      temp *= 60;
+      break;
+
+    case 'h':
+    case 'H':
+      temp *= 3600;
+      break;
+
+    case 'd':
+    case 'D':
+      temp *= 86400;
+      break;
+
+    case 'w':
+    case 'W':
+      temp *= 7 * 86400;
+      break;
+
+    case 'y':
+    case 'Y':
+      temp *= 31557600; /* == 365.25 * 86400 */
+      break;
+
+    default:
+      WARNING ("filecount plugin: Invalid suffix for `MTime': `%c'", *endptr);
+      return (-1);
+  } /* switch (*endptr) */
+
+  dir->mtime = (int64_t) temp;
+
+  return (0);
+} /* int fc_config_add_dir_mtime */
+
+static int fc_config_add_dir_size (fc_directory_conf_t *dir,
+    oconfig_item_t *ci)
+{
+  char *endptr;
+  double temp;
+
+  if ((ci->values_num != 1)
+      || ((ci->values[0].type != OCONFIG_TYPE_STRING)
+        && (ci->values[0].type != OCONFIG_TYPE_NUMBER)))
+  {
+    WARNING ("filecount plugin: The `Size' config option needs exactly one "
+        "string or numeric argument.");
+    return (-1);
+  }
+
+  if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
+  {
+    dir->size = (int64_t) ci->values[0].value.number;
+    return (0);
+  }
+
+  errno = 0;
+  endptr = NULL;
+  temp = strtod (ci->values[0].value.string, &endptr);
+  if ((errno != 0) || (endptr == NULL)
+      || (endptr == ci->values[0].value.string))
+  {
+    WARNING ("filecount plugin: Converting `%s' to a number failed.",
+        ci->values[0].value.string);
+    return (-1);
+  }
+
+  switch (*endptr)
+  {
+    case 0:
+    case 'b':
+    case 'B':
+      break;
+
+    case 'k':
+    case 'K':
+      temp *= 1000.0;
+      break;
+
+    case 'm':
+    case 'M':
+      temp *= 1000.0 * 1000.0;
+      break;
+
+    case 'g':
+    case 'G':
+      temp *= 1000.0 * 1000.0 * 1000.0;
+      break;
+
+    case 't':
+    case 'T':
+      temp *= 1000.0 * 1000.0 * 1000.0 * 1000.0;
+      break;
+
+    case 'p':
+    case 'P':
+      temp *= 1000.0 * 1000.0 * 1000.0 * 1000.0 * 1000.0;
+      break;
+
+    default:
+      WARNING ("filecount plugin: Invalid suffix for `Size': `%c'", *endptr);
+      return (-1);
+  } /* switch (*endptr) */
+
+  dir->size = (int64_t) temp;
+
+  return (0);
+} /* int fc_config_add_dir_size */
+
+static int fc_config_add_dir_option (fc_directory_conf_t *dir,
+    oconfig_item_t *ci, int bit)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+  {
+    WARNING ("filecount plugin: The `Recursive' config options needs exactly "
+        "one boolean argument.");
+    return (-1);
+  }
+
+  if (ci->values[0].value.boolean)
+    dir->options |= bit;
+  else
+    dir->options &= ~bit;
+
+  return (0);
+} /* int fc_config_add_dir_option */
+
+static int fc_config_add_dir (oconfig_item_t *ci)
+{
+  fc_directory_conf_t *dir;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("filecount plugin: `Directory' needs exactly one string "
+        "argument.");
+    return (-1);
+  }
+
+  /* Initialize `dir' */
+  dir = (fc_directory_conf_t *) malloc (sizeof (*dir));
+  if (dir == NULL)
+  {
+    ERROR ("filecount plugin: malloc failed.");
+    return (-1);
+  }
+  memset (dir, 0, sizeof (*dir));
+
+  dir->path = strdup (ci->values[0].value.string);
+  if (dir->path == NULL)
+  {
+    ERROR ("filecount plugin: strdup failed.");
+    return (-1);
+  }
+
+  fc_config_set_instance (dir, dir->path);
+
+  dir->options = FC_RECURSIVE;
+
+  dir->name = NULL;
+  dir->mtime = 0;
+  dir->size = 0;
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if (strcasecmp ("Instance", option->key) == 0)
+      status = fc_config_add_dir_instance (dir, option);
+    else if (strcasecmp ("Name", option->key) == 0)
+      status = fc_config_add_dir_name (dir, option);
+    else if (strcasecmp ("MTime", option->key) == 0)
+      status = fc_config_add_dir_mtime (dir, option);
+    else if (strcasecmp ("Size", option->key) == 0)
+      status = fc_config_add_dir_size (dir, option);
+    else if (strcasecmp ("Recursive", option->key) == 0)
+      status = fc_config_add_dir_option (dir, option, FC_RECURSIVE);
+    else if (strcasecmp ("IncludeHidden", option->key) == 0)
+      status = fc_config_add_dir_option (dir, option, FC_HIDDEN);
+    else
+    {
+      WARNING ("filecount plugin: fc_config_add_dir: "
+          "Option `%s' not allowed here.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (ci->children) */
+
+  if (status == 0)
+  {
+    fc_directory_conf_t **temp;
+
+    temp = (fc_directory_conf_t **) realloc (directories,
+        sizeof (*directories) * (directories_num + 1));
+    if (temp == NULL)
+    {
+      ERROR ("filecount plugin: realloc failed.");
+      status = -1;
+    }
+    else
+    {
+      directories = temp;
+      directories[directories_num] = dir;
+      directories_num++;
+    }
+  }
+
+  if (status != 0)
+  {
+    sfree (dir->name);
+    sfree (dir->instance);
+    sfree (dir->path);
+    sfree (dir);
+    return (-1);
+  }
+
+  return (0);
+} /* int fc_config_add_dir */
+
+static int fc_config (oconfig_item_t *ci)
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp ("Directory", child->key) == 0)
+      fc_config_add_dir (child);
+    else
+    {
+      WARNING ("filecount plugin: Ignoring unknown config option `%s'.",
+          child->key);
+    }
+  } /* for (ci->children) */
+
+  return (0);
+} /* int fc_config */
+
+static int fc_init (void)
+{
+  if (directories_num < 1)
+  {
+    WARNING ("filecount plugin: No directories have been configured.");
+    return (-1);
+  }
+
+  return (0);
+} /* int fc_init */
+
+static int fc_read_dir_callback (const char *dirname, const char *filename,
+    void *user_data)
+{
+  fc_directory_conf_t *dir = user_data;
+  char abs_path[PATH_MAX];
+  struct stat statbuf;
+  int status;
+
+  if (dir == NULL)
+    return (-1);
+
+  ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, filename);
+
+  status = lstat (abs_path, &statbuf);
+  if (status != 0)
+  {
+    ERROR ("filecount plugin: stat (%s) failed.", abs_path);
+    return (-1);
+  }
+
+  if (S_ISDIR (statbuf.st_mode) && (dir->options & FC_RECURSIVE))
+  {
+    status = walk_directory (abs_path, fc_read_dir_callback, dir,
+        /* include hidden = */ (dir->options & FC_HIDDEN) ? 1 : 0);
+    return (status);
+  }
+  else if (!S_ISREG (statbuf.st_mode))
+  {
+    return (0);
+  }
+
+  if (dir->name != NULL)
+  {
+    status = fnmatch (dir->name, filename, /* flags = */ 0);
+    if (status != 0)
+      return (0);
+  }
+
+  if (dir->mtime != 0)
+  {
+    time_t mtime = dir->now;
+
+    if (dir->mtime < 0)
+      mtime += dir->mtime;
+    else
+      mtime -= dir->mtime;
+
+    DEBUG ("filecount plugin: Only collecting files that were touched %s %u.",
+        (dir->mtime < 0) ? "after" : "before",
+        (unsigned int) mtime);
+
+    if (((dir->mtime < 0) && (statbuf.st_mtime < mtime))
+        || ((dir->mtime > 0) && (statbuf.st_mtime > mtime)))
+      return (0);
+  }
+
+  if (dir->size != 0)
+  {
+    off_t size;
+
+    if (dir->size < 0)
+      size = (off_t) ((-1) * dir->size);
+    else
+      size = (off_t) dir->size;
+
+    if (((dir->size < 0) && (statbuf.st_size > size))
+        || ((dir->size > 0) && (statbuf.st_size < size)))
+      return (0);
+  }
+
+  dir->files_num++;
+  dir->files_size += (uint64_t) statbuf.st_size;
+
+  return (0);
+} /* int fc_read_dir_callback */
+
+static int fc_read_dir (fc_directory_conf_t *dir)
+{
+  int status;
+
+  dir->files_num = 0;
+  dir->files_size = 0;
+
+  if (dir->mtime != 0)
+    dir->now = time (NULL);
+    
+  status = walk_directory (dir->path, fc_read_dir_callback, dir,
+      /* include hidden */ (dir->options & FC_HIDDEN) ? 1 : 0);
+  if (status != 0)
+  {
+    WARNING ("filecount plugin: walk_directory (%s) failed.", dir->path);
+    return (-1);
+  }
+
+  fc_submit_dir (dir);
+
+  return (0);
+} /* int fc_read_dir */
+
+static int fc_read (void)
+{
+  size_t i;
+
+  for (i = 0; i < directories_num; i++)
+    fc_read_dir (directories[i]);
+
+  return (0);
+} /* int fc_read */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("filecount", fc_config);
+  plugin_register_init ("filecount", fc_init);
+  plugin_register_read ("filecount", fc_read);
+} /* void module_register */
+
+/*
+ * vim: set sw=2 sts=2 et :
+ */
diff --git a/src/fscache.c b/src/fscache.c
new file mode 100644 (file)
index 0000000..8fbd271
--- /dev/null
@@ -0,0 +1,230 @@
+/**
+ * collectd - src/fscache.c
+ * Copyright (C) 2009 Edward "Koko" Konetzko
+ *
+ * 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:
+ *   Edward "Koko" Konetzko <konetzed at quixoticagony.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include <stdio.h>  /* a header needed for FILE */
+#include <string.h> /* a header needed for scanf function */
+#include <stdlib.h> /* used for atoi */
+
+
+#if !KERNEL_LINUX
+# error "This module only supports the Linux implementation of fscache"
+#endif
+
+#define BUFSIZE 1024
+
+/*
+see /proc/fs/fscache/stats
+see Documentation/filesystems/caching/fscache.txt in linux kernel >= 2.6.30
+
+This shows counts of a number of events that can happen in FS-Cache:
+
+CLASS   EVENT   MEANING
+======= ======= =======================================================
+Cookies idx=N   Number of index cookies allocated
+        dat=N   Number of data storage cookies allocated
+        spc=N   Number of special cookies allocated
+Objects alc=N   Number of objects allocated
+        nal=N   Number of object allocation failures
+        avl=N   Number of objects that reached the available state
+        ded=N   Number of objects that reached the dead state
+ChkAux  non=N   Number of objects that didn't have a coherency check
+        ok=N    Number of objects that passed a coherency check
+        upd=N   Number of objects that needed a coherency data update
+        obs=N   Number of objects that were declared obsolete
+Pages   mrk=N   Number of pages marked as being cached
+        unc=N   Number of uncache page requests seen
+Acquire n=N Number of acquire cookie requests seen
+        nul=N   Number of acq reqs given a NULL parent
+        noc=N   Number of acq reqs rejected due to no cache available
+        ok=N    Number of acq reqs succeeded
+        nbf=N   Number of acq reqs rejected due to error
+        oom=N   Number of acq reqs failed on ENOMEM
+Lookups n=N Number of lookup calls made on cache backends
+        neg=N   Number of negative lookups made
+        pos=N   Number of positive lookups made
+        crt=N   Number of objects created by lookup
+Updates n=N Number of update cookie requests seen
+        nul=N   Number of upd reqs given a NULL parent
+        run=N   Number of upd reqs granted CPU time
+Relinqs n=N Number of relinquish cookie requests seen
+        nul=N   Number of rlq reqs given a NULL parent
+        wcr=N   Number of rlq reqs waited on completion of creation
+AttrChg n=N Number of attribute changed requests seen
+        ok=N    Number of attr changed requests queued
+        nbf=N   Number of attr changed rejected -ENOBUFS
+        oom=N   Number of attr changed failed -ENOMEM
+        run=N   Number of attr changed ops given CPU time
+Allocs  n=N Number of allocation requests seen
+        ok=N    Number of successful alloc reqs
+        wt=N    Number of alloc reqs that waited on lookup completion
+        nbf=N   Number of alloc reqs rejected -ENOBUFS
+        ops=N   Number of alloc reqs submitted
+        owt=N   Number of alloc reqs waited for CPU time
+Retrvls n=N Number of retrieval (read) requests seen
+        ok=N    Number of successful retr reqs
+        wt=N    Number of retr reqs that waited on lookup completion
+        nod=N   Number of retr reqs returned -ENODATA
+        nbf=N   Number of retr reqs rejected -ENOBUFS
+        int=N   Number of retr reqs aborted -ERESTARTSYS
+        oom=N   Number of retr reqs failed -ENOMEM
+        ops=N   Number of retr reqs submitted
+        owt=N   Number of retr reqs waited for CPU time
+Stores  n=N Number of storage (write) requests seen
+        ok=N    Number of successful store reqs
+        agn=N   Number of store reqs on a page already pending storage
+        nbf=N   Number of store reqs rejected -ENOBUFS
+        oom=N   Number of store reqs failed -ENOMEM
+        ops=N   Number of store reqs submitted
+        run=N   Number of store reqs granted CPU time
+Ops pend=N  Number of times async ops added to pending queues
+        run=N   Number of times async ops given CPU time
+        enq=N   Number of times async ops queued for processing
+        dfr=N   Number of async ops queued for deferred release
+        rel=N   Number of async ops released
+        gc=N    Number of deferred-release async ops garbage collected
+
+63 events to collect in 13 groups
+*/
+static void fscache_submit (const char *section, const char *name,
+        value_t value)
+{
+    value_list_t vl = VALUE_LIST_INIT;
+
+    vl.values = &value;
+    vl.values_len = 1;
+
+    sstrncpy(vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy(vl.plugin, "fscache", sizeof (vl.plugin));
+    sstrncpy(vl.plugin_instance, section, sizeof (vl.plugin_instance));
+    sstrncpy(vl.type, "fscache_stat", sizeof(vl.type));
+    sstrncpy(vl.type_instance, name, sizeof(vl.type_instance));
+
+    plugin_dispatch_values (&vl);
+}
+
+static void fscache_read_stats_file (FILE *fh)
+{
+    char section[DATA_MAX_NAME_LEN];
+    size_t section_len;
+
+    char linebuffer[BUFSIZE];
+
+/*
+ *  cat /proc/fs/fscache/stats
+ *      FS-Cache statistics
+ *      Cookies: idx=2 dat=0 spc=0
+ *      Objects: alc=0 nal=0 avl=0 ded=0
+ *      ChkAux : non=0 ok=0 upd=0 obs=0
+ *      Pages  : mrk=0 unc=0
+ *      Acquire: n=2 nul=0 noc=0 ok=2 nbf=0 oom=0
+ *      Lookups: n=0 neg=0 pos=0 crt=0
+ *      Updates: n=0 nul=0 run=0
+ *      Relinqs: n=0 nul=0 wcr=0
+ *      AttrChg: n=0 ok=0 nbf=0 oom=0 run=0
+ *      Allocs : n=0 ok=0 wt=0 nbf=0
+ *      Allocs : ops=0 owt=0
+ *      Retrvls: n=0 ok=0 wt=0 nod=0 nbf=0 int=0 oom=0
+ *      Retrvls: ops=0 owt=0
+ *      Stores : n=0 ok=0 agn=0 nbf=0 oom=0
+ *      Stores : ops=0 run=0
+ *      Ops    : pend=0 run=0 enq=0
+ *      Ops    : dfr=0 rel=0 gc=0
+ */
+
+    /* Read file line by line */
+    while (fgets (linebuffer, sizeof (linebuffer), fh) != NULL)
+    {
+        char *lineptr;
+        char *fields[32];
+        int fields_num;
+        int i;
+
+        /* Find the colon and replace it with a null byte */
+        lineptr = strchr (linebuffer, ':');
+        if (lineptr == NULL)
+            continue;
+        *lineptr = 0;
+        lineptr++;
+
+        /* Copy and clean up the section name */
+        sstrncpy (section, linebuffer, sizeof (section));
+        section_len = strlen (section);
+        while ((section_len > 0) && isspace ((int) section[section_len - 1]))
+        {
+            section_len--;
+            section[section_len] = 0;
+        }
+        if (section_len <= 0)
+            continue;
+
+        fields_num = strsplit (lineptr, fields, STATIC_ARRAY_SIZE (fields));
+        if (fields_num <= 0)
+            continue;
+
+        for (i = 0; i < fields_num; i++)
+        {
+            char *field_name;
+            char *field_value_str;
+            value_t field_value_cnt;
+            int status;
+
+            field_name = fields[i];
+            assert (field_name != NULL);
+
+            field_value_str = strchr (field_name, '=');
+            if (field_value_str == NULL)
+                continue;
+            *field_value_str = 0;
+            field_value_str++;
+
+            status = parse_value (field_value_str, &field_value_cnt,
+                    DS_TYPE_DERIVE);
+            if (status != 0)
+                continue;
+
+            fscache_submit (section, field_name, field_value_cnt);
+        }
+    } /* while (fgets) */
+} /* void fscache_read_stats_file */
+
+static int fscache_read (void){
+    FILE *fh;
+    fh = fopen("/proc/fs/fscache/stats", "r");
+    if (fh != NULL){
+        fscache_read_stats_file(fh);
+        fclose(fh);
+
+    }else{
+        printf("cant open file\n");
+        return (-1);
+    }
+    return (0);
+}
+
+void module_register (void)
+{
+    plugin_register_read ("fscache", fscache_read);
+} /* void module_register */
+
+/* vim: set sw=4 sts=4 et : */
diff --git a/src/gmond.c b/src/gmond.c
new file mode 100644 (file)
index 0000000..a00b26d
--- /dev/null
@@ -0,0 +1,1129 @@
+/**
+ * collectd - src/gmond.c
+ * Copyright (C) 2009,2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "utils_avltree.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#if HAVE_POLL_H
+# include <poll.h>
+#endif
+
+#include <gm_protocol.h>
+
+#ifndef IPV6_ADD_MEMBERSHIP
+# ifdef IPV6_JOIN_GROUP
+#  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+# else
+#  error "Neither IP_ADD_MEMBERSHIP nor IPV6_JOIN_GROUP is defined"
+# endif
+#endif /* !IP_ADD_MEMBERSHIP */
+
+#ifdef GANGLIA_MAX_MESSAGE_LEN
+# define BUFF_SIZE GANGLIA_MAX_MESSAGE_LEN
+#else
+# define BUFF_SIZE 1400
+#endif
+
+struct socket_entry_s
+{
+  int                     fd;
+  struct sockaddr_storage addr;
+  socklen_t               addrlen;
+};
+typedef struct socket_entry_s socket_entry_t;
+
+struct staging_entry_s
+{
+  char key[2 * DATA_MAX_NAME_LEN];
+  value_list_t vl;
+  int flags;
+};
+typedef struct staging_entry_s staging_entry_t;
+
+struct metric_map_s
+{
+  char *ganglia_name;
+  char *type;
+  char *type_instance;
+  char *ds_name;
+  int   ds_type;
+  int   ds_index;
+};
+typedef struct metric_map_s metric_map_t;
+
+#define MC_RECEIVE_GROUP_DEFAULT "239.2.11.71"
+static char          *mc_receive_group = NULL;
+#define MC_RECEIVE_PORT_DEFAULT "8649"
+static char          *mc_receive_port = NULL;
+
+static struct pollfd *mc_receive_sockets = NULL;
+static size_t         mc_receive_sockets_num = 0;
+
+static socket_entry_t  *mc_send_sockets = NULL;
+static size_t           mc_send_sockets_num = 0;
+static pthread_mutex_t  mc_send_sockets_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int            mc_receive_thread_loop    = 0;
+static int            mc_receive_thread_running = 0;
+static pthread_t      mc_receive_thread_id;
+
+static metric_map_t metric_map_default[] =
+{ /*---------------+-------------+-----------+-------------+------+-----*
+   * ganglia_name  ! type        ! type_inst ! data_source ! type ! idx *
+   *---------------+-------------+-----------+-------------+------+-----*/
+  { "load_one",     "load",       "",         "shortterm",     -1,   -1 },
+  { "load_five",    "load",       "",         "midterm",       -1,   -1 },
+  { "load_fifteen", "load",       "",         "longterm",      -1,   -1 },
+  { "cpu_user",     "cpu",        "user",     "value",         -1,   -1 },
+  { "cpu_system",   "cpu",        "system",   "value",         -1,   -1 },
+  { "cpu_idle",     "cpu",        "idle",     "value",         -1,   -1 },
+  { "cpu_nice",     "cpu",        "nice",     "value",         -1,   -1 },
+  { "cpu_wio",      "cpu",        "wait",     "value",         -1,   -1 },
+  { "mem_free",     "memory",     "free",     "value",         -1,   -1 },
+  { "mem_shared",   "memory",     "shared",   "value",         -1,   -1 },
+  { "mem_buffers",  "memory",     "buffered", "value",         -1,   -1 },
+  { "mem_cached",   "memory",     "cached",   "value",         -1,   -1 },
+  { "mem_total",    "memory",     "total",    "value",         -1,   -1 },
+  { "bytes_in",     "if_octets",  "",         "rx",            -1,   -1 },
+  { "bytes_out",    "if_octets",  "",         "tx",            -1,   -1 },
+  { "pkts_in",      "if_packets", "",         "rx",            -1,   -1 },
+  { "pkts_out",     "if_packets", "",         "tx",            -1,   -1 }
+};
+static size_t metric_map_len_default = STATIC_ARRAY_SIZE (metric_map_default);
+
+static metric_map_t *metric_map = NULL;
+static size_t        metric_map_len = 0;
+
+static c_avl_tree_t   *staging_tree;
+static pthread_mutex_t staging_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static metric_map_t *metric_lookup (const char *key) /* {{{ */
+{
+  metric_map_t *map;
+  size_t map_len;
+  size_t i;
+
+  /* Search the user-supplied table first.. */
+  map = metric_map;
+  map_len = metric_map_len;
+  for (i = 0; i < map_len; i++)
+    if (strcmp (map[i].ganglia_name, key) == 0)
+      break;
+
+  /* .. and fall back to the built-in table if nothing is found. */
+  if (i >= map_len)
+  {
+    map = metric_map_default;
+    map_len = metric_map_len_default;
+
+    for (i = 0; i < map_len; i++)
+      if (strcmp (map[i].ganglia_name, key) == 0)
+        break;
+  }
+
+  if (i >= map_len)
+    return (NULL);
+
+  /* Look up the DS type and ds_index. */
+  if ((map[i].ds_type < 0) || (map[i].ds_index < 0)) /* {{{ */
+  {
+    const data_set_t *ds;
+
+    ds = plugin_get_ds (map[i].type);
+    if (ds == NULL)
+    {
+      WARNING ("gmond plugin: Type not defined: %s", map[i].type);
+      return (NULL);
+    }
+
+    if ((map[i].ds_name == NULL) && (ds->ds_num != 1))
+    {
+      WARNING ("gmond plugin: No data source name defined for metric %s, "
+          "but type %s has more than one data source.",
+          map[i].ganglia_name, map[i].type);
+      return (NULL);
+    }
+
+    if (map[i].ds_name == NULL)
+    {
+      map[i].ds_index = 0;
+    }
+    else
+    {
+      int j;
+
+      for (j = 0; j < ds->ds_num; j++)
+        if (strcasecmp (ds->ds[j].name, map[i].ds_name) == 0)
+          break;
+
+      if (j >= ds->ds_num)
+      {
+        WARNING ("gmond plugin: There is no data source "
+            "named `%s' in type `%s'.",
+            map[i].ds_name, ds->type);
+        return (NULL);
+      }
+      map[i].ds_index = j;
+    }
+
+    map[i].ds_type = ds->ds[map[i].ds_index].type;
+  } /* }}} if ((map[i].ds_type < 0) || (map[i].ds_index < 0)) */
+
+  return (map + i);
+} /* }}} metric_map_t *metric_lookup */
+
+static int create_sockets (socket_entry_t **ret_sockets, /* {{{ */
+    size_t *ret_sockets_num,
+    const char *node, const char *service, int listen)
+{
+  struct addrinfo  ai_hints;
+  struct addrinfo *ai_list;
+  struct addrinfo *ai_ptr;
+  int              ai_return;
+
+  socket_entry_t *sockets;
+  size_t          sockets_num;
+
+  int status;
+    
+  sockets     = *ret_sockets;
+  sockets_num = *ret_sockets_num;
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags    = 0;
+#ifdef AI_PASSIVE
+  ai_hints.ai_flags |= AI_PASSIVE;
+#endif
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family   = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_DGRAM;
+  ai_hints.ai_protocol = IPPROTO_UDP;
+
+  ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
+  if (ai_return != 0)
+  {
+    char errbuf[1024];
+    ERROR ("gmond plugin: getaddrinfo (%s, %s) failed: %s",
+        (node == NULL) ? "(null)" : node,
+        (service == NULL) ? "(null)" : service,
+        (ai_return == EAI_SYSTEM)
+        ? sstrerror (errno, errbuf, sizeof (errbuf))
+        : gai_strerror (ai_return));
+    return (-1);
+  }
+
+  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) /* {{{ */
+  {
+    socket_entry_t *tmp;
+
+    tmp = realloc (sockets, (sockets_num + 1) * sizeof (*sockets));
+    if (tmp == NULL)
+    {
+      ERROR ("gmond plugin: realloc failed.");
+      continue;
+    }
+    sockets = tmp;
+
+    sockets[sockets_num].fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
+        ai_ptr->ai_protocol);
+    if (sockets[sockets_num].fd < 0)
+    {
+      char errbuf[1024];
+      ERROR ("gmond plugin: socket failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      continue;
+    }
+
+    assert (sizeof (sockets[sockets_num].addr) >= ai_ptr->ai_addrlen);
+    memcpy (&sockets[sockets_num].addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    sockets[sockets_num].addrlen = ai_ptr->ai_addrlen;
+
+    /* Sending socket: Open only one socket and don't bind it. */
+    if (listen == 0)
+    {
+      sockets_num++;
+      break;
+    }
+    else
+    {
+      int yes = 1;
+
+      setsockopt (sockets[sockets_num].fd, SOL_SOCKET, SO_REUSEADDR,
+          (void *) &yes, sizeof (yes));
+    }
+
+    status = bind (sockets[sockets_num].fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    if (status != 0)
+    {
+      char errbuf[1024];
+      ERROR ("gmond plugin: bind failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      close (sockets[sockets_num].fd);
+      continue;
+    }
+
+    if (ai_ptr->ai_family == AF_INET)
+    {
+      struct sockaddr_in *addr;
+      struct ip_mreq mreq;
+      int loop;
+
+      addr = (struct sockaddr_in *) ai_ptr->ai_addr;
+
+      if (!IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+      {
+        sockets_num++;
+        continue;
+      }
+
+      loop = 1;
+      setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+          (void *) &loop, sizeof (loop));
+
+      memset (&mreq, 0, sizeof (mreq));
+      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+      mreq.imr_interface.s_addr = htonl (INADDR_ANY);
+      setsockopt (sockets[sockets_num].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+          (void *) &mreq, sizeof (mreq));
+    } /* if (ai_ptr->ai_family == AF_INET) */
+    else if (ai_ptr->ai_family == AF_INET6)
+    {
+      struct sockaddr_in6 *addr;
+      struct ipv6_mreq mreq;
+      int loop;
+
+      addr = (struct sockaddr_in6 *) ai_ptr->ai_addr;
+
+      if (!IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+      {
+        sockets_num++;
+        continue;
+      }
+
+      loop = 1;
+      setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+          (void *) &loop, sizeof (loop));
+
+      memset (&mreq, 0, sizeof (mreq));
+      memcpy (&mreq.ipv6mr_multiaddr,
+          &addr->sin6_addr, sizeof (addr->sin6_addr));
+      mreq.ipv6mr_interface = 0; /* any */
+      setsockopt (sockets[sockets_num].fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
+          (void *) &mreq, sizeof (mreq));
+    } /* if (ai_ptr->ai_family == AF_INET6) */
+
+    sockets_num++;
+  } /* }}} for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) */
+
+  freeaddrinfo (ai_list);
+
+  if ((*ret_sockets_num) >= sockets_num)
+    return (-1);
+
+  *ret_sockets = sockets;
+  *ret_sockets_num = sockets_num;
+  return (0);
+} /* }}} int create_sockets */
+
+static int request_meta_data (const char *host, const char *name) /* {{{ */
+{
+  Ganglia_metadata_msg msg;
+  char buffer[BUFF_SIZE];
+  unsigned int buffer_size;
+  XDR xdr;
+  size_t i;
+
+  memset (&msg, 0, sizeof (msg));
+
+  msg.id = gmetadata_request;
+  msg.Ganglia_metadata_msg_u.grequest.metric_id.host = strdup (host);
+  msg.Ganglia_metadata_msg_u.grequest.metric_id.name = strdup (name);
+
+  if ((msg.Ganglia_metadata_msg_u.grequest.metric_id.host == NULL)
+      || (msg.Ganglia_metadata_msg_u.grequest.metric_id.name == NULL))
+  {
+    sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host);
+    sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.name);
+    return (-1);
+  }
+
+  memset (buffer, 0, sizeof (buffer));
+  xdrmem_create (&xdr, buffer, sizeof (buffer), XDR_ENCODE);
+
+  if (!xdr_Ganglia_metadata_msg (&xdr, &msg))
+  {
+    sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host);
+    sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.name);
+    return (-1);
+  }
+
+  buffer_size = xdr_getpos (&xdr);
+
+  DEBUG ("gmond plugin: Requesting meta data for %s/%s.",
+      host, name);
+
+  pthread_mutex_lock (&mc_send_sockets_lock);
+  for (i = 0; i < mc_send_sockets_num; i++)
+    sendto (mc_send_sockets[i].fd, buffer, (size_t) buffer_size,
+        /* flags = */ 0,
+        (struct sockaddr *) &mc_send_sockets[i].addr,
+        mc_send_sockets[i].addrlen);
+  pthread_mutex_unlock (&mc_send_sockets_lock);
+
+  sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host);
+  sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.name);
+  return (0);
+} /* }}} int request_meta_data */
+
+static staging_entry_t *staging_entry_get (const char *host, /* {{{ */
+    const char *name,
+    const char *type, const char *type_instance,
+    int values_len)
+{
+  char key[2 * DATA_MAX_NAME_LEN];
+  staging_entry_t *se;
+  int status;
+
+  if (staging_tree == NULL)
+    return (NULL);
+
+  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);
+  if (status == 0)
+    return (se);
+
+  /* insert new entry */
+  se = (staging_entry_t *) malloc (sizeof (*se));
+  if (se == NULL)
+    return (NULL);
+  memset (se, 0, sizeof (*se));
+
+  sstrncpy (se->key, key, sizeof (se->key));
+  se->flags = 0;
+
+  se->vl.values = (value_t *) calloc (values_len, sizeof (*se->vl.values));
+  if (se->vl.values == NULL)
+  {
+    sfree (se);
+    return (NULL);
+  }
+  se->vl.values_len = values_len;
+
+  se->vl.time = 0;
+  se->vl.interval = 0;
+  sstrncpy (se->vl.host, host, sizeof (se->vl.host));
+  sstrncpy (se->vl.plugin, "gmond", sizeof (se->vl.plugin));
+  sstrncpy (se->vl.type, type, sizeof (se->vl.type));
+  if (type_instance != NULL)
+    sstrncpy (se->vl.type_instance, type_instance,
+        sizeof (se->vl.type_instance));
+
+  status = c_avl_insert (staging_tree, se->key, se);
+  if (status != 0)
+  {
+    ERROR ("gmond plugin: c_avl_insert failed.");
+    sfree (se->vl.values);
+    sfree (se);
+    return (NULL);
+  }
+
+  return (se);
+} /* }}} staging_entry_t *staging_entry_get */
+
+static int staging_entry_submit (const char *host, const char *name, /* {{{ */
+    staging_entry_t *se)
+{
+  value_list_t vl;
+  value_t values[se->vl.values_len];
+
+  if (se->vl.interval == 0)
+  {
+    /* No meta data has been received for this metric yet. */
+    se->flags = 0;
+    pthread_mutex_unlock (&staging_lock);
+    request_meta_data (host, name);
+    return (0);
+  }
+
+  se->flags = 0;
+
+  memcpy (values, se->vl.values, sizeof (values));
+  memcpy (&vl, &se->vl, sizeof (vl));
+
+  /* Unlock before calling `plugin_dispatch_values'.. */
+  pthread_mutex_unlock (&staging_lock);
+
+  vl.values = values;
+
+  plugin_dispatch_values (&vl);
+
+  return (0);
+} /* }}} int staging_entry_submit */
+
+static int staging_entry_update (const char *host, const char *name, /* {{{ */
+    const char *type, const char *type_instance,
+    int ds_index, int ds_type, value_t value)
+{
+  const data_set_t *ds;
+  staging_entry_t *se;
+
+  ds = plugin_get_ds (type);
+  if (ds == NULL)
+  {
+    ERROR ("gmond plugin: Looking up type %s failed.", type);
+    return (-1);
+  }
+
+  if (ds->ds_num <= ds_index)
+  {
+    ERROR ("gmond plugin: Invalid index %i: %s has only %i data source(s).",
+        ds_index, ds->type, ds->ds_num);
+    return (-1);
+  }
+
+  pthread_mutex_lock (&staging_lock);
+
+  se = staging_entry_get (host, name, type, type_instance, ds->ds_num);
+  if (se == NULL)
+  {
+    pthread_mutex_unlock (&staging_lock);
+    ERROR ("gmond plugin: staging_entry_get failed.");
+    return (-1);
+  }
+  if (se->vl.values_len != ds->ds_num)
+  {
+    pthread_mutex_unlock (&staging_lock);
+    return (-1);
+  }
+
+  if (ds_type == DS_TYPE_COUNTER)
+    se->vl.values[ds_index].counter += value.counter;
+  else if (ds_type == DS_TYPE_GAUGE)
+    se->vl.values[ds_index].gauge = value.gauge;
+  else if (ds_type == DS_TYPE_DERIVE)
+    se->vl.values[ds_index].derive += value.derive;
+  else if (ds_type == DS_TYPE_ABSOLUTE)
+    se->vl.values[ds_index].absolute = value.absolute;
+  else
+    assert (23 == 42);
+
+  se->flags |= (0x01 << ds_index);
+
+  /* Check if all values have been set and submit if so. */
+  if (se->flags == ((0x01 << se->vl.values_len) - 1))
+  {
+    /* `staging_lock' is unlocked in `staging_entry_submit'. */
+    staging_entry_submit (host, name, se);
+  }
+  else
+  {
+    pthread_mutex_unlock (&staging_lock);
+  }
+
+  return (0);
+} /* }}} int staging_entry_update */
+
+static int mc_handle_value_msg (Ganglia_value_msg *msg) /* {{{ */
+{
+  const char *host;
+  const char *name;
+  metric_map_t *map;
+
+  value_t value_counter;
+  value_t value_gauge;
+  value_t value_derive;
+
+  /* Fill in `host', `name', `value_counter', and `value_gauge' according to
+   * the value type, or return with an error. */
+  switch (msg->id) /* {{{ */
+  {
+    case gmetric_uint:
+    {
+      Ganglia_gmetric_uint msg_uint;
+
+      msg_uint = msg->Ganglia_value_msg_u.gu_int;
+
+      host = msg_uint.metric_id.host;
+      name = msg_uint.metric_id.name;
+      value_counter.counter = (counter_t) msg_uint.ui;
+      value_gauge.gauge = (gauge_t) msg_uint.ui;
+      value_derive.derive = (derive_t) msg_uint.ui;
+      break;
+    }
+
+    case gmetric_string:
+    {
+      Ganglia_gmetric_string msg_string;
+      int status;
+
+      msg_string = msg->Ganglia_value_msg_u.gstr;
+
+      host = msg_string.metric_id.host;
+      name = msg_string.metric_id.name;
+
+      status = parse_value (msg_string.str, &value_derive, DS_TYPE_DERIVE);
+      if (status != 0)
+        value_derive.derive = -1;
+
+      status = parse_value (msg_string.str, &value_gauge, DS_TYPE_GAUGE);
+      if (status != 0)
+        value_gauge.gauge = NAN;
+
+      status = parse_value (msg_string.str, &value_counter, DS_TYPE_COUNTER);
+      if (status != 0)
+        value_counter.counter = 0;
+
+      break;
+    }
+
+    case gmetric_float:
+    {
+      Ganglia_gmetric_float msg_float;
+
+      msg_float = msg->Ganglia_value_msg_u.gf;
+
+      host = msg_float.metric_id.host;
+      name = msg_float.metric_id.name;
+      value_counter.counter = (counter_t) msg_float.f;
+      value_gauge.gauge = (gauge_t) msg_float.f;
+      value_derive.derive = (derive_t) msg_float.f;
+      break;
+    }
+
+    case gmetric_double:
+    {
+      Ganglia_gmetric_double msg_double;
+
+      msg_double = msg->Ganglia_value_msg_u.gd;
+
+      host = msg_double.metric_id.host;
+      name = msg_double.metric_id.name;
+      value_counter.counter = (counter_t) msg_double.d;
+      value_gauge.gauge = (gauge_t) msg_double.d;
+      value_derive.derive = (derive_t) msg_double.d;
+      break;
+    }
+    default:
+      DEBUG ("gmond plugin: Value type not handled: %i", msg->id);
+      return (-1);
+  } /* }}} switch (msg->id) */
+
+  assert (host != NULL);
+  assert (name != NULL);
+
+  map = metric_lookup (name);
+  if (map != NULL)
+  {
+    value_t val_copy;
+
+    if ((map->ds_type == DS_TYPE_COUNTER)
+        || (map->ds_type == DS_TYPE_ABSOLUTE))
+      val_copy = value_counter;
+    if (map->ds_type == DS_TYPE_GAUGE)
+      val_copy = value_gauge;
+    else if (map->ds_type == DS_TYPE_DERIVE)
+      val_copy = value_derive;
+    else
+      assert (23 == 42);
+
+    return (staging_entry_update (host, name,
+          map->type, map->type_instance,
+          map->ds_index, map->ds_type,
+          val_copy));
+  }
+
+  DEBUG ("gmond plugin: Cannot find a translation for %s.", name);
+  return (-1);
+} /* }}} int mc_handle_value_msg */
+
+static int mc_handle_metadata_msg (Ganglia_metadata_msg *msg) /* {{{ */
+{
+  switch (msg->id)
+  {
+    case gmetadata_full:
+    {
+      Ganglia_metadatadef msg_meta;
+      staging_entry_t *se;
+      const data_set_t *ds;
+      metric_map_t *map;
+
+      msg_meta = msg->Ganglia_metadata_msg_u.gfull;
+
+      if (msg_meta.metric.tmax <= 0)
+        return (-1);
+
+      map = metric_lookup (msg_meta.metric_id.name);
+      if (map == NULL)
+      {
+        DEBUG ("gmond plugin: Not handling meta data %s.",
+            msg_meta.metric_id.name);
+        return (0);
+      }
+
+      ds = plugin_get_ds (map->type);
+      if (ds == NULL)
+      {
+        WARNING ("gmond plugin: Could not find data set %s.", map->type);
+        return (-1);
+      }
+
+      DEBUG ("gmond plugin: Received meta data for %s/%s.",
+          msg_meta.metric_id.host, msg_meta.metric_id.name);
+
+      pthread_mutex_lock (&staging_lock);
+      se = staging_entry_get (msg_meta.metric_id.host,
+          msg_meta.metric_id.name,
+          map->type, map->type_instance,
+          ds->ds_num);
+      if (se != NULL)
+        se->vl.interval = TIME_T_TO_CDTIME_T (msg_meta.metric.tmax);
+      pthread_mutex_unlock (&staging_lock);
+
+      if (se == NULL)
+      {
+        ERROR ("gmond plugin: staging_entry_get failed.");
+        return (-1);
+      }
+
+      break;
+    }
+
+    default:
+    {
+      return (-1);
+    }
+  }
+
+  return (0);
+} /* }}} int mc_handle_metadata_msg */
+
+static int mc_handle_metric (void *buffer, size_t buffer_size) /* {{{ */
+{
+  XDR xdr;
+  Ganglia_msg_formats format;
+
+  xdrmem_create (&xdr, buffer, buffer_size, XDR_DECODE);
+
+  xdr_Ganglia_msg_formats (&xdr, &format);
+  xdr_setpos (&xdr, 0);
+
+  switch (format)
+  {
+    case gmetric_ushort:
+    case gmetric_short:
+    case gmetric_int:
+    case gmetric_uint:
+    case gmetric_string:
+    case gmetric_float:
+    case gmetric_double:
+    {
+      Ganglia_value_msg msg;
+
+      memset (&msg, 0, sizeof (msg));
+      if (xdr_Ganglia_value_msg (&xdr, &msg))
+        mc_handle_value_msg (&msg);
+      break;
+    }
+
+    case gmetadata_full:
+    case gmetadata_request:
+    {
+      Ganglia_metadata_msg msg;
+      memset (&msg, 0, sizeof (msg));
+      if (xdr_Ganglia_metadata_msg (&xdr, &msg))
+        mc_handle_metadata_msg (&msg);
+      break;
+    }
+
+    default:
+      DEBUG ("gmond plugin: Unknown format: %i", format);
+      return (-1);
+  } /* switch (format) */
+
+
+  return (0);
+} /* }}} int mc_handle_metric */
+
+static int mc_handle_socket (struct pollfd *p) /* {{{ */
+{
+  char buffer[BUFF_SIZE];
+  ssize_t buffer_size;
+
+  if ((p->revents & (POLLIN | POLLPRI)) == 0)
+  {
+    p->revents = 0;
+    return (-1);
+  }
+
+  buffer_size = recv (p->fd, buffer, sizeof (buffer), /* flags = */ 0);
+  if (buffer_size <= 0)
+  {
+    char errbuf[1024];
+    ERROR ("gmond plugin: recv failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    p->revents = 0;
+    return (-1);
+  }
+
+  mc_handle_metric (buffer, (size_t) buffer_size);
+  return (0);
+} /* }}} int mc_handle_socket */
+
+static void *mc_receive_thread (void *arg) /* {{{ */
+{
+  socket_entry_t *mc_receive_socket_entries;
+  int status;
+  size_t i;
+
+  mc_receive_socket_entries = NULL;
+  status = create_sockets (&mc_receive_socket_entries, &mc_receive_sockets_num,
+      (mc_receive_group != NULL) ? mc_receive_group : MC_RECEIVE_GROUP_DEFAULT,
+      (mc_receive_port != NULL) ? mc_receive_port : MC_RECEIVE_PORT_DEFAULT,
+      /* listen = */ 1);
+  if (status != 0)
+  {
+    ERROR ("gmond plugin: create_sockets failed.");
+    return ((void *) -1);
+  }
+
+  mc_receive_sockets = (struct pollfd *) calloc (mc_receive_sockets_num,
+      sizeof (*mc_receive_sockets));
+  if (mc_receive_sockets == NULL)
+  {
+    ERROR ("gmond plugin: calloc failed.");
+    for (i = 0; i < mc_receive_sockets_num; i++)
+      close (mc_receive_socket_entries[i].fd);
+    free (mc_receive_socket_entries);
+    mc_receive_socket_entries = NULL;
+    mc_receive_sockets_num = 0;
+    return ((void *) -1);
+  }
+
+  for (i = 0; i < mc_receive_sockets_num; i++)
+  {
+    mc_receive_sockets[i].fd = mc_receive_socket_entries[i].fd;
+    mc_receive_sockets[i].events = POLLIN | POLLPRI;
+    mc_receive_sockets[i].revents = 0;
+  }
+
+  while (mc_receive_thread_loop != 0)
+  {
+    status = poll (mc_receive_sockets, mc_receive_sockets_num, -1);
+    if (status <= 0)
+    {
+      char errbuf[1024];
+      if (errno == EINTR)
+        continue;
+      ERROR ("gmond plugin: poll failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      break;
+    }
+
+    for (i = 0; i < mc_receive_sockets_num; i++)
+    {
+      if (mc_receive_sockets[i].revents != 0)
+        mc_handle_socket (mc_receive_sockets + i);
+    }
+  } /* while (mc_receive_thread_loop != 0) */
+
+  return ((void *) 0);
+} /* }}} void *mc_receive_thread */
+
+static int mc_receive_thread_start (void) /* {{{ */
+{
+  int status;
+
+  if (mc_receive_thread_running != 0)
+    return (-1);
+
+  mc_receive_thread_loop = 1;
+
+  status = plugin_thread_create (&mc_receive_thread_id, /* attr = */ NULL,
+      mc_receive_thread, /* args = */ NULL);
+  if (status != 0)
+  {
+    ERROR ("gmond plugin: Starting receive thread failed.");
+    mc_receive_thread_loop = 0;
+    return (-1);
+  }
+
+  mc_receive_thread_running = 1;
+  return (0);
+} /* }}} int start_receive_thread */
+
+static int mc_receive_thread_stop (void) /* {{{ */
+{
+  if (mc_receive_thread_running == 0)
+    return (-1);
+
+  mc_receive_thread_loop = 0;
+
+  INFO ("gmond plugin: Stopping receive thread.");
+  pthread_kill (mc_receive_thread_id, SIGTERM);
+  pthread_join (mc_receive_thread_id, /* return value = */ NULL);
+  memset (&mc_receive_thread_id, 0, sizeof (mc_receive_thread_id));
+
+  mc_receive_thread_running = 0;
+
+  return (0);
+} /* }}} int mc_receive_thread_stop */
+
+/* 
+ * Config:
+ *
+ * <Plugin gmond>
+ *   MCReceiveFrom "239.2.11.71" "8649"
+ *   <Metric "load_one">
+ *     Type "load"
+ *     [TypeInstance "foo"]
+ *     [DataSource "bar"]
+ *   </Metric>
+ * </Plugin>
+ */
+static int gmond_config_set_string (oconfig_item_t *ci, char **str) /* {{{ */
+{
+  char *tmp;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("gmond plugin: The `%s' option needs "
+        "exactly one string argument.", ci->key);
+    return (-1);
+  }
+
+  tmp = strdup (ci->values[0].value.string);
+  if (tmp == NULL)
+  {
+    ERROR ("gmond plugin: strdup failed.");
+    return (-1);
+  }
+
+  sfree (*str);
+  *str = tmp;
+  return (0);
+} /* }}} int gmond_config_set_string */
+
+static int gmond_config_add_metric (oconfig_item_t *ci) /* {{{ */
+{
+  metric_map_t *map;
+  int i;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("gmond plugin: `Metric' blocks need "
+        "exactly one string argument.");
+    return (-1);
+  }
+
+  map = realloc (metric_map, (metric_map_len + 1) * sizeof (*metric_map));
+  if (map == NULL)
+  {
+    ERROR ("gmond plugin: realloc failed.");
+    return (-1);
+  }
+  metric_map = map;
+  map = metric_map + metric_map_len;
+
+  memset (map, 0, sizeof (*map));
+  map->type = NULL;
+  map->type_instance = NULL;
+  map->ds_name = NULL;
+  map->ds_type = -1;
+  map->ds_index = -1;
+
+  map->ganglia_name = strdup (ci->values[0].value.string);
+  if (map->ganglia_name == NULL)
+  {
+    ERROR ("gmond plugin: strdup failed.");
+    return (-1);
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp ("Type", child->key) == 0)
+      gmond_config_set_string (child, &map->type);
+    else if (strcasecmp ("TypeInstance", child->key) == 0)
+      gmond_config_set_string (child, &map->type_instance);
+    else if (strcasecmp ("DataSource", child->key) == 0)
+      gmond_config_set_string (child, &map->ds_name);
+    else
+    {
+      WARNING ("gmond plugin: Unknown configuration option `%s' ignored.",
+          child->key);
+    }
+  }
+
+  if (map->type == NULL)
+  {
+    ERROR ("gmond plugin: No type is set for metric %s.",
+        map->ganglia_name);
+    sfree (map->ganglia_name);
+    sfree (map->type_instance);
+    return (-1);
+  }
+
+  metric_map_len++;
+  return (0);
+} /* }}} int gmond_config_add_metric */
+
+static int gmond_config_set_address (oconfig_item_t *ci, /* {{{ */
+    char **ret_addr, char **ret_port)
+{
+  char *addr;
+  char *port;
+
+  if ((ci->values_num != 1) && (ci->values_num != 2))
+  {
+    WARNING ("gmond plugin: The `%s' config option needs "
+        "one or two string arguments.",
+        ci->key);
+    return (-1);
+  }
+  if ((ci->values[0].type != OCONFIG_TYPE_STRING)
+      || ((ci->values_num == 2)
+        && (ci->values[1].type != OCONFIG_TYPE_STRING)))
+  {
+    WARNING ("gmond plugin: The `%s' config option needs "
+        "one or two string arguments.",
+        ci->key);
+    return (-1);
+  }
+
+  addr = strdup (ci->values[0].value.string);
+  if (ci->values_num == 2)
+    port = strdup (ci->values[1].value.string);
+  else
+    port = NULL;
+
+  if ((addr == NULL) || ((ci->values_num == 2) && (port == NULL)))
+  {
+    ERROR ("gmond plugin: strdup failed.");
+    sfree (addr);
+    sfree (port);
+    return (-1);
+  }
+
+  sfree (*ret_addr);
+  sfree (*ret_port);
+
+  *ret_addr = addr;
+  *ret_port = port;
+
+  return (0);
+} /* }}} int gmond_config_set_address */
+
+static int gmond_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp ("MCReceiveFrom", child->key) == 0)
+      gmond_config_set_address (child, &mc_receive_group, &mc_receive_port);
+    else if (strcasecmp ("Metric", child->key) == 0)
+      gmond_config_add_metric (child);
+    else
+    {
+      WARNING ("gmond plugin: Unknown configuration option `%s' ignored.",
+          child->key);
+    }
+  }
+
+  return (0);
+} /* }}} int gmond_config */
+
+static int gmond_init (void) /* {{{ */
+{
+  create_sockets (&mc_send_sockets, &mc_send_sockets_num,
+      (mc_receive_group != NULL) ? mc_receive_group : MC_RECEIVE_GROUP_DEFAULT,
+      (mc_receive_port != NULL) ? mc_receive_port : MC_RECEIVE_PORT_DEFAULT,
+      /* listen = */ 0);
+
+  staging_tree = c_avl_create ((void *) strcmp);
+  if (staging_tree == NULL)
+  {
+    ERROR ("gmond plugin: c_avl_create failed.");
+    return (-1);
+  }
+
+  mc_receive_thread_start ();
+
+  return (0);
+} /* }}} int gmond_init */
+
+static int gmond_shutdown (void) /* {{{ */
+{
+  size_t i;
+
+  mc_receive_thread_stop ();
+
+  pthread_mutex_lock (&mc_send_sockets_lock);
+  for (i = 0; i < mc_send_sockets_num; i++)
+  {
+    close (mc_send_sockets[i].fd);
+    mc_send_sockets[i].fd = -1;
+  }
+  sfree (mc_send_sockets);
+  mc_send_sockets_num = 0;
+  pthread_mutex_unlock (&mc_send_sockets_lock);
+
+
+  return (0);
+} /* }}} int gmond_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("gmond", gmond_config);
+  plugin_register_init ("gmond", gmond_init);
+  plugin_register_shutdown ("gmond", gmond_shutdown);
+}
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/hddtemp.c b/src/hddtemp.c
new file mode 100644 (file)
index 0000000..82c158c
--- /dev/null
@@ -0,0 +1,309 @@
+/**
+ * collectd - src/hddtemp.c
+ * Copyright (C) 2005,2006  Vincent Stehlé
+ * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2008       Sebastian Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Vincent Stehlé <vincent.stehle at free.fr>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ *
+ * TODO:
+ *   Do a pass, some day, and spare some memory. We consume too much for now
+ *   in string buffers and the like.
+ *
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <libgen.h> /* for basename */
+
+#if HAVE_LINUX_MAJOR_H
+# include <linux/major.h>
+#endif
+
+#define HDDTEMP_DEF_HOST "127.0.0.1"
+#define HDDTEMP_DEF_PORT "7634"
+
+static const char *config_keys[] =
+{
+       "Host",
+       "Port"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char *hddtemp_host = NULL;
+static char hddtemp_port[16];
+
+/*
+ * NAME
+ *  hddtemp_query_daemon
+ *
+ * DESCRIPTION
+ * Connect to the hddtemp daemon and receive data.
+ *
+ * ARGUMENTS:
+ *  `buffer'            The buffer where we put the received ascii string.
+ *  `buffer_size'       Size of the buffer
+ *
+ * RETURN VALUE:
+ *   >= 0 if ok, < 0 otherwise.
+ *
+ * NOTES:
+ *  Example of possible strings, as received from daemon:
+ *    |/dev/hda|ST340014A|36|C|
+ *    |/dev/hda|ST380011A|46|C||/dev/hdd|ST340016A|SLP|*|
+ *
+ * FIXME:
+ *  we need to create a new socket each time. Is there another way?
+ *  Hm, maybe we can re-use the `sockaddr' structure? -octo
+ */
+static int hddtemp_query_daemon (char *buffer, int buffer_size)
+{
+       int fd;
+       ssize_t status;
+       int buffer_fill;
+
+       const char *host;
+       const char *port;
+
+       struct addrinfo  ai_hints;
+       struct addrinfo *ai_list, *ai_ptr;
+       int              ai_return;
+
+       memset (&ai_hints, '\0', sizeof (ai_hints));
+       ai_hints.ai_flags    = 0;
+#ifdef AI_ADDRCONFIG
+       ai_hints.ai_flags   |= AI_ADDRCONFIG;
+#endif
+       ai_hints.ai_family   = PF_UNSPEC;
+       ai_hints.ai_socktype = SOCK_STREAM;
+       ai_hints.ai_protocol = IPPROTO_TCP;
+
+       host = hddtemp_host;
+       if (host == NULL)
+               host = HDDTEMP_DEF_HOST;
+
+       port = hddtemp_port;
+       if (strlen (port) == 0)
+               port = HDDTEMP_DEF_PORT;
+
+       if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
+       {
+               char errbuf[1024];
+               ERROR ("hddtemp plugin: getaddrinfo (%s, %s): %s",
+                               host, port,
+                               (ai_return == EAI_SYSTEM)
+                               ? sstrerror (errno, errbuf, sizeof (errbuf))
+                               : gai_strerror (ai_return));
+               return (-1);
+       }
+
+       fd = -1;
+       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               /* create our socket descriptor */
+               fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
+                               ai_ptr->ai_protocol);
+               if (fd < 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("hddtemp plugin: socket: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       continue;
+               }
+
+               /* connect to the hddtemp daemon */
+               if (connect (fd, (struct sockaddr *) ai_ptr->ai_addr,
+                                       ai_ptr->ai_addrlen))
+               {
+                       char errbuf[1024];
+                       INFO ("hddtemp plugin: connect (%s, %s) failed: %s",
+                                       host, port,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (fd);
+                       fd = -1;
+                       continue;
+               }
+
+               /* A socket could be opened and connecting succeeded. We're
+                * done. */
+               break;
+       }
+
+       freeaddrinfo (ai_list);
+
+       if (fd < 0)
+       {
+               ERROR ("hddtemp plugin: Could not connect to daemon.");
+               return (-1);
+       }
+
+       /* receive data from the hddtemp daemon */
+       memset (buffer, '\0', buffer_size);
+
+       buffer_fill = 0;
+       while ((status = read (fd, buffer + buffer_fill, buffer_size - buffer_fill)) != 0)
+       {
+               if (status == -1)
+               {
+                       char errbuf[1024];
+
+                       if ((errno == EAGAIN) || (errno == EINTR))
+                               continue;
+
+                       ERROR ("hddtemp plugin: Error reading from socket: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (fd);
+                       return (-1);
+               }
+               buffer_fill += status;
+
+               if (buffer_fill >= buffer_size)
+                       break;
+       }
+
+       if (buffer_fill >= buffer_size)
+       {
+               buffer[buffer_size - 1] = '\0';
+               WARNING ("hddtemp plugin: Message from hddtemp has been "
+                               "truncated.");
+       }
+       else if (buffer_fill == 0)
+       {
+               WARNING ("hddtemp plugin: Peer has unexpectedly shut down "
+                               "the socket. Buffer: `%s'", buffer);
+               close (fd);
+               return (-1);
+       }
+
+       close (fd);
+       return (0);
+}
+
+static int hddtemp_config (const char *key, const char *value)
+{
+       if (strcasecmp (key, "Host") == 0)
+       {
+               if (hddtemp_host != NULL)
+                       free (hddtemp_host);
+               hddtemp_host = strdup (value);
+       }
+       else if (strcasecmp (key, "Port") == 0)
+       {
+               int port = (int) (atof (value));
+               if ((port > 0) && (port <= 65535))
+                       ssnprintf (hddtemp_port, sizeof (hddtemp_port),
+                                       "%i", port);
+               else
+                       sstrncpy (hddtemp_port, value, sizeof (hddtemp_port));
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+}
+
+static void hddtemp_submit (char *type_instance, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "hddtemp", sizeof (vl.plugin));
+       sstrncpy (vl.type, "temperature", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int hddtemp_read (void)
+{
+       char buf[1024];
+       char *fields[128];
+       char *ptr;
+       char *saveptr;
+       int num_fields;
+       int num_disks;
+       int i;
+
+       /* get data from daemon */
+       if (hddtemp_query_daemon (buf, sizeof (buf)) < 0)
+               return (-1);
+
+       /* NB: strtok_r will eat up "||" and leading "|"'s */
+       num_fields = 0;
+       ptr = buf;
+       saveptr = NULL;
+       while ((fields[num_fields] = strtok_r (ptr, "|", &saveptr)) != NULL)
+       {
+               ptr = NULL;
+               num_fields++;
+
+               if (num_fields >= 128)
+                       break;
+       }
+
+       num_disks = num_fields / 4;
+
+       for (i = 0; i < num_disks; i++)
+       {
+               char *name;
+               double temperature;
+               char *mode;
+
+               mode = fields[4*i + 3];
+               name = basename (fields[4*i + 0]);
+
+               /* Skip non-temperature information */
+               if (mode[0] != 'C' && mode[0] != 'F')
+                       continue;
+
+               temperature = atof (fields[4*i + 2]);
+
+               /* Convert farenheit to celsius */
+               if (mode[0] == 'F')
+                       temperature = (temperature - 32.0) * 5.0 / 9.0;
+
+               hddtemp_submit (name, temperature);
+       }
+       
+       return (0);
+} /* int hddtemp_read */
+
+/* module_register
+   Register collectd plugin. */
+void module_register (void)
+{
+       plugin_register_config ("hddtemp", hddtemp_config,
+                       config_keys, config_keys_num);
+       plugin_register_read ("hddtemp", hddtemp_read);
+}
diff --git a/src/interface.c b/src/interface.c
new file mode 100644 (file)
index 0000000..df8ffb4
--- /dev/null
@@ -0,0 +1,388 @@
+/**
+ * collectd - src/interface.c
+ * Copyright (C) 2005-2010  Florian octo Forster
+ * Copyright (C) 2009       Manuel Sanmartin
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sune Marcher <sm at flork.dk>
+ *   Manuel Sanmartin
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_ignorelist.h"
+
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+
+/* One cannot include both. This sucks. */
+#if HAVE_LINUX_IF_H
+#  include <linux/if.h>
+#elif HAVE_NET_IF_H
+#  include <net/if.h>
+#endif
+
+#if HAVE_LINUX_NETDEVICE_H
+#  include <linux/netdevice.h>
+#endif
+#if HAVE_IFADDRS_H
+#  include <ifaddrs.h>
+#endif
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
+
+#if HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+#endif
+
+/*
+ * Various people have reported problems with `getifaddrs' and varying versions
+ * of `glibc'. That's why it's disabled by default. Since more statistics are
+ * available this way one may enable it using the `--enable-getifaddrs' option
+ * of the configure script. -octo
+ */
+#if KERNEL_LINUX
+# if !COLLECT_GETIFADDRS
+#  undef HAVE_GETIFADDRS
+# endif /* !COLLECT_GETIFADDRS */
+#endif /* KERNEL_LINUX */
+
+#if HAVE_PERFSTAT
+static perfstat_netinterface_t *ifstat;
+static int nif;
+static int pnif;
+#endif /* HAVE_PERFSTAT */
+
+#if !HAVE_GETIFADDRS && !KERNEL_LINUX && !HAVE_LIBKSTAT && !HAVE_LIBSTATGRAB && !HAVE_PERFSTAT
+# error "No applicable input method."
+#endif
+
+/*
+ * (Module-)Global variables
+ */
+static const char *config_keys[] =
+{
+       "Interface",
+       "IgnoreSelected",
+       NULL
+};
+static int config_keys_num = 2;
+
+static ignorelist_t *ignorelist = NULL;
+
+#ifdef HAVE_LIBKSTAT
+#define MAX_NUMIF 256
+extern kstat_ctl_t *kc;
+static kstat_t *ksp[MAX_NUMIF];
+static int numif = 0;
+#endif /* HAVE_LIBKSTAT */
+
+static int interface_config (const char *key, const char *value)
+{
+       if (ignorelist == NULL)
+               ignorelist = ignorelist_create (/* invert = */ 1);
+
+       if (strcasecmp (key, "Interface") == 0)
+       {
+               ignorelist_add (ignorelist, value);
+       }
+       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);
+}
+
+#if HAVE_LIBKSTAT
+static int interface_init (void)
+{
+       kstat_t *ksp_chain;
+       derive_t val;
+
+       numif = 0;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (numif = 0, ksp_chain = kc->kc_chain;
+                       (numif < MAX_NUMIF) && (ksp_chain != NULL);
+                       ksp_chain = ksp_chain->ks_next)
+       {
+               if (strncmp (ksp_chain->ks_class, "net", 3))
+                       continue;
+               if (ksp_chain->ks_type != KSTAT_TYPE_NAMED)
+                       continue;
+               if (kstat_read (kc, ksp_chain, NULL) == -1)
+                       continue;
+               if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
+                       continue;
+               ksp[numif++] = ksp_chain;
+       }
+
+       return (0);
+} /* int interface_init */
+#endif /* HAVE_LIBKSTAT */
+
+static void if_submit (const char *dev, const char *type,
+               derive_t rx,
+               derive_t tx)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       if (ignorelist_match (ignorelist, dev) != 0)
+               return;
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       vl.values = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "interface", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void if_submit */
+
+static int interface_read (void)
+{
+#if HAVE_GETIFADDRS
+       struct ifaddrs *if_list;
+       struct ifaddrs *if_ptr;
+
+/* Darin/Mac OS X and possible other *BSDs */
+#if HAVE_STRUCT_IF_DATA
+#  define IFA_DATA if_data
+#  define IFA_RX_BYTES ifi_ibytes
+#  define IFA_TX_BYTES ifi_obytes
+#  define IFA_RX_PACKT ifi_ipackets
+#  define IFA_TX_PACKT ifi_opackets
+#  define IFA_RX_ERROR ifi_ierrors
+#  define IFA_TX_ERROR ifi_oerrors
+/* #endif HAVE_STRUCT_IF_DATA */
+
+#elif HAVE_STRUCT_NET_DEVICE_STATS
+#  define IFA_DATA net_device_stats
+#  define IFA_RX_BYTES rx_bytes
+#  define IFA_TX_BYTES tx_bytes
+#  define IFA_RX_PACKT rx_packets
+#  define IFA_TX_PACKT tx_packets
+#  define IFA_RX_ERROR rx_errors
+#  define IFA_TX_ERROR tx_errors
+#else
+#  error "No suitable type for `struct ifaddrs->ifa_data' found."
+#endif
+
+       struct IFA_DATA *if_data;
+
+       if (getifaddrs (&if_list) != 0)
+               return (-1);
+
+       for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
+       {
+               if (if_ptr->ifa_addr != NULL && if_ptr->ifa_addr->sa_family == AF_LINK) {
+                       if_data = (struct IFA_DATA *) if_ptr->ifa_data;
+
+                       if_submit (if_ptr->ifa_name, "if_octets",
+                               if_data->IFA_RX_BYTES,
+                               if_data->IFA_TX_BYTES);
+                       if_submit (if_ptr->ifa_name, "if_packets",
+                               if_data->IFA_RX_PACKT,
+                               if_data->IFA_TX_PACKT);
+                       if_submit (if_ptr->ifa_name, "if_errors",
+                               if_data->IFA_RX_ERROR,
+                               if_data->IFA_TX_ERROR);
+               }
+       }
+
+       freeifaddrs (if_list);
+/* #endif HAVE_GETIFADDRS */
+
+#elif KERNEL_LINUX
+       FILE *fh;
+       char buffer[1024];
+       derive_t incoming, outgoing;
+       char *device;
+
+       char *dummy;
+       char *fields[16];
+       int numfields;
+
+       if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("interface plugin: fopen: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buffer, 1024, fh) != NULL)
+       {
+               if (!(dummy = strchr(buffer, ':')))
+                       continue;
+               dummy[0] = '\0';
+               dummy++;
+
+               device = buffer;
+               while (device[0] == ' ')
+                       device++;
+
+               if (device[0] == '\0')
+                       continue;
+
+               numfields = strsplit (dummy, fields, 16);
+
+               if (numfields < 11)
+                       continue;
+
+               incoming = atoll (fields[0]);
+               outgoing = atoll (fields[8]);
+               if_submit (device, "if_octets", incoming, outgoing);
+
+               incoming = atoll (fields[1]);
+               outgoing = atoll (fields[9]);
+               if_submit (device, "if_packets", incoming, outgoing);
+
+               incoming = atoll (fields[2]);
+               outgoing = atoll (fields[10]);
+               if_submit (device, "if_errors", incoming, outgoing);
+       }
+
+       fclose (fh);
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+       int i;
+       derive_t rx;
+       derive_t tx;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (i = 0; i < numif; i++)
+       {
+               if (kstat_read (kc, ksp[i], NULL) == -1)
+                       continue;
+
+               /* try to get 64bit counters */
+               rx = get_kstat_value (ksp[i], "rbytes64");
+               tx = get_kstat_value (ksp[i], "obytes64");
+               /* or fallback to 32bit */
+               if (rx == -1LL)
+                       rx = get_kstat_value (ksp[i], "rbytes");
+               if (tx == -1LL)
+                       tx = get_kstat_value (ksp[i], "obytes");
+               if ((rx != -1LL) || (tx != -1LL))
+                       if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
+
+               /* try to get 64bit counters */
+               rx = get_kstat_value (ksp[i], "ipackets64");
+               tx = get_kstat_value (ksp[i], "opackets64");
+               /* or fallback to 32bit */
+               if (rx == -1LL)
+                       rx = get_kstat_value (ksp[i], "ipackets");
+               if (tx == -1LL)
+                       tx = get_kstat_value (ksp[i], "opackets");
+               if ((rx != -1LL) || (tx != -1LL))
+                       if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
+
+               /* no 64bit error counters yet */
+               rx = get_kstat_value (ksp[i], "ierrors");
+               tx = get_kstat_value (ksp[i], "oerrors");
+               if ((rx != -1LL) || (tx != -1LL))
+                       if_submit (ksp[i]->ks_name, "if_errors", rx, tx);
+       }
+/* #endif HAVE_LIBKSTAT */
+
+#elif defined(HAVE_LIBSTATGRAB)
+       sg_network_io_stats *ios;
+       int i, num;
+
+       ios = sg_get_network_io_stats (&num);
+
+       for (i = 0; i < num; i++)
+               if_submit (ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif defined(HAVE_PERFSTAT)
+       perfstat_id_t id;
+       int i, ifs;
+
+       if ((nif =  perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0)) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("interface plugin: perfstat_netinterface: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       if (pnif != nif || ifstat == NULL)
+       {
+               if (ifstat != NULL)
+                       free(ifstat);
+               ifstat = malloc(nif * sizeof(perfstat_netinterface_t));
+       }
+       pnif = nif;
+
+       id.name[0]='\0';
+       if ((ifs = perfstat_netinterface(&id, ifstat, sizeof(perfstat_netinterface_t), nif)) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("interface plugin: perfstat_netinterface (interfaces=%d): %s",
+                       nif, sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       for (i = 0; i < ifs; i++)
+       {
+               if_submit (ifstat[i].name, "if_octets", ifstat[i].ibytes, ifstat[i].obytes);
+               if_submit (ifstat[i].name, "if_packets", ifstat[i].ipackets ,ifstat[i].opackets);
+               if_submit (ifstat[i].name, "if_errors", ifstat[i].ierrors, ifstat[i].oerrors );
+       }
+#endif /* HAVE_PERFSTAT */
+
+       return (0);
+} /* int interface_read */
+
+void module_register (void)
+{
+       plugin_register_config ("interface", interface_config,
+                       config_keys, config_keys_num);
+#if HAVE_LIBKSTAT
+       plugin_register_init ("interface", interface_init);
+#endif
+       plugin_register_read ("interface", interface_read);
+} /* void module_register */
diff --git a/src/ipc.c b/src/ipc.c
new file mode 100644 (file)
index 0000000..3763f24
--- /dev/null
+++ b/src/ipc.c
@@ -0,0 +1,330 @@
+/**
+ * collectd - src/ipc.c, based on src/memcached.c
+ * Copyright (C) 2010       Andres J. Diaz <ajdiaz@connectical.com>
+ * Copyright (C) 2010       Manuel L. Sanmartin <manuel.luis@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Andres J. Diaz <ajdiaz@connectical.com>
+ *   Manuel L. Sanmartin <manuel.luis@gmail>
+ **/
+
+/* Many of this code is based on busybox ipc implementation, which is:
+ *   (C) Rodney Radford <rradford@mindspring.com> and distributed under GPLv2.
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#if KERNEL_LINUX
+  /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
+  /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
+  /* X/OPEN tells us to use <sys/{types,ipc,shm}.h> for shmctl() */
+# include <sys/types.h>
+# include <sys/ipc.h>
+# include <sys/sem.h>
+# include <sys/msg.h>
+# include <sys/shm.h>
+
+  /* For older kernels the same holds for the defines below */
+# ifndef MSG_STAT
+#  define MSG_STAT    11
+#  define MSG_INFO    12
+# endif
+
+# ifndef SHM_STAT
+#   define SHM_STAT        13
+#   define SHM_INFO        14
+    struct shm_info {
+        int used_ids;
+        ulong shm_tot;      /* total allocated shm */
+        ulong shm_rss;      /* total resident shm */
+        ulong shm_swp;      /* total swapped shm */
+        ulong swap_attempts;
+        ulong swap_successes;
+    };
+# endif
+
+# ifndef SEM_STAT
+#  define SEM_STAT    18
+#  define SEM_INFO    19
+# endif
+
+  /* The last arg of semctl is a union semun, but where is it defined?
+     X/OPEN tells us to define it ourselves, but until recently
+     Linux include files would also define it. */
+# if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+    /* union semun is defined by including <sys/sem.h> */
+# else
+    /* according to X/OPEN we have to define it ourselves */
+    union semun {
+      int val;
+      struct semid_ds *buf;
+      unsigned short *array;
+      struct seminfo *__buf;
+    };
+# endif
+static long pagesize_g;
+/* #endif  KERNEL_LINUX */
+#elif KERNEL_AIX
+# include <sys/ipc_info.h>
+/* #endif KERNEL_AIX */
+#else
+# error "No applicable input method."
+#endif
+
+__attribute__ ((nonnull(1)))
+static void ipc_submit_g (const char *plugin_instance,
+                          const char *type,
+                          const char *type_instance,
+                          gauge_t value) /* {{{ */
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "ipc", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* }}} */
+
+#if KERNEL_LINUX
+static int ipc_read_sem (void) /* {{{ */
+{
+  struct seminfo seminfo;
+  union semun arg;
+  int status;
+
+  arg.array = (void *) &seminfo;
+
+  status = semctl (/* id = */ 0, /* num = */ 0, SEM_INFO, arg);
+  if (status == -1)
+  {
+    char errbuf[1024];
+    ERROR("ipc plugin: semctl(2) failed: %s. "
+        "Maybe the kernel is not configured for semaphores?",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  ipc_submit_g("sem", "count", "arrays", seminfo.semusz);
+  ipc_submit_g("sem", "count", "total", seminfo.semaem);
+
+  return (0);
+} /* }}} int ipc_read_sem */
+
+static int ipc_read_shm (void) /* {{{ */
+{
+  struct shm_info shm_info;
+  int status;
+
+  status = shmctl (/* id = */ 0, SHM_INFO, (void *) &shm_info);
+  if (status == -1)
+  {
+    char errbuf[1024];
+    ERROR("ipc plugin: shmctl(2) failed: %s. "
+        "Maybe the kernel is not configured for shared memory?",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  ipc_submit_g("shm", "segments", NULL, shm_info.used_ids);
+  ipc_submit_g("shm", "bytes", "total", shm_info.shm_tot * pagesize_g);
+  ipc_submit_g("shm", "bytes", "rss", shm_info.shm_rss * pagesize_g);
+  ipc_submit_g("shm", "bytes", "swapped", shm_info.shm_swp * pagesize_g);
+  return (0);
+}
+/* }}} int ipc_read_shm */
+
+static int ipc_read_msg (void) /* {{{ */
+{
+  struct msginfo msginfo;
+
+  if ( msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo) < 0 )
+  {
+    ERROR("Kernel is not configured for message queues");
+    return (-1);
+  }
+  ipc_submit_g("msg", "count", "queues", msginfo.msgmni);
+  ipc_submit_g("msg", "count", "headers", msginfo.msgmap);
+  ipc_submit_g("msg", "count", "space", msginfo.msgtql);
+
+  return (0);
+}
+/* }}} int ipc_read_msg */
+
+static int ipc_init (void) /* {{{ */
+{
+  pagesize_g = sysconf(_SC_PAGESIZE);
+  return (0);
+}
+/* }}} */
+/* #endif KERNEL_LINUX */
+
+#elif KERNEL_AIX
+static caddr_t ipc_get_info (cid_t cid, int cmd, int version, int stsize, int *nmemb) /* {{{ */
+{
+  int size = 0;
+  caddr_t buff = NULL;
+
+  if (get_ipc_info(cid, cmd, version, buff, &size) < 0)
+  {
+    if (errno != ENOSPC) {
+      char errbuf[1024];
+      WARNING ("ipc plugin: get_ipc_info: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (NULL);
+    }
+  }
+
+  if (size == 0)
+    return NULL;
+
+  if (size % stsize) {
+    ERROR ("ipc plugin: ipc_get_info: missmatch struct size and buffer size");
+    return (NULL);
+  }
+
+  *nmemb = size / stsize;
+
+  buff = (caddr_t)malloc (size);
+  if (buff == NULL)  {
+    ERROR ("ipc plugin: ipc_get_info malloc failed.");
+    return (NULL);
+  }
+
+  if (get_ipc_info(cid, cmd, version, buff, &size) < 0)
+  {
+    char errbuf[1024];
+    WARNING ("ipc plugin: get_ipc_info: %s",
+      sstrerror (errno, errbuf, sizeof (errbuf)));
+    free(buff);
+    return (NULL);
+  }
+
+  return buff;
+} /* }}} */
+
+static int ipc_read_sem (void) /* {{{ */
+{
+  ipcinfo_sem_t *ipcinfo_sem;
+  unsigned short sem_nsems=0;
+  unsigned short sems=0;
+  int i,n;
+
+  ipcinfo_sem = (ipcinfo_sem_t *)ipc_get_info(0,
+    GET_IPCINFO_SEM_ALL, IPCINFO_SEM_VERSION, sizeof(ipcinfo_sem_t), &n);
+  if (ipcinfo_sem == NULL)
+    return -1;
+
+  for (i=0; i<n; i++) {
+    sem_nsems += ipcinfo_sem[i].sem_nsems;
+    sems++;
+  }
+  free(ipcinfo_sem);
+
+  ipc_submit_g("sem", "count", "arrays", sem_nsems);
+  ipc_submit_g("sem", "count", "total", sems);
+
+  return (0);
+} /* }}} int ipc_read_sem */
+
+static int ipc_read_shm (void) /* {{{ */
+{
+  ipcinfo_shm_t *ipcinfo_shm;
+  ipcinfo_shm_t *pshm;
+  unsigned int shm_segments=0;
+  size64_t shm_bytes=0;
+  int i,n;
+
+  ipcinfo_shm = (ipcinfo_shm_t *)ipc_get_info(0,
+    GET_IPCINFO_SHM_ALL, IPCINFO_SHM_VERSION, sizeof(ipcinfo_shm_t), &n);
+  if (ipcinfo_shm == NULL)
+    return -1;
+
+  for (i=0, pshm=ipcinfo_shm; i<n; i++, pshm++) {
+    shm_segments++;
+    shm_bytes += pshm->shm_segsz;
+  }
+  free(ipcinfo_shm);
+
+  ipc_submit_g("shm", "segments", NULL, shm_segments);
+  ipc_submit_g("shm", "bytes", "total", shm_bytes);
+
+  return (0);
+}
+/* }}} int ipc_read_shm */
+
+static int ipc_read_msg (void) /* {{{ */
+{
+  ipcinfo_msg_t *ipcinfo_msg;
+  uint32_t msg_used_space=0;
+  uint32_t msg_alloc_queues=0;
+  msgqnum32_t msg_qnum=0;
+  int i,n;
+
+  ipcinfo_msg = (ipcinfo_msg_t *)ipc_get_info(0,
+    GET_IPCINFO_MSG_ALL, IPCINFO_MSG_VERSION, sizeof(ipcinfo_msg_t), &n);
+  if (ipcinfo_msg == NULL)
+    return -1;
+
+  for (i=0; i<n; i++) {
+    msg_alloc_queues++;
+    msg_used_space += ipcinfo_msg[i].msg_cbytes;
+    msg_qnum += ipcinfo_msg[i].msg_qnum;
+
+  free(ipcinfo_msg);
+
+  ipc_submit_g("msg", "count", "queues", msg_alloc_queues);
+  ipc_submit_g("msg", "count", "headers", msg_qnum);
+  ipc_submit_g("msg", "count", "space", msg_used_space);
+
+  return (0);
+}
+/* }}} */
+#endif /* KERNEL_AIX */
+
+static int ipc_read (void) /* {{{ */
+{
+  int x = 0;
+  x |= ipc_read_shm();
+  x |= ipc_read_sem();
+  x |= ipc_read_msg();
+
+  return (x);
+}
+/* }}} */
+
+void module_register (void) /* {{{ */
+{
+#ifdef KERNEL_LINUX
+  plugin_register_init ("ipc", ipc_init);
+#endif
+  plugin_register_read ("ipc", ipc_read);
+}
+/* }}} */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/ipmi.c b/src/ipmi.c
new file mode 100644 (file)
index 0000000..51d33dc
--- /dev/null
@@ -0,0 +1,727 @@
+/**
+ * collectd - src/ipmi.c
+ * Copyright (C) 2008-2009  Florian octo Forster
+ * Copyright (C) 2008       Peter Holik
+ * Copyright (C) 2009       Bruno Prémont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Peter Holik <peter at holik.at>
+ *   Bruno Prémont <bonbons at linux-vserver.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#include <pthread.h>
+
+#include <OpenIPMI/ipmiif.h>
+#include <OpenIPMI/ipmi_err.h>
+#include <OpenIPMI/ipmi_posix.h>
+#include <OpenIPMI/ipmi_conn.h>
+#include <OpenIPMI/ipmi_smi.h>
+
+/*
+ * Private data types
+ */
+struct c_ipmi_sensor_list_s;
+typedef struct c_ipmi_sensor_list_s c_ipmi_sensor_list_t;
+
+struct c_ipmi_sensor_list_s
+{
+  ipmi_sensor_id_t sensor_id;
+  char sensor_name[DATA_MAX_NAME_LEN];
+  char sensor_type[DATA_MAX_NAME_LEN];
+  int sensor_not_present;
+  c_ipmi_sensor_list_t *next;
+};
+
+/*
+ * Module global variables
+ */
+static pthread_mutex_t sensor_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static c_ipmi_sensor_list_t *sensor_list = NULL;
+
+static int c_ipmi_init_in_progress = 0;
+static int c_ipmi_active = 0;
+static pthread_t thread_id = (pthread_t) 0;
+
+static const char *config_keys[] =
+{
+       "Sensor",
+       "IgnoreSelected",
+       "NotifySensorAdd",
+       "NotifySensorRemove",
+       "NotifySensorNotPresent"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+static int c_ipmi_nofiy_add = 0;
+static int c_ipmi_nofiy_remove = 0;
+static int c_ipmi_nofiy_notpresent = 0;
+
+/*
+ * Misc private functions
+ */
+static void c_ipmi_error (const char *func, int status)
+{
+  char errbuf[4096];
+
+  memset (errbuf, 0, sizeof (errbuf));
+
+  if (IPMI_IS_OS_ERR (status))
+  {
+    sstrerror (IPMI_GET_OS_ERR (status), errbuf, sizeof (errbuf));
+  }
+  else if (IPMI_IS_IPMI_ERR (status))
+  {
+    ipmi_get_error_string (IPMI_GET_IPMI_ERR (status), errbuf, sizeof (errbuf));
+  }
+
+  if (errbuf[0] == 0)
+  {
+    ssnprintf (errbuf, sizeof (errbuf), "Unknown error %#x", status);
+  }
+  errbuf[sizeof (errbuf) - 1] = 0;
+
+  ERROR ("ipmi plugin: %s failed: %s", func, errbuf);
+} /* void c_ipmi_error */
+
+/*
+ * Sensor handlers
+ */
+/* Prototype for sensor_list_remove, so sensor_read_handler can call it. */
+static int sensor_list_remove (ipmi_sensor_t *sensor);
+
+static void sensor_read_handler (ipmi_sensor_t *sensor,
+    int err,
+    enum ipmi_value_present_e value_present,
+    unsigned int __attribute__((unused)) raw_value,
+    double value,
+    ipmi_states_t __attribute__((unused)) *states,
+    void *user_data)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  c_ipmi_sensor_list_t *list_item = (c_ipmi_sensor_list_t *)user_data;
+
+  if (err != 0)
+  {
+    if ((err & 0xff) == IPMI_NOT_PRESENT_CC)
+    {
+      if (list_item->sensor_not_present == 0)
+      {
+        list_item->sensor_not_present = 1;
+
+        INFO ("ipmi plugin: sensor_read_handler: sensor %s "
+            "not present.", list_item->sensor_name);
+
+        if (c_ipmi_nofiy_notpresent)
+        {
+          notification_t n = { NOTIF_WARNING, cdtime (), "", "", "ipmi",
+            "", "", "", NULL };
+
+          sstrncpy (n.host, hostname_g, sizeof (n.host));
+          sstrncpy (n.type_instance, list_item->sensor_name,
+              sizeof (n.type_instance));
+          sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+          ssnprintf (n.message, sizeof (n.message),
+              "sensor %s not present", list_item->sensor_name);
+
+          plugin_dispatch_notification (&n);
+        }
+      }
+    }
+    else if (IPMI_IS_IPMI_ERR(err) && IPMI_GET_IPMI_ERR(err) == IPMI_NOT_SUPPORTED_IN_PRESENT_STATE_CC)
+    {
+      INFO ("ipmi plugin: sensor_read_handler: Sensor %s not ready",
+          list_item->sensor_name);
+    }
+    else
+    {
+      if (IPMI_IS_IPMI_ERR(err))
+        INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+            "because it failed with IPMI error %#x.",
+            list_item->sensor_name, IPMI_GET_IPMI_ERR(err));
+      else if (IPMI_IS_OS_ERR(err))
+        INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+            "because it failed with OS error %#x.",
+            list_item->sensor_name, IPMI_GET_OS_ERR(err));
+      else if (IPMI_IS_RMCPP_ERR(err))
+        INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+            "because it failed with RMCPP error %#x.",
+            list_item->sensor_name, IPMI_GET_RMCPP_ERR(err));
+      else if (IPMI_IS_SOL_ERR(err))
+        INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+            "because it failed with RMCPP error %#x.",
+            list_item->sensor_name, IPMI_GET_SOL_ERR(err));
+      else
+        INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+            "because it failed with error %#x. of class %#x",
+            list_item->sensor_name, err & 0xff, err & 0xffffff00);
+      sensor_list_remove (sensor);
+    }
+    return;
+  }
+  else if (list_item->sensor_not_present == 1)
+  {
+    list_item->sensor_not_present = 0;
+
+    INFO ("ipmi plugin: sensor_read_handler: sensor %s present.",
+        list_item->sensor_name);
+
+    if (c_ipmi_nofiy_notpresent)
+    {
+      notification_t n = { NOTIF_OKAY, cdtime (), "", "", "ipmi",
+        "", "", "", NULL };
+
+      sstrncpy (n.host, hostname_g, sizeof (n.host));
+      sstrncpy (n.type_instance, list_item->sensor_name,
+          sizeof (n.type_instance));
+      sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+      ssnprintf (n.message, sizeof (n.message),
+          "sensor %s present", list_item->sensor_name);
+
+      plugin_dispatch_notification (&n);
+    }
+  }
+
+  if (value_present != IPMI_BOTH_VALUES_PRESENT)
+  {
+    INFO ("ipmi plugin: sensor_read_handler: Removing sensor %s, "
+        "because it provides %s. If you need this sensor, "
+        "please file a bug report.",
+        list_item->sensor_name,
+        (value_present == IPMI_RAW_VALUE_PRESENT)
+        ? "only the raw value"
+        : "no value");
+    sensor_list_remove (sensor);
+    return;
+  }
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "ipmi", sizeof (vl.plugin));
+  sstrncpy (vl.type, list_item->sensor_type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, list_item->sensor_name, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void sensor_read_handler */
+
+static int sensor_list_add (ipmi_sensor_t *sensor)
+{
+  ipmi_sensor_id_t sensor_id;
+  c_ipmi_sensor_list_t *list_item;
+  c_ipmi_sensor_list_t *list_prev;
+
+  char buffer[DATA_MAX_NAME_LEN];
+  const char *entity_id_string;
+  char sensor_name[DATA_MAX_NAME_LEN];
+  char *sensor_name_ptr;
+  int sensor_type;
+  const char *type;
+  ipmi_entity_t *ent = ipmi_sensor_get_entity(sensor);
+
+  sensor_id = ipmi_sensor_convert_to_id (sensor);
+
+  memset (buffer, 0, sizeof (buffer));
+  ipmi_sensor_get_name (sensor, buffer, sizeof (buffer));
+  buffer[sizeof (buffer) - 1] = 0;
+
+  entity_id_string = ipmi_entity_get_entity_id_string (ent);
+
+  if (entity_id_string == NULL)
+    sstrncpy (sensor_name, buffer, sizeof (sensor_name));
+  else
+    ssnprintf (sensor_name, sizeof (sensor_name),
+        "%s %s", buffer, entity_id_string);
+
+  sstrncpy (buffer, sensor_name, sizeof (buffer));
+  sensor_name_ptr = strstr (buffer, ").");
+  if (sensor_name_ptr != NULL)
+  {
+    /* If name is something like "foo (123).bar",
+     * change that to "bar (123)".
+     * Both, sensor_name_ptr and sensor_id_ptr point to memory within the
+     * `buffer' array, which holds a copy of the current `sensor_name'. */
+    char *sensor_id_ptr;
+
+    /* `sensor_name_ptr' points to ").bar". */
+    sensor_name_ptr[1] = 0;
+    /* `buffer' holds "foo (123)\0bar\0". */
+    sensor_name_ptr += 2;
+    /* `sensor_name_ptr' now points to "bar". */
+
+    sensor_id_ptr = strstr (buffer, "(");
+    if (sensor_id_ptr != NULL)
+    {
+      /* `sensor_id_ptr' now points to "(123)". */
+      ssnprintf (sensor_name, sizeof (sensor_name),
+          "%s %s", sensor_name_ptr, sensor_id_ptr); 
+    }
+    /* else: don't touch sensor_name. */
+  }
+  sensor_name_ptr = sensor_name;
+
+  /* Both `ignorelist' and `plugin_instance' may be NULL. */
+  if (ignorelist_match (ignorelist, sensor_name_ptr) != 0)
+    return (0);
+
+  /* FIXME: Use rate unit or base unit to scale the value */
+
+  sensor_type = ipmi_sensor_get_sensor_type (sensor);
+  switch (sensor_type)
+  {
+    case IPMI_SENSOR_TYPE_TEMPERATURE:
+      type = "temperature";
+      break;
+
+    case IPMI_SENSOR_TYPE_VOLTAGE:
+      type = "voltage";
+      break;
+
+    case IPMI_SENSOR_TYPE_CURRENT:
+      type = "current";
+      break;
+
+    case IPMI_SENSOR_TYPE_FAN:
+      type = "fanspeed";
+      break;
+
+    default:
+      {
+        const char *sensor_type_str;
+
+        sensor_type_str = ipmi_sensor_get_sensor_type_string (sensor);
+        INFO ("ipmi plugin: sensor_list_add: Ignore sensor %s, "
+            "because I don't know how to handle its type (%#x, %s). "
+            "If you need this sensor, please file a bug report.",
+            sensor_name_ptr, sensor_type, sensor_type_str);
+        return (-1);
+      }
+  } /* switch (sensor_type) */
+
+  pthread_mutex_lock (&sensor_list_lock);
+
+  list_prev = NULL;
+  for (list_item = sensor_list;
+      list_item != NULL;
+      list_item = list_item->next)
+  {
+    if (ipmi_cmp_sensor_id (sensor_id, list_item->sensor_id) == 0)
+      break;
+    list_prev = list_item;
+  } /* for (list_item) */
+
+  if (list_item != NULL)
+  {
+    pthread_mutex_unlock (&sensor_list_lock);
+    return (0);
+  }
+
+  list_item = (c_ipmi_sensor_list_t *) calloc (1, sizeof (c_ipmi_sensor_list_t));
+  if (list_item == NULL)
+  {
+    pthread_mutex_unlock (&sensor_list_lock);
+    return (-1);
+  }
+
+  list_item->sensor_id = ipmi_sensor_convert_to_id (sensor);
+
+  if (list_prev != NULL)
+    list_prev->next = list_item;
+  else
+    sensor_list = list_item;
+
+  sstrncpy (list_item->sensor_name, sensor_name_ptr,
+            sizeof (list_item->sensor_name));
+  sstrncpy (list_item->sensor_type, type, sizeof (list_item->sensor_type));
+
+  pthread_mutex_unlock (&sensor_list_lock);
+
+  if (c_ipmi_nofiy_add && (c_ipmi_init_in_progress == 0))
+  {
+    notification_t n = { NOTIF_OKAY, cdtime (), "", "", "ipmi",
+                         "", "", "", NULL };
+
+    sstrncpy (n.host, hostname_g, sizeof (n.host));
+    sstrncpy (n.type_instance, list_item->sensor_name,
+              sizeof (n.type_instance));
+    sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+    ssnprintf (n.message, sizeof (n.message),
+              "sensor %s added", list_item->sensor_name);
+
+    plugin_dispatch_notification (&n);
+  }
+
+  return (0);
+} /* int sensor_list_add */
+
+static int sensor_list_remove (ipmi_sensor_t *sensor)
+{
+  ipmi_sensor_id_t sensor_id;
+  c_ipmi_sensor_list_t *list_item;
+  c_ipmi_sensor_list_t *list_prev;
+
+  sensor_id = ipmi_sensor_convert_to_id (sensor);
+
+  pthread_mutex_lock (&sensor_list_lock);
+
+  list_prev = NULL;
+  for (list_item = sensor_list;
+      list_item != NULL;
+      list_item = list_item->next)
+  {
+    if (ipmi_cmp_sensor_id (sensor_id, list_item->sensor_id) == 0)
+      break;
+    list_prev = list_item;
+  } /* for (list_item) */
+
+  if (list_item == NULL)
+  {
+    pthread_mutex_unlock (&sensor_list_lock);
+    return (-1);
+  }
+
+  if (list_prev == NULL)
+    sensor_list = list_item->next;
+  else
+    list_prev->next = list_item->next;
+
+  list_prev = NULL;
+  list_item->next = NULL;
+
+  pthread_mutex_unlock (&sensor_list_lock);
+
+  if (c_ipmi_nofiy_remove && c_ipmi_active)
+  {
+    notification_t n = { NOTIF_WARNING, cdtime (), "", "",
+                         "ipmi", "", "", "", NULL };
+
+    sstrncpy (n.host, hostname_g, sizeof (n.host));
+    sstrncpy (n.type_instance, list_item->sensor_name,
+              sizeof (n.type_instance));
+    sstrncpy (n.type, list_item->sensor_type, sizeof (n.type));
+    ssnprintf (n.message, sizeof (n.message),
+              "sensor %s removed", list_item->sensor_name);
+
+    plugin_dispatch_notification (&n);
+  }
+
+  free (list_item);
+  return (0);
+} /* int sensor_list_remove */
+
+static int sensor_list_read_all (void)
+{
+  c_ipmi_sensor_list_t *list_item;
+
+  pthread_mutex_lock (&sensor_list_lock);
+
+  for (list_item = sensor_list;
+      list_item != NULL;
+      list_item = list_item->next)
+  {
+    ipmi_sensor_id_get_reading (list_item->sensor_id,
+        sensor_read_handler, /* user data = */ list_item);
+  } /* for (list_item) */
+
+  pthread_mutex_unlock (&sensor_list_lock);
+
+  return (0);
+} /* int sensor_list_read_all */
+
+static int sensor_list_remove_all (void)
+{
+  c_ipmi_sensor_list_t *list_item;
+
+  pthread_mutex_lock (&sensor_list_lock);
+
+  list_item = sensor_list;
+  sensor_list = NULL;
+
+  pthread_mutex_unlock (&sensor_list_lock);
+
+  while (list_item != NULL)
+  {
+    c_ipmi_sensor_list_t *list_next = list_item->next;
+
+    free (list_item);
+
+    list_item = list_next;
+  } /* while (list_item) */
+
+  return (0);
+} /* int sensor_list_remove_all */
+
+/*
+ * Entity handlers
+ */
+static void entity_sensor_update_handler (enum ipmi_update_e op,
+    ipmi_entity_t __attribute__((unused)) *entity,
+    ipmi_sensor_t *sensor,
+    void __attribute__((unused)) *user_data)
+{
+  /* TODO: Ignore sensors we cannot read */
+
+  if ((op == IPMI_ADDED) || (op == IPMI_CHANGED))
+  {
+    /* Will check for duplicate entries.. */
+    sensor_list_add (sensor);
+  }
+  else if (op == IPMI_DELETED)
+  {
+    sensor_list_remove (sensor);
+  }
+} /* void entity_sensor_update_handler */
+
+/*
+ * Domain handlers
+ */
+static void domain_entity_update_handler (enum ipmi_update_e op,
+    ipmi_domain_t __attribute__((unused)) *domain,
+    ipmi_entity_t *entity,
+    void __attribute__((unused)) *user_data)
+{
+  int status;
+
+  if (op == IPMI_ADDED)
+  {
+    status = ipmi_entity_add_sensor_update_handler (entity,
+        entity_sensor_update_handler, /* user data = */ NULL);
+    if (status != 0)
+    {
+      c_ipmi_error ("ipmi_entity_add_sensor_update_handler", status);
+    }
+  }
+  else if (op == IPMI_DELETED)
+  {
+    status = ipmi_entity_remove_sensor_update_handler (entity,
+        entity_sensor_update_handler, /* user data = */ NULL);
+    if (status != 0)
+    {
+      c_ipmi_error ("ipmi_entity_remove_sensor_update_handler", status);
+    }
+  }
+} /* void domain_entity_update_handler */
+
+static void domain_connection_change_handler (ipmi_domain_t *domain,
+    int err,
+    unsigned int conn_num,
+    unsigned int port_num,
+    int still_connected,
+    void *user_data)
+{
+  int status;
+
+  DEBUG ("domain_connection_change_handler (domain = %p, err = %i, "
+      "conn_num = %u, port_num = %u, still_connected = %i, "
+      "user_data = %p);\n",
+      (void *) domain, err, conn_num, port_num, still_connected, user_data);
+
+  status = ipmi_domain_add_entity_update_handler (domain,
+      domain_entity_update_handler, /* user data = */ NULL);
+  if (status != 0)
+  {
+    c_ipmi_error ("ipmi_domain_add_entity_update_handler", status);
+  }
+} /* void domain_connection_change_handler */
+
+static int thread_init (os_handler_t **ret_os_handler)
+{
+  os_handler_t *os_handler;
+  ipmi_open_option_t open_option[1];
+  ipmi_con_t *smi_connection = NULL;
+  ipmi_domain_id_t domain_id;
+  int status;
+
+  os_handler = ipmi_posix_thread_setup_os_handler (SIGIO);
+  if (os_handler == NULL)
+  {
+    ERROR ("ipmi plugin: ipmi_posix_thread_setup_os_handler failed.");
+    return (-1);
+  }
+
+  ipmi_init (os_handler);
+
+  status = ipmi_smi_setup_con (/* if_num = */ 0,
+      os_handler,
+      /* user data = */ NULL,
+      &smi_connection);
+  if (status != 0)
+  {
+    c_ipmi_error ("ipmi_smi_setup_con", status);
+    return (-1);
+  }
+
+  memset (open_option, 0, sizeof (open_option));
+  open_option[0].option = IPMI_OPEN_OPTION_ALL;
+  open_option[0].ival = 1;
+
+  status = ipmi_open_domain ("mydomain", &smi_connection, /* num_con = */ 1,
+      domain_connection_change_handler, /* user data = */ NULL,
+      /* domain_fully_up_handler = */ NULL, /* user data = */ NULL,
+      open_option, sizeof (open_option) / sizeof (open_option[0]),
+      &domain_id);
+  if (status != 0)
+  {
+    c_ipmi_error ("ipmi_open_domain", status);
+    return (-1);
+  }
+
+  *ret_os_handler = os_handler;
+  return (0);
+} /* int thread_init */
+
+static void *thread_main (void __attribute__((unused)) *user_data)
+{
+  int status;
+  os_handler_t *os_handler = NULL;
+
+  status = thread_init (&os_handler);
+  if (status != 0)
+  {
+    ERROR ("ipmi plugin: thread_init failed.\n");
+    return ((void *) -1);
+  }
+
+  while (c_ipmi_active != 0)
+  {
+    struct timeval tv = { 1, 0 };
+    os_handler->perform_one_op (os_handler, &tv);
+  }
+
+  ipmi_posix_thread_free_os_handler (os_handler);
+
+  return ((void *) 0);
+} /* void *thread_main */
+
+static int c_ipmi_config (const char *key, const char *value)
+{
+  if (ignorelist == NULL)
+    ignorelist = ignorelist_create (/* invert = */ 1);
+  if (ignorelist == NULL)
+    return (1);
+
+  if (strcasecmp ("Sensor", key) == 0)
+  {
+    ignorelist_add (ignorelist, value);
+  }
+  else if (strcasecmp ("IgnoreSelected", key) == 0)
+  {
+    int invert = 1;
+    if (IS_TRUE (value))
+      invert = 0;
+    ignorelist_set_invert (ignorelist, invert);
+  }
+  else if (strcasecmp ("NotifySensorAdd", key) == 0)
+  {
+    if (IS_TRUE (value))
+      c_ipmi_nofiy_add = 1;
+  }
+  else if (strcasecmp ("NotifySensorRemove", key) == 0)
+  {
+    if (IS_TRUE (value))
+      c_ipmi_nofiy_remove = 1;
+  }
+  else if (strcasecmp ("NotifySensorNotPresent", key) == 0)
+  {
+    if (IS_TRUE (value))
+      c_ipmi_nofiy_notpresent = 1;
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int c_ipmi_config */
+
+static int c_ipmi_init (void)
+{
+  int status;
+
+  /* Don't send `ADD' notifications during startup (~ 1 minute) */
+  time_t iv = CDTIME_T_TO_TIME_T (plugin_get_interval ());
+  c_ipmi_init_in_progress = 1 + (60 / iv);
+
+  c_ipmi_active = 1;
+
+  status = plugin_thread_create (&thread_id, /* attr = */ NULL, thread_main,
+      /* user data = */ NULL);
+  if (status != 0)
+  {
+    c_ipmi_active = 0;
+    thread_id = (pthread_t) 0;
+    ERROR ("ipmi plugin: pthread_create failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* int c_ipmi_init */
+
+static int c_ipmi_read (void)
+{
+  if ((c_ipmi_active == 0) || (thread_id == (pthread_t) 0))
+  {
+    INFO ("ipmi plugin: c_ipmi_read: I'm not active, returning false.");
+    return (-1);
+  }
+
+  sensor_list_read_all ();
+
+  if (c_ipmi_init_in_progress > 0)
+    c_ipmi_init_in_progress--;
+  else
+    c_ipmi_init_in_progress = 0;
+
+  return (0);
+} /* int c_ipmi_read */
+
+static int c_ipmi_shutdown (void)
+{
+  c_ipmi_active = 0;
+
+  if (thread_id != (pthread_t) 0)
+  {
+    pthread_join (thread_id, NULL);
+    thread_id = (pthread_t) 0;
+  }
+
+  sensor_list_remove_all ();
+
+  return (0);
+} /* int c_ipmi_shutdown */
+
+void module_register (void)
+{
+  plugin_register_config ("ipmi", c_ipmi_config,
+      config_keys, config_keys_num);
+  plugin_register_init ("ipmi", c_ipmi_init);
+  plugin_register_read ("ipmi", c_ipmi_read);
+  plugin_register_shutdown ("ipmi", c_ipmi_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 ts=8 fdm=marker et : */
diff --git a/src/iptables.c b/src/iptables.c
new file mode 100644 (file)
index 0000000..49454f0
--- /dev/null
@@ -0,0 +1,524 @@
+/**
+ * collectd - src/iptables.c
+ * Copyright (C) 2007       Sjoerd van der Berg
+ * Copyright (C) 2007-2010  Florian octo Forster
+ * Copyright (C) 2009       Marco Chiappero
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *  Sjoerd van der Berg <harekiet at users.sourceforge.net>
+ *  Florian Forster <octo at collectd.org>
+ *  Marco Chiappero <marco at absence.it>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <sys/socket.h>
+
+#include <libiptc/libiptc.h>
+#include <libiptc/libip6tc.h>
+
+/*
+ * iptc_handle_t was available before libiptc was officially available as a
+ * shared library. Note, that when the shared lib was introduced, the API and
+ * ABI have changed slightly:
+ * 'iptc_handle_t' used to be 'struct iptc_handle *' and most functions used
+ * 'iptc_handle_t *' as an argument. Now, most functions use 'struct
+ * iptc_handle *' (thus removing one level of pointer indirection).
+ *
+ * HAVE_IPTC_HANDLE_T is used to determine which API ought to be used. While
+ * this is somewhat hacky, I didn't find better way to solve that :-/
+ * -tokkee
+ */
+#ifndef HAVE_IPTC_HANDLE_T
+typedef struct iptc_handle iptc_handle_t;
+#endif
+#ifndef HAVE_IP6TC_HANDLE_T
+typedef struct ip6tc_handle ip6tc_handle_t;
+#endif
+
+/*
+ * (Module-)Global variables
+ */
+
+/*
+ * Config format should be `Chain table chainname',
+ * e. g. `Chain mangle incoming'
+ */
+static const char *config_keys[] =
+{
+       "Chain",
+       "Chain6"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+/*
+    Each table/chain combo that will be queried goes into this list
+*/
+
+enum protocol_version_e
+{
+    IPV4,
+    IPV6
+};
+typedef enum protocol_version_e protocol_version_t;
+
+#ifndef XT_TABLE_MAXNAMELEN
+# define XT_TABLE_MAXNAMELEN 32
+#endif
+typedef struct {
+    protocol_version_t ip_version;
+    char table[XT_TABLE_MAXNAMELEN];
+    char chain[XT_TABLE_MAXNAMELEN];
+    union
+    {
+       int   num;
+       char *comment;
+    } rule;
+    enum
+    {
+       RTYPE_NUM,
+       RTYPE_COMMENT,
+       RTYPE_COMMENT_ALL
+    } rule_type;
+    char name[64];
+} ip_chain_t;
+
+static ip_chain_t **chain_list = NULL;
+static int chain_num = 0;
+
+static int iptables_config (const char *key, const char *value)
+{
+       /* int ip_value; */
+       protocol_version_t ip_version = 0;
+
+       if (strcasecmp (key, "Chain") == 0)
+               ip_version = IPV4;
+       else if (strcasecmp (key, "Chain6") == 0)
+               ip_version = IPV6;
+
+       if (( ip_version == IPV4 ) || ( ip_version == IPV6 ))
+       {
+               ip_chain_t temp, *final, **list;
+               char *table;
+               int   table_len;
+               char *chain;
+               int   chain_len;
+
+               char *value_copy;
+               char *fields[4];
+               int   fields_num;
+               
+               memset (&temp, 0, sizeof (temp));
+
+               value_copy = strdup (value);
+               if (value_copy == NULL)
+               {
+                   char errbuf[1024];
+                   ERROR ("strdup failed: %s",
+                           sstrerror (errno, errbuf, sizeof (errbuf)));
+                   return (1);
+               }
+
+               /*
+                *  Time to fill the temp element
+                *  Examine value string, it should look like:
+                *  Chain[6] <table> <chain> [<comment|num> [name]]
+                        */
+
+               /* set IPv4 or IPv6 */
+                temp.ip_version = ip_version;
+
+               /* Chain <table> <chain> [<comment|num> [name]] */
+               fields_num = strsplit (value_copy, fields, 4);
+               if (fields_num < 2)
+               {
+                   free (value_copy);
+                   return (1);
+               }
+
+               table = fields[0];
+               chain = fields[1];
+
+               table_len = strlen (table) + 1;
+               if ((unsigned int)table_len > sizeof(temp.table))
+               {
+                       ERROR ("Table `%s' too long.", table);
+                       free (value_copy);
+                       return (1);
+               }
+               sstrncpy (temp.table, table, table_len);
+
+               chain_len = strlen (chain) + 1;
+               if ((unsigned int)chain_len > sizeof(temp.chain))
+               {
+                       ERROR ("Chain `%s' too long.", chain);
+                       free (value_copy);
+                       return (1);
+               }
+               sstrncpy (temp.chain, chain, chain_len);
+
+               if (fields_num >= 3)
+               {
+                   char *comment = fields[2];
+                   int   rule = atoi (comment);
+
+                   if (rule)
+                   {
+                       temp.rule.num = rule;
+                       temp.rule_type = RTYPE_NUM;
+                   }
+                   else
+                   {
+                       temp.rule.comment = strdup (comment);
+                       if (temp.rule.comment == NULL)
+                       {
+                           free (value_copy);
+                           return (1);
+                       }
+                       temp.rule_type = RTYPE_COMMENT;
+                   }
+               }
+               else
+               {
+                   temp.rule_type = RTYPE_COMMENT_ALL;
+               }
+
+               if (fields_num >= 4)
+                   sstrncpy (temp.name, fields[3], sizeof (temp.name));
+
+               free (value_copy);
+               value_copy = NULL;
+               table = NULL;
+               chain = NULL;
+
+               list = (ip_chain_t **) realloc (chain_list, (chain_num + 1) * sizeof (ip_chain_t *));
+               if (list == NULL)
+               {
+                   char errbuf[1024];
+                   ERROR ("realloc failed: %s",
+                           sstrerror (errno, errbuf, sizeof (errbuf)));
+                   return (1);
+               }
+
+               chain_list = list;
+               final = (ip_chain_t *) malloc( sizeof(temp) );
+               if (final == NULL) 
+               {
+                   char errbuf[1024];
+                   ERROR ("malloc failed: %s",
+                           sstrerror (errno, errbuf, sizeof (errbuf)));
+                   return (1);
+               }
+               memcpy (final, &temp, sizeof (temp));
+               chain_list[chain_num] = final;
+               chain_num++;
+
+               DEBUG ("Chain #%i: table = %s; chain = %s;", chain_num, final->table, final->chain);
+       }
+       else 
+       {
+               return (-1);
+       }
+
+       return (0);
+} /* int iptables_config */
+
+static int submit6_match (const struct ip6t_entry_match *match,
+                const struct ip6t_entry *entry,
+                const ip_chain_t *chain,
+                int rule_num)
+{
+    int status;
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    /* Select the rules to collect */
+    if (chain->rule_type == RTYPE_NUM)
+    {
+        if (chain->rule.num != rule_num)
+            return (0);
+    }
+    else
+    {
+        if (strcmp (match->u.user.name, "comment") != 0)
+            return (0);
+        if ((chain->rule_type == RTYPE_COMMENT)
+                && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+            return (0);
+    }
+
+    vl.values = values;
+    vl.values_len = 1;
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "ip6tables", sizeof (vl.plugin));
+
+    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);
+
+    if (chain->name[0] != '\0')
+    {
+        sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
+    }
+    else
+    {
+        if (chain->rule_type == RTYPE_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));
+    }
+
+    sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
+    values[0].derive = (derive_t) entry->counters.bcnt;
+    plugin_dispatch_values (&vl);
+
+    sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
+    values[0].derive = (derive_t) entry->counters.pcnt;
+    plugin_dispatch_values (&vl);
+
+    return (0);
+} /* int submit_match */
+
+
+/* This needs to return `int' for IPT_MATCH_ITERATE to work. */
+static int submit_match (const struct ipt_entry_match *match,
+               const struct ipt_entry *entry,
+               const ip_chain_t *chain,
+               int rule_num) 
+{
+    int status;
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    /* Select the rules to collect */
+    if (chain->rule_type == RTYPE_NUM)
+    {
+       if (chain->rule.num != rule_num)
+           return (0);
+    }
+    else
+    {
+       if (strcmp (match->u.user.name, "comment") != 0)
+           return (0);
+       if ((chain->rule_type == RTYPE_COMMENT)
+               && (strcmp (chain->rule.comment, (char *) match->data) != 0))
+           return (0);
+    }
+
+    vl.values = values;
+    vl.values_len = 1;
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
+
+    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);
+
+    if (chain->name[0] != '\0')
+    {
+       sstrncpy (vl.type_instance, chain->name, sizeof (vl.type_instance));
+    }
+    else
+    {
+       if (chain->rule_type == RTYPE_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));
+    }
+
+    sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
+    values[0].derive = (derive_t) entry->counters.bcnt;
+    plugin_dispatch_values (&vl);
+
+    sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
+    values[0].derive = (derive_t) entry->counters.pcnt;
+    plugin_dispatch_values (&vl);
+
+    return (0);
+} /* int submit_match */
+
+
+/* ipv6 submit_chain */
+static void submit6_chain( ip6tc_handle_t *handle, ip_chain_t *chain )
+{
+    const struct ip6t_entry *entry;
+    int rule_num;
+
+    /* Find first rule for chain and use the iterate macro */
+    entry = ip6tc_first_rule( chain->chain, handle );
+    if (entry == NULL)
+    {
+        DEBUG ("ip6tc_first_rule failed: %s", ip6tc_strerror (errno));
+        return;
+    }
+
+    rule_num = 1;
+    while (entry)
+    {
+        if (chain->rule_type == RTYPE_NUM)
+        {
+            submit6_match (NULL, entry, chain, rule_num);
+        }
+        else
+        {
+            IP6T_MATCH_ITERATE( entry, submit6_match, entry, chain, rule_num );
+        }
+
+        entry = ip6tc_next_rule( entry, handle );
+        rule_num++;
+    } /* while (entry) */
+}
+
+
+/* ipv4 submit_chain */
+static void submit_chain( iptc_handle_t *handle, ip_chain_t *chain )
+{
+    const struct ipt_entry *entry;
+    int rule_num;
+
+    /* Find first rule for chain and use the iterate macro */    
+    entry = iptc_first_rule( chain->chain, handle );
+    if (entry == NULL)
+    {
+       DEBUG ("iptc_first_rule failed: %s", iptc_strerror (errno));
+       return;
+    }
+
+    rule_num = 1;
+    while (entry)
+    {
+       if (chain->rule_type == RTYPE_NUM)
+       {
+           submit_match (NULL, entry, chain, rule_num);
+       }
+       else
+       {
+           IPT_MATCH_ITERATE( entry, submit_match, entry, chain, rule_num );
+       }
+
+       entry = iptc_next_rule( entry, handle );
+       rule_num++;
+    } /* while (entry) */
+}
+
+
+static int iptables_read (void)
+{
+    int i;
+    int num_failures = 0;
+    ip_chain_t *chain;
+
+    /* Init the iptc handle structure and query the correct table */    
+    for (i = 0; i < chain_num; i++)
+    {
+       chain = chain_list[i];
+       
+       if (!chain)
+       {
+           DEBUG ("iptables plugin: chain == NULL");
+           continue;
+       }
+
+       if ( chain->ip_version == IPV4 )
+        {
+#ifdef HAVE_IPTC_HANDLE_T
+               iptc_handle_t _handle;
+               iptc_handle_t *handle = &_handle;
+
+               *handle = iptc_init (chain->table);
+#else
+               iptc_handle_t *handle;
+                handle = iptc_init (chain->table);
+#endif
+
+                if (!handle)
+                {
+                        ERROR ("iptables plugin: iptc_init (%s) failed: %s",
+                                chain->table, iptc_strerror (errno));
+                        num_failures++;
+                        continue;
+                }
+
+                submit_chain (handle, chain);
+                iptc_free (handle);
+        }
+        else if ( chain->ip_version == IPV6 )
+        {
+#ifdef HAVE_IP6TC_HANDLE_T
+               ip6tc_handle_t _handle;
+               ip6tc_handle_t *handle = &_handle;
+
+               *handle = ip6tc_init (chain->table);
+#else
+                ip6tc_handle_t *handle;
+                handle = ip6tc_init (chain->table);
+#endif
+
+                if (!handle)
+                {
+                        ERROR ("iptables plugin: ip6tc_init (%s) failed: %s",
+                                chain->table, ip6tc_strerror (errno));
+                        num_failures++;
+                        continue;
+                }
+
+                submit6_chain (handle, chain);
+                ip6tc_free (handle);
+        }
+        else num_failures++;
+
+    } /* for (i = 0 .. chain_num) */
+
+    return ((num_failures < chain_num) ? 0 : -1);
+} /* int iptables_read */
+
+static int iptables_shutdown (void)
+{
+    int i;
+
+    for (i = 0; i < chain_num; i++)
+    {
+       if ((chain_list[i] != NULL) && (chain_list[i]->rule_type == RTYPE_COMMENT))
+       {
+           sfree (chain_list[i]->rule.comment);
+       }
+       sfree (chain_list[i]);
+    }
+    sfree (chain_list);
+
+    return (0);
+} /* int iptables_shutdown */
+
+void module_register (void)
+{
+    plugin_register_config ("iptables", iptables_config,
+           config_keys, config_keys_num);
+    plugin_register_read ("iptables", iptables_read);
+    plugin_register_shutdown ("iptables", iptables_shutdown);
+} /* void module_register */
+
+/*
+ * vim:shiftwidth=4:softtabstop=4:tabstop=8
+ */
diff --git a/src/ipvs.c b/src/ipvs.c
new file mode 100644 (file)
index 0000000..fa89489
--- /dev/null
@@ -0,0 +1,346 @@
+/**
+ * collectd - src/ipvs.c (based on ipvsadm and libipvs)
+ * Copyright (C) 1997  Steven Clarke <steven@monmouth.demon.co.uk>
+ * Copyright (C) 1998-2004  Wensong Zhang <wensong@linuxvirtualserver.org>
+ * Copyright (C) 2003-2004  Peter Kese <peter.kese@ijs.si>
+ * Copyright (C) 2007  Sebastian Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This plugin collects statistics about IPVS connections. It requires Linux
+ * kernels >= 2.6.
+ *
+ * See http://www.linuxvirtualserver.org/software/index.html for more
+ * information about IPVS.
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif /* HAVE_ARPA_INET_H */
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif /* HAVE_SYS_SOCKET_H */
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
+
+/* this can probably only be found in the kernel sources */
+#if HAVE_LINUX_IP_VS_H
+# include <linux/ip_vs.h>
+#elif HAVE_NET_IP_VS_H
+# include <net/ip_vs.h>
+#elif HAVE_IP_VS_H
+# include <ip_vs.h>
+#endif /* HAVE_IP_VS_H */
+
+#define log_err(...) ERROR ("ipvs: " __VA_ARGS__)
+#define log_info(...) INFO ("ipvs: " __VA_ARGS__)
+
+/*
+ * private variables
+ */
+static int sockfd = -1;
+
+/*
+ * libipvs API
+ */
+static struct ip_vs_get_services *ipvs_get_services (void)
+{
+       struct ip_vs_getinfo       ipvs_info;
+       struct ip_vs_get_services *ret;
+
+       socklen_t len;
+
+       len = sizeof (ipvs_info);
+
+       if (0 != getsockopt (sockfd, IPPROTO_IP, IP_VS_SO_GET_INFO,
+                               (void *)&ipvs_info, &len)) {
+               char errbuf[1024];
+               log_err ("ip_vs_get_services: getsockopt() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return NULL;
+       }
+
+       len = sizeof (*ret) +
+               sizeof (struct ip_vs_service_entry) * ipvs_info.num_services;
+
+       if (NULL == (ret = malloc (len))) {
+               log_err ("ipvs_get_services: Out of memory.");
+               exit (3);
+       }
+
+       ret->num_services = ipvs_info.num_services;
+
+       if (0 != getsockopt (sockfd, IPPROTO_IP, IP_VS_SO_GET_SERVICES,
+                               (void *)ret, &len)) {
+               char errbuf[1024];
+               log_err ("ipvs_get_services: getsockopt failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+
+               free(ret);
+               return NULL;
+       }
+       return ret;
+} /* ipvs_get_services */
+
+static struct ip_vs_get_dests *ipvs_get_dests (struct ip_vs_service_entry *se)
+{
+       struct ip_vs_get_dests *ret;
+       socklen_t len;
+
+       len = sizeof (*ret) + sizeof (struct ip_vs_dest_entry) * se->num_dests;
+
+       if (NULL == (ret = malloc (len))) {
+               log_err ("ipvs_get_dests: Out of memory.");
+               exit (3);
+       }
+
+       ret->fwmark    = se->fwmark;
+       ret->protocol  = se->protocol;
+       ret->addr      = se->addr;
+       ret->port      = se->port;
+       ret->num_dests = se->num_dests;
+
+       if (0 != getsockopt (sockfd, IPPROTO_IP, IP_VS_SO_GET_DESTS,
+                               (void *)ret, &len)) {
+               char errbuf[1024];
+               log_err ("ipvs_get_dests: getsockopt() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               free (ret);
+               return NULL;
+       }
+       return ret;
+} /* ip_vs_get_dests */
+
+/*
+ * collectd plugin API and helper functions
+ */
+static int cipvs_init (void)
+{
+       struct ip_vs_getinfo ipvs_info;
+
+       socklen_t len;
+
+       if (-1 == (sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW))) {
+               char errbuf[1024];
+               log_err ("cipvs_init: socket() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       len = sizeof (ipvs_info);
+
+       if (0 != getsockopt (sockfd, IPPROTO_IP, IP_VS_SO_GET_INFO,
+                               (void *)&ipvs_info, &len)) {
+               char errbuf[1024];
+               log_err ("cipvs_init: getsockopt() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (sockfd);
+               sockfd = -1;
+               return -1;
+       }
+
+       /* we need IPVS >= 1.1.4 */
+       if (ipvs_info.version < ((1 << 16) + (1 << 8) + 4)) {
+               log_err ("cipvs_init: IPVS version too old (%d.%d.%d < %d.%d.%d)",
+                               NVERSION (ipvs_info.version), 1, 1, 4);
+               close (sockfd);
+               sockfd = -1;
+               return -1;
+       }
+       else {
+               log_info ("Successfully connected to IPVS %d.%d.%d",
+                               NVERSION (ipvs_info.version));
+       }
+       return 0;
+} /* cipvs_init */
+
+/*
+ * ipvs-<virtual IP>_{UDP,TCP}<port>/<type>-total
+ * ipvs-<virtual IP>_{UDP,TCP}<port>/<type>-<real IP>_<port>
+ */
+
+/* plugin instance */
+static int get_pi (struct ip_vs_service_entry *se, char *pi, size_t size)
+{
+       struct in_addr addr;
+       int len = 0;
+
+       if ((NULL == se) || (NULL == pi))
+               return 0;
+
+       addr.s_addr = se->addr;
+
+       /* inet_ntoa() returns a pointer to a statically allocated buffer
+        * I hope non-glibc systems behave the same */
+       len = ssnprintf (pi, size, "%s_%s%u", inet_ntoa (addr),
+                       (se->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
+                       ntohs (se->port));
+
+       if ((0 > len) || (size <= len)) {
+               log_err ("plugin instance truncated: %s", pi);
+               return -1;
+       }
+       return 0;
+} /* get_pi */
+
+/* type instance */
+static int get_ti (struct ip_vs_dest_entry *de, char *ti, size_t size)
+{
+       struct in_addr addr;
+       int len = 0;
+
+       if ((NULL == de) || (NULL == ti))
+               return 0;
+
+       addr.s_addr = de->addr;
+
+       /* inet_ntoa() returns a pointer to a statically allocated buffer
+        * I hope non-glibc systems behave the same */
+       len = ssnprintf (ti, size, "%s_%u", inet_ntoa (addr),
+                       ntohs (de->port));
+
+       if ((0 > len) || (size <= len)) {
+               log_err ("type instance truncated: %s", ti);
+               return -1;
+       }
+       return 0;
+} /* get_ti */
+
+static void cipvs_submit_connections (char *pi, char *ti, derive_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = value;
+
+       vl.values     = values;
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "connections", sizeof (vl.type));
+       sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total",
+               sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+       return;
+} /* cipvs_submit_connections */
+
+static void cipvs_submit_if (char *pi, char *t, char *ti,
+               derive_t rx, derive_t tx)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       vl.values     = values;
+       vl.values_len = 2;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, t, sizeof (vl.type));
+       sstrncpy (vl.type_instance, (NULL != ti) ? ti : "total",
+               sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+       return;
+} /* cipvs_submit_if */
+
+static void cipvs_submit_dest (char *pi, struct ip_vs_dest_entry *de) {
+       struct ip_vs_stats_user stats = de->stats;
+
+       char ti[DATA_MAX_NAME_LEN];
+
+       if (0 != get_ti (de, ti, sizeof (ti)))
+               return;
+
+       cipvs_submit_connections (pi, ti, stats.conns);
+       cipvs_submit_if (pi, "if_packets", ti, stats.inpkts, stats.outpkts);
+       cipvs_submit_if (pi, "if_octets", ti, stats.inbytes, stats.outbytes);
+       return;
+} /* cipvs_submit_dest */
+
+static void cipvs_submit_service (struct ip_vs_service_entry *se)
+{
+       struct ip_vs_stats_user  stats = se->stats;
+       struct ip_vs_get_dests  *dests = ipvs_get_dests (se);
+
+       char pi[DATA_MAX_NAME_LEN];
+
+       int i = 0;
+
+       if (0 != get_pi (se, pi, sizeof (pi)))
+               return;
+
+       cipvs_submit_connections (pi, NULL, stats.conns);
+       cipvs_submit_if (pi, "if_packets", NULL, stats.inpkts, stats.outpkts);
+       cipvs_submit_if (pi, "if_octets", NULL, stats.inbytes, stats.outbytes);
+
+       for (i = 0; i < dests->num_dests; ++i)
+               cipvs_submit_dest (pi, &dests->entrytable[i]);
+
+       free (dests);
+       return;
+} /* cipvs_submit_service */
+
+static int cipvs_read (void)
+{
+       struct ip_vs_get_services *services = NULL;
+       int i = 0;
+
+       if (sockfd < 0)
+               return (-1);
+
+       if (NULL == (services = ipvs_get_services ()))
+               return -1;
+
+       for (i = 0; i < services->num_services; ++i)
+               cipvs_submit_service (&services->entrytable[i]);
+
+       free (services);
+       return 0;
+} /* cipvs_read */
+
+static int cipvs_shutdown (void)
+{
+       if (sockfd >= 0)
+               close (sockfd);
+       sockfd = -1;
+
+       return 0;
+} /* cipvs_shutdown */
+
+void module_register (void)
+{
+       plugin_register_init ("ipvs", cipvs_init);
+       plugin_register_read ("ipvs", cipvs_read);
+       plugin_register_shutdown ("ipvs", cipvs_shutdown);
+       return;
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --git a/src/irq.c b/src/irq.c
new file mode 100644 (file)
index 0000000..1168b97
--- /dev/null
+++ b/src/irq.c
@@ -0,0 +1,192 @@
+/**
+ * collectd - src/irq.c
+ * Copyright (C) 2007  Peter Holik
+ * Copyright (C) 2011  Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Peter Holik <peter at holik.at>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_ignorelist.h"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+/*
+ * (Module-)Global variables
+ */
+static const char *config_keys[] =
+{
+       "Irq",
+       "IgnoreSelected"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+/*
+ * Private functions
+ */
+static int irq_config (const char *key, const char *value)
+{
+       if (ignorelist == NULL)
+               ignorelist = ignorelist_create (/* invert = */ 1);
+
+       if (strcasecmp (key, "Irq") == 0)
+       {
+               ignorelist_add (ignorelist, value);
+       }
+       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);
+}
+
+static void irq_submit (const char *irq_name, derive_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       if (ignorelist_match (ignorelist, irq_name) != 0)
+               return;
+
+       values[0].derive = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "irq", sizeof (vl.plugin));
+       sstrncpy (vl.type, "irq", sizeof (vl.type));
+       sstrncpy (vl.type_instance, irq_name, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void irq_submit */
+
+static int irq_read (void)
+{
+       FILE *fh;
+       char buffer[1024];
+       int  cpu_count;
+       char *fields[256];
+
+       /*
+        * Example content:
+        *         CPU0       CPU1       CPU2       CPU3
+        * 0:       2574          1          3          2   IO-APIC-edge      timer
+        * 1:     102553     158669     218062      70587   IO-APIC-edge      i8042
+        * 8:          0          0          0          1   IO-APIC-edge      rtc0
+        */
+       fh = fopen ("/proc/interrupts", "r");
+       if (fh == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("irq plugin: fopen (/proc/interrupts): %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       /* Get CPU count from the first line */
+       if(fgets (buffer, sizeof (buffer), fh) != NULL) {
+               cpu_count = strsplit (buffer, fields,
+                               STATIC_ARRAY_SIZE (fields));
+       } else {
+               ERROR ("irq plugin: unable to get CPU count from first line "
+                               "of /proc/interrupts");
+               return (-1);
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               char *irq_name;
+               size_t irq_name_len;
+               derive_t irq_value;
+               int i;
+               int fields_num;
+               int irq_values_to_parse;
+
+               fields_num = strsplit (buffer, fields,
+                               STATIC_ARRAY_SIZE (fields));
+               if (fields_num < 2)
+                       continue;
+
+               /* Parse this many numeric fields, skip the rest
+                * (+1 because first there is a name of irq in each line) */
+               if (fields_num >= cpu_count + 1)
+                       irq_values_to_parse = cpu_count;
+               else
+                       irq_values_to_parse = fields_num - 1;
+
+               /* First field is irq name and colon */
+               irq_name = fields[0];
+               irq_name_len = strlen (irq_name);
+               if (irq_name_len < 2)
+                       continue;
+
+               /* Check if irq name ends with colon.
+                * Otherwise it's a header. */
+               if (irq_name[irq_name_len - 1] != ':')
+                       continue;
+
+               irq_name[irq_name_len - 1] = 0;
+               irq_name_len--;
+
+               irq_value = 0;
+               for (i = 1; i <= irq_values_to_parse; i++)
+               {
+                       /* Per-CPU value */
+                       value_t v;
+                       int status;
+
+                       status = parse_value (fields[i], &v, DS_TYPE_DERIVE);
+                       if (status != 0)
+                               break;
+
+                       irq_value += v.derive;
+               } /* for (i) */
+
+               /* No valid fields -> do not submit anything. */
+               if (i <= 1)
+                       continue;
+
+               irq_submit (irq_name, irq_value);
+       }
+
+       fclose (fh);
+
+       return (0);
+} /* int irq_read */
+
+void module_register (void)
+{
+       plugin_register_config ("irq", irq_config,
+                       config_keys, config_keys_num);
+       plugin_register_read ("irq", irq_read);
+} /* void module_register */
diff --git a/src/java.c b/src/java.c
new file mode 100644 (file)
index 0000000..2f1efbf
--- /dev/null
@@ -0,0 +1,3108 @@
+/**
+ * collectd - src/java.c
+ * Copyright (C) 2009  Florian octo Forster
+ * Copyright (C) 2008  Justo Alonso Achaques
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Justo Alonso Achaques <justo.alonso at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "filter_chain.h"
+
+#include <pthread.h>
+#include <jni.h>
+
+#if !defined(JNI_VERSION_1_2)
+# error "Need JNI 1.2 compatible interface!"
+#endif
+
+/*
+ * Types
+ */
+struct cjni_jvm_env_s /* {{{ */
+{
+  JNIEnv *jvm_env;
+  int reference_counter;
+};
+typedef struct cjni_jvm_env_s cjni_jvm_env_t;
+/* }}} */
+
+struct java_plugin_class_s /* {{{ */
+{
+  char     *name;
+  jclass    class;
+  jobject   object;
+};
+typedef struct java_plugin_class_s java_plugin_class_t;
+/* }}} */
+
+#define CB_TYPE_CONFIG       1
+#define CB_TYPE_INIT         2
+#define CB_TYPE_READ         3
+#define CB_TYPE_WRITE        4
+#define CB_TYPE_FLUSH        5
+#define CB_TYPE_SHUTDOWN     6
+#define CB_TYPE_LOG          7
+#define CB_TYPE_NOTIFICATION 8
+#define CB_TYPE_MATCH        9
+#define CB_TYPE_TARGET      10
+struct cjni_callback_info_s /* {{{ */
+{
+  char     *name;
+  int       type;
+  jclass    class;
+  jobject   object;
+  jmethodID method;
+};
+typedef struct cjni_callback_info_s cjni_callback_info_t;
+/* }}} */
+
+/*
+ * Global variables
+ */
+static JavaVM *jvm = NULL;
+static pthread_key_t jvm_env_key;
+
+/* Configuration options for the JVM. */
+static char **jvm_argv = NULL;
+static size_t jvm_argc = 0;
+
+/* List of class names to load */
+static java_plugin_class_t  *java_classes_list = NULL;
+static size_t                java_classes_list_len;
+
+/* List of config, init, and shutdown callbacks. */
+static cjni_callback_info_t *java_callbacks      = NULL;
+static size_t                java_callbacks_num  = 0;
+static pthread_mutex_t       java_callbacks_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static oconfig_item_t       *config_block = NULL;
+
+/*
+ * Prototypes
+ *
+ * Mostly functions that are needed by the Java interface (``native'')
+ * functions.
+ */
+static void cjni_callback_info_destroy (void *arg);
+static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env,
+    jobject o_name, jobject o_callback, int type);
+static int cjni_callback_register (JNIEnv *jvm_env, jobject o_name,
+    jobject o_callback, int type);
+static int cjni_read (user_data_t *user_data);
+static int cjni_write (const data_set_t *ds, const value_list_t *vl,
+    user_data_t *ud);
+static int cjni_flush (cdtime_t timeout, const char *identifier, user_data_t *ud);
+static void cjni_log (int severity, const char *message, user_data_t *ud);
+static int cjni_notification (const notification_t *n, user_data_t *ud);
+
+/* Create, destroy, and match/invoke functions, used by both, matches AND
+ * targets. */
+static int cjni_match_target_create (const oconfig_item_t *ci, void **user_data);
+static int cjni_match_target_destroy (void **user_data);
+static int cjni_match_target_invoke (const data_set_t *ds, value_list_t *vl,
+    notification_meta_t **meta, void **user_data);
+
+/*
+ * C to Java conversion functions
+ */
+static int ctoj_string (JNIEnv *jvm_env, /* {{{ */
+    const char *string,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID m_set;
+  jstring o_string;
+
+  /* Create a java.lang.String */
+  o_string = (*jvm_env)->NewStringUTF (jvm_env,
+      (string != NULL) ? string : "");
+  if (o_string == NULL)
+  {
+    ERROR ("java plugin: ctoj_string: NewStringUTF failed.");
+    return (-1);
+  }
+
+  /* Search for the `void setFoo (String s)' method. */
+  m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "(Ljava/lang/String;)V");
+  if (m_set == NULL)
+  {
+    ERROR ("java plugin: ctoj_string: Cannot find method `void %s (String)'.",
+        method_name);
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_string);
+    return (-1);
+  }
+
+  /* Call the method. */
+  (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, o_string);
+
+  /* Decrease reference counter on the java.lang.String object. */
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_string);
+
+  return (0);
+} /* }}} int ctoj_string */
+
+static jstring ctoj_output_string (JNIEnv *jvm_env, /* {{{ */
+    const char *string)
+{
+  jstring o_string;
+
+  /* Create a java.lang.String */
+  o_string = (*jvm_env)->NewStringUTF (jvm_env,
+      (string != NULL) ? string : "");
+  if (o_string == NULL)
+  {
+    ERROR ("java plugin: ctoj_output_string: NewStringUTF failed.");
+    return NULL;
+  }
+
+  return (o_string);
+} /* }}} int ctoj_output_string */
+
+static int ctoj_int (JNIEnv *jvm_env, /* {{{ */
+    jint value,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID m_set;
+
+  /* Search for the `void setFoo (int i)' method. */
+  m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "(I)V");
+  if (m_set == NULL)
+  {
+    ERROR ("java plugin: ctoj_int: Cannot find method `void %s (int)'.",
+        method_name);
+    return (-1);
+  }
+
+  (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
+
+  return (0);
+} /* }}} int ctoj_int */
+
+static int ctoj_long (JNIEnv *jvm_env, /* {{{ */
+    jlong value,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID m_set;
+
+  /* Search for the `void setFoo (long l)' method. */
+  m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "(J)V");
+  if (m_set == NULL)
+  {
+    ERROR ("java plugin: ctoj_long: Cannot find method `void %s (long)'.",
+        method_name);
+    return (-1);
+  }
+
+  (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
+
+  return (0);
+} /* }}} int ctoj_long */
+
+static int ctoj_double (JNIEnv *jvm_env, /* {{{ */
+    jdouble value,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID m_set;
+
+  /* Search for the `void setFoo (double d)' method. */
+  m_set = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "(D)V");
+  if (m_set == NULL)
+  {
+    ERROR ("java plugin: ctoj_double: Cannot find method `void %s (double)'.",
+        method_name);
+    return (-1);
+  }
+
+  (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_set, value);
+
+  return (0);
+} /* }}} int ctoj_double */
+
+/* Convert a jlong to a java.lang.Number */
+static jobject ctoj_jlong_to_number (JNIEnv *jvm_env, jlong value) /* {{{ */
+{
+  jclass c_long;
+  jmethodID m_long_constructor;
+
+  /* Look up the java.lang.Long class */
+  c_long = (*jvm_env)->FindClass (jvm_env, "java/lang/Long");
+  if (c_long == NULL)
+  {
+    ERROR ("java plugin: ctoj_jlong_to_number: Looking up the "
+        "java.lang.Long class failed.");
+    return (NULL);
+  }
+
+  m_long_constructor = (*jvm_env)->GetMethodID (jvm_env,
+      c_long, "<init>", "(J)V");
+  if (m_long_constructor == NULL)
+  {
+    ERROR ("java plugin: ctoj_jlong_to_number: Looking up the "
+        "`Long (long)' constructor failed.");
+    return (NULL);
+  }
+
+  return ((*jvm_env)->NewObject (jvm_env,
+        c_long, m_long_constructor, value));
+} /* }}} jobject ctoj_jlong_to_number */
+
+/* Convert a jdouble to a java.lang.Number */
+static jobject ctoj_jdouble_to_number (JNIEnv *jvm_env, jdouble value) /* {{{ */
+{
+  jclass c_double;
+  jmethodID m_double_constructor;
+
+  /* Look up the java.lang.Long class */
+  c_double = (*jvm_env)->FindClass (jvm_env, "java/lang/Double");
+  if (c_double == NULL)
+  {
+    ERROR ("java plugin: ctoj_jdouble_to_number: Looking up the "
+        "java.lang.Double class failed.");
+    return (NULL);
+  }
+
+  m_double_constructor = (*jvm_env)->GetMethodID (jvm_env,
+      c_double, "<init>", "(D)V");
+  if (m_double_constructor == NULL)
+  {
+    ERROR ("java plugin: ctoj_jdouble_to_number: Looking up the "
+        "`Double (double)' constructor failed.");
+    return (NULL);
+  }
+
+  return ((*jvm_env)->NewObject (jvm_env,
+        c_double, m_double_constructor, value));
+} /* }}} jobject ctoj_jdouble_to_number */
+
+/* Convert a value_t to a java.lang.Number */
+static jobject ctoj_value_to_number (JNIEnv *jvm_env, /* {{{ */
+    value_t value, int ds_type)
+{
+  if (ds_type == DS_TYPE_COUNTER)
+    return (ctoj_jlong_to_number (jvm_env, (jlong) value.counter));
+  else if (ds_type == DS_TYPE_GAUGE)
+    return (ctoj_jdouble_to_number (jvm_env, (jdouble) value.gauge));
+  if (ds_type == DS_TYPE_DERIVE)
+    return (ctoj_jlong_to_number (jvm_env, (jlong) value.derive));
+  if (ds_type == DS_TYPE_ABSOLUTE)
+    return (ctoj_jlong_to_number (jvm_env, (jlong) value.absolute));
+  else
+    return (NULL);
+} /* }}} jobject ctoj_value_to_number */
+
+/* Convert a data_source_t to a org/collectd/api/DataSource */
+static jobject ctoj_data_source (JNIEnv *jvm_env, /* {{{ */
+    const data_source_t *dsrc)
+{
+  jclass c_datasource;
+  jmethodID m_datasource_constructor;
+  jobject o_datasource;
+  int status;
+
+  /* Look up the DataSource class */
+  c_datasource = (*jvm_env)->FindClass (jvm_env,
+      "org/collectd/api/DataSource");
+  if (c_datasource == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_source: "
+        "FindClass (org/collectd/api/DataSource) failed.");
+    return (NULL);
+  }
+
+  /* Lookup the `ValueList ()' constructor. */
+  m_datasource_constructor = (*jvm_env)->GetMethodID (jvm_env, c_datasource,
+      "<init>", "()V");
+  if (m_datasource_constructor == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_source: Cannot find the "
+        "`DataSource ()' constructor.");
+    return (NULL);
+  }
+
+  /* Create a new instance. */
+  o_datasource = (*jvm_env)->NewObject (jvm_env, c_datasource,
+      m_datasource_constructor);
+  if (o_datasource == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_source: "
+        "Creating a new DataSource instance failed.");
+    return (NULL);
+  }
+
+  /* Set name via `void setName (String name)' */
+  status = ctoj_string (jvm_env, dsrc->name,
+      c_datasource, o_datasource, "setName");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_data_source: "
+        "ctoj_string (setName) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
+    return (NULL);
+  }
+
+  /* Set type via `void setType (int type)' */
+  status = ctoj_int (jvm_env, dsrc->type,
+      c_datasource, o_datasource, "setType");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_data_source: "
+        "ctoj_int (setType) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
+    return (NULL);
+  }
+
+  /* Set min via `void setMin (double min)' */
+  status = ctoj_double (jvm_env, dsrc->min,
+      c_datasource, o_datasource, "setMin");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_data_source: "
+        "ctoj_double (setMin) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
+    return (NULL);
+  }
+
+  /* Set max via `void setMax (double max)' */
+  status = ctoj_double (jvm_env, dsrc->max,
+      c_datasource, o_datasource, "setMax");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_data_source: "
+        "ctoj_double (setMax) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
+    return (NULL);
+  }
+
+  return (o_datasource);
+} /* }}} jobject ctoj_data_source */
+
+/* Convert a oconfig_value_t to a org/collectd/api/OConfigValue */
+static jobject ctoj_oconfig_value (JNIEnv *jvm_env, /* {{{ */
+    oconfig_value_t ocvalue)
+{
+  jclass c_ocvalue;
+  jmethodID m_ocvalue_constructor;
+  jobject o_argument;
+  jobject o_ocvalue;
+
+  m_ocvalue_constructor = NULL;
+  o_argument = NULL;
+
+  c_ocvalue = (*jvm_env)->FindClass (jvm_env,
+      "org/collectd/api/OConfigValue");
+  if (c_ocvalue == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_value: "
+        "FindClass (org/collectd/api/OConfigValue) failed.");
+    return (NULL);
+  }
+
+  if (ocvalue.type == OCONFIG_TYPE_BOOLEAN)
+  {
+    jboolean tmp_boolean;
+
+    tmp_boolean = (ocvalue.value.boolean == 0) ? JNI_FALSE : JNI_TRUE;
+
+    m_ocvalue_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocvalue,
+        "<init>", "(Z)V");
+    if (m_ocvalue_constructor == NULL)
+    {
+      ERROR ("java plugin: ctoj_oconfig_value: Cannot find the "
+          "`OConfigValue (boolean)' constructor.");
+      return (NULL);
+    }
+
+    return ((*jvm_env)->NewObject (jvm_env,
+          c_ocvalue, m_ocvalue_constructor, tmp_boolean));
+  } /* if (ocvalue.type == OCONFIG_TYPE_BOOLEAN) */
+  else if (ocvalue.type == OCONFIG_TYPE_STRING)
+  {
+    m_ocvalue_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocvalue,
+        "<init>", "(Ljava/lang/String;)V");
+    if (m_ocvalue_constructor == NULL)
+    {
+      ERROR ("java plugin: ctoj_oconfig_value: Cannot find the "
+          "`OConfigValue (String)' constructor.");
+      return (NULL);
+    }
+
+    o_argument = (*jvm_env)->NewStringUTF (jvm_env, ocvalue.value.string);
+    if (o_argument == NULL)
+    {
+      ERROR ("java plugin: ctoj_oconfig_value: "
+          "Creating a String object failed.");
+      return (NULL);
+    }
+  }
+  else if (ocvalue.type == OCONFIG_TYPE_NUMBER)
+  {
+    m_ocvalue_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocvalue,
+        "<init>", "(Ljava/lang/Number;)V");
+    if (m_ocvalue_constructor == NULL)
+    {
+      ERROR ("java plugin: ctoj_oconfig_value: Cannot find the "
+          "`OConfigValue (Number)' constructor.");
+      return (NULL);
+    }
+
+    o_argument = ctoj_jdouble_to_number (jvm_env,
+        (jdouble) ocvalue.value.number);
+    if (o_argument == NULL)
+    {
+      ERROR ("java plugin: ctoj_oconfig_value: "
+          "Creating a Number object failed.");
+      return (NULL);
+    }
+  }
+  else
+  {
+    return (NULL);
+  }
+
+  assert (m_ocvalue_constructor != NULL);
+  assert (o_argument != NULL);
+
+  o_ocvalue = (*jvm_env)->NewObject (jvm_env,
+      c_ocvalue, m_ocvalue_constructor, o_argument);
+  if (o_ocvalue == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_value: "
+        "Creating an OConfigValue object failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_argument);
+    return (NULL);
+  }
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_argument);
+  return (o_ocvalue);
+} /* }}} jobject ctoj_oconfig_value */
+
+/* Convert a oconfig_item_t to a org/collectd/api/OConfigItem */
+static jobject ctoj_oconfig_item (JNIEnv *jvm_env, /* {{{ */
+    const oconfig_item_t *ci)
+{
+  jclass c_ocitem;
+  jmethodID m_ocitem_constructor;
+  jmethodID m_addvalue;
+  jmethodID m_addchild;
+  jobject o_key;
+  jobject o_ocitem;
+  int i;
+
+  c_ocitem = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/OConfigItem");
+  if (c_ocitem == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_item: "
+        "FindClass (org/collectd/api/OConfigItem) failed.");
+    return (NULL);
+  }
+
+  /* Get the required methods: m_ocitem_constructor, m_addvalue, and m_addchild
+   * {{{ */
+  m_ocitem_constructor = (*jvm_env)->GetMethodID (jvm_env, c_ocitem,
+      "<init>", "(Ljava/lang/String;)V");
+  if (m_ocitem_constructor == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_item: Cannot find the "
+        "`OConfigItem (String)' constructor.");
+    return (NULL);
+  }
+
+  m_addvalue = (*jvm_env)->GetMethodID (jvm_env, c_ocitem,
+      "addValue", "(Lorg/collectd/api/OConfigValue;)V");
+  if (m_addvalue == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_item: Cannot find the "
+        "`addValue (OConfigValue)' method.");
+    return (NULL);
+  }
+
+  m_addchild = (*jvm_env)->GetMethodID (jvm_env, c_ocitem,
+      "addChild", "(Lorg/collectd/api/OConfigItem;)V");
+  if (m_addchild == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_item: Cannot find the "
+        "`addChild (OConfigItem)' method.");
+    return (NULL);
+  }
+  /* }}} */
+
+  /* Create a String object with the key.
+   * Needed for calling the constructor. */
+  o_key = (*jvm_env)->NewStringUTF (jvm_env, ci->key);
+  if (o_key == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_item: "
+        "Creating String object failed.");
+    return (NULL);
+  }
+
+  /* Create an OConfigItem object */
+  o_ocitem = (*jvm_env)->NewObject (jvm_env,
+      c_ocitem, m_ocitem_constructor, o_key);
+  if (o_ocitem == NULL)
+  {
+    ERROR ("java plugin: ctoj_oconfig_item: "
+        "Creating an OConfigItem object failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_key);
+    return (NULL);
+  }
+
+  /* We don't need the String object any longer.. */
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_key);
+
+  /* Call OConfigItem.addValue for each value */
+  for (i = 0; i < ci->values_num; i++) /* {{{ */
+  {
+    jobject o_value;
+
+    o_value = ctoj_oconfig_value (jvm_env, ci->values[i]);
+    if (o_value == NULL)
+    {
+      ERROR ("java plugin: ctoj_oconfig_item: "
+          "Creating an OConfigValue object failed.");
+      (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
+      return (NULL);
+    }
+
+    (*jvm_env)->CallVoidMethod (jvm_env, o_ocitem, m_addvalue, o_value);
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_value);
+  } /* }}} for (i = 0; i < ci->values_num; i++) */
+
+  /* Call OConfigItem.addChild for each child */
+  for (i = 0; i < ci->children_num; i++) /* {{{ */
+  {
+    jobject o_child;
+
+    o_child = ctoj_oconfig_item (jvm_env, ci->children + i);
+    if (o_child == NULL)
+    {
+      ERROR ("java plugin: ctoj_oconfig_item: "
+          "Creating an OConfigItem object failed.");
+      (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
+      return (NULL);
+    }
+
+    (*jvm_env)->CallVoidMethod (jvm_env, o_ocitem, m_addchild, o_child);
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_child);
+  } /* }}} for (i = 0; i < ci->children_num; i++) */
+
+  return (o_ocitem);
+} /* }}} jobject ctoj_oconfig_item */
+
+/* Convert a data_set_t to a org/collectd/api/DataSet */
+static jobject ctoj_data_set (JNIEnv *jvm_env, const data_set_t *ds) /* {{{ */
+{
+  jclass c_dataset;
+  jmethodID m_constructor;
+  jmethodID m_add;
+  jobject o_type;
+  jobject o_dataset;
+  int i;
+
+  /* Look up the org/collectd/api/DataSet class */
+  c_dataset = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/DataSet");
+  if (c_dataset == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_set: Looking up the "
+        "org/collectd/api/DataSet class failed.");
+    return (NULL);
+  }
+
+  /* Search for the `DataSet (String type)' constructor. */
+  m_constructor = (*jvm_env)->GetMethodID (jvm_env,
+      c_dataset, "<init>", "(Ljava/lang/String;)V");
+  if (m_constructor == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_set: Looking up the "
+        "`DataSet (String)' constructor failed.");
+    return (NULL);
+  }
+
+  /* Search for the `void addDataSource (DataSource)' method. */
+  m_add = (*jvm_env)->GetMethodID (jvm_env,
+      c_dataset, "addDataSource", "(Lorg/collectd/api/DataSource;)V");
+  if (m_add == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_set: Looking up the "
+        "`addDataSource (DataSource)' method failed.");
+    return (NULL);
+  }
+
+  o_type = (*jvm_env)->NewStringUTF (jvm_env, ds->type);
+  if (o_type == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_set: Creating a String object failed.");
+    return (NULL);
+  }
+
+  o_dataset = (*jvm_env)->NewObject (jvm_env,
+      c_dataset, m_constructor, o_type);
+  if (o_dataset == NULL)
+  {
+    ERROR ("java plugin: ctoj_data_set: Creating a DataSet object failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_type);
+    return (NULL);
+  }
+
+  /* Decrease reference counter on the java.lang.String object. */
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_type);
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    jobject o_datasource;
+
+    o_datasource = ctoj_data_source (jvm_env, ds->ds + i);
+    if (o_datasource == NULL)
+    {
+      ERROR ("java plugin: ctoj_data_set: ctoj_data_source (%s.%s) failed",
+          ds->type, ds->ds[i].name);
+      (*jvm_env)->DeleteLocalRef (jvm_env, o_dataset);
+      return (NULL);
+    }
+
+    (*jvm_env)->CallVoidMethod (jvm_env, o_dataset, m_add, o_datasource);
+
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_datasource);
+  } /* for (i = 0; i < ds->ds_num; i++) */
+
+  return (o_dataset);
+} /* }}} jobject ctoj_data_set */
+
+static int ctoj_value_list_add_value (JNIEnv *jvm_env, /* {{{ */
+    value_t value, int ds_type,
+    jclass class_ptr, jobject object_ptr)
+{
+  jmethodID m_addvalue;
+  jobject o_number;
+
+  m_addvalue = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      "addValue", "(Ljava/lang/Number;)V");
+  if (m_addvalue == NULL)
+  {
+    ERROR ("java plugin: ctoj_value_list_add_value: "
+        "Cannot find method `void addValue (Number)'.");
+    return (-1);
+  }
+
+  o_number = ctoj_value_to_number (jvm_env, value, ds_type);
+  if (o_number == NULL)
+  {
+    ERROR ("java plugin: ctoj_value_list_add_value: "
+        "ctoj_value_to_number failed.");
+    return (-1);
+  }
+
+  (*jvm_env)->CallVoidMethod (jvm_env, object_ptr, m_addvalue, o_number);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_number);
+
+  return (0);
+} /* }}} int ctoj_value_list_add_value */
+
+static int ctoj_value_list_add_data_set (JNIEnv *jvm_env, /* {{{ */
+    jclass c_valuelist, jobject o_valuelist, const data_set_t *ds)
+{
+  jmethodID m_setdataset;
+  jobject o_dataset;
+
+  /* Look for the `void setDataSource (List<DataSource> ds)' method. */
+  m_setdataset = (*jvm_env)->GetMethodID (jvm_env, c_valuelist,
+      "setDataSet", "(Lorg/collectd/api/DataSet;)V");
+  if (m_setdataset == NULL)
+  {
+    ERROR ("java plugin: ctoj_value_list_add_data_set: "
+        "Cannot find the `void setDataSet (DataSet)' method.");
+    return (-1);
+  }
+
+  /* Create a DataSet object. */
+  o_dataset = ctoj_data_set (jvm_env, ds);
+  if (o_dataset == NULL)
+  {
+    ERROR ("java plugin: ctoj_value_list_add_data_set: "
+        "ctoj_data_set (%s) failed.", ds->type);
+    return (-1);
+  }
+
+  /* Actually call the method. */
+  (*jvm_env)->CallVoidMethod (jvm_env,
+      o_valuelist, m_setdataset, o_dataset);
+
+  /* Decrease reference counter on the List<DataSource> object. */
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_dataset);
+
+  return (0);
+} /* }}} int ctoj_value_list_add_data_set */
+
+/* Convert a value_list_t (and data_set_t) to a org/collectd/api/ValueList */
+static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */
+    const data_set_t *ds, const value_list_t *vl)
+{
+  jclass c_valuelist;
+  jmethodID m_valuelist_constructor;
+  jobject o_valuelist;
+  int status;
+  int i;
+
+  /* First, create a new ValueList instance..
+   * Look up the class.. */
+  c_valuelist = (*jvm_env)->FindClass (jvm_env,
+      "org/collectd/api/ValueList");
+  if (c_valuelist == NULL)
+  {
+    ERROR ("java plugin: ctoj_value_list: "
+        "FindClass (org/collectd/api/ValueList) failed.");
+    return (NULL);
+  }
+
+  /* Lookup the `ValueList ()' constructor. */
+  m_valuelist_constructor = (*jvm_env)->GetMethodID (jvm_env, c_valuelist,
+      "<init>", "()V");
+  if (m_valuelist_constructor == NULL)
+  {
+    ERROR ("java plugin: ctoj_value_list: Cannot find the "
+        "`ValueList ()' constructor.");
+    return (NULL);
+  }
+
+  /* Create a new instance. */
+  o_valuelist = (*jvm_env)->NewObject (jvm_env, c_valuelist,
+      m_valuelist_constructor);
+  if (o_valuelist == NULL)
+  {
+    ERROR ("java plugin: ctoj_value_list: Creating a new ValueList instance "
+        "failed.");
+    return (NULL);
+  }
+
+  status = ctoj_value_list_add_data_set (jvm_env,
+      c_valuelist, o_valuelist, ds);
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_value_list: "
+        "ctoj_value_list_add_data_set failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
+    return (NULL);
+  }
+
+  /* Set the strings.. */
+#define SET_STRING(str,method_name) do { \
+  status = ctoj_string (jvm_env, str, \
+      c_valuelist, o_valuelist, method_name); \
+  if (status != 0) { \
+    ERROR ("java plugin: ctoj_value_list: ctoj_string (%s) failed.", \
+        method_name); \
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist); \
+    return (NULL); \
+  } } while (0)
+
+  SET_STRING (vl->host,            "setHost");
+  SET_STRING (vl->plugin,          "setPlugin");
+  SET_STRING (vl->plugin_instance, "setPluginInstance");
+  SET_STRING (vl->type,            "setType");
+  SET_STRING (vl->type_instance,   "setTypeInstance");
+
+#undef SET_STRING
+
+  /* Set the `time' member. Java stores time in milliseconds. */
+  status = ctoj_long (jvm_env, (jlong) CDTIME_T_TO_MS (vl->time),
+      c_valuelist, o_valuelist, "setTime");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_value_list: ctoj_long (setTime) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
+    return (NULL);
+  }
+
+  /* Set the `interval' member.. */
+  status = ctoj_long (jvm_env,
+      (jlong) CDTIME_T_TO_MS (vl->interval),
+      c_valuelist, o_valuelist, "setInterval");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_value_list: ctoj_long (setInterval) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
+    return (NULL);
+  }
+
+  for (i = 0; i < vl->values_len; i++)
+  {
+    status = ctoj_value_list_add_value (jvm_env, vl->values[i], ds->ds[i].type,
+        c_valuelist, o_valuelist);
+    if (status != 0)
+    {
+      ERROR ("java plugin: ctoj_value_list: "
+          "ctoj_value_list_add_value failed.");
+      (*jvm_env)->DeleteLocalRef (jvm_env, o_valuelist);
+      return (NULL);
+    }
+  }
+
+  return (o_valuelist);
+} /* }}} jobject ctoj_value_list */
+
+/* Convert a notification_t to a org/collectd/api/Notification */
+static jobject ctoj_notification (JNIEnv *jvm_env, /* {{{ */
+    const notification_t *n)
+{
+  jclass c_notification;
+  jmethodID m_constructor;
+  jobject o_notification;
+  int status;
+
+  /* First, create a new Notification instance..
+   * Look up the class.. */
+  c_notification = (*jvm_env)->FindClass (jvm_env,
+      "org/collectd/api/Notification");
+  if (c_notification == NULL)
+  {
+    ERROR ("java plugin: ctoj_notification: "
+        "FindClass (org/collectd/api/Notification) failed.");
+    return (NULL);
+  }
+
+  /* Lookup the `Notification ()' constructor. */
+  m_constructor = (*jvm_env)->GetMethodID (jvm_env, c_notification,
+      "<init>", "()V");
+  if (m_constructor == NULL)
+  {
+    ERROR ("java plugin: ctoj_notification: Cannot find the "
+        "`Notification ()' constructor.");
+    return (NULL);
+  }
+
+  /* Create a new instance. */
+  o_notification = (*jvm_env)->NewObject (jvm_env, c_notification,
+      m_constructor);
+  if (o_notification == NULL)
+  {
+    ERROR ("java plugin: ctoj_notification: Creating a new Notification "
+        "instance failed.");
+    return (NULL);
+  }
+
+  /* Set the strings.. */
+#define SET_STRING(str,method_name) do { \
+  status = ctoj_string (jvm_env, str, \
+      c_notification, o_notification, method_name); \
+  if (status != 0) { \
+    ERROR ("java plugin: ctoj_notification: ctoj_string (%s) failed.", \
+        method_name); \
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_notification); \
+    return (NULL); \
+  } } while (0)
+
+  SET_STRING (n->host,            "setHost");
+  SET_STRING (n->plugin,          "setPlugin");
+  SET_STRING (n->plugin_instance, "setPluginInstance");
+  SET_STRING (n->type,            "setType");
+  SET_STRING (n->type_instance,   "setTypeInstance");
+  SET_STRING (n->message,         "setMessage");
+
+#undef SET_STRING
+
+  /* Set the `time' member. Java stores time in milliseconds. */
+  status = ctoj_long (jvm_env, (jlong) CDTIME_T_TO_MS (n->time),
+      c_notification, o_notification, "setTime");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_notification: ctoj_long (setTime) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_notification);
+    return (NULL);
+  }
+
+  /* Set the `severity' member.. */
+  status = ctoj_int (jvm_env, (jint) n->severity,
+      c_notification, o_notification, "setSeverity");
+  if (status != 0)
+  {
+    ERROR ("java plugin: ctoj_notification: ctoj_int (setSeverity) failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_notification);
+    return (NULL);
+  }
+
+  return (o_notification);
+} /* }}} jobject ctoj_notification */
+
+/*
+ * Java to C conversion functions
+ */
+/* Call a `String <method> ()' method. */
+static int jtoc_string (JNIEnv *jvm_env, /* {{{ */
+    char *buffer, size_t buffer_size, int empty_okay,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID method_id;
+  jobject string_obj;
+  const char *c_str;
+
+  method_id = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "()Ljava/lang/String;");
+  if (method_id == NULL)
+  {
+    ERROR ("java plugin: jtoc_string: Cannot find method `String %s ()'.",
+        method_name);
+    return (-1);
+  }
+
+  string_obj = (*jvm_env)->CallObjectMethod (jvm_env, object_ptr, method_id);
+  if ((string_obj == NULL) && (empty_okay == 0))
+  {
+    ERROR ("java plugin: jtoc_string: CallObjectMethod (%s) failed.",
+        method_name);
+    return (-1);
+  }
+  else if ((string_obj == NULL) && (empty_okay != 0))
+  {
+    memset (buffer, 0, buffer_size);
+    return (0);
+  }
+
+  c_str = (*jvm_env)->GetStringUTFChars (jvm_env, string_obj, 0);
+  if (c_str == NULL)
+  {
+    ERROR ("java plugin: jtoc_string: GetStringUTFChars failed.");
+    (*jvm_env)->DeleteLocalRef (jvm_env, string_obj);
+    return (-1);
+  }
+
+  sstrncpy (buffer, c_str, buffer_size);
+
+  (*jvm_env)->ReleaseStringUTFChars (jvm_env, string_obj, c_str);
+  (*jvm_env)->DeleteLocalRef (jvm_env, string_obj);
+
+  return (0);
+} /* }}} int jtoc_string */
+
+/* Call an `int <method> ()' method. */
+static int jtoc_int (JNIEnv *jvm_env, /* {{{ */
+    jint *ret_value,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID method_id;
+
+  method_id = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "()I");
+  if (method_id == NULL)
+  {
+    ERROR ("java plugin: jtoc_int: Cannot find method `int %s ()'.",
+        method_name);
+    return (-1);
+  }
+
+  *ret_value = (*jvm_env)->CallIntMethod (jvm_env, object_ptr, method_id);
+
+  return (0);
+} /* }}} int jtoc_int */
+
+/* Call a `long <method> ()' method. */
+static int jtoc_long (JNIEnv *jvm_env, /* {{{ */
+    jlong *ret_value,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID method_id;
+
+  method_id = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "()J");
+  if (method_id == NULL)
+  {
+    ERROR ("java plugin: jtoc_long: Cannot find method `long %s ()'.",
+        method_name);
+    return (-1);
+  }
+
+  *ret_value = (*jvm_env)->CallLongMethod (jvm_env, object_ptr, method_id);
+
+  return (0);
+} /* }}} int jtoc_long */
+
+/* Call a `double <method> ()' method. */
+static int jtoc_double (JNIEnv *jvm_env, /* {{{ */
+    jdouble *ret_value,
+    jclass class_ptr, jobject object_ptr, const char *method_name)
+{
+  jmethodID method_id;
+
+  method_id = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      method_name, "()D");
+  if (method_id == NULL)
+  {
+    ERROR ("java plugin: jtoc_double: Cannot find method `double %s ()'.",
+        method_name);
+    return (-1);
+  }
+
+  *ret_value = (*jvm_env)->CallDoubleMethod (jvm_env, object_ptr, method_id);
+
+  return (0);
+} /* }}} int jtoc_double */
+
+static int jtoc_value (JNIEnv *jvm_env, /* {{{ */
+    value_t *ret_value, int ds_type, jobject object_ptr)
+{
+  jclass class_ptr;
+  int status;
+
+  class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
+
+  if (ds_type == DS_TYPE_GAUGE)
+  {
+    jdouble tmp_double;
+
+    status = jtoc_double (jvm_env, &tmp_double,
+        class_ptr, object_ptr, "doubleValue");
+    if (status != 0)
+    {
+      ERROR ("java plugin: jtoc_value: "
+          "jtoc_double failed.");
+      return (-1);
+    }
+    (*ret_value).gauge = (gauge_t) tmp_double;
+  }
+  else
+  {
+    jlong tmp_long;
+
+    status = jtoc_long (jvm_env, &tmp_long,
+        class_ptr, object_ptr, "longValue");
+    if (status != 0)
+    {
+      ERROR ("java plugin: jtoc_value: "
+          "jtoc_long failed.");
+      return (-1);
+    }
+
+    if (ds_type == DS_TYPE_DERIVE)
+      (*ret_value).derive = (derive_t) tmp_long;
+    else if (ds_type == DS_TYPE_ABSOLUTE)
+      (*ret_value).absolute = (absolute_t) tmp_long;
+    else
+      (*ret_value).counter = (counter_t) tmp_long;
+  }
+
+  return (0);
+} /* }}} int jtoc_value */
+
+/* Read a List<Number>, convert it to `value_t' and add it to the given
+ * `value_list_t'. */
+static int jtoc_values_array (JNIEnv *jvm_env, /* {{{ */
+    const data_set_t *ds, value_list_t *vl,
+    jclass class_ptr, jobject object_ptr)
+{
+  jmethodID m_getvalues;
+  jmethodID m_toarray;
+  jobject o_list;
+  jobjectArray o_number_array;
+
+  value_t *values;
+  int values_num;
+  int i;
+
+  values_num = ds->ds_num;
+
+  values = NULL;
+  o_number_array = NULL;
+  o_list = NULL;
+
+#define BAIL_OUT(status) \
+  free (values); \
+  if (o_number_array != NULL) \
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_number_array); \
+  if (o_list != NULL) \
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_list); \
+  return (status);
+
+  /* Call: List<Number> ValueList.getValues () */
+  m_getvalues = (*jvm_env)->GetMethodID (jvm_env, class_ptr,
+      "getValues", "()Ljava/util/List;");
+  if (m_getvalues == NULL)
+  {
+    ERROR ("java plugin: jtoc_values_array: "
+        "Cannot find method `List getValues ()'.");
+    BAIL_OUT (-1);
+  }
+
+  o_list = (*jvm_env)->CallObjectMethod (jvm_env, object_ptr, m_getvalues);
+  if (o_list == NULL)
+  {
+    ERROR ("java plugin: jtoc_values_array: "
+        "CallObjectMethod (getValues) failed.");
+    BAIL_OUT (-1);
+  }
+
+  /* Call: Number[] List.toArray () */
+  m_toarray = (*jvm_env)->GetMethodID (jvm_env,
+      (*jvm_env)->GetObjectClass (jvm_env, o_list),
+      "toArray", "()[Ljava/lang/Object;");
+  if (m_toarray == NULL)
+  {
+    ERROR ("java plugin: jtoc_values_array: "
+        "Cannot find method `Object[] toArray ()'.");
+    BAIL_OUT (-1);
+  }
+
+  o_number_array = (*jvm_env)->CallObjectMethod (jvm_env, o_list, m_toarray);
+  if (o_number_array == NULL)
+  {
+    ERROR ("java plugin: jtoc_values_array: "
+        "CallObjectMethod (toArray) failed.");
+    BAIL_OUT (-1);
+  }
+
+  values = (value_t *) calloc (values_num, sizeof (value_t));
+  if (values == NULL)
+  {
+    ERROR ("java plugin: jtoc_values_array: calloc failed.");
+    BAIL_OUT (-1);
+  }
+
+  for (i = 0; i < values_num; i++)
+  {
+    jobject o_number;
+    int status;
+
+    o_number = (*jvm_env)->GetObjectArrayElement (jvm_env,
+        o_number_array, (jsize) i);
+    if (o_number == NULL)
+    {
+      ERROR ("java plugin: jtoc_values_array: "
+          "GetObjectArrayElement (%i) failed.", i);
+      BAIL_OUT (-1);
+    }
+
+    status = jtoc_value (jvm_env, values + i, ds->ds[i].type, o_number);
+    if (status != 0)
+    {
+      ERROR ("java plugin: jtoc_values_array: "
+          "jtoc_value (%i) failed.", i);
+      BAIL_OUT (-1);
+    }
+  } /* for (i = 0; i < values_num; i++) */
+
+  vl->values = values;
+  vl->values_len = values_num;
+
+#undef BAIL_OUT
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_number_array);
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_list);
+  return (0);
+} /* }}} int jtoc_values_array */
+
+/* Convert a org/collectd/api/ValueList to a value_list_t. */
+static int jtoc_value_list (JNIEnv *jvm_env, value_list_t *vl, /* {{{ */
+    jobject object_ptr)
+{
+  jclass class_ptr;
+  int status;
+  jlong tmp_long;
+  const data_set_t *ds;
+
+  class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
+  if (class_ptr == NULL)
+  {
+    ERROR ("java plugin: jtoc_value_list: GetObjectClass failed.");
+    return (-1);
+  }
+
+  /* eo == empty okay */
+#define SET_STRING(buffer,method, eo) do { \
+  status = jtoc_string (jvm_env, buffer, sizeof (buffer), eo, \
+      class_ptr, object_ptr, method); \
+  if (status != 0) { \
+    ERROR ("java plugin: jtoc_value_list: jtoc_string (%s) failed.", \
+        method); \
+    return (-1); \
+  } } while (0)
+
+  SET_STRING(vl->type, "getType", /* empty = */ 0);
+
+  ds = plugin_get_ds (vl->type);
+  if (ds == NULL)
+  {
+    ERROR ("java plugin: jtoc_value_list: Data-set `%s' is not defined. "
+        "Please consult the types.db(5) manpage for mor information.",
+        vl->type);
+    return (-1);
+  }
+
+  SET_STRING(vl->host,            "getHost",           /* empty = */ 0);
+  SET_STRING(vl->plugin,          "getPlugin",         /* empty = */ 0);
+  SET_STRING(vl->plugin_instance, "getPluginInstance", /* empty = */ 1);
+  SET_STRING(vl->type_instance,   "getTypeInstance",   /* empty = */ 1);
+
+#undef SET_STRING
+
+  status = jtoc_long (jvm_env, &tmp_long, class_ptr, object_ptr, "getTime");
+  if (status != 0)
+  {
+    ERROR ("java plugin: jtoc_value_list: jtoc_long (getTime) failed.");
+    return (-1);
+  }
+  /* Java measures time in milliseconds. */
+  vl->time = MS_TO_CDTIME_T (tmp_long);
+
+  status = jtoc_long (jvm_env, &tmp_long,
+      class_ptr, object_ptr, "getInterval");
+  if (status != 0)
+  {
+    ERROR ("java plugin: jtoc_value_list: jtoc_long (getInterval) failed.");
+    return (-1);
+  }
+  vl->interval = MS_TO_CDTIME_T (tmp_long);
+
+  status = jtoc_values_array (jvm_env, ds, vl, class_ptr, object_ptr);
+  if (status != 0)
+  {
+    ERROR ("java plugin: jtoc_value_list: jtoc_values_array failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int jtoc_value_list */
+
+/* Convert a org/collectd/api/Notification to a notification_t. */
+static int jtoc_notification (JNIEnv *jvm_env, notification_t *n, /* {{{ */
+    jobject object_ptr)
+{
+  jclass class_ptr;
+  int status;
+  jlong tmp_long;
+  jint tmp_int;
+
+  class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
+  if (class_ptr == NULL)
+  {
+    ERROR ("java plugin: jtoc_notification: GetObjectClass failed.");
+    return (-1);
+  }
+
+  /* eo == empty okay */
+#define SET_STRING(buffer,method, eo) do { \
+  status = jtoc_string (jvm_env, buffer, sizeof (buffer), eo, \
+      class_ptr, object_ptr, method); \
+  if (status != 0) { \
+    ERROR ("java plugin: jtoc_notification: jtoc_string (%s) failed.", \
+        method); \
+    return (-1); \
+  } } while (0)
+
+  SET_STRING (n->host,            "getHost",           /* empty = */ 1);
+  SET_STRING (n->plugin,          "getPlugin",         /* empty = */ 1);
+  SET_STRING (n->plugin_instance, "getPluginInstance", /* empty = */ 1);
+  SET_STRING (n->type,            "getType",           /* empty = */ 1);
+  SET_STRING (n->type_instance,   "getTypeInstance",   /* empty = */ 1);
+  SET_STRING (n->message,         "getMessage",        /* empty = */ 0);
+
+#undef SET_STRING
+
+  status = jtoc_long (jvm_env, &tmp_long, class_ptr, object_ptr, "getTime");
+  if (status != 0)
+  {
+    ERROR ("java plugin: jtoc_notification: jtoc_long (getTime) failed.");
+    return (-1);
+  }
+  /* Java measures time in milliseconds. */
+  n->time = MS_TO_CDTIME_T(tmp_long);
+
+  status = jtoc_int (jvm_env, &tmp_int,
+      class_ptr, object_ptr, "getSeverity");
+  if (status != 0)
+  {
+    ERROR ("java plugin: jtoc_notification: jtoc_int (getSeverity) failed.");
+    return (-1);
+  }
+  n->severity = (int) tmp_int;
+
+  return (0);
+} /* }}} int jtoc_notification */
+/*
+ * Functions accessible from Java
+ */
+static jint JNICALL cjni_api_dispatch_values (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject java_vl)
+{
+  value_list_t vl = VALUE_LIST_INIT;
+  int status;
+
+  DEBUG ("cjni_api_dispatch_values: java_vl = %p;", (void *) java_vl);
+
+  status = jtoc_value_list (jvm_env, &vl, java_vl);
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_api_dispatch_values: jtoc_value_list failed.");
+    return (-1);
+  }
+
+  status = plugin_dispatch_values (&vl);
+
+  sfree (vl.values);
+
+  return (status);
+} /* }}} jint cjni_api_dispatch_values */
+
+static jint JNICALL cjni_api_dispatch_notification (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_notification)
+{
+  notification_t n;
+  int status;
+
+  memset (&n, 0, sizeof (n));
+  n.meta = NULL;
+
+  status = jtoc_notification (jvm_env, &n, o_notification);
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_api_dispatch_notification: jtoc_notification failed.");
+    return (-1);
+  }
+
+  status = plugin_dispatch_notification (&n);
+
+  return (status);
+} /* }}} jint cjni_api_dispatch_notification */
+
+static jobject JNICALL cjni_api_get_ds (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_string_type)
+{
+  const char *ds_name;
+  const data_set_t *ds;
+  jobject o_dataset;
+
+  ds_name = (*jvm_env)->GetStringUTFChars (jvm_env, o_string_type, 0);
+  if (ds_name == NULL)
+  {
+    ERROR ("java plugin: cjni_api_get_ds: GetStringUTFChars failed.");
+    return (NULL);
+  }
+
+  ds = plugin_get_ds (ds_name);
+  DEBUG ("java plugin: cjni_api_get_ds: "
+      "plugin_get_ds (%s) = %p;", ds_name, (void *) ds);
+
+  (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_string_type, ds_name);
+
+  if (ds == NULL)
+    return (NULL);
+
+  o_dataset = ctoj_data_set (jvm_env, ds);
+  return (o_dataset);
+} /* }}} jint cjni_api_get_ds */
+
+static jint JNICALL cjni_api_register_config (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_config)
+{
+  return (cjni_callback_register (jvm_env, o_name, o_config, CB_TYPE_CONFIG));
+} /* }}} jint cjni_api_register_config */
+
+static jint JNICALL cjni_api_register_init (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_config)
+{
+  return (cjni_callback_register (jvm_env, o_name, o_config, CB_TYPE_INIT));
+} /* }}} jint cjni_api_register_init */
+
+static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_read)
+{
+  user_data_t ud;
+  cjni_callback_info_t *cbi;
+
+  cbi = cjni_callback_info_create (jvm_env, o_name, o_read, CB_TYPE_READ);
+  if (cbi == NULL)
+    return (-1);
+
+  DEBUG ("java plugin: Registering new read callback: %s", cbi->name);
+
+  memset (&ud, 0, sizeof (ud));
+  ud.data = (void *) cbi;
+  ud.free_func = cjni_callback_info_destroy;
+
+  plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
+      /* interval = */ NULL, &ud);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_read);
+
+  return (0);
+} /* }}} jint cjni_api_register_read */
+
+static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_write)
+{
+  user_data_t ud;
+  cjni_callback_info_t *cbi;
+
+  cbi = cjni_callback_info_create (jvm_env, o_name, o_write, CB_TYPE_WRITE);
+  if (cbi == NULL)
+    return (-1);
+
+  DEBUG ("java plugin: Registering new write callback: %s", cbi->name);
+
+  memset (&ud, 0, sizeof (ud));
+  ud.data = (void *) cbi;
+  ud.free_func = cjni_callback_info_destroy;
+
+  plugin_register_write (cbi->name, cjni_write, &ud);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_write);
+
+  return (0);
+} /* }}} jint cjni_api_register_write */
+
+static jint JNICALL cjni_api_register_flush (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_flush)
+{
+  user_data_t ud;
+  cjni_callback_info_t *cbi;
+
+  cbi = cjni_callback_info_create (jvm_env, o_name, o_flush, CB_TYPE_FLUSH);
+  if (cbi == NULL)
+    return (-1);
+
+  DEBUG ("java plugin: Registering new flush callback: %s", cbi->name);
+
+  memset (&ud, 0, sizeof (ud));
+  ud.data = (void *) cbi;
+  ud.free_func = cjni_callback_info_destroy;
+
+  plugin_register_flush (cbi->name, cjni_flush, &ud);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_flush);
+
+  return (0);
+} /* }}} jint cjni_api_register_flush */
+
+static jint JNICALL cjni_api_register_shutdown (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_shutdown)
+{
+  return (cjni_callback_register (jvm_env, o_name, o_shutdown,
+        CB_TYPE_SHUTDOWN));
+} /* }}} jint cjni_api_register_shutdown */
+
+static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_log)
+{
+  user_data_t ud;
+  cjni_callback_info_t *cbi;
+
+  cbi = cjni_callback_info_create (jvm_env, o_name, o_log, CB_TYPE_LOG);
+  if (cbi == NULL)
+    return (-1);
+
+  DEBUG ("java plugin: Registering new log callback: %s", cbi->name);
+
+  memset (&ud, 0, sizeof (ud));
+  ud.data = (void *) cbi;
+  ud.free_func = cjni_callback_info_destroy;
+
+  plugin_register_log (cbi->name, cjni_log, &ud);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_log);
+
+  return (0);
+} /* }}} jint cjni_api_register_log */
+
+static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_notification)
+{
+  user_data_t ud;
+  cjni_callback_info_t *cbi;
+
+  cbi = cjni_callback_info_create (jvm_env, o_name, o_notification,
+      CB_TYPE_NOTIFICATION);
+  if (cbi == NULL)
+    return (-1);
+
+  DEBUG ("java plugin: Registering new notification callback: %s", cbi->name);
+
+  memset (&ud, 0, sizeof (ud));
+  ud.data = (void *) cbi;
+  ud.free_func = cjni_callback_info_destroy;
+
+  plugin_register_notification (cbi->name, cjni_notification, &ud);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_notification);
+
+  return (0);
+} /* }}} jint cjni_api_register_notification */
+
+static jint JNICALL cjni_api_register_match_target (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_match, int type)
+{
+  int status;
+  const char *c_name;
+
+  c_name = (*jvm_env)->GetStringUTFChars (jvm_env, o_name, 0);
+  if (c_name == NULL)
+  {
+    ERROR ("java plugin: cjni_api_register_match_target: "
+        "GetStringUTFChars failed.");
+    return (-1);
+  }
+
+  status = cjni_callback_register (jvm_env, o_name, o_match, type);
+  if (status != 0)
+  {
+    (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+    return (-1);
+  }
+
+  if (type == CB_TYPE_MATCH)
+  {
+    match_proc_t m_proc;
+
+    memset (&m_proc, 0, sizeof (m_proc));
+    m_proc.create  = cjni_match_target_create;
+    m_proc.destroy = cjni_match_target_destroy;
+    m_proc.match   = (void *) cjni_match_target_invoke;
+
+    status = fc_register_match (c_name, m_proc);
+  }
+  else if (type == CB_TYPE_TARGET)
+  {
+    target_proc_t t_proc;
+
+    memset (&t_proc, 0, sizeof (t_proc));
+    t_proc.create  = cjni_match_target_create;
+    t_proc.destroy = cjni_match_target_destroy;
+    t_proc.invoke  = cjni_match_target_invoke;
+
+    status = fc_register_target (c_name, t_proc);
+  }
+  else
+  {
+    ERROR ("java plugin: cjni_api_register_match_target: "
+        "Don't know whether to create a match or a target.");
+    (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+    return (-1);
+  }
+
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_api_register_match_target: "
+        "%s failed.",
+        (type == CB_TYPE_MATCH) ? "fc_register_match" : "fc_register_target");
+    (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+    return (-1);
+  }
+
+  (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+
+  return (0);
+} /* }}} jint cjni_api_register_match_target */
+
+static jint JNICALL cjni_api_register_match (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_match)
+{
+  return (cjni_api_register_match_target (jvm_env, this, o_name, o_match,
+        CB_TYPE_MATCH));
+} /* }}} jint cjni_api_register_match */
+
+static jint JNICALL cjni_api_register_target (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jobject o_name, jobject o_target)
+{
+  return (cjni_api_register_match_target (jvm_env, this, o_name, o_target,
+        CB_TYPE_TARGET));
+} /* }}} jint cjni_api_register_target */
+
+static void JNICALL cjni_api_log (JNIEnv *jvm_env, /* {{{ */
+    jobject this, jint severity, jobject o_message)
+{
+  const char *c_str;
+
+  c_str = (*jvm_env)->GetStringUTFChars (jvm_env, o_message, 0);
+  if (c_str == NULL)
+  {
+    ERROR ("java plugin: cjni_api_log: GetStringUTFChars failed.");
+    return;
+  }
+
+  if (severity < LOG_ERR)
+    severity = LOG_ERR;
+  if (severity > LOG_DEBUG)
+    severity = LOG_DEBUG;
+
+  plugin_log (severity, "%s", c_str);
+
+  (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_message, c_str);
+} /* }}} void cjni_api_log */
+
+static jstring JNICALL cjni_api_get_hostname (JNIEnv *jvm_env, jobject this)
+{
+    return ctoj_output_string(jvm_env, hostname_g);
+}
+
+/* List of ``native'' functions, i. e. C-functions that can be called from
+ * Java. */
+static JNINativeMethod jni_api_functions[] = /* {{{ */
+{
+  { "dispatchValues",
+    "(Lorg/collectd/api/ValueList;)I",
+    cjni_api_dispatch_values },
+
+  { "dispatchNotification",
+    "(Lorg/collectd/api/Notification;)I",
+    cjni_api_dispatch_notification },
+
+  { "getDS",
+    "(Ljava/lang/String;)Lorg/collectd/api/DataSet;",
+    cjni_api_get_ds },
+
+  { "registerConfig",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdConfigInterface;)I",
+    cjni_api_register_config },
+
+  { "registerInit",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdInitInterface;)I",
+    cjni_api_register_init },
+
+  { "registerRead",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdReadInterface;)I",
+    cjni_api_register_read },
+
+  { "registerWrite",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdWriteInterface;)I",
+    cjni_api_register_write },
+
+  { "registerFlush",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdFlushInterface;)I",
+    cjni_api_register_flush },
+
+  { "registerShutdown",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdShutdownInterface;)I",
+    cjni_api_register_shutdown },
+
+  { "registerLog",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdLogInterface;)I",
+    cjni_api_register_log },
+
+  { "registerNotification",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdNotificationInterface;)I",
+    cjni_api_register_notification },
+
+  { "registerMatch",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdMatchFactoryInterface;)I",
+    cjni_api_register_match },
+
+  { "registerTarget",
+    "(Ljava/lang/String;Lorg/collectd/api/CollectdTargetFactoryInterface;)I",
+    cjni_api_register_target },
+
+  { "log",
+    "(ILjava/lang/String;)V",
+    cjni_api_log },
+
+  { "getHostname",
+    "()Ljava/lang/String;",
+    cjni_api_get_hostname },
+
+};
+static size_t jni_api_functions_num = sizeof (jni_api_functions)
+  / sizeof (jni_api_functions[0]);
+/* }}} */
+
+/*
+ * Functions
+ */
+/* Allocate a `cjni_callback_info_t' given the type and objects necessary for
+ * all registration functions. */
+static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env, /* {{{ */
+    jobject o_name, jobject o_callback, int type)
+{
+  const char *c_name;
+  cjni_callback_info_t *cbi;
+  const char *method_name;
+  const char *method_signature;
+
+  switch (type)
+  {
+    case CB_TYPE_CONFIG:
+      method_name = "config";
+      method_signature = "(Lorg/collectd/api/OConfigItem;)I";
+      break;
+
+    case CB_TYPE_INIT:
+      method_name = "init";
+      method_signature = "()I";
+      break;
+
+    case CB_TYPE_READ:
+      method_name = "read";
+      method_signature = "()I";
+      break;
+
+    case CB_TYPE_WRITE:
+      method_name = "write";
+      method_signature = "(Lorg/collectd/api/ValueList;)I";
+      break;
+
+    case CB_TYPE_FLUSH:
+      method_name = "flush";
+      method_signature = "(Ljava/lang/Number;Ljava/lang/String;)I";
+      break;
+
+    case CB_TYPE_SHUTDOWN:
+      method_name = "shutdown";
+      method_signature = "()I";
+      break;
+
+    case CB_TYPE_LOG:
+      method_name = "log";
+      method_signature = "(ILjava/lang/String;)V";
+      break;
+
+    case CB_TYPE_NOTIFICATION:
+      method_name = "notification";
+      method_signature = "(Lorg/collectd/api/Notification;)I";
+      break;
+
+    case CB_TYPE_MATCH:
+      method_name = "createMatch";
+      method_signature = "(Lorg/collectd/api/OConfigItem;)"
+        "Lorg/collectd/api/CollectdMatchInterface;";
+      break;
+
+    case CB_TYPE_TARGET:
+      method_name = "createTarget";
+      method_signature = "(Lorg/collectd/api/OConfigItem;)"
+        "Lorg/collectd/api/CollectdTargetInterface;";
+      break;
+
+    default:
+      ERROR ("java plugin: cjni_callback_info_create: Unknown type: %#x",
+          type);
+      return (NULL);
+  }
+
+  c_name = (*jvm_env)->GetStringUTFChars (jvm_env, o_name, 0);
+  if (c_name == NULL)
+  {
+    ERROR ("java plugin: cjni_callback_info_create: "
+        "GetStringUTFChars failed.");
+    return (NULL);
+  }
+
+  cbi = (cjni_callback_info_t *) malloc (sizeof (*cbi));
+  if (cbi == NULL)
+  {
+    ERROR ("java plugin: cjni_callback_info_create: malloc failed.");
+    (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+    return (NULL);
+  }
+  memset (cbi, 0, sizeof (*cbi));
+  cbi->type = type;
+
+  cbi->name = strdup (c_name);
+  if (cbi->name == NULL)
+  {
+    pthread_mutex_unlock (&java_callbacks_lock);
+    ERROR ("java plugin: cjni_callback_info_create: strdup failed.");
+    (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+    return (NULL);
+  }
+
+  (*jvm_env)->ReleaseStringUTFChars (jvm_env, o_name, c_name);
+
+  cbi->object = (*jvm_env)->NewGlobalRef (jvm_env, o_callback);
+  if (cbi->object == NULL)
+  {
+    ERROR ("java plugin: cjni_callback_info_create: NewGlobalRef failed.");
+    free (cbi);
+    return (NULL);
+  }
+
+  cbi->class  = (*jvm_env)->GetObjectClass (jvm_env, cbi->object);
+  if (cbi->class == NULL)
+  {
+    ERROR ("java plugin: cjni_callback_info_create: GetObjectClass failed.");
+    free (cbi);
+    return (NULL);
+  }
+
+  cbi->method = (*jvm_env)->GetMethodID (jvm_env, cbi->class,
+      method_name, method_signature);
+  if (cbi->method == NULL)
+  {
+    ERROR ("java plugin: cjni_callback_info_create: "
+        "Cannot find the `%s' method with signature `%s'.",
+        method_name, method_signature);
+    free (cbi);
+    return (NULL);
+  }
+
+  return (cbi);
+} /* }}} cjni_callback_info_t cjni_callback_info_create */
+
+/* Allocate a `cjni_callback_info_t' via `cjni_callback_info_create' and add it
+ * to the global `java_callbacks' variable. This is used for `config', `init',
+ * and `shutdown' callbacks. */
+static int cjni_callback_register (JNIEnv *jvm_env, /* {{{ */
+    jobject o_name, jobject o_callback, int type)
+{
+  cjni_callback_info_t *cbi;
+  cjni_callback_info_t *tmp;
+#if COLLECT_DEBUG
+  const char *type_str;
+#endif
+
+  cbi = cjni_callback_info_create (jvm_env, o_name, o_callback, type);
+  if (cbi == NULL)
+    return (-1);
+
+#if COLLECT_DEBUG
+  switch (type)
+  {
+    case CB_TYPE_CONFIG:
+      type_str = "config";
+      break;
+
+    case CB_TYPE_INIT:
+      type_str = "init";
+      break;
+
+    case CB_TYPE_SHUTDOWN:
+      type_str = "shutdown";
+      break;
+
+    case CB_TYPE_MATCH:
+      type_str = "match";
+      break;
+
+    case CB_TYPE_TARGET:
+      type_str = "target";
+      break;
+
+    default:
+      type_str = "<unknown>";
+  }
+  DEBUG ("java plugin: Registering new %s callback: %s",
+      type_str, cbi->name);
+#endif
+
+  pthread_mutex_lock (&java_callbacks_lock);
+
+  tmp = (cjni_callback_info_t *) realloc (java_callbacks,
+      (java_callbacks_num + 1) * sizeof (*java_callbacks));
+  if (tmp == NULL)
+  {
+    pthread_mutex_unlock (&java_callbacks_lock);
+    ERROR ("java plugin: cjni_callback_register: realloc failed.");
+
+    (*jvm_env)->DeleteGlobalRef (jvm_env, cbi->object);
+    free (cbi);
+
+    return (-1);
+  }
+  java_callbacks = tmp;
+  java_callbacks[java_callbacks_num] = *cbi;
+  java_callbacks_num++;
+
+  pthread_mutex_unlock (&java_callbacks_lock);
+
+  free (cbi);
+  return (0);
+} /* }}} int cjni_callback_register */
+
+/* Callback for `pthread_key_create'. It frees the data contained in
+ * `jvm_env_key' and prints a warning if the reference counter is not zero. */
+static void cjni_jvm_env_destroy (void *args) /* {{{ */
+{
+  cjni_jvm_env_t *cjni_env;
+
+  if (args == NULL)
+    return;
+
+  cjni_env = (cjni_jvm_env_t *) args;
+
+  if (cjni_env->reference_counter > 0)
+  {
+    ERROR ("java plugin: cjni_jvm_env_destroy: "
+        "cjni_env->reference_counter = %i;", cjni_env->reference_counter);
+  }
+
+  if (cjni_env->jvm_env != NULL)
+  {
+    ERROR ("java plugin: cjni_jvm_env_destroy: cjni_env->jvm_env = %p;",
+        (void *) cjni_env->jvm_env);
+  }
+
+  /* The pointer is allocated in `cjni_thread_attach' */
+  free (cjni_env);
+} /* }}} void cjni_jvm_env_destroy */
+
+/* Register ``native'' functions with the JVM. Native functions are C-functions
+ * that can be called by Java code. */
+static int cjni_init_native (JNIEnv *jvm_env) /* {{{ */
+{
+  jclass api_class_ptr;
+  int status;
+
+  api_class_ptr = (*jvm_env)->FindClass (jvm_env, "org/collectd/api/Collectd");
+  if (api_class_ptr == NULL)
+  {
+    ERROR ("cjni_init_native: Cannot find the API class \"org.collectd.api"
+        ".Collectd\". Please set the correct class path "
+        "using 'JVMArg \"-Djava.class.path=...\"'.");
+    return (-1);
+  }
+
+  status = (*jvm_env)->RegisterNatives (jvm_env, api_class_ptr,
+      jni_api_functions, (jint) jni_api_functions_num);
+  if (status != 0)
+  {
+    ERROR ("cjni_init_native: RegisterNatives failed with status %i.", status);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cjni_init_native */
+
+/* Create the JVM. This is called when the first thread tries to access the JVM
+ * via cjni_thread_attach. */
+static int cjni_create_jvm (void) /* {{{ */
+{
+  JNIEnv *jvm_env;
+  JavaVMInitArgs vm_args;
+  JavaVMOption vm_options[jvm_argc];
+
+  int status;
+  size_t i;
+
+  if (jvm != NULL)
+    return (0);
+
+  status = pthread_key_create (&jvm_env_key, cjni_jvm_env_destroy);
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_create_jvm: pthread_key_create failed "
+        "with status %i.", status);
+    return (-1);
+  }
+
+  jvm_env = NULL;
+
+  memset (&vm_args, 0, sizeof (vm_args));
+  vm_args.version = JNI_VERSION_1_2;
+  vm_args.options = vm_options;
+  vm_args.nOptions = (jint) jvm_argc;
+
+  for (i = 0; i < jvm_argc; i++)
+  {
+    DEBUG ("java plugin: cjni_create_jvm: jvm_argv[%zu] = %s",
+        i, jvm_argv[i]);
+    vm_args.options[i].optionString = jvm_argv[i];
+  }
+
+  status = JNI_CreateJavaVM (&jvm, (void *) &jvm_env, (void *) &vm_args);
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_create_jvm: "
+        "JNI_CreateJavaVM failed with status %i.",
+       status);
+    return (-1);
+  }
+  assert (jvm != NULL);
+  assert (jvm_env != NULL);
+
+  /* Call RegisterNatives */
+  status = cjni_init_native (jvm_env);
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_create_jvm: cjni_init_native failed.");
+    return (-1);
+  }
+
+  DEBUG ("java plugin: The JVM has been created.");
+  return (0);
+} /* }}} int cjni_create_jvm */
+
+/* Increase the reference counter to the JVM for this thread. If it was zero,
+ * attach the JVM first. */
+static JNIEnv *cjni_thread_attach (void) /* {{{ */
+{
+  cjni_jvm_env_t *cjni_env;
+  JNIEnv *jvm_env;
+
+  /* If we're the first thread to access the JVM, we'll have to create it
+   * first.. */
+  if (jvm == NULL)
+  {
+    int status;
+
+    status = cjni_create_jvm ();
+    if (status != 0)
+    {
+      ERROR ("java plugin: cjni_thread_attach: cjni_create_jvm failed.");
+      return (NULL);
+    }
+  }
+  assert (jvm != NULL);
+
+  cjni_env = pthread_getspecific (jvm_env_key);
+  if (cjni_env == NULL)
+  {
+    /* This pointer is free'd in `cjni_jvm_env_destroy'. */
+    cjni_env = (cjni_jvm_env_t *) malloc (sizeof (*cjni_env));
+    if (cjni_env == NULL)
+    {
+      ERROR ("java plugin: cjni_thread_attach: malloc failed.");
+      return (NULL);
+    }
+    memset (cjni_env, 0, sizeof (*cjni_env));
+    cjni_env->reference_counter = 0;
+    cjni_env->jvm_env = NULL;
+
+    pthread_setspecific (jvm_env_key, cjni_env);
+  }
+
+  if (cjni_env->reference_counter > 0)
+  {
+    cjni_env->reference_counter++;
+    jvm_env = cjni_env->jvm_env;
+  }
+  else
+  {
+    int status;
+    JavaVMAttachArgs args;
+
+    assert (cjni_env->jvm_env == NULL);
+
+    memset (&args, 0, sizeof (args));
+    args.version = JNI_VERSION_1_2;
+
+    status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, (void *) &args);
+    if (status != 0)
+    {
+      ERROR ("java plugin: cjni_thread_attach: AttachCurrentThread failed "
+          "with status %i.", status);
+      return (NULL);
+    }
+
+    cjni_env->reference_counter = 1;
+    cjni_env->jvm_env = jvm_env;
+  }
+
+  DEBUG ("java plugin: cjni_thread_attach: cjni_env->reference_counter = %i",
+      cjni_env->reference_counter);
+  assert (jvm_env != NULL);
+  return (jvm_env);
+} /* }}} JNIEnv *cjni_thread_attach */
+
+/* Decrease the reference counter of this thread. If it reaches zero, detach
+ * from the JVM. */
+static int cjni_thread_detach (void) /* {{{ */
+{
+  cjni_jvm_env_t *cjni_env;
+  int status;
+
+  cjni_env = pthread_getspecific (jvm_env_key);
+  if (cjni_env == NULL)
+  {
+    ERROR ("java plugin: cjni_thread_detach: pthread_getspecific failed.");
+    return (-1);
+  }
+
+  assert (cjni_env->reference_counter > 0);
+  assert (cjni_env->jvm_env != NULL);
+
+  cjni_env->reference_counter--;
+  DEBUG ("java plugin: cjni_thread_detach: cjni_env->reference_counter = %i",
+      cjni_env->reference_counter);
+
+  if (cjni_env->reference_counter > 0)
+    return (0);
+
+  status = (*jvm)->DetachCurrentThread (jvm);
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_thread_detach: DetachCurrentThread failed "
+        "with status %i.", status);
+  }
+
+  cjni_env->reference_counter = 0;
+  cjni_env->jvm_env = NULL;
+
+  return (0);
+} /* }}} int cjni_thread_detach */
+
+static int cjni_config_add_jvm_arg (oconfig_item_t *ci) /* {{{ */
+{
+  char **tmp;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("java plugin: `JVMArg' needs exactly one string argument.");
+    return (-1);
+  }
+
+  if (jvm != NULL)
+  {
+    ERROR ("java plugin: All `JVMArg' options MUST appear before all "
+        "`LoadPlugin' options! The JVM is already started and I have to "
+        "ignore this argument: %s",
+        ci->values[0].value.string);
+    return (-1);
+  }
+
+  tmp = (char **) realloc (jvm_argv, sizeof (char *) * (jvm_argc + 1));
+  if (tmp == NULL)
+  {
+    ERROR ("java plugin: realloc failed.");
+    return (-1);
+  }
+  jvm_argv = tmp;
+
+  jvm_argv[jvm_argc] = strdup (ci->values[0].value.string);
+  if (jvm_argv[jvm_argc] == NULL)
+  {
+    ERROR ("java plugin: strdup failed.");
+    return (-1);
+  }
+  jvm_argc++;
+
+  return (0);
+} /* }}} int cjni_config_add_jvm_arg */
+
+static int cjni_config_load_plugin (oconfig_item_t *ci) /* {{{ */
+{
+  JNIEnv *jvm_env;
+  java_plugin_class_t *class;
+  jmethodID constructor_id;
+  jobject tmp_object;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("java plugin: `LoadPlugin' needs exactly one string argument.");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  class = (java_plugin_class_t *) realloc (java_classes_list,
+      (java_classes_list_len + 1) * sizeof (*java_classes_list));
+  if (class == NULL)
+  {
+    ERROR ("java plugin: realloc failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+  java_classes_list = class;
+  class = java_classes_list + java_classes_list_len;
+
+  memset (class, 0, sizeof (*class));
+  class->name = strdup (ci->values[0].value.string);
+  if (class->name == NULL)
+  {
+    ERROR ("java plugin: strdup failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+  class->class = NULL;
+  class->object = NULL;
+
+  { /* Replace all dots ('.') with slashes ('/'). Dots are usually used
+       thorough the Java community, but (Sun's) `FindClass' and friends need
+       slashes. */
+    size_t i;
+    for (i = 0; class->name[i] != 0; i++)
+      if (class->name[i] == '.')
+        class->name[i] = '/';
+  }
+
+  DEBUG ("java plugin: Loading class %s", class->name);
+
+  class->class = (*jvm_env)->FindClass (jvm_env, class->name);
+  if (class->class == NULL)
+  {
+    ERROR ("java plugin: cjni_config_load_plugin: FindClass (%s) failed.",
+        class->name);
+    cjni_thread_detach ();
+    free (class->name);
+    return (-1);
+  }
+
+  constructor_id = (*jvm_env)->GetMethodID (jvm_env, class->class,
+      "<init>", "()V");
+  if (constructor_id == NULL)
+  {
+    ERROR ("java plugin: cjni_config_load_plugin: "
+        "Could not find the constructor for `%s'.",
+        class->name);
+    cjni_thread_detach ();
+    free (class->name);
+    return (-1);
+  }
+
+  tmp_object = (*jvm_env)->NewObject (jvm_env, class->class,
+      constructor_id);
+  if (tmp_object != NULL)
+    class->object = (*jvm_env)->NewGlobalRef (jvm_env, tmp_object);
+  else
+    class->object = NULL;
+  if (class->object == NULL)
+  {
+    ERROR ("java plugin: cjni_config_load_plugin: "
+        "Could create a new `%s' object.",
+        class->name);
+    cjni_thread_detach ();
+    free (class->name);
+    return (-1);
+  }
+
+  cjni_thread_detach ();
+
+  java_classes_list_len++;
+
+  return (0);
+} /* }}} int cjni_config_load_plugin */
+
+static int cjni_config_plugin_block (oconfig_item_t *ci) /* {{{ */
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+  jobject o_ocitem;
+  const char *name;
+  size_t i;
+
+  jclass class;
+  jmethodID method;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("java plugin: `Plugin' blocks "
+        "need exactly one string argument.");
+    return (-1);
+  }
+
+  name = ci->values[0].value.string;
+
+  cbi = NULL;
+  for (i = 0; i < java_callbacks_num; i++)
+  {
+    if (java_callbacks[i].type != CB_TYPE_CONFIG)
+      continue;
+
+    if (strcmp (name, java_callbacks[i].name) != 0)
+      continue;
+
+    cbi = java_callbacks + i;
+    break;
+  }
+
+  if (cbi == NULL)
+  {
+    NOTICE ("java plugin: Configuration block for `%s' found, but no such "
+        "configuration callback has been registered. Please make sure, the "
+        "`LoadPlugin' lines precede the `Plugin' blocks.",
+        name);
+    return (0);
+  }
+
+  DEBUG ("java plugin: Configuring %s", name);
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  o_ocitem = ctoj_oconfig_item (jvm_env, ci);
+  if (o_ocitem == NULL)
+  {
+    ERROR ("java plugin: cjni_config_plugin_block: ctoj_oconfig_item failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+
+  class = (*jvm_env)->GetObjectClass (jvm_env, cbi->object);
+  method = (*jvm_env)->GetMethodID (jvm_env, class,
+      "config", "(Lorg/collectd/api/OConfigItem;)I");
+
+  (*jvm_env)->CallIntMethod (jvm_env,
+      cbi->object, method, o_ocitem);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
+  cjni_thread_detach ();
+  return (0);
+} /* }}} int cjni_config_plugin_block */
+
+static int cjni_config_perform (oconfig_item_t *ci) /* {{{ */
+{
+  int success;
+  int errors;
+  int status;
+  int i;
+
+  success = 0;
+  errors = 0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("JVMArg", child->key) == 0)
+    {
+      status = cjni_config_add_jvm_arg (child);
+      if (status == 0)
+        success++;
+      else
+        errors++;
+    }
+    else if (strcasecmp ("LoadPlugin", child->key) == 0)
+    {
+      status = cjni_config_load_plugin (child);
+      if (status == 0)
+        success++;
+      else
+        errors++;
+    }
+    else if (strcasecmp ("Plugin", child->key) == 0)
+    {
+      status = cjni_config_plugin_block (child);
+      if (status == 0)
+        success++;
+      else
+        errors++;
+    }
+    else
+    {
+      WARNING ("java plugin: Option `%s' not allowed here.", child->key);
+      errors++;
+    }
+  }
+
+  DEBUG ("java plugin: jvm_argc = %zu;", jvm_argc);
+  DEBUG ("java plugin: java_classes_list_len = %zu;", java_classes_list_len);
+
+  if ((success == 0) && (errors > 0))
+  {
+    ERROR ("java plugin: All statements failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cjni_config_perform */
+
+/* Copy the children of `ci' to the global `config_block' variable. */
+static int cjni_config_callback (oconfig_item_t *ci) /* {{{ */
+{
+  oconfig_item_t *ci_copy;
+  oconfig_item_t *tmp;
+
+  assert (ci != NULL);
+  if (ci->children_num == 0)
+    return (0); /* nothing to do */
+
+  ci_copy = oconfig_clone (ci);
+  if (ci_copy == NULL)
+  {
+    ERROR ("java plugin: oconfig_clone failed.");
+    return (-1);
+  }
+
+  if (config_block == NULL)
+  {
+    config_block = ci_copy;
+    return (0);
+  }
+
+  tmp = realloc (config_block->children,
+      (config_block->children_num + ci_copy->children_num) * sizeof (*tmp));
+  if (tmp == NULL)
+  {
+    ERROR ("java plugin: realloc failed.");
+    oconfig_free (ci_copy);
+    return (-1);
+  }
+  config_block->children = tmp;
+
+  /* Copy the pointers */
+  memcpy (config_block->children + config_block->children_num,
+      ci_copy->children,
+      ci_copy->children_num * sizeof (*ci_copy->children));
+  config_block->children_num += ci_copy->children_num;
+
+  /* Delete the pointers from the copy, so `oconfig_free' can't free them. */
+  memset (ci_copy->children, 0,
+      ci_copy->children_num * sizeof (*ci_copy->children));
+  ci_copy->children_num = 0;
+
+  oconfig_free (ci_copy);
+
+  return (0);
+} /* }}} int cjni_config_callback */
+
+/* Free the data contained in the `user_data_t' pointer passed to `cjni_read'
+ * and `cjni_write'. In particular, delete the global reference to the Java
+ * object. */
+static void cjni_callback_info_destroy (void *arg) /* {{{ */
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+
+  DEBUG ("java plugin: cjni_callback_info_destroy (arg = %p);", arg);
+
+  cbi = (cjni_callback_info_t *) arg;
+
+  /* This condition can occur when shutting down. */
+  if (jvm == NULL)
+  {
+    sfree (cbi);
+    return;
+  }
+
+  if (arg == NULL)
+    return;
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+  {
+    ERROR ("java plugin: cjni_callback_info_destroy: cjni_thread_attach failed.");
+    return;
+  }
+
+  (*jvm_env)->DeleteGlobalRef (jvm_env, cbi->object);
+
+  cbi->method = NULL;
+  cbi->object = NULL;
+  cbi->class  = NULL;
+  free (cbi);
+
+  cjni_thread_detach ();
+} /* }}} void cjni_callback_info_destroy */
+
+/* Call the CB_TYPE_READ callback pointed to by the `user_data_t' pointer. */
+static int cjni_read (user_data_t *ud) /* {{{ */
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+  int ret_status;
+
+  if (jvm == NULL)
+  {
+    ERROR ("java plugin: cjni_read: jvm == NULL");
+    return (-1);
+  }
+
+  if ((ud == NULL) || (ud->data == NULL))
+  {
+    ERROR ("java plugin: cjni_read: Invalid user data.");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  cbi = (cjni_callback_info_t *) ud->data;
+
+  ret_status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object,
+      cbi->method);
+
+  cjni_thread_detach ();
+  return (ret_status);
+} /* }}} int cjni_read */
+
+/* Call the CB_TYPE_WRITE callback pointed to by the `user_data_t' pointer. */
+static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+    user_data_t *ud)
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+  jobject vl_java;
+  int ret_status;
+
+  if (jvm == NULL)
+  {
+    ERROR ("java plugin: cjni_write: jvm == NULL");
+    return (-1);
+  }
+
+  if ((ud == NULL) || (ud->data == NULL))
+  {
+    ERROR ("java plugin: cjni_write: Invalid user data.");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  cbi = (cjni_callback_info_t *) ud->data;
+
+  vl_java = ctoj_value_list (jvm_env, ds, vl);
+  if (vl_java == NULL)
+  {
+    ERROR ("java plugin: cjni_write: ctoj_value_list failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+
+  ret_status = (*jvm_env)->CallIntMethod (jvm_env,
+      cbi->object, cbi->method, vl_java);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, vl_java);
+
+  cjni_thread_detach ();
+  return (ret_status);
+} /* }}} int cjni_write */
+
+/* Call the CB_TYPE_FLUSH callback pointed to by the `user_data_t' pointer. */
+static int cjni_flush (cdtime_t timeout, const char *identifier, /* {{{ */
+    user_data_t *ud)
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+  jobject o_timeout;
+  jobject o_identifier;
+  int ret_status;
+
+  if (jvm == NULL)
+  {
+    ERROR ("java plugin: cjni_flush: jvm == NULL");
+    return (-1);
+  }
+
+  if ((ud == NULL) || (ud->data == NULL))
+  {
+    ERROR ("java plugin: cjni_flush: Invalid user data.");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  cbi = (cjni_callback_info_t *) ud->data;
+
+  o_timeout = ctoj_jdouble_to_number (jvm_env,
+      (jdouble) CDTIME_T_TO_DOUBLE (timeout));
+  if (o_timeout == NULL)
+  {
+    ERROR ("java plugin: cjni_flush: Converting double "
+        "to Number object failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+
+  o_identifier = NULL;
+  if (identifier != NULL)
+  {
+    o_identifier = (*jvm_env)->NewStringUTF (jvm_env, identifier);
+    if (o_identifier == NULL)
+    {
+      (*jvm_env)->DeleteLocalRef (jvm_env, o_timeout);
+      ERROR ("java plugin: cjni_flush: NewStringUTF failed.");
+      cjni_thread_detach ();
+      return (-1);
+    }
+  }
+
+  ret_status = (*jvm_env)->CallIntMethod (jvm_env,
+      cbi->object, cbi->method, o_timeout, o_identifier);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_identifier);
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_timeout);
+
+  cjni_thread_detach ();
+  return (ret_status);
+} /* }}} int cjni_flush */
+
+/* Call the CB_TYPE_LOG callback pointed to by the `user_data_t' pointer. */
+static void cjni_log (int severity, const char *message, /* {{{ */
+    user_data_t *ud)
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+  jobject o_message;
+
+  if (jvm == NULL)
+    return;
+
+  if ((ud == NULL) || (ud->data == NULL))
+    return;
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return;
+
+  cbi = (cjni_callback_info_t *) ud->data;
+
+  o_message = (*jvm_env)->NewStringUTF (jvm_env, message);
+  if (o_message == NULL)
+  {
+    cjni_thread_detach ();
+    return;
+  }
+
+  (*jvm_env)->CallVoidMethod (jvm_env,
+      cbi->object, cbi->method, (jint) severity, o_message);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_message);
+
+  cjni_thread_detach ();
+} /* }}} void cjni_log */
+
+/* Call the CB_TYPE_NOTIFICATION callback pointed to by the `user_data_t'
+ * pointer. */
+static int cjni_notification (const notification_t *n, /* {{{ */
+    user_data_t *ud)
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+  jobject o_notification;
+  int ret_status;
+
+  if (jvm == NULL)
+  {
+    ERROR ("java plugin: cjni_read: jvm == NULL");
+    return (-1);
+  }
+
+  if ((ud == NULL) || (ud->data == NULL))
+  {
+    ERROR ("java plugin: cjni_read: Invalid user data.");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  cbi = (cjni_callback_info_t *) ud->data;
+
+  o_notification = ctoj_notification (jvm_env, n);
+  if (o_notification == NULL)
+  {
+    ERROR ("java plugin: cjni_notification: ctoj_notification failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+
+  ret_status = (*jvm_env)->CallIntMethod (jvm_env,
+      cbi->object, cbi->method, o_notification);
+
+  (*jvm_env)->DeleteLocalRef (jvm_env, o_notification);
+
+  cjni_thread_detach ();
+  return (ret_status);
+} /* }}} int cjni_notification */
+
+/* Callbacks for matches implemented in Java */
+static int cjni_match_target_create (const oconfig_item_t *ci, /* {{{ */
+    void **user_data)
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi_ret;
+  cjni_callback_info_t *cbi_factory;
+  const char *name;
+  jobject o_ci;
+  jobject o_tmp;
+  int type;
+  size_t i;
+
+  cbi_ret = NULL;
+  o_ci = NULL;
+  jvm_env = NULL;
+
+#define BAIL_OUT(status) \
+  if (cbi_ret != NULL) { \
+    free (cbi_ret->name); \
+    if ((jvm_env != NULL) && (cbi_ret->object != NULL)) \
+      (*jvm_env)->DeleteLocalRef (jvm_env, cbi_ret->object); \
+  } \
+  free (cbi_ret); \
+  if (o_ci != NULL) \
+    (*jvm_env)->DeleteLocalRef (jvm_env, o_ci); \
+  cjni_thread_detach (); \
+  return (status)
+
+  if (jvm == NULL)
+  {
+    ERROR ("java plugin: cjni_read: jvm == NULL");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  /* Find out whether to create a match or a target. */
+  if (strcasecmp ("Match", ci->key) == 0)
+    type = CB_TYPE_MATCH;
+  else if (strcasecmp ("Target", ci->key) == 0)
+    type = CB_TYPE_TARGET;
+  else
+  {
+    ERROR ("java plugin: cjni_match_target_create: Can't figure out whether "
+        "to create a match or a target.");
+    BAIL_OUT (-1);
+  }
+
+  /* This is the name of the match we should create. */
+  name = ci->values[0].value.string;
+
+  /* Lets see if we have a matching factory here.. */
+  cbi_factory = NULL;
+  for (i = 0; i < java_callbacks_num; i++)
+  {
+    if (java_callbacks[i].type != type)
+      continue;
+
+    if (strcmp (name, java_callbacks[i].name) != 0)
+      continue;
+
+    cbi_factory = java_callbacks + i;
+    break;
+  }
+
+  /* Nope, no factory for that name.. */
+  if (cbi_factory == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: "
+        "No such match factory registered: %s",
+        name);
+    BAIL_OUT (-1);
+  }
+
+  /* We convert `ci' to its Java equivalent.. */
+  o_ci = ctoj_oconfig_item (jvm_env, ci);
+  if (o_ci == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: "
+        "ctoj_oconfig_item failed.");
+    BAIL_OUT (-1);
+  }
+
+  /* Allocate a new callback info structure. This is going to be our user_data
+   * pointer. */
+  cbi_ret = (cjni_callback_info_t *) malloc (sizeof (*cbi_ret));
+  if (cbi_ret == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: malloc failed.");
+    BAIL_OUT (-1);
+  }
+  memset (cbi_ret, 0, sizeof (*cbi_ret));
+  cbi_ret->object = NULL;
+  cbi_ret->type = type;
+
+  /* Lets fill the callback info structure.. First, the name: */
+  cbi_ret->name = strdup (name);
+  if (cbi_ret->name == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: strdup failed.");
+    BAIL_OUT (-1);
+  }
+
+  /* Then call the factory method so it creates a new object for us. */
+  o_tmp = (*jvm_env)->CallObjectMethod (jvm_env,
+      cbi_factory->object, cbi_factory->method, o_ci);
+  if (o_tmp == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: CallObjectMethod failed.");
+    BAIL_OUT (-1);
+  }
+
+  cbi_ret->object = (*jvm_env)->NewGlobalRef (jvm_env, o_tmp);
+  if (o_tmp == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: NewGlobalRef failed.");
+    BAIL_OUT (-1);
+  }
+
+  /* This is the class of the match. It is possibly different from the class of
+   * the match-factory! */
+  cbi_ret->class = (*jvm_env)->GetObjectClass (jvm_env, cbi_ret->object);
+  if (cbi_ret->class == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: GetObjectClass failed.");
+    BAIL_OUT (-1);
+  }
+
+  /* Lookup the `int match (DataSet, ValueList)' method. */
+  cbi_ret->method = (*jvm_env)->GetMethodID (jvm_env, cbi_ret->class,
+      /* method name = */ (type == CB_TYPE_MATCH) ? "match" : "invoke",
+      "(Lorg/collectd/api/DataSet;Lorg/collectd/api/ValueList;)I");
+  if (cbi_ret->method == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_create: GetMethodID failed.");
+    BAIL_OUT (-1);
+  }
+
+  /* Return the newly created match via the user_data pointer. */
+  *user_data = (void *) cbi_ret;
+
+  cjni_thread_detach ();
+
+  DEBUG ("java plugin: cjni_match_target_create: "
+      "Successfully created a `%s' %s.",
+      cbi_ret->name, (type == CB_TYPE_MATCH) ? "match" : "target");
+
+  /* Success! */
+  return (0);
+#undef BAIL_OUT
+} /* }}} int cjni_match_target_create */
+
+static int cjni_match_target_destroy (void **user_data) /* {{{ */
+{
+  cjni_callback_info_destroy (*user_data);
+  *user_data = NULL;
+
+  return (0);
+} /* }}} int cjni_match_target_destroy */
+
+static int cjni_match_target_invoke (const data_set_t *ds, /* {{{ */
+    value_list_t *vl, notification_meta_t **meta, void **user_data)
+{
+  JNIEnv *jvm_env;
+  cjni_callback_info_t *cbi;
+  jobject o_vl;
+  jobject o_ds;
+  int ret_status;
+  int status;
+
+  if (jvm == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_invoke: jvm == NULL");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  cbi = (cjni_callback_info_t *) *user_data;
+
+  o_vl = ctoj_value_list (jvm_env, ds, vl);
+  if (o_vl == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_invoke: ctoj_value_list failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+
+  o_ds = ctoj_data_set (jvm_env, ds);
+  if (o_ds == NULL)
+  {
+    ERROR ("java plugin: cjni_match_target_invoke: ctoj_value_list failed.");
+    cjni_thread_detach ();
+    return (-1);
+  }
+
+  ret_status = (*jvm_env)->CallIntMethod (jvm_env, cbi->object, cbi->method,
+      o_ds, o_vl);
+
+  DEBUG ("java plugin: cjni_match_target_invoke: Method returned %i.", ret_status);
+
+  /* If we're executing a target, copy the `ValueList' back to our
+   * `value_list_t'. */
+  if (cbi->type == CB_TYPE_TARGET)
+  {
+    value_list_t new_vl;
+
+    memset (&new_vl, 0, sizeof (new_vl));
+    status = jtoc_value_list (jvm_env, &new_vl, o_vl);
+    if (status != 0)
+    {
+      ERROR ("java plugin: cjni_match_target_invoke: "
+          "jtoc_value_list failed.");
+    }
+    else /* if (status == 0) */
+    {
+      /* plugin_dispatch_values assures that this is dynamically allocated
+       * memory. */
+      sfree (vl->values);
+
+      /* This will replace the vl->values pointer to a new, dynamically
+       * allocated piece of memory. */
+      memcpy (vl, &new_vl, sizeof (*vl));
+    }
+  } /* if (cbi->type == CB_TYPE_TARGET) */
+
+  cjni_thread_detach ();
+  return (ret_status);
+} /* }}} int cjni_match_target_invoke */
+
+/* Iterate over `java_callbacks' and call all CB_TYPE_INIT callbacks. */
+static int cjni_init_plugins (JNIEnv *jvm_env) /* {{{ */
+{
+  int status;
+  size_t i;
+
+  for (i = 0; i < java_callbacks_num; i++)
+  {
+    if (java_callbacks[i].type != CB_TYPE_INIT)
+      continue;
+
+    DEBUG ("java plugin: Initializing %s", java_callbacks[i].name);
+
+    status = (*jvm_env)->CallIntMethod (jvm_env,
+        java_callbacks[i].object, java_callbacks[i].method);
+    if (status != 0)
+    {
+      ERROR ("java plugin: Initializing `%s' failed with status %i. "
+          "Removing read function.",
+          java_callbacks[i].name, status);
+      plugin_unregister_read (java_callbacks[i].name);
+    }
+  }
+
+  return (0);
+} /* }}} int cjni_init_plugins */
+
+/* Iterate over `java_callbacks' and call all CB_TYPE_SHUTDOWN callbacks. */
+static int cjni_shutdown_plugins (JNIEnv *jvm_env) /* {{{ */
+{
+  int status;
+  size_t i;
+
+  for (i = 0; i < java_callbacks_num; i++)
+  {
+    if (java_callbacks[i].type != CB_TYPE_SHUTDOWN)
+      continue;
+
+    DEBUG ("java plugin: Shutting down %s", java_callbacks[i].name);
+
+    status = (*jvm_env)->CallIntMethod (jvm_env,
+        java_callbacks[i].object, java_callbacks[i].method);
+    if (status != 0)
+    {
+      ERROR ("java plugin: Shutting down `%s' failed with status %i. ",
+          java_callbacks[i].name, status);
+    }
+  }
+
+  return (0);
+} /* }}} int cjni_shutdown_plugins */
+
+
+static int cjni_shutdown (void) /* {{{ */
+{
+  JNIEnv *jvm_env;
+  JavaVMAttachArgs args;
+  int status;
+  size_t i;
+
+  if (jvm == NULL)
+    return (0);
+
+  jvm_env = NULL;
+  memset (&args, 0, sizeof (args));
+  args.version = JNI_VERSION_1_2;
+
+  status = (*jvm)->AttachCurrentThread (jvm, (void *) &jvm_env, &args);
+  if (status != 0)
+  {
+    ERROR ("java plugin: cjni_shutdown: AttachCurrentThread failed with status %i.",
+        status);
+    return (-1);
+  }
+
+  /* Execute all the shutdown functions registered by plugins. */
+  cjni_shutdown_plugins (jvm_env);
+
+  /* Release all the global references to callback functions */
+  for (i = 0; i < java_callbacks_num; i++)
+  {
+    if (java_callbacks[i].object != NULL)
+    {
+      (*jvm_env)->DeleteGlobalRef (jvm_env, java_callbacks[i].object);
+      java_callbacks[i].object = NULL;
+    }
+    sfree (java_callbacks[i].name);
+  }
+  java_callbacks_num = 0;
+  sfree (java_callbacks);
+
+  /* Release all the global references to directly loaded classes. */
+  for (i = 0; i < java_classes_list_len; i++)
+  {
+    if (java_classes_list[i].object != NULL)
+    {
+      (*jvm_env)->DeleteGlobalRef (jvm_env, java_classes_list[i].object);
+      java_classes_list[i].object = NULL;
+    }
+    sfree (java_classes_list[i].name);
+  }
+  java_classes_list_len = 0;
+  sfree (java_classes_list);
+
+  /* Destroy the JVM */
+  DEBUG ("java plugin: Destroying the JVM.");
+  (*jvm)->DestroyJavaVM (jvm);
+  jvm = NULL;
+  jvm_env = NULL;
+
+  pthread_key_delete (jvm_env_key);
+
+  /* Free the JVM argument list */
+  for (i = 0; i < jvm_argc; i++)
+    sfree (jvm_argv[i]);
+  jvm_argc = 0;
+  sfree (jvm_argv);
+
+  return (0);
+} /* }}} int cjni_shutdown */
+
+/* Initialization: Create a JVM, load all configured classes and call their
+ * `config' and `init' callback methods. */
+static int cjni_init (void) /* {{{ */
+{
+  JNIEnv *jvm_env;
+
+  if ((config_block == NULL) && (jvm == NULL))
+  {
+    ERROR ("java plugin: cjni_init: No configuration block for "
+        "the java plugin was found.");
+    return (-1);
+  }
+
+  if (config_block != NULL)
+  {
+    cjni_config_perform (config_block);
+    oconfig_free (config_block);
+  }
+
+  if (jvm == NULL)
+  {
+    ERROR ("java plugin: cjni_init: jvm == NULL");
+    return (-1);
+  }
+
+  jvm_env = cjni_thread_attach ();
+  if (jvm_env == NULL)
+    return (-1);
+
+  cjni_init_plugins (jvm_env);
+
+  cjni_thread_detach ();
+  return (0);
+} /* }}} int cjni_init */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("java", cjni_config_callback);
+  plugin_register_init ("java", cjni_init);
+  plugin_register_shutdown ("java", cjni_shutdown);
+} /* void module_register (void) */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/libcollectdclient/Makefile.am b/src/libcollectdclient/Makefile.am
new file mode 100644 (file)
index 0000000..5abee2f
--- /dev/null
@@ -0,0 +1,24 @@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+if COMPILER_IS_GCC
+AM_CFLAGS = -Wall -Werror
+endif
+
+pkginclude_HEADERS = collectd/client.h collectd/network.h collectd/network_buffer.h collectd/lcc_features.h
+lib_LTLIBRARIES = libcollectdclient.la
+nodist_pkgconfig_DATA = libcollectdclient.pc
+
+BUILT_SOURCES = collectd/lcc_features.h
+
+libcollectdclient_la_SOURCES = client.c network.c network_buffer.c
+libcollectdclient_la_CPPFLAGS = $(AM_CPPFLAGS) \
+                               -I$(top_srcdir)/src/libcollectdclient/collectd \
+                               -I$(top_builddir)/src/libcollectdclient/collectd \
+                               -I$(top_srcdir)/src/daemon
+libcollectdclient_la_LDFLAGS = -version-info 1:0:0
+libcollectdclient_la_LIBADD = 
+if BUILD_WITH_LIBGCRYPT
+libcollectdclient_la_CPPFLAGS += $(GCRYPT_CPPFLAGS)
+libcollectdclient_la_LDFLAGS += $(GCRYPT_LDFLAGS)
+libcollectdclient_la_LIBADD += $(GCRYPT_LIBS)
+endif
diff --git a/src/libcollectdclient/Makefile.in b/src/libcollectdclient/Makefile.in
new file mode 100644 (file)
index 0000000..d73bb2c
--- /dev/null
@@ -0,0 +1,850 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@BUILD_WITH_LIBGCRYPT_TRUE@am__append_1 = $(GCRYPT_CPPFLAGS)
+@BUILD_WITH_LIBGCRYPT_TRUE@am__append_2 = $(GCRYPT_LDFLAGS)
+@BUILD_WITH_LIBGCRYPT_TRUE@am__append_3 = $(GCRYPT_LIBS)
+subdir = src/libcollectdclient
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+       $(srcdir)/libcollectdclient.pc.in $(pkginclude_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = libcollectdclient.pc
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+       "$(DESTDIR)$(pkgincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@BUILD_WITH_LIBGCRYPT_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+libcollectdclient_la_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_libcollectdclient_la_OBJECTS = libcollectdclient_la-client.lo \
+       libcollectdclient_la-network.lo \
+       libcollectdclient_la-network_buffer.lo
+libcollectdclient_la_OBJECTS = $(am_libcollectdclient_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+libcollectdclient_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+       $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+       $(AM_CFLAGS) $(CFLAGS) $(libcollectdclient_la_LDFLAGS) \
+       $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(libcollectdclient_la_SOURCES)
+DIST_SOURCES = $(libcollectdclient_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+DATA = $(nodist_pkgconfig_DATA)
+HEADERS = $(pkginclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_WITH_LIBAQUAERO5_CFLAGS = @BUILD_WITH_LIBAQUAERO5_CFLAGS@
+BUILD_WITH_LIBAQUAERO5_LDFLAGS = @BUILD_WITH_LIBAQUAERO5_LDFLAGS@
+BUILD_WITH_LIBATASMART_CPPFLAGS = @BUILD_WITH_LIBATASMART_CPPFLAGS@
+BUILD_WITH_LIBATASMART_LDFLAGS = @BUILD_WITH_LIBATASMART_LDFLAGS@
+BUILD_WITH_LIBATASMART_LIBS = @BUILD_WITH_LIBATASMART_LIBS@
+BUILD_WITH_LIBCURL_CFLAGS = @BUILD_WITH_LIBCURL_CFLAGS@
+BUILD_WITH_LIBCURL_LIBS = @BUILD_WITH_LIBCURL_LIBS@
+BUILD_WITH_LIBDBI_CPPFLAGS = @BUILD_WITH_LIBDBI_CPPFLAGS@
+BUILD_WITH_LIBDBI_LDFLAGS = @BUILD_WITH_LIBDBI_LDFLAGS@
+BUILD_WITH_LIBDBI_LIBS = @BUILD_WITH_LIBDBI_LIBS@
+BUILD_WITH_LIBHAL_CFLAGS = @BUILD_WITH_LIBHAL_CFLAGS@
+BUILD_WITH_LIBHAL_LIBS = @BUILD_WITH_LIBHAL_LIBS@
+BUILD_WITH_LIBHIREDIS_CPPFLAGS = @BUILD_WITH_LIBHIREDIS_CPPFLAGS@
+BUILD_WITH_LIBHIREDIS_LDFLAGS = @BUILD_WITH_LIBHIREDIS_LDFLAGS@
+BUILD_WITH_LIBIPTC_CPPFLAGS = @BUILD_WITH_LIBIPTC_CPPFLAGS@
+BUILD_WITH_LIBIPTC_LDFLAGS = @BUILD_WITH_LIBIPTC_LDFLAGS@
+BUILD_WITH_LIBLDAP_CPPFLAGS = @BUILD_WITH_LIBLDAP_CPPFLAGS@
+BUILD_WITH_LIBLDAP_LDFLAGS = @BUILD_WITH_LIBLDAP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_CPPFLAGS = @BUILD_WITH_LIBLVM2APP_CPPFLAGS@
+BUILD_WITH_LIBLVM2APP_LDFLAGS = @BUILD_WITH_LIBLVM2APP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_LIBS = @BUILD_WITH_LIBLVM2APP_LIBS@
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS = @BUILD_WITH_LIBMEMCACHED_CPPFLAGS@
+BUILD_WITH_LIBMEMCACHED_LDFLAGS = @BUILD_WITH_LIBMEMCACHED_LDFLAGS@
+BUILD_WITH_LIBMEMCACHED_LIBS = @BUILD_WITH_LIBMEMCACHED_LIBS@
+BUILD_WITH_LIBMNL_CFLAGS = @BUILD_WITH_LIBMNL_CFLAGS@
+BUILD_WITH_LIBMNL_LIBS = @BUILD_WITH_LIBMNL_LIBS@
+BUILD_WITH_LIBMODBUS_CFLAGS = @BUILD_WITH_LIBMODBUS_CFLAGS@
+BUILD_WITH_LIBMODBUS_LIBS = @BUILD_WITH_LIBMODBUS_LIBS@
+BUILD_WITH_LIBMONGOC_CPPFLAGS = @BUILD_WITH_LIBMONGOC_CPPFLAGS@
+BUILD_WITH_LIBMONGOC_LDFLAGS = @BUILD_WITH_LIBMONGOC_LDFLAGS@
+BUILD_WITH_LIBMYSQL_CFLAGS = @BUILD_WITH_LIBMYSQL_CFLAGS@
+BUILD_WITH_LIBMYSQL_LIBS = @BUILD_WITH_LIBMYSQL_LIBS@
+BUILD_WITH_LIBOPING_CPPFLAGS = @BUILD_WITH_LIBOPING_CPPFLAGS@
+BUILD_WITH_LIBOPING_LDFLAGS = @BUILD_WITH_LIBOPING_LDFLAGS@
+BUILD_WITH_LIBOWCAPI_CPPFLAGS = @BUILD_WITH_LIBOWCAPI_CPPFLAGS@
+BUILD_WITH_LIBOWCAPI_LIBS = @BUILD_WITH_LIBOWCAPI_LIBS@
+BUILD_WITH_LIBPQ_CPPFLAGS = @BUILD_WITH_LIBPQ_CPPFLAGS@
+BUILD_WITH_LIBPQ_LDFLAGS = @BUILD_WITH_LIBPQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS = @BUILD_WITH_LIBRABBITMQ_CPPFLAGS@
+BUILD_WITH_LIBRABBITMQ_LDFLAGS = @BUILD_WITH_LIBRABBITMQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_LIBS = @BUILD_WITH_LIBRABBITMQ_LIBS@
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS = @BUILD_WITH_LIBRDKAFKA_CPPFLAGS@
+BUILD_WITH_LIBRDKAFKA_LDFLAGS = @BUILD_WITH_LIBRDKAFKA_LDFLAGS@
+BUILD_WITH_LIBRDKAFKA_LIBS = @BUILD_WITH_LIBRDKAFKA_LIBS@
+BUILD_WITH_LIBROUTEROS_CPPFLAGS = @BUILD_WITH_LIBROUTEROS_CPPFLAGS@
+BUILD_WITH_LIBROUTEROS_LDFLAGS = @BUILD_WITH_LIBROUTEROS_LDFLAGS@
+BUILD_WITH_LIBRRD_CFLAGS = @BUILD_WITH_LIBRRD_CFLAGS@
+BUILD_WITH_LIBRRD_LDFLAGS = @BUILD_WITH_LIBRRD_LDFLAGS@
+BUILD_WITH_LIBSENSORS_CFLAGS = @BUILD_WITH_LIBSENSORS_CFLAGS@
+BUILD_WITH_LIBSENSORS_LDFLAGS = @BUILD_WITH_LIBSENSORS_LDFLAGS@
+BUILD_WITH_LIBSIGROK_CFLAGS = @BUILD_WITH_LIBSIGROK_CFLAGS@
+BUILD_WITH_LIBSIGROK_LDFLAGS = @BUILD_WITH_LIBSIGROK_LDFLAGS@
+BUILD_WITH_LIBSNMP_CFLAGS = @BUILD_WITH_LIBSNMP_CFLAGS@
+BUILD_WITH_LIBSNMP_LIBS = @BUILD_WITH_LIBSNMP_LIBS@
+BUILD_WITH_LIBSTATGRAB_CFLAGS = @BUILD_WITH_LIBSTATGRAB_CFLAGS@
+BUILD_WITH_LIBSTATGRAB_LDFLAGS = @BUILD_WITH_LIBSTATGRAB_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LIBS = @BUILD_WITH_LIBTOKYOTYRANT_LIBS@
+BUILD_WITH_LIBUDEV_CFLAGS = @BUILD_WITH_LIBUDEV_CFLAGS@
+BUILD_WITH_LIBUDEV_LDFLAGS = @BUILD_WITH_LIBUDEV_LDFLAGS@
+BUILD_WITH_LIBUPSCLIENT_CFLAGS = @BUILD_WITH_LIBUPSCLIENT_CFLAGS@
+BUILD_WITH_LIBUPSCLIENT_LIBS = @BUILD_WITH_LIBUPSCLIENT_LIBS@
+BUILD_WITH_LIBVARNISH_CFLAGS = @BUILD_WITH_LIBVARNISH_CFLAGS@
+BUILD_WITH_LIBVARNISH_LIBS = @BUILD_WITH_LIBVARNISH_LIBS@
+BUILD_WITH_LIBVIRT_CFLAGS = @BUILD_WITH_LIBVIRT_CFLAGS@
+BUILD_WITH_LIBVIRT_LIBS = @BUILD_WITH_LIBVIRT_LIBS@
+BUILD_WITH_LIBXML2_CFLAGS = @BUILD_WITH_LIBXML2_CFLAGS@
+BUILD_WITH_LIBXML2_LIBS = @BUILD_WITH_LIBXML2_LIBS@
+BUILD_WITH_LIBXMMS_CFLAGS = @BUILD_WITH_LIBXMMS_CFLAGS@
+BUILD_WITH_LIBXMMS_LIBS = @BUILD_WITH_LIBXMMS_LIBS@
+BUILD_WITH_LIBYAJL_CPPFLAGS = @BUILD_WITH_LIBYAJL_CPPFLAGS@
+BUILD_WITH_LIBYAJL_LDFLAGS = @BUILD_WITH_LIBYAJL_LDFLAGS@
+BUILD_WITH_LIBYAJL_LIBS = @BUILD_WITH_LIBYAJL_LIBS@
+BUILD_WITH_MIC_CPPFLAGS = @BUILD_WITH_MIC_CPPFLAGS@
+BUILD_WITH_MIC_LDADD = @BUILD_WITH_MIC_LDADD@
+BUILD_WITH_MIC_LIBPATH = @BUILD_WITH_MIC_LIBPATH@
+BUILD_WITH_OPENIPMI_CFLAGS = @BUILD_WITH_OPENIPMI_CFLAGS@
+BUILD_WITH_OPENIPMI_LIBS = @BUILD_WITH_OPENIPMI_LIBS@
+BUILD_WITH_ORACLE_CFLAGS = @BUILD_WITH_ORACLE_CFLAGS@
+BUILD_WITH_ORACLE_LIBS = @BUILD_WITH_ORACLE_LIBS@
+BUILD_WITH_PYTHON_CPPFLAGS = @BUILD_WITH_PYTHON_CPPFLAGS@
+BUILD_WITH_PYTHON_LDFLAGS = @BUILD_WITH_PYTHON_LDFLAGS@
+BUILD_WITH_PYTHON_LIBS = @BUILD_WITH_PYTHON_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_LOG_LEVEL = @DEFAULT_LOG_LEVEL@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GANGLIA_CPPFLAGS = @GANGLIA_CPPFLAGS@
+GANGLIA_LDFLAGS = @GANGLIA_LDFLAGS@
+GANGLIA_LIBS = @GANGLIA_LIBS@
+GCRYPT_CPPFLAGS = @GCRYPT_CPPFLAGS@
+GCRYPT_LDFLAGS = @GCRYPT_LDFLAGS@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVA_CFLAGS = @JAVA_CFLAGS@
+JAVA_CPPFLAGS = @JAVA_CPPFLAGS@
+JAVA_LDFLAGS = @JAVA_LDFLAGS@
+JAVA_LIBS = @JAVA_LIBS@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_DIR = @KERNEL_DIR@
+LCC_VERSION_EXTRA = @LCC_VERSION_EXTRA@
+LCC_VERSION_MAJOR = @LCC_VERSION_MAJOR@
+LCC_VERSION_MINOR = @LCC_VERSION_MINOR@
+LCC_VERSION_PATCH = @LCC_VERSION_PATCH@
+LCC_VERSION_STRING = @LCC_VERSION_STRING@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBNETAPP_CPPFLAGS = @LIBNETAPP_CPPFLAGS@
+LIBNETAPP_LDFLAGS = @LIBNETAPP_LDFLAGS@
+LIBNETAPP_LIBS = @LIBNETAPP_LIBS@
+LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
+LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOAD_PLUGIN_CSV = @LOAD_PLUGIN_CSV@
+LOAD_PLUGIN_LOGFILE = @LOAD_PLUGIN_LOGFILE@
+LOAD_PLUGIN_LOG_LOGSTASH = @LOAD_PLUGIN_LOG_LOGSTASH@
+LOAD_PLUGIN_NETWORK = @LOAD_PLUGIN_NETWORK@
+LOAD_PLUGIN_RRDTOOL = @LOAD_PLUGIN_RRDTOOL@
+LOAD_PLUGIN_SYSLOG = @LOAD_PLUGIN_SYSLOG@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_BINDINGS = @PERL_BINDINGS@
+PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_LIBS = @PERL_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_protoc_c = @have_protoc_c@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+@COMPILER_IS_GCC_TRUE@AM_CFLAGS = -Wall -Werror
+pkginclude_HEADERS = collectd/client.h collectd/network.h collectd/network_buffer.h collectd/lcc_features.h
+lib_LTLIBRARIES = libcollectdclient.la
+nodist_pkgconfig_DATA = libcollectdclient.pc
+BUILT_SOURCES = collectd/lcc_features.h
+libcollectdclient_la_SOURCES = client.c network.c network_buffer.c
+libcollectdclient_la_CPPFLAGS = $(AM_CPPFLAGS) \
+       -I$(top_srcdir)/src/libcollectdclient/collectd \
+       -I$(top_builddir)/src/libcollectdclient/collectd \
+       -I$(top_srcdir)/src/daemon $(am__append_1)
+libcollectdclient_la_LDFLAGS = -version-info 1:0:0 $(am__append_2)
+libcollectdclient_la_LIBADD = $(am__append_3)
+all: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/libcollectdclient/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign src/libcollectdclient/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+libcollectdclient.pc: $(top_builddir)/config.status $(srcdir)/libcollectdclient.pc.in
+       cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+       list2=; for p in $$list; do \
+         if test -f $$p; then \
+           list2="$$list2 $$p"; \
+         else :; fi; \
+       done; \
+       test -z "$$list2" || { \
+         echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+       }
+
+uninstall-libLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+       for p in $$list; do \
+         $(am__strip_dir) \
+         echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+         $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+       done
+
+clean-libLTLIBRARIES:
+       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+       @list='$(lib_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
+
+libcollectdclient.la: $(libcollectdclient_la_OBJECTS) $(libcollectdclient_la_DEPENDENCIES) $(EXTRA_libcollectdclient_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(libcollectdclient_la_LINK) -rpath $(libdir) $(libcollectdclient_la_OBJECTS) $(libcollectdclient_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+.c.o:
+       $(AM_V_CC)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+       $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+       $(AM_V_CC)$(LTCOMPILE) -c -o $@ $<
+
+libcollectdclient_la-client.lo: client.c
+       $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcollectdclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcollectdclient_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c
+
+libcollectdclient_la-network.lo: network.c
+       $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcollectdclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcollectdclient_la-network.lo `test -f 'network.c' || echo '$(srcdir)/'`network.c
+
+libcollectdclient_la-network_buffer.lo: network_buffer.c
+       $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcollectdclient_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcollectdclient_la-network_buffer.lo `test -f 'network_buffer.c' || echo '$(srcdir)/'`network_buffer.c
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+install-nodist_pkgconfigDATA: $(nodist_pkgconfig_DATA)
+       @$(NORMAL_INSTALL)
+       @list='$(nodist_pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+       fi; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+         $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+       done
+
+uninstall-nodist_pkgconfigDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(nodist_pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+       @$(NORMAL_INSTALL)
+       @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+       fi; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
+         $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
+       done
+
+uninstall-pkgincludeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-nodist_pkgconfigDATA \
+       install-pkgincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-nodist_pkgconfigDATA \
+       uninstall-pkgincludeHEADERS
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \
+       ctags-am distclean distclean-compile distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-libLTLIBRARIES install-man \
+       install-nodist_pkgconfigDATA install-pdf install-pdf-am \
+       install-pkgincludeHEADERS install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+       uninstall-libLTLIBRARIES uninstall-nodist_pkgconfigDATA \
+       uninstall-pkgincludeHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libcollectdclient/client.c b/src/libcollectdclient/client.c
new file mode 100644 (file)
index 0000000..9ad61f6
--- /dev/null
@@ -0,0 +1,1110 @@
+/**
+ * libcollectdclient - src/libcollectdclient/client.c
+ * Copyright (C) 2008-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#if !defined(__GNUC__) || !__GNUC__
+# define __attribute__(x) /**/
+#endif
+
+#include "collectd/lcc_features.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+
+#include "collectd/client.h"
+
+/* NI_MAXHOST has been obsoleted by RFC 3493 which is a reason for SunOS 5.11
+ * to no longer define it. We'll use the old, RFC 2553 value here. */
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif
+
+/* OpenBSD doesn't have EPROTO, FreeBSD doesn't have EILSEQ. Oh what joy! */
+#ifndef EILSEQ
+# ifdef EPROTO
+#  define EILSEQ EPROTO
+# else
+#  define EILSEQ EINVAL
+# endif
+#endif
+
+/* Secure/static macros. They work like `strcpy' and `strcat', but assure null
+ * termination. They work for static buffers only, because they use `sizeof'.
+ * The `SSTRCATF' combines the functionality of `snprintf' and `strcat' which
+ * is very useful to add formatted stuff to the end of a buffer. */
+#define SSTRCPY(d,s) do { \
+    strncpy ((d), (s), sizeof (d)); \
+    (d)[sizeof (d) - 1] = 0; \
+  } while (0)
+
+#define SSTRCAT(d,s) do { \
+    size_t _l = strlen (d); \
+    strncpy ((d) + _l, (s), sizeof (d) - _l); \
+    (d)[sizeof (d) - 1] = 0; \
+  } while (0)
+
+#define SSTRCATF(d, ...) do { \
+    char _b[sizeof (d)]; \
+    snprintf (_b, sizeof (_b), __VA_ARGS__); \
+    _b[sizeof (_b) - 1] = 0; \
+    SSTRCAT ((d), _b); \
+  } while (0)
+
+
+#define LCC_SET_ERRSTR(c, ...) do { \
+  snprintf ((c)->errbuf, sizeof ((c)->errbuf), __VA_ARGS__); \
+  (c)->errbuf[sizeof ((c)->errbuf) - 1] = 0; \
+} while (0)
+
+#if COLLECT_DEBUG
+# define LCC_DEBUG(...) printf (__VA_ARGS__)
+#else
+# define LCC_DEBUG(...) /**/
+#endif
+
+/*
+ * Types
+ */
+struct lcc_connection_s
+{
+  FILE *fh;
+  char errbuf[1024];
+};
+
+struct lcc_response_s
+{
+  int status;
+  char message[1024];
+  char **lines;
+  size_t lines_num;
+};
+typedef struct lcc_response_s lcc_response_t;
+
+/*
+ * Private functions
+ */
+/* Even though Posix requires "strerror_r" to return an "int",
+ * some systems (e.g. the GNU libc) return a "char *" _and_
+ * ignore the second argument ... -tokkee */
+static char *sstrerror (int errnum, char *buf, size_t buflen)
+{
+  buf[0] = 0;
+
+#if !HAVE_STRERROR_R
+  snprintf (buf, buflen, "Error #%i; strerror_r is not available.", errnum);
+/* #endif !HAVE_STRERROR_R */
+
+#elif STRERROR_R_CHAR_P
+  {
+    char *temp;
+    temp = strerror_r (errnum, buf, buflen);
+    if (buf[0] == 0)
+    {
+      if ((temp != NULL) && (temp != buf) && (temp[0] != 0))
+        strncpy (buf, temp, buflen);
+      else
+        strncpy (buf, "strerror_r did not return "
+            "an error message", buflen);
+    }
+  }
+/* #endif STRERROR_R_CHAR_P */
+
+#else
+  if (strerror_r (errnum, buf, buflen) != 0)
+  {
+    snprintf (buf, buflen, "Error #%i; "
+        "Additionally, strerror_r failed.",
+        errnum);
+  }
+#endif /* STRERROR_R_CHAR_P */
+
+  buf[buflen - 1] = 0;
+
+  return (buf);
+} /* char *sstrerror */
+
+static int lcc_set_errno (lcc_connection_t *c, int err) /* {{{ */
+{
+  if (c == NULL)
+    return (-1);
+
+  sstrerror (err, c->errbuf, sizeof (c->errbuf));
+  c->errbuf[sizeof (c->errbuf) - 1] = 0;
+
+  return (0);
+} /* }}} int lcc_set_errno */
+
+static char *lcc_strescape (char *dest, const char *src, size_t dest_size) /* {{{ */
+{
+  size_t dest_pos;
+  size_t src_pos;
+
+  if ((dest == NULL) || (src == NULL))
+    return (NULL);
+
+  dest_pos = 0;
+  src_pos = 0;
+
+  assert (dest_size >= 3);
+
+  dest[dest_pos] = '"';
+  dest_pos++;
+
+  while (42)
+  {
+    if ((dest_pos == (dest_size - 2))
+        || (src[src_pos] == 0))
+      break;
+
+    if ((src[src_pos] == '"') || (src[src_pos] == '\\'))
+    {
+      /* Check if there is enough space for both characters.. */
+      if (dest_pos == (dest_size - 3))
+        break;
+
+      dest[dest_pos] = '\\';
+      dest_pos++;
+    }
+
+    dest[dest_pos] = src[src_pos];
+    dest_pos++;
+    src_pos++;
+  }
+
+  assert (dest_pos <= (dest_size - 2));
+
+  dest[dest_pos] = '"';
+  dest_pos++;
+
+  dest[dest_pos] = 0;
+  dest_pos++;
+  src_pos++;
+
+  return (dest);
+} /* }}} char *lcc_strescape */
+
+/* lcc_chomp: Removes all control-characters at the end of a string. */
+static void lcc_chomp (char *str) /* {{{ */
+{
+  size_t str_len;
+
+  str_len = strlen (str);
+  while (str_len > 0)
+  {
+    if (str[str_len - 1] >= 32)
+      break;
+    str[str_len - 1] = 0;
+    str_len--;
+  }
+} /* }}} void lcc_chomp */
+
+static void lcc_response_free (lcc_response_t *res) /* {{{ */
+{
+  size_t i;
+
+  if (res == NULL)
+    return;
+
+  for (i = 0; i < res->lines_num; i++)
+    free (res->lines[i]);
+  free (res->lines);
+  res->lines = NULL;
+} /* }}} void lcc_response_free */
+
+static int lcc_send (lcc_connection_t *c, const char *command) /* {{{ */
+{
+  int status;
+
+  LCC_DEBUG ("send:    --> %s\n", command);
+
+  status = fprintf (c->fh, "%s\r\n", command);
+  if (status < 0)
+  {
+    lcc_set_errno (c, errno);
+    return (-1);
+  }
+  fflush(c->fh);
+
+  return (0);
+} /* }}} int lcc_send */
+
+static int lcc_receive (lcc_connection_t *c, /* {{{ */
+    lcc_response_t *ret_res)
+{
+  lcc_response_t res;
+  char *ptr;
+  char buffer[4096];
+  size_t i;
+
+  memset (&res, 0, sizeof (res));
+
+  /* Read the first line, containing the status and a message */
+  ptr = fgets (buffer, sizeof (buffer), c->fh);
+  if (ptr == NULL)
+  {
+    lcc_set_errno (c, errno);
+    return (-1);
+  }
+  lcc_chomp (buffer);
+  LCC_DEBUG ("receive: <-- %s\n", buffer);
+
+  /* Convert the leading status to an integer and make `ptr' to point to the
+   * beginning of the message. */
+  ptr = NULL;
+  errno = 0;
+  res.status = strtol (buffer, &ptr, 0);
+  if ((errno != 0) || (ptr == &buffer[0]))
+  {
+    lcc_set_errno (c, errno);
+    return (-1);
+  }
+
+  /* Skip white spaces after the status number */
+  while ((*ptr == ' ') || (*ptr == '\t'))
+    ptr++;
+
+  /* Now copy the message. */
+  strncpy (res.message, ptr, sizeof (res.message));
+  res.message[sizeof (res.message) - 1] = 0;
+
+  /* Error or no lines follow: We're done. */
+  if (res.status <= 0)
+  {
+    memcpy (ret_res, &res, sizeof (res));
+    return (0);
+  }
+
+  /* Allocate space for the char-pointers */
+  res.lines_num = (size_t) res.status;
+  res.status = 0;
+  res.lines = (char **) malloc (res.lines_num * sizeof (char *));
+  if (res.lines == NULL)
+  {
+    lcc_set_errno (c, ENOMEM);
+    return (-1);
+  }
+
+  /* Now receive all the lines */
+  for (i = 0; i < res.lines_num; i++)
+  {
+    ptr = fgets (buffer, sizeof (buffer), c->fh);
+    if (ptr == NULL)
+    {
+      lcc_set_errno (c, errno);
+      break;
+    }
+    lcc_chomp (buffer);
+    LCC_DEBUG ("receive: <-- %s\n", buffer);
+
+    res.lines[i] = strdup (buffer);
+    if (res.lines[i] == NULL)
+    {
+      lcc_set_errno (c, ENOMEM);
+      break;
+    }
+  }
+
+  /* Check if the for-loop exited with an error. */
+  if (i < res.lines_num)
+  {
+    while (i > 0)
+    {
+      i--;
+      free (res.lines[i]);
+    }
+    free (res.lines);
+    return (-1);
+  }
+
+  memcpy (ret_res, &res, sizeof (res));
+  return (0);
+} /* }}} int lcc_receive */
+
+static int lcc_sendreceive (lcc_connection_t *c, /* {{{ */
+    const char *command, lcc_response_t *ret_res)
+{
+  lcc_response_t res;
+  int status;
+
+  if (c->fh == NULL)
+  {
+    lcc_set_errno (c, EBADF);
+    return (-1);
+  }
+
+  status = lcc_send (c, command);
+  if (status != 0)
+    return (status);
+
+  memset (&res, 0, sizeof (res));
+  status = lcc_receive (c, &res);
+  if (status == 0)
+    memcpy (ret_res, &res, sizeof (*ret_res));
+
+  return (status);
+} /* }}} int lcc_sendreceive */
+
+static int lcc_open_unixsocket (lcc_connection_t *c, const char *path) /* {{{ */
+{
+  struct sockaddr_un sa;
+  int fd;
+  int status;
+
+  assert (c != NULL);
+  assert (c->fh == NULL);
+  assert (path != NULL);
+
+  /* Don't use PF_UNIX here, because it's broken on Mac OS X (10.4, possibly
+   * others). */
+  fd = socket (AF_UNIX, SOCK_STREAM, /* protocol = */ 0);
+  if (fd < 0)
+  {
+    lcc_set_errno (c, errno);
+    return (-1);
+  }
+
+  memset (&sa, 0, sizeof (sa));
+  sa.sun_family = AF_UNIX;
+  strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
+
+  status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
+  if (status != 0)
+  {
+    lcc_set_errno (c, errno);
+    close (fd);
+    return (-1);
+  }
+
+  c->fh = fdopen (fd, "r+");
+  if (c->fh == NULL)
+  {
+    lcc_set_errno (c, errno);
+    close (fd);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int lcc_open_unixsocket */
+
+static int lcc_open_netsocket (lcc_connection_t *c, /* {{{ */
+    const char *addr_orig)
+{
+  struct addrinfo ai_hints;
+  struct addrinfo *ai_res;
+  struct addrinfo *ai_ptr;
+  char addr_copy[NI_MAXHOST];
+  char *addr;
+  char *port;
+  int fd;
+  int status;
+
+  assert (c != NULL);
+  assert (c->fh == NULL);
+  assert (addr_orig != NULL);
+
+  strncpy(addr_copy, addr_orig, sizeof(addr_copy));
+  addr_copy[sizeof(addr_copy) - 1] = '\0';
+  addr = addr_copy;
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags = 0;
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_STREAM;
+
+  port = NULL;
+  if (*addr == '[') /* IPv6+port format */
+  {
+    /* `addr' is something like "[2001:780:104:2:211:24ff:feab:26f8]:12345" */
+    addr++;
+
+    port = strchr (addr, ']');
+    if (port == NULL)
+    {
+      LCC_SET_ERRSTR (c, "malformed address: %s", addr_orig);
+      return (-1);
+    }
+    *port = 0;
+    port++;
+
+    if (*port == ':')
+      port++;
+    else if (*port == 0)
+      port = NULL;
+    else
+    {
+      LCC_SET_ERRSTR (c, "garbage after address: %s", port);
+      return (-1);
+    }
+  } /* if (*addr = ']') */
+  else if (strchr (addr, '.') != NULL) /* Hostname or IPv4 */
+  {
+    port = strrchr (addr, ':');
+    if (port != NULL)
+    {
+      *port = 0;
+      port++;
+    }
+  }
+
+  ai_res = NULL;
+  status = getaddrinfo (addr,
+                        port == NULL ? LCC_DEFAULT_PORT : port,
+                        &ai_hints, &ai_res);
+  if (status != 0)
+  {
+    LCC_SET_ERRSTR (c, "getaddrinfo: %s", gai_strerror (status));
+    return (-1);
+  }
+
+  for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+    if (fd < 0)
+    {
+      status = errno;
+      fd = -1;
+      continue;
+    }
+
+    status = connect (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    if (status != 0)
+    {
+      status = errno;
+      close (fd);
+      fd = -1;
+      continue;
+    }
+
+    c->fh = fdopen (fd, "r+");
+    if (c->fh == NULL)
+    {
+      status = errno;
+      close (fd);
+      fd = -1;
+      continue;
+    }
+
+    assert (status == 0);
+    break;
+  } /* for (ai_ptr) */
+
+  if (status != 0)
+  {
+    lcc_set_errno (c, status);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int lcc_open_netsocket */
+
+static int lcc_open_socket (lcc_connection_t *c, const char *addr) /* {{{ */
+{
+  int status = 0;
+
+  if (addr == NULL)
+    return (-1);
+
+  assert (c != NULL);
+  assert (c->fh == NULL);
+  assert (addr != NULL);
+
+  if (strncmp ("unix:", addr, strlen ("unix:")) == 0)
+    status = lcc_open_unixsocket (c, addr + strlen ("unix:"));
+  else if (addr[0] == '/')
+    status = lcc_open_unixsocket (c, addr);
+  else
+    status = lcc_open_netsocket (c, addr);
+
+  return (status);
+} /* }}} int lcc_open_socket */
+
+/*
+ * Public functions
+ */
+unsigned int lcc_version (void) /* {{{ */
+{
+  return (LCC_VERSION);
+} /* }}} unsigned int lcc_version */
+
+const char *lcc_version_string (void) /* {{{ */
+{
+  return (LCC_VERSION_STRING);
+} /* }}} const char *lcc_version_string */
+
+const char *lcc_version_extra (void) /* {{{ */
+{
+  return (LCC_VERSION_EXTRA);
+} /* }}} const char *lcc_version_extra */
+
+int lcc_connect (const char *address, lcc_connection_t **ret_con) /* {{{ */
+{
+  lcc_connection_t *c;
+  int status;
+
+  if (address == NULL)
+    return (-1);
+
+  if (ret_con == NULL)
+    return (-1);
+
+  c = (lcc_connection_t *) malloc (sizeof (*c));
+  if (c == NULL)
+    return (-1);
+  memset (c, 0, sizeof (*c));
+
+  status = lcc_open_socket (c, address);
+  if (status != 0)
+  {
+    lcc_disconnect (c);
+    return (status);
+  }
+
+  *ret_con = c;
+  return (0);
+} /* }}} int lcc_connect */
+
+int lcc_disconnect (lcc_connection_t *c) /* {{{ */
+{
+  if (c == NULL)
+    return (-1);
+
+  if (c->fh != NULL)
+  {
+    fclose (c->fh);
+    c->fh = NULL;
+  }
+
+  free (c);
+  return (0);
+} /* }}} int lcc_disconnect */
+
+int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident, /* {{{ */
+    size_t *ret_values_num, gauge_t **ret_values, char ***ret_values_names)
+{
+  char ident_str[6 * LCC_NAME_LEN];
+  char ident_esc[12 * LCC_NAME_LEN];
+  char command[14 * LCC_NAME_LEN];
+
+  lcc_response_t res;
+  size_t   values_num;
+  gauge_t *values = NULL;
+  char   **values_names = NULL;
+
+  size_t i;
+  int status;
+
+  if (c == NULL)
+    return (-1);
+
+  if (ident == NULL)
+  {
+    lcc_set_errno (c, EINVAL);
+    return (-1);
+  }
+
+  /* Build a commend with an escaped version of the identifier string. */
+  status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), ident);
+  if (status != 0)
+    return (status);
+
+  snprintf (command, sizeof (command), "GETVAL %s",
+      lcc_strescape (ident_esc, ident_str, sizeof (ident_esc)));
+  command[sizeof (command) - 1] = 0;
+
+  /* Send talk to the daemon.. */
+  status = lcc_sendreceive (c, command, &res);
+  if (status != 0)
+    return (status);
+
+  if (res.status != 0)
+  {
+    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
+    lcc_response_free (&res);
+    return (-1);
+  }
+
+  values_num = res.lines_num;
+
+#define BAIL_OUT(e) do { \
+  lcc_set_errno (c, (e)); \
+  free (values); \
+  if (values_names != NULL) { \
+    for (i = 0; i < values_num; i++) { \
+      free (values_names[i]); \
+    } \
+  } \
+  free (values_names); \
+  lcc_response_free (&res); \
+  return (-1); \
+} while (0)
+
+  /* If neither the values nor the names are requested, return here.. */
+  if ((ret_values == NULL) && (ret_values_names == NULL))
+  {
+    if (ret_values_num != NULL)
+      *ret_values_num = values_num;
+    lcc_response_free (&res);
+    return (0);
+  }
+
+  /* Allocate space for the values */
+  if (ret_values != NULL)
+  {
+    values = (gauge_t *) malloc (values_num * sizeof (*values));
+    if (values == NULL)
+      BAIL_OUT (ENOMEM);
+  }
+
+  if (ret_values_names != NULL)
+  {
+    values_names = (char **) calloc (values_num, sizeof (*values_names));
+    if (values_names == NULL)
+      BAIL_OUT (ENOMEM);
+  }
+
+  for (i = 0; i < res.lines_num; i++)
+  {
+    char *key;
+    char *value;
+    char *endptr;
+
+    key = res.lines[i];
+    value = strchr (key, '=');
+    if (value == NULL)
+      BAIL_OUT (EILSEQ);
+
+    *value = 0;
+    value++;
+
+    if (values != NULL)
+    {
+      endptr = NULL;
+      errno = 0;
+      values[i] = strtod (value, &endptr);
+
+      if ((endptr == value) || (errno != 0))
+        BAIL_OUT (errno);
+    }
+
+    if (values_names != NULL)
+    {
+      values_names[i] = strdup (key);
+      if (values_names[i] == NULL)
+        BAIL_OUT (ENOMEM);
+    }
+  } /* for (i = 0; i < res.lines_num; i++) */
+
+  if (ret_values_num != NULL)
+    *ret_values_num = values_num;
+  if (ret_values != NULL)
+    *ret_values = values;
+  if (ret_values_names != NULL)
+    *ret_values_names = values_names;
+
+  lcc_response_free (&res);
+
+  return (0);
+} /* }}} int lcc_getval */
+
+int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl) /* {{{ */
+{
+  char ident_str[6 * LCC_NAME_LEN];
+  char ident_esc[12 * LCC_NAME_LEN];
+  char command[1024] = "";
+  lcc_response_t res;
+  int status;
+  size_t i;
+
+  if ((c == NULL) || (vl == NULL) || (vl->values_len < 1)
+      || (vl->values == NULL) || (vl->values_types == NULL))
+  {
+    lcc_set_errno (c, EINVAL);
+    return (-1);
+  }
+
+  status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str),
+      &vl->identifier);
+  if (status != 0)
+    return (status);
+
+  SSTRCATF (command, "PUTVAL %s",
+      lcc_strescape (ident_esc, ident_str, sizeof (ident_esc)));
+
+  if (vl->interval > 0.0)
+    SSTRCATF (command, " interval=%.3f", vl->interval);
+
+  if (vl->time > 0.0)
+    SSTRCATF (command, " %.3f", vl->time);
+  else
+    SSTRCAT (command, " N");
+
+  for (i = 0; i < vl->values_len; i++)
+  {
+    if (vl->values_types[i] == LCC_TYPE_COUNTER)
+      SSTRCATF (command, ":%"PRIu64, vl->values[i].counter);
+    else if (vl->values_types[i] == LCC_TYPE_GAUGE)
+    {
+      if (isnan (vl->values[i].gauge))
+        SSTRCATF (command, ":U");
+      else
+        SSTRCATF (command, ":%g", vl->values[i].gauge);
+    }
+    else if (vl->values_types[i] == LCC_TYPE_DERIVE)
+       SSTRCATF (command, ":%"PRIu64, vl->values[i].derive);
+    else if (vl->values_types[i] == LCC_TYPE_ABSOLUTE)
+       SSTRCATF (command, ":%"PRIu64, vl->values[i].absolute);
+
+  } /* for (i = 0; i < vl->values_len; i++) */
+
+  status = lcc_sendreceive (c, command, &res);
+  if (status != 0)
+    return (status);
+
+  if (res.status != 0)
+  {
+    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
+    lcc_response_free (&res);
+    return (-1);
+  }
+
+  lcc_response_free (&res);
+  return (0);
+} /* }}} int lcc_putval */
+
+int lcc_flush (lcc_connection_t *c, const char *plugin, /* {{{ */
+    lcc_identifier_t *ident, int timeout)
+{
+  char command[1024] = "";
+  lcc_response_t res;
+  int status;
+
+  if (c == NULL)
+  {
+    lcc_set_errno (c, EINVAL);
+    return (-1);
+  }
+
+  SSTRCPY (command, "FLUSH");
+
+  if (timeout > 0)
+    SSTRCATF (command, " timeout=%i", timeout);
+
+  if (plugin != NULL)
+  {
+    char buffer[2 * LCC_NAME_LEN];
+    SSTRCATF (command, " plugin=%s",
+        lcc_strescape (buffer, plugin, sizeof (buffer)));
+  }
+
+  if (ident != NULL)
+  {
+    char ident_str[6 * LCC_NAME_LEN];
+    char ident_esc[12 * LCC_NAME_LEN];
+
+    status = lcc_identifier_to_string (c, ident_str, sizeof (ident_str), ident);
+    if (status != 0)
+      return (status);
+
+    SSTRCATF (command, " identifier=%s",
+        lcc_strescape (ident_esc, ident_str, sizeof (ident_esc)));
+  }
+
+  status = lcc_sendreceive (c, command, &res);
+  if (status != 0)
+    return (status);
+
+  if (res.status != 0)
+  {
+    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
+    lcc_response_free (&res);
+    return (-1);
+  }
+
+  lcc_response_free (&res);
+  return (0);
+} /* }}} int lcc_flush */
+
+/* TODO: Implement lcc_putnotif */
+
+int lcc_listval (lcc_connection_t *c, /* {{{ */
+    lcc_identifier_t **ret_ident, size_t *ret_ident_num)
+{
+  lcc_response_t res;
+  size_t i;
+  int status;
+
+  lcc_identifier_t *ident;
+  size_t ident_num;
+
+  if (c == NULL)
+    return (-1);
+
+  if ((ret_ident == NULL) || (ret_ident_num == NULL))
+  {
+    lcc_set_errno (c, EINVAL);
+    return (-1);
+  }
+
+  status = lcc_sendreceive (c, "LISTVAL", &res);
+  if (status != 0)
+    return (status);
+
+  if (res.status != 0)
+  {
+    LCC_SET_ERRSTR (c, "Server error: %s", res.message);
+    lcc_response_free (&res);
+    return (-1);
+  }
+
+  ident_num = res.lines_num;
+  ident = (lcc_identifier_t *) malloc (ident_num * sizeof (*ident));
+  if (ident == NULL)
+  {
+    lcc_response_free (&res);
+    lcc_set_errno (c, ENOMEM);
+    return (-1);
+  }
+
+  for (i = 0; i < res.lines_num; i++)
+  {
+    char *time_str;
+    char *ident_str;
+
+    /* First field is the time. */
+    time_str = res.lines[i];
+
+    /* Set `ident_str' to the beginning of the second field. */
+    ident_str = time_str;
+    while ((*ident_str != ' ') && (*ident_str != '\t') && (*ident_str != 0))
+      ident_str++;
+    while ((*ident_str == ' ') || (*ident_str == '\t'))
+    {
+      *ident_str = 0;
+      ident_str++;
+    }
+
+    if (*ident_str == 0)
+    {
+      lcc_set_errno (c, EILSEQ);
+      status = -1;
+      break;
+    }
+
+    status = lcc_string_to_identifier (c, ident + i, ident_str);
+    if (status != 0)
+      break;
+  }
+
+  lcc_response_free (&res);
+
+  if (status != 0)
+  {
+    free (ident);
+    return (-1);
+  }
+
+  *ret_ident = ident;
+  *ret_ident_num = ident_num;
+
+  return (0);
+} /* }}} int lcc_listval */
+
+const char *lcc_strerror (lcc_connection_t *c) /* {{{ */
+{
+  if (c == NULL)
+    return ("Invalid object");
+  return (c->errbuf);
+} /* }}} const char *lcc_strerror */
+
+int lcc_identifier_to_string (lcc_connection_t *c, /* {{{ */
+    char *string, size_t string_size, const lcc_identifier_t *ident)
+{
+  if ((string == NULL) || (string_size < 6) || (ident == NULL))
+  {
+    lcc_set_errno (c, EINVAL);
+    return (-1);
+  }
+
+  if (ident->plugin_instance[0] == 0)
+  {
+    if (ident->type_instance[0] == 0)
+      snprintf (string, string_size, "%s/%s/%s",
+          ident->host,
+          ident->plugin,
+          ident->type);
+    else
+      snprintf (string, string_size, "%s/%s/%s-%s",
+          ident->host,
+          ident->plugin,
+          ident->type,
+          ident->type_instance);
+  }
+  else
+  {
+    if (ident->type_instance[0] == 0)
+      snprintf (string, string_size, "%s/%s-%s/%s",
+          ident->host,
+          ident->plugin,
+          ident->plugin_instance,
+          ident->type);
+    else
+      snprintf (string, string_size, "%s/%s-%s/%s-%s",
+          ident->host,
+          ident->plugin,
+          ident->plugin_instance,
+          ident->type,
+          ident->type_instance);
+  }
+
+  string[string_size - 1] = 0;
+  return (0);
+} /* }}} int lcc_identifier_to_string */
+
+int lcc_string_to_identifier (lcc_connection_t *c, /* {{{ */
+    lcc_identifier_t *ident, const char *string)
+{
+  char *string_copy;
+  char *host;
+  char *plugin;
+  char *plugin_instance;
+  char *type;
+  char *type_instance;
+
+  string_copy = strdup (string);
+  if (string_copy == NULL)
+  {
+    lcc_set_errno (c, ENOMEM);
+    return (-1);
+  }
+
+  host = string_copy;
+  plugin = strchr (host, '/');
+  if (plugin == NULL)
+  {
+    LCC_SET_ERRSTR (c, "Malformed identifier string: %s", string);
+    free (string_copy);
+    return (-1);
+  }
+  *plugin = 0;
+  plugin++;
+
+  type = strchr (plugin, '/');
+  if (type == NULL)
+  {
+    LCC_SET_ERRSTR (c, "Malformed identifier string: %s", string);
+    free (string_copy);
+    return (-1);
+  }
+  *type = 0;
+  type++;
+
+  plugin_instance = strchr (plugin, '-');
+  if (plugin_instance != NULL)
+  {
+    *plugin_instance = 0;
+    plugin_instance++;
+  }
+
+  type_instance = strchr (type, '-');
+  if (type_instance != NULL)
+  {
+    *type_instance = 0;
+    type_instance++;
+  }
+
+  memset (ident, 0, sizeof (*ident));
+
+  SSTRCPY (ident->host, host);
+  SSTRCPY (ident->plugin, plugin);
+  if (plugin_instance != NULL)
+    SSTRCPY (ident->plugin_instance, plugin_instance);
+  SSTRCPY (ident->type, type);
+  if (type_instance != NULL)
+    SSTRCPY (ident->type_instance, type_instance);
+
+  free (string_copy);
+  return (0);
+} /* }}} int lcc_string_to_identifier */
+
+int lcc_identifier_compare (const lcc_identifier_t *i0, /* {{{ */
+    const lcc_identifier_t *i1)
+{
+  int status;
+
+  if ((i0 == NULL) && (i1 == NULL))
+    return (0);
+  else if (i0 == NULL)
+    return (-1);
+  else if (i1 == NULL)
+    return (1);
+
+#define CMP_FIELD(f) do {         \
+  status = strcmp (i0->f, i1->f); \
+  if (status != 0)                \
+    return (status);              \
+} while (0);
+
+    CMP_FIELD (host);
+    CMP_FIELD (plugin);
+    CMP_FIELD (plugin_instance);
+    CMP_FIELD (type);
+    CMP_FIELD (type_instance);
+
+#undef CMP_FIELD
+
+    return (0);
+} /* }}} int lcc_identifier_compare */
+
+int lcc_sort_identifiers (lcc_connection_t *c, /* {{{ */
+    lcc_identifier_t *idents, size_t idents_num)
+{
+  if (idents == NULL)
+  {
+    lcc_set_errno (c, EINVAL);
+    return (-1);
+  }
+
+  qsort (idents, idents_num, sizeof (*idents),
+      (void *) lcc_identifier_compare);
+  return (0);
+} /* }}} int lcc_sort_identifiers */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/libcollectdclient/collectd/client.h b/src/libcollectdclient/collectd/client.h
new file mode 100644 (file)
index 0000000..6ae8598
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+ * libcollectdclient - src/libcollectdclient/collectd/client.h
+ * Copyright (C) 2008-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef LIBCOLLECTD_COLLECTDCLIENT_H
+#define LIBCOLLECTD_COLLECTDCLIENT_H 1
+
+#include "lcc_features.h"
+
+/*
+ * Includes (for data types)
+ */
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#include <inttypes.h>
+#include <time.h>
+
+/*
+ * Defines
+ */
+#define LCC_NAME_LEN 64
+#define LCC_DEFAULT_PORT "25826"
+
+/*
+ * Types
+ */
+#define LCC_TYPE_COUNTER 0
+#define LCC_TYPE_GAUGE   1
+#define LCC_TYPE_DERIVE   2
+#define LCC_TYPE_ABSOLUTE   3
+
+LCC_BEGIN_DECLS
+
+typedef uint64_t counter_t;
+typedef double gauge_t;
+typedef uint64_t derive_t;
+typedef uint64_t absolute_t;
+
+union value_u
+{
+  counter_t counter;
+  gauge_t   gauge;
+  derive_t  derive;
+  absolute_t absolute;
+};
+typedef union value_u value_t;
+
+struct lcc_identifier_s
+{
+  char host[LCC_NAME_LEN];
+  char plugin[LCC_NAME_LEN];
+  char plugin_instance[LCC_NAME_LEN];
+  char type[LCC_NAME_LEN];
+  char type_instance[LCC_NAME_LEN];
+};
+typedef struct lcc_identifier_s lcc_identifier_t;
+#define LCC_IDENTIFIER_INIT { "localhost", "", "", "", "" }
+
+struct lcc_value_list_s
+{
+  value_t *values;
+  int     *values_types;
+  size_t   values_len;
+  double   time;
+  double   interval;
+  lcc_identifier_t identifier;
+};
+typedef struct lcc_value_list_s lcc_value_list_t;
+#define LCC_VALUE_LIST_INIT { NULL, NULL, 0, 0, 0, LCC_IDENTIFIER_INIT }
+
+struct lcc_connection_s;
+typedef struct lcc_connection_s lcc_connection_t;
+
+/*
+ * Functions
+ */
+int lcc_connect (const char *address, lcc_connection_t **ret_con);
+int lcc_disconnect (lcc_connection_t *c);
+#define LCC_DESTROY(c) do { lcc_disconnect (c); (c) = NULL; } while (0)
+
+int lcc_getval (lcc_connection_t *c, lcc_identifier_t *ident,
+    size_t *ret_values_num, gauge_t **ret_values, char ***ret_values_names);
+
+int lcc_putval (lcc_connection_t *c, const lcc_value_list_t *vl);
+
+int lcc_flush (lcc_connection_t *c, const char *plugin,
+    lcc_identifier_t *ident, int timeout);
+
+int lcc_listval (lcc_connection_t *c,
+    lcc_identifier_t **ret_ident, size_t *ret_ident_num);
+
+/* TODO: putnotif */
+
+const char *lcc_strerror (lcc_connection_t *c);
+
+int lcc_identifier_to_string (lcc_connection_t *c,
+    char *string, size_t string_size, const lcc_identifier_t *ident);
+int lcc_string_to_identifier (lcc_connection_t *c,
+    lcc_identifier_t *ident, const char *string);
+
+/* Compares the identifiers "i0" and "i1" and returns less than zero or greater
+ * than zero if "i0" is smaller than or greater than "i1", respectively. If
+ * "i0" and "i1" are identical, zero is returned. */
+int lcc_identifier_compare (const lcc_identifier_t *i0,
+    const lcc_identifier_t *i1);
+int lcc_sort_identifiers (lcc_connection_t *c,
+    lcc_identifier_t *idents, size_t idents_num);
+
+LCC_END_DECLS
+
+/* vim: set sw=2 sts=2 et : */
+#endif /* LIBCOLLECTD_COLLECTDCLIENT_H */
diff --git a/src/libcollectdclient/collectd/lcc_features.h b/src/libcollectdclient/collectd/lcc_features.h
new file mode 100644 (file)
index 0000000..1c633d2
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * libcollectdclient - src/libcollectdclient/lcc_features.h
+ * Copyright (C) 2009  Sebastian Harl
+ *
+ * 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:
+ *   Sebastian tokkee Harl <sh at tokkee.org>
+ **/
+
+#ifndef LIBCOLLECTD_LCC_FEATURES_H
+#define LIBCOLLECTD_LCC_FEATURES_H 1
+
+#ifdef __cplusplus
+# define LCC_BEGIN_DECLS extern "C" {
+# define LCC_END_DECLS   }
+#else
+# define LCC_BEGIN_DECLS
+# define LCC_END_DECLS
+#endif
+
+#define LCC_API_VERSION 0
+
+#define LCC_VERSION_MAJOR 5
+#define LCC_VERSION_MINOR 5
+#define LCC_VERSION_PATCH 0
+
+#define LCC_VERSION_EXTRA ""
+
+#define LCC_VERSION_STRING "5.5.0"
+
+#define LCC_VERSION_ENCODE(major, minor, patch) \
+       ((major) * 10000 + (minor) * 100 + (patch))
+
+#define LCC_VERSION \
+       LCC_VERSION_ENCODE(LCC_VERSION_MAJOR, LCC_VERSION_MINOR, LCC_VERSION_PATCH)
+
+LCC_BEGIN_DECLS
+
+unsigned int lcc_version (void);
+
+const char *lcc_version_string (void);
+
+const char *lcc_version_extra (void);
+
+LCC_END_DECLS
+
+#endif /* ! LIBCOLLECTD_LCC_FEATURES_H */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/libcollectdclient/collectd/lcc_features.h.in b/src/libcollectdclient/collectd/lcc_features.h.in
new file mode 100644 (file)
index 0000000..0e6fcd4
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * libcollectdclient - src/libcollectdclient/lcc_features.h
+ * Copyright (C) 2009  Sebastian Harl
+ *
+ * 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:
+ *   Sebastian tokkee Harl <sh at tokkee.org>
+ **/
+
+#ifndef LIBCOLLECTD_LCC_FEATURES_H
+#define LIBCOLLECTD_LCC_FEATURES_H 1
+
+#ifdef __cplusplus
+# define LCC_BEGIN_DECLS extern "C" {
+# define LCC_END_DECLS   }
+#else
+# define LCC_BEGIN_DECLS
+# define LCC_END_DECLS
+#endif
+
+#define LCC_API_VERSION 0
+
+#define LCC_VERSION_MAJOR @LCC_VERSION_MAJOR@
+#define LCC_VERSION_MINOR @LCC_VERSION_MINOR@
+#define LCC_VERSION_PATCH @LCC_VERSION_PATCH@
+
+#define LCC_VERSION_EXTRA "@LCC_VERSION_EXTRA@"
+
+#define LCC_VERSION_STRING "@LCC_VERSION_STRING@"
+
+#define LCC_VERSION_ENCODE(major, minor, patch) \
+       ((major) * 10000 + (minor) * 100 + (patch))
+
+#define LCC_VERSION \
+       LCC_VERSION_ENCODE(LCC_VERSION_MAJOR, LCC_VERSION_MINOR, LCC_VERSION_PATCH)
+
+LCC_BEGIN_DECLS
+
+unsigned int lcc_version (void);
+
+const char *lcc_version_string (void);
+
+const char *lcc_version_extra (void);
+
+LCC_END_DECLS
+
+#endif /* ! LIBCOLLECTD_LCC_FEATURES_H */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/libcollectdclient/collectd/network.h b/src/libcollectdclient/collectd/network.h
new file mode 100644 (file)
index 0000000..049f7f0
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * collectd - src/libcollectdclient/collectd/network.h
+ * Copyright (C) 2005-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef LIBCOLLECTDCLIENT_NETWORK_H
+#define LIBCOLLECTDCLIENT_NETWORK_H 1
+
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "client.h"
+
+#define NET_DEFAULT_V4_ADDR "239.192.74.66"
+#define NET_DEFAULT_V6_ADDR "ff18::efc0:4a42"
+#define NET_DEFAULT_PORT    "25826"
+
+struct lcc_network_s;
+typedef struct lcc_network_s lcc_network_t;
+
+struct lcc_server_s;
+typedef struct lcc_server_s lcc_server_t;
+
+enum lcc_security_level_e
+{
+  NONE,
+  SIGN,
+  ENCRYPT
+};
+typedef enum lcc_security_level_e lcc_security_level_t;
+
+/*
+ * Create / destroy object
+ */
+lcc_network_t *lcc_network_create (void);
+void lcc_network_destroy (lcc_network_t *net);
+
+/* 
+ * Add servers
+ */
+lcc_server_t *lcc_server_create (lcc_network_t *net,
+    const char *node, const char *service);
+int lcc_server_destroy (lcc_network_t *net, lcc_server_t *srv);
+
+/* Configure servers */
+int lcc_server_set_ttl (lcc_server_t *srv, uint8_t ttl);
+int lcc_server_set_interface (lcc_server_t *srv, char const *interface);
+int lcc_server_set_security_level (lcc_server_t *srv,
+    lcc_security_level_t level,
+    const char *username, const char *password);
+
+/*
+ * Send data
+ */
+int lcc_network_values_send (lcc_network_t *net,
+    const lcc_value_list_t *vl);
+#if 0
+int lcc_network_notification_send (lcc_network_t *net,
+    const lcc_notification_t *notif);
+#endif
+
+/* vim: set sw=2 sts=2 et : */
+#endif /* LIBCOLLECTDCLIENT_NETWORK_H */
diff --git a/src/libcollectdclient/collectd/network_buffer.h b/src/libcollectdclient/collectd/network_buffer.h
new file mode 100644 (file)
index 0000000..edf49ff
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * collectd - src/libcollectdclient/collectd/network_buffer.h
+ * Copyright (C) 2010-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef LIBCOLLECTDCLIENT_NETWORK_BUFFER_H
+#define LIBCOLLECTDCLIENT_NETWORK_BUFFER_H 1
+
+/* FIXME */
+#include "client.h"
+#include "network.h"
+
+/* Ethernet frame - (IPv6 header + UDP header) */
+#define LCC_NETWORK_BUFFER_SIZE_DEFAULT 1452
+
+struct lcc_network_buffer_s;
+typedef struct lcc_network_buffer_s lcc_network_buffer_t;
+
+lcc_network_buffer_t *lcc_network_buffer_create (size_t size);
+void lcc_network_buffer_destroy (lcc_network_buffer_t *nb);
+
+int lcc_network_buffer_set_security_level (lcc_network_buffer_t *nb,
+    lcc_security_level_t level,
+    const char *user, const char *password);
+
+int lcc_network_buffer_initialize (lcc_network_buffer_t *nb);
+int lcc_network_buffer_finalize (lcc_network_buffer_t *nb);
+
+int lcc_network_buffer_add_value (lcc_network_buffer_t *nb,
+    const lcc_value_list_t *vl);
+
+int lcc_network_buffer_get (lcc_network_buffer_t *nb,
+    void *buffer, size_t *buffer_size);
+
+#endif /* LIBCOLLECTDCLIENT_NETWORK_BUFFER_H */
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/libcollectdclient/libcollectdclient.pc.in b/src/libcollectdclient/libcollectdclient.pc.in
new file mode 100644 (file)
index 0000000..faade70
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libcollectdclient
+Description: Client library for the unixsock plugin of collectd.
+Version: @LCC_VERSION_STRING@
+URL: http://collectd.org/
+Libs: -L${libdir} -lcollectdclient
+Cflags: -I${includedir}
diff --git a/src/libcollectdclient/network.c b/src/libcollectdclient/network.c
new file mode 100644 (file)
index 0000000..c390a1c
--- /dev/null
@@ -0,0 +1,491 @@
+/**
+ * collectd - src/libcollectdclient/network.c
+ * Copyright (C) 2005-2015  Florian Forster
+ * Copyright (C) 2010       Max Henkel
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ *   Max Henkel <henkel at gmx.at>
+ **/
+
+#include "collectd.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+#include "collectd/network.h"
+#include "collectd/network_buffer.h"
+
+/*
+ * Private data types
+ */
+struct lcc_network_s
+{
+  lcc_server_t *servers;
+};
+
+struct lcc_server_s
+{
+  char *node;
+  char *service;
+
+  int ttl;
+  lcc_security_level_t security_level;
+  char *username;
+  char *password;
+
+  int fd;
+  struct sockaddr *sa;
+  socklen_t sa_len;
+
+  lcc_network_buffer_t *buffer;
+
+  lcc_server_t *next;
+};
+
+/*
+ * Private functions
+ */
+static int server_close_socket (lcc_server_t *srv) /* {{{ */
+{
+  if (srv == NULL)
+    return (EINVAL);
+
+  if (srv->fd < 0)
+    return (0);
+
+  close (srv->fd);
+  free (srv->sa);
+  srv->sa = NULL;
+  srv->sa_len = 0;
+
+  return (0);
+} /* }}} int server_close_socket */
+
+static void int_server_destroy (lcc_server_t *srv) /* {{{ */
+{
+  lcc_server_t *next;
+
+  if (srv == NULL)
+    return;
+
+  server_close_socket (srv);
+
+  next = srv->next;
+
+  if (srv->fd >= 0)
+  {
+    close (srv->fd);
+    srv->fd = -1;
+  }
+
+  free (srv->node);
+  free (srv->service);
+  free (srv->username);
+  free (srv->password);
+  free (srv);
+
+  int_server_destroy (next);
+} /* }}} void int_server_destroy */
+
+static int server_open_socket (lcc_server_t *srv) /* {{{ */
+{
+  struct addrinfo ai_hints = { 0 };
+  struct addrinfo *ai_list = NULL;
+  struct addrinfo *ai_ptr;
+  int status;
+
+  if (srv == NULL)
+    return (EINVAL);
+
+  if (srv->fd >= 0)
+    server_close_socket (srv);
+
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family   = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_DGRAM;
+
+  status = getaddrinfo (srv->node, srv->service, &ai_hints, &ai_list);
+  if (status != 0)
+    return (status);
+  assert (ai_list != NULL);
+
+  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    srv->fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+    if (srv->fd < 0)
+      continue;
+
+    if (ai_ptr->ai_family == AF_INET)
+    {
+
+      struct sockaddr_in *addr = (struct sockaddr_in *) ai_ptr->ai_addr;
+      int optname;
+
+      if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+        optname = IP_MULTICAST_TTL;
+      else
+        optname = IP_TTL;
+
+      setsockopt (srv->fd, IPPROTO_IP, optname,
+          &srv->ttl,
+          sizeof (srv->ttl));
+    }
+    else if (ai_ptr->ai_family == AF_INET6)
+    {
+      /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
+      struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai_ptr->ai_addr;
+      int optname;
+
+      if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+        optname = IPV6_MULTICAST_HOPS;
+      else
+        optname = IPV6_UNICAST_HOPS;
+
+      setsockopt (srv->fd, IPPROTO_IPV6, optname,
+          &srv->ttl,
+          sizeof (srv->ttl));
+    }
+
+    srv->sa = malloc (ai_ptr->ai_addrlen);
+    if (srv->sa == NULL)
+    {
+      close (srv->fd);
+      srv->fd = -1;
+      continue;
+    }
+
+    memcpy (srv->sa, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    srv->sa_len = ai_ptr->ai_addrlen;
+    break;
+  }
+
+  freeaddrinfo (ai_list);
+
+  if (srv->fd < 0)
+    return (-1);
+  return (0);
+} /* }}} int server_open_socket */
+
+static int server_send_buffer (lcc_server_t *srv) /* {{{ */
+{
+  char buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
+  size_t buffer_size;
+  int status;
+
+  if (srv->fd < 0)
+  {
+    status = server_open_socket (srv);
+    if (status != 0)
+      return (status);
+  }
+
+  memset (buffer, 0, sizeof (buffer));
+  buffer_size = sizeof (buffer);
+
+  status = lcc_network_buffer_finalize (srv->buffer);
+  if (status != 0)
+  {
+    lcc_network_buffer_initialize (srv->buffer);
+    return (status);
+  }
+
+  status = lcc_network_buffer_get (srv->buffer, buffer, &buffer_size);
+  lcc_network_buffer_initialize (srv->buffer);
+
+  if (status != 0)
+    return (status);
+
+  if (buffer_size > sizeof (buffer))
+    buffer_size = sizeof (buffer);
+
+  while (42)
+  {
+    assert (srv->fd >= 0);
+    assert (srv->sa != NULL);
+    status = (int) sendto (srv->fd, buffer, buffer_size, /* flags = */ 0,
+        srv->sa, srv->sa_len);
+    if ((status < 0) && ((errno == EINTR) || (errno == EAGAIN)))
+      continue;
+
+    break;
+  }
+
+  if (status < 0)
+    return (status);
+  return (0);
+} /* }}} int server_send_buffer */
+
+static int server_value_add (lcc_server_t *srv, /* {{{ */
+    const lcc_value_list_t *vl)
+{
+  int status;
+
+  status = lcc_network_buffer_add_value (srv->buffer, vl);
+  if (status == 0)
+    return (0);
+
+  server_send_buffer (srv);
+  return (lcc_network_buffer_add_value (srv->buffer, vl));
+} /* }}} int server_value_add */
+
+/*
+ * Public functions
+ */
+lcc_network_t *lcc_network_create (void) /* {{{ */
+{
+  lcc_network_t *net;
+
+  net = malloc (sizeof (*net));
+  if (net == NULL)
+    return (NULL);
+  memset (net, 0, sizeof (*net));
+
+  net->servers = NULL;
+
+  return (net);
+} /* }}} lcc_network_t *lcc_network_create */
+
+void lcc_network_destroy (lcc_network_t *net) /* {{{ */
+{
+  if (net == NULL)
+    return;
+  int_server_destroy (net->servers);
+  free (net);
+} /* }}} void lcc_network_destroy */
+
+lcc_server_t *lcc_server_create (lcc_network_t *net, /* {{{ */
+    const char *node, const char *service)
+{
+  lcc_server_t *srv;
+
+  if ((net == NULL) || (node == NULL))
+    return (NULL);
+  if (service == NULL)
+    service = NET_DEFAULT_PORT;
+
+  srv = malloc (sizeof (*srv));
+  if (srv == NULL)
+    return (NULL);
+  memset (srv, 0, sizeof (*srv));
+
+  srv->fd = -1;
+  srv->security_level = NONE;
+  srv->username = NULL;
+  srv->password = NULL;
+  srv->next = NULL;
+
+  srv->node = strdup (node);
+  if (srv->node == NULL)
+  {
+    free (srv);
+    return (NULL);
+  }
+
+  srv->service = strdup (service);
+  if (srv->service == NULL)
+  {
+    free (srv->node);
+    free (srv);
+    return (NULL);
+  }
+
+  srv->buffer = lcc_network_buffer_create (/* size = */ 0);
+  if (srv->buffer == NULL)
+  {
+    free (srv->service);
+    free (srv->node);
+    free (srv);
+    return (NULL);
+  }
+
+  if (net->servers == NULL)
+  {
+    net->servers = srv;
+  }
+  else
+  {
+    lcc_server_t *last = net->servers;
+
+    while (last->next != NULL)
+      last = last->next;
+
+    last->next = srv;
+  }
+
+  return (srv);
+} /* }}} lcc_server_t *lcc_server_create */
+
+int lcc_server_destroy (lcc_network_t *net, lcc_server_t *srv) /* {{{ */
+{
+  if ((net == NULL) || (srv == NULL))
+    return (EINVAL);
+
+  if (net->servers == srv)
+  {
+    net->servers = srv->next;
+    srv->next = NULL;
+  }
+  else
+  {
+    lcc_server_t *prev = net->servers;
+
+    while ((prev != NULL) && (prev->next != srv))
+      prev = prev->next;
+
+    if (prev == NULL)
+      return (ENOENT);
+
+    prev->next = srv->next;
+    srv->next = NULL;
+  }
+
+  int_server_destroy (srv);
+
+  return (0);
+} /* }}} int lcc_server_destroy */
+
+int lcc_server_set_ttl (lcc_server_t *srv, uint8_t ttl) /* {{{ */
+{
+  if (srv == NULL)
+    return (EINVAL);
+
+  srv->ttl = (int) ttl;
+
+  return (0);
+} /* }}} int lcc_server_set_ttl */
+
+int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
+{
+  int if_index;
+  int status;
+
+  if ((srv == NULL) || (interface == NULL))
+    return (EINVAL);
+
+  if_index = if_nametoindex (interface);
+  if (if_index == 0)
+    return (ENOENT);
+
+  /* IPv4 multicast */
+  if (srv->sa->sa_family == AF_INET)
+  {
+    struct sockaddr_in *addr = (struct sockaddr_in *) srv->sa;
+
+    if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+    {
+#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+      /* If possible, use the "ip_mreqn" structure which has
+       * an "interface index" member. Using the interface
+       * index is preferred here, because of its similarity
+       * to the way IPv6 handles this. Unfortunately, it
+       * appears not to be portable. */
+      struct ip_mreqn mreq;
+
+      memset (&mreq, 0, sizeof (mreq));
+      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+      mreq.imr_address.s_addr = ntohl (INADDR_ANY);
+      mreq.imr_ifindex = if_index;
+#else
+      struct ip_mreq mreq;
+
+      memset (&mreq, 0, sizeof (mreq));
+      mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+      mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+#endif
+
+      status = setsockopt (srv->fd, IPPROTO_IP, IP_MULTICAST_IF,
+          &mreq, sizeof (mreq));
+      if (status != 0)
+        return (status);
+
+      return (0);
+    }
+  }
+
+  /* IPv6 multicast */
+  if (srv->sa->sa_family == AF_INET6)
+  {
+    struct sockaddr_in6 *addr = (struct sockaddr_in6 *) srv->sa;
+
+    if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+    {
+      status = setsockopt (srv->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+          &if_index, sizeof (if_index));
+      if (status != 0)
+        return (status);
+
+      return (0);
+    }
+  }
+
+  /* else: Not a multicast interface. */
+#if defined(SO_BINDTODEVICE)
+  status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE,
+      interface, strlen (interface) + 1);
+  if (status != 0)
+    return (-1);
+#endif
+
+  return (0);
+} /* }}} int lcc_server_set_interface */
+
+int lcc_server_set_security_level (lcc_server_t *srv, /* {{{ */
+    lcc_security_level_t level,
+    const char *username, const char *password)
+{
+  return (lcc_network_buffer_set_security_level (srv->buffer,
+        level, username, password));
+} /* }}} int lcc_server_set_security_level */
+
+int lcc_network_values_send (lcc_network_t *net, /* {{{ */
+    const lcc_value_list_t *vl)
+{
+  lcc_server_t *srv;
+
+  if ((net == NULL) || (vl == NULL))
+    return (EINVAL);
+
+  for (srv = net->servers; srv != NULL; srv = srv->next)
+    server_value_add (srv, vl);
+
+  return (0);
+} /* }}} int lcc_network_values_send */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/libcollectdclient/network_buffer.c b/src/libcollectdclient/network_buffer.c
new file mode 100644 (file)
index 0000000..343c285
--- /dev/null
@@ -0,0 +1,836 @@
+/**
+ * collectd - src/libcollectdclient/network_buffer.c
+ * Copyright (C) 2010-2015  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <errno.h>
+#include <arpa/inet.h> /* htons */
+
+#include <pthread.h>
+
+#if HAVE_LIBGCRYPT
+# include <pthread.h>
+# if defined __APPLE__
+/* default xcode compiler throws warnings even when deprecated functionality
+ * is not used. -Werror breaks the build because of erroneous warnings.
+ * http://stackoverflow.com/questions/10556299/compiler-warnings-with-libgcrypt-v1-5-0/12830209#12830209
+ */
+#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+# endif
+/* FreeBSD's copy of libgcrypt extends the existing GCRYPT_NO_DEPRECATED
+ * to properly hide all deprecated functionality.
+ * http://svnweb.freebsd.org/ports/head/security/libgcrypt/files/patch-src__gcrypt.h.in
+ */
+# define GCRYPT_NO_DEPRECATED
+# include <gcrypt.h>
+# if defined __APPLE__
+/* Re enable deprecation warnings */
+#  pragma GCC diagnostic warning "-Wdeprecated-declarations"
+# endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
+#endif
+
+#include "collectd/network_buffer.h"
+
+#define TYPE_HOST            0x0000
+#define TYPE_TIME            0x0001
+#define TYPE_TIME_HR         0x0008
+#define TYPE_PLUGIN          0x0002
+#define TYPE_PLUGIN_INSTANCE 0x0003
+#define TYPE_TYPE            0x0004
+#define TYPE_TYPE_INSTANCE   0x0005
+#define TYPE_VALUES          0x0006
+#define TYPE_INTERVAL        0x0007
+#define TYPE_INTERVAL_HR     0x0009
+
+/* Types to transmit notifications */
+#define TYPE_MESSAGE         0x0100
+#define TYPE_SEVERITY        0x0101
+
+#define TYPE_SIGN_SHA256     0x0200
+#define TYPE_ENCR_AES256     0x0210
+
+#define PART_SIGNATURE_SHA256_SIZE 36
+#define PART_ENCRYPTION_AES256_SIZE 42
+
+#define ADD_GENERIC(nb,srcptr,size) do {         \
+  assert ((size) <= (nb)->free);                 \
+  memcpy ((nb)->ptr, (srcptr), (size));          \
+  (nb)->ptr += (size);                           \
+  (nb)->free -= (size);                          \
+} while (0)
+
+#define ADD_STATIC(nb,var) \
+  ADD_GENERIC(nb,&(var),sizeof(var));
+
+/*
+ * Data types
+ */
+struct lcc_network_buffer_s
+{
+  char *buffer;
+  size_t size;
+
+  lcc_value_list_t state;
+  char *ptr;
+  size_t free;
+
+  lcc_security_level_t seclevel;
+  char *username;
+  char *password;
+
+#if HAVE_LIBGCRYPT
+  gcry_cipher_hd_t encr_cypher;
+  size_t encr_header_len;
+  char encr_iv[16];
+#endif
+};
+
+#define SSTRNCPY(dst,src,sz) do { \
+  strncpy ((dst), (src), (sz));   \
+  (dst)[(sz) - 1] = 0;            \
+} while (0)
+
+/*
+ * Private functions
+ */
+static _Bool have_gcrypt (void) /* {{{ */
+{
+  static _Bool result = 0;
+  static _Bool need_init = 1;
+
+  if (!need_init)
+    return (result);
+  need_init = 0;
+
+#if HAVE_LIBGCRYPT
+# if GCRYPT_VERSION_NUMBER < 0x010600
+  gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
+
+  if (!gcry_check_version (GCRYPT_VERSION))
+    return (0);
+
+  gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+  result = 1;
+  return (1);
+#else
+  return(0);
+#endif
+} /* }}} _Bool have_gcrypt */
+
+#ifndef HAVE_HTONLL
+static uint64_t htonll (uint64_t val) /* {{{ */
+{
+  static int config = 0;
+
+  uint32_t hi;
+  uint32_t lo;
+
+  if (config == 0)
+  {
+    uint16_t h = 0x1234;
+    uint16_t n = htons (h);
+
+    if (h == n)
+      config = 1;
+    else
+      config = 2;
+  }
+
+  if (config == 1)
+    return (val);
+
+  hi = (uint32_t) (val >> 32);
+  lo = (uint32_t) (val & 0x00000000FFFFFFFF);
+
+  hi = htonl (hi);
+  lo = htonl (lo);
+
+  return ((((uint64_t) lo) << 32) | ((uint64_t) hi));
+} /* }}} uint64_t htonll */
+#endif
+
+static double htond (double val) /* {{{ */
+{
+  static int config = 0;
+
+  union { uint8_t byte[8]; double floating; } in;
+  union { uint8_t byte[8]; double floating; } out;
+
+  if (config == 0)
+  {
+    double d = 8.642135e130;
+    uint8_t c[8];
+
+    memcpy (c, &d, 8);
+
+    if ((c[0] == 0x2f) && (c[1] == 0x25)
+        && (c[2] == 0xc0) && (c[3] == 0xc7)
+        && (c[4] == 0x43) && (c[5] == 0x2b)
+        && (c[6] == 0x1f) && (c[7] == 0x5b))
+      config = 1; /* need nothing */
+    else if ((c[7] == 0x2f) && (c[6] == 0x25)
+        && (c[5] == 0xc0) && (c[4] == 0xc7)
+        && (c[3] == 0x43) && (c[2] == 0x2b)
+        && (c[1] == 0x1f) && (c[0] == 0x5b))
+      config = 2; /* endian flip */
+    else if ((c[4] == 0x2f) && (c[5] == 0x25)
+        && (c[6] == 0xc0) && (c[7] == 0xc7)
+        && (c[0] == 0x43) && (c[1] == 0x2b)
+        && (c[2] == 0x1f) && (c[3] == 0x5b))
+      config = 3; /* int swap */
+    else
+      config = 4;
+  }
+
+  if (isnan (val))
+  {
+    out.byte[0] = out.byte[1] = out.byte[2] = out.byte[3] = 0x00;
+    out.byte[4] = out.byte[5] = 0x00;
+    out.byte[6] = 0xf8;
+    out.byte[7] = 0x7f;
+    return (out.floating);
+  }
+  else if (config == 1)
+    return (val);
+  else if (config == 2)
+  {
+    in.floating = val;
+    out.byte[0] = in.byte[7];
+    out.byte[1] = in.byte[6];
+    out.byte[2] = in.byte[5];
+    out.byte[3] = in.byte[4];
+    out.byte[4] = in.byte[3];
+    out.byte[5] = in.byte[2];
+    out.byte[6] = in.byte[1];
+    out.byte[7] = in.byte[0];
+    return (out.floating);
+  }
+  else if (config == 3)
+  {
+    in.floating = val;
+    out.byte[0] = in.byte[4];
+    out.byte[1] = in.byte[5];
+    out.byte[2] = in.byte[6];
+    out.byte[3] = in.byte[7];
+    out.byte[4] = in.byte[0];
+    out.byte[5] = in.byte[1];
+    out.byte[6] = in.byte[2];
+    out.byte[7] = in.byte[3];
+    return (out.floating);
+  }
+  else
+  {
+    /* If in doubt, just copy the value back to the caller. */
+    return (val);
+  }
+} /* }}} double htond */
+
+static int nb_add_values (char **ret_buffer, /* {{{ */
+    size_t *ret_buffer_len,
+    const lcc_value_list_t *vl)
+{
+  char *packet_ptr;
+  size_t packet_len;
+
+  uint16_t      pkg_type;
+  uint16_t      pkg_length;
+  uint16_t      pkg_num_values;
+  uint8_t       pkg_values_types[vl->values_len];
+  value_t       pkg_values[vl->values_len];
+
+  size_t offset;
+  size_t i;
+
+  packet_len = sizeof (pkg_type) + sizeof (pkg_length)
+    + sizeof (pkg_num_values)
+    + sizeof (pkg_values_types)
+    + sizeof (pkg_values);
+
+  if (*ret_buffer_len < packet_len)
+    return (ENOMEM);
+
+  pkg_type = htons (TYPE_VALUES);
+  pkg_length = htons ((uint16_t) packet_len);
+  pkg_num_values = htons ((uint16_t) vl->values_len);
+
+  for (i = 0; i < vl->values_len; i++)
+  {
+    pkg_values_types[i] = (uint8_t) vl->values_types[i];
+    switch (vl->values_types[i])
+    {
+      case LCC_TYPE_COUNTER:
+        pkg_values[i].counter = (counter_t) htonll (vl->values[i].counter);
+        break;
+
+      case LCC_TYPE_GAUGE:
+        pkg_values[i].gauge = (gauge_t) htond (vl->values[i].gauge);
+        break;
+
+      case LCC_TYPE_DERIVE:
+        pkg_values[i].derive = (derive_t) htonll (vl->values[i].derive);
+        break;
+
+      case LCC_TYPE_ABSOLUTE:
+        pkg_values[i].absolute = (absolute_t) htonll (vl->values[i].absolute);
+        break;
+
+      default:
+        return (EINVAL);
+    } /* switch (vl->values_types[i]) */
+  } /* for (vl->values_len) */
+
+  /*
+   * Use `memcpy' to write everything to the buffer, because the pointer
+   * may be unaligned and some architectures, such as SPARC, can't handle
+   * that.
+   */
+  packet_ptr = *ret_buffer;
+  offset = 0;
+  memcpy (packet_ptr + offset, &pkg_type, sizeof (pkg_type));
+  offset += sizeof (pkg_type);
+  memcpy (packet_ptr + offset, &pkg_length, sizeof (pkg_length));
+  offset += sizeof (pkg_length);
+  memcpy (packet_ptr + offset, &pkg_num_values, sizeof (pkg_num_values));
+  offset += sizeof (pkg_num_values);
+  memcpy (packet_ptr + offset, pkg_values_types, sizeof (pkg_values_types));
+  offset += sizeof (pkg_values_types);
+  memcpy (packet_ptr + offset, pkg_values, sizeof (pkg_values));
+  offset += sizeof (pkg_values);
+
+  assert (offset == packet_len);
+
+  *ret_buffer = packet_ptr + packet_len;
+  *ret_buffer_len -= packet_len;
+  return (0);
+} /* }}} int nb_add_values */
+
+static int nb_add_number (char **ret_buffer, /* {{{ */
+    size_t *ret_buffer_len,
+    uint16_t type, uint64_t value)
+{
+  char *packet_ptr;
+  size_t packet_len;
+
+  uint16_t pkg_type;
+  uint16_t pkg_length;
+  uint64_t pkg_value;
+
+  size_t offset;
+
+  packet_len = sizeof (pkg_type)
+    + sizeof (pkg_length)
+    + sizeof (pkg_value);
+
+  if (*ret_buffer_len < packet_len)
+    return (ENOMEM);
+
+  pkg_type = htons (type);
+  pkg_length = htons ((uint16_t) packet_len);
+  pkg_value = htonll (value);
+
+  packet_ptr = *ret_buffer;
+  offset = 0;
+  memcpy (packet_ptr + offset, &pkg_type, sizeof (pkg_type));
+  offset += sizeof (pkg_type);
+  memcpy (packet_ptr + offset, &pkg_length, sizeof (pkg_length));
+  offset += sizeof (pkg_length);
+  memcpy (packet_ptr + offset, &pkg_value, sizeof (pkg_value));
+  offset += sizeof (pkg_value);
+
+  assert (offset == packet_len);
+
+  *ret_buffer = packet_ptr + packet_len;
+  *ret_buffer_len -= packet_len;
+  return (0);
+} /* }}} int nb_add_number */
+
+static int nb_add_time (char **ret_buffer, /* {{{ */
+    size_t *ret_buffer_len,
+    uint16_t type, double value)
+{
+  /* Convert to collectd's "cdtime" representation. */
+  uint64_t cdtime_value = (uint64_t) (value * 1073741824.0);
+  return (nb_add_number (ret_buffer, ret_buffer_len, type, cdtime_value));
+} /* }}} int nb_add_time */
+
+static int nb_add_string (char **ret_buffer, /* {{{ */
+    size_t *ret_buffer_len,
+    uint16_t type, const char *str, size_t str_len)
+{
+  char *packet_ptr;
+  size_t packet_len;
+
+  uint16_t pkg_type;
+  uint16_t pkg_length;
+
+  size_t offset;
+
+  packet_len = sizeof (pkg_type)
+    + sizeof (pkg_length)
+    + str_len + 1;
+  if (*ret_buffer_len < packet_len)
+    return (ENOMEM);
+
+  pkg_type = htons (type);
+  pkg_length = htons ((uint16_t) packet_len);
+
+  packet_ptr = *ret_buffer;
+  offset = 0;
+  memcpy (packet_ptr + offset, &pkg_type, sizeof (pkg_type));
+  offset += sizeof (pkg_type);
+  memcpy (packet_ptr + offset, &pkg_length, sizeof (pkg_length));
+  offset += sizeof (pkg_length);
+  memcpy (packet_ptr + offset, str, str_len);
+  offset += str_len;
+  memset (packet_ptr + offset, 0, 1);
+  offset += 1;
+
+  assert (offset == packet_len);
+
+  *ret_buffer = packet_ptr + packet_len;
+  *ret_buffer_len -= packet_len;
+  return (0);
+} /* }}} int nb_add_string */
+
+static int nb_add_value_list (lcc_network_buffer_t *nb, /* {{{ */
+    const lcc_value_list_t *vl)
+{
+  char *buffer = nb->ptr;
+  size_t buffer_size = nb->free;
+
+  const lcc_identifier_t *ident_src;
+  lcc_identifier_t *ident_dst;
+
+  ident_src = &vl->identifier;
+  ident_dst = &nb->state.identifier;
+
+  if (strcmp (ident_dst->host, ident_src->host) != 0)
+  {
+    if (nb_add_string (&buffer, &buffer_size, TYPE_HOST,
+          ident_src->host, strlen (ident_src->host)) != 0)
+      return (-1);
+    SSTRNCPY (ident_dst->host, ident_src->host, sizeof (ident_dst->host));
+  }
+
+  if (strcmp (ident_dst->plugin, ident_src->plugin) != 0)
+  {
+    if (nb_add_string (&buffer, &buffer_size, TYPE_PLUGIN,
+          ident_src->plugin, strlen (ident_src->plugin)) != 0)
+      return (-1);
+    SSTRNCPY (ident_dst->plugin, ident_src->plugin,
+        sizeof (ident_dst->plugin));
+  }
+
+  if (strcmp (ident_dst->plugin_instance,
+        ident_src->plugin_instance) != 0)
+  {
+    if (nb_add_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+          ident_src->plugin_instance,
+          strlen (ident_src->plugin_instance)) != 0)
+      return (-1);
+    SSTRNCPY (ident_dst->plugin_instance, ident_src->plugin_instance,
+        sizeof (ident_dst->plugin_instance));
+  }
+
+  if (strcmp (ident_dst->type, ident_src->type) != 0)
+  {
+    if (nb_add_string (&buffer, &buffer_size, TYPE_TYPE,
+          ident_src->type, strlen (ident_src->type)) != 0)
+      return (-1);
+    SSTRNCPY (ident_dst->type, ident_src->type, sizeof (ident_dst->type));
+  }
+
+  if (strcmp (ident_dst->type_instance,
+        ident_src->type_instance) != 0)
+  {
+    if (nb_add_string (&buffer, &buffer_size, TYPE_TYPE_INSTANCE,
+          ident_src->type_instance,
+          strlen (ident_src->type_instance)) != 0)
+      return (-1);
+    SSTRNCPY (ident_dst->type_instance, ident_src->type_instance,
+        sizeof (ident_dst->type_instance));
+  }
+
+  if (nb->state.time != vl->time)
+  {
+    if (nb_add_time (&buffer, &buffer_size, TYPE_TIME_HR, vl->time))
+      return (-1);
+    nb->state.time = vl->time;
+  }
+
+  if (nb->state.interval != vl->interval)
+  {
+    if (nb_add_time (&buffer, &buffer_size, TYPE_INTERVAL_HR, vl->interval))
+      return (-1);
+    nb->state.interval = vl->interval;
+  }
+
+  if (nb_add_values (&buffer, &buffer_size, vl) != 0)
+    return (-1);
+
+  nb->ptr = buffer;
+  nb->free = buffer_size;
+  return (0);
+} /* }}} int nb_add_value_list */
+
+#if HAVE_LIBGCRYPT
+static int nb_add_signature (lcc_network_buffer_t *nb) /* {{{ */
+{
+  char *buffer;
+  size_t buffer_size;
+
+  gcry_md_hd_t hd;
+  gcry_error_t err;
+  unsigned char *hash;
+  const size_t hash_length = 32;
+
+  /* The type, length and username have already been filled in by
+   * "lcc_network_buffer_initialize". All we do here is calculate the hash over
+   * the username and the data and add the hash value to the buffer. */
+
+  buffer = nb->buffer + PART_SIGNATURE_SHA256_SIZE;
+  assert (nb->size >= (nb->free + PART_SIGNATURE_SHA256_SIZE));
+  buffer_size = nb->size - (nb->free + PART_SIGNATURE_SHA256_SIZE);
+
+  hd = NULL;
+  err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+  if (err != 0)
+    return (-1);
+
+  assert (nb->password != NULL);
+  err = gcry_md_setkey (hd, nb->password, strlen (nb->password));
+  if (err != 0)
+  {
+    gcry_md_close (hd);
+    return (-1);
+  }
+
+  gcry_md_write (hd, buffer, buffer_size);
+  hash = gcry_md_read (hd, GCRY_MD_SHA256);
+  if (hash == NULL)
+  {
+    gcry_md_close (hd);
+    return (-1);
+  }
+
+  assert (((2 * sizeof (uint16_t)) + hash_length) == PART_SIGNATURE_SHA256_SIZE);
+  memcpy (nb->buffer + (2 * sizeof (uint16_t)), hash, hash_length);
+
+  gcry_md_close (hd);
+  return (0);
+} /* }}} int nb_add_signature */
+
+static int nb_add_encryption (lcc_network_buffer_t *nb) /* {{{ */
+{
+  size_t package_length;
+  char *encr_ptr; /* pointer to data being encrypted */
+  size_t encr_size;
+
+  char *hash_ptr; /* pointer to data being hashed */
+  size_t hash_size;
+  char hash[20];
+
+  uint16_t pkg_length;
+  gcry_error_t err;
+
+  /* Fill in the package length */
+  package_length = nb->size - nb->free;
+  pkg_length = htons ((uint16_t) package_length);
+  memcpy (nb->buffer + 2, &pkg_length, sizeof (pkg_length));
+
+  /* Calculate what to hash */
+  hash_ptr = nb->buffer + PART_ENCRYPTION_AES256_SIZE;
+  hash_size = package_length - nb->encr_header_len;
+
+  /* Calculate what to encrypt */
+  encr_ptr = hash_ptr - sizeof (hash);
+  encr_size = hash_size + sizeof (hash);
+
+  /* Calculate the SHA-1 hash */
+  gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash_ptr, hash_size);
+  memcpy (encr_ptr, hash, sizeof (hash));
+
+  if (nb->encr_cypher == NULL)
+  {
+    unsigned char password_hash[32];
+
+    err = gcry_cipher_open (&nb->encr_cypher,
+        GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB, /* flags = */ 0);
+    if (err != 0)
+      return (-1);
+
+    /* Calculate our 256bit key used for AES */
+    gcry_md_hash_buffer (GCRY_MD_SHA256, password_hash,
+        nb->password, strlen (nb->password));
+
+    err = gcry_cipher_setkey (nb->encr_cypher,
+        password_hash, sizeof (password_hash));
+    if (err != 0)
+    {
+      gcry_cipher_close (nb->encr_cypher);
+      nb->encr_cypher = NULL;
+      return (-1);
+    }
+  }
+  else /* if (nb->encr_cypher != NULL) */
+  {
+    gcry_cipher_reset (nb->encr_cypher);
+  }
+
+  /* Set the initialization vector */
+  err = gcry_cipher_setiv (nb->encr_cypher,
+      nb->encr_iv, sizeof (nb->encr_iv));
+  if (err != 0)
+  {
+    gcry_cipher_close (nb->encr_cypher);
+    nb->encr_cypher = NULL;
+    return (-1);
+  }
+
+  /* Encrypt the buffer in-place */
+  err = gcry_cipher_encrypt (nb->encr_cypher,
+      encr_ptr, encr_size,
+      /* in = */ NULL, /* in len = */ 0);
+  if (err != 0)
+  {
+    gcry_cipher_close (nb->encr_cypher);
+    nb->encr_cypher = NULL;
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int nb_add_encryption */
+#endif
+
+/*
+ * Public functions
+ */
+lcc_network_buffer_t *lcc_network_buffer_create (size_t size) /* {{{ */
+{
+  lcc_network_buffer_t *nb;
+
+  if (size == 0)
+    size = LCC_NETWORK_BUFFER_SIZE_DEFAULT;
+
+  if (size < 128)
+  {
+    errno = EINVAL;
+    return (NULL);
+  }
+
+  nb = malloc (sizeof (*nb));
+  if (nb == NULL)
+    return (NULL);
+  memset (nb, 0, sizeof (*nb));
+
+  nb->size = size;
+  nb->buffer = malloc (nb->size);
+  if (nb->buffer == NULL)
+  {
+    free (nb);
+    return (NULL);
+  }
+  memset (nb->buffer, 0, nb->size);
+
+  nb->ptr = nb->buffer;
+  nb->free = nb->size;
+
+  nb->seclevel = NONE;
+  nb->username = NULL;
+  nb->password = NULL;
+
+  return (nb);
+} /* }}} lcc_network_buffer_t *lcc_network_buffer_create */
+
+void lcc_network_buffer_destroy (lcc_network_buffer_t *nb) /* {{{ */
+{
+  if (nb == NULL)
+    return;
+
+  free (nb->buffer);
+  free (nb);
+} /* }}} void lcc_network_buffer_destroy */
+
+int lcc_network_buffer_set_security_level (lcc_network_buffer_t *nb, /* {{{ */
+    lcc_security_level_t level,
+    const char *username, const char *password)
+{
+  char *username_copy;
+  char *password_copy;
+
+  if (level == NONE)
+  {
+    free (nb->username);
+    free (nb->password);
+    nb->username = NULL;
+    nb->password = NULL;
+    nb->seclevel = NONE;
+    lcc_network_buffer_initialize (nb);
+    return (0);
+  }
+
+  if (!have_gcrypt ())
+    return (ENOTSUP);
+
+  username_copy = strdup (username);
+  password_copy = strdup (password);
+  if ((username_copy == NULL) || (password_copy == NULL))
+  {
+    free (username_copy);
+    free (password_copy);
+    return (ENOMEM);
+  }
+
+  free (nb->username);
+  free (nb->password);
+  nb->username = username_copy;
+  nb->password = password_copy;
+  nb->seclevel = level;
+
+  lcc_network_buffer_initialize (nb);
+  return (0);
+} /* }}} int lcc_network_buffer_set_security_level */
+
+int lcc_network_buffer_initialize (lcc_network_buffer_t *nb) /* {{{ */
+{
+  if (nb == NULL)
+    return (EINVAL);
+
+  memset (nb->buffer, 0, nb->size);
+  memset (&nb->state, 0, sizeof (nb->state));
+  nb->ptr = nb->buffer;
+  nb->free = nb->size;
+
+#if HAVE_LIBGCRYPT
+  if (nb->seclevel == SIGN)
+  {
+    size_t username_len;
+    uint16_t pkg_type = htons (TYPE_SIGN_SHA256);
+    uint16_t pkg_length = PART_SIGNATURE_SHA256_SIZE;
+
+    assert (nb->username != NULL);
+    username_len = strlen (nb->username);
+    pkg_length = htons (pkg_length + ((uint16_t) username_len));
+
+    /* Fill in everything but the hash value here. */
+    memcpy (nb->ptr, &pkg_type, sizeof (pkg_type));
+    memcpy (nb->ptr + sizeof (pkg_type), &pkg_length, sizeof (pkg_length));
+    nb->ptr += PART_SIGNATURE_SHA256_SIZE;
+    nb->free -= PART_SIGNATURE_SHA256_SIZE;
+
+    memcpy (nb->ptr, nb->username, username_len);
+    nb->ptr += username_len;
+    nb->free -= username_len;
+  }
+  else if (nb->seclevel == ENCRYPT)
+  {
+    size_t username_length = strlen (nb->username);
+    uint16_t pkg_type = htons (TYPE_ENCR_AES256);
+    uint16_t pkg_length = 0; /* Filled in in finalize. */
+    uint16_t pkg_user_len = htons ((uint16_t) username_length);
+    char hash[20];
+
+    nb->encr_header_len = username_length;
+    nb->encr_header_len += PART_ENCRYPTION_AES256_SIZE;
+
+    gcry_randomize ((void *) &nb->encr_iv, sizeof (nb->encr_iv),
+        GCRY_STRONG_RANDOM);
+
+    /* Filled in in finalize. */
+    memset (hash, 0, sizeof (hash));
+
+    ADD_STATIC (nb, pkg_type);
+    ADD_STATIC (nb, pkg_length);
+    ADD_STATIC (nb, pkg_user_len);
+    ADD_GENERIC (nb, nb->username, username_length);
+    ADD_GENERIC (nb, nb->encr_iv, sizeof (nb->encr_iv));
+    ADD_GENERIC (nb, hash, sizeof (hash));
+    assert ((nb->encr_header_len + nb->free) == nb->size);
+  }
+#endif
+
+  return (0);
+} /* }}} int lcc_network_buffer_initialize */
+
+int lcc_network_buffer_finalize (lcc_network_buffer_t *nb) /* {{{ */
+{
+  if (nb == NULL)
+    return (EINVAL);
+
+#if HAVE_LIBGCRYPT
+  if (nb->seclevel == SIGN)
+    return nb_add_signature (nb);
+  else if (nb->seclevel == ENCRYPT)
+    return nb_add_encryption (nb);
+#endif
+
+  return (0);
+} /* }}} int lcc_network_buffer_finalize */
+
+int lcc_network_buffer_add_value (lcc_network_buffer_t *nb, /* {{{ */
+    const lcc_value_list_t *vl)
+{
+  int status;
+
+  if ((nb == NULL) || (vl == NULL))
+    return (EINVAL);
+
+  status = nb_add_value_list (nb, vl);
+  return (status);
+} /* }}} int lcc_network_buffer_add_value */
+
+int lcc_network_buffer_get (lcc_network_buffer_t *nb, /* {{{ */
+    void *buffer, size_t *buffer_size)
+{
+  size_t sz_required;
+  size_t sz_available;
+
+  if ((nb == NULL) || (buffer_size == NULL))
+    return (EINVAL);
+
+  assert (nb->size >= nb->free);
+  sz_required = nb->size - nb->free;
+  sz_available = *buffer_size;
+
+  *buffer_size = sz_required;
+  if (buffer != NULL)
+    memcpy (buffer, nb->buffer,
+        (sz_available < sz_required) ? sz_available : sz_required);
+
+  return (0);
+} /* }}} int lcc_network_buffer_get */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/liboconfig/AUTHORS b/src/liboconfig/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/liboconfig/COPYING b/src/liboconfig/COPYING
new file mode 100644 (file)
index 0000000..623b625
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/src/liboconfig/ChangeLog b/src/liboconfig/ChangeLog
new file mode 100644 (file)
index 0000000..390c507
--- /dev/null
@@ -0,0 +1,5 @@
+2007-02-15, Version 0.1.1
+       * src/parser.y: Fixes a memory leak.
+
+2007-02-11, Version 0.1.0
+       * Initial release.
diff --git a/src/liboconfig/Makefile.am b/src/liboconfig/Makefile.am
new file mode 100644 (file)
index 0000000..c3de92c
--- /dev/null
@@ -0,0 +1,10 @@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+BUILT_SOURCES = parser.h
+#CLEANFILES = parser.[ch] scanner.c
+AM_YFLAGS = -d
+
+noinst_LTLIBRARIES = liboconfig.la
+
+liboconfig_la_LDFLAGS = -version-info 0:0:0 $(LEXLIB)
+liboconfig_la_SOURCES = oconfig.c oconfig.h aux_types.h scanner.l parser.y
diff --git a/src/liboconfig/Makefile.in b/src/liboconfig/Makefile.in
new file mode 100644 (file)
index 0000000..69a912f
--- /dev/null
@@ -0,0 +1,748 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/liboconfig
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am scanner.c \
+       parser.h parser.c $(top_srcdir)/libltdl/config/ylwrap AUTHORS \
+       COPYING ChangeLog
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+liboconfig_la_LIBADD =
+am_liboconfig_la_OBJECTS = oconfig.lo scanner.lo parser.lo
+liboconfig_la_OBJECTS = $(am_liboconfig_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 = 
+liboconfig_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(liboconfig_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
+AM_V_LEX = $(am__v_LEX_@AM_V@)
+am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
+am__v_LEX_0 = @echo "  LEX     " $@;
+am__v_LEX_1 = 
+YLWRAP = $(top_srcdir)/libltdl/config/ylwrap
+am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
+                  -e s/c++$$/h++/ -e s/c$$/h/
+YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+       $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
+AM_V_YACC = $(am__v_YACC_@AM_V@)
+am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
+am__v_YACC_0 = @echo "  YACC    " $@;
+am__v_YACC_1 = 
+SOURCES = $(liboconfig_la_SOURCES)
+DIST_SOURCES = $(liboconfig_la_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ARGZ_H = @ARGZ_H@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_WITH_LIBAQUAERO5_CFLAGS = @BUILD_WITH_LIBAQUAERO5_CFLAGS@
+BUILD_WITH_LIBAQUAERO5_LDFLAGS = @BUILD_WITH_LIBAQUAERO5_LDFLAGS@
+BUILD_WITH_LIBATASMART_CPPFLAGS = @BUILD_WITH_LIBATASMART_CPPFLAGS@
+BUILD_WITH_LIBATASMART_LDFLAGS = @BUILD_WITH_LIBATASMART_LDFLAGS@
+BUILD_WITH_LIBATASMART_LIBS = @BUILD_WITH_LIBATASMART_LIBS@
+BUILD_WITH_LIBCURL_CFLAGS = @BUILD_WITH_LIBCURL_CFLAGS@
+BUILD_WITH_LIBCURL_LIBS = @BUILD_WITH_LIBCURL_LIBS@
+BUILD_WITH_LIBDBI_CPPFLAGS = @BUILD_WITH_LIBDBI_CPPFLAGS@
+BUILD_WITH_LIBDBI_LDFLAGS = @BUILD_WITH_LIBDBI_LDFLAGS@
+BUILD_WITH_LIBDBI_LIBS = @BUILD_WITH_LIBDBI_LIBS@
+BUILD_WITH_LIBHAL_CFLAGS = @BUILD_WITH_LIBHAL_CFLAGS@
+BUILD_WITH_LIBHAL_LIBS = @BUILD_WITH_LIBHAL_LIBS@
+BUILD_WITH_LIBHIREDIS_CPPFLAGS = @BUILD_WITH_LIBHIREDIS_CPPFLAGS@
+BUILD_WITH_LIBHIREDIS_LDFLAGS = @BUILD_WITH_LIBHIREDIS_LDFLAGS@
+BUILD_WITH_LIBIPTC_CPPFLAGS = @BUILD_WITH_LIBIPTC_CPPFLAGS@
+BUILD_WITH_LIBIPTC_LDFLAGS = @BUILD_WITH_LIBIPTC_LDFLAGS@
+BUILD_WITH_LIBLDAP_CPPFLAGS = @BUILD_WITH_LIBLDAP_CPPFLAGS@
+BUILD_WITH_LIBLDAP_LDFLAGS = @BUILD_WITH_LIBLDAP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_CPPFLAGS = @BUILD_WITH_LIBLVM2APP_CPPFLAGS@
+BUILD_WITH_LIBLVM2APP_LDFLAGS = @BUILD_WITH_LIBLVM2APP_LDFLAGS@
+BUILD_WITH_LIBLVM2APP_LIBS = @BUILD_WITH_LIBLVM2APP_LIBS@
+BUILD_WITH_LIBMEMCACHED_CPPFLAGS = @BUILD_WITH_LIBMEMCACHED_CPPFLAGS@
+BUILD_WITH_LIBMEMCACHED_LDFLAGS = @BUILD_WITH_LIBMEMCACHED_LDFLAGS@
+BUILD_WITH_LIBMEMCACHED_LIBS = @BUILD_WITH_LIBMEMCACHED_LIBS@
+BUILD_WITH_LIBMNL_CFLAGS = @BUILD_WITH_LIBMNL_CFLAGS@
+BUILD_WITH_LIBMNL_LIBS = @BUILD_WITH_LIBMNL_LIBS@
+BUILD_WITH_LIBMODBUS_CFLAGS = @BUILD_WITH_LIBMODBUS_CFLAGS@
+BUILD_WITH_LIBMODBUS_LIBS = @BUILD_WITH_LIBMODBUS_LIBS@
+BUILD_WITH_LIBMONGOC_CPPFLAGS = @BUILD_WITH_LIBMONGOC_CPPFLAGS@
+BUILD_WITH_LIBMONGOC_LDFLAGS = @BUILD_WITH_LIBMONGOC_LDFLAGS@
+BUILD_WITH_LIBMYSQL_CFLAGS = @BUILD_WITH_LIBMYSQL_CFLAGS@
+BUILD_WITH_LIBMYSQL_LIBS = @BUILD_WITH_LIBMYSQL_LIBS@
+BUILD_WITH_LIBOPING_CPPFLAGS = @BUILD_WITH_LIBOPING_CPPFLAGS@
+BUILD_WITH_LIBOPING_LDFLAGS = @BUILD_WITH_LIBOPING_LDFLAGS@
+BUILD_WITH_LIBOWCAPI_CPPFLAGS = @BUILD_WITH_LIBOWCAPI_CPPFLAGS@
+BUILD_WITH_LIBOWCAPI_LIBS = @BUILD_WITH_LIBOWCAPI_LIBS@
+BUILD_WITH_LIBPQ_CPPFLAGS = @BUILD_WITH_LIBPQ_CPPFLAGS@
+BUILD_WITH_LIBPQ_LDFLAGS = @BUILD_WITH_LIBPQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_CPPFLAGS = @BUILD_WITH_LIBRABBITMQ_CPPFLAGS@
+BUILD_WITH_LIBRABBITMQ_LDFLAGS = @BUILD_WITH_LIBRABBITMQ_LDFLAGS@
+BUILD_WITH_LIBRABBITMQ_LIBS = @BUILD_WITH_LIBRABBITMQ_LIBS@
+BUILD_WITH_LIBRDKAFKA_CPPFLAGS = @BUILD_WITH_LIBRDKAFKA_CPPFLAGS@
+BUILD_WITH_LIBRDKAFKA_LDFLAGS = @BUILD_WITH_LIBRDKAFKA_LDFLAGS@
+BUILD_WITH_LIBRDKAFKA_LIBS = @BUILD_WITH_LIBRDKAFKA_LIBS@
+BUILD_WITH_LIBROUTEROS_CPPFLAGS = @BUILD_WITH_LIBROUTEROS_CPPFLAGS@
+BUILD_WITH_LIBROUTEROS_LDFLAGS = @BUILD_WITH_LIBROUTEROS_LDFLAGS@
+BUILD_WITH_LIBRRD_CFLAGS = @BUILD_WITH_LIBRRD_CFLAGS@
+BUILD_WITH_LIBRRD_LDFLAGS = @BUILD_WITH_LIBRRD_LDFLAGS@
+BUILD_WITH_LIBSENSORS_CFLAGS = @BUILD_WITH_LIBSENSORS_CFLAGS@
+BUILD_WITH_LIBSENSORS_LDFLAGS = @BUILD_WITH_LIBSENSORS_LDFLAGS@
+BUILD_WITH_LIBSIGROK_CFLAGS = @BUILD_WITH_LIBSIGROK_CFLAGS@
+BUILD_WITH_LIBSIGROK_LDFLAGS = @BUILD_WITH_LIBSIGROK_LDFLAGS@
+BUILD_WITH_LIBSNMP_CFLAGS = @BUILD_WITH_LIBSNMP_CFLAGS@
+BUILD_WITH_LIBSNMP_LIBS = @BUILD_WITH_LIBSNMP_LIBS@
+BUILD_WITH_LIBSTATGRAB_CFLAGS = @BUILD_WITH_LIBSTATGRAB_CFLAGS@
+BUILD_WITH_LIBSTATGRAB_LDFLAGS = @BUILD_WITH_LIBSTATGRAB_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS = @BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS@
+BUILD_WITH_LIBTOKYOTYRANT_LIBS = @BUILD_WITH_LIBTOKYOTYRANT_LIBS@
+BUILD_WITH_LIBUDEV_CFLAGS = @BUILD_WITH_LIBUDEV_CFLAGS@
+BUILD_WITH_LIBUDEV_LDFLAGS = @BUILD_WITH_LIBUDEV_LDFLAGS@
+BUILD_WITH_LIBUPSCLIENT_CFLAGS = @BUILD_WITH_LIBUPSCLIENT_CFLAGS@
+BUILD_WITH_LIBUPSCLIENT_LIBS = @BUILD_WITH_LIBUPSCLIENT_LIBS@
+BUILD_WITH_LIBVARNISH_CFLAGS = @BUILD_WITH_LIBVARNISH_CFLAGS@
+BUILD_WITH_LIBVARNISH_LIBS = @BUILD_WITH_LIBVARNISH_LIBS@
+BUILD_WITH_LIBVIRT_CFLAGS = @BUILD_WITH_LIBVIRT_CFLAGS@
+BUILD_WITH_LIBVIRT_LIBS = @BUILD_WITH_LIBVIRT_LIBS@
+BUILD_WITH_LIBXML2_CFLAGS = @BUILD_WITH_LIBXML2_CFLAGS@
+BUILD_WITH_LIBXML2_LIBS = @BUILD_WITH_LIBXML2_LIBS@
+BUILD_WITH_LIBXMMS_CFLAGS = @BUILD_WITH_LIBXMMS_CFLAGS@
+BUILD_WITH_LIBXMMS_LIBS = @BUILD_WITH_LIBXMMS_LIBS@
+BUILD_WITH_LIBYAJL_CPPFLAGS = @BUILD_WITH_LIBYAJL_CPPFLAGS@
+BUILD_WITH_LIBYAJL_LDFLAGS = @BUILD_WITH_LIBYAJL_LDFLAGS@
+BUILD_WITH_LIBYAJL_LIBS = @BUILD_WITH_LIBYAJL_LIBS@
+BUILD_WITH_MIC_CPPFLAGS = @BUILD_WITH_MIC_CPPFLAGS@
+BUILD_WITH_MIC_LDADD = @BUILD_WITH_MIC_LDADD@
+BUILD_WITH_MIC_LIBPATH = @BUILD_WITH_MIC_LIBPATH@
+BUILD_WITH_OPENIPMI_CFLAGS = @BUILD_WITH_OPENIPMI_CFLAGS@
+BUILD_WITH_OPENIPMI_LIBS = @BUILD_WITH_OPENIPMI_LIBS@
+BUILD_WITH_ORACLE_CFLAGS = @BUILD_WITH_ORACLE_CFLAGS@
+BUILD_WITH_ORACLE_LIBS = @BUILD_WITH_ORACLE_LIBS@
+BUILD_WITH_PYTHON_CPPFLAGS = @BUILD_WITH_PYTHON_CPPFLAGS@
+BUILD_WITH_PYTHON_LDFLAGS = @BUILD_WITH_PYTHON_LDFLAGS@
+BUILD_WITH_PYTHON_LIBS = @BUILD_WITH_PYTHON_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFAULT_LOG_LEVEL = @DEFAULT_LOG_LEVEL@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GANGLIA_CPPFLAGS = @GANGLIA_CPPFLAGS@
+GANGLIA_LDFLAGS = @GANGLIA_LDFLAGS@
+GANGLIA_LIBS = @GANGLIA_LIBS@
+GCRYPT_CPPFLAGS = @GCRYPT_CPPFLAGS@
+GCRYPT_LDFLAGS = @GCRYPT_LDFLAGS@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GREP = @GREP@
+INCLTDL = @INCLTDL@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVA_CFLAGS = @JAVA_CFLAGS@
+JAVA_CPPFLAGS = @JAVA_CPPFLAGS@
+JAVA_LDFLAGS = @JAVA_LDFLAGS@
+JAVA_LIBS = @JAVA_LIBS@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_DIR = @KERNEL_DIR@
+LCC_VERSION_EXTRA = @LCC_VERSION_EXTRA@
+LCC_VERSION_MAJOR = @LCC_VERSION_MAJOR@
+LCC_VERSION_MINOR = @LCC_VERSION_MINOR@
+LCC_VERSION_PATCH = @LCC_VERSION_PATCH@
+LCC_VERSION_STRING = @LCC_VERSION_STRING@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBADD_DL = @LIBADD_DL@
+LIBADD_DLD_LINK = @LIBADD_DLD_LINK@
+LIBADD_DLOPEN = @LIBADD_DLOPEN@
+LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBLTDL = @LIBLTDL@
+LIBNETAPP_CPPFLAGS = @LIBNETAPP_CPPFLAGS@
+LIBNETAPP_LDFLAGS = @LIBNETAPP_LDFLAGS@
+LIBNETAPP_LIBS = @LIBNETAPP_LIBS@
+LIBNOTIFY_CFLAGS = @LIBNOTIFY_CFLAGS@
+LIBNOTIFY_LIBS = @LIBNOTIFY_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOAD_PLUGIN_CSV = @LOAD_PLUGIN_CSV@
+LOAD_PLUGIN_LOGFILE = @LOAD_PLUGIN_LOGFILE@
+LOAD_PLUGIN_LOG_LOGSTASH = @LOAD_PLUGIN_LOG_LOGSTASH@
+LOAD_PLUGIN_NETWORK = @LOAD_PLUGIN_NETWORK@
+LOAD_PLUGIN_RRDTOOL = @LOAD_PLUGIN_RRDTOOL@
+LOAD_PLUGIN_SYSLOG = @LOAD_PLUGIN_SYSLOG@
+LTDLDEPS = @LTDLDEPS@
+LTDLINCL = @LTDLINCL@
+LTDLOPEN = @LTDLOPEN@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CONFIG_H = @LT_CONFIG_H@
+LT_DLLOADERS = @LT_DLLOADERS@
+LT_DLPREOPEN = @LT_DLPREOPEN@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PERL_BINDINGS = @PERL_BINDINGS@
+PERL_BINDINGS_OPTIONS = @PERL_BINDINGS_OPTIONS@
+PERL_CFLAGS = @PERL_CFLAGS@
+PERL_LIBS = @PERL_LIBS@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+have_protoc_c = @have_protoc_c@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+ltdl_LIBOBJS = @ltdl_LIBOBJS@
+ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgconfigdir = @pkgconfigdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sys_symbol_underscore = @sys_symbol_underscore@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+BUILT_SOURCES = parser.h
+#CLEANFILES = parser.[ch] scanner.c
+AM_YFLAGS = -d
+noinst_LTLIBRARIES = liboconfig.la
+liboconfig_la_LDFLAGS = -version-info 0:0:0 $(LEXLIB)
+liboconfig_la_SOURCES = oconfig.c oconfig.h aux_types.h scanner.l parser.y
+all: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .l .lo .o .obj .y
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/liboconfig/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign src/liboconfig/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+       -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+       @list='$(noinst_LTLIBRARIES)'; \
+       locs=`for p in $$list; do echo $$p; done | \
+             sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+             sort -u`; \
+       test -z "$$locs" || { \
+         echo rm -f $${locs}; \
+         rm -f $${locs}; \
+       }
+parser.h: parser.c
+       @if test ! -f $@; then rm -f parser.c; else :; fi
+       @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) parser.c; else :; fi
+
+liboconfig.la: $(liboconfig_la_OBJECTS) $(liboconfig_la_DEPENDENCIES) $(EXTRA_liboconfig_la_DEPENDENCIES) 
+       $(AM_V_CCLD)$(liboconfig_la_LINK)  $(liboconfig_la_OBJECTS) $(liboconfig_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+.c.o:
+       $(AM_V_CC)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+       $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+       $(AM_V_CC)$(LTCOMPILE) -c -o $@ $<
+
+.l.c:
+       $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
+
+.y.c:
+       $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -rm -f parser.c
+       -rm -f parser.h
+       -rm -f scanner.c
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
+       ctags-am distclean distclean-compile distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+       tags tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/liboconfig/aux_types.h b/src/liboconfig/aux_types.h
new file mode 100644 (file)
index 0000000..25b81ab
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef AUX_TYPES_H
+#define AUX_TYPES_H 1
+
+struct statement_list_s
+{
+       oconfig_item_t *statement;
+       int             statement_num;
+};
+typedef struct statement_list_s statement_list_t;
+
+struct argument_list_s
+{
+       oconfig_value_t *argument;
+       int              argument_num;
+};
+typedef struct argument_list_s argument_list_t;
+
+#endif /* AUX_TYPES_H */
diff --git a/src/liboconfig/oconfig.c b/src/liboconfig/oconfig.c
new file mode 100644 (file)
index 0000000..bf21b90
--- /dev/null
@@ -0,0 +1,232 @@
+/**
+ * collectd - src/liboconfig/oconfig.c
+ * Copyright (C) 2006,2007  Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "oconfig.h"
+
+extern FILE *yyin;
+
+oconfig_item_t *ci_root;
+const char     *c_file;
+
+static void yyset_in  (FILE *fd)
+{
+  yyin = fd;
+} /* void yyset_in */
+
+oconfig_item_t *oconfig_parse_fh (FILE *fh)
+{
+  int status;
+  oconfig_item_t *ret;
+
+  char file[10];
+
+  yyset_in (fh);
+
+  if (NULL == c_file) {
+    int status;
+
+    status = snprintf (file, sizeof (file), "<fd#%d>", fileno (fh));
+
+    if ((status < 0) || (status >= sizeof (file))) {
+      c_file = "<unknown>";
+    }
+    else {
+      file[sizeof (file) - 1] = '\0';
+      c_file = file;
+    }
+  }
+
+  status = yyparse ();
+  if (status != 0)
+  {
+    fprintf (stderr, "yyparse returned error #%i\n", status);
+    return (NULL);
+  }
+
+  c_file = NULL;
+
+  ret = ci_root;
+  ci_root = NULL;
+  yyset_in ((FILE *) 0);
+
+  return (ret);
+} /* oconfig_item_t *oconfig_parse_fh */
+
+oconfig_item_t *oconfig_parse_file (const char *file)
+{
+  FILE *fh;
+  oconfig_item_t *ret;
+
+  c_file = file;
+
+  fh = fopen (file, "r");
+  if (fh == NULL)
+  {
+    fprintf (stderr, "fopen (%s) failed: %s\n", file, strerror (errno));
+    return (NULL);
+  }
+
+  ret = oconfig_parse_fh (fh);
+  fclose (fh);
+
+  c_file = NULL;
+
+  return (ret);
+} /* oconfig_item_t *oconfig_parse_file */
+
+oconfig_item_t *oconfig_clone (const oconfig_item_t *ci_orig)
+{
+  oconfig_item_t *ci_copy;
+
+  ci_copy = (oconfig_item_t *) malloc (sizeof (*ci_copy));
+  if (ci_copy == NULL)
+  {
+    fprintf (stderr, "malloc failed.\n");
+    return (NULL);
+  }
+  memset (ci_copy, 0, sizeof (*ci_copy));
+  ci_copy->values = NULL;
+  ci_copy->parent = NULL;
+  ci_copy->children = NULL;
+
+  ci_copy->key = strdup (ci_orig->key);
+  if (ci_copy->key == NULL)
+  {
+    fprintf (stderr, "strdup failed.\n");
+    free (ci_copy);
+    return (NULL);
+  }
+
+  if (ci_orig->values_num > 0) /* {{{ */
+  {
+    int i;
+
+    ci_copy->values = (oconfig_value_t *) calloc (ci_orig->values_num,
+       sizeof (*ci_copy->values));
+    if (ci_copy->values == NULL)
+    {
+      fprintf (stderr, "calloc failed.\n");
+      free (ci_copy->key);
+      free (ci_copy);
+      return (NULL);
+    }
+    ci_copy->values_num = ci_orig->values_num;
+
+    for (i = 0; i < ci_copy->values_num; i++)
+    {
+       ci_copy->values[i].type = ci_orig->values[i].type;
+       if (ci_copy->values[i].type == OCONFIG_TYPE_STRING)
+       {
+        ci_copy->values[i].value.string
+          = strdup (ci_orig->values[i].value.string);
+        if (ci_copy->values[i].value.string == NULL)
+        {
+          fprintf (stderr, "strdup failed.\n");
+          oconfig_free (ci_copy);
+          return (NULL);
+        }
+       }
+       else /* ci_copy->values[i].type != OCONFIG_TYPE_STRING) */
+       {
+        ci_copy->values[i].value = ci_orig->values[i].value;
+       }
+    }
+  } /* }}} if (ci_orig->values_num > 0) */
+
+  if (ci_orig->children_num > 0) /* {{{ */
+  {
+    int i;
+
+    ci_copy->children = (oconfig_item_t *) calloc (ci_orig->children_num,
+       sizeof (*ci_copy->children));
+    if (ci_copy->children == NULL)
+    {
+      fprintf (stderr, "calloc failed.\n");
+      oconfig_free (ci_copy);
+      return (NULL);
+    }
+    ci_copy->children_num = ci_orig->children_num;
+
+    for (i = 0; i < ci_copy->children_num; i++)
+    {
+      oconfig_item_t *child;
+      
+      child = oconfig_clone (ci_orig->children + i);
+      if (child == NULL)
+      {
+       oconfig_free (ci_copy);
+       return (NULL);
+      }
+      child->parent = ci_copy;
+      ci_copy->children[i] = *child;
+      free (child);
+    } /* for (i = 0; i < ci_copy->children_num; i++) */
+  } /* }}} if (ci_orig->children_num > 0) */
+
+  return (ci_copy);
+} /* oconfig_item_t *oconfig_clone */
+
+void oconfig_free_all (oconfig_item_t *ci)
+{
+  int i;
+
+  if (ci == NULL)
+    return;
+
+  if (ci->key != NULL)
+    free (ci->key);
+
+  for (i = 0; i < ci->values_num; i++)
+    if ((ci->values[i].type == OCONFIG_TYPE_STRING)
+        && (NULL != ci->values[i].value.string))
+      free (ci->values[i].value.string);
+
+  if (ci->values != NULL)
+    free (ci->values);
+
+  for (i = 0; i < ci->children_num; i++)
+    oconfig_free_all (ci->children + i);
+
+  if (ci->children != NULL)
+    free (ci->children);
+}
+
+void oconfig_free (oconfig_item_t *ci)
+{
+  oconfig_free_all (ci);
+  free (ci);
+  ci = NULL;
+}
+
+/*
+ * vim:shiftwidth=2:tabstop=8:softtabstop=2:fdm=marker
+ */
diff --git a/src/liboconfig/oconfig.h b/src/liboconfig/oconfig.h
new file mode 100644 (file)
index 0000000..840137c
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * collectd - src/liboconfig/oconfig.h
+ * Copyright (C) 2006-2009  Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ */
+
+#ifndef OCONFIG_H
+#define OCONFIG_H 1
+
+#include <stdio.h>
+
+/*
+ * Types
+ */
+#define OCONFIG_TYPE_STRING  0
+#define OCONFIG_TYPE_NUMBER  1
+#define OCONFIG_TYPE_BOOLEAN 2
+
+struct oconfig_value_s
+{
+  union
+  {
+    char  *string;
+    double number;
+    int    boolean;
+  } value;
+  int type;
+};
+typedef struct oconfig_value_s oconfig_value_t;
+
+struct oconfig_item_s;
+typedef struct oconfig_item_s oconfig_item_t;
+struct oconfig_item_s
+{
+  char            *key;
+  oconfig_value_t *values;
+  int              values_num;
+
+  oconfig_item_t  *parent;
+  oconfig_item_t  *children;
+  int              children_num;
+};
+
+/*
+ * Functions
+ */
+oconfig_item_t *oconfig_parse_fh (FILE *fh);
+oconfig_item_t *oconfig_parse_file (const char *file);
+
+oconfig_item_t *oconfig_clone (const oconfig_item_t *ci);
+
+void oconfig_free (oconfig_item_t *ci);
+
+/*
+ * vim: shiftwidth=2:tabstop=8:softtabstop=2
+ */
+#endif /* OCONFIG_H */
diff --git a/src/liboconfig/parser.c b/src/liboconfig/parser.c
new file mode 100644 (file)
index 0000000..34dd9a8
--- /dev/null
@@ -0,0 +1,1742 @@
+/* A Bison parser, made by GNU Bison 3.0.2.  */
+
+/* Bison implementation for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+   simplifying the original so-called "semantic" parser.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+/* Identify Bison output.  */
+#define YYBISON 1
+
+/* Bison version.  */
+#define YYBISON_VERSION "3.0.2"
+
+/* Skeleton name.  */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers.  */
+#define YYPURE 0
+
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
+
+
+
+/* Copy the first part of user declarations.  */
+#line 27 "parser.y" /* yacc.c:339  */
+
+#include <stdlib.h>
+#include <string.h>
+#include "oconfig.h"
+#include "aux_types.h"
+
+static char *unquote (const char *orig);
+static int yyerror (const char *s);
+
+/* Lexer variables */
+extern int yylineno;
+extern char *yytext;
+
+extern oconfig_item_t *ci_root;
+extern char           *c_file;
+
+#line 83 "parser.c" /* yacc.c:339  */
+
+# ifndef YY_NULLPTR
+#  if defined __cplusplus && 201103L <= __cplusplus
+#   define YY_NULLPTR nullptr
+#  else
+#   define YY_NULLPTR 0
+#  endif
+# endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 1
+#endif
+
+/* In a future release of Bison, this section will be replaced
+   by #include "y.tab.h".  */
+#ifndef YY_YY_Y_TAB_H_INCLUDED
+# define YY_YY_Y_TAB_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    NUMBER = 258,
+    BTRUE = 259,
+    BFALSE = 260,
+    QUOTED_STRING = 261,
+    UNQUOTED_STRING = 262,
+    SLASH = 263,
+    OPENBRAC = 264,
+    CLOSEBRAC = 265,
+    EOL = 266
+  };
+#endif
+/* Tokens.  */
+#define NUMBER 258
+#define BTRUE 259
+#define BFALSE 260
+#define QUOTED_STRING 261
+#define UNQUOTED_STRING 262
+#define SLASH 263
+#define OPENBRAC 264
+#define CLOSEBRAC 265
+#define EOL 266
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE YYSTYPE;
+union YYSTYPE
+{
+#line 46 "parser.y" /* yacc.c:355  */
+
+       double  number;
+       int     boolean;
+       char   *string;
+       oconfig_value_t  cv;
+       oconfig_item_t   ci;
+       argument_list_t  al;
+       statement_list_t sl;
+
+#line 155 "parser.c" /* yacc.c:355  */
+};
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+extern YYSTYPE yylval;
+
+int yyparse (void);
+
+#endif /* !YY_YY_Y_TAB_H_INCLUDED  */
+
+/* Copy the second part of user declarations.  */
+
+#line 170 "parser.c" /* yacc.c:358  */
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#else
+typedef signed char yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+#  define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+#  define YYSIZE_T size_t
+# elif ! defined YYSIZE_T
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# else
+#  define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E.  */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
+#else
+# define YY_INITIAL_VALUE(Value) Value
+#endif
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols.  */
+
+# ifdef YYSTACK_USE_ALLOCA
+#  if YYSTACK_USE_ALLOCA
+#   ifdef __GNUC__
+#    define YYSTACK_ALLOC __builtin_alloca
+#   elif defined __BUILTIN_VA_ARG_INCR
+#    include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+#   elif defined _AIX
+#    define YYSTACK_ALLOC __alloca
+#   elif defined _MSC_VER
+#    include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+#    define alloca _alloca
+#   else
+#    define YYSTACK_ALLOC alloca
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+      /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
+#     ifndef EXIT_SUCCESS
+#      define EXIT_SUCCESS 0
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+#  endif
+# else
+#  define YYSTACK_ALLOC YYMALLOC
+#  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+#  endif
+#  if (defined __cplusplus && ! defined EXIT_SUCCESS \
+       && ! ((defined YYMALLOC || defined malloc) \
+             && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef EXIT_SUCCESS
+#    define EXIT_SUCCESS 0
+#   endif
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if ! defined malloc && ! defined EXIT_SUCCESS
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if ! defined free && ! defined EXIT_SUCCESS
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+     && (! defined __cplusplus \
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+      + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if defined __GNUC__ && 1 < __GNUC__
+#   define YYCOPY(Dst, Src, Count) \
+      __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+#  else
+#   define YYCOPY(Dst, Src, Count)              \
+      do                                        \
+        {                                       \
+          YYSIZE_T yyi;                         \
+          for (yyi = 0; yyi < (Count); yyi++)   \
+            (Dst)[yyi] = (Src)[yyi];            \
+        }                                       \
+      while (0)
+#  endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state.  */
+#define YYFINAL  24
+/* YYLAST -- Last index in YYTABLE.  */
+#define YYLAST   46
+
+/* YYNTOKENS -- Number of terminals.  */
+#define YYNTOKENS  12
+/* YYNNTS -- Number of nonterminals.  */
+#define YYNNTS  12
+/* YYNRULES -- Number of rules.  */
+#define YYNRULES  23
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  37
+
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
+#define YYUNDEFTOK  2
+#define YYMAXUTOK   266
+
+#define YYTRANSLATE(YYX)                                                \
+  ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
+static const yytype_uint8 yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
+       5,     6,     7,     8,     9,    10,    11
+};
+
+#if YYDEBUG
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+static const yytype_uint8 yyrline[] =
+{
+       0,    81,    81,    82,    86,    87,    88,    89,    93,   100,
+     109,   113,   123,   129,   139,   146,   159,   175,   176,   177,
+     181,   191,   208,   216
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 1
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+   First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
+static const char *const yytname[] =
+{
+  "$end", "error", "$undefined", "NUMBER", "BTRUE", "BFALSE",
+  "QUOTED_STRING", "UNQUOTED_STRING", "SLASH", "OPENBRAC", "CLOSEBRAC",
+  "EOL", "$accept", "string", "argument", "argument_list", "identifier",
+  "option", "block_begin", "block_end", "block", "statement",
+  "statement_list", "entire_file", YY_NULLPTR
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
+static const yytype_uint16 yytoknum[] =
+{
+       0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
+     265,   266
+};
+# endif
+
+#define YYPACT_NINF -12
+
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-12)))
+
+#define YYTABLE_NINF -1
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int8 yypact[] =
+{
+       0,   -12,     9,   -12,    33,   -12,    34,   -12,   -12,     0,
+      17,    16,   -12,   -12,   -12,   -12,   -12,   -12,   -12,    -1,
+       5,   -12,    34,   -12,   -12,    13,    25,   -12,   -12,     9,
+     -12,   -12,    14,    23,   -12,    31,   -12
+};
+
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
+{
+      23,    10,     0,    19,     0,    17,     0,    18,    21,    22,
+       0,     0,     4,     5,     6,     2,     3,     7,     9,     0,
+       0,    16,     0,    20,     1,     0,     0,    11,     8,     0,
+      15,    12,     0,     0,    13,     0,    14
+};
+
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int8 yypgoto[] =
+{
+     -12,   -12,   -11,    35,    -2,   -12,   -12,    12,   -12,    -8,
+      38,   -12
+};
+
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int8 yydefgoto[] =
+{
+      -1,    17,    18,    19,     4,     5,     6,    21,     7,     8,
+       9,    10
+};
+
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
+static const yytype_uint8 yytable[] =
+{
+      11,    23,    12,    13,    14,    15,    16,     1,    28,     2,
+      27,     3,     1,    29,    23,    28,     1,    24,    11,    12,
+      13,    14,    15,    16,    31,    34,    25,    33,    12,    13,
+      14,    15,    16,    35,    30,    32,    12,    13,    14,    15,
+      16,     1,    36,    20,    22,     3,    26
+};
+
+static const yytype_uint8 yycheck[] =
+{
+       2,     9,     3,     4,     5,     6,     7,     7,    19,     9,
+      11,    11,     7,     8,    22,    26,     7,     0,    20,     3,
+       4,     5,     6,     7,    11,    11,    10,    29,     3,     4,
+       5,     6,     7,    10,    22,    10,     3,     4,     5,     6,
+       7,     7,    11,     9,     6,    11,    11
+};
+
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
+static const yytype_uint8 yystos[] =
+{
+       0,     7,     9,    11,    16,    17,    18,    20,    21,    22,
+      23,    16,     3,     4,     5,     6,     7,    13,    14,    15,
+       9,    19,    22,    21,     0,    10,    15,    11,    14,     8,
+      19,    11,    10,    16,    11,    10,    11
+};
+
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    12,    13,    13,    14,    14,    14,    14,    15,    15,
+      16,    17,    18,    18,    19,    20,    20,    21,    21,    21,
+      22,    22,    23,    23
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     1,     1,     1,     1,     1,     1,     2,     1,
+       1,     3,     4,     5,     5,     3,     2,     1,     1,     1,
+       2,     1,     1,     0
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
+
+#define YYRECOVERING()  (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value)                                  \
+do                                                              \
+  if (yychar == YYEMPTY)                                        \
+    {                                                           \
+      yychar = (Token);                                         \
+      yylval = (Value);                                         \
+      YYPOPSTACK (yylen);                                       \
+      yystate = *yyssp;                                         \
+      goto yybackup;                                            \
+    }                                                           \
+  else                                                          \
+    {                                                           \
+      yyerror (YY_("syntax error: cannot back up")); \
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
+
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
+
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
+
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+{
+  FILE *yyo = yyoutput;
+  YYUSE (yyo);
+  if (!yyvaluep)
+    return;
+# ifdef YYPRINT
+  if (yytype < YYNTOKENS)
+    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# endif
+  YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT.  |
+`--------------------------------*/
+
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+{
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
+
+  yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+  YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included).                                                   |
+`------------------------------------------------------------------*/
+
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+{
+  YYFPRINTF (stderr, "Stack now");
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
+  YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced.  |
+`------------------------------------------------*/
+
+static void
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
+{
+  unsigned long int yylno = yyrline[yyrule];
+  int yynrhs = yyr2[yyrule];
+  int yyi;
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+             yyrule - 1, yylno);
+  /* The symbols being reduced.  */
+  for (yyi = 0; yyi < yynrhs; yyi++)
+    {
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              );
+      YYFPRINTF (stderr, "\n");
+    }
+}
+
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
+
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined __GLIBC__ && defined _STRING_H
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+yystrlen (const char *yystr)
+{
+  YYSIZE_T yylen;
+  for (yylen = 0; yystr[yylen]; yylen++)
+    continue;
+  return yylen;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+{
+  char *yyd = yydest;
+  const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      YYSIZE_T yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+   about the unexpected token YYTOKEN for the state stack whose top is
+   YYSSP.
+
+   Return 0 if *YYMSG was successfully written.  Return 1 if *YYMSG is
+   not large enough to hold the message.  In that case, also set
+   *YYMSG_ALLOC to the required number of bytes.  Return 2 if the
+   required number of bytes is too large to store.  */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+                yytype_int16 *yyssp, int yytoken)
+{
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
+  YYSIZE_T yysize = yysize0;
+  enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+  /* Internationalized format string. */
+  const char *yyformat = YY_NULLPTR;
+  /* Arguments of yyformat. */
+  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+  /* Number of reported tokens (one for the "unexpected", one per
+     "expected"). */
+  int yycount = 0;
+
+  /* There are many possibilities here to consider:
+     - If this state is a consistent state with a default action, then
+       the only way this function was invoked is if the default action
+       is an error action.  In that case, don't check for expected
+       tokens because there are none.
+     - The only way there can be no lookahead present (in yychar) is if
+       this state is a consistent state with a default action.  Thus,
+       detecting the absence of a lookahead is sufficient to determine
+       that there is no unexpected or expected token to report.  In that
+       case, just report a simple "syntax error".
+     - Don't assume there isn't a lookahead just because this state is a
+       consistent state with a default action.  There might have been a
+       previous inconsistent state, consistent state with a non-default
+       action, or user semantic action that manipulated yychar.
+     - Of course, the expected token list depends on states to have
+       correct lookahead information, and it depends on the parser not
+       to perform extra reductions after fetching a lookahead from the
+       scanner and before detecting a syntax error.  Thus, state merging
+       (from LALR or IELR) and default reductions corrupt the expected
+       token list.  However, the list is correct for canonical LR with
+       one exception: it will still contain any token that will not be
+       accepted due to an error action in a later state.
+  */
+  if (yytoken != YYEMPTY)
+    {
+      int yyn = yypact[*yyssp];
+      yyarg[yycount++] = yytname[yytoken];
+      if (!yypact_value_is_default (yyn))
+        {
+          /* Start YYX at -YYN if negative to avoid negative indexes in
+             YYCHECK.  In other words, skip the first -YYN actions for
+             this state because they are default actions.  */
+          int yyxbegin = yyn < 0 ? -yyn : 0;
+          /* Stay within bounds of both yycheck and yytname.  */
+          int yychecklim = YYLAST - yyn + 1;
+          int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+          int yyx;
+
+          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+                && !yytable_value_is_error (yytable[yyx + yyn]))
+              {
+                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+                  {
+                    yycount = 1;
+                    yysize = yysize0;
+                    break;
+                  }
+                yyarg[yycount++] = yytname[yyx];
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
+              }
+        }
+    }
+
+  switch (yycount)
+    {
+# define YYCASE_(N, S)                      \
+      case N:                               \
+        yyformat = S;                       \
+      break
+      YYCASE_(0, YY_("syntax error"));
+      YYCASE_(1, YY_("syntax error, unexpected %s"));
+      YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+      YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+      YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+      YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+    }
+
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
+
+  if (*yymsg_alloc < yysize)
+    {
+      *yymsg_alloc = 2 * yysize;
+      if (! (yysize <= *yymsg_alloc
+             && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+        *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+      return 1;
+    }
+
+  /* Avoid sprintf, as that infringes on the user's name space.
+     Don't have undefined behavior even if the translation
+     produced a string with the wrong number of "%s"s.  */
+  {
+    char *yyp = *yymsg;
+    int yyi = 0;
+    while ((*yyp = *yyformat) != '\0')
+      if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+        {
+          yyp += yytnamerr (yyp, yyarg[yyi++]);
+          yyformat += 2;
+        }
+      else
+        {
+          yyp++;
+          yyformat++;
+        }
+  }
+  return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol.  |
+`-----------------------------------------------*/
+
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+{
+  YYUSE (yyvaluep);
+  if (!yymsg)
+    yymsg = "Deleting";
+  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  YYUSE (yytype);
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+
+
+
+/* The lookahead symbol.  */
+int yychar;
+
+/* The semantic value of the lookahead symbol.  */
+YYSTYPE yylval;
+/* Number of syntax errors so far.  */
+int yynerrs;
+
+
+/*----------.
+| yyparse.  |
+`----------*/
+
+int
+yyparse (void)
+{
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
+
+    /* The stacks and their tools:
+       'yyss': related to states.
+       'yyvs': related to semantic values.
+
+       Refer to the stacks through separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
+
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
+
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
+
+    YYSIZE_T yystacksize;
+
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken = 0;
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
+
+  /* The number of symbols on the RHS of the reduced rule.
+     Keep to zero when no symbol should be popped.  */
+  int yylen = 0;
+
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY; /* Cause a token to be read.  */
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed.  So pushing a state here evens the stacks.  */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyss + yystacksize - 1 <= yyssp)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyexhaustedlab;
+# else
+      /* Extend the stack our own way.  */
+      if (YYMAXDEPTH <= yystacksize)
+        goto yyexhaustedlab;
+      yystacksize *= 2;
+      if (YYMAXDEPTH < yystacksize)
+        yystacksize = YYMAXDEPTH;
+
+      {
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+#  undef YYSTACK_RELOCATE
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                  (unsigned long int) yystacksize));
+
+      if (yyss + yystacksize - 1 <= yyssp)
+        YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
+  goto yybackup;
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+  /* Do appropriate processing given the current state.  Read a
+     lookahead token if we need one and don't already have one.  */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+  yyn = yypact[yystate];
+  if (yypact_value_is_default (yyn))
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = yylex ();
+    }
+
+  if (yychar <= YYEOF)
+    {
+      yychar = yytoken = YYEOF;
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yytoken = YYTRANSLATE (yychar);
+      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+    }
+
+  /* If the proper action on seeing token YYTOKEN is to reduce or to
+     detect an error, take that action.  */
+  yyn += yytoken;
+  if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+    goto yydefault;
+  yyn = yytable[yyn];
+  if (yyn <= 0)
+    {
+      if (yytable_value_is_error (yyn))
+        goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  /* Shift the lookahead token.  */
+  YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
+
+  yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     '$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to garbage.
+     This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+
+  YY_REDUCE_PRINT (yyn);
+  switch (yyn)
+    {
+        case 2:
+#line 81 "parser.y" /* yacc.c:1646  */
+    {(yyval.string) = unquote ((yyvsp[0].string));}
+#line 1265 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 3:
+#line 82 "parser.y" /* yacc.c:1646  */
+    {(yyval.string) = strdup ((yyvsp[0].string));}
+#line 1271 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 4:
+#line 86 "parser.y" /* yacc.c:1646  */
+    {(yyval.cv).value.number = (yyvsp[0].number); (yyval.cv).type = OCONFIG_TYPE_NUMBER;}
+#line 1277 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 5:
+#line 87 "parser.y" /* yacc.c:1646  */
+    {(yyval.cv).value.boolean = 1; (yyval.cv).type = OCONFIG_TYPE_BOOLEAN;}
+#line 1283 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 6:
+#line 88 "parser.y" /* yacc.c:1646  */
+    {(yyval.cv).value.boolean = 0; (yyval.cv).type = OCONFIG_TYPE_BOOLEAN;}
+#line 1289 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 7:
+#line 89 "parser.y" /* yacc.c:1646  */
+    {(yyval.cv).value.string = (yyvsp[0].string); (yyval.cv).type = OCONFIG_TYPE_STRING;}
+#line 1295 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 8:
+#line 94 "parser.y" /* yacc.c:1646  */
+    {
+        (yyval.al) = (yyvsp[-1].al);
+        (yyval.al).argument_num++;
+        (yyval.al).argument = realloc ((yyval.al).argument, (yyval.al).argument_num * sizeof (oconfig_value_t));
+        (yyval.al).argument[(yyval.al).argument_num-1] = (yyvsp[0].cv);
+       }
+#line 1306 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 9:
+#line 101 "parser.y" /* yacc.c:1646  */
+    {
+        (yyval.al).argument = malloc (sizeof (oconfig_value_t));
+        (yyval.al).argument[0] = (yyvsp[0].cv);
+        (yyval.al).argument_num = 1;
+       }
+#line 1316 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 10:
+#line 109 "parser.y" /* yacc.c:1646  */
+    {(yyval.string) = strdup ((yyvsp[0].string));}
+#line 1322 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 11:
+#line 114 "parser.y" /* yacc.c:1646  */
+    {
+        memset (&(yyval.ci), '\0', sizeof ((yyval.ci)));
+        (yyval.ci).key = (yyvsp[-2].string);
+        (yyval.ci).values = (yyvsp[-1].al).argument;
+        (yyval.ci).values_num = (yyvsp[-1].al).argument_num;
+       }
+#line 1333 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 12:
+#line 124 "parser.y" /* yacc.c:1646  */
+    {
+        memset (&(yyval.ci), '\0', sizeof ((yyval.ci)));
+        (yyval.ci).key = (yyvsp[-2].string);
+       }
+#line 1342 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 13:
+#line 130 "parser.y" /* yacc.c:1646  */
+    {
+        memset (&(yyval.ci), '\0', sizeof ((yyval.ci)));
+        (yyval.ci).key = (yyvsp[-3].string);
+        (yyval.ci).values = (yyvsp[-2].al).argument;
+        (yyval.ci).values_num = (yyvsp[-2].al).argument_num;
+       }
+#line 1353 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 14:
+#line 140 "parser.y" /* yacc.c:1646  */
+    {
+        (yyval.string) = (yyvsp[-2].string);
+       }
+#line 1361 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 15:
+#line 147 "parser.y" /* yacc.c:1646  */
+    {
+        if (strcmp ((yyvsp[-2].ci).key, (yyvsp[0].string)) != 0)
+        {
+               printf ("block_begin = %s; block_end = %s;\n", (yyvsp[-2].ci).key, (yyvsp[0].string));
+               yyerror ("Block not closed..\n");
+               exit (1);
+        }
+        free ((yyvsp[0].string)); (yyvsp[0].string) = NULL;
+        (yyval.ci) = (yyvsp[-2].ci);
+        (yyval.ci).children = (yyvsp[-1].sl).statement;
+        (yyval.ci).children_num = (yyvsp[-1].sl).statement_num;
+       }
+#line 1378 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 16:
+#line 160 "parser.y" /* yacc.c:1646  */
+    {
+        if (strcmp ((yyvsp[-1].ci).key, (yyvsp[0].string)) != 0)
+        {
+               printf ("block_begin = %s; block_end = %s;\n", (yyvsp[-1].ci).key, (yyvsp[0].string));
+               yyerror ("Block not closed..\n");
+               exit (1);
+        }
+        free ((yyvsp[0].string)); (yyvsp[0].string) = NULL;
+        (yyval.ci) = (yyvsp[-1].ci);
+        (yyval.ci).children = NULL;
+        (yyval.ci).children_num = 0;
+       }
+#line 1395 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 17:
+#line 175 "parser.y" /* yacc.c:1646  */
+    {(yyval.ci) = (yyvsp[0].ci);}
+#line 1401 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 18:
+#line 176 "parser.y" /* yacc.c:1646  */
+    {(yyval.ci) = (yyvsp[0].ci);}
+#line 1407 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 19:
+#line 177 "parser.y" /* yacc.c:1646  */
+    {(yyval.ci).values_num = 0;}
+#line 1413 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 20:
+#line 182 "parser.y" /* yacc.c:1646  */
+    {
+        (yyval.sl) = (yyvsp[-1].sl);
+        if (((yyvsp[0].ci).values_num > 0) || ((yyvsp[0].ci).children_num > 0))
+        {
+                (yyval.sl).statement_num++;
+                (yyval.sl).statement = realloc ((yyval.sl).statement, (yyval.sl).statement_num * sizeof (oconfig_item_t));
+                (yyval.sl).statement[(yyval.sl).statement_num-1] = (yyvsp[0].ci);
+        }
+       }
+#line 1427 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 21:
+#line 192 "parser.y" /* yacc.c:1646  */
+    {
+        if (((yyvsp[0].ci).values_num > 0) || ((yyvsp[0].ci).children_num > 0))
+        {
+                (yyval.sl).statement = malloc (sizeof (oconfig_item_t));
+                (yyval.sl).statement[0] = (yyvsp[0].ci);
+                (yyval.sl).statement_num = 1;
+        }
+        else
+        {
+               (yyval.sl).statement = NULL;
+               (yyval.sl).statement_num = 0;
+        }
+       }
+#line 1445 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 22:
+#line 209 "parser.y" /* yacc.c:1646  */
+    {
+        ci_root = malloc (sizeof (oconfig_item_t));
+        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root->children = (yyvsp[0].sl).statement;
+        ci_root->children_num = (yyvsp[0].sl).statement_num;
+       }
+#line 1456 "parser.c" /* yacc.c:1646  */
+    break;
+
+  case 23:
+#line 216 "parser.y" /* yacc.c:1646  */
+    {
+        ci_root = malloc (sizeof (oconfig_item_t));
+        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root->children = NULL;
+        ci_root->children_num = 0;
+       }
+#line 1467 "parser.c" /* yacc.c:1646  */
+    break;
+
+
+#line 1471 "parser.c" /* yacc.c:1646  */
+      default: break;
+    }
+  /* User semantic actions sometimes alter yychar, and that requires
+     that yytoken be updated with the new translation.  We take the
+     approach of translating immediately before every use of yytoken.
+     One alternative is translating here after every semantic action,
+     but that translation would be missed if the semantic action invokes
+     YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+     if it invokes YYBACKUP.  In the case of YYABORT or YYACCEPT, an
+     incorrect destructor might then be invoked immediately.  In the
+     case of YYERROR or YYBACKUP, subsequent parser actions might lead
+     to an incorrect destructor call or verbose syntax error message
+     before the lookahead is translated.  */
+  YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+
+  *++yyvsp = yyval;
+
+  /* Now 'shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTOKENS];
+
+  goto yynewstate;
+
+
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
+yyerrlab:
+  /* Make sure we have latest lookahead translation.  See comments at
+     user semantic actions for why this is necessary.  */
+  yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+#if ! YYERROR_VERBOSE
+      yyerror (YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+                                        yyssp, yytoken)
+      {
+        char const *yymsgp = YY_("syntax error");
+        int yysyntax_error_status;
+        yysyntax_error_status = YYSYNTAX_ERROR;
+        if (yysyntax_error_status == 0)
+          yymsgp = yymsg;
+        else if (yysyntax_error_status == 1)
+          {
+            if (yymsg != yymsgbuf)
+              YYSTACK_FREE (yymsg);
+            yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+            if (!yymsg)
+              {
+                yymsg = yymsgbuf;
+                yymsg_alloc = sizeof yymsgbuf;
+                yysyntax_error_status = 2;
+              }
+            else
+              {
+                yysyntax_error_status = YYSYNTAX_ERROR;
+                yymsgp = yymsg;
+              }
+          }
+        yyerror (yymsgp);
+        if (yysyntax_error_status == 2)
+          goto yyexhaustedlab;
+      }
+# undef YYSYNTAX_ERROR
+#endif
+    }
+
+
+
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+         error, discard it.  */
+
+      if (yychar <= YYEOF)
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
+      else
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval);
+          yychar = YYEMPTY;
+        }
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+  goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR.  |
+`---------------------------------------------------*/
+yyerrorlab:
+
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
+  if (/*CONSTCOND*/ 0)
+     goto yyerrorlab;
+
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYERROR.  */
+  YYPOPSTACK (yylen);
+  yylen = 0;
+  YY_STACK_PRINT (yyss, yyssp);
+  yystate = *yyssp;
+  goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR.  |
+`-------------------------------------------------------------*/
+yyerrlab1:
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
+
+  for (;;)
+    {
+      yyn = yypact[yystate];
+      if (!yypact_value_is_default (yyn))
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
+
+      /* Pop the current state because it cannot handle the error token.  */
+      if (yyssp == yyss)
+        YYABORT;
+
+
+      yydestruct ("Error: popping",
+                  yystos[yystate], yyvsp);
+      YYPOPSTACK (1);
+      yystate = *yyssp;
+      YY_STACK_PRINT (yyss, yyssp);
+    }
+
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+  *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+
+  /* Shift the error token.  */
+  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
+  yyresult = 2;
+  /* Fall through.  */
+#endif
+
+yyreturn:
+  if (yychar != YYEMPTY)
+    {
+      /* Make sure we have latest lookahead translation.  See comments at
+         user semantic actions for why this is necessary.  */
+      yytoken = YYTRANSLATE (yychar);
+      yydestruct ("Cleanup: discarding lookahead",
+                  yytoken, &yylval);
+    }
+  /* Do not reclaim the symbols of the rule whose action triggered
+     this YYABORT or YYACCEPT.  */
+  YYPOPSTACK (yylen);
+  YY_STACK_PRINT (yyss, yyssp);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+                  yystos[*yyssp], yyvsp);
+      YYPOPSTACK (1);
+    }
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+  if (yymsg != yymsgbuf)
+    YYSTACK_FREE (yymsg);
+#endif
+  return yyresult;
+}
+#line 224 "parser.y" /* yacc.c:1906  */
+
+static int yyerror (const char *s)
+{
+       char *text;
+
+       if (*yytext == '\n')
+               text = "<newline>";
+       else
+               text = yytext;
+
+       fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
+               c_file, yylineno, text, s);
+       return (-1);
+} /* int yyerror */
+
+static char *unquote (const char *orig)
+{
+       char *ret = strdup (orig);
+       int len;
+       int i;
+
+       if (ret == NULL)
+               return (NULL);
+
+       len = strlen (ret);
+
+       if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
+               return (ret);
+
+       len -= 2;
+       memmove (ret, ret + 1, len);
+       ret[len] = '\0';
+
+       for (i = 0; i < len; i++)
+       {
+               if (ret[i] == '\\')
+               {
+                       memmove (ret + i, ret + (i + 1), len - i);
+                       len--;
+               }
+       }
+
+       return (ret);
+} /* char *unquote */
diff --git a/src/liboconfig/parser.h b/src/liboconfig/parser.h
new file mode 100644 (file)
index 0000000..746e4b8
--- /dev/null
@@ -0,0 +1,96 @@
+/* A Bison parser, made by GNU Bison 3.0.2.  */
+
+/* Bison interface for Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+#ifndef YY_YY_PARSER_H_INCLUDED
+# define YY_YY_PARSER_H_INCLUDED
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+
+/* Token type.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+  enum yytokentype
+  {
+    NUMBER = 258,
+    BTRUE = 259,
+    BFALSE = 260,
+    QUOTED_STRING = 261,
+    UNQUOTED_STRING = 262,
+    SLASH = 263,
+    OPENBRAC = 264,
+    CLOSEBRAC = 265,
+    EOL = 266
+  };
+#endif
+/* Tokens.  */
+#define NUMBER 258
+#define BTRUE 259
+#define BFALSE 260
+#define QUOTED_STRING 261
+#define UNQUOTED_STRING 262
+#define SLASH 263
+#define OPENBRAC 264
+#define CLOSEBRAC 265
+#define EOL 266
+
+/* Value type.  */
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE YYSTYPE;
+union YYSTYPE
+{
+#line 46 "parser.y" /* yacc.c:1909  */
+
+       double  number;
+       int     boolean;
+       char   *string;
+       oconfig_value_t  cv;
+       oconfig_item_t   ci;
+       argument_list_t  al;
+       statement_list_t sl;
+
+#line 86 "parser.h" /* yacc.c:1909  */
+};
+# define YYSTYPE_IS_TRIVIAL 1
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+extern YYSTYPE yylval;
+
+int yyparse (void);
+
+#endif /* !YY_YY_PARSER_H_INCLUDED  */
diff --git a/src/liboconfig/parser.y b/src/liboconfig/parser.y
new file mode 100644 (file)
index 0000000..d91df8c
--- /dev/null
@@ -0,0 +1,267 @@
+/**
+ * collectd - src/liboconfig/parser.y
+ * Copyright (C) 2007,2008  Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ */
+
+%{
+#include <stdlib.h>
+#include <string.h>
+#include "oconfig.h"
+#include "aux_types.h"
+
+static char *unquote (const char *orig);
+static int yyerror (const char *s);
+
+/* Lexer variables */
+extern int yylineno;
+extern char *yytext;
+
+extern oconfig_item_t *ci_root;
+extern char           *c_file;
+%}
+
+%start entire_file
+
+%union {
+       double  number;
+       int     boolean;
+       char   *string;
+       oconfig_value_t  cv;
+       oconfig_item_t   ci;
+       argument_list_t  al;
+       statement_list_t sl;
+}
+
+%token <number> NUMBER
+%token <boolean> BTRUE BFALSE
+%token <string> QUOTED_STRING UNQUOTED_STRING
+%token SLASH OPENBRAC CLOSEBRAC EOL
+
+%type <string> string
+%type <string> identifier
+/* arguments */
+%type <cv> argument
+%type <al> argument_list
+/* blocks */
+%type <ci> block_begin
+%type <ci> block
+%type <string> block_end
+/* statements */
+%type <ci> option
+%type <ci> statement
+%type <sl> statement_list
+%type <ci> entire_file
+
+/* pass an verbose, specific error message to yyerror() */
+%error-verbose
+
+%%
+string:
+       QUOTED_STRING           {$$ = unquote ($1);}
+       | UNQUOTED_STRING       {$$ = strdup ($1);}
+       ;
+
+argument:
+       NUMBER                  {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
+       | BTRUE                 {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
+       | BFALSE                {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
+       | string                {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
+       ;
+
+argument_list:
+       argument_list argument
+       {
+        $$ = $1;
+        $$.argument_num++;
+        $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
+        $$.argument[$$.argument_num-1] = $2;
+       }
+       | argument
+       {
+        $$.argument = malloc (sizeof (oconfig_value_t));
+        $$.argument[0] = $1;
+        $$.argument_num = 1;
+       }
+       ;
+
+identifier:
+       UNQUOTED_STRING                 {$$ = strdup ($1);}
+       ;
+
+option:
+       identifier argument_list EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $1;
+        $$.values = $2.argument;
+        $$.values_num = $2.argument_num;
+       }
+       ;
+
+block_begin:
+       OPENBRAC identifier CLOSEBRAC EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $2;
+       }
+       |
+       OPENBRAC identifier argument_list CLOSEBRAC EOL
+       {
+        memset (&$$, '\0', sizeof ($$));
+        $$.key = $2;
+        $$.values = $3.argument;
+        $$.values_num = $3.argument_num;
+       }
+       ;
+
+block_end:
+       OPENBRAC SLASH identifier CLOSEBRAC EOL
+       {
+        $$ = $3;
+       }
+       ;
+
+block:
+       block_begin statement_list block_end
+       {
+        if (strcmp ($1.key, $3) != 0)
+        {
+               printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
+               yyerror ("Block not closed..\n");
+               exit (1);
+        }
+        free ($3); $3 = NULL;
+        $$ = $1;
+        $$.children = $2.statement;
+        $$.children_num = $2.statement_num;
+       }
+       | block_begin block_end
+       {
+        if (strcmp ($1.key, $2) != 0)
+        {
+               printf ("block_begin = %s; block_end = %s;\n", $1.key, $2);
+               yyerror ("Block not closed..\n");
+               exit (1);
+        }
+        free ($2); $2 = NULL;
+        $$ = $1;
+        $$.children = NULL;
+        $$.children_num = 0;
+       }
+       ;
+
+statement:
+       option          {$$ = $1;}
+       | block         {$$ = $1;}
+       | EOL           {$$.values_num = 0;}
+       ;
+
+statement_list:
+       statement_list statement
+       {
+        $$ = $1;
+        if (($2.values_num > 0) || ($2.children_num > 0))
+        {
+                $$.statement_num++;
+                $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
+                $$.statement[$$.statement_num-1] = $2;
+        }
+       }
+       | statement
+       {
+        if (($1.values_num > 0) || ($1.children_num > 0))
+        {
+                $$.statement = malloc (sizeof (oconfig_item_t));
+                $$.statement[0] = $1;
+                $$.statement_num = 1;
+        }
+        else
+        {
+               $$.statement = NULL;
+               $$.statement_num = 0;
+        }
+       }
+       ;
+
+entire_file:
+       statement_list
+       {
+        ci_root = malloc (sizeof (oconfig_item_t));
+        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root->children = $1.statement;
+        ci_root->children_num = $1.statement_num;
+       }
+       | /* epsilon */
+       {
+        ci_root = malloc (sizeof (oconfig_item_t));
+        memset (ci_root, '\0', sizeof (oconfig_item_t));
+        ci_root->children = NULL;
+        ci_root->children_num = 0;
+       }
+       ;
+
+%%
+static int yyerror (const char *s)
+{
+       char *text;
+
+       if (*yytext == '\n')
+               text = "<newline>";
+       else
+               text = yytext;
+
+       fprintf (stderr, "Parse error in file `%s', line %i near `%s': %s\n",
+               c_file, yylineno, text, s);
+       return (-1);
+} /* int yyerror */
+
+static char *unquote (const char *orig)
+{
+       char *ret = strdup (orig);
+       int len;
+       int i;
+
+       if (ret == NULL)
+               return (NULL);
+
+       len = strlen (ret);
+
+       if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
+               return (ret);
+
+       len -= 2;
+       memmove (ret, ret + 1, len);
+       ret[len] = '\0';
+
+       for (i = 0; i < len; i++)
+       {
+               if (ret[i] == '\\')
+               {
+                       memmove (ret + i, ret + (i + 1), len - i);
+                       len--;
+               }
+       }
+
+       return (ret);
+} /* char *unquote */
diff --git a/src/liboconfig/scanner.c b/src/liboconfig/scanner.c
new file mode 100644 (file)
index 0000000..bf5c53a
--- /dev/null
@@ -0,0 +1,4829 @@
+
+#line 3 "scanner.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 39
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin  )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern yy_size_t yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex. 
+     *       One obvious solution it to make yy_act a global. I tried that, and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    #define YY_LINENO_REWIND_TO(dst) \
+            do {\
+                const char *p;\
+                for ( p = yy_cp-1; p >= (dst); --p)\
+                    if ( *p == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               *yy_cp = (yy_hold_char); \
+               YY_RESTORE_YY_MORE_OFFSET \
+               (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr)  )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       yy_size_t yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+    
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+
+       };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+                          ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+                          : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static yy_size_t yy_n_chars;           /* number of characters read into yy_ch_buf */
+yy_size_t yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0;                /* whether we need to initialize */
+static int yy_start = 0;       /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file  );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+void yy_delete_buffer (YY_BUFFER_STATE b  );
+void yy_flush_buffer (YY_BUFFER_STATE b  );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len  );
+
+void *yyalloc (yy_size_t  );
+void *yyrealloc (void *,yy_size_t  );
+void yyfree (void *  );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer(yyin,YY_BUF_SIZE ); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[]  );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       (yytext_ptr) = yy_bp; \
+       yyleng = (size_t) (yy_cp - yy_bp); \
+       (yy_hold_char) = *yy_cp; \
+       *yy_cp = '\0'; \
+       (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 19
+#define YY_END_OF_BUFFER 20
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+       {
+       flex_int32_t yy_verify;
+       flex_int32_t yy_nxt;
+       };
+static yyconst flex_int16_t yy_accept[1519] =
+    {   0,
+        0,    0,    0,    0,   20,   19,    1,    4,   19,   19,
+        2,   19,   19,    5,   12,   12,   12,   12,   19,    6,
+        7,   14,   14,   19,   19,   14,   14,   14,   14,   14,
+       19,   16,    4,    0,   13,    0,    2,    0,   12,   12,
+        0,   12,   12,    0,   14,   14,   14,   12,   12,   12,
+       12,   11,    0,    0,    3,    0,   14,    9,   14,    8,
+       14,   14,    0,   18,    0,   16,    0,   15,    0,    0,
+       12,   12,   12,   12,   12,   12,   14,    0,   11,   12,
+       12,   11,   11,   11,   11,   11,    0,    0,    0,   14,
+       14,    0,   17,    0,   15,    0,    0,   12,   12,   12,
+
+       12,   12,   14,    0,    0,   11,   11,   11,   11,   11,
+        0,   11,    0,   11,   11,   11,   11,    0,    0,    0,
+        0,    0,    0,    0,    0,   11,   14,   17,   12,    0,
+        0,    0,    0,   12,   12,    0,    0,   11,   11,    0,
+       11,   11,   11,   11,    0,    0,    0,    0,   11,   11,
+       11,   11,   11,   11,   11,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+        0,    0,    0,    0,   11,    0,   11,    0,   11,   11,
+
+       11,   11,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   11,   11,   11,   10,   10,   10,   10,    0,
+        0,   11,   11,    0,   11,   11,   11,   11,   11,   11,
+        0,   11,   11,   11,   11,    0,    0,    0,    0,    0,
+        0,    0,    0,   11,   11,   11,   11,   11,   11,   11,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   11,   11,   11,
+       11,    0,   10,   10,   10,    0,    0,    0,   11,   11,
+
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,    0,    0,    0,
+        0,    0,    0,    0,    0,   11,    0,   11,    0,   11,
+       11,   11,   11,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   11,   11,   11,   11,   11,   10,
+       10,   10,    0,    0,   11,   11,    0,   11,   11,   11,
+       11,   11,   11,    0,   11,   11,   11,   11,   11,   11,
+        0,   11,   11,   11,   11,   11,   11,   11,   11,    0,
+
+        0,    0,    0,    0,    0,    0,    0,   11,   11,   11,
+       11,   11,   11,   11,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   11,   11,   11,   11,   11,   11,   10,   10,
+       10,   10,    0,    0,    0,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,    0,   11,   11,   11,    0,    0,    0,    0,    0,
+
+        0,    0,    0,   11,    0,   11,    0,   11,   11,   11,
+       11,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   11,   10,   10,   10,   10,   10,    0,
+        0,   11,   11,    0,   11,   11,   11,   11,   11,   11,
+        0,   11,   11,   11,   11,   11,   11,    0,   11,   11,
+       11,   11,   11,   11,    0,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,    0,    0,    0,    0,
+
+        0,    0,    0,    0,   11,   11,   11,   11,   11,   11,
+       11,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+       10,   10,   10,   10,   10,   10,    0,    0,    0,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+
+       11,   11,   11,   11,   11,   11,    0,   11,   11,   11,
+        0,    0,    0,    0,    0,    0,    0,    0,   11,    0,
+       11,    0,   11,   11,   11,   11,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   10,    0,
+        0,    0,    0,    0,   11,    0,   11,    0,   11,   11,
+       11,   11,   11,   11,    0,   11,   11,   11,   11,   11,
+
+       11,    0,   11,   11,   11,   11,   11,   11,    0,   11,
+       11,   11,   11,   11,   11,    0,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,    0,    0,    0,    0,    0,    0,    0,    0,
+       11,   11,   11,   11,   11,   11,   11,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,    0,   11,   11,   11,    0,    0,    0,    0,    0,
+        0,    0,    0,   11,    0,   11,    0,   11,   11,   11,
+       11,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   11,   11,    0,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,    0,    0,    0,    0,    0,    0,    0,    0,   11,
+       11,   11,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,    0,   11,
+       11,   11,    0,    0,    0,    0,    0,    0,    0,    0,
+       11,   11,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,    0,
+        0,    0,    0,   11,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,    0,   11,   11,   11,    0,    0,
+        0,    0,   11,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,    0,   11,   11,   11,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   11,   11,   11,
+
+       11,   11,   11,   11,   11,   11,   11,   11,   11,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+       11,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   11,   11,   11,   11,   11,   11,   11,
+       11,   11,   11,   11,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,   11,   11,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0
+    } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    2,    2,    3,
+        1,    1,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    5,    6,    1,    1,    1,    1,    1,
+        1,    1,    7,    1,    7,    8,    9,   10,   11,   12,
+       13,   14,   15,   16,   17,   18,   18,   19,    1,   20,
+        1,   21,    1,    1,   22,   22,   22,   22,   23,   22,
+       24,   24,   24,   24,   24,   24,   24,   24,   24,   24,
+       24,   24,   24,   24,   24,   24,   24,   25,   24,   24,
+       26,   27,   28,    1,   24,    1,   29,   22,   22,   22,
+
+       30,   31,   24,   24,   24,   24,   24,   32,   24,   33,
+       34,   24,   24,   35,   36,   37,   38,   24,   24,   25,
+       39,   24,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst flex_int32_t yy_meta[40] =
+    {   0,
+        1,    1,    2,    1,    1,    1,    1,    3,    1,    4,
+        5,    5,    5,    5,    5,    6,    6,    6,    7,    1,
+        1,    8,    9,   10,   10,    1,    1,   11,    8,    9,
+        8,   10,   10,   10,   10,   10,   10,   10,   10
+    } ;
+
+static yyconst flex_int16_t yy_base[2140] =
+    {   0,
+        0,    0, 4302, 4301, 4302, 9978, 9978, 9978, 4298,   35,
+        0, 4292,    0, 9978,   55,   85,  101,  110, 4280, 9978,
+     9978,  118,    0, 4279,   38, 4263, 4257,   12, 4255, 4259,
+       48, 4283, 9978,   49, 9978,   43,    0,    0, 4266,   21,
+       38,  129,  159, 4250,  169,    0,  178,  210,    0,   39,
+     4260,  219, 4248, 4247, 9978, 4262, 4230,    0, 4230,    0,
+     4222, 4210,   54, 9978,   57, 4243,   77, 9978,  235, 4237,
+      231,  235,  258,  279,  287,  317,  327, 4224,  336,    0,
+     4232,  119,  360,  384,  406,  236, 4220, 4219,  412, 4189,
+     4194,   78, 9978,  280,  151,    0,   96,    0,    0,  181,
+
+      436,  446, 4204, 4203, 4202,  237,  456,  480,  502,  238,
+      194, 4199,  508,  532,    0,  235,  259, 4198, 4187,  554,
+      567,  588,  612,  634,  631, 4182, 4170,  255,    0, 4191,
+     4190,  652, 4189, 4175, 4174, 4173, 4145,  661, 4144,  683,
+      707,    0,  297,  361, 4154, 4153,  731, 4152, 4138,  385,
+      742,  766,  788,  457,  481, 4137, 4126, 4121,  785,  806,
+      830,  852,  849,  345,  258,  868,  892,    0,  344,  868,
+      368,  398, 4131, 4130, 4129, 4117, 4114, 4113,  533,  916,
+      940,  962,  570, 4102,  571,  970,  994, 1016,  572,  573,
+      421, 4102, 4101, 4100, 4088,  426, 4087, 1022, 1046,    0,
+
+      464,  589, 4084, 4083, 1068,  268, 1090, 1114,    0,  488,
+     1127, 4083, 4078, 1148, 4077,  508, 1149, 1170, 1194, 1216,
+     1213, 1225,    0, 1244,    0, 4065, 4064, 1253, 4063, 4060,
+     4059, 1263, 4048, 1285, 1309,    0,  516,  613, 4037, 4036,
+     1331, 1355,    0,  540,  708, 4046, 4045, 1379, 4044, 4041,
+     4040, 1390, 4029, 4013,  732, 1401, 1425, 1447,  767,  786,
+     4012, 4011, 4010, 1444, 1465, 1489, 1511, 1508,  633, 1520,
+     1541, 1565, 1587, 1522, 1584,  602, 4020, 4017, 4016,  661,
+      626,  683, 1603, 1627,    0,  637, 1603,    0,    0, 1649,
+        0,  640, 3994, 3983, 3982, 3981, 3980, 3979,  807, 1660,
+
+     1684, 1706,  831, 3976,  893, 1714, 1738, 1760,  917,  941,
+     3975,  960, 1768, 1792, 1814,  995, 1047,  675, 3975, 3970,
+     3969,  697, 3968, 3967, 3966, 3952,  721, 3951, 1820, 1844,
+        0,  750, 1115, 3940, 3929, 1866, 1022, 1888, 1912,    0,
+      774, 1925, 1090, 1119, 1944, 1968,    0,  790, 1944, 3939,
+     3938, 1992, 3937, 3936, 3933, 2003, 3932, 1120, 2004, 2025,
+     2049, 2071, 2068, 2080,    0,    0,    0, 2099,  799,    0,
+     2108,    0, 3905, 3904, 2117, 3903, 2139, 2163,    0,  814,
+     1132, 3902, 3898, 2185, 2209,    0,  838, 1133, 3897, 3881,
+     2231, 2255,    0,  853, 1171, 3880, 3879, 2277, 3878, 3885,
+
+     3884, 2289, 3869, 3868, 3867, 2300, 3866, 3852, 1195, 2311,
+     2335, 2357, 1226, 1227, 3851, 3834, 3833, 2354, 2375, 2399,
+     2421, 2418, 1148, 2430, 2451, 2475, 2497, 2432, 2494, 1219,
+     2506, 2527, 2551, 2573, 2508, 2570,  862, 3843, 3839, 3838,
+      882, 3825, 3824, 3823, 1220,  906, 1221, 2589, 2613,    0,
+      924, 2589,    0,    0,    0,    0,  948, 9978,    0,    0,
+     2635,    0, 3811, 3810, 3809, 1310, 2646, 2670, 2692, 1356,
+     3808, 1380, 2700, 2724, 2746, 1402, 1426, 3795, 1445, 2754,
+     2778, 2800, 1466, 1490, 3794, 1521, 2808, 2832, 2854, 1523,
+     1524,  978, 3793, 3790, 3789, 1008, 3783, 3782, 3781, 1036,
+
+     3777, 3776, 3762, 3749, 1060, 3736, 2860, 2884,    0, 1071,
+     1525, 3719, 3718, 2906, 1223, 2928, 2952,    0, 1076, 2965,
+     1224, 1263, 2984, 3008,    0, 1098, 2984, 1285, 1331, 3030,
+     3054,    0, 1153, 3067, 1518, 1519, 3086, 1546, 3728, 3725,
+     3107, 3724, 3707, 3706, 3118, 3705, 1608, 3119, 3140, 3164,
+     3186, 3183, 3195, 9978,    0,    0,    0, 3214, 1162, 3690,
+     3689, 3223, 3675, 3245, 3269,    0, 1178, 1526, 3673, 3660,
+     3291, 3315,    0, 1202, 1661, 3643, 3642, 3337, 3361,    0,
+     1271, 1685, 3641, 3638, 3383, 3407,    0, 1293, 1704,    0,
+     3429,    0, 3637, 3620, 3438, 3619, 3629, 3625, 3450, 3624,
+
+     3610, 3608, 3461, 3595, 3567, 1739, 3472, 3496, 3518, 1758,
+     1793, 3566, 3565, 3562, 3515, 3536, 3560, 3582, 3579, 1820,
+     3591, 3612, 3636, 3658, 3593, 3655, 1825, 3667, 3688, 3712,
+     3734, 3669, 3731, 1888, 3743, 3764, 3788, 3810, 3745, 3807,
+     1317, 1893, 1917, 1918, 1345, 3572, 3555, 3554, 1369, 3553,
+     3549, 3548, 1919, 1415, 1920, 3826, 3850,    0, 1433, 3826,
+        0,    0,    0,    0, 1449, 9978, 3523, 3522, 3872, 1969,
+     3896, 3920, 3942, 2026, 3521, 2050, 3950, 3974, 3996, 2081,
+     2082, 3520, 2083, 4004, 4028, 4050, 2084, 2085, 3519, 2086,
+     4058, 4082, 4104, 2087, 2164, 3518, 2210, 4112, 4136, 4158,
+
+     2256, 2290,    0,    0, 4164,    0, 1452, 3516, 3505, 3503,
+     1479, 3513, 3512, 3509, 1503, 3508, 3492, 3491, 3479, 1556,
+     3478, 4173, 4197,    0, 1573, 2312, 3474, 3473, 4219, 1973,
+     4241, 4265,    0, 1588, 4278, 2003, 2079, 4297, 4321,    0,
+     1591, 4297, 2117, 2139, 4343, 4367,    0, 1612, 4380, 2185,
+     2231, 4399, 4423,    0, 1635, 4399, 3453, 4445, 3442, 2316,
+     2356, 4464, 2380, 3451, 3427, 4485, 3420, 3419, 3402, 4496,
+     3401, 2420, 4497, 4518, 4542, 4564, 4561, 4573, 9978, 3389,
+     2355, 4594, 4618, 4640,    0, 2433, 3385,    0, 4648,    0,
+     1668, 2434, 3384, 3370,    0, 4672,    0, 1692, 2435, 3363,
+
+     3362,    0, 4696,    0, 1722, 2436, 3339, 3338,    0, 4720,
+        0, 1746, 2437, 3324, 3317,    0, 4744,    0, 1776, 2476,
+        0,    0,    0, 4766, 1806,    0, 4775,    0, 3293, 3292,
+     4784, 3278, 3282, 3281, 4796, 3258, 3257, 3242, 4807, 3236,
+     3224, 2507, 4818, 4842, 4864, 2509, 2510, 3201, 3187, 4870,
+     4575, 4894, 4918, 4940, 4937, 2502, 4949, 4970, 4994, 5016,
+     4951, 5013, 2504, 5025, 5046, 5070, 5092, 5027, 5089, 2505,
+     5101, 5122, 5146, 5168, 5103, 5165, 2532, 5177, 5198, 5222,
+     5244, 5179, 5241, 3177, 3157, 5260, 3156, 1829, 2594, 2651,
+     2705, 1858, 3153, 3152, 3137, 1875, 3131, 3105, 3104, 2759,
+
+     1880, 2813, 5279, 5303,    0, 1897, 5279, 3087, 1939, 3075,
+     3055, 5327,    0, 1952, 2512,    0, 3032,    0, 2647, 3031,
+        0, 2690, 3016,    0, 2744, 3010,    0, 2798, 3009,    0,
+     2885,    0,    0,    0,    0, 1977, 9978,    0,    0, 5349,
+        0, 2008, 2986, 2985, 2972, 2017, 2978, 2977, 2947, 2039,
+     2941, 2940, 2904, 2886, 2063, 2868,    0, 5360,    0, 2125,
+     2953, 2862, 2968, 5384, 5408, 5430, 2852, 2969, 2860,    0,
+     5438,    0, 2147, 5451, 2928, 2989,    0, 5472,    0, 2171,
+     5485, 3030, 3035,    0, 5506,    0, 2193, 5519, 3059, 3060,
+        0, 5540,    0, 2217, 5553, 3061, 3062,    0, 5574,    0,
+
+     2239, 5587, 2832, 2831, 2825, 5606, 2269, 2824, 5625, 2808,
+     3088, 3118, 5644, 3121, 2821, 2820, 5665, 2797, 2791, 2790,
+     5676, 2774, 3145, 5677, 5698, 5722, 5744, 5741, 5753, 2767,
+     2766, 5774, 2743, 2726,    0, 9978, 2970,    0, 2725,    0,
+     2709,    0, 2702,    0, 2701,    0, 2678,    0, 9978,    0,
+        0,    0, 5783, 2326,    0, 5792,    0, 2672, 2671, 5801,
+     2648, 2626, 2625, 5813, 2602, 2601, 2588, 5824, 2564, 2552,
+        0, 2971, 2529, 2349, 2528, 2500, 5835,    0, 2360, 3196,
+     2468, 3188, 2450, 5755, 3189, 2444, 5848, 3190, 2443, 5851,
+     3191, 2429, 5852, 3193, 2422, 5853, 2419, 2392, 2391, 2368,
+
+     2367, 2328, 2327, 2304, 5872, 2255, 2363, 3194, 3223, 3245,
+     2390, 2268, 2250, 2244, 2413, 2243, 2229, 2228, 3250, 2465,
+     3291,    0, 5893,    0, 2483, 5906, 2542, 2222, 2204, 2198,
+     2186,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0, 2559, 9978,    0,    0, 5925,    0, 2574, 2172,
+     2171, 2165, 2583, 2158, 2152, 2151, 2604, 2136, 2130, 2129,
+     2078,    0, 2062, 2044, 5936, 2038, 2011, 1961, 1943, 3316,
+     1937, 3337, 1936, 3342, 1904, 3383, 1881, 3388, 1880, 3477,
+     1865, 1844, 1843, 1837, 1836, 5945, 2627, 1813, 5964, 1812,
+     3517, 3541, 5983, 3581, 1812, 1805, 6004, 1788, 1787, 1781,
+
+     6015, 1780, 3583, 1737, 6016, 1751, 1734, 6037, 1733,    0,
+     9978, 9978, 9978, 9978, 9978, 9978, 9978,    0,    0,    0,
+     6046, 2661,    0, 6055,    0, 1716, 1715, 6064, 1692, 1697,
+     1680, 6076, 1679,    0, 2684, 1673, 1646, 1640, 1628, 1596,
+     1595, 1582, 1558, 1557, 1534, 1533, 1507, 1482, 1464, 1458,
+     1443, 1418, 1401, 1400, 6085, 1394, 2709, 3585, 3586, 3587,
+     2738, 1375, 1374, 1368, 2769, 1350, 1344, 1343, 3589, 1309,
+     2792, 1328, 1322, 1304,    0,    0,    0,    0, 2817, 9978,
+        0,    0, 6104,    0, 2840, 1287, 1286, 1271, 2874, 1276,
+     1275, 1242, 9978, 1229, 1228, 6115, 1207, 1169, 1163, 1126,
+
+     1125, 1122, 1121, 1089, 1083, 1082, 1067, 1046, 6124, 2898,
+     1045, 6143, 1039, 3617, 3657, 6162, 3659, 1041, 1035, 6183,
+     1034,  994, 1002,  996, 6192,  979, 9978,    0,    0,    0,
+     6202, 2920,    0, 6211,    0,  978,  972, 6220,  971, 2915,
+      959,  953,  936,  915,  909,  891,  885,  867,  861,  860,
+      847, 6230,  823, 2936, 3661, 3662, 3663, 2999,  825,  819,
+      779,  742, 3016,  750,  744,  743,    0,    0,    0,    0,
+     3039, 9978,    0,    0, 6249,    0, 3075,  716,  715,  709,
+     3665, 3693, 6258, 3733,  682,  676,  675,  660, 6277, 3098,
+      654, 6296,  653, 3735, 3737, 6315, 3738,    0, 6334,    0,
+
+     9978,    0,    0,    0, 6343, 3131,    0, 6352,    0, 3149,
+     3739, 3741, 3769,  623,  605,  587,  581,  566,  565,  560,
+      559, 6361,  546, 3172, 3831, 3877, 3901,    0,    0, 6380,
+        0,    0,    0,    0,    0, 3231, 9978,    0,    0, 6389,
+        0,  545, 6398,  532,  531,  525,  507,  501, 6417, 3283,
+      500, 6436,  480,    0,    0,    0, 6455, 3305, 9978,    0,
+        0,    0, 6464, 3329,  479,  473, 6473,  456,  455,  449,
+      417,  411,  384,  383,  377,  360, 6492,  359,    0,    0,
+        0,    0, 3254, 9978,    0,    0,    0,    0, 3346, 9978,
+      353,  336,  335, 6511, 3375,  308,  280,   24,   30, 6530,
+
+     3421, 9978, 9978,   36,   81,  121,  122,  127,  129,  191,
+      219,  231,  235,  236,  251,  252,  256, 9978, 6558, 6569,
+     6580, 6589, 6592, 6595, 6602, 6611, 6622, 6630, 6633, 6639,
+     6648, 6657, 6663, 6670, 6676, 6682, 6688, 6691, 6694, 6700,
+     6707, 6713, 6716, 6722, 6728, 6735, 6744, 6748, 6751, 6757,
+     6763, 6770, 6774, 6777, 6784, 6790, 6796, 6803, 6811, 6814,
+     6821, 6824, 6828, 6830, 6836, 6843, 6849, 6856, 6862, 6866,
+     6868, 6871, 6877, 6883, 6889, 6898, 6902, 6905, 6914, 6922,
+     6925, 6928, 6932, 6936, 6942, 6948, 6954, 6961, 6965, 6969,
+     6973, 6976, 6983, 6989, 6995, 7002, 7010, 7019, 7027, 7031,
+
+     7033, 7036, 7044, 7047, 7050, 7052, 7055, 7059, 7065, 7072,
+     7078, 7085, 7091, 7098, 7104, 7108, 7112, 7114, 7118, 7122,
+     7124, 7127, 7133, 7139, 7145, 7153, 7162, 7166, 7170, 7174,
+     7177, 7186, 7194, 7197, 7200, 7203, 7206, 7209, 7215, 7221,
+     7227, 7233, 7239, 7243, 7248, 7252, 7256, 7260, 7263, 7270,
+     7276, 7282, 7289, 7297, 7306, 7314, 7323, 7331, 7335, 7339,
+     7341, 7345, 7349, 7351, 7354, 7362, 7365, 7368, 7371, 7374,
+     7380, 7387, 7393, 7400, 7406, 7413, 7419, 7426, 7431, 7434,
+     7438, 7442, 7446, 7450, 7452, 7456, 7460, 7462, 7465, 7471,
+     7477, 7483, 7491, 7499, 7507, 7515, 7524, 7528, 7532, 7536,
+
+     7539, 7548, 7556, 7559, 7562, 7565, 7571, 7577, 7583, 7589,
+     7595, 7601, 7604, 7607, 7611, 7616, 7620, 7624, 7628, 7631,
+     7638, 7644, 7650, 7657, 7665, 7674, 7682, 7691, 7699, 7708,
+     7715, 7718, 7726, 7734, 7738, 7742, 7744, 7748, 7752, 7754,
+     7757, 7765, 7768, 7775, 7781, 7788, 7794, 7801, 7807, 7814,
+     7820, 7827, 7833, 7836, 7839, 7841, 7844, 7848, 7852, 7856,
+     7860, 7862, 7866, 7870, 7872, 7875, 7881, 7887, 7893, 7901,
+     7909, 7917, 7925, 7933, 7941, 7949, 7958, 7962, 7966, 7970,
+     7973, 7982, 7990, 7997, 8003, 8009, 8015, 8021, 8027, 8033,
+     8039, 8045, 8051, 8057, 8063, 8069, 8072, 8075, 8078, 8081,
+
+     8084, 8088, 8093, 8097, 8101, 8105, 8108, 8115, 8121, 8128,
+     8136, 8145, 8153, 8162, 8170, 8179, 8187, 8196, 8204, 8212,
+     8220, 8227, 8230, 8238, 8246, 8250, 8254, 8256, 8260, 8264,
+     8266, 8269, 8277, 8280, 8286, 8292, 8298, 8304, 8310, 8316,
+     8322, 8328, 8334, 8340, 8346, 8352, 8358, 8361, 8364, 8367,
+     8369, 8372, 8376, 8380, 8384, 8388, 8390, 8394, 8398, 8400,
+     8403, 8409, 8415, 8422, 8428, 8436, 8444, 8450, 8458, 8464,
+     8472, 8478, 8486, 8492, 8500, 8506, 8514, 8522, 8530, 8538,
+     8546, 8554, 8563, 8567, 8571, 8575, 8578, 8587, 8596, 8600,
+     8603, 8609, 8615, 8621, 8627, 8633, 8639, 8645, 8651, 8654,
+
+     8657, 8660, 8663, 8666, 8670, 8675, 8679, 8683, 8687, 8690,
+     8696, 8702, 8705, 8711, 8717, 8725, 8733, 8741, 8749, 8757,
+     8765, 8773, 8781, 8789, 8797, 8805, 8813, 8821, 8829, 8837,
+     8844, 8847, 8855, 8863, 8867, 8871, 8873, 8877, 8881, 8883,
+     8886, 8894, 8900, 8904, 8908, 8910, 8916, 8922, 8928, 8934,
+     8940, 8946, 8952, 8955, 8958, 8961, 8963, 8966, 8970, 8974,
+     8978, 8982, 8984, 8988, 8992, 8994, 9001, 9005, 9008, 9014,
+     9022, 9030, 9038, 9046, 9054, 9062, 9070, 9078, 9086, 9094,
+     9102, 9110, 9118, 9127, 9131, 9135, 9139, 9142, 9150, 9159,
+     9163, 9166, 9172, 9175, 9178, 9181, 9184, 9187, 9191, 9196,
+
+     9200, 9203, 9209, 9213, 9215, 9223, 9231, 9239, 9247, 9255,
+     9263, 9271, 9279, 9287, 9295, 9303, 9310, 9313, 9321, 9325,
+     9327, 9331, 9333, 9341, 9345, 9347, 9350, 9353, 9356, 9358,
+     9361, 9365, 9369, 9372, 9376, 9379, 9387, 9395, 9403, 9411,
+     9419, 9427, 9435, 9444, 9448, 9451, 9459, 9463, 9467, 9470,
+     9473, 9476, 9479, 9482, 9486, 9490, 9494, 9496, 9504, 9512,
+     9520, 9528, 9535, 9538, 9546, 9550, 9551, 9554, 9558, 9561,
+     9564, 9567, 9569, 9572, 9576, 9584, 9592, 9600, 9608, 9616,
+     9624, 9632, 9640, 9648, 9651, 9654, 9657, 9660, 9663, 9666,
+     9668, 9671, 9679, 9687, 9695, 9703, 9711, 9718, 9721, 9729,
+
+     9732, 9735, 9738, 9741, 9744, 9747, 9750, 9758, 9766, 9774,
+     9782, 9790, 9798, 9806, 9809, 9812, 9815, 9818, 9821, 9824,
+     9832, 9840, 9848, 9856, 9864, 9872, 9880, 9888, 9891, 9894,
+     9902, 9910, 9918, 9926, 9934, 9942, 9950, 9958, 9966
+    } ;
+
+static yyconst flex_int16_t yy_def[2140] =
+    {   0,
+     1518,    1, 1519, 1519, 1518, 1518, 1518, 1518, 1518, 1520,
+     1521, 1522, 1523, 1518, 1518,   15,   16,   17, 1518, 1518,
+     1518,   17, 1524, 1525, 1518,   22, 1524, 1524, 1524, 1524,
+     1526, 1518, 1518, 1520, 1518, 1527, 1521, 1523, 1522, 1523,
+     1528, 1518,   42, 1529,   42, 1524, 1518,   42,   48,   48,
+       43, 1518, 1530, 1518, 1518, 1518,   45, 1524, 1524, 1524,
+     1524, 1524, 1526, 1518, 1531, 1518, 1520, 1518, 1520, 1518,
+     1523, 1532, 1518,   73, 1518,   75,   75, 1533, 1518,   47,
+       76, 1534, 1518, 1518,   84, 1534, 1535, 1536, 1518, 1524,
+     1524, 1526, 1518, 1526, 1520, 1537, 1538,   74,   74,   74,
+
+     1524,  101, 1524, 1539, 1540, 1541, 1518, 1518,  108, 1541,
+     1542, 1543, 1518, 1518,  114,  114, 1543, 1544, 1545, 1518,
+     1546, 1518, 1518,  123, 1546, 1518, 1524, 1526, 1537, 1518,
+     1547, 1518, 1548,  101,  102, 1549, 1550, 1518, 1551, 1518,
+     1518,  141,  141, 1551, 1518, 1552, 1518, 1553, 1554, 1555,
+     1518, 1518,  152, 1555, 1554, 1518, 1556, 1557, 1558, 1518,
+     1518,  161, 1558, 1559, 1560, 1518, 1518,  167,  167, 1560,
+     1561, 1562, 1548, 1548, 1563, 1518, 1564, 1565, 1566, 1518,
+     1518,  181, 1566, 1567, 1568, 1518, 1518,  187, 1568, 1567,
+     1569, 1553, 1553, 1570, 1518, 1571, 1572, 1518, 1518,  199,
+
+      199, 1572, 1573, 1574, 1518, 1575, 1518, 1518,  208,  208,
+     1575, 1518, 1576, 1518, 1577, 1578, 1579, 1518, 1518,  219,
+     1579, 1578, 1580, 1518, 1581, 1518, 1582, 1518, 1583, 1584,
+     1585, 1518, 1586, 1518, 1518,  235,  235, 1586, 1518, 1587,
+     1518, 1518,  242,  242, 1587, 1518, 1588, 1518, 1589, 1518,
+     1590, 1518, 1591, 1592, 1593, 1518, 1518,  257, 1593, 1592,
+     1518, 1594, 1595, 1596, 1518, 1518,  266, 1596, 1597, 1598,
+     1518, 1518,  272, 1598, 1597, 1599, 1577, 1577, 1600, 1518,
+     1601, 1602, 1518, 1518,  284,  284, 1602, 1603, 1604, 1518,
+     1605, 1606, 1583, 1583, 1607, 1518, 1608, 1609, 1610, 1518,
+
+     1518,  301, 1610, 1611, 1612, 1518, 1518,  307, 1612, 1611,
+     1613, 1614, 1518, 1518,  314, 1614, 1613, 1615, 1616, 1616,
+     1617, 1618, 1619, 1619, 1620, 1518, 1621, 1622, 1518, 1518,
+      330,  330, 1622, 1623, 1624, 1518, 1625, 1518, 1518,  339,
+      339, 1625, 1518, 1626, 1518, 1518,  346,  346, 1626, 1518,
+     1627, 1518, 1628, 1518, 1629, 1518, 1630, 1631, 1632, 1518,
+     1518,  361, 1632, 1631, 1633, 1634, 1635, 1518,  368, 1636,
+     1518, 1637, 1638, 1639, 1518, 1640, 1518, 1518,  378,  378,
+     1640, 1518, 1641, 1518, 1518,  385,  385, 1641, 1518, 1642,
+     1518, 1518,  392,  392, 1642, 1518, 1643, 1518, 1644, 1518,
+
+     1645, 1518, 1646, 1518, 1647, 1518, 1648, 1649, 1650, 1518,
+     1518,  411, 1650, 1649, 1518, 1651, 1652, 1653, 1518, 1518,
+      420, 1653, 1654, 1655, 1518, 1518,  426, 1655, 1654, 1656,
+     1657, 1518, 1518,  433, 1657, 1656, 1658, 1659, 1659, 1660,
+     1661, 1662, 1662, 1663, 1518, 1664, 1665, 1518, 1518,  449,
+      449, 1665, 1666, 1666, 1666, 1666, 1666, 1518, 1667, 1668,
+     1518, 1669, 1518, 1670, 1671, 1672, 1518, 1518,  468, 1672,
+     1673, 1674, 1518, 1518,  474, 1674, 1673, 1675, 1676, 1518,
+     1518,  481, 1676, 1675, 1677, 1678, 1518, 1518,  488, 1678,
+     1677, 1679, 1680, 1680, 1681, 1682, 1683, 1683, 1684, 1685,
+
+     1686, 1686, 1687, 1518, 1688, 1689, 1518, 1518,  508,  508,
+     1689, 1690, 1691, 1518, 1692, 1518, 1518,  517,  517, 1692,
+     1518, 1693, 1518, 1518,  524,  524, 1693, 1518, 1694, 1518,
+     1518,  531,  531, 1694, 1518, 1695, 1518, 1696, 1518, 1697,
+     1518, 1698, 1518, 1699, 1518, 1700, 1701, 1702, 1518, 1518,
+      550, 1702, 1701, 1518, 1703, 1704, 1705, 1518,  558, 1706,
+     1707, 1518, 1708, 1518, 1518,  565,  565, 1708, 1518, 1709,
+     1518, 1518,  572,  572, 1709, 1518, 1710, 1518, 1518,  579,
+      579, 1710, 1518, 1711, 1518, 1518,  586,  586, 1711, 1712,
+     1518, 1713, 1518, 1714, 1518, 1715, 1518, 1716, 1518, 1717,
+
+     1518, 1718, 1518, 1719, 1720, 1721, 1518, 1518,  608, 1721,
+     1720, 1518, 1722, 1723, 1724, 1518, 1518,  617, 1724, 1725,
+     1726, 1518, 1518,  623, 1726, 1725, 1727, 1728, 1518, 1518,
+      630, 1728, 1727, 1729, 1730, 1518, 1518,  637, 1730, 1729,
+     1731, 1732, 1732, 1733, 1734, 1735, 1735, 1736, 1737, 1738,
+     1738, 1739, 1518, 1740, 1741, 1518, 1518,  657,  657, 1741,
+     1742, 1742, 1742, 1742, 1742, 1518, 1518, 1743, 1518, 1744,
+     1518, 1518,  672, 1744, 1745, 1746, 1518, 1518,  678, 1746,
+     1745, 1747, 1748, 1518, 1518,  685, 1748, 1747, 1749, 1750,
+     1518, 1518,  692, 1750, 1749, 1751, 1752, 1518, 1518,  699,
+
+     1752, 1751, 1753, 1754, 1518, 1755, 1756, 1757, 1757, 1758,
+     1759, 1760, 1760, 1761, 1762, 1763, 1763, 1764, 1518, 1765,
+     1766, 1518, 1518,  723,  723, 1766, 1767, 1768, 1518, 1769,
+     1518, 1518,  732,  732, 1769, 1518, 1770, 1518, 1518,  739,
+      739, 1770, 1518, 1771, 1518, 1518,  746,  746, 1771, 1518,
+     1772, 1518, 1518,  753,  753, 1772, 1773, 1518, 1774, 1518,
+     1775, 1518, 1776, 1518, 1777, 1518, 1778, 1518, 1779, 1518,
+     1780, 1781, 1782, 1518, 1518,  775, 1782, 1781, 1518, 1783,
+     1784, 1518, 1518,  783, 1785, 1784, 1786, 1787, 1518,  789,
+      789, 1786, 1518, 1788, 1789, 1518,  796,  796, 1788, 1518,
+
+     1790, 1791, 1518,  803,  803, 1790, 1518, 1792, 1793, 1518,
+      810,  810, 1792, 1518, 1794, 1795, 1518,  817,  817, 1794,
+     1796, 1797, 1798, 1518,  824, 1799, 1518, 1800, 1518, 1801,
+     1518, 1802, 1518, 1803, 1518, 1804, 1518, 1805, 1518, 1806,
+     1807, 1808, 1518, 1518,  844, 1808, 1807, 1518, 1809, 1518,
+     1810, 1518, 1518,  853, 1810, 1811, 1812, 1518, 1518,  859,
+     1812, 1811, 1813, 1814, 1518, 1518,  866, 1814, 1813, 1815,
+     1816, 1518, 1518,  873, 1816, 1815, 1817, 1818, 1518, 1518,
+      880, 1818, 1817, 1819, 1820, 1518, 1821, 1822, 1823, 1823,
+     1824, 1825, 1826, 1826, 1827, 1828, 1829, 1829, 1830, 1518,
+
+     1831, 1832, 1518, 1518,  904,  904, 1832, 1518, 1833, 1834,
+     1835, 1518,  912,  912, 1834, 1836, 1837, 1838, 1837, 1839,
+     1840, 1839, 1841, 1842, 1841, 1843, 1844, 1843, 1845, 1846,
+     1845, 1847, 1847, 1847, 1847, 1847, 1518, 1848, 1849, 1518,
+     1850, 1851, 1852, 1852, 1853, 1854, 1855, 1855, 1856, 1857,
+     1858, 1858, 1859, 1518, 1860, 1861, 1862, 1518,  958,  958,
+     1861, 1863, 1864, 1518, 1518,  965, 1865, 1864, 1866, 1867,
+     1518,  971,  971, 1866, 1518, 1868, 1869, 1518,  978,  978,
+     1868, 1518, 1870, 1871, 1518,  985,  985, 1870, 1518, 1872,
+     1873, 1518,  992,  992, 1872, 1518, 1874, 1875, 1518,  999,
+
+      999, 1874, 1876, 1877, 1878, 1518, 1006, 1879, 1518, 1880,
+     1518, 1881, 1518, 1882, 1518, 1883, 1518, 1884, 1518, 1885,
+     1518, 1886, 1887, 1888, 1518, 1518, 1026, 1888, 1887, 1518,
+     1889, 1518, 1890, 1891, 1892, 1518, 1891, 1893, 1518, 1894,
+     1518, 1895, 1518, 1896, 1518, 1897, 1518, 1898, 1518, 1899,
+     1900, 1901, 1518, 1053, 1902, 1518, 1903, 1518, 1904, 1518,
+     1905, 1518, 1906, 1518, 1907, 1518, 1908, 1518, 1909, 1910,
+     1911, 1910, 1518, 1912, 1913, 1914, 1518, 1077, 1077, 1913,
+     1915, 1916, 1917, 1916, 1918, 1919, 1918, 1920, 1921, 1920,
+     1922, 1923, 1922, 1924, 1925, 1924, 1926, 1926, 1926, 1926,
+
+     1927, 1518, 1928, 1929, 1518, 1930, 1931, 1932, 1932, 1933,
+     1934, 1935, 1935, 1936, 1937, 1938, 1938, 1939, 1518, 1940,
+     1941, 1942, 1518, 1123, 1123, 1941, 1943, 1944, 1944, 1945,
+     1518, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1953,
+     1953, 1953, 1953, 1518, 1954, 1955, 1518, 1956, 1957, 1958,
+     1958, 1959, 1960, 1961, 1961, 1962, 1963, 1964, 1964, 1965,
+     1518, 1966, 1518, 1967, 1518, 1968, 1969, 1970, 1518, 1969,
+     1971, 1518, 1972, 1518, 1973, 1518, 1974, 1518, 1975, 1518,
+     1976, 1518, 1977, 1978, 1979, 1518, 1186, 1980, 1518, 1981,
+     1518, 1982, 1518, 1983, 1518, 1984, 1518, 1985, 1518, 1986,
+
+     1518, 1987, 1988, 1989, 1988, 1518, 1990, 1518, 1991, 1992,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1993, 1994, 1995,
+     1518, 1221, 1996, 1518, 1997, 1518, 1998, 1518, 1999, 1518,
+     2000, 1518, 2001, 2002, 2003, 1968, 1968, 2004, 1518, 2005,
+     2006, 2007, 2008, 2009, 2010, 2011, 2012, 2012, 2012, 2012,
+     2013, 1518, 2014, 2015, 1518, 2016, 2017, 1983, 1983, 2018,
+     2019, 1985, 1985, 2020, 2021, 1987, 1987, 2022, 1518, 2023,
+     2024, 1991, 1991, 2025, 2026, 2026, 2026, 2026, 2026, 1518,
+     2027, 2028, 1518, 2029, 2030, 1999, 1999, 2031, 2032, 2001,
+     2001, 2033, 1518, 1518, 2034, 1518, 2035, 2036, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 2037, 2038, 2039, 1518, 1309,
+     2040, 1518, 2041, 1518, 2042, 1518, 2043, 1518, 2044, 1518,
+     2045, 2046, 1518, 2047, 1518, 2048, 1518, 2049, 2050, 2051,
+     1518, 1331, 2052, 1518, 2053, 1518, 2054, 1518, 2055, 2056,
+     2035, 2035, 2057, 2058, 2058, 2058, 2058, 2059, 1518, 2060,
+     2061, 1518, 2062, 2063, 2043, 2043, 2064, 2065, 2045, 2045,
+     2066, 1518, 2067, 2048, 2048, 2068, 2069, 2069, 2069, 2069,
+     2069, 1518, 2070, 2071, 1518, 2072, 2073, 2055, 2055, 2074,
+     1518, 2075, 1518, 2076, 1518, 2077, 2078, 2079, 1518, 1389,
+     2080, 1518, 2081, 1518, 2082, 1518, 2083, 2084, 1518, 2085,
+
+     1518, 2086, 2087, 2088, 1518, 1405, 2089, 1518, 2090, 2091,
+     2076, 2076, 2092, 2093, 2093, 2093, 2093, 2094, 1518, 2095,
+     2096, 1518, 2097, 2098, 2083, 2083, 2099, 2100, 2101, 1518,
+     2102, 2103, 2103, 2103, 2103, 2103, 1518, 2104, 2105, 1518,
+     2106, 2107, 1518, 2108, 1518, 2109, 2110, 2111, 1518, 1449,
+     2112, 1518, 2113, 2114, 2115, 2116, 1518, 1457, 1518, 2117,
+     2118, 2119, 1518, 1463, 2120, 2121, 1518, 2122, 2123, 2123,
+     2123, 2123, 2124, 1518, 2125, 2126, 1518, 2127, 2128, 2128,
+     2128, 2128, 2128, 1518, 2129, 2129, 2129, 2129, 2129, 1518,
+     2130, 2131, 2132, 1518, 1494, 1518, 2133, 2134, 2135, 1518,
+
+     1500, 1518, 1518, 2136, 2136, 2136, 2136, 2137, 1518, 2138,
+     2138, 2138, 2138, 2139, 1518, 1518, 1518,    0, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518
+    } ;
+
+static yyconst flex_int16_t yy_nxt[10018] =
+    {   0,
+        6,    7,    8,    9,   10,   11,   12,   13,   14,   15,
+       16,   17,   18,   18,   18,   18,   18,   18,   19,   20,
+       21,   22,   22,   23,   23,   24,   25,    6,   22,   22,
+       26,   23,   27,   28,   23,   23,   29,   23,   30,   35,
+       55,   56,   59,   70,   60,   68,   69,   71,   72,   73,
+       70,  126,   64,   35,   76,   76,   76,  126,   64,   93,
+       94,   36,   41,  126,   42,   42,   42,   42,   42,   42,
+       42,   42,   43,   44,   65,   36,   45,   45,   46,   47,
+       65,   35,   64,   45,   45,   45,   46,   46,   46,   46,
+       46,   46,   46,   46,   48,   48,   48,   48,   48,   48,
+
+       48,   48,   48,   36,   65,  130,  131,  132,  126,   46,
+       49,   49,   49,   49,   49,   50,   51,   51,   51,   51,
+       51,   51,   51,   51,   51, 1518,  111,   45,   45,   45,
+       45,   45,   45,   45,   45,   45,   38,  113,   75,   75,
+       75,   75,   75,   75,   75,   75,   76,   44,  126,  126,
+       77,   77,   46,   46,  126,   35,  126,   77,   77,   77,
+       46,   46,   46,   46,   46,   46,   46,   46,   76,   76,
+       76,   76,   76,   76,   76,   76, 1518,   36,   77,   77,
+       77,   77,   77,   77,   77,   77,   77,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   40,   40,   40,   80,
+
+       80,   46,   46,  145,  146,  147,   80,   80,   80,   46,
+       46,   46,   46,   46,   46,   46,   46,   41,  126,   81,
+       81,   81,   81,   81,   81,   81,   81,   81,   82,   83,
+       84,   85,   85,   85,   85,   85,   85,   95,   97,   35,
+       86,   86,   97, 1518,  111, 1518,  126,   86,   86,   86,
+      149,  149,  149,   70,  113,  140,  140,   70,  126,   64,
+       70,   36,  126,  126,   70,   97,  111,   99,   99,   99,
+       99,   99,  100,   71,   71,   71,  166,  113,  126,  126,
+       70,   65,  128,  126,   64,  126,  207,   70,   71,   71,
+       71,   71,   71,   71,   38,  126,  101,  101,  101,  101,
+
+      101,  101,  101,  101,  102,   44,   65,  126,  103,  103,
+       46,   46,  184,  184,  184,  103,  103,  103,   46,   46,
+       46,   46,   46,   46,   46,   46,  102,  102,  102,  102,
+      102,  102,  102,  102, 1518,  126,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  106,  107,  108,  109,  109,
+      109,  109,  109,  109,  212,  213,  214,  110,  110,  216,
+      216,  216,  126,  126,  110,  110,  110,  111,  111,  114,
+      114,  114,  114,  114,  114,  114,  114,  114,  113,  140,
+      126,  112,  112,  224,  225,  225,  126,  126,  112,  112,
+      112,  111,  196,  115,  115,  115,  115,  115,  116,  117,
+
+      117,  117,  113,  198,  126,  112,  112,  226,  227,  228,
+      126,  126,  112,  112,  112,  117,  117,  117,  117,  117,
+      117,  121,  122,  123,  124,  124,  124,  124,  124,  124,
+      246,  247,  248,  125,  125,  250,  251,  252,  126,  126,
+      125,  125,  125,   38,  126,  134,  134,  134,  134,  134,
+      134,  134,  134,  135,   44,  135,  135,  135,  135,  135,
+      135,  135,  135,  111, 1518,  141,  141,  141,  141,  141,
+      141,  141,  141,  141,  140,  198,  126,  139,  139,  254,
+      254,  254,  126,  126,  139,  139,  139,  111,  111,  142,
+      142,  142,  142,  142,  143,  144,  144,  144,  140,  113,
+
+      126,  139,  139,  269,  269,  269,  126,  126,  139,  139,
+      139,  144,  144,  144,  144,  144,  144,  150,  151,  152,
+      153,  153,  153,  153,  153,  153,  166,  126,  126,  154,
+      154,  304,  304,  304,  126,  126,  154,  154,  154,  111,
+      111,  155,  155,  155,  155,  155,  155,  155,  155,  155,
+      113,  234,  126,  149,  149,  311,  311,  311,  126,  126,
+      149,  149,  149,  159,  160,  161,  162,  162,  162,  162,
+      162,  162,  126,  126,  164,  163,  163, 1518,  196, 1518,
+      111,  126,  163,  163,  163,  166,  126,  126,  234,  241,
+      241,  140,  126,  126,  126,  164,  196,  167,  167,  167,
+
+      167,  167,  167,  167,  167,  167,  166,  198,  126,  165,
+      165,  350,  351,  352,  126,  126,  165,  165,  165,  164,
+      111,  168,  168,  168,  168,  168,  169,  170,  170,  170,
+      166,  234,  126,  165,  165,  354,  355,  356, 1518,  126,
+      165,  165,  165,  170,  170,  170,  170,  170,  170,  166,
+      126,  207,  358,  358,  358,  371,  372,  372,  126,  172,
+      126,  174,  174,  174,  174,  174,  175,  130,  130,  130,
+      179,  180,  181,  182,  182,  182,  182,  182,  182,  166,
+      126,  126,  183,  183,  396,  397,  398,  126,  126,  183,
+      183,  183,  185,  186,  187,  188,  188,  188,  188,  188,
+
+      188,  283,  126,  126,  189,  189,  400,  401,  402,  126,
+      126,  189,  189,  189,  111,  196,  190,  190,  190,  190,
+      190,  190,  190,  190,  190,  140,  241, 1377,  184,  184,
+      404,  405,  406, 1377, 1377,  184,  184,  184,  191,  327,
+      193,  193,  193,  193,  193,  194,  145,  145,  145,  196,
+      329,  199,  199,  199,  199,  199,  199,  199,  199,  199,
+      198, 1363, 1363,  197,  197,  408,  408,  408, 1363,  126,
+      197,  197,  197,  196, 1518,  200,  200,  200,  200,  200,
+      201,  202,  202,  202,  198,  329, 1358,  197,  197,  423,
+      423,  423,  164,  196,  197,  197,  197,  202,  202,  202,
+
+      202,  202,  202,  207,  198,  430,  430,  430,  458,  458,
+      458,  458,  126,  164,  111,  208,  208,  208,  208,  208,
+      208,  208,  208,  208,  207,  377, 1358,  206,  206,  471,
+      471,  471, 1358,  126,  206,  206,  206,  164, 1518,  209,
+      209,  209,  209,  209,  210,  211,  211,  211,  207,  377,
+      126,  206,  206,  478,  478,  478, 1518,  126,  206,  206,
+      206,  211,  211,  211,  211,  211,  211,  207,  485,  485,
+      485,  535,  536,  537,  126,  164,  126,  217,  218,  219,
+      220,  220,  220,  220,  220,  220,  166,  126,  126,  221,
+      221,  539,  540,  541,  126,  126,  221,  221,  221,  164,
+
+      196,  222,  222,  222,  222,  222,  222,  222,  222,  222,
+      166,  384,  126,  216,  216,  543,  544,  545,  126,  126,
+      216,  216,  216,  111, 1518,  235,  235,  235,  235,  235,
+      235,  235,  235,  235,  234,  384,  126,  233,  233,  547,
+      547,  547,  126, 1340,  233,  233,  233,  111,  111,  236,
+      236,  236,  236,  236,  237,  238,  238,  238,  234,  234,
+     1340,  233,  233, 1518, 1518, 1518, 1340,  327,  233,  233,
+      233,  238,  238,  238,  238,  238,  238,  196,  391,  242,
+      242,  242,  242,  242,  242,  242,  242,  242,  241, 1377,
+     1377,  240,  240,  591,  592,  592, 1377, 1363,  240,  240,
+
+      240,  196, 1518,  243,  243,  243,  243,  243,  244,  245,
+      245,  245,  241,  391, 1363,  240,  240,  593,  594,  595,
+     1363,  126,  240,  240,  240,  245,  245,  245,  245,  245,
+      245,  255,  256,  257,  258,  258,  258,  258,  258,  258,
+      338, 1358, 1358,  259,  259,  597,  598,  599, 1358,  126,
+      259,  259,  259,  196,  196,  260,  260,  260,  260,  260,
+      260,  260,  260,  260,  198,  241,  126,  254,  254,  601,
+      602,  603,  126,  126,  254,  254,  254,  264,  265,  266,
+      267,  267,  267,  267,  267,  267,  605,  605,  605,  268,
+      268,  620,  620,  620,  126,  126,  268,  268,  268,  270,
+
+      271,  272,  273,  273,  273,  273,  273,  273,  207,  126,
+      126,  274,  274,  627,  627,  627,  126,  126,  274,  274,
+      274,  164,  327,  275,  275,  275,  275,  275,  275,  275,
+      275,  275,  207,  329,  164,  269,  269,  345,  283,  111,
+      196,  126,  269,  269,  269,  207,  126,  126,  126,  126,
+      377,  384,  126,  126,  126,  276,  281,  278,  278,  278,
+      278,  278,  279,  212,  212,  212,  338,  283,  634,  634,
+      634,  666,  666,  666,  666,  126,  126,  281,  327,  284,
+      284,  284,  284,  284,  284,  284,  284,  284,  283,  391,
+      126,  282,  282,  675,  675,  675,  126,  126,  282,  282,
+
+      282,  281,  505,  285,  285,  285,  285,  285,  286,  287,
+      287,  287,  283,  507, 1340,  282,  282,  682,  682,  682,
+     1518,  126,  282,  282,  282,  287,  287,  287,  287,  287,
+      287,  283,  164, 1518,  327, 1340, 1340,  345,  283,  448,
+      126,  516,  338,  166,  507,  329,  126,  126,  126, 1289,
+      126,  126,  126,  289,  289,  289,  289,  289,  290,  291,
+      291,  291,  294,  294,  294,  294,  294,  295,  226,  226,
+      226,  292,  299,  300,  301,  302,  302,  302,  302,  302,
+      302,  523, 1289, 1289,  303,  303,  689,  689,  689, 1285,
+      126,  303,  303,  303,  305,  306,  307,  308,  308,  308,
+
+      308,  308,  308,  345, 1285, 1285,  309,  309,  696,  696,
+      696, 1271,  126,  309,  309,  309,  111,  111,  310,  310,
+      310,  310,  310,  310,  310,  310,  310,  234,  564, 1271,
+      304,  304,  758,  759,  759, 1271,  126,  304,  304,  304,
+      312,  313,  314,  315,  315,  315,  315,  315,  315,  530,
+     1265, 1265,  316,  316,  760,  761,  762, 1265,  126,  316,
+      316,  316,  196, 1518,  317,  317,  317,  317,  317,  317,
+      317,  317,  317,  241,  564, 1261,  311,  311,  764,  765,
+      766, 1261, 1261,  311,  311,  311,  318,  196,  320,  320,
+      320,  320,  320,  321,  246,  246,  246,  322,  571,  324,
+
+      324,  324,  324,  324,  325,  250,  250,  250,  327, 1518,
+      330,  330,  330,  330,  330,  330,  330,  330,  330,  329,
+      571,  126,  328,  328,  768,  769,  770,  126,  126,  328,
+      328,  328,  327,  111,  331,  331,  331,  331,  331,  332,
+      333,  333,  333,  329,  377,  126,  328,  328,  772,  772,
+      772,  164,  327,  328,  328,  328,  333,  333,  333,  333,
+      333,  333,  338,  578, 1518, 1518, 1518,  827,  828,  828,
+      126,  126,  164, 1518,  339,  339,  339,  339,  339,  339,
+      339,  339,  339,  338,  578,  126,  337,  337,  829,  830,
+      831,  126,  126,  337,  337,  337,  164,  196,  340,  340,
+
+      340,  340,  340,  341,  342,  342,  342,  338,  384,  126,
+      337,  337,  833,  834,  835, 1518,  126,  337,  337,  337,
+      342,  342,  342,  342,  342,  342,  338,  281,  505, 1518,
+     1518,  327,  505,  111,  126,  126,  641,  641,  345,  585,
+      345,  585,  391,  507,  564,  126,  126,  126,  281,  126,
+      346,  346,  346,  346,  346,  346,  346,  346,  346,  345,
+      126,  126,  344,  344,  641,  837,  838,  839,  126,  344,
+      344,  344,  281,  126,  347,  347,  347,  347,  347,  348,
+      349,  349,  349,  345,  126,  126,  344,  344,  841,  841,
+      841,  164,  126,  344,  344,  344,  349,  349,  349,  349,
+
+      349,  349,  207,  856,  856,  856,  863,  863,  863,  126,
+      281,  126,  359,  360,  361,  362,  362,  362,  362,  362,
+      362,  283,  126,  126,  363,  363,  448,  870,  870,  870,
+      126,  363,  363,  363,  281,  126,  364,  364,  364,  364,
+      364,  364,  364,  364,  364,  283, 1076, 1235,  358,  358,
+      877,  877,  877, 1235,  126,  358,  358,  358,  367,  367,
+      367,  367,  367,  368,  369,  369,  369,  111,  196,  378,
+      378,  378,  378,  378,  378,  378,  378,  378,  377,  571,
+     1235,  376,  376,  917,  917,  917, 1289, 1289,  376,  376,
+      376,  111,  327,  379,  379,  379,  379,  379,  380,  381,
+
+      381,  381,  377,  578, 1289,  376,  376,  920,  920,  920,
+     1285,  505,  376,  376,  376,  381,  381,  381,  381,  381,
+      381,  196,  585,  385,  385,  385,  385,  385,  385,  385,
+      385,  385,  384, 1285, 1285,  383,  383,  923,  923,  923,
+     1271, 1271,  383,  383,  383,  196,  720,  386,  386,  386,
+      386,  386,  387,  388,  388,  388,  384,  722, 1271,  383,
+      383,  926,  926,  926,  126, 1518,  383,  383,  383,  388,
+      388,  388,  388,  388,  388,  327,  722,  392,  392,  392,
+      392,  392,  392,  392,  392,  392,  391, 1265, 1265,  390,
+      390,  929,  929,  929, 1265, 1261,  390,  390,  390,  327,
+
+      505,  393,  393,  393,  393,  393,  394,  395,  395,  395,
+      391,  507, 1261,  390,  390,  937,  937,  937,  937, 1261,
+      390,  390,  390,  395,  395,  395,  395,  395,  395,  409,
+      410,  411,  412,  412,  412,  412,  412,  412,  516,  126,
+      126,  413,  413,  523, 1009, 1010, 1010,  126,  413,  413,
+      413,  327,  126,  414,  414,  414,  414,  414,  414,  414,
+      414,  414,  329,  126,  126,  408,  408, 1011, 1012, 1013,
+      126,  126,  408,  408,  408,  418,  419,  420,  421,  421,
+      421,  421,  421,  421, 1015, 1016, 1017,  422,  422, 1019,
+     1020, 1021,  126,  126,  422,  422,  422,  424,  425,  426,
+
+      427,  427,  427,  427,  427,  427,  530,  126,  126,  428,
+      428,  641, 1023, 1023, 1023,  126,  428,  428,  428,  164,
+      126,  429,  429,  429,  429,  429,  429,  429,  429,  429,
+      338,  126,  164,  423,  423,  641,  641,  448,  656,  126,
+      423,  423,  423,  338,  126,  126,  126,  126, 1030, 1031,
+     1032,  281,  126,  431,  432,  433,  434,  434,  434,  434,
+      434,  434,  345,  126,  126,  435,  435, 1034, 1034, 1034,
+      126,  126,  435,  435,  435,  281,  111,  436,  436,  436,
+      436,  436,  436,  436,  436,  436,  345,  788,  126,  430,
+      430,  731, 1518, 1518, 1518,  126,  430,  430,  430,  437,
+
+      126,  439,  439,  439,  439,  439,  440,  350,  350,  350,
+      441,  446,  443,  443,  443,  443,  443,  444,  354,  354,
+      354,  516,  448, 1056, 1057, 1057, 1058, 1059, 1060, 1076,
+      126,  126,  446, 1518,  449,  449,  449,  449,  449,  449,
+      449,  449,  449,  448,  788, 1235,  447,  447, 1062, 1063,
+     1064, 1235,  126,  447,  447,  447,  446,  196,  450,  450,
+      450,  450,  450,  451,  452,  452,  452,  448,  795, 1235,
+      447,  447, 1066, 1067, 1068, 1518,  126,  447,  447,  447,
+      452,  452,  452,  452,  452,  452,  448,  281, 1518,  111,
+      327, 1518,  196,  505, 1518,  126,  957,  738,  283,  795,
+
+      564,  802,  802,  571,  809,  809,  126,  126,  456,  456,
+      456,  457,  458,  458,  458,  458,  458,  460,  460,  460,
+      460,  460,  461,  462,  462,  462,  466,  467,  468,  469,
+      469,  469,  469,  469,  469,  523, 1157, 1157,  470,  470,
+     1070, 1070, 1070, 1157,  126,  470,  470,  470,  472,  473,
+      474,  475,  475,  475,  475,  475,  475,  745, 1153, 1153,
+      476,  476, 1082, 1082, 1082, 1153,  126,  476,  476,  476,
+      111,  327,  477,  477,  477,  477,  477,  477,  477,  477,
+      477,  377,  578, 1149,  471,  471, 1085, 1085, 1085, 1149,
+     1149,  471,  471,  471,  479,  480,  481,  482,  482,  482,
+
+      482,  482,  482,  530,  911, 1127,  483,  483, 1088, 1088,
+     1088, 1127,  126,  483,  483,  483,  196,  720,  484,  484,
+      484,  484,  484,  484,  484,  484,  484,  384,  816, 1127,
+      478,  478, 1091, 1091, 1091, 1115, 1115,  478,  478,  478,
+      486,  487,  488,  489,  489,  489,  489,  489,  489,  752,
+     1115, 1111,  490,  490, 1094, 1094, 1094, 1111,  126,  490,
+      490,  490,  327, 1518,  491,  491,  491,  491,  491,  491,
+      491,  491,  491,  391,  816, 1111,  485,  485, 1102, 1102,
+     1102, 1102,  126,  485,  485,  485,  494,  494,  494,  494,
+      494,  495,  396,  396,  396,  492,  496,  505,  498,  498,
+
+      498,  498,  498,  499,  400,  400,  400,  500,  585,  502,
+      502,  502,  502,  502,  503,  404,  404,  404,  505,  720,
+      508,  508,  508,  508,  508,  508,  508,  508,  508,  507,
+      722,  126,  506,  506,  888, 1144, 1144, 1144, 1144,  506,
+      506,  506,  505,  126,  509,  509,  509,  509,  509,  510,
+      511,  511,  511,  507,  126,  126,  506,  506, 1163, 1164,
+     1165,  164,  909,  506,  506,  506,  511,  511,  511,  511,
+      511,  511,  516,  911,  888, 1167, 1167, 1167, 1189, 1190,
+     1190,  126,  164,  126,  517,  517,  517,  517,  517,  517,
+      517,  517,  517,  516,  126,  126,  515,  515,  888, 1191,
+
+     1192, 1193,  126,  515,  515,  515,  164,  126,  518,  518,
+      518,  518,  518,  519,  520,  520,  520,  516,  126,  126,
+      515,  515, 1195, 1196, 1197, 1518,  126,  515,  515,  515,
+      520,  520,  520,  520,  520,  520,  516,  281,  656, 1518,
+     1518,  111,  196,  327,  505,  126,  126,  126,  523,  126,
+      523,  911,  788,  795,  802,  809,  126,  126,  281,  126,
+      524,  524,  524,  524,  524,  524,  524,  524,  524,  523,
+      126,  126,  522,  522, 1199, 1200, 1201,  126,  126,  522,
+      522,  522,  281,  720,  525,  525,  525,  525,  525,  526,
+      527,  527,  527,  523,  816,  126,  522,  522, 1203, 1203,
+
+     1203,  164,  126,  522,  522,  522,  527,  527,  527,  527,
+      527,  527,  338,  446,  955, 1518, 1518,  720, 1169,  909,
+      731,  126,  738,  745,  530,  957,  530,  957,  722,  126,
+      911,  126,  126,  126,  446,  126,  531,  531,  531,  531,
+      531,  531,  531,  531,  531,  530, 1076,  850,  529,  529,
+      752, 1206, 1207, 1208,  126,  529,  529,  529,  446,  126,
+      532,  532,  532,  532,  532,  533,  534,  534,  534,  530,
+      957, 1157,  529,  529, 1518, 1518, 1518,  281,  126,  529,
+      529,  529,  534,  534,  534,  534,  534,  534,  345, 1224,
+     1225, 1225, 1226, 1227, 1228, 1157,  446,  126,  548,  549,
+
+      550,  551,  551,  551,  551,  551,  551,  448, 1157, 1153,
+      552,  552,  888, 1230, 1231, 1232,  126,  552,  552,  552,
+      446,  126,  553,  553,  553,  553,  553,  553,  553,  553,
+      553,  448, 1153, 1153,  547,  547, 1252, 1252, 1252, 1252,
+      126,  547,  547,  547,  557,  557,  557,  557,  557,  558,
+      559,  559,  559,  111,  111,  565,  565,  565,  565,  565,
+      565,  565,  565,  565,  564,  788, 1149,  563,  563,  888,
+     1280, 1280, 1280, 1280,  563,  563,  563,  111,  126,  566,
+      566,  566,  566,  566,  567,  568,  568,  568,  564, 1149,
+     1149,  563,  563, 1294, 1295, 1296,  816,  196,  563,  563,
+
+      563,  568,  568,  568,  568,  568,  568,  196,  795,  572,
+      572,  572,  572,  572,  572,  572,  572,  572,  571,  809,
+      802,  570,  570,  888, 1312, 1313, 1313,  795,  570,  570,
+      570,  196,  126,  573,  573,  573,  573,  573,  574,  575,
+      575,  575,  571,  788,  911,  570,  570, 1314, 1315, 1316,
+     1127,  327,  570,  570,  570,  575,  575,  575,  575,  575,
+      575,  327,  802,  579,  579,  579,  579,  579,  579,  579,
+      579,  579,  578, 1127, 1127,  577,  577,  656, 1318, 1319,
+     1320, 1115,  577,  577,  577,  327,  126,  580,  580,  580,
+      580,  580,  581,  582,  582,  582,  578, 1115, 1115,  577,
+
+      577, 1323, 1324, 1325, 1111,  505,  577,  577,  577,  582,
+      582,  582,  582,  582,  582,  505,  809,  586,  586,  586,
+      586,  586,  586,  586,  586,  586,  585, 1111, 1111,  584,
+      584,  903, 1518, 1518, 1518,  126,  584,  584,  584,  505,
+      126,  587,  587,  587,  587,  587,  588,  589,  589,  589,
+      585,  126,  126,  584,  584, 1334, 1335, 1335,  126,  126,
+      584,  584,  584,  589,  589,  589,  589,  589,  589,  606,
+      607,  608,  609,  609,  609,  609,  609,  609,  970,  126,
+      850,  610,  610, 1336, 1337, 1338,  957,  126,  610,  610,
+      610,  505,  720,  611,  611,  611,  611,  611,  611,  611,
+
+      611,  611,  507,  816,  722,  605,  605, 1349, 1349, 1349,
+     1349,  950,  605,  605,  605,  615,  616,  617,  618,  618,
+      618,  618,  618,  618, 1381, 1382, 1383,  619,  619, 1372,
+     1372, 1372, 1372,  126,  619,  619,  619,  621,  622,  623,
+      624,  624,  624,  624,  624,  624,  731,  950,  950,  625,
+      625, 1392, 1393, 1393,  946,  126,  625,  625,  625,  164,
+      955,  626,  626,  626,  626,  626,  626,  626,  626,  626,
+      516,  957,  164,  620,  620, 1074, 1518,  909,  955,  126,
+      620,  620,  620,  516,  946,  946, 1076, 1076,  911,  957,
+      942,  281,  126,  628,  629,  630,  631,  631,  631,  631,
+
+      631,  631,  523,  942,  942,  632,  632,  977, 1394, 1395,
+     1396,  126,  632,  632,  632,  281,  126,  633,  633,  633,
+      633,  633,  633,  633,  633,  633,  523,  816,  809,  627,
+      627, 1399, 1400, 1400,  802,  126,  627,  627,  627,  635,
+      636,  637,  638,  638,  638,  638,  638,  638,  738,  795,
+      788,  639,  639,  984, 1518, 1518, 1518,  126,  639,  639,
+      639,  446,  126,  640,  640,  640,  640,  640,  640,  640,
+      640,  640,  530, 1036,  446,  634,  634,  745,  991,  752,
+      998,  126,  634,  634,  634,  530,  126,  126,  126,  126,
+     1408, 1409, 1409,  911,  126,  643,  643,  643,  643,  643,
+
+      644,  535,  535,  535,  641,  669, 1107, 1419, 1419, 1419,
+     1419,  896,  896,  126,  645,  126,  647,  647,  647,  647,
+      647,  648,  539,  539,  539,  649,  654,  651,  651,  651,
+      651,  651,  652,  543,  543,  543, 1107,  656,  896, 1107,
+     1437, 1437, 1437, 1437,  892,  126,  126,  654,  126,  657,
+      657,  657,  657,  657,  657,  657,  657,  657,  656,  892,
+      892,  655,  655,  903, 1443, 1444, 1444,  126,  655,  655,
+      655,  654,  126,  658,  658,  658,  658,  658,  659,  660,
+      660,  660,  656,  126,  126,  655,  655, 1452, 1453, 1453,
+     1518,  126,  655,  655,  655,  660,  660,  660,  660,  660,
+
+      660,  656,  446, 1074,  126,  850,  970,  977,  984,  991,
+      126,  998, 1107,  448, 1076,  126,  126,  126,  126,  614,
+      126,  126,  126,  664,  664,  664,  665,  666,  666,  666,
+      666,  666,  670,  671,  672,  673,  673,  673,  673,  673,
+      673, 1107,  722,  950,  674,  674, 1518, 1518, 1518,  950,
+      126,  674,  674,  674,  676,  677,  678,  679,  679,  679,
+      679,  679,  679, 1107,  950,  946,  680,  680,  903, 1518,
+     1518, 1518,  126,  680,  680,  680,  111,  126,  681,  681,
+      681,  681,  681,  681,  681,  681,  681,  564,  946,  946,
+      675,  675, 1474, 1474, 1474, 1474,  942,  675,  675,  675,
+
+      683,  684,  685,  686,  686,  686,  686,  686,  686, 1122,
+      942,  942,  687,  687, 1484, 1484, 1484, 1484,  126,  687,
+      687,  687,  196, 1074,  688,  688,  688,  688,  688,  688,
+      688,  688,  688,  571, 1076,  816,  682,  682, 1490, 1490,
+     1490, 1490,  585,  682,  682,  682,  690,  691,  692,  693,
+      693,  693,  693,  693,  693,  970,  809,  578,  694,  694,
+      977, 1518, 1518, 1518,  126,  694,  694,  694,  327,  126,
+      695,  695,  695,  695,  695,  695,  695,  695,  695,  578,
+      802,  571,  689,  689, 1509, 1509, 1509, 1509,  795,  689,
+      689,  689,  697,  698,  699,  700,  700,  700,  700,  700,
+
+      700,  984,  564,  788,  701,  701,  991,  669,  896,  896,
+      126,  701,  701,  701,  505,  126,  702,  702,  702,  702,
+      702,  702,  702,  702,  702,  585,  896,  892,  696,  696,
+     1515, 1515, 1515, 1515,  892,  696,  696,  696,  704,  704,
+      704,  704,  704,  705,  706,  706,  706,  709,  709,  709,
+      709,  709,  710,  593,  593,  593,  707,  711,  892,  713,
+      713,  713,  713,  713,  714,  597,  597,  597,  715,  126,
+      717,  717,  717,  717,  717,  718,  601,  601,  601,  720,
+      126,  723,  723,  723,  723,  723,  723,  723,  723,  723,
+      722,  850,  614,  721,  721,  998,  722,  507,  715,  715,
+
+      721,  721,  721,  720,  126,  724,  724,  724,  724,  724,
+      725,  726,  726,  726,  722,  715,  711,  721,  721,  711,
+      711,  707,  164,  707,  721,  721,  721,  726,  726,  726,
+      726,  726,  726,  731,  707, 1257,  585,  578,  571,  564,
+      669,  465,  126,  164,  126,  732,  732,  732,  732,  732,
+      732,  732,  732,  732,  731,  649,  649,  730,  730, 1257,
+      649,  645,  645,  126,  730,  730,  730,  164,  126,  733,
+      733,  733,  733,  733,  734,  735,  735,  735,  731,  645,
+      729,  730,  730,  614,  417,  507, 1518,  126,  730,  730,
+      730,  735,  735,  735,  735,  735,  735,  731,  281, 1257,
+
+     1518, 1122,  715, 1257, 1257, 1257,  126, 1122,  126,  738,
+      126,  738,  126,  126,  126,  715,  126,  715,  126,  281,
+      126,  739,  739,  739,  739,  739,  739,  739,  739,  739,
+      738,  711,  711,  737,  737, 1354,  711,  707,  707,  126,
+      737,  737,  737,  281,  126,  740,  740,  740,  740,  740,
+      741,  742,  742,  742,  738,  707,  585,  737,  737,  391,
+      578,  384,  164,  126,  737,  737,  737,  742,  742,  742,
+      742,  742,  742,  516,  446, 1354, 1518, 1354,  571, 1354,
+     1354, 1354,  126, 1410,  126,  745,  126,  745,  126,  126,
+      126,  377,  126,  564,  126,  446,  126,  746,  746,  746,
+
+      746,  746,  746,  746,  746,  746,  745,  669,  465,  744,
+      744, 1410,  649,  649,  649,  126,  744,  744,  744,  446,
+      126,  747,  747,  747,  747,  747,  748,  749,  749,  749,
+      745,  645,  645,  744,  744,  645,  614,  417,  281,  126,
+      744,  744,  744,  749,  749,  749,  749,  749,  749,  523,
+      654, 1410, 1518, 1424,  507, 1424, 1424, 1410,  126, 1410,
+      126,  752,  126,  752,  126,  126,  126,  329,  126,  500,
+      126,  654,  126,  753,  753,  753,  753,  753,  753,  753,
+      753,  753,  752,  500,  500,  751,  751, 1410,  496,  496,
+      496,  126,  751,  751,  751,  654,  126,  754,  754,  754,
+
+      754,  754,  755,  756,  756,  756,  752,  492,  492,  751,
+      751,  492,  391,  384,  446,  126,  751,  751,  751,  756,
+      756,  756,  756,  756,  756,  530,  377,  562,  465,  298,
+      441,  441,  441,  654,  126,  773,  774,  775,  776,  776,
+      776,  776,  776,  776,  656,  437,  437,  777,  777, 1424,
+      437,  514,  417,  126,  777,  777,  777,  654,  126,  778,
+      778,  778,  778,  778,  778,  778,  778,  778,  656,  263,
+      329,  772,  772,  500,  500,  500,  496,  126,  772,  772,
+      772,  781,  782,  783,  784,  784,  784,  784,  784,  784,
+      785,  496,  496,  786,  786, 1424,  492,  492,  492,  391,
+
+      786,  786,  786,  111,  126,  789,  789,  789,  789,  789,
+      789,  789,  789,  789,  788,  241,  384,  787,  787, 1424,
+      234,  377,  465,  298,  787,  787,  787,  111,  126,  790,
+      790,  790,  790,  790,  791,  792,  792,  792,  788,  441,
+      441,  787,  787,  441,  437,  437,  437,  417,  787,  787,
+      787,  792,  792,  792,  792,  792,  792,  196,  263,  796,
+      796,  796,  796,  796,  796,  796,  796,  796,  795,  329,
+      198,  794,  794,  322,  322,  322,  318,  318,  794,  794,
+      794,  196,  318,  797,  797,  797,  797,  797,  798,  799,
+      799,  799,  795,  241,  234,  794,  794,  375,  298,  178,
+
+      292,  292,  794,  794,  794,  799,  799,  799,  799,  799,
+      799,  327,  292,  803,  803,  803,  803,  803,  803,  803,
+      803,  803,  802,  276,  276,  801,  801,  276,  336,  263,
+      158,  198,  801,  801,  801,  327,  322,  804,  804,  804,
+      804,  804,  805,  806,  806,  806,  802,  322,  322,  801,
+      801,  318,  318,  318,  241,  140,  801,  801,  801,  806,
+      806,  806,  806,  806,  806,  505,  234,  810,  810,  810,
+      810,  810,  810,  810,  810,  810,  809,  298,  178,  808,
+      808,  292,  292,  292,  276,  276,  808,  808,  808,  505,
+      276,  811,  811,  811,  811,  811,  812,  813,  813,  813,
+
+      809,  263,  158,  808,  808,  198,  113,  191,  191,  191,
+      808,  808,  808,  813,  813,  813,  813,  813,  813,  720,
+      140,  817,  817,  817,  817,  817,  817,  817,  817,  817,
+      816,  232,  178,  815,  815,  105,  172,  172,  172,  205,
+      815,  815,  815,  720,  158,  818,  818,  818,  818,  818,
+      819,  820,  820,  820,  816,   88,  113,  815,  815,  191,
+      191,  191,  140,  178,  815,  815,  815,  820,  820,  820,
+      820,  820,  820,  823,  823,  823,  823,  823,  824,  825,
+      825,  825,  842,  843,  844,  845,  845,  845,  845,  845,
+      845,  105, 1518, 1518,  846,  846,  172,  172,  172,   58,
+
+      171,  846,  846,  846,  720,  158,  847,  847,  847,  847,
+      847,  847,  847,  847,  847,  722,   88,  113,  841,  841,
+      138,  105,   44,   60,  127,  841,  841,  841,  851,  852,
+      853,  854,  854,  854,  854,  854,  854,  120,   88,   41,
+      855,  855,  105,   96,   66,   60,  126,  855,  855,  855,
+      857,  858,  859,  860,  860,  860,  860,  860,  860,   91,
+       58,   90,  861,  861,   55,   89,   88,   41,   79,  861,
+      861,  861,  164,   38,  862,  862,  862,  862,  862,  862,
+      862,  862,  862,  731,   66,  164,  856,  856,   62,   61,
+       58,   57,  126,  856,  856,  856,  731,   54,   52,   38,
+
+       33, 1518,   32,    6,  281,  126,  864,  865,  866,  867,
+      867,  867,  867,  867,  867,  738, 1518, 1518,  868,  868,
+     1518, 1518, 1518, 1518,  126,  868,  868,  868,  281, 1518,
+      869,  869,  869,  869,  869,  869,  869,  869,  869,  738,
+     1518, 1518,  863,  863, 1518, 1518, 1518, 1518,  126,  863,
+      863,  863,  871,  872,  873,  874,  874,  874,  874,  874,
+      874, 1518, 1518, 1518,  875,  875, 1518, 1518, 1518, 1518,
+     1518,  875,  875,  875,  446, 1518,  876,  876,  876,  876,
+      876,  876,  876,  876,  876,  745, 1518,  446,  870,  870,
+     1518, 1518, 1518, 1518,  126,  870,  870,  870,  745, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518,  654,  126,  878,  879,
+      880,  881,  881,  881,  881,  881,  881,  752, 1518, 1518,
+      882,  882, 1518, 1518, 1518, 1518,  126,  882,  882,  882,
+      654, 1518,  883,  883,  883,  883,  883,  883,  883,  883,
+      883,  752, 1518, 1518,  877,  877, 1518, 1518, 1518, 1518,
+      126,  877,  877,  877,  885,  885,  885,  885,  885,  886,
+      887,  887,  887, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518,  126,  890,  890,  890,  890,  890,  891,  760,
+      760,  760,  888, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518,  126,  892, 1518,  894,  894,  894,  894,  894,  895,
+
+      764,  764,  764,  896,  901,  898,  898,  898,  898,  898,
+      899,  768,  768,  768, 1518,  903, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518,  126,  901, 1518,  904,  904,  904,
+      904,  904,  904,  904,  904,  904,  903, 1518, 1518,  902,
+      902, 1518, 1518, 1518, 1518,  126,  902,  902,  902,  901,
+     1518,  905,  905,  905,  905,  905,  906,  907,  907,  907,
+      903, 1518, 1518,  902,  902, 1518, 1518, 1518, 1518,  126,
+      902,  902,  902,  907,  907,  907,  907,  907,  907,  903,
+      654, 1518,  164, 1518, 1518, 1518, 1518, 1518,  126, 1518,
+     1518,  656, 1518,  970, 1518, 1518, 1518, 1518, 1518, 1518,
+
+      126,  909,  126,  912,  912,  912,  912,  912,  912,  912,
+      912,  912,  911, 1518, 1518,  910,  910, 1518, 1518, 1518,
+     1518, 1518,  910,  910,  910,  909, 1518,  913,  913,  913,
+      913,  913,  914,  915,  915,  915,  911, 1518, 1518,  910,
+      910, 1518, 1518, 1518, 1518, 1518,  910,  910,  910,  915,
+      915,  915,  915,  915,  915,  111, 1518,  919,  919,  919,
+      919,  919,  919,  919,  919,  919,  788, 1518, 1518,  917,
+      917, 1518, 1518, 1518, 1518, 1518,  917,  917,  917,  196,
+     1518,  922,  922,  922,  922,  922,  922,  922,  922,  922,
+      795, 1518, 1518,  920,  920, 1518, 1518, 1518, 1518, 1518,
+
+      920,  920,  920,  327, 1518,  925,  925,  925,  925,  925,
+      925,  925,  925,  925,  802, 1518, 1518,  923,  923, 1518,
+     1518, 1518, 1518, 1518,  923,  923,  923,  505, 1518,  928,
+      928,  928,  928,  928,  928,  928,  928,  928,  809, 1518,
+     1518,  926,  926, 1518, 1518, 1518, 1518, 1518,  926,  926,
+      926,  720, 1518,  931,  931,  931,  931,  931,  931,  931,
+      931,  931,  816, 1518, 1518,  929,  929, 1518, 1518, 1518,
+     1518, 1518,  929,  929,  929,  935,  935,  935,  936,  937,
+      937,  937,  937,  937,  939,  939,  939,  939,  939,  940,
+      941,  941,  941,  944,  944,  944,  944,  944,  945,  829,
+
+      829,  829,  942,  946, 1518,  948,  948,  948,  948,  948,
+      949,  833,  833,  833,  950, 1518,  952,  952,  952,  952,
+      952,  953,  837,  837,  837,  955, 1518,  958,  958,  958,
+      958,  958,  958,  958,  958,  958,  957, 1518, 1518,  956,
+      956, 1518, 1518, 1518, 1518, 1518,  956,  956,  956,  955,
+     1518,  959,  959,  959,  959,  959,  960,  961,  961,  961,
+      957, 1518, 1518,  956,  956, 1518, 1518, 1518, 1518, 1518,
+      956,  956,  956,  961,  961,  961,  961,  961,  961,  963,
+      964,  965,  966,  966,  966,  966,  966,  966,  967, 1518,
+     1518,  968,  968, 1518, 1518, 1518, 1518, 1518,  968,  968,
+
+      968,  164, 1518,  971,  971,  971,  971,  971,  971,  971,
+      971,  971,  970, 1518, 1518,  969,  969, 1518, 1518, 1518,
+     1518,  126,  969,  969,  969,  164, 1518,  972,  972,  972,
+      972,  972,  973,  974,  974,  974,  970, 1518, 1518,  969,
+      969, 1518, 1518, 1518, 1518,  126,  969,  969,  969,  974,
+      974,  974,  974,  974,  974,  970,  281, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518,  126, 1518, 1518,  977, 1518,  977,
+     1518, 1518, 1518, 1518, 1518, 1518,  126,  281,  126,  978,
+      978,  978,  978,  978,  978,  978,  978,  978,  977, 1518,
+     1518,  976,  976, 1518, 1518, 1518, 1518,  126,  976,  976,
+
+      976,  281, 1518,  979,  979,  979,  979,  979,  980,  981,
+      981,  981,  977, 1518, 1518,  976,  976, 1518, 1518, 1518,
+      164,  126,  976,  976,  976,  981,  981,  981,  981,  981,
+      981,  731,  446, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+      126, 1518, 1518,  984, 1518,  984, 1518, 1518, 1518, 1518,
+     1518, 1518,  126,  446,  126,  985,  985,  985,  985,  985,
+      985,  985,  985,  985,  984, 1518, 1518,  983,  983, 1518,
+     1518, 1518, 1518,  126,  983,  983,  983,  446, 1518,  986,
+      986,  986,  986,  986,  987,  988,  988,  988,  984, 1518,
+     1518,  983,  983, 1518, 1518, 1518,  281,  126,  983,  983,
+
+      983,  988,  988,  988,  988,  988,  988,  738,  654, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518,  126, 1518, 1518,  991,
+     1518,  991, 1518, 1518, 1518, 1518, 1518, 1518,  126,  654,
+      126,  992,  992,  992,  992,  992,  992,  992,  992,  992,
+      991, 1518, 1518,  990,  990, 1518, 1518, 1518, 1518,  126,
+      990,  990,  990,  654, 1518,  993,  993,  993,  993,  993,
+      994,  995,  995,  995,  991, 1518, 1518,  990,  990, 1518,
+     1518, 1518,  446,  126,  990,  990,  990,  995,  995,  995,
+      995,  995,  995,  745,  901, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518,  126, 1518, 1518,  998, 1518,  998, 1518, 1518,
+
+     1518, 1518, 1518, 1518,  126,  901,  126,  999,  999,  999,
+      999,  999,  999,  999,  999,  999,  998, 1518, 1518,  997,
+      997, 1518, 1518, 1518, 1518,  126,  997,  997,  997,  901,
+     1518, 1000, 1000, 1000, 1000, 1000, 1001, 1002, 1002, 1002,
+      998, 1518, 1518,  997,  997, 1518, 1518, 1518,  654,  126,
+      997,  997,  997, 1002, 1002, 1002, 1002, 1002, 1002,  752,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,  126, 1005,
+     1005, 1005, 1005, 1005, 1006, 1007, 1007, 1007, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518,  901,  126, 1024, 1025,
+     1026, 1027, 1027, 1027, 1027, 1027, 1027,  903, 1518, 1518,
+
+     1028, 1028, 1518, 1518, 1518, 1518,  126, 1028, 1028, 1028,
+      901, 1518, 1029, 1029, 1029, 1029, 1029, 1029, 1029, 1029,
+     1029,  903, 1518, 1518, 1023, 1023, 1518, 1518, 1518, 1518,
+      126, 1023, 1023, 1023,  909, 1518, 1037, 1037, 1037, 1037,
+     1037, 1037, 1037, 1037, 1037,  911, 1518, 1518, 1034, 1034,
+     1518, 1518, 1518, 1518, 1518, 1034, 1034, 1034, 1052, 1052,
+     1052, 1052, 1052, 1053, 1054, 1054, 1054,  955, 1518, 1072,
+     1072, 1072, 1072, 1072, 1072, 1072, 1072, 1072,  957, 1518,
+     1518, 1070, 1070, 1518, 1518, 1518, 1518, 1518, 1070, 1070,
+     1070, 1074, 1518, 1077, 1077, 1077, 1077, 1077, 1077, 1077,
+
+     1077, 1077, 1076, 1518, 1518, 1075, 1075, 1518, 1518, 1518,
+     1518, 1518, 1075, 1075, 1075, 1074, 1518, 1078, 1078, 1078,
+     1078, 1078, 1079, 1080, 1080, 1080, 1076, 1518, 1518, 1075,
+     1075, 1518, 1518, 1518, 1518, 1518, 1075, 1075, 1075, 1080,
+     1080, 1080, 1080, 1080, 1080,  164, 1518, 1084, 1084, 1084,
+     1084, 1084, 1084, 1084, 1084, 1084,  970, 1518,  164, 1082,
+     1082, 1518, 1518, 1518, 1518,  126, 1082, 1082, 1082,  970,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,  126,  281,
+     1518, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087, 1087,
+      977, 1518,  281, 1085, 1085, 1518, 1518, 1518, 1518,  126,
+
+     1085, 1085, 1085,  977, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518,  126,  446, 1518, 1090, 1090, 1090, 1090, 1090,
+     1090, 1090, 1090, 1090,  984, 1518,  446, 1088, 1088, 1518,
+     1518, 1518, 1518,  126, 1088, 1088, 1088,  984, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518,  126,  654, 1518, 1093,
+     1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,  991, 1518,
+      654, 1091, 1091, 1518, 1518, 1518, 1518,  126, 1091, 1091,
+     1091,  991, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+      126,  901, 1518, 1096, 1096, 1096, 1096, 1096, 1096, 1096,
+     1096, 1096,  998, 1518,  901, 1094, 1094, 1518, 1518, 1518,
+
+     1518,  126, 1094, 1094, 1094,  998, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518,  126, 1100, 1100, 1100, 1101, 1102,
+     1102, 1102, 1102, 1102, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518,  126, 1104, 1104, 1104, 1104, 1104, 1105,
+     1106, 1106, 1106, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518,  126, 1109, 1109, 1109, 1109, 1109, 1110, 1011,
+     1011, 1011, 1107, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518,  126, 1111, 1518, 1113, 1113, 1113, 1113, 1113, 1114,
+     1015, 1015, 1015, 1115, 1120, 1117, 1117, 1117, 1117, 1117,
+     1118, 1019, 1019, 1019, 1518, 1122, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518,  126, 1120, 1518, 1123, 1123, 1123,
+     1123, 1123, 1123, 1123, 1123, 1123, 1122, 1518, 1518, 1121,
+     1121, 1518, 1518, 1518, 1518,  126, 1121, 1121, 1121, 1120,
+     1518, 1124, 1124, 1124, 1124, 1124, 1125, 1126, 1126, 1126,
+     1122, 1518, 1518, 1121, 1121, 1518, 1518, 1518, 1518,  126,
+     1121, 1121, 1121, 1126, 1126, 1126, 1126, 1126, 1126, 1122,
+      901, 1518,  164, 1518, 1518, 1518, 1518, 1518,  126, 1518,
+     1518,  903, 1518,  970, 1518, 1518, 1518, 1518, 1518, 1518,
+      126, 1127,  126, 1129, 1129, 1129, 1129, 1129, 1130, 1030,
+     1030, 1030, 1142, 1142, 1142, 1143, 1144, 1144, 1144, 1144,
+
+     1144, 1146, 1146, 1146, 1146, 1146, 1147, 1148, 1148, 1148,
+     1151, 1151, 1151, 1151, 1151, 1152, 1058, 1058, 1058, 1149,
+     1153, 1518, 1155, 1155, 1155, 1155, 1155, 1156, 1062, 1062,
+     1062, 1157, 1518, 1159, 1159, 1159, 1159, 1159, 1160, 1066,
+     1066, 1066, 1074, 1518, 1170, 1170, 1170, 1170, 1170, 1170,
+     1170, 1170, 1170, 1076, 1518,  281, 1167, 1167,  446,  654,
+      901, 1518, 1518, 1167, 1167, 1167,  977, 1518, 1518,  984,
+      991,  998, 1518, 1518, 1518,  126, 1518, 1518,  126,  126,
+      126, 1185, 1185, 1185, 1185, 1185, 1186, 1187, 1187, 1187,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,  126,
+
+     1120, 1518, 1205, 1205, 1205, 1205, 1205, 1205, 1205, 1205,
+     1205, 1122, 1518, 1120, 1203, 1203, 1518, 1518, 1518, 1518,
+      126, 1203, 1203, 1203, 1122, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518,  126, 1220, 1220, 1220, 1220, 1220, 1221,
+     1222, 1222, 1222, 1235, 1518, 1237, 1237, 1237, 1237, 1237,
+     1238, 1163, 1163, 1163, 1250, 1250, 1250, 1251, 1252, 1252,
+     1252, 1252, 1252, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518,  126, 1254, 1254, 1254, 1254, 1254, 1255, 1256,
+     1256, 1256, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518,  126, 1259, 1259, 1259, 1259, 1259, 1260, 1191, 1191,
+
+     1191, 1257, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+      126, 1261, 1518, 1263, 1263, 1263, 1263, 1263, 1264, 1195,
+     1195, 1195, 1265, 1120, 1267, 1267, 1267, 1267, 1267, 1268,
+     1199, 1199, 1199, 1518, 1122, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518,  126, 1271, 1518, 1273, 1273, 1273, 1273,
+     1273, 1274, 1206, 1206, 1206, 1278, 1278, 1278, 1279, 1280,
+     1280, 1280, 1280, 1280, 1282, 1282, 1282, 1282, 1282, 1283,
+     1284, 1284, 1284, 1287, 1287, 1287, 1287, 1287, 1288, 1226,
+     1226, 1226, 1285, 1289, 1518, 1291, 1291, 1291, 1291, 1291,
+     1292, 1230, 1230, 1230, 1308, 1308, 1308, 1308, 1308, 1309,
+
+     1310, 1310, 1310, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518,  126, 1330, 1330, 1330, 1330, 1330, 1331, 1332,
+     1332, 1332, 1340, 1518, 1342, 1342, 1342, 1342, 1342, 1343,
+     1294, 1294, 1294, 1347, 1347, 1347, 1348, 1349, 1349, 1349,
+     1349, 1349, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518,  126, 1351, 1351, 1351, 1351, 1351, 1352, 1353, 1353,
+     1353, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+      126, 1356, 1356, 1356, 1356, 1356, 1357, 1314, 1314, 1314,
+     1354, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,  126,
+     1358, 1518, 1360, 1360, 1360, 1360, 1360, 1361, 1318, 1318,
+
+     1318, 1365, 1365, 1365, 1365, 1365, 1366, 1323, 1323, 1323,
+     1363, 1370, 1370, 1370, 1371, 1372, 1372, 1372, 1372, 1372,
+     1374, 1374, 1374, 1374, 1374, 1375, 1376, 1376, 1376, 1379,
+     1379, 1379, 1379, 1379, 1380, 1336, 1336, 1336, 1377, 1388,
+     1388, 1388, 1388, 1388, 1389, 1390, 1390, 1390, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518,  126, 1404, 1404,
+     1404, 1404, 1404, 1405, 1406, 1406, 1406, 1412, 1412, 1412,
+     1412, 1412, 1413, 1381, 1381, 1381, 1410, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518,  126, 1417, 1417, 1417, 1418,
+     1419, 1419, 1419, 1419, 1419, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518,  126, 1421, 1421, 1421, 1421, 1421,
+     1422, 1423, 1423, 1423, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518,  126, 1426, 1426, 1426, 1426, 1426, 1427,
+     1394, 1394, 1394, 1424, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518,  126, 1429, 1429, 1429, 1429, 1429, 1430, 1431,
+     1431, 1431, 1435, 1435, 1435, 1436, 1437, 1437, 1437, 1437,
+     1437, 1439, 1439, 1439, 1439, 1439, 1440, 1441, 1441, 1441,
+     1448, 1448, 1448, 1448, 1448, 1449, 1450, 1450, 1450, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,  126, 1456,
+     1456, 1456, 1456, 1456, 1457, 1458, 1458, 1458, 1462, 1462,
+
+     1462, 1462, 1462, 1463, 1464, 1464, 1464, 1466, 1466, 1466,
+     1466, 1466, 1467, 1468, 1468, 1468, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518,  126, 1472, 1472, 1472, 1473,
+     1474, 1474, 1474, 1474, 1474, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518,  126, 1476, 1476, 1476, 1476, 1476,
+     1477, 1478, 1478, 1478, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518,  126, 1482, 1482, 1482, 1483, 1484, 1484,
+     1484, 1484, 1484, 1488, 1488, 1488, 1489, 1490, 1490, 1490,
+     1490, 1490, 1493, 1493, 1493, 1493, 1493, 1494, 1495, 1495,
+     1495, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+      126, 1499, 1499, 1499, 1499, 1499, 1500, 1501, 1501, 1501,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,  126,
+     1507, 1507, 1507, 1508, 1509, 1509, 1509, 1509, 1509, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,  126, 1513,
+     1513, 1513, 1514, 1515, 1515, 1515, 1515, 1515, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518,  126,   31,   31,
+       31,   31,   31,   31,   31,   31,   31,   31,   31,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       37, 1518,   37,   37,   37,   37,   37,   37,   37,   37,
+       37,   39,   39,   39,   39,   40,   40,   40,   46,   46,
+
+       46, 1518,   46,   46,   46,   53,   53,   53,   53,   53,
+       53,   63,   63,   63,   63,   63,   63,   63,   63,   63,
+       63,   63,   67,   67,   67,   67,   67,   67,   67,   67,
+       67,   67,   67,   74,   74,   74,   78,   78,   78,   78,
+       78,   78,   87,   87,   87,   87,   87,   87,   92,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,   92,   98,
+       98,   98,   98, 1518, 1518,   98,  104,  104,  104,  104,
+      104,  104,  112,  112,  112,  112,  112,  112,  112,  118,
+      118,  118,  118,  118,  118,  119,  119,  119,  119,  119,
+      119,  129,  129,  129,  133,  133,  133,  136,  136,  136,
+
+      136,  136,  136,  137,  137,  137,  137,  137,  137,  139,
+      139,  139,  139,  139,  139,  139,  148,  148,  148,  149,
+      149,  149,  149,  149,  149,  156,  156,  156,  156,  156,
+      156,  157,  157,  157,  157,  157,  157,  165,  165,  165,
+      165,  165,  165,  165, 1518,  165,  173,  173,  173,  173,
+      130,  130,  130,  130,  176,  176,  176,  176,  176,  176,
+      177,  177,  177,  177,  177,  177,  184,  184,  184,  184,
+      184,  184,  192,  192,  192,  192,  145,  145,  145,  145,
+      195,  195,  195,  195,  195,  195,  197,  197,  197,  197,
+      197,  197,  197,  203,  203,  203,  203,  203,  203,  204,
+
+      204,  204,  204,  204,  204,  206,  206,  206,  206,  206,
+      206,  206, 1518,  206,  215,  215,  215,  216,  216,  216,
+      216,  216,  216, 1518,  216,  223,  223,  229,  229,  229,
+      130,  130,  130,  230,  230,  230,  230,  230,  230,  231,
+      231,  231,  231,  231,  231,  233,  233,  233,  233,  233,
+      233,  233,  239,  239,  239,  239,  239,  239,  240,  240,
+      240,  240,  240,  240,  240,  249,  249,  249,  145,  145,
+      145,  253,  253,  253,  254,  254,  254,  254,  254,  254,
+      261,  261,  261,  261,  261,  261,  262,  262,  262,  262,
+      262,  262,  269,  269,  269,  269,  269,  269, 1518,  269,
+
+      277,  277,  277,  277,  212,  212,  212,  212,  280,  280,
+      280,  280,  280,  280, 1518,  280,  282,  282,  282,  282,
+      282,  282,  282, 1518,  282,  288,  288,  288,  291,  291,
+      291,  293,  293,  293,  293,  226,  226,  226,  226,  296,
+      296,  296,  296,  296,  296,  297,  297,  297,  297,  297,
+      297,  304,  304,  304,  304,  304,  304,  311,  311,  311,
+      311,  311,  311,  319,  319,  319,  319,  246,  246,  246,
+      246,  323,  323,  323,  323,  250,  250,  250,  250,  326,
+      326,  326,  326,  326,  326,  328,  328,  328,  328,  328,
+      328,  328,  334,  334,  334,  334,  334,  334,  335,  335,
+
+      335,  335,  335,  335,  337,  337,  337,  337,  337,  337,
+      337, 1518,  337,  343,  343,  343,  343,  343,  343, 1518,
+      343,  344,  344,  344,  344,  344,  344,  344, 1518,  344,
+      353,  353,  353,  212,  212,  212,  357,  357,  357,  358,
+      358,  358,  358,  358,  358, 1518,  358,  365,  365,  365,
+      366,  366,  366,  369,  369,  369,  370,  370,  226,  226,
+     1518,  226,  373,  373,  373,  373,  373,  373,  374,  374,
+      374,  374,  374,  374,  376,  376,  376,  376,  376,  376,
+      376,  382,  382,  382,  382,  382,  382,  383,  383,  383,
+      383,  383,  383,  383,  389,  389,  389,  389,  389,  389,
+
+      390,  390,  390,  390,  390,  390,  390,  399,  399,  399,
+      246,  246,  246,  246,  246,  246,  246,  403,  403,  403,
+      250,  250,  250,  250,  250,  250,  250,  407,  407,  407,
+      408,  408,  408,  408,  408,  408,  415,  415,  415,  415,
+      415,  415,  416,  416,  416,  416,  416,  416,  423,  423,
+      423,  423,  423,  423, 1518,  423,  430,  430,  430,  430,
+      430,  430, 1518,  430,  438,  438,  438,  438,  350,  350,
+      350,  350,  442,  442,  442,  442,  354,  354,  354,  354,
+      445,  445,  445,  445,  445,  445, 1518,  445,  447,  447,
+      447,  447,  447,  447,  447, 1518,  447,  453,  453,  453,
+
+      454,  454,  454,  455,  455,  455,  459,  459,  459,  462,
+      462,  462,  463,  463,  463,  463,  463,  463,  464,  464,
+      464,  464,  464,  464,  471,  471,  471,  471,  471,  471,
+      478,  478,  478,  478,  478,  478,  485,  485,  485,  485,
+      485,  485,  493,  493,  493,  493,  396,  396,  396,  396,
+      497,  497,  497,  497,  400,  400,  400,  400,  501,  501,
+      501,  501,  404,  404,  404,  404,  504,  504,  504,  504,
+      504,  504,  506,  506,  506,  506,  506,  506,  506,  512,
+      512,  512,  512,  512,  512,  513,  513,  513,  513,  513,
+      513,  515,  515,  515,  515,  515,  515,  515, 1518,  515,
+
+      521,  521,  521,  521,  521,  521, 1518,  521,  522,  522,
+      522,  522,  522,  522,  522, 1518,  522,  528,  528,  528,
+      528,  528,  528, 1518,  528,  529,  529,  529,  529,  529,
+      529,  529, 1518,  529,  538,  538,  538,  350,  350,  350,
+      350,  350,  350,  350,  542,  542,  542,  354,  354,  354,
+      354,  354,  354,  354,  546,  546,  546,  547,  547,  547,
+      547,  547,  547, 1518,  547,  554,  554,  554,  555,  555,
+      555,  556,  556,  556,  559,  559,  559,  560,  560,  560,
+      560,  560,  560,  561,  561,  561,  561,  561,  561,  563,
+      563,  563,  563,  563,  563,  563,  569,  569,  569,  569,
+
+      569,  569,  570,  570,  570,  570,  570,  570,  570,  576,
+      576,  576,  576,  576,  576,  577,  577,  577,  577,  577,
+      577,  577,  583,  583,  583,  583,  583,  583,  584,  584,
+      584,  584,  584,  584,  584,  590,  590,  396,  396,  396,
+      396,  396,  396, 1518,  396,  596,  596,  596,  400,  400,
+      400,  400,  400,  400,  400,  600,  600,  600,  404,  404,
+      404,  404,  404,  404,  404,  604,  604,  604,  605,  605,
+      605,  605,  605,  605,  612,  612,  612,  612,  612,  612,
+      613,  613,  613,  613,  613,  613,  620,  620,  620,  620,
+      620,  620, 1518,  620,  627,  627,  627,  627,  627,  627,
+
+     1518,  627,  634,  634,  634,  634,  634,  634, 1518,  634,
+      642,  642,  642,  642, 1518, 1518, 1518,  642,  535,  535,
+      535,  535, 1518, 1518, 1518,  535,  646,  646,  646,  646,
+      539,  539,  539,  539,  650,  650,  650,  650,  543,  543,
+      543,  543,  653,  653,  653,  653,  653,  653, 1518,  653,
+      655,  655,  655,  655,  655,  655,  655, 1518,  655,  661,
+      661,  661,  662,  662,  662,  663,  663,  663,  667,  667,
+      667,  667,  667,  667,  668,  668,  668,  668,  668,  668,
+      675,  675,  675,  675,  675,  675,  682,  682,  682,  682,
+      682,  682,  689,  689,  689,  689,  689,  689,  696,  696,
+
+      696,  696,  696,  696,  703,  703,  703,  706,  706,  706,
+      708,  708,  708,  708,  593,  593,  593,  593,  712,  712,
+      712,  712,  597,  597,  597,  597,  716,  716,  716,  716,
+      601,  601,  601,  601,  719,  719,  719,  719,  719,  719,
+      721,  721,  721,  721,  721,  721,  721,  727,  727,  727,
+      727,  727,  727,  728,  728,  728,  728,  728,  728,  730,
+      730,  730,  730,  730,  730,  730, 1518,  730,  736,  736,
+      736,  736,  736,  736, 1518,  736,  737,  737,  737,  737,
+      737,  737,  737, 1518,  737,  743,  743,  743,  743,  743,
+      743, 1518,  743,  744,  744,  744,  744,  744,  744,  744,
+
+     1518,  744,  750,  750,  750,  750,  750,  750, 1518,  750,
+      751,  751,  751,  751,  751,  751,  751, 1518,  751,  757,
+      757,  535,  535,  535,  535, 1518, 1518, 1518,  535,  535,
+      535, 1518,  535, 1518, 1518, 1518,  535,  763,  763,  763,
+      539,  539,  539,  539,  539,  539,  539,  767,  767,  767,
+      543,  543,  543,  543,  543,  543,  543,  771,  771,  771,
+      772,  772,  772,  772,  772,  772, 1518,  772,  779,  779,
+      779,  780,  780,  780,  780,  780,  780,  787,  787,  787,
+      787,  787,  787,  787,  793,  793,  793,  793,  793,  793,
+      794,  794,  794,  794,  794,  794,  794,  800,  800,  800,
+
+      800,  800,  800,  801,  801,  801,  801,  801,  801,  801,
+      807,  807,  807,  807,  807,  807,  808,  808,  808,  808,
+      808,  808,  808,  814,  814,  814,  814,  814,  814,  815,
+      815,  815,  815,  815,  815,  815,  821,  821,  821,  822,
+      822,  822,  825,  825,  825,  826,  826,  593,  593,  593,
+      593,  593,  593, 1518,  593,  832,  832,  832,  597,  597,
+      597,  597,  597,  597,  597,  836,  836,  836,  601,  601,
+      601,  601,  601,  601,  601,  840,  840,  840,  841,  841,
+      841,  841,  841,  841,  848,  848,  848,  848,  848,  848,
+      849,  849,  849,  849,  849,  849,  856,  856,  856,  856,
+
+      856,  856, 1518,  856,  863,  863,  863,  863,  863,  863,
+     1518,  863,  870,  870,  870,  870,  870,  870, 1518,  870,
+      877,  877,  877,  877,  877,  877, 1518,  877,  884,  884,
+      884, 1518, 1518, 1518, 1518,  884,  887,  887,  887, 1518,
+     1518, 1518, 1518,  887,  889,  889,  889,  889, 1518, 1518,
+     1518,  889,  760,  760,  760,  760, 1518, 1518, 1518,  760,
+      893,  893,  893,  893,  764,  764,  764,  764,  897,  897,
+      897,  897,  768,  768,  768,  768,  900,  900,  900,  900,
+      900,  900, 1518,  900,  902,  902,  902,  902,  902,  902,
+      902, 1518,  902,  908,  908,  908,  908,  908,  908,  910,
+
+      910,  910,  910,  910,  910,  910,  916,  916,  916, 1518,
+      916,  916,  917,  917,  917,  917,  917,  917,  918,  918,
+      918, 1518,  918,  918,  920,  920,  920,  920,  920,  920,
+      921,  921,  921, 1518,  921,  921,  923,  923,  923,  923,
+      923,  923,  924,  924,  924, 1518,  924,  924,  926,  926,
+      926,  926,  926,  926,  927,  927,  927, 1518,  927,  927,
+      929,  929,  929,  929,  929,  929,  930,  930,  930, 1518,
+      930,  930,  932,  932,  932,  933,  933,  933,  934,  934,
+      934,  938,  938,  938,  941,  941,  941,  943,  943,  943,
+      943,  829,  829,  829,  829,  947,  947,  947,  947,  833,
+
+      833,  833,  833,  951,  951,  951,  951,  837,  837,  837,
+      837,  954,  954,  954,  954,  954,  954,  956,  956,  956,
+      956,  956,  956,  956,  962,  962,  962,  962,  962,  962,
+      969,  969,  969,  969,  969,  969,  969, 1518,  969,  975,
+      975,  975,  975,  975,  975, 1518,  975,  976,  976,  976,
+      976,  976,  976,  976, 1518,  976,  982,  982,  982,  982,
+      982,  982, 1518,  982,  983,  983,  983,  983,  983,  983,
+      983, 1518,  983,  989,  989,  989,  989,  989,  989, 1518,
+      989,  990,  990,  990,  990,  990,  990,  990, 1518,  990,
+      996,  996,  996,  996,  996,  996, 1518,  996,  997,  997,
+
+      997,  997,  997,  997,  997, 1518,  997, 1003, 1003, 1003,
+     1518, 1518, 1518, 1518, 1003, 1004, 1004, 1004, 1518, 1518,
+     1518, 1518, 1004, 1007, 1007, 1007, 1518, 1518, 1518, 1518,
+     1007, 1008, 1008,  760,  760,  760,  760, 1518, 1518, 1518,
+      760,  760,  760, 1518,  760, 1518, 1518, 1518,  760, 1014,
+     1014, 1014,  764,  764,  764,  764,  764,  764,  764, 1018,
+     1018, 1018,  768,  768,  768,  768,  768,  768,  768, 1022,
+     1022, 1022, 1023, 1023, 1023, 1023, 1023, 1023, 1518, 1023,
+     1033, 1033, 1033, 1034, 1034, 1034, 1034, 1034, 1034, 1035,
+     1035, 1035, 1035, 1035, 1035, 1038, 1038, 1038, 1518, 1038,
+
+     1038, 1039, 1039, 1039, 1039, 1039, 1039, 1040, 1040, 1040,
+     1518, 1040, 1040, 1041, 1041, 1041, 1041, 1041, 1041, 1042,
+     1042, 1042, 1518, 1042, 1042, 1043, 1043, 1043, 1043, 1043,
+     1043, 1044, 1044, 1044, 1518, 1044, 1044, 1045, 1045, 1045,
+     1045, 1045, 1045, 1046, 1046, 1046, 1518, 1046, 1046, 1047,
+     1047, 1047, 1047, 1047, 1047, 1048, 1048, 1048, 1518, 1048,
+     1048, 1049, 1049, 1049, 1050, 1050, 1050, 1051, 1051, 1051,
+     1054, 1054, 1054, 1055, 1055,  829,  829,  829,  829,  829,
+      829, 1518,  829, 1061, 1061, 1061,  833,  833,  833,  833,
+      833,  833,  833, 1065, 1065, 1065,  837,  837,  837,  837,
+
+      837,  837,  837, 1069, 1069, 1069, 1070, 1070, 1070, 1070,
+     1070, 1070, 1071, 1071, 1071, 1518, 1071, 1071, 1073, 1073,
+     1073, 1073, 1073, 1073, 1075, 1075, 1075, 1075, 1075, 1075,
+     1075, 1081, 1081, 1081, 1518, 1081, 1081, 1518, 1081, 1082,
+     1082, 1082, 1082, 1082, 1082, 1518, 1082, 1083, 1083, 1083,
+     1518, 1083, 1083, 1085, 1085, 1085, 1085, 1085, 1085, 1518,
+     1085, 1086, 1086, 1086, 1518, 1086, 1086, 1088, 1088, 1088,
+     1088, 1088, 1088, 1518, 1088, 1089, 1089, 1089, 1518, 1089,
+     1089, 1091, 1091, 1091, 1091, 1091, 1091, 1518, 1091, 1092,
+     1092, 1092, 1518, 1092, 1092, 1094, 1094, 1094, 1094, 1094,
+
+     1094, 1518, 1094, 1095, 1095, 1095, 1518, 1095, 1095, 1097,
+     1097, 1097, 1518, 1518, 1518, 1518, 1097, 1098, 1098, 1098,
+     1518, 1518, 1518, 1518, 1098, 1099, 1099, 1099, 1518, 1518,
+     1518, 1518, 1099, 1103, 1103, 1103, 1518, 1518, 1518, 1518,
+     1103, 1106, 1106, 1106, 1518, 1518, 1518, 1518, 1106, 1108,
+     1108, 1108, 1108, 1518, 1518, 1518, 1108, 1011, 1011, 1011,
+     1011, 1518, 1518, 1518, 1011, 1112, 1112, 1112, 1112, 1015,
+     1015, 1015, 1015, 1116, 1116, 1116, 1116, 1019, 1019, 1019,
+     1019, 1119, 1119, 1119, 1119, 1119, 1119, 1518, 1119, 1121,
+     1121, 1121, 1121, 1121, 1121, 1121, 1518, 1121, 1128, 1128,
+
+     1128, 1128, 1030, 1030, 1030, 1030, 1131, 1131, 1131, 1131,
+     1131, 1131, 1132, 1132, 1132, 1518, 1132, 1132, 1133, 1133,
+     1133, 1518, 1133, 1133, 1134, 1134, 1134, 1518, 1134, 1134,
+     1135, 1135, 1135, 1518, 1135, 1135, 1136, 1136, 1136, 1518,
+     1136, 1136, 1137, 1137, 1137, 1518, 1137, 1137, 1138, 1138,
+     1138, 1518, 1138, 1138, 1139, 1139, 1139, 1140, 1140, 1140,
+     1141, 1141, 1141, 1145, 1145, 1145, 1148, 1148, 1148, 1150,
+     1150, 1150, 1150, 1058, 1058, 1058, 1058, 1154, 1154, 1154,
+     1154, 1062, 1062, 1062, 1062, 1158, 1158, 1158, 1158, 1066,
+     1066, 1066, 1066, 1161, 1161, 1161, 1161, 1161, 1161, 1162,
+
+     1162, 1162, 1518, 1162, 1162, 1166, 1166, 1166, 1167, 1167,
+     1167, 1167, 1167, 1167, 1168, 1168, 1168, 1168, 1168, 1168,
+     1171, 1171, 1171, 1518, 1171, 1171, 1518, 1171, 1172, 1172,
+     1172, 1172, 1172, 1172, 1518, 1172, 1173, 1173, 1173, 1518,
+     1173, 1173, 1518, 1173, 1174, 1174, 1174, 1174, 1174, 1174,
+     1518, 1174, 1175, 1175, 1175, 1518, 1175, 1175, 1518, 1175,
+     1176, 1176, 1176, 1176, 1176, 1176, 1518, 1176, 1177, 1177,
+     1177, 1518, 1177, 1177, 1518, 1177, 1178, 1178, 1178, 1178,
+     1178, 1178, 1518, 1178, 1179, 1179, 1179, 1518, 1179, 1179,
+     1518, 1179, 1180, 1180, 1180, 1180, 1180, 1180, 1518, 1180,
+
+     1181, 1181, 1181, 1518, 1181, 1181, 1518, 1181, 1182, 1182,
+     1182, 1518, 1518, 1518, 1518, 1182, 1182, 1182, 1518, 1518,
+     1518, 1518, 1518, 1182, 1183, 1183, 1183, 1518, 1518, 1518,
+     1518, 1183, 1184, 1184, 1184, 1518, 1518, 1518, 1518, 1184,
+     1187, 1187, 1187, 1518, 1518, 1518, 1518, 1187, 1188, 1188,
+     1011, 1011, 1011, 1011, 1518, 1518, 1518, 1011, 1011, 1011,
+     1518, 1011, 1518, 1518, 1518, 1011, 1194, 1194, 1194, 1015,
+     1015, 1015, 1015, 1015, 1015, 1015, 1198, 1198, 1198, 1019,
+     1019, 1019, 1019, 1019, 1019, 1019, 1202, 1202, 1202, 1203,
+     1203, 1203, 1203, 1203, 1203, 1518, 1203, 1204, 1204, 1204,
+
+     1518, 1204, 1204, 1209, 1209, 1209, 1030, 1030, 1030, 1030,
+     1030, 1030, 1030, 1210, 1210, 1210, 1518, 1210, 1210, 1211,
+     1211, 1211, 1518, 1211, 1211, 1212, 1212, 1212, 1518, 1212,
+     1212, 1213, 1213, 1213, 1518, 1213, 1213, 1214, 1214, 1214,
+     1518, 1214, 1214, 1215, 1215, 1215, 1518, 1215, 1215, 1216,
+     1216, 1216, 1518, 1216, 1216, 1217, 1217, 1217, 1218, 1218,
+     1218, 1219, 1219, 1219, 1222, 1222, 1222, 1223, 1223, 1058,
+     1058, 1058, 1058, 1058, 1058, 1518, 1058, 1229, 1229, 1229,
+     1062, 1062, 1062, 1062, 1062, 1062, 1062, 1233, 1233, 1233,
+     1066, 1066, 1066, 1066, 1066, 1066, 1066, 1234, 1234, 1234,
+
+     1518, 1234, 1234, 1236, 1236, 1236, 1236, 1163, 1163, 1163,
+     1163, 1239, 1239, 1239, 1239, 1239, 1239, 1240, 1240, 1240,
+     1518, 1240, 1240, 1518, 1240, 1241, 1241, 1241, 1518, 1241,
+     1241, 1518, 1241, 1242, 1242, 1242, 1518, 1242, 1242, 1518,
+     1242, 1243, 1243, 1243, 1518, 1243, 1243, 1518, 1243, 1244,
+     1244, 1244, 1518, 1244, 1244, 1518, 1244, 1245, 1245, 1245,
+     1518, 1245, 1245, 1518, 1245, 1246, 1246, 1246, 1518, 1246,
+     1246, 1518, 1246, 1247, 1247, 1247, 1518, 1518, 1518, 1518,
+     1247, 1248, 1248, 1248, 1518, 1518, 1518, 1518, 1248, 1249,
+     1249, 1249, 1518, 1518, 1518, 1518, 1249, 1253, 1253, 1253,
+
+     1518, 1518, 1518, 1518, 1253, 1256, 1256, 1256, 1518, 1518,
+     1518, 1518, 1256, 1258, 1258, 1258, 1258, 1518, 1518, 1518,
+     1258, 1191, 1191, 1191, 1191, 1518, 1518, 1518, 1191, 1262,
+     1262, 1262, 1262, 1195, 1195, 1195, 1195, 1266, 1266, 1266,
+     1266, 1199, 1199, 1199, 1199, 1269, 1269, 1269, 1269, 1269,
+     1269, 1518, 1269, 1270, 1270, 1270, 1518, 1270, 1270, 1518,
+     1270, 1272, 1272, 1272, 1272, 1206, 1206, 1206, 1206, 1036,
+     1036, 1036, 1518, 1036, 1036, 1275, 1275, 1275, 1276, 1276,
+     1276, 1277, 1277, 1277, 1281, 1281, 1281, 1284, 1284, 1284,
+     1286, 1286, 1286, 1286, 1226, 1226, 1226, 1226, 1290, 1290,
+
+     1290, 1290, 1230, 1230, 1230, 1230, 1293, 1293, 1293, 1518,
+     1293, 1293, 1297, 1297, 1297, 1163, 1163, 1163, 1298, 1298,
+     1298, 1518, 1298, 1298, 1518, 1298, 1299, 1299, 1299, 1518,
+     1299, 1299, 1518, 1299, 1300, 1300, 1300, 1518, 1300, 1300,
+     1518, 1300, 1301, 1301, 1301, 1518, 1301, 1301, 1518, 1301,
+     1302, 1302, 1302, 1518, 1302, 1302, 1518, 1302, 1303, 1303,
+     1303, 1518, 1303, 1303, 1518, 1303, 1304, 1304, 1304, 1518,
+     1304, 1304, 1518, 1304, 1305, 1305, 1305, 1518, 1518, 1518,
+     1518, 1305, 1305, 1305, 1518, 1518, 1518, 1518, 1518, 1305,
+     1306, 1306, 1306, 1518, 1518, 1518, 1518, 1306, 1307, 1307,
+
+     1307, 1518, 1518, 1518, 1518, 1307, 1310, 1310, 1310, 1518,
+     1518, 1518, 1518, 1310, 1311, 1311, 1191, 1191, 1518, 1191,
+     1518, 1518, 1518, 1191, 1317, 1317, 1317, 1195, 1195, 1195,
+     1321, 1321, 1321, 1199, 1199, 1199, 1322, 1322, 1322, 1518,
+     1322, 1322, 1518, 1322, 1326, 1326, 1326, 1206, 1206, 1206,
+     1327, 1327, 1327, 1328, 1328, 1328, 1329, 1329, 1329, 1332,
+     1332, 1332, 1333, 1333, 1226, 1226, 1518, 1226, 1339, 1339,
+     1339, 1230, 1230, 1230, 1341, 1341, 1341, 1341, 1294, 1294,
+     1294, 1294, 1169, 1169, 1169, 1518, 1169, 1169, 1518, 1169,
+     1344, 1344, 1344, 1518, 1518, 1518, 1518, 1344, 1345, 1345,
+
+     1345, 1518, 1518, 1518, 1518, 1345, 1346, 1346, 1346, 1518,
+     1518, 1518, 1518, 1346, 1350, 1350, 1350, 1518, 1518, 1518,
+     1518, 1350, 1353, 1353, 1353, 1518, 1518, 1518, 1518, 1353,
+     1355, 1355, 1355, 1355, 1518, 1518, 1518, 1355, 1314, 1314,
+     1314, 1314, 1518, 1518, 1518, 1314, 1359, 1359, 1359, 1359,
+     1318, 1318, 1318, 1318, 1362, 1362, 1362, 1518, 1362, 1362,
+     1518, 1362, 1364, 1364, 1364, 1364, 1323, 1323, 1323, 1323,
+     1367, 1367, 1367, 1368, 1368, 1368, 1369, 1369, 1369, 1373,
+     1373, 1373, 1376, 1376, 1376, 1378, 1378, 1378, 1378, 1336,
+     1336, 1336, 1336, 1384, 1384, 1384, 1294, 1294, 1294, 1385,
+
+     1385, 1385, 1518, 1518, 1518, 1518, 1385, 1385, 1385, 1518,
+     1518, 1518, 1518, 1518, 1385, 1386, 1386, 1386, 1518, 1518,
+     1518, 1518, 1386, 1387, 1387, 1387, 1518, 1518, 1518, 1518,
+     1387, 1390, 1390, 1390, 1518, 1518, 1518, 1518, 1390, 1391,
+     1391, 1314, 1314, 1518, 1314, 1518, 1518, 1518, 1314, 1397,
+     1397, 1397, 1318, 1318, 1318, 1398, 1398, 1323, 1323, 1518,
+     1323, 1401, 1401, 1401, 1402, 1402, 1402, 1403, 1403, 1403,
+     1406, 1406, 1406, 1407, 1407, 1336, 1336, 1518, 1336, 1411,
+     1411, 1411, 1411, 1518, 1518, 1518, 1411, 1381, 1381, 1381,
+     1381, 1518, 1518, 1518, 1381, 1414, 1414, 1414, 1518, 1518,
+
+     1518, 1518, 1414, 1415, 1415, 1415, 1518, 1518, 1518, 1518,
+     1415, 1416, 1416, 1416, 1518, 1518, 1518, 1518, 1416, 1420,
+     1420, 1420, 1518, 1518, 1518, 1518, 1420, 1423, 1423, 1423,
+     1518, 1518, 1518, 1518, 1423, 1425, 1425, 1425, 1425, 1518,
+     1518, 1518, 1425, 1394, 1394, 1394, 1394, 1518, 1518, 1518,
+     1394, 1428, 1428, 1428, 1431, 1431, 1431, 1432, 1432, 1432,
+     1433, 1433, 1433, 1434, 1434, 1434, 1438, 1438, 1438, 1441,
+     1441, 1441, 1442, 1442, 1381, 1381, 1518, 1381, 1518, 1518,
+     1518, 1381, 1445, 1445, 1445, 1518, 1518, 1518, 1518, 1445,
+     1445, 1445, 1518, 1518, 1518, 1518, 1518, 1445, 1446, 1446,
+
+     1446, 1518, 1518, 1518, 1518, 1446, 1447, 1447, 1447, 1518,
+     1518, 1518, 1518, 1447, 1450, 1450, 1450, 1518, 1518, 1518,
+     1518, 1450, 1451, 1451, 1394, 1394, 1518, 1394, 1518, 1518,
+     1518, 1394, 1454, 1454, 1454, 1455, 1455, 1455, 1458, 1458,
+     1458, 1459, 1459, 1459, 1460, 1460, 1460, 1461, 1461, 1461,
+     1464, 1464, 1464, 1465, 1465, 1465, 1518, 1518, 1518, 1518,
+     1465, 1468, 1468, 1468, 1518, 1518, 1518, 1518, 1468, 1469,
+     1469, 1469, 1518, 1518, 1518, 1518, 1469, 1470, 1470, 1470,
+     1518, 1518, 1518, 1518, 1470, 1471, 1471, 1471, 1518, 1518,
+     1518, 1518, 1471, 1475, 1475, 1475, 1518, 1518, 1518, 1518,
+
+     1475, 1478, 1478, 1478, 1518, 1518, 1518, 1518, 1478, 1479,
+     1479, 1479, 1480, 1480, 1480, 1481, 1481, 1481, 1485, 1485,
+     1485, 1486, 1486, 1486, 1487, 1487, 1487, 1491, 1491, 1491,
+     1518, 1518, 1518, 1518, 1491, 1492, 1492, 1492, 1518, 1518,
+     1518, 1518, 1492, 1495, 1495, 1495, 1518, 1518, 1518, 1518,
+     1495, 1496, 1496, 1496, 1518, 1518, 1518, 1518, 1496, 1496,
+     1496, 1518, 1518, 1518, 1518, 1518, 1496, 1497, 1497, 1497,
+     1518, 1518, 1518, 1518, 1497, 1498, 1498, 1498, 1518, 1518,
+     1518, 1518, 1498, 1501, 1501, 1501, 1518, 1518, 1518, 1518,
+     1501, 1502, 1502, 1502, 1503, 1503, 1503, 1504, 1504, 1504,
+
+     1518, 1518, 1518, 1518, 1504, 1505, 1505, 1505, 1518, 1518,
+     1518, 1518, 1505, 1506, 1506, 1506, 1518, 1518, 1518, 1518,
+     1506, 1510, 1510, 1510, 1518, 1518, 1518, 1518, 1510, 1511,
+     1511, 1511, 1518, 1518, 1518, 1518, 1511, 1512, 1512, 1512,
+     1518, 1518, 1518, 1518, 1512, 1516, 1516, 1516, 1518, 1518,
+     1518, 1518, 1516, 1516, 1516, 1518, 1518, 1518, 1518, 1518,
+     1516, 1517, 1517, 1517, 1518, 1518, 1518, 1518, 1517, 1517,
+     1517, 1518, 1518, 1518, 1518, 1518, 1517,    5, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518
+    } ;
+
+static yyconst flex_int16_t yy_chk[10018] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,   10,
+       25,   25,   28,   40,   28,   36,   36,   41,   41,   41,
+       40, 1498,   31,   34,   50,   50,   50, 1499,   63,   65,
+       65,   10,   15, 1504,   15,   15,   15,   15,   15,   15,
+       15,   15,   15,   15,   31,   34,   15,   15,   15,   15,
+       63,   67,   92,   15,   15,   15,   15,   15,   15,   15,
+       15,   15,   15,   15,   16,   16,   16,   16,   16,   16,
+
+       16,   16,   16,   67,   92,   97,   97,   97, 1505,   16,
+       17,   17,   17,   17,   17,   17,   17,   17,   17,   18,
+       18,   18,   18,   18,   18,   22,   82,   22,   22,   22,
+       22,   22,   22,   22,   22,   22,   42,   82,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42, 1506, 1507,
+       42,   42,   42,   42, 1508,   95, 1509,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,   43,   43,
+       43,   43,   43,   43,   43,   43,   45,   95,   45,   45,
+       45,   45,   45,   45,   45,   45,   45,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,  100,  100,  100,   47,
+
+       47,   47,   47,  111,  111,  111,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   48, 1510,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   52,   52,
+       52,   52,   52,   52,   52,   52,   52,   69,   71,   69,
+       52,   52,   72,   86,  106,  110, 1511,   52,   52,   52,
+      116,  116,  116,   71,   86,  106,  110,   72, 1512,  128,
+       71,   69, 1513, 1514,   72,   73,  117,   73,   73,   73,
+       73,   73,   73,   73,   73,   73,  165,  117, 1515, 1516,
+       73,  128,   94, 1517,   94,  165,  206,   73,   74,   74,
+       74,   74,   74,   74,   75,  206,   75,   75,   75,   75,
+
+       75,   75,   75,   75,   75,   75,   94, 1497,   75,   75,
+       75,   75,  143,  143,  143,   75,   75,   75,   75,   75,
+       75,   75,   75,   75,   75,   75,   76,   76,   76,   76,
+       76,   76,   76,   76,   77, 1496,   77,   77,   77,   77,
+       77,   77,   77,   77,   77,   79,   79,   79,   79,   79,
+       79,   79,   79,   79,  164,  164,  164,   79,   79,  169,
+      169,  169, 1493, 1492,   79,   79,   79,   83,  144,   83,
+       83,   83,   83,   83,   83,   83,   83,   83,   83,  144,
+     1491,   83,   83,  171,  171,  171, 1478, 1476,   83,   83,
+       83,   84,  150,   84,   84,   84,   84,   84,   84,   84,
+
+       84,   84,   84,  150, 1475,   84,   84,  172,  172,  172,
+     1474, 1473,   84,   84,   84,   85,   85,   85,   85,   85,
+       85,   89,   89,   89,   89,   89,   89,   89,   89,   89,
+      191,  191,  191,   89,   89,  196,  196,  196, 1472,   89,
+       89,   89,   89,  101, 1471,  101,  101,  101,  101,  101,
+      101,  101,  101,  101,  101,  102,  102,  102,  102,  102,
+      102,  102,  102,  107,  154,  107,  107,  107,  107,  107,
+      107,  107,  107,  107,  107,  154, 1470,  107,  107,  201,
+      201,  201, 1469, 1468,  107,  107,  107,  108,  155,  108,
+      108,  108,  108,  108,  108,  108,  108,  108,  108,  155,
+
+     1466,  108,  108,  210,  210,  210, 1465, 1453,  108,  108,
+      108,  109,  109,  109,  109,  109,  109,  113,  113,  113,
+      113,  113,  113,  113,  113,  113,  216, 1451, 1448,  113,
+      113,  237,  237,  237, 1447,  216,  113,  113,  113,  114,
+      179,  114,  114,  114,  114,  114,  114,  114,  114,  114,
+      114,  179, 1446,  114,  114,  244,  244,  244, 1445, 1444,
+      114,  114,  114,  120,  120,  120,  120,  120,  120,  120,
+      120,  120, 1442, 1423,  121,  120,  120,  183,  185,  189,
+      190,  120,  120,  120,  120,  121, 1421, 1420,  183,  185,
+      189,  190, 1419, 1418,  121,  122,  202,  122,  122,  122,
+
+      122,  122,  122,  122,  122,  122,  122,  202, 1417,  122,
+      122,  276,  276,  276, 1416,  122,  122,  122,  122,  123,
+      238,  123,  123,  123,  123,  123,  123,  123,  123,  123,
+      123,  238, 1415,  123,  123,  281,  281,  281,  125,  123,
+      123,  123,  123,  124,  124,  124,  124,  124,  124,  125,
+     1414,  269,  286,  286,  286,  292,  292,  292,  125,  132,
+      269,  132,  132,  132,  132,  132,  132,  132,  132,  132,
+      138,  138,  138,  138,  138,  138,  138,  138,  138,  280,
+     1393, 1391,  138,  138,  318,  318,  318, 1388,  280,  138,
+      138,  138,  140,  140,  140,  140,  140,  140,  140,  140,
+
+      140,  282, 1387, 1386,  140,  140,  322,  322,  322, 1385,
+      282,  140,  140,  140,  141,  245,  141,  141,  141,  141,
+      141,  141,  141,  141,  141,  141,  245, 1380,  141,  141,
+      327,  327,  327, 1379, 1378,  141,  141,  141,  147,  255,
+      147,  147,  147,  147,  147,  147,  147,  147,  147,  151,
+      255,  151,  151,  151,  151,  151,  151,  151,  151,  151,
+      151, 1366, 1365,  151,  151,  332,  332,  332, 1364, 1362,
+      151,  151,  151,  152,  259,  152,  152,  152,  152,  152,
+      152,  152,  152,  152,  152,  259, 1361,  152,  152,  341,
+      341,  341,  159,  260,  152,  152,  152,  153,  153,  153,
+
+      153,  153,  153,  159,  260,  348,  348,  348,  369,  369,
+      369,  369,  159,  160,  299,  160,  160,  160,  160,  160,
+      160,  160,  160,  160,  160,  299, 1360,  160,  160,  380,
+      380,  380, 1359,  160,  160,  160,  160,  161,  303,  161,
+      161,  161,  161,  161,  161,  161,  161,  161,  161,  303,
+     1353,  161,  161,  387,  387,  387,  163,  161,  161,  161,
+      161,  162,  162,  162,  162,  162,  162,  163,  394,  394,
+      394,  437,  437,  437, 1351,  170,  163,  166,  166,  166,
+      166,  166,  166,  166,  166,  166,  170, 1350, 1349,  166,
+      166,  441,  441,  441, 1348,  170,  166,  166,  166,  167,
+
+      305,  167,  167,  167,  167,  167,  167,  167,  167,  167,
+      167,  305, 1347,  167,  167,  446,  446,  446, 1346,  167,
+      167,  167,  167,  180,  309,  180,  180,  180,  180,  180,
+      180,  180,  180,  180,  180,  309, 1345,  180,  180,  451,
+      451,  451, 1344, 1343,  180,  180,  180,  181,  310,  181,
+      181,  181,  181,  181,  181,  181,  181,  181,  181,  310,
+     1342,  181,  181,  457,  457,  457, 1341,  312,  181,  181,
+      181,  182,  182,  182,  182,  182,  182,  186,  312,  186,
+      186,  186,  186,  186,  186,  186,  186,  186,  186, 1339,
+     1337,  186,  186,  492,  492,  492, 1336, 1326,  186,  186,
+
+      186,  187,  316,  187,  187,  187,  187,  187,  187,  187,
+      187,  187,  187,  316, 1324,  187,  187,  496,  496,  496,
+     1323, 1322,  187,  187,  187,  188,  188,  188,  188,  188,
+      188,  198,  198,  198,  198,  198,  198,  198,  198,  198,
+      337, 1321, 1319,  198,  198,  500,  500,  500, 1318,  337,
+      198,  198,  198,  199,  317,  199,  199,  199,  199,  199,
+      199,  199,  199,  199,  199,  317, 1313,  199,  199,  505,
+      505,  505, 1311, 1308,  199,  199,  199,  205,  205,  205,
+      205,  205,  205,  205,  205,  205,  510,  510,  510,  205,
+      205,  519,  519,  519, 1307,  205,  205,  205,  205,  207,
+
+      207,  207,  207,  207,  207,  207,  207,  207,  343, 1306,
+     1305,  207,  207,  526,  526,  526, 1304,  343,  207,  207,
+      207,  208,  333,  208,  208,  208,  208,  208,  208,  208,
+      208,  208,  208,  333,  211,  208,  208,  344,  358,  381,
+      388,  208,  208,  208,  208,  211,  344,  358, 1303, 1302,
+      381,  388, 1301, 1300,  211,  214,  217,  214,  214,  214,
+      214,  214,  214,  214,  214,  214,  423,  217,  533,  533,
+      533,  559,  559,  559,  559,  423,  217,  218,  395,  218,
+      218,  218,  218,  218,  218,  218,  218,  218,  218,  395,
+     1299,  218,  218,  567,  567,  567, 1298,  218,  218,  218,
+
+      218,  219,  409,  219,  219,  219,  219,  219,  219,  219,
+      219,  219,  219,  409, 1297,  219,  219,  574,  574,  574,
+      221,  219,  219,  219,  219,  220,  220,  220,  220,  220,
+      220,  221,  222,  413,  414, 1295, 1294,  430,  445,  447,
+      221,  515,  521,  222,  413,  414,  430,  445,  447, 1292,
+      515,  521,  222,  224,  224,  224,  224,  224,  224,  224,
+      224,  224,  228,  228,  228,  228,  228,  228,  228,  228,
+      228,  228,  232,  232,  232,  232,  232,  232,  232,  232,
+      232,  522, 1291, 1290,  232,  232,  581,  581,  581, 1288,
+      522,  232,  232,  232,  234,  234,  234,  234,  234,  234,
+
+      234,  234,  234,  528, 1287, 1286,  234,  234,  588,  588,
+      588, 1274,  528,  234,  234,  234,  235,  466,  235,  235,
+      235,  235,  235,  235,  235,  235,  235,  235,  466, 1273,
+      235,  235,  641,  641,  641, 1272, 1270,  235,  235,  235,
+      241,  241,  241,  241,  241,  241,  241,  241,  241,  529,
+     1268, 1267,  241,  241,  645,  645,  645, 1266,  529,  241,
+      241,  241,  242,  470,  242,  242,  242,  242,  242,  242,
+      242,  242,  242,  242,  470, 1264,  242,  242,  649,  649,
+      649, 1263, 1262,  242,  242,  242,  248,  472,  248,  248,
+      248,  248,  248,  248,  248,  248,  248,  252,  472,  252,
+
+      252,  252,  252,  252,  252,  252,  252,  252,  256,  476,
+      256,  256,  256,  256,  256,  256,  256,  256,  256,  256,
+      476, 1256,  256,  256,  654,  654,  654, 1254, 1253,  256,
+      256,  256,  257,  477,  257,  257,  257,  257,  257,  257,
+      257,  257,  257,  257,  477, 1252,  257,  257,  659,  659,
+      659,  264,  479,  257,  257,  257,  258,  258,  258,  258,
+      258,  258,  264,  479,  665,  665,  665,  707,  707,  707,
+     1251,  264,  265,  483,  265,  265,  265,  265,  265,  265,
+      265,  265,  265,  265,  483, 1250,  265,  265,  711,  711,
+      711, 1249,  265,  265,  265,  265,  266,  484,  266,  266,
+
+      266,  266,  266,  266,  266,  266,  266,  266,  484, 1248,
+      266,  266,  715,  715,  715,  268,  266,  266,  266,  266,
+      267,  267,  267,  267,  267,  267,  268,  270,  486,  274,
+      490,  491,  511,  568, 1247,  268,  535,  536,  270,  486,
+      274,  490,  491,  511,  568,  535,  536,  270,  271,  274,
+      271,  271,  271,  271,  271,  271,  271,  271,  271,  271,
+     1246, 1245,  271,  271,  538,  720,  720,  720,  271,  271,
+      271,  271,  272,  538,  272,  272,  272,  272,  272,  272,
+      272,  272,  272,  272, 1244, 1243,  272,  272,  725,  725,
+      725,  275,  272,  272,  272,  272,  273,  273,  273,  273,
+
+      273,  273,  275,  734,  734,  734,  741,  741,  741, 1242,
+      287,  275,  283,  283,  283,  283,  283,  283,  283,  283,
+      283,  287, 1241, 1240,  283,  283,  547,  748,  748,  748,
+      287,  283,  283,  283,  284,  547,  284,  284,  284,  284,
+      284,  284,  284,  284,  284,  284, 1239, 1238,  284,  284,
+      755,  755,  755, 1237,  284,  284,  284,  284,  290,  290,
+      290,  290,  290,  290,  290,  290,  290,  300,  575,  300,
+      300,  300,  300,  300,  300,  300,  300,  300,  300,  575,
+     1236,  300,  300,  791,  791,  791, 1233, 1231,  300,  300,
+      300,  301,  582,  301,  301,  301,  301,  301,  301,  301,
+
+      301,  301,  301,  582, 1230,  301,  301,  798,  798,  798,
+     1229,  589,  301,  301,  301,  302,  302,  302,  302,  302,
+      302,  306,  589,  306,  306,  306,  306,  306,  306,  306,
+      306,  306,  306, 1227, 1226,  306,  306,  805,  805,  805,
+     1209, 1207,  306,  306,  306,  307,  606,  307,  307,  307,
+      307,  307,  307,  307,  307,  307,  307,  606, 1206,  307,
+      307,  812,  812,  812, 1204,  610,  307,  307,  307,  308,
+      308,  308,  308,  308,  308,  313,  610,  313,  313,  313,
+      313,  313,  313,  313,  313,  313,  313, 1202, 1200,  313,
+      313,  819,  819,  819, 1199, 1198,  313,  313,  313,  314,
+
+      611,  314,  314,  314,  314,  314,  314,  314,  314,  314,
+      314,  611, 1196,  314,  314,  825,  825,  825,  825, 1195,
+      314,  314,  314,  315,  315,  315,  315,  315,  315,  329,
+      329,  329,  329,  329,  329,  329,  329,  329,  620, 1190,
+     1188,  329,  329,  627,  888,  888,  888,  620,  329,  329,
+      329,  330,  627,  330,  330,  330,  330,  330,  330,  330,
+      330,  330,  330, 1185, 1184,  330,  330,  892,  892,  892,
+     1183, 1182,  330,  330,  330,  336,  336,  336,  336,  336,
+      336,  336,  336,  336,  896,  896,  896,  336,  336,  901,
+      901,  901, 1181,  336,  336,  336,  336,  338,  338,  338,
+
+      338,  338,  338,  338,  338,  338,  634, 1179, 1177,  338,
+      338,  642,  906,  906,  906,  634,  338,  338,  338,  339,
+      642,  339,  339,  339,  339,  339,  339,  339,  339,  339,
+      339, 1175,  342,  339,  339,  643,  644,  653,  655,  339,
+      339,  339,  339,  342,  643,  644,  653,  655,  909,  909,
+      909,  349,  342,  345,  345,  345,  345,  345,  345,  345,
+      345,  345,  349, 1173, 1171,  345,  345,  914,  914,  914,
+     1169,  349,  345,  345,  345,  346,  670,  346,  346,  346,
+      346,  346,  346,  346,  346,  346,  346,  670, 1168,  346,
+      346,  730,  936,  936,  936,  346,  346,  346,  346,  352,
+
+      730,  352,  352,  352,  352,  352,  352,  352,  352,  352,
+      356,  359,  356,  356,  356,  356,  356,  356,  356,  356,
+      356,  736,  359,  942,  942,  942,  946,  946,  946, 1167,
+      736,  359,  360,  674,  360,  360,  360,  360,  360,  360,
+      360,  360,  360,  360,  674, 1166,  360,  360,  950,  950,
+      950, 1164,  360,  360,  360,  360,  361,  676,  361,  361,
+      361,  361,  361,  361,  361,  361,  361,  361,  676, 1163,
+      361,  361,  955,  955,  955,  363,  361,  361,  361,  361,
+      362,  362,  362,  362,  362,  362,  363,  364,  680,  681,
+      683,  687,  688,  690,  694,  363, 1161,  737,  364,  680,
+
+      681,  683,  687,  688,  690,  694,  737,  364,  368,  368,
+      368,  368,  368,  368,  368,  368,  368,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  375,  375,  375,  375,
+      375,  375,  375,  375,  375,  743, 1160, 1159,  375,  375,
+      960,  960,  960, 1158,  743,  375,  375,  375,  377,  377,
+      377,  377,  377,  377,  377,  377,  377,  744, 1156, 1155,
+      377,  377,  973,  973,  973, 1154,  744,  377,  377,  377,
+      378,  695,  378,  378,  378,  378,  378,  378,  378,  378,
+      378,  378,  695, 1152,  378,  378,  980,  980,  980, 1151,
+     1150,  378,  378,  378,  384,  384,  384,  384,  384,  384,
+
+      384,  384,  384,  750, 1131, 1130,  384,  384,  987,  987,
+      987, 1129,  750,  384,  384,  384,  385,  697,  385,  385,
+      385,  385,  385,  385,  385,  385,  385,  385,  697, 1128,
+      385,  385,  994,  994,  994, 1118, 1117,  385,  385,  385,
+      391,  391,  391,  391,  391,  391,  391,  391,  391,  751,
+     1116, 1114,  391,  391, 1001, 1001, 1001, 1113,  751,  391,
+      391,  391,  392,  701,  392,  392,  392,  392,  392,  392,
+      392,  392,  392,  392,  701, 1112,  392,  392, 1007, 1007,
+     1007, 1007, 1106,  392,  392,  392,  398,  398,  398,  398,
+      398,  398,  398,  398,  398,  398,  402,  702,  402,  402,
+
+      402,  402,  402,  402,  402,  402,  402,  406,  702,  406,
+      406,  406,  406,  406,  406,  406,  406,  406,  410,  726,
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      726, 1104,  410,  410,  760, 1054, 1054, 1054, 1054,  410,
+      410,  410,  411,  760,  411,  411,  411,  411,  411,  411,
+      411,  411,  411,  411, 1103, 1102,  411,  411, 1074, 1074,
+     1074,  418,  781,  411,  411,  411,  412,  412,  412,  412,
+      412,  412,  418,  781,  761, 1079, 1079, 1079, 1107, 1107,
+     1107,  418,  419,  761,  419,  419,  419,  419,  419,  419,
+      419,  419,  419,  419, 1101, 1100,  419,  419,  763, 1111,
+
+     1111, 1111,  419,  419,  419,  419,  420,  763,  420,  420,
+      420,  420,  420,  420,  420,  420,  420,  420, 1099, 1098,
+      420,  420, 1115, 1115, 1115,  422,  420,  420,  420,  420,
+      421,  421,  421,  421,  421,  421,  422,  424,  772,  428,
+      786,  792,  799,  806,  813,  422, 1097,  772,  424, 1095,
+      428,  786,  792,  799,  806,  813, 1092,  424,  425,  428,
+      425,  425,  425,  425,  425,  425,  425,  425,  425,  425,
+     1089, 1086,  425,  425, 1120, 1120, 1120, 1083,  425,  425,
+      425,  425,  426,  820,  426,  426,  426,  426,  426,  426,
+      426,  426,  426,  426,  820, 1081,  426,  426, 1125, 1125,
+
+     1125,  429,  426,  426,  426,  426,  427,  427,  427,  427,
+      427,  427,  429,  431,  842,  435,  846,  847, 1076,  915,
+      856,  429,  863,  870,  431,  842,  435,  846,  847,  856,
+      915,  863,  870,  431,  432,  435,  432,  432,  432,  432,
+      432,  432,  432,  432,  432,  432, 1075, 1073,  432,  432,
+      877, 1127, 1127, 1127,  432,  432,  432,  432,  433,  877,
+      433,  433,  433,  433,  433,  433,  433,  433,  433,  433,
+     1070, 1069,  433,  433, 1143, 1143, 1143,  436,  433,  433,
+      433,  433,  434,  434,  434,  434,  434,  434,  436, 1149,
+     1149, 1149, 1153, 1153, 1153, 1067,  452,  436,  448,  448,
+
+      448,  448,  448,  448,  448,  448,  448,  452, 1066, 1065,
+      448,  448,  889, 1157, 1157, 1157,  452,  448,  448,  448,
+      449,  889,  449,  449,  449,  449,  449,  449,  449,  449,
+      449,  449, 1063, 1062,  449,  449, 1187, 1187, 1187, 1187,
+      449,  449,  449,  449,  461,  461,  461,  461,  461,  461,
+      461,  461,  461,  467,  919,  467,  467,  467,  467,  467,
+      467,  467,  467,  467,  467,  919, 1061,  467,  467,  890,
+     1222, 1222, 1222, 1222,  467,  467,  467,  468,  890,  468,
+      468,  468,  468,  468,  468,  468,  468,  468,  468, 1059,
+     1058,  468,  468, 1235, 1235, 1235, 1047,  922,  468,  468,
+
+      468,  469,  469,  469,  469,  469,  469,  473,  922,  473,
+      473,  473,  473,  473,  473,  473,  473,  473,  473, 1045,
+     1043,  473,  473,  891, 1257, 1257, 1257, 1041,  473,  473,
+      473,  474,  891,  474,  474,  474,  474,  474,  474,  474,
+      474,  474,  474, 1039, 1034,  474,  474, 1261, 1261, 1261,
+     1033,  925,  474,  474,  474,  475,  475,  475,  475,  475,
+      475,  480,  925,  480,  480,  480,  480,  480,  480,  480,
+      480,  480,  480, 1031, 1030,  480,  480,  900, 1265, 1265,
+     1265, 1022,  480,  480,  480,  481,  900,  481,  481,  481,
+      481,  481,  481,  481,  481,  481,  481, 1020, 1019,  481,
+
+      481, 1271, 1271, 1271, 1018,  928,  481,  481,  481,  482,
+      482,  482,  482,  482,  482,  487,  928,  487,  487,  487,
+      487,  487,  487,  487,  487,  487,  487, 1016, 1015,  487,
+      487,  902, 1279, 1279, 1279, 1010,  487,  487,  487,  488,
+      902,  488,  488,  488,  488,  488,  488,  488,  488,  488,
+      488, 1008, 1005,  488,  488, 1285, 1285, 1285, 1004, 1003,
+      488,  488,  488,  489,  489,  489,  489,  489,  489,  507,
+      507,  507,  507,  507,  507,  507,  507,  507,  969,  967,
+      962,  507,  507, 1289, 1289, 1289,  956,  969,  507,  507,
+      507,  508,  931,  508,  508,  508,  508,  508,  508,  508,
+
+      508,  508,  508,  931,  954,  508,  508, 1310, 1310, 1310,
+     1310,  953,  508,  508,  508,  514,  514,  514,  514,  514,
+      514,  514,  514,  514, 1340, 1340, 1340,  514,  514, 1332,
+     1332, 1332, 1332,  514,  514,  514,  514,  516,  516,  516,
+      516,  516,  516,  516,  516,  516,  975,  952,  951,  516,
+      516, 1354, 1354, 1354,  949,  975,  516,  516,  516,  517,
+      961,  517,  517,  517,  517,  517,  517,  517,  517,  517,
+      517,  961,  520,  517,  517,  963,  968, 1037, 1072,  517,
+      517,  517,  517,  520,  948,  947,  963,  968, 1037, 1072,
+      945,  527,  520,  523,  523,  523,  523,  523,  523,  523,
+
+      523,  523,  527,  944,  943,  523,  523,  976, 1358, 1358,
+     1358,  527,  523,  523,  523,  524,  976,  524,  524,  524,
+      524,  524,  524,  524,  524,  524,  524,  929,  926,  524,
+      524, 1363, 1363, 1363,  923,  524,  524,  524,  524,  530,
+      530,  530,  530,  530,  530,  530,  530,  530,  982,  920,
+      917,  530,  530,  983, 1371, 1371, 1371,  982,  530,  530,
+      530,  531,  983,  531,  531,  531,  531,  531,  531,  531,
+      531,  531,  531,  911,  534,  531,  531,  989,  990,  996,
+      997,  531,  531,  531,  531,  534,  989,  990,  996,  997,
+     1377, 1377, 1377,  910,  534,  537,  537,  537,  537,  537,
+
+      537,  537,  537,  537,  537,  908, 1011, 1390, 1390, 1390,
+     1390,  899,  898,  537,  541, 1011,  541,  541,  541,  541,
+      541,  541,  541,  541,  541,  545,  548,  545,  545,  545,
+      545,  545,  545,  545,  545,  545, 1012,  548,  897, 1014,
+     1406, 1406, 1406, 1406,  895, 1012,  548,  549, 1014,  549,
+      549,  549,  549,  549,  549,  549,  549,  549,  549,  894,
+      893,  549,  549, 1023, 1410, 1410, 1410,  549,  549,  549,
+      549,  550, 1023,  550,  550,  550,  550,  550,  550,  550,
+      550,  550,  550,  887,  885,  550,  550, 1424, 1424, 1424,
+      552,  550,  550,  550,  550,  551,  551,  551,  551,  551,
+
+      551,  552,  553, 1080,  884,  849, 1082, 1085, 1088, 1091,
+      552, 1094, 1108,  553, 1080, 1082, 1085, 1088, 1091,  848,
+     1094, 1108,  553,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  562,  562,  562,  562,  562,  562,  562,  562,
+      562, 1109,  841,  840,  562,  562, 1436, 1436, 1436,  838,
+     1109,  562,  562,  562,  564,  564,  564,  564,  564,  564,
+      564,  564,  564, 1110,  837,  836,  564,  564, 1119, 1483,
+     1483, 1483, 1110,  564,  564,  564,  565, 1119,  565,  565,
+      565,  565,  565,  565,  565,  565,  565,  565,  834,  833,
+      565,  565, 1450, 1450, 1450, 1450,  832,  565,  565,  565,
+
+      571,  571,  571,  571,  571,  571,  571,  571,  571, 1121,
+      830,  829,  571,  571, 1458, 1458, 1458, 1458, 1121,  571,
+      571,  571,  572, 1170,  572,  572,  572,  572,  572,  572,
+      572,  572,  572,  572, 1170,  815,  572,  572, 1464, 1464,
+     1464, 1464,  814,  572,  572,  572,  578,  578,  578,  578,
+      578,  578,  578,  578,  578, 1172,  808,  807,  578,  578,
+     1174, 1489, 1489, 1489, 1172,  578,  578,  578,  579, 1174,
+      579,  579,  579,  579,  579,  579,  579,  579,  579,  579,
+      801,  800,  579,  579, 1495, 1495, 1495, 1495,  794,  579,
+      579,  579,  585,  585,  585,  585,  585,  585,  585,  585,
+
+      585, 1176,  793,  787,  585,  585, 1178,  780,  771,  769,
+     1176,  585,  585,  585,  586, 1178,  586,  586,  586,  586,
+      586,  586,  586,  586,  586,  586,  768,  767,  586,  586,
+     1501, 1501, 1501, 1501,  765,  586,  586,  586,  591,  591,
+      591,  591,  591,  591,  591,  591,  591,  595,  595,  595,
+      595,  595,  595,  595,  595,  595,  595,  599,  764,  599,
+      599,  599,  599,  599,  599,  599,  599,  599,  603,  759,
+      603,  603,  603,  603,  603,  603,  603,  603,  603,  607,
+      757,  607,  607,  607,  607,  607,  607,  607,  607,  607,
+      607,  728,  727,  607,  607, 1180,  721,  719,  718,  717,
+
+      607,  607,  607,  608, 1180,  608,  608,  608,  608,  608,
+      608,  608,  608,  608,  608,  716,  714,  608,  608,  713,
+      712,  710,  615,  709,  608,  608,  608,  609,  609,  609,
+      609,  609,  609,  615,  708, 1191,  696,  689,  682,  675,
+      668,  667,  615,  616, 1191,  616,  616,  616,  616,  616,
+      616,  616,  616,  616,  616,  652,  651,  616,  616, 1192,
+      650,  648,  647,  616,  616,  616,  616,  617, 1192,  617,
+      617,  617,  617,  617,  617,  617,  617,  617,  617,  646,
+      614,  617,  617,  613,  612,  605,  619,  617,  617,  617,
+      617,  618,  618,  618,  618,  618,  618,  619,  621, 1194,
+
+      625, 1203,  604, 1258, 1259, 1260,  619, 1269, 1194,  621,
+     1203,  625, 1258, 1259, 1260,  602, 1269,  601,  621,  622,
+      625,  622,  622,  622,  622,  622,  622,  622,  622,  622,
+      622,  600,  598,  622,  622, 1314,  597,  596,  594,  622,
+      622,  622,  622,  623, 1314,  623,  623,  623,  623,  623,
+      623,  623,  623,  623,  623,  593,  584,  623,  623,  583,
+      577,  576,  626,  623,  623,  623,  623,  624,  624,  624,
+      624,  624,  624,  626,  628, 1315,  632, 1317,  570, 1355,
+     1356, 1357,  626, 1381, 1315,  628, 1317,  632, 1355, 1356,
+     1357,  569, 1381,  563,  628,  629,  632,  629,  629,  629,
+
+      629,  629,  629,  629,  629,  629,  629,  561,  560,  629,
+      629, 1382,  546,  544,  543,  629,  629,  629,  629,  630,
+     1382,  630,  630,  630,  630,  630,  630,  630,  630,  630,
+      630,  542,  540,  630,  630,  539,  513,  512,  633,  630,
+      630,  630,  630,  631,  631,  631,  631,  631,  631,  633,
+      635, 1384,  639, 1394,  506, 1395, 1397, 1411,  633, 1412,
+     1384,  635, 1394,  639, 1395, 1397, 1411,  504, 1412,  503,
+      635,  636,  639,  636,  636,  636,  636,  636,  636,  636,
+      636,  636,  636,  502,  501,  636,  636, 1413,  499,  498,
+      497,  636,  636,  636,  636,  637, 1413,  637,  637,  637,
+
+      637,  637,  637,  637,  637,  637,  637,  495,  494,  637,
+      637,  493,  485,  478,  640,  637,  637,  637,  637,  638,
+      638,  638,  638,  638,  638,  640,  471,  465,  464,  463,
+      444,  443,  442,  660,  640,  656,  656,  656,  656,  656,
+      656,  656,  656,  656,  660,  440,  439,  656,  656, 1425,
+      438,  417,  416,  660,  656,  656,  656,  657, 1425,  657,
+      657,  657,  657,  657,  657,  657,  657,  657,  657,  415,
+      408,  657,  657,  407,  405,  404,  403,  657,  657,  657,
+      657,  669,  669,  669,  669,  669,  669,  669,  669,  669,
+      669,  401,  400,  669,  669, 1426,  399,  397,  396,  390,
+
+      669,  669,  669,  671, 1426,  671,  671,  671,  671,  671,
+      671,  671,  671,  671,  671,  389,  383,  671,  671, 1427,
+      382,  376,  374,  373,  671,  671,  671,  672, 1427,  672,
+      672,  672,  672,  672,  672,  672,  672,  672,  672,  357,
+      355,  672,  672,  354,  353,  351,  350,  335,  672,  672,
+      672,  673,  673,  673,  673,  673,  673,  677,  334,  677,
+      677,  677,  677,  677,  677,  677,  677,  677,  677,  328,
+      326,  677,  677,  325,  324,  323,  321,  320,  677,  677,
+      677,  678,  319,  678,  678,  678,  678,  678,  678,  678,
+      678,  678,  678,  311,  304,  678,  678,  298,  297,  296,
+
+      295,  294,  678,  678,  678,  679,  679,  679,  679,  679,
+      679,  684,  293,  684,  684,  684,  684,  684,  684,  684,
+      684,  684,  684,  279,  278,  684,  684,  277,  263,  262,
+      261,  254,  684,  684,  684,  685,  253,  685,  685,  685,
+      685,  685,  685,  685,  685,  685,  685,  251,  250,  685,
+      685,  249,  247,  246,  240,  239,  685,  685,  685,  686,
+      686,  686,  686,  686,  686,  691,  233,  691,  691,  691,
+      691,  691,  691,  691,  691,  691,  691,  231,  230,  691,
+      691,  229,  227,  226,  215,  213,  691,  691,  691,  692,
+      212,  692,  692,  692,  692,  692,  692,  692,  692,  692,
+
+      692,  204,  203,  692,  692,  197,  195,  194,  193,  192,
+      692,  692,  692,  693,  693,  693,  693,  693,  693,  698,
+      184,  698,  698,  698,  698,  698,  698,  698,  698,  698,
+      698,  178,  177,  698,  698,  176,  175,  174,  173,  158,
+      698,  698,  698,  699,  157,  699,  699,  699,  699,  699,
+      699,  699,  699,  699,  699,  156,  149,  699,  699,  148,
+      146,  145,  139,  137,  699,  699,  699,  700,  700,  700,
+      700,  700,  700,  705,  705,  705,  705,  705,  705,  705,
+      705,  705,  722,  722,  722,  722,  722,  722,  722,  722,
+      722,  136,  135,  134,  722,  722,  133,  131,  130,  127,
+
+      126,  722,  722,  722,  723,  119,  723,  723,  723,  723,
+      723,  723,  723,  723,  723,  723,  118,  112,  723,  723,
+      105,  104,  103,   91,   90,  723,  723,  723,  729,  729,
+      729,  729,  729,  729,  729,  729,  729,   88,   87,   81,
+      729,  729,   78,   70,   66,   62,  729,  729,  729,  729,
+      731,  731,  731,  731,  731,  731,  731,  731,  731,   61,
+       59,   57,  731,  731,   56,   54,   53,   51,   44,  731,
+      731,  731,  732,   39,  732,  732,  732,  732,  732,  732,
+      732,  732,  732,  732,   32,  735,  732,  732,   30,   29,
+       27,   26,  732,  732,  732,  732,  735,   24,   19,   12,
+
+        9,    5,    4,    3,  742,  735,  738,  738,  738,  738,
+      738,  738,  738,  738,  738,  742,    0,    0,  738,  738,
+        0,    0,    0,    0,  742,  738,  738,  738,  739,    0,
+      739,  739,  739,  739,  739,  739,  739,  739,  739,  739,
+        0,    0,  739,  739,    0,    0,    0,    0,  739,  739,
+      739,  739,  745,  745,  745,  745,  745,  745,  745,  745,
+      745,    0,    0,    0,  745,  745,    0,    0,    0,    0,
+        0,  745,  745,  745,  746,    0,  746,  746,  746,  746,
+      746,  746,  746,  746,  746,  746,    0,  749,  746,  746,
+        0,    0,    0,    0,  746,  746,  746,  746,  749,    0,
+
+        0,    0,    0,    0,    0,    0,  756,  749,  752,  752,
+      752,  752,  752,  752,  752,  752,  752,  756,    0,    0,
+      752,  752,    0,    0,    0,    0,  756,  752,  752,  752,
+      753,    0,  753,  753,  753,  753,  753,  753,  753,  753,
+      753,  753,    0,    0,  753,  753,    0,    0,    0,    0,
+      753,  753,  753,  753,  758,  758,  758,  758,  758,  758,
+      758,  758,  758,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,  758,  762,  762,  762,  762,  762,  762,  762,
+      762,  762,  762,    0,    0,    0,    0,    0,    0,    0,
+        0,  762,  766,    0,  766,  766,  766,  766,  766,  766,
+
+      766,  766,  766,  770,  773,  770,  770,  770,  770,  770,
+      770,  770,  770,  770,    0,  773,    0,    0,    0,    0,
+        0,    0,    0,    0,  773,  774,    0,  774,  774,  774,
+      774,  774,  774,  774,  774,  774,  774,    0,    0,  774,
+      774,    0,    0,    0,    0,  774,  774,  774,  774,  775,
+        0,  775,  775,  775,  775,  775,  775,  775,  775,  775,
+      775,    0,    0,  775,  775,    0,    0,    0,  777,  775,
+      775,  775,  775,  776,  776,  776,  776,  776,  776,  777,
+      778,    0,  851,    0,    0,    0,    0,    0,  777,    0,
+        0,  778,    0,  851,    0,    0,    0,    0,    0,    0,
+
+      778,  782,  851,  782,  782,  782,  782,  782,  782,  782,
+      782,  782,  782,    0,    0,  782,  782,    0,    0,    0,
+        0,    0,  782,  782,  782,  783,    0,  783,  783,  783,
+      783,  783,  783,  783,  783,  783,  783,    0,    0,  783,
+      783,    0,    0,    0,    0,    0,  783,  783,  783,  784,
+      784,  784,  784,  784,  784,  789,    0,  789,  789,  789,
+      789,  789,  789,  789,  789,  789,  789,    0,    0,  789,
+      789,    0,    0,    0,    0,    0,  789,  789,  789,  796,
+        0,  796,  796,  796,  796,  796,  796,  796,  796,  796,
+      796,    0,    0,  796,  796,    0,    0,    0,    0,    0,
+
+      796,  796,  796,  803,    0,  803,  803,  803,  803,  803,
+      803,  803,  803,  803,  803,    0,    0,  803,  803,    0,
+        0,    0,    0,    0,  803,  803,  803,  810,    0,  810,
+      810,  810,  810,  810,  810,  810,  810,  810,  810,    0,
+        0,  810,  810,    0,    0,    0,    0,    0,  810,  810,
+      810,  817,    0,  817,  817,  817,  817,  817,  817,  817,
+      817,  817,  817,    0,    0,  817,  817,    0,    0,    0,
+        0,    0,  817,  817,  817,  824,  824,  824,  824,  824,
+      824,  824,  824,  824,  827,  827,  827,  827,  827,  827,
+      827,  827,  827,  831,  831,  831,  831,  831,  831,  831,
+
+      831,  831,  831,  835,    0,  835,  835,  835,  835,  835,
+      835,  835,  835,  835,  839,    0,  839,  839,  839,  839,
+      839,  839,  839,  839,  839,  843,    0,  843,  843,  843,
+      843,  843,  843,  843,  843,  843,  843,    0,    0,  843,
+      843,    0,    0,    0,    0,    0,  843,  843,  843,  844,
+        0,  844,  844,  844,  844,  844,  844,  844,  844,  844,
+      844,    0,    0,  844,  844,    0,    0,    0,    0,    0,
+      844,  844,  844,  845,  845,  845,  845,  845,  845,  850,
+      850,  850,  850,  850,  850,  850,  850,  850,  850,    0,
+        0,  850,  850,    0,    0,    0,    0,    0,  850,  850,
+
+      850,  852,    0,  852,  852,  852,  852,  852,  852,  852,
+      852,  852,  852,    0,    0,  852,  852,    0,    0,    0,
+        0,  852,  852,  852,  852,  853,    0,  853,  853,  853,
+      853,  853,  853,  853,  853,  853,  853,    0,    0,  853,
+      853,    0,    0,    0,  855,  853,  853,  853,  853,  854,
+      854,  854,  854,  854,  854,  855,  857,    0,  861,    0,
+        0,    0,    0,    0,  855,    0,    0,  857,    0,  861,
+        0,    0,    0,    0,    0,    0,  857,  858,  861,  858,
+      858,  858,  858,  858,  858,  858,  858,  858,  858,    0,
+        0,  858,  858,    0,    0,    0,    0,  858,  858,  858,
+
+      858,  859,    0,  859,  859,  859,  859,  859,  859,  859,
+      859,  859,  859,    0,    0,  859,  859,    0,    0,    0,
+      862,  859,  859,  859,  859,  860,  860,  860,  860,  860,
+      860,  862,  864,    0,  868,    0,    0,    0,    0,    0,
+      862,    0,    0,  864,    0,  868,    0,    0,    0,    0,
+        0,    0,  864,  865,  868,  865,  865,  865,  865,  865,
+      865,  865,  865,  865,  865,    0,    0,  865,  865,    0,
+        0,    0,    0,  865,  865,  865,  865,  866,    0,  866,
+      866,  866,  866,  866,  866,  866,  866,  866,  866,    0,
+        0,  866,  866,    0,    0,    0,  869,  866,  866,  866,
+
+      866,  867,  867,  867,  867,  867,  867,  869,  871,    0,
+      875,    0,    0,    0,    0,    0,  869,    0,    0,  871,
+        0,  875,    0,    0,    0,    0,    0,    0,  871,  872,
+      875,  872,  872,  872,  872,  872,  872,  872,  872,  872,
+      872,    0,    0,  872,  872,    0,    0,    0,    0,  872,
+      872,  872,  872,  873,    0,  873,  873,  873,  873,  873,
+      873,  873,  873,  873,  873,    0,    0,  873,  873,    0,
+        0,    0,  876,  873,  873,  873,  873,  874,  874,  874,
+      874,  874,  874,  876,  878,    0,  882,    0,    0,    0,
+        0,    0,  876,    0,    0,  878,    0,  882,    0,    0,
+
+        0,    0,    0,    0,  878,  879,  882,  879,  879,  879,
+      879,  879,  879,  879,  879,  879,  879,    0,    0,  879,
+      879,    0,    0,    0,    0,  879,  879,  879,  879,  880,
+        0,  880,  880,  880,  880,  880,  880,  880,  880,  880,
+      880,    0,    0,  880,  880,    0,    0,    0,  883,  880,
+      880,  880,  880,  881,  881,  881,  881,  881,  881,  883,
+        0,    0,    0,    0,    0,    0,    0,    0,  883,  886,
+      886,  886,  886,  886,  886,  886,  886,  886,    0,    0,
+        0,    0,    0,    0,    0,    0,  907,  886,  903,  903,
+      903,  903,  903,  903,  903,  903,  903,  907,    0,    0,
+
+      903,  903,    0,    0,    0,    0,  907,  903,  903,  903,
+      904,    0,  904,  904,  904,  904,  904,  904,  904,  904,
+      904,  904,    0,    0,  904,  904,    0,    0,    0,    0,
+      904,  904,  904,  904,  912,    0,  912,  912,  912,  912,
+      912,  912,  912,  912,  912,  912,    0,    0,  912,  912,
+        0,    0,    0,    0,    0,  912,  912,  912,  940,  940,
+      940,  940,  940,  940,  940,  940,  940,  958,    0,  958,
+      958,  958,  958,  958,  958,  958,  958,  958,  958,    0,
+        0,  958,  958,    0,    0,    0,    0,    0,  958,  958,
+      958,  964,    0,  964,  964,  964,  964,  964,  964,  964,
+
+      964,  964,  964,    0,    0,  964,  964,    0,    0,    0,
+        0,    0,  964,  964,  964,  965,    0,  965,  965,  965,
+      965,  965,  965,  965,  965,  965,  965,    0,    0,  965,
+      965,    0,    0,    0,    0,    0,  965,  965,  965,  966,
+      966,  966,  966,  966,  966,  971,    0,  971,  971,  971,
+      971,  971,  971,  971,  971,  971,  971,    0,  974,  971,
+      971,    0,    0,    0,    0,  971,  971,  971,  971,  974,
+        0,    0,    0,    0,    0,    0,    0,    0,  974,  978,
+        0,  978,  978,  978,  978,  978,  978,  978,  978,  978,
+      978,    0,  981,  978,  978,    0,    0,    0,    0,  978,
+
+      978,  978,  978,  981,    0,    0,    0,    0,    0,    0,
+        0,    0,  981,  985,    0,  985,  985,  985,  985,  985,
+      985,  985,  985,  985,  985,    0,  988,  985,  985,    0,
+        0,    0,    0,  985,  985,  985,  985,  988,    0,    0,
+        0,    0,    0,    0,    0,    0,  988,  992,    0,  992,
+      992,  992,  992,  992,  992,  992,  992,  992,  992,    0,
+      995,  992,  992,    0,    0,    0,    0,  992,  992,  992,
+      992,  995,    0,    0,    0,    0,    0,    0,    0,    0,
+      995,  999,    0,  999,  999,  999,  999,  999,  999,  999,
+      999,  999,  999,    0, 1002,  999,  999,    0,    0,    0,
+
+        0,  999,  999,  999,  999, 1002,    0,    0,    0,    0,
+        0,    0,    0,    0, 1002, 1006, 1006, 1006, 1006, 1006,
+     1006, 1006, 1006, 1006,    0,    0,    0,    0,    0,    0,
+        0,    0,    0, 1006, 1009, 1009, 1009, 1009, 1009, 1009,
+     1009, 1009, 1009,    0,    0,    0,    0,    0,    0,    0,
+        0,    0, 1009, 1013, 1013, 1013, 1013, 1013, 1013, 1013,
+     1013, 1013, 1013,    0,    0,    0,    0,    0,    0,    0,
+        0, 1013, 1017,    0, 1017, 1017, 1017, 1017, 1017, 1017,
+     1017, 1017, 1017, 1021, 1024, 1021, 1021, 1021, 1021, 1021,
+     1021, 1021, 1021, 1021,    0, 1024,    0,    0,    0,    0,
+
+        0,    0,    0,    0, 1024, 1025,    0, 1025, 1025, 1025,
+     1025, 1025, 1025, 1025, 1025, 1025, 1025,    0,    0, 1025,
+     1025,    0,    0,    0,    0, 1025, 1025, 1025, 1025, 1026,
+        0, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026, 1026,
+     1026,    0,    0, 1026, 1026,    0,    0,    0, 1028, 1026,
+     1026, 1026, 1026, 1027, 1027, 1027, 1027, 1027, 1027, 1028,
+     1029,    0, 1084,    0,    0,    0,    0,    0, 1028,    0,
+        0, 1029,    0, 1084,    0,    0,    0,    0,    0,    0,
+     1029, 1032, 1084, 1032, 1032, 1032, 1032, 1032, 1032, 1032,
+     1032, 1032, 1053, 1053, 1053, 1053, 1053, 1053, 1053, 1053,
+
+     1053, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056, 1056,
+     1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060,
+     1064,    0, 1064, 1064, 1064, 1064, 1064, 1064, 1064, 1064,
+     1064, 1068,    0, 1068, 1068, 1068, 1068, 1068, 1068, 1068,
+     1068, 1068, 1077,    0, 1077, 1077, 1077, 1077, 1077, 1077,
+     1077, 1077, 1077, 1077,    0, 1087, 1077, 1077, 1090, 1093,
+     1096,    0,    0, 1077, 1077, 1077, 1087,    0,    0, 1090,
+     1093, 1096,    0,    0,    0, 1087,    0,    0, 1090, 1093,
+     1096, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105, 1105,
+        0,    0,    0,    0,    0,    0,    0,    0,    0, 1105,
+
+     1123,    0, 1123, 1123, 1123, 1123, 1123, 1123, 1123, 1123,
+     1123, 1123,    0, 1126, 1123, 1123,    0,    0,    0,    0,
+     1123, 1123, 1123, 1123, 1126,    0,    0,    0,    0,    0,
+        0,    0,    0, 1126, 1147, 1147, 1147, 1147, 1147, 1147,
+     1147, 1147, 1147, 1165,    0, 1165, 1165, 1165, 1165, 1165,
+     1165, 1165, 1165, 1165, 1186, 1186, 1186, 1186, 1186, 1186,
+     1186, 1186, 1186,    0,    0,    0,    0,    0,    0,    0,
+        0,    0, 1186, 1189, 1189, 1189, 1189, 1189, 1189, 1189,
+     1189, 1189,    0,    0,    0,    0,    0,    0,    0,    0,
+        0, 1189, 1193, 1193, 1193, 1193, 1193, 1193, 1193, 1193,
+
+     1193, 1193,    0,    0,    0,    0,    0,    0,    0,    0,
+     1193, 1197,    0, 1197, 1197, 1197, 1197, 1197, 1197, 1197,
+     1197, 1197, 1201, 1205, 1201, 1201, 1201, 1201, 1201, 1201,
+     1201, 1201, 1201,    0, 1205,    0,    0,    0,    0,    0,
+        0,    0,    0, 1205, 1208,    0, 1208, 1208, 1208, 1208,
+     1208, 1208, 1208, 1208, 1208, 1221, 1221, 1221, 1221, 1221,
+     1221, 1221, 1221, 1221, 1224, 1224, 1224, 1224, 1224, 1224,
+     1224, 1224, 1224, 1228, 1228, 1228, 1228, 1228, 1228, 1228,
+     1228, 1228, 1228, 1232,    0, 1232, 1232, 1232, 1232, 1232,
+     1232, 1232, 1232, 1232, 1255, 1255, 1255, 1255, 1255, 1255,
+
+     1255, 1255, 1255,    0,    0,    0,    0,    0,    0,    0,
+        0,    0, 1255, 1283, 1283, 1283, 1283, 1283, 1283, 1283,
+     1283, 1283, 1296,    0, 1296, 1296, 1296, 1296, 1296, 1296,
+     1296, 1296, 1296, 1309, 1309, 1309, 1309, 1309, 1309, 1309,
+     1309, 1309,    0,    0,    0,    0,    0,    0,    0,    0,
+        0, 1309, 1312, 1312, 1312, 1312, 1312, 1312, 1312, 1312,
+     1312,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+     1312, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316, 1316,
+     1316,    0,    0,    0,    0,    0,    0,    0,    0, 1316,
+     1320,    0, 1320, 1320, 1320, 1320, 1320, 1320, 1320, 1320,
+
+     1320, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325, 1325,
+     1325, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331,
+     1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1334, 1338,
+     1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1338, 1352,
+     1352, 1352, 1352, 1352, 1352, 1352, 1352, 1352,    0,    0,
+        0,    0,    0,    0,    0,    0,    0, 1352, 1375, 1375,
+     1375, 1375, 1375, 1375, 1375, 1375, 1375, 1383, 1383, 1383,
+     1383, 1383, 1383, 1383, 1383, 1383, 1383,    0,    0,    0,
+        0,    0,    0,    0,    0, 1383, 1389, 1389, 1389, 1389,
+     1389, 1389, 1389, 1389, 1389,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0, 1389, 1392, 1392, 1392, 1392, 1392,
+     1392, 1392, 1392, 1392,    0,    0,    0,    0,    0,    0,
+        0,    0,    0, 1392, 1396, 1396, 1396, 1396, 1396, 1396,
+     1396, 1396, 1396, 1396,    0,    0,    0,    0,    0,    0,
+        0,    0, 1396, 1399, 1399, 1399, 1399, 1399, 1399, 1399,
+     1399, 1399, 1405, 1405, 1405, 1405, 1405, 1405, 1405, 1405,
+     1405, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408, 1408,
+     1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422,    0,
+        0,    0,    0,    0,    0,    0,    0,    0, 1422, 1430,
+     1430, 1430, 1430, 1430, 1430, 1430, 1430, 1430, 1440, 1440,
+
+     1440, 1440, 1440, 1440, 1440, 1440, 1440, 1443, 1443, 1443,
+     1443, 1443, 1443, 1443, 1443, 1443,    0,    0,    0,    0,
+        0,    0,    0,    0,    0, 1443, 1449, 1449, 1449, 1449,
+     1449, 1449, 1449, 1449, 1449,    0,    0,    0,    0,    0,
+        0,    0,    0,    0, 1449, 1452, 1452, 1452, 1452, 1452,
+     1452, 1452, 1452, 1452,    0,    0,    0,    0,    0,    0,
+        0,    0,    0, 1452, 1457, 1457, 1457, 1457, 1457, 1457,
+     1457, 1457, 1457, 1463, 1463, 1463, 1463, 1463, 1463, 1463,
+     1463, 1463, 1467, 1467, 1467, 1467, 1467, 1467, 1467, 1467,
+     1467,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+     1467, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477, 1477,
+        0,    0,    0,    0,    0,    0,    0,    0,    0, 1477,
+     1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494, 1494,    0,
+        0,    0,    0,    0,    0,    0,    0,    0, 1494, 1500,
+     1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500,    0,    0,
+        0,    0,    0,    0,    0,    0,    0, 1500, 1519, 1519,
+     1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1519, 1520,
+     1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520, 1520,
+     1521,    0, 1521, 1521, 1521, 1521, 1521, 1521, 1521, 1521,
+     1521, 1522, 1522, 1522, 1522, 1523, 1523, 1523, 1524, 1524,
+
+     1524,    0, 1524, 1524, 1524, 1525, 1525, 1525, 1525, 1525,
+     1525, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526, 1526,
+     1526, 1526, 1527, 1527, 1527, 1527, 1527, 1527, 1527, 1527,
+     1527, 1527, 1527, 1528, 1528, 1528, 1529, 1529, 1529, 1529,
+     1529, 1529, 1530, 1530, 1530, 1530, 1530, 1530, 1531, 1531,
+     1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1532,
+     1532, 1532, 1532,    0,    0, 1532, 1533, 1533, 1533, 1533,
+     1533, 1533, 1534, 1534, 1534, 1534, 1534, 1534, 1534, 1535,
+     1535, 1535, 1535, 1535, 1535, 1536, 1536, 1536, 1536, 1536,
+     1536, 1537, 1537, 1537, 1538, 1538, 1538, 1539, 1539, 1539,
+
+     1539, 1539, 1539, 1540, 1540, 1540, 1540, 1540, 1540, 1541,
+     1541, 1541, 1541, 1541, 1541, 1541, 1542, 1542, 1542, 1543,
+     1543, 1543, 1543, 1543, 1543, 1544, 1544, 1544, 1544, 1544,
+     1544, 1545, 1545, 1545, 1545, 1545, 1545, 1546, 1546, 1546,
+     1546, 1546, 1546, 1546,    0, 1546, 1547, 1547, 1547, 1547,
+     1548, 1548, 1548, 1548, 1549, 1549, 1549, 1549, 1549, 1549,
+     1550, 1550, 1550, 1550, 1550, 1550, 1551, 1551, 1551, 1551,
+     1551, 1551, 1552, 1552, 1552, 1552, 1553, 1553, 1553, 1553,
+     1554, 1554, 1554, 1554, 1554, 1554, 1555, 1555, 1555, 1555,
+     1555, 1555, 1555, 1556, 1556, 1556, 1556, 1556, 1556, 1557,
+
+     1557, 1557, 1557, 1557, 1557, 1558, 1558, 1558, 1558, 1558,
+     1558, 1558,    0, 1558, 1559, 1559, 1559, 1560, 1560, 1560,
+     1560, 1560, 1560,    0, 1560, 1561, 1561, 1562, 1562, 1562,
+     1563, 1563, 1563, 1564, 1564, 1564, 1564, 1564, 1564, 1565,
+     1565, 1565, 1565, 1565, 1565, 1566, 1566, 1566, 1566, 1566,
+     1566, 1566, 1567, 1567, 1567, 1567, 1567, 1567, 1568, 1568,
+     1568, 1568, 1568, 1568, 1568, 1569, 1569, 1569, 1570, 1570,
+     1570, 1571, 1571, 1571, 1572, 1572, 1572, 1572, 1572, 1572,
+     1573, 1573, 1573, 1573, 1573, 1573, 1574, 1574, 1574, 1574,
+     1574, 1574, 1575, 1575, 1575, 1575, 1575, 1575,    0, 1575,
+
+     1576, 1576, 1576, 1576, 1577, 1577, 1577, 1577, 1578, 1578,
+     1578, 1578, 1578, 1578,    0, 1578, 1579, 1579, 1579, 1579,
+     1579, 1579, 1579,    0, 1579, 1580, 1580, 1580, 1581, 1581,
+     1581, 1582, 1582, 1582, 1582, 1583, 1583, 1583, 1583, 1584,
+     1584, 1584, 1584, 1584, 1584, 1585, 1585, 1585, 1585, 1585,
+     1585, 1586, 1586, 1586, 1586, 1586, 1586, 1587, 1587, 1587,
+     1587, 1587, 1587, 1588, 1588, 1588, 1588, 1589, 1589, 1589,
+     1589, 1590, 1590, 1590, 1590, 1591, 1591, 1591, 1591, 1592,
+     1592, 1592, 1592, 1592, 1592, 1593, 1593, 1593, 1593, 1593,
+     1593, 1593, 1594, 1594, 1594, 1594, 1594, 1594, 1595, 1595,
+
+     1595, 1595, 1595, 1595, 1596, 1596, 1596, 1596, 1596, 1596,
+     1596,    0, 1596, 1597, 1597, 1597, 1597, 1597, 1597,    0,
+     1597, 1598, 1598, 1598, 1598, 1598, 1598, 1598,    0, 1598,
+     1599, 1599, 1599, 1600, 1600, 1600, 1601, 1601, 1601, 1602,
+     1602, 1602, 1602, 1602, 1602,    0, 1602, 1603, 1603, 1603,
+     1604, 1604, 1604, 1605, 1605, 1605, 1606, 1606, 1607, 1607,
+        0, 1607, 1608, 1608, 1608, 1608, 1608, 1608, 1609, 1609,
+     1609, 1609, 1609, 1609, 1610, 1610, 1610, 1610, 1610, 1610,
+     1610, 1611, 1611, 1611, 1611, 1611, 1611, 1612, 1612, 1612,
+     1612, 1612, 1612, 1612, 1613, 1613, 1613, 1613, 1613, 1613,
+
+     1614, 1614, 1614, 1614, 1614, 1614, 1614, 1615, 1615, 1615,
+     1616, 1616, 1616, 1616, 1617, 1617, 1617, 1618, 1618, 1618,
+     1619, 1619, 1619, 1619, 1620, 1620, 1620, 1621, 1621, 1621,
+     1622, 1622, 1622, 1622, 1622, 1622, 1623, 1623, 1623, 1623,
+     1623, 1623, 1624, 1624, 1624, 1624, 1624, 1624, 1625, 1625,
+     1625, 1625, 1625, 1625,    0, 1625, 1626, 1626, 1626, 1626,
+     1626, 1626,    0, 1626, 1627, 1627, 1627, 1627, 1628, 1628,
+     1628, 1628, 1629, 1629, 1629, 1629, 1630, 1630, 1630, 1630,
+     1631, 1631, 1631, 1631, 1631, 1631,    0, 1631, 1632, 1632,
+     1632, 1632, 1632, 1632, 1632,    0, 1632, 1633, 1633, 1633,
+
+     1634, 1634, 1634, 1635, 1635, 1635, 1636, 1636, 1636, 1637,
+     1637, 1637, 1638, 1638, 1638, 1638, 1638, 1638, 1639, 1639,
+     1639, 1639, 1639, 1639, 1640, 1640, 1640, 1640, 1640, 1640,
+     1641, 1641, 1641, 1641, 1641, 1641, 1642, 1642, 1642, 1642,
+     1642, 1642, 1643, 1643, 1643, 1643, 1644, 1644, 1644, 1644,
+     1645, 1645, 1645, 1645, 1646, 1646, 1646, 1646, 1647, 1647,
+     1647, 1647, 1648, 1648, 1648, 1648, 1649, 1649, 1649, 1649,
+     1649, 1649, 1650, 1650, 1650, 1650, 1650, 1650, 1650, 1651,
+     1651, 1651, 1651, 1651, 1651, 1652, 1652, 1652, 1652, 1652,
+     1652, 1653, 1653, 1653, 1653, 1653, 1653, 1653,    0, 1653,
+
+     1654, 1654, 1654, 1654, 1654, 1654,    0, 1654, 1655, 1655,
+     1655, 1655, 1655, 1655, 1655,    0, 1655, 1656, 1656, 1656,
+     1656, 1656, 1656,    0, 1656, 1657, 1657, 1657, 1657, 1657,
+     1657, 1657,    0, 1657, 1658, 1658, 1658, 1659, 1659, 1659,
+     1659, 1660, 1660, 1660, 1661, 1661, 1661, 1662, 1662, 1662,
+     1662, 1663, 1663, 1663, 1664, 1664, 1664, 1665, 1665, 1665,
+     1665, 1665, 1665,    0, 1665, 1666, 1666, 1666, 1667, 1667,
+     1667, 1668, 1668, 1668, 1669, 1669, 1669, 1670, 1670, 1670,
+     1670, 1670, 1670, 1671, 1671, 1671, 1671, 1671, 1671, 1672,
+     1672, 1672, 1672, 1672, 1672, 1672, 1673, 1673, 1673, 1673,
+
+     1673, 1673, 1674, 1674, 1674, 1674, 1674, 1674, 1674, 1675,
+     1675, 1675, 1675, 1675, 1675, 1676, 1676, 1676, 1676, 1676,
+     1676, 1676, 1677, 1677, 1677, 1677, 1677, 1677, 1678, 1678,
+     1678, 1678, 1678, 1678, 1678, 1679, 1679, 1680, 1680, 1680,
+     1680, 1681, 1681,    0, 1681, 1682, 1682, 1682, 1683, 1683,
+     1683, 1683, 1684, 1684, 1684, 1685, 1685, 1685, 1686, 1686,
+     1686, 1686, 1687, 1687, 1687, 1688, 1688, 1688, 1689, 1689,
+     1689, 1689, 1689, 1689, 1690, 1690, 1690, 1690, 1690, 1690,
+     1691, 1691, 1691, 1691, 1691, 1691, 1692, 1692, 1692, 1692,
+     1692, 1692,    0, 1692, 1693, 1693, 1693, 1693, 1693, 1693,
+
+        0, 1693, 1694, 1694, 1694, 1694, 1694, 1694,    0, 1694,
+     1695, 1695, 1695, 1695,    0,    0,    0, 1695, 1696, 1696,
+     1696, 1696,    0,    0,    0, 1696, 1697, 1697, 1697, 1697,
+     1698, 1698, 1698, 1698, 1699, 1699, 1699, 1699, 1700, 1700,
+     1700, 1700, 1701, 1701, 1701, 1701, 1701, 1701,    0, 1701,
+     1702, 1702, 1702, 1702, 1702, 1702, 1702,    0, 1702, 1703,
+     1703, 1703, 1704, 1704, 1704, 1705, 1705, 1705, 1706, 1706,
+     1706, 1706, 1706, 1706, 1707, 1707, 1707, 1707, 1707, 1707,
+     1708, 1708, 1708, 1708, 1708, 1708, 1709, 1709, 1709, 1709,
+     1709, 1709, 1710, 1710, 1710, 1710, 1710, 1710, 1711, 1711,
+
+     1711, 1711, 1711, 1711, 1712, 1712, 1712, 1713, 1713, 1713,
+     1714, 1714, 1714, 1714, 1715, 1715, 1715, 1715, 1716, 1716,
+     1716, 1716, 1717, 1717, 1717, 1717, 1718, 1718, 1718, 1718,
+     1719, 1719, 1719, 1719, 1720, 1720, 1720, 1720, 1720, 1720,
+     1721, 1721, 1721, 1721, 1721, 1721, 1721, 1722, 1722, 1722,
+     1722, 1722, 1722, 1723, 1723, 1723, 1723, 1723, 1723, 1724,
+     1724, 1724, 1724, 1724, 1724, 1724,    0, 1724, 1725, 1725,
+     1725, 1725, 1725, 1725,    0, 1725, 1726, 1726, 1726, 1726,
+     1726, 1726, 1726,    0, 1726, 1727, 1727, 1727, 1727, 1727,
+     1727,    0, 1727, 1728, 1728, 1728, 1728, 1728, 1728, 1728,
+
+        0, 1728, 1729, 1729, 1729, 1729, 1729, 1729,    0, 1729,
+     1730, 1730, 1730, 1730, 1730, 1730, 1730,    0, 1730, 1731,
+     1731, 1732, 1732, 1732, 1732,    0,    0,    0, 1732, 1733,
+     1733,    0, 1733,    0,    0,    0, 1733, 1734, 1734, 1734,
+     1735, 1735, 1735, 1735, 1736, 1736, 1736, 1737, 1737, 1737,
+     1738, 1738, 1738, 1738, 1739, 1739, 1739, 1740, 1740, 1740,
+     1741, 1741, 1741, 1741, 1741, 1741,    0, 1741, 1742, 1742,
+     1742, 1743, 1743, 1743, 1743, 1743, 1743, 1744, 1744, 1744,
+     1744, 1744, 1744, 1744, 1745, 1745, 1745, 1745, 1745, 1745,
+     1746, 1746, 1746, 1746, 1746, 1746, 1746, 1747, 1747, 1747,
+
+     1747, 1747, 1747, 1748, 1748, 1748, 1748, 1748, 1748, 1748,
+     1749, 1749, 1749, 1749, 1749, 1749, 1750, 1750, 1750, 1750,
+     1750, 1750, 1750, 1751, 1751, 1751, 1751, 1751, 1751, 1752,
+     1752, 1752, 1752, 1752, 1752, 1752, 1753, 1753, 1753, 1754,
+     1754, 1754, 1755, 1755, 1755, 1756, 1756, 1757, 1757, 1757,
+     1757, 1758, 1758,    0, 1758, 1759, 1759, 1759, 1760, 1760,
+     1760, 1760, 1761, 1761, 1761, 1762, 1762, 1762, 1763, 1763,
+     1763, 1763, 1764, 1764, 1764, 1765, 1765, 1765, 1766, 1766,
+     1766, 1766, 1766, 1766, 1767, 1767, 1767, 1767, 1767, 1767,
+     1768, 1768, 1768, 1768, 1768, 1768, 1769, 1769, 1769, 1769,
+
+     1769, 1769,    0, 1769, 1770, 1770, 1770, 1770, 1770, 1770,
+        0, 1770, 1771, 1771, 1771, 1771, 1771, 1771,    0, 1771,
+     1772, 1772, 1772, 1772, 1772, 1772,    0, 1772, 1773, 1773,
+     1773,    0,    0,    0,    0, 1773, 1774, 1774, 1774,    0,
+        0,    0,    0, 1774, 1775, 1775, 1775, 1775,    0,    0,
+        0, 1775, 1776, 1776, 1776, 1776,    0,    0,    0, 1776,
+     1777, 1777, 1777, 1777, 1778, 1778, 1778, 1778, 1779, 1779,
+     1779, 1779, 1780, 1780, 1780, 1780, 1781, 1781, 1781, 1781,
+     1781, 1781,    0, 1781, 1782, 1782, 1782, 1782, 1782, 1782,
+     1782,    0, 1782, 1783, 1783, 1783, 1783, 1783, 1783, 1784,
+
+     1784, 1784, 1784, 1784, 1784, 1784, 1785, 1785, 1785,    0,
+     1785, 1785, 1786, 1786, 1786, 1786, 1786, 1786, 1787, 1787,
+     1787,    0, 1787, 1787, 1788, 1788, 1788, 1788, 1788, 1788,
+     1789, 1789, 1789,    0, 1789, 1789, 1790, 1790, 1790, 1790,
+     1790, 1790, 1791, 1791, 1791,    0, 1791, 1791, 1792, 1792,
+     1792, 1792, 1792, 1792, 1793, 1793, 1793,    0, 1793, 1793,
+     1794, 1794, 1794, 1794, 1794, 1794, 1795, 1795, 1795,    0,
+     1795, 1795, 1796, 1796, 1796, 1797, 1797, 1797, 1798, 1798,
+     1798, 1799, 1799, 1799, 1800, 1800, 1800, 1801, 1801, 1801,
+     1801, 1802, 1802, 1802, 1802, 1803, 1803, 1803, 1803, 1804,
+
+     1804, 1804, 1804, 1805, 1805, 1805, 1805, 1806, 1806, 1806,
+     1806, 1807, 1807, 1807, 1807, 1807, 1807, 1808, 1808, 1808,
+     1808, 1808, 1808, 1808, 1809, 1809, 1809, 1809, 1809, 1809,
+     1810, 1810, 1810, 1810, 1810, 1810, 1810,    0, 1810, 1811,
+     1811, 1811, 1811, 1811, 1811,    0, 1811, 1812, 1812, 1812,
+     1812, 1812, 1812, 1812,    0, 1812, 1813, 1813, 1813, 1813,
+     1813, 1813,    0, 1813, 1814, 1814, 1814, 1814, 1814, 1814,
+     1814,    0, 1814, 1815, 1815, 1815, 1815, 1815, 1815,    0,
+     1815, 1816, 1816, 1816, 1816, 1816, 1816, 1816,    0, 1816,
+     1817, 1817, 1817, 1817, 1817, 1817,    0, 1817, 1818, 1818,
+
+     1818, 1818, 1818, 1818, 1818,    0, 1818, 1819, 1819, 1819,
+        0,    0,    0,    0, 1819, 1820, 1820, 1820,    0,    0,
+        0,    0, 1820, 1821, 1821, 1821,    0,    0,    0,    0,
+     1821, 1822, 1822, 1823, 1823, 1823, 1823,    0,    0,    0,
+     1823, 1824, 1824,    0, 1824,    0,    0,    0, 1824, 1825,
+     1825, 1825, 1826, 1826, 1826, 1826, 1827, 1827, 1827, 1828,
+     1828, 1828, 1829, 1829, 1829, 1829, 1830, 1830, 1830, 1831,
+     1831, 1831, 1832, 1832, 1832, 1832, 1832, 1832,    0, 1832,
+     1833, 1833, 1833, 1834, 1834, 1834, 1834, 1834, 1834, 1835,
+     1835, 1835, 1835, 1835, 1835, 1836, 1836, 1836,    0, 1836,
+
+     1836, 1837, 1837, 1837, 1837, 1837, 1837, 1838, 1838, 1838,
+        0, 1838, 1838, 1839, 1839, 1839, 1839, 1839, 1839, 1840,
+     1840, 1840,    0, 1840, 1840, 1841, 1841, 1841, 1841, 1841,
+     1841, 1842, 1842, 1842,    0, 1842, 1842, 1843, 1843, 1843,
+     1843, 1843, 1843, 1844, 1844, 1844,    0, 1844, 1844, 1845,
+     1845, 1845, 1845, 1845, 1845, 1846, 1846, 1846,    0, 1846,
+     1846, 1847, 1847, 1847, 1848, 1848, 1848, 1849, 1849, 1849,
+     1850, 1850, 1850, 1851, 1851, 1852, 1852, 1852, 1852, 1853,
+     1853,    0, 1853, 1854, 1854, 1854, 1855, 1855, 1855, 1855,
+     1856, 1856, 1856, 1857, 1857, 1857, 1858, 1858, 1858, 1858,
+
+     1859, 1859, 1859, 1860, 1860, 1860, 1861, 1861, 1861, 1861,
+     1861, 1861, 1862, 1862, 1862,    0, 1862, 1862, 1863, 1863,
+     1863, 1863, 1863, 1863, 1864, 1864, 1864, 1864, 1864, 1864,
+     1864, 1865, 1865, 1865,    0, 1865, 1865,    0, 1865, 1866,
+     1866, 1866, 1866, 1866, 1866,    0, 1866, 1867, 1867, 1867,
+        0, 1867, 1867, 1868, 1868, 1868, 1868, 1868, 1868,    0,
+     1868, 1869, 1869, 1869,    0, 1869, 1869, 1870, 1870, 1870,
+     1870, 1870, 1870,    0, 1870, 1871, 1871, 1871,    0, 1871,
+     1871, 1872, 1872, 1872, 1872, 1872, 1872,    0, 1872, 1873,
+     1873, 1873,    0, 1873, 1873, 1874, 1874, 1874, 1874, 1874,
+
+     1874,    0, 1874, 1875, 1875, 1875,    0, 1875, 1875, 1876,
+     1876, 1876,    0,    0,    0,    0, 1876, 1877, 1877, 1877,
+        0,    0,    0,    0, 1877, 1878, 1878, 1878,    0,    0,
+        0,    0, 1878, 1879, 1879, 1879,    0,    0,    0,    0,
+     1879, 1880, 1880, 1880,    0,    0,    0,    0, 1880, 1881,
+     1881, 1881, 1881,    0,    0,    0, 1881, 1882, 1882, 1882,
+     1882,    0,    0,    0, 1882, 1883, 1883, 1883, 1883, 1884,
+     1884, 1884, 1884, 1885, 1885, 1885, 1885, 1886, 1886, 1886,
+     1886, 1887, 1887, 1887, 1887, 1887, 1887,    0, 1887, 1888,
+     1888, 1888, 1888, 1888, 1888, 1888,    0, 1888, 1889, 1889,
+
+     1889, 1889, 1890, 1890, 1890, 1890, 1891, 1891, 1891, 1891,
+     1891, 1891, 1892, 1892, 1892,    0, 1892, 1892, 1893, 1893,
+     1893,    0, 1893, 1893, 1894, 1894, 1894,    0, 1894, 1894,
+     1895, 1895, 1895,    0, 1895, 1895, 1896, 1896, 1896,    0,
+     1896, 1896, 1897, 1897, 1897,    0, 1897, 1897, 1898, 1898,
+     1898,    0, 1898, 1898, 1899, 1899, 1899, 1900, 1900, 1900,
+     1901, 1901, 1901, 1902, 1902, 1902, 1903, 1903, 1903, 1904,
+     1904, 1904, 1904, 1905, 1905, 1905, 1905, 1906, 1906, 1906,
+     1906, 1907, 1907, 1907, 1907, 1908, 1908, 1908, 1908, 1909,
+     1909, 1909, 1909, 1910, 1910, 1910, 1910, 1910, 1910, 1911,
+
+     1911, 1911,    0, 1911, 1911, 1912, 1912, 1912, 1913, 1913,
+     1913, 1913, 1913, 1913, 1914, 1914, 1914, 1914, 1914, 1914,
+     1915, 1915, 1915,    0, 1915, 1915,    0, 1915, 1916, 1916,
+     1916, 1916, 1916, 1916,    0, 1916, 1917, 1917, 1917,    0,
+     1917, 1917,    0, 1917, 1918, 1918, 1918, 1918, 1918, 1918,
+        0, 1918, 1919, 1919, 1919,    0, 1919, 1919,    0, 1919,
+     1920, 1920, 1920, 1920, 1920, 1920,    0, 1920, 1921, 1921,
+     1921,    0, 1921, 1921,    0, 1921, 1922, 1922, 1922, 1922,
+     1922, 1922,    0, 1922, 1923, 1923, 1923,    0, 1923, 1923,
+        0, 1923, 1924, 1924, 1924, 1924, 1924, 1924,    0, 1924,
+
+     1925, 1925, 1925,    0, 1925, 1925,    0, 1925, 1926, 1926,
+     1926,    0,    0,    0,    0, 1926, 1927, 1927,    0,    0,
+        0,    0,    0, 1927, 1928, 1928, 1928,    0,    0,    0,
+        0, 1928, 1929, 1929, 1929,    0,    0,    0,    0, 1929,
+     1930, 1930, 1930,    0,    0,    0,    0, 1930, 1931, 1931,
+     1932, 1932, 1932, 1932,    0,    0,    0, 1932, 1933, 1933,
+        0, 1933,    0,    0,    0, 1933, 1934, 1934, 1934, 1935,
+     1935, 1935, 1935, 1936, 1936, 1936, 1937, 1937, 1937, 1938,
+     1938, 1938, 1938, 1939, 1939, 1939, 1940, 1940, 1940, 1941,
+     1941, 1941, 1941, 1941, 1941,    0, 1941, 1942, 1942, 1942,
+
+        0, 1942, 1942, 1943, 1943, 1943, 1944, 1944, 1944, 1944,
+     1945, 1945, 1945, 1946, 1946, 1946,    0, 1946, 1946, 1947,
+     1947, 1947,    0, 1947, 1947, 1948, 1948, 1948,    0, 1948,
+     1948, 1949, 1949, 1949,    0, 1949, 1949, 1950, 1950, 1950,
+        0, 1950, 1950, 1951, 1951, 1951,    0, 1951, 1951, 1952,
+     1952, 1952,    0, 1952, 1952, 1953, 1953, 1953, 1954, 1954,
+     1954, 1955, 1955, 1955, 1956, 1956, 1956, 1957, 1957, 1958,
+     1958, 1958, 1958, 1959, 1959,    0, 1959, 1960, 1960, 1960,
+     1961, 1961, 1961, 1961, 1962, 1962, 1962, 1963, 1963, 1963,
+     1964, 1964, 1964, 1964, 1965, 1965, 1965, 1966, 1966, 1966,
+
+        0, 1966, 1966, 1967, 1967, 1967, 1967, 1968, 1968, 1968,
+     1968, 1969, 1969, 1969, 1969, 1969, 1969, 1970, 1970, 1970,
+        0, 1970, 1970,    0, 1970, 1971, 1971, 1971,    0, 1971,
+     1971,    0, 1971, 1972, 1972, 1972,    0, 1972, 1972,    0,
+     1972, 1973, 1973, 1973,    0, 1973, 1973,    0, 1973, 1974,
+     1974, 1974,    0, 1974, 1974,    0, 1974, 1975, 1975, 1975,
+        0, 1975, 1975,    0, 1975, 1976, 1976, 1976,    0, 1976,
+     1976,    0, 1976, 1977, 1977, 1977,    0,    0,    0,    0,
+     1977, 1978, 1978, 1978,    0,    0,    0,    0, 1978, 1979,
+     1979, 1979,    0,    0,    0,    0, 1979, 1980, 1980, 1980,
+
+        0,    0,    0,    0, 1980, 1981, 1981, 1981,    0,    0,
+        0,    0, 1981, 1982, 1982, 1982, 1982,    0,    0,    0,
+     1982, 1983, 1983, 1983, 1983,    0,    0,    0, 1983, 1984,
+     1984, 1984, 1984, 1985, 1985, 1985, 1985, 1986, 1986, 1986,
+     1986, 1987, 1987, 1987, 1987, 1988, 1988, 1988, 1988, 1988,
+     1988,    0, 1988, 1989, 1989, 1989,    0, 1989, 1989,    0,
+     1989, 1990, 1990, 1990, 1990, 1991, 1991, 1991, 1991, 1992,
+     1992, 1992,    0, 1992, 1992, 1993, 1993, 1993, 1994, 1994,
+     1994, 1995, 1995, 1995, 1996, 1996, 1996, 1997, 1997, 1997,
+     1998, 1998, 1998, 1998, 1999, 1999, 1999, 1999, 2000, 2000,
+
+     2000, 2000, 2001, 2001, 2001, 2001, 2002, 2002, 2002,    0,
+     2002, 2002, 2003, 2003, 2003, 2004, 2004, 2004, 2005, 2005,
+     2005,    0, 2005, 2005,    0, 2005, 2006, 2006, 2006,    0,
+     2006, 2006,    0, 2006, 2007, 2007, 2007,    0, 2007, 2007,
+        0, 2007, 2008, 2008, 2008,    0, 2008, 2008,    0, 2008,
+     2009, 2009, 2009,    0, 2009, 2009,    0, 2009, 2010, 2010,
+     2010,    0, 2010, 2010,    0, 2010, 2011, 2011, 2011,    0,
+     2011, 2011,    0, 2011, 2012, 2012, 2012,    0,    0,    0,
+        0, 2012, 2013, 2013,    0,    0,    0,    0,    0, 2013,
+     2014, 2014, 2014,    0,    0,    0,    0, 2014, 2015, 2015,
+
+     2015,    0,    0,    0,    0, 2015, 2016, 2016, 2016,    0,
+        0,    0,    0, 2016, 2017, 2017, 2018, 2018,    0, 2018,
+        0,    0,    0, 2018, 2019, 2019, 2019, 2020, 2020, 2020,
+     2021, 2021, 2021, 2022, 2022, 2022, 2023, 2023, 2023,    0,
+     2023, 2023,    0, 2023, 2024, 2024, 2024, 2025, 2025, 2025,
+     2026, 2026, 2026, 2027, 2027, 2027, 2028, 2028, 2028, 2029,
+     2029, 2029, 2030, 2030, 2031, 2031,    0, 2031, 2032, 2032,
+     2032, 2033, 2033, 2033, 2034, 2034, 2034, 2034, 2035, 2035,
+     2035, 2035, 2036, 2036, 2036,    0, 2036, 2036,    0, 2036,
+     2037, 2037, 2037,    0,    0,    0,    0, 2037, 2038, 2038,
+
+     2038,    0,    0,    0,    0, 2038, 2039, 2039, 2039,    0,
+        0,    0,    0, 2039, 2040, 2040, 2040,    0,    0,    0,
+        0, 2040, 2041, 2041, 2041,    0,    0,    0,    0, 2041,
+     2042, 2042, 2042, 2042,    0,    0,    0, 2042, 2043, 2043,
+     2043, 2043,    0,    0,    0, 2043, 2044, 2044, 2044, 2044,
+     2045, 2045, 2045, 2045, 2046, 2046, 2046,    0, 2046, 2046,
+        0, 2046, 2047, 2047, 2047, 2047, 2048, 2048, 2048, 2048,
+     2049, 2049, 2049, 2050, 2050, 2050, 2051, 2051, 2051, 2052,
+     2052, 2052, 2053, 2053, 2053, 2054, 2054, 2054, 2054, 2055,
+     2055, 2055, 2055, 2056, 2056, 2056, 2057, 2057, 2057, 2058,
+
+     2058, 2058,    0,    0,    0,    0, 2058, 2059, 2059,    0,
+        0,    0,    0,    0, 2059, 2060, 2060, 2060,    0,    0,
+        0,    0, 2060, 2061, 2061, 2061,    0,    0,    0,    0,
+     2061, 2062, 2062, 2062,    0,    0,    0,    0, 2062, 2063,
+     2063, 2064, 2064,    0, 2064,    0,    0,    0, 2064, 2065,
+     2065, 2065, 2066, 2066, 2066, 2067, 2067, 2068, 2068,    0,
+     2068, 2069, 2069, 2069, 2070, 2070, 2070, 2071, 2071, 2071,
+     2072, 2072, 2072, 2073, 2073, 2074, 2074,    0, 2074, 2075,
+     2075, 2075, 2075,    0,    0,    0, 2075, 2076, 2076, 2076,
+     2076,    0,    0,    0, 2076, 2077, 2077, 2077,    0,    0,
+
+        0,    0, 2077, 2078, 2078, 2078,    0,    0,    0,    0,
+     2078, 2079, 2079, 2079,    0,    0,    0,    0, 2079, 2080,
+     2080, 2080,    0,    0,    0,    0, 2080, 2081, 2081, 2081,
+        0,    0,    0,    0, 2081, 2082, 2082, 2082, 2082,    0,
+        0,    0, 2082, 2083, 2083, 2083, 2083,    0,    0,    0,
+     2083, 2084, 2084, 2084, 2085, 2085, 2085, 2086, 2086, 2086,
+     2087, 2087, 2087, 2088, 2088, 2088, 2089, 2089, 2089, 2090,
+     2090, 2090, 2091, 2091, 2092, 2092,    0, 2092,    0,    0,
+        0, 2092, 2093, 2093, 2093,    0,    0,    0,    0, 2093,
+     2094, 2094,    0,    0,    0,    0,    0, 2094, 2095, 2095,
+
+     2095,    0,    0,    0,    0, 2095, 2096, 2096, 2096,    0,
+        0,    0,    0, 2096, 2097, 2097, 2097,    0,    0,    0,
+        0, 2097, 2098, 2098, 2099, 2099,    0, 2099,    0,    0,
+        0, 2099, 2100, 2100, 2100, 2101, 2101, 2101, 2102, 2102,
+     2102, 2103, 2103, 2103, 2104, 2104, 2104, 2105, 2105, 2105,
+     2106, 2106, 2106, 2107, 2107, 2107,    0,    0,    0,    0,
+     2107, 2108, 2108, 2108,    0,    0,    0,    0, 2108, 2109,
+     2109, 2109,    0,    0,    0,    0, 2109, 2110, 2110, 2110,
+        0,    0,    0,    0, 2110, 2111, 2111, 2111,    0,    0,
+        0,    0, 2111, 2112, 2112, 2112,    0,    0,    0,    0,
+
+     2112, 2113, 2113, 2113,    0,    0,    0,    0, 2113, 2114,
+     2114, 2114, 2115, 2115, 2115, 2116, 2116, 2116, 2117, 2117,
+     2117, 2118, 2118, 2118, 2119, 2119, 2119, 2120, 2120, 2120,
+        0,    0,    0,    0, 2120, 2121, 2121, 2121,    0,    0,
+        0,    0, 2121, 2122, 2122, 2122,    0,    0,    0,    0,
+     2122, 2123, 2123, 2123,    0,    0,    0,    0, 2123, 2124,
+     2124,    0,    0,    0,    0,    0, 2124, 2125, 2125, 2125,
+        0,    0,    0,    0, 2125, 2126, 2126, 2126,    0,    0,
+        0,    0, 2126, 2127, 2127, 2127,    0,    0,    0,    0,
+     2127, 2128, 2128, 2128, 2129, 2129, 2129, 2130, 2130, 2130,
+
+        0,    0,    0,    0, 2130, 2131, 2131, 2131,    0,    0,
+        0,    0, 2131, 2132, 2132, 2132,    0,    0,    0,    0,
+     2132, 2133, 2133, 2133,    0,    0,    0,    0, 2133, 2134,
+     2134, 2134,    0,    0,    0,    0, 2134, 2135, 2135, 2135,
+        0,    0,    0,    0, 2135, 2136, 2136, 2136,    0,    0,
+        0,    0, 2136, 2137, 2137,    0,    0,    0,    0,    0,
+     2137, 2138, 2138, 2138,    0,    0,    0,    0, 2138, 2139,
+     2139,    0,    0,    0,    0,    0, 2139, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+
+     1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518, 1518,
+     1518, 1518, 1518, 1518, 1518, 1518, 1518
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[20] =
+    {   0,
+0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 
+        };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "scanner.l"
+/**
+ * collectd - src/liboconfig/scanner.l
+ * Copyright (C) 2007  Florian Forster
+ * Copyright (C) 2008  Sebastian Harl
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ */
+#line 30 "scanner.l"
+#include <stdlib.h>
+#include "oconfig.h"
+#include "aux_types.h"
+#include "parser.h"
+
+/* multiline string buffer */
+static char *ml_buffer = NULL;
+static int   ml_pos    = 0;
+static int   ml_len    = 0;
+
+#define ml_free (ml_len - ml_pos)
+
+static void ml_append (char *);
+
+#ifdef yyterminate
+# undef yyterminate
+#endif
+#define yyterminate() \
+       do { free (ml_buffer); ml_buffer = NULL; ml_pos = 0; ml_len = 0; \
+               return YY_NULL; } while (0)
+
+/* IPv6 address according to http://www.ietf.org/rfc/rfc2373.txt
+ * This supports embedded IPv4 addresses as well but does not strictly check
+ * for the right prefix (::0:<v4> or ::FFFF:<v4>) because there are too many
+ * ways to correctly represent the zero bytes. It's up to the user to check
+ * for valid addresses. */
+#line 3380 "scanner.c"
+
+#define INITIAL 0
+#define ML 1
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (void );
+
+int yyget_debug (void );
+
+void yyset_debug (int debug_flag  );
+
+YY_EXTRA_TYPE yyget_extra (void );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined  );
+
+FILE *yyget_in (void );
+
+void yyset_in  (FILE * in_str  );
+
+FILE *yyget_out (void );
+
+void yyset_out  (FILE * out_str  );
+
+yy_size_t yyget_leng (void );
+
+char *yyget_text (void );
+
+int yyget_lineno (void );
+
+void yyset_lineno (int line_number  );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+    static void yyunput (int c,char *buf_ptr  );
+    
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+               { \
+               int c = '*'; \
+               size_t n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       if ( yyleng > 0 ) \
+               YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+                               (yytext[yyleng - 1] == '\n'); \
+       YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+    
+       if ( !(yy_init) )
+               {
+               (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! (yy_start) )
+                       (yy_start) = 1; /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! YY_CURRENT_BUFFER ) {
+                       yyensure_buffer_stack ();
+                       YY_CURRENT_BUFFER_LVALUE =
+                               yy_create_buffer(yyin,YY_BUF_SIZE );
+               }
+
+               yy_load_buffer_state( );
+               }
+
+       {
+#line 82 "scanner.l"
+
+#line 3600 "scanner.c"
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = (yy_c_buf_p);
+
+               /* Support of yytext. */
+               *yy_cp = (yy_hold_char);
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = (yy_start);
+               yy_current_state += YY_AT_BOL();
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               (yy_last_accepting_state) = yy_current_state;
+                               (yy_last_accepting_cpos) = yy_cp;
+                               }
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 1519 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_base[yy_current_state] != 9978 );
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+               if ( yy_act == 0 )
+                       { /* have to back up */
+                       yy_cp = (yy_last_accepting_cpos);
+                       yy_current_state = (yy_last_accepting_state);
+                       yy_act = yy_accept[yy_current_state];
+                       }
+
+               YY_DO_BEFORE_ACTION;
+
+               if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+                       {
+                       yy_size_t yyl;
+                       for ( yyl = 0; yyl < yyleng; ++yyl )
+                               if ( yytext[yyl] == '\n' )
+                                          
+    yylineno++;
+;
+                       }
+
+do_action:     /* This label is used only to access EOF actions. */
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = (yy_hold_char);
+                       yy_cp = (yy_last_accepting_cpos);
+                       yy_current_state = (yy_last_accepting_state);
+                       goto yy_find_action;
+
+case 1:
+#line 84 "scanner.l"
+case 2:
+YY_RULE_SETUP
+#line 84 "scanner.l"
+{/* ignore */}
+       YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 86 "scanner.l"
+{/* continue line */}
+       YY_BREAK
+case 4:
+/* rule 4 can match eol */
+YY_RULE_SETUP
+#line 88 "scanner.l"
+{return (EOL);}
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 89 "scanner.l"
+{return (SLASH);}
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 90 "scanner.l"
+{return (OPENBRAC);}
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 91 "scanner.l"
+{return (CLOSEBRAC);}
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 92 "scanner.l"
+{yylval.boolean = 1; return (BTRUE);}
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 93 "scanner.l"
+{yylval.boolean = 0; return (BFALSE);}
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 95 "scanner.l"
+{yylval.string = yytext; return (UNQUOTED_STRING);}
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 96 "scanner.l"
+{yylval.string = yytext; return (UNQUOTED_STRING);}
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 98 "scanner.l"
+{yylval.number = strtod (yytext, NULL); return (NUMBER);}
+       YY_BREAK
+case 13:
+/* rule 13 can match eol */
+YY_RULE_SETUP
+#line 100 "scanner.l"
+{yylval.string = yytext; return (QUOTED_STRING);}
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 101 "scanner.l"
+{yylval.string = yytext; return (UNQUOTED_STRING);}
+       YY_BREAK
+case 15:
+/* rule 15 can match eol */
+YY_RULE_SETUP
+#line 103 "scanner.l"
+{
+       int len = strlen (yytext);
+
+       ml_pos = 0;
+
+       /* remove "\\<EOL>" */
+       if ('\r' == yytext[len - 2])
+               len -= 3;
+       else
+               len -= 2;
+       yytext[len] = '\0';
+
+       ml_append (yytext);
+       BEGIN (ML);
+}
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 118 "scanner.l"
+{/* remove leading white-space */}
+       YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 119 "scanner.l"
+{
+       int len = strlen (yytext);
+
+       /* remove "\\<EOL>" */
+       if ('\r' == yytext[len - 2])
+               len -= 3;
+       else
+               len -= 2;
+       yytext[len] = '\0';
+
+       ml_append(yytext);
+}
+       YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 131 "scanner.l"
+{
+       ml_append(yytext);
+       yylval.string = ml_buffer;
+
+       BEGIN (INITIAL);
+       return (QUOTED_STRING);
+}
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 138 "scanner.l"
+ECHO;
+       YY_BREAK
+#line 3797 "scanner.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(ML):
+       yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = (yy_hold_char);
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between YY_CURRENT_BUFFER and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+                       YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state(  );
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+                       yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++(yy_c_buf_p);
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = (yy_c_buf_p);
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer(  ) )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               (yy_did_buffer_switch_on_eof) = 0;
+
+                               if ( yywrap( ) )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! (yy_did_buffer_switch_on_eof) )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               (yy_c_buf_p) =
+                                       (yytext_ptr) + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state(  );
+
+                               yy_cp = (yy_c_buf_p);
+                               yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               (yy_c_buf_p) =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+                               yy_current_state = yy_get_previous_state(  );
+
+                               yy_cp = (yy_c_buf_p);
+                               yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+       } /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+       register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+       register char *source = (yytext_ptr);
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+       else
+               {
+                       yy_size_t num_to_read =
+                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+                       int yy_c_buf_p_offset =
+                               (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               yy_size_t new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+                                               number_to_move - 1;
+
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+                       (yy_n_chars), num_to_read );
+
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+               }
+
+       if ( (yy_n_chars) == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart(yyin  );
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+               /* Extend the array by 50%, plus the number we really need. */
+               yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+               YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+               if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+       }
+
+       (yy_n_chars) += number_to_move;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+       (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+       return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+    static yy_state_type yy_get_previous_state (void)
+{
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+    
+       yy_current_state = (yy_start);
+       yy_current_state += YY_AT_BOL();
+
+       for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       (yy_last_accepting_state) = yy_current_state;
+                       (yy_last_accepting_cpos) = yy_cp;
+                       }
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 1519 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               }
+
+       return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+    static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+{
+       register int yy_is_jam;
+       register char *yy_cp = (yy_c_buf_p);
+
+       register YY_CHAR yy_c = 1;
+       if ( yy_accept[yy_current_state] )
+               {
+               (yy_last_accepting_state) = yy_current_state;
+               (yy_last_accepting_cpos) = yy_cp;
+               }
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 1519 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 1518);
+
+               return yy_is_jam ? 0 : yy_current_state;
+}
+
+    static void yyunput (int c, register char * yy_bp )
+{
+       register char *yy_cp;
+    
+    yy_cp = (yy_c_buf_p);
+
+       /* undo effects of setting up yytext */
+       *yy_cp = (yy_hold_char);
+
+       if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register yy_size_t number_to_move = (yy_n_chars) + 2;
+               register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+                                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+               register char *source =
+                               &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+               while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+                       (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+               if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+    if ( c == '\n' ){
+        --yylineno;
+    }
+
+       (yytext_ptr) = yy_bp;
+       (yy_hold_char) = *yy_cp;
+       (yy_c_buf_p) = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+    static int yyinput (void)
+#else
+    static int input  (void)
+#endif
+
+{
+       int c;
+    
+       *(yy_c_buf_p) = (yy_hold_char);
+
+       if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+                       /* This was really a NUL. */
+                       *(yy_c_buf_p) = '\0';
+
+               else
+                       { /* need more input */
+                       yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
+                       ++(yy_c_buf_p);
+
+                       switch ( yy_get_next_buffer(  ) )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       yyrestart(yyin );
+
+                                       /*FALLTHROUGH*/
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( yywrap( ) )
+                                               return EOF;
+
+                                       if ( ! (yy_did_buffer_switch_on_eof) )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput();
+#else
+                                       return input();
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       (yy_c_buf_p) = (yytext_ptr) + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) (yy_c_buf_p);    /* cast for 8-bit char's */
+       *(yy_c_buf_p) = '\0';   /* preserve yytext */
+       (yy_hold_char) = *++(yy_c_buf_p);
+
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol )
+                  
+    yylineno++;
+;
+
+       return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * 
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+    void yyrestart  (FILE * input_file )
+{
+    
+       if ( ! YY_CURRENT_BUFFER ){
+        yyensure_buffer_stack ();
+               YY_CURRENT_BUFFER_LVALUE =
+            yy_create_buffer(yyin,YY_BUF_SIZE );
+       }
+
+       yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+       yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * 
+ */
+    void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+{
+    
+       /* TODO. We should be able to replace this entire function body
+        * with
+        *              yypop_buffer_state();
+        *              yypush_buffer_state(new_buffer);
+     */
+       yyensure_buffer_stack ();
+       if ( YY_CURRENT_BUFFER == new_buffer )
+               return;
+
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *(yy_c_buf_p) = (yy_hold_char);
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+               }
+
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+       yy_load_buffer_state( );
+
+       /* We don't actually know whether we did this switch during
+        * EOF (yywrap()) processing, but the only time this flag
+        * is looked at is after yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state  (void)
+{
+       (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+       (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+       yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+       (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * 
+ * @return the allocated buffer state.
+ */
+    YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+{
+       YY_BUFFER_STATE b;
+    
+       b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       yy_init_buffer(b,file );
+
+       return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * 
+ */
+    void yy_delete_buffer (YY_BUFFER_STATE  b )
+{
+    
+       if ( ! b )
+               return;
+
+       if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+               YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               yyfree((void *) b->yy_ch_buf  );
+
+       yyfree((void *) b  );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+    static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+
+{
+       int oerrno = errno;
+    
+       yy_flush_buffer(b );
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+    /* If b is the current buffer, then yy_init_buffer was _probably_
+     * called from yyrestart() or through yy_get_next_buffer.
+     * In that case, we don't want to reset the lineno or column.
+     */
+    if (b != YY_CURRENT_BUFFER){
+        b->yy_bs_lineno = 1;
+        b->yy_bs_column = 0;
+    }
+
+        b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+    
+       errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * 
+ */
+    void yy_flush_buffer (YY_BUFFER_STATE  b )
+{
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == YY_CURRENT_BUFFER )
+               yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ *  the current state. This function will allocate the stack
+ *  if necessary.
+ *  @param new_buffer The new state.
+ *  
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+       if (new_buffer == NULL)
+               return;
+
+       yyensure_buffer_stack();
+
+       /* This block is copied from yy_switch_to_buffer. */
+       if ( YY_CURRENT_BUFFER )
+               {
+               /* Flush out information for old buffer. */
+               *(yy_c_buf_p) = (yy_hold_char);
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+               }
+
+       /* Only push if top exists. Otherwise, replace top. */
+       if (YY_CURRENT_BUFFER)
+               (yy_buffer_stack_top)++;
+       YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+       /* copied from yy_switch_to_buffer. */
+       yy_load_buffer_state( );
+       (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ *  The next element becomes the new top.
+ *  
+ */
+void yypop_buffer_state (void)
+{
+       if (!YY_CURRENT_BUFFER)
+               return;
+
+       yy_delete_buffer(YY_CURRENT_BUFFER );
+       YY_CURRENT_BUFFER_LVALUE = NULL;
+       if ((yy_buffer_stack_top) > 0)
+               --(yy_buffer_stack_top);
+
+       if (YY_CURRENT_BUFFER) {
+               yy_load_buffer_state( );
+               (yy_did_buffer_switch_on_eof) = 1;
+       }
+}
+
+/* Allocates the stack if it does not exist.
+ *  Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+       yy_size_t num_to_alloc;
+    
+       if (!(yy_buffer_stack)) {
+
+               /* First allocation is just for 2 elements, since we don't know if this
+                * scanner will even need a stack. We use 2 instead of 1 to avoid an
+                * immediate realloc on the next call.
+         */
+               num_to_alloc = 1;
+               (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+                                                               (num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               );
+               if ( ! (yy_buffer_stack) )
+                       YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+                                                                 
+               memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+                               
+               (yy_buffer_stack_max) = num_to_alloc;
+               (yy_buffer_stack_top) = 0;
+               return;
+       }
+
+       if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+               /* Increase the buffer to prepare for a possible push. */
+               int grow_size = 8 /* arbitrary grow size */;
+
+               num_to_alloc = (yy_buffer_stack_max) + grow_size;
+               (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+                                                               ((yy_buffer_stack),
+                                                               num_to_alloc * sizeof(struct yy_buffer_state*)
+                                                               );
+               if ( ! (yy_buffer_stack) )
+                       YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+               /* zero only the new slots.*/
+               memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+               (yy_buffer_stack_max) = num_to_alloc;
+       }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * 
+ * @return the newly allocated buffer state object. 
+ */
+YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+{
+       YY_BUFFER_STATE b;
+    
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       yy_switch_to_buffer(b  );
+
+       return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * 
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ *       yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+    
+       return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * 
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len )
+{
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       yy_size_t i;
+    
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = _yybytes_len + 2;
+       buf = (char *) yyalloc(n  );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+       for ( i = 0; i < _yybytes_len; ++i )
+               buf[i] = yybytes[i];
+
+       buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = yy_scan_buffer(buf,n );
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               yytext[yyleng] = (yy_hold_char); \
+               (yy_c_buf_p) = yytext + yyless_macro_arg; \
+               (yy_hold_char) = *(yy_c_buf_p); \
+               *(yy_c_buf_p) = '\0'; \
+               yyleng = yyless_macro_arg; \
+               } \
+       while ( 0 )
+
+/* Accessor  methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
+/** Get the input stream.
+ * 
+ */
+FILE *yyget_in  (void)
+{
+        return yyin;
+}
+
+/** Get the output stream.
+ * 
+ */
+FILE *yyget_out  (void)
+{
+        return yyout;
+}
+
+/** Get the length of the current token.
+ * 
+ */
+yy_size_t yyget_leng  (void)
+{
+        return yyleng;
+}
+
+/** Get the current token.
+ * 
+ */
+
+char *yyget_text  (void)
+{
+        return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * 
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE *  in_str )
+{
+        yyin = in_str ;
+}
+
+void yyset_out (FILE *  out_str )
+{
+        yyout = out_str ;
+}
+
+int yyget_debug  (void)
+{
+        return yy_flex_debug;
+}
+
+void yyset_debug (int  bdebug )
+{
+        yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from yylex_destroy(), so don't allocate here.
+     */
+
+    /* We do not touch yylineno unless the option is enabled. */
+    yylineno =  1;
+    
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    yyin = stdin;
+    yyout = stdout;
+#else
+    yyin = (FILE *) 0;
+    yyout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * yylex_init()
+     */
+    return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy  (void)
+{
+    
+    /* Pop the buffer stack, destroying each element. */
+       while(YY_CURRENT_BUFFER){
+               yy_delete_buffer(YY_CURRENT_BUFFER  );
+               YY_CURRENT_BUFFER_LVALUE = NULL;
+               yypop_buffer_state();
+       }
+
+       /* Destroy the stack itself. */
+       yyfree((yy_buffer_stack) );
+       (yy_buffer_stack) = NULL;
+
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * yylex() is called, initialization will occur. */
+    yy_init_globals( );
+
+    return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+}
+#endif
+
+void *yyalloc (yy_size_t  size )
+{
+       return (void *) malloc( size );
+}
+
+void *yyrealloc  (void * ptr, yy_size_t  size )
+{
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+       free( (char *) ptr );   /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 137 "scanner.l"
+
+
+static void ml_append (char *string)
+{
+       int len = strlen (string);
+       int s;
+
+       if (ml_free <= len) {
+               ml_len += len - ml_free + 1;
+               ml_buffer = (char *)realloc (ml_buffer, ml_len);
+               if (NULL == ml_buffer)
+                       YY_FATAL_ERROR ("out of dynamic memory in ml_append");
+       }
+
+       s = snprintf (ml_buffer + ml_pos, ml_free, "%s", string);
+       if ((0 > s) || (ml_free <= s))
+               YY_FATAL_ERROR ("failed to write to multiline buffer");
+
+       ml_pos += s;
+       return;
+} /* ml_append */
+
+
diff --git a/src/liboconfig/scanner.l b/src/liboconfig/scanner.l
new file mode 100644 (file)
index 0000000..cb3754d
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ * collectd - src/liboconfig/scanner.l
+ * Copyright (C) 2007  Florian Forster
+ * Copyright (C) 2008  Sebastian Harl
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ */
+
+%{
+#include <stdlib.h>
+#include "oconfig.h"
+#include "aux_types.h"
+#include "parser.h"
+
+/* multiline string buffer */
+static char *ml_buffer = NULL;
+static int   ml_pos    = 0;
+static int   ml_len    = 0;
+
+#define ml_free (ml_len - ml_pos)
+
+static void ml_append (char *);
+
+#ifdef yyterminate
+# undef yyterminate
+#endif
+#define yyterminate() \
+       do { free (ml_buffer); ml_buffer = NULL; ml_pos = 0; ml_len = 0; \
+               return YY_NULL; } while (0)
+%}
+%option yylineno
+%option noyywrap
+%x ML
+WHITE_SPACE [\ \t\b]
+NON_WHITE_SPACE [^\ \t\b]
+EOL (\r\n|\n)
+QUOTED_STRING ([^\\"]+|\\.)*
+UNQUOTED_STRING [0-9A-Za-z_]+
+HEX_NUMBER 0[xX][0-9a-fA-F]+
+OCT_NUMBER 0[0-7]+
+DEC_NUMBER [\+\-]?[0-9]+
+FLOAT_NUMBER [\+\-]?[0-9]*\.[0-9]+([eE][\+\-][0-9]+)?
+NUMBER ({FLOAT_NUMBER}|{HEX_NUMBER}|{OCT_NUMBER}|{DEC_NUMBER})
+BOOL_TRUE (true|yes|on)
+BOOL_FALSE (false|no|off)
+COMMENT #.*
+PORT (6(5(5(3[0-5]|[0-2][0-9])|[0-4][0-9][0-9])|[0-4][0-9][0-9][0-9])|[1-5][0-9][0-9][0-9][0-9]|[1-9][0-9]?[0-9]?[0-9]?)
+
+IP_BYTE (2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])
+IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
+
+/* IPv6 address according to http://www.ietf.org/rfc/rfc2373.txt
+ * This supports embedded IPv4 addresses as well but does not strictly check
+ * for the right prefix (::0:<v4> or ::FFFF:<v4>) because there are too many
+ * ways to correctly represent the zero bytes. It's up to the user to check
+ * for valid addresses. */
+HEX16 ([0-9A-Fa-f]{1,4})
+V6_PART ({HEX16}:{HEX16}|{IPV4_ADDR})
+IPV6_BASE ({HEX16}:){6}{V6_PART}|::({HEX16}:){5}{V6_PART}|({HEX16})?::({HEX16}:){4}{V6_PART}|(({HEX16}:){0,1}{HEX16})?::({HEX16}:){3}{V6_PART}|(({HEX16}:){0,2}{HEX16})?::({HEX16}:){2}{V6_PART}|(({HEX16}:){0,3}{HEX16})?::{HEX16}:{V6_PART}|(({HEX16}:){0,4}{HEX16})?::{V6_PART}|(({HEX16}:){0,5}{HEX16})?::{HEX16}|(({HEX16}:){0,6}{HEX16})?::
+IPV6_ADDR ({IPV6_BASE})|(\[{IPV6_BASE}\](:{PORT})?)
+
+%%
+{WHITE_SPACE}          |
+{COMMENT}              {/* ignore */}
+
+\\{EOL}                        {/* continue line */}
+
+{EOL}                  {return (EOL);}
+"/"                    {return (SLASH);}
+"<"                    {return (OPENBRAC);}
+">"                    {return (CLOSEBRAC);}
+{BOOL_TRUE}            {yylval.boolean = 1; return (BTRUE);}
+{BOOL_FALSE}           {yylval.boolean = 0; return (BFALSE);}
+
+{IPV4_ADDR}            {yylval.string = yytext; return (UNQUOTED_STRING);}
+{IPV6_ADDR}            {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+{NUMBER}               {yylval.number = strtod (yytext, NULL); return (NUMBER);}
+
+\"{QUOTED_STRING}\"    {yylval.string = yytext; return (QUOTED_STRING);}
+{UNQUOTED_STRING}      {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+\"{QUOTED_STRING}\\{EOL} {
+       int len = strlen (yytext);
+
+       ml_pos = 0;
+
+       /* remove "\\<EOL>" */
+       if ('\r' == yytext[len - 2])
+               len -= 3;
+       else
+               len -= 2;
+       yytext[len] = '\0';
+
+       ml_append (yytext);
+       BEGIN (ML);
+}
+<ML>^{WHITE_SPACE}+ {/* remove leading white-space */}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\\{EOL} {
+       int len = strlen (yytext);
+
+       /* remove "\\<EOL>" */
+       if ('\r' == yytext[len - 2])
+               len -= 3;
+       else
+               len -= 2;
+       yytext[len] = '\0';
+
+       ml_append(yytext);
+}
+<ML>{NON_WHITE_SPACE}{QUOTED_STRING}\" {
+       ml_append(yytext);
+       yylval.string = ml_buffer;
+
+       BEGIN (INITIAL);
+       return (QUOTED_STRING);
+}
+%%
+static void ml_append (char *string)
+{
+       int len = strlen (string);
+       int s;
+
+       if (ml_free <= len) {
+               ml_len += len - ml_free + 1;
+               ml_buffer = (char *)realloc (ml_buffer, ml_len);
+               if (NULL == ml_buffer)
+                       YY_FATAL_ERROR ("out of dynamic memory in ml_append");
+       }
+
+       s = snprintf (ml_buffer + ml_pos, ml_free, "%s", string);
+       if ((0 > s) || (ml_free <= s))
+               YY_FATAL_ERROR ("failed to write to multiline buffer");
+
+       ml_pos += s;
+       return;
+} /* ml_append */
+
diff --git a/src/load.c b/src/load.c
new file mode 100644 (file)
index 0000000..18b5f8e
--- /dev/null
@@ -0,0 +1,219 @@
+/**
+ * collectd - src/load.c
+ * Copyright (C) 2005-2008  Florian octo Forster
+ * Copyright (C) 2009       Manuel Sanmartin
+ * Copyright (C) 2013       Vedran Bartonicek
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Manuel Sanmartin
+ *   Vedran Bartonicek <vbartoni at gmail.com>
+ **/
+
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <unistd.h>
+
+#ifdef HAVE_SYS_LOADAVG_H
+#include <sys/loadavg.h>
+#endif
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
+
+#ifdef HAVE_GETLOADAVG
+#if !defined(LOADAVG_1MIN) || !defined(LOADAVG_5MIN) || !defined(LOADAVG_15MIN)
+#define LOADAVG_1MIN  0
+#define LOADAVG_5MIN  1
+#define LOADAVG_15MIN 2
+#endif
+#endif /* defined(HAVE_GETLOADAVG) */
+
+#ifdef HAVE_PERFSTAT
+# include <sys/proc.h> /* AIX 5 */
+# include <sys/protosw.h>
+# include <libperfstat.h>
+#endif /* HAVE_PERFSTAT */
+
+static _Bool report_relative_load = 0;
+
+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)
+#ifdef _SC_NPROCESSORS_ONLN
+               report_relative_load = IS_TRUE (value) ? 1 : 0;
+#else
+                WARNING ("load plugin: The \"ReportRelative\" configuration "
+                         "is not available, because I can't determine the "
+                         "number of CPUS on this system. Sorry.");
+#endif
+       return (-1);
+
+}
+static void load_submit (gauge_t snum, gauge_t mnum, gauge_t lnum)
+{
+       value_t values[3];
+       value_list_t vl = VALUE_LIST_INIT;
+        int cores = 0;
+        char errbuf[1024];
+
+#ifdef  _SC_NPROCESSORS_ONLN
+        if (report_relative_load) {
+                if ((cores = sysconf(_SC_NPROCESSORS_ONLN)) < 1) {
+                       WARNING ("load: sysconf failed : %s",
+                                sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+       }
+#endif
+       if (cores > 0) {
+               snum /= cores;
+               mnum /= cores;
+               lnum /= cores;
+       }
+
+       values[0].gauge = snum;
+       values[1].gauge = mnum;
+       values[2].gauge = lnum;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "load", sizeof (vl.plugin));
+       sstrncpy (vl.type, "load", sizeof (vl.type));
+
+       if (cores > 0) {
+               sstrncpy(vl.type_instance, "relative",
+                        sizeof (vl.type_instance));
+       }
+
+       plugin_dispatch_values (&vl);
+}
+
+static int load_read (void)
+{
+#if defined(HAVE_GETLOADAVG)
+       double load[3];
+
+       if (getloadavg (load, 3) == 3)
+                load_submit (load[LOADAVG_1MIN], load[LOADAVG_5MIN], load[LOADAVG_15MIN]);
+        else
+        {
+                char errbuf[1024];
+                WARNING ("load: getloadavg failed: %s",
+                         sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+/* #endif HAVE_GETLOADAVG */
+
+#elif defined(KERNEL_LINUX)
+        gauge_t snum, mnum, lnum;
+       FILE *loadavg;
+       char buffer[16];
+
+       char *fields[8];
+       int numfields;
+
+       if ((loadavg = fopen ("/proc/loadavg", "r")) == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("load: fopen: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       if (fgets (buffer, 16, loadavg) == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("load: fgets: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               fclose (loadavg);
+               return (-1);
+       }
+
+       if (fclose (loadavg))
+       {
+               char errbuf[1024];
+               WARNING ("load: fclose: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+
+       numfields = strsplit (buffer, fields, 8);
+
+       if (numfields < 3)
+               return (-1);
+
+       snum = atof (fields[0]);
+       mnum = atof (fields[1]);
+       lnum = atof (fields[2]);
+
+        load_submit(snum, mnum, lnum);
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBSTATGRAB
+        gauge_t snum, mnum, lnum;
+       sg_load_stats *ls;
+
+       if ((ls = sg_get_load_stats ()) == NULL)
+               return;
+
+       snum = ls->min1;
+       mnum = ls->min5;
+       lnum = ls->min15;
+        load_submit(snum, mnum, lnum);
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif HAVE_PERFSTAT
+        gauge_t snum, mnum, lnum;
+       perfstat_cpu_total_t cputotal;
+
+       if (perfstat_cpu_total(NULL,  &cputotal, sizeof(perfstat_cpu_total_t), 1) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("load: perfstat_cpu : %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       snum = (float)cputotal.loadavg[0]/(float)(1<<SBITS);
+       mnum = (float)cputotal.loadavg[1]/(float)(1<<SBITS);
+       lnum = (float)cputotal.loadavg[2]/(float)(1<<SBITS);
+        load_submit(snum, mnum, lnum);
+/* #endif HAVE_PERFSTAT */
+
+#else
+# error "No applicable input method."
+#endif
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_config ("load", load_config, config_keys, config_keys_num);
+       plugin_register_read ("load", load_read);
+} /* void module_register */
diff --git a/src/log_logstash.c b/src/log_logstash.c
new file mode 100644 (file)
index 0000000..61e7f48
--- /dev/null
@@ -0,0 +1,384 @@
+/**
+ * collectd - src/log_logstash.c
+ * Copyright (C) 2013       Pierre-Yves Ritschard
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ * Acknowledgements:
+ *   This file is largely inspired by logfile.c
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <sys/types.h>
+#include <pthread.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 DEFAULT_LOGFILE LOCALSTATEDIR"/log/"PACKAGE_NAME".json.log"
+
+#if COLLECT_DEBUG
+static int log_level = LOG_DEBUG;
+#else
+static int log_level = LOG_INFO;
+#endif /* COLLECT_DEBUG */
+
+static pthread_mutex_t file_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static char *log_file = NULL;
+
+static const char *config_keys[] =
+{
+       "LogLevel",
+       "File"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int log_logstash_config (const char *key, const char *value)
+{
+
+       if (0 == strcasecmp (key, "LogLevel")) {
+               log_level = parse_log_severity(value);
+        if (log_level < 0) {
+            log_level = LOG_INFO;
+            ERROR("log_logstash: invalid loglevel [%s] defaulting to 'info'",
+                  value);
+            return 1;
+        }
+       }
+       else if (0 == strcasecmp (key, "File")) {
+               sfree (log_file);
+               log_file = strdup (value);
+       }
+       else {
+               return -1;
+       }
+       return 0;
+} /* int log_logstash_config (const char *, const char *) */
+
+static void log_logstash_print (yajl_gen g, int severity,
+               cdtime_t timestamp_time)
+{
+       FILE *fh;
+       _Bool do_close = 0;
+       struct tm timestamp_tm;
+       char timestamp_str[64];
+       const unsigned char *buf;
+       time_t tt;
+#if HAVE_YAJL_V2
+       size_t len;
+#else
+       unsigned int len;
+#endif
+
+       if (yajl_gen_string(g, (u_char *)"level", strlen("level")) !=
+           yajl_gen_status_ok)
+               goto err;
+
+       switch (severity) {
+       case LOG_ERR:
+               if (yajl_gen_string(g, (u_char *)"error", strlen("error")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       case LOG_WARNING:
+               if (yajl_gen_string(g, (u_char *)"warning",
+                                   strlen("warning")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       case LOG_NOTICE:
+               if (yajl_gen_string(g, (u_char *)"notice", strlen("notice")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       case LOG_INFO:
+               if (yajl_gen_string(g, (u_char *)"info", strlen("info")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       case LOG_DEBUG:
+               if (yajl_gen_string(g, (u_char *)"debug", strlen("debug")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       default:
+               if (yajl_gen_string(g, (u_char *)"unknown",
+                                   strlen("unknown")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       }
+
+       if (yajl_gen_string(g, (u_char *)"@timestamp", strlen("@timestamp")) !=
+           yajl_gen_status_ok)
+               goto err;
+
+       tt = CDTIME_T_TO_TIME_T (timestamp_time);
+       gmtime_r (&tt, &timestamp_tm);
+
+       /*
+        * format time as a UTC ISO 8601 compliant string
+        */
+       strftime (timestamp_str, sizeof (timestamp_str),
+                 "%Y-%m-%d %H:%M:%SZ", &timestamp_tm);
+       timestamp_str[sizeof (timestamp_str) - 1] = '\0';
+
+       if (yajl_gen_string(g, (u_char *)timestamp_str,
+                           strlen(timestamp_str)) !=
+           yajl_gen_status_ok)
+               goto err;
+
+       if (yajl_gen_map_close(g) != yajl_gen_status_ok)
+               goto err;
+
+       if (yajl_gen_get_buf(g, &buf, &len) != yajl_gen_status_ok)
+               goto err;
+       pthread_mutex_lock (&file_lock);
+
+       if (log_file == NULL)
+       {
+               fh = fopen (DEFAULT_LOGFILE, "a");
+               do_close = 1;
+       } else if (strcasecmp(log_file, "stdout") == 0) {
+        fh = stdout;
+        do_close = 0;
+       } else if (strcasecmp(log_file, "stderr") == 0) {
+        fh = stderr;
+        do_close = 0;
+       } else {
+               fh = fopen (log_file, "a");
+               do_close = 1;
+       }
+
+       if (fh == NULL)
+       {
+                       char errbuf[1024];
+                       fprintf (stderr, "log_logstash plugin: fopen (%s) failed: %s\n",
+                                       (log_file == NULL) ? DEFAULT_LOGFILE : log_file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+       else
+       {
+               fprintf(fh, "%s\n", buf);
+               if (do_close) {
+                       fclose (fh);
+               } else {
+                       fflush(fh);
+               }
+       }
+       pthread_mutex_unlock (&file_lock);
+       yajl_gen_free(g);
+       return;
+
+ err:
+       yajl_gen_free(g);
+       fprintf(stderr, "Could not correctly generate JSON message\n");
+       return;
+} /* void log_logstash_print */
+
+static void log_logstash_log (int severity, const char *msg,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       yajl_gen g;
+#if !defined(HAVE_YAJL_V2)
+       yajl_gen_config conf;
+
+       conf.beautify = 0;
+#endif
+
+       if (severity > log_level)
+               return;
+
+#if HAVE_YAJL_V2
+       g = yajl_gen_alloc(NULL);
+#else
+       g = yajl_gen_alloc(&conf, NULL);
+#endif
+
+       if (g == NULL) {
+               fprintf(stderr, "Could not allocate JSON generator.\n");
+               return;
+       }
+
+       if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+               goto err;
+       if (yajl_gen_string(g, (u_char *)"message", strlen("message")) !=
+           yajl_gen_status_ok)
+               goto err;
+       if (yajl_gen_string(g, (u_char *)msg, strlen(msg)) !=
+           yajl_gen_status_ok)
+               goto err;
+
+       log_logstash_print (g, severity, cdtime ());
+       return;
+ err:
+       yajl_gen_free(g);
+       fprintf(stderr, "Could not generate JSON message preamble\n");
+       return;
+
+} /* void log_logstash_log (int, const char *) */
+
+static int log_logstash_notification (const notification_t *n,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       yajl_gen g;
+#if HAVE_YAJL_V2
+       g = yajl_gen_alloc(NULL);
+#else
+       yajl_gen_config conf;
+
+       conf.beautify = 0;
+       g = yajl_gen_alloc(&conf, NULL);
+#endif
+
+       if (g == NULL) {
+               fprintf(stderr, "Could not allocate JSON generator.\n");
+               return (0);
+       }
+
+       if (yajl_gen_map_open(g) != yajl_gen_status_ok)
+               goto err;
+       if (yajl_gen_string(g, (u_char *)"message", strlen("message")) !=
+           yajl_gen_status_ok)
+               goto err;
+       if (strlen(n->message) > 0) {
+               if (yajl_gen_string(g, (u_char *)n->message,
+                                   strlen(n->message)) !=
+                   yajl_gen_status_ok)
+                       goto err;
+       } else {
+               if (yajl_gen_string(g, (u_char *)"notification without a message",
+                                   strlen("notification without a message")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+       }
+
+       if (strlen(n->host) > 0) {
+               if (yajl_gen_string(g, (u_char *)"host", strlen("host")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               if (yajl_gen_string(g, (u_char *)n->host, strlen(n->host)) !=
+                   yajl_gen_status_ok)
+                       goto err;
+
+       }
+       if (strlen(n->plugin) > 0) {
+               if (yajl_gen_string(g, (u_char *)"plugin", strlen("plugin")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               if (yajl_gen_string(g, (u_char *)n->plugin, strlen(n->plugin)) !=
+                   yajl_gen_status_ok)
+                       goto err;
+       }
+       if (strlen(n->plugin_instance) > 0) {
+               if (yajl_gen_string(g, (u_char *)"plugin_instance",
+                                   strlen("plugin_instance")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               if (yajl_gen_string(g, (u_char *)n->plugin_instance,
+                                   strlen(n->plugin_instance)) !=
+                   yajl_gen_status_ok)
+                       goto err;
+       }
+       if (strlen(n->type) > 0) {
+               if (yajl_gen_string(g, (u_char *)"type", strlen("type")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               if (yajl_gen_string(g, (u_char *)n->type, strlen(n->type)) !=
+                   yajl_gen_status_ok)
+                       goto err;
+       }
+       if (strlen(n->type_instance) > 0) {
+               if (yajl_gen_string(g, (u_char *)"type_instance",
+                                   strlen("type_instance")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               if (yajl_gen_string(g, (u_char *)n->type_instance,
+                                   strlen(n->type_instance)) !=
+                   yajl_gen_status_ok)
+                       goto err;
+       }
+
+       if (yajl_gen_string(g, (u_char *)"severity",
+                           strlen("severity")) !=
+           yajl_gen_status_ok)
+               goto err;
+
+       switch (n->severity) {
+       case NOTIF_FAILURE:
+               if (yajl_gen_string(g, (u_char *)"failure",
+                                   strlen("failure")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       case NOTIF_WARNING:
+               if (yajl_gen_string(g, (u_char *)"warning",
+                                   strlen("warning")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       case NOTIF_OKAY:
+               if (yajl_gen_string(g, (u_char *)"ok",
+                                   strlen("ok")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       default:
+               if (yajl_gen_string(g, (u_char *)"unknown",
+                                   strlen("unknown")) !=
+                   yajl_gen_status_ok)
+                       goto err;
+               break;
+       }
+
+       log_logstash_print (g, LOG_INFO, (n->time != 0) ? n->time : cdtime ());
+       return (0);
+
+ err:
+       yajl_gen_free(g);
+       fprintf(stderr, "Could not correctly generate JSON notification\n");
+       return (0);
+} /* int log_logstash_notification */
+
+void module_register (void)
+{
+       plugin_register_config ("log_logstash",
+                               log_logstash_config,
+                               config_keys,
+                               config_keys_num);
+       plugin_register_log ("log_logstash",
+                            log_logstash_log,
+                            /* user_data = */ NULL);
+       plugin_register_notification ("log_logstash",
+                                     log_logstash_notification,
+                                     /* user_data = */ NULL);
+} /* void module_register (void) */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --git a/src/logfile.c b/src/logfile.c
new file mode 100644 (file)
index 0000000..b75ecb8
--- /dev/null
@@ -0,0 +1,235 @@
+/**
+ * collectd - src/logfile.c
+ * Copyright (C) 2007       Sebastian Harl
+ * Copyright (C) 2007,2008  Florian Forster
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <pthread.h>
+
+#define DEFAULT_LOGFILE LOCALSTATEDIR"/log/collectd.log"
+
+#if COLLECT_DEBUG
+static int log_level = LOG_DEBUG;
+#else
+static int log_level = LOG_INFO;
+#endif /* COLLECT_DEBUG */
+
+static pthread_mutex_t file_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static char *log_file = NULL;
+static int print_timestamp = 1;
+static int print_severity = 0;
+
+static const char *config_keys[] =
+{
+       "LogLevel",
+       "File",
+       "Timestamp",
+       "PrintSeverity"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int logfile_config (const char *key, const char *value)
+{
+       if (0 == strcasecmp (key, "LogLevel")) {
+               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);
+               }
+       }
+       else if (0 == strcasecmp (key, "File")) {
+               sfree (log_file);
+               log_file = strdup (value);
+       }
+       else if (0 == strcasecmp (key, "Timestamp")) {
+               if (IS_FALSE (value))
+                       print_timestamp = 0;
+               else
+                       print_timestamp = 1;
+       } else if (0 == strcasecmp(key, "PrintSeverity")) {
+               if (IS_FALSE (value))
+                       print_severity = 0;
+               else
+                       print_severity = 1;
+       }
+       else {
+               return -1;
+       }
+       return 0;
+} /* int logfile_config (const char *, const char *) */
+
+static void logfile_print (const char *msg, int severity,
+               cdtime_t timestamp_time)
+{
+       FILE *fh;
+       _Bool do_close = 0;
+       struct tm timestamp_tm;
+       char timestamp_str[64];
+       char level_str[16] = "";
+
+       if (print_severity)
+       {
+               switch (severity)
+               {
+               case LOG_ERR:
+                       snprintf(level_str, sizeof (level_str), "[error] ");
+                       break;  
+               case LOG_WARNING:
+                       snprintf(level_str, sizeof (level_str), "[warning] ");
+                       break;
+               case LOG_NOTICE:
+                       snprintf(level_str, sizeof (level_str), "[notice] ");
+                       break;  
+               case LOG_INFO:
+                       snprintf(level_str, sizeof (level_str), "[info] ");
+                       break;  
+               case LOG_DEBUG:
+                       snprintf(level_str, sizeof (level_str), "[debug] ");
+                       break;  
+               default:
+                       break;
+               }
+       }
+
+       if (print_timestamp)
+       {
+               time_t tt = CDTIME_T_TO_TIME_T (timestamp_time);
+               localtime_r (&tt, &timestamp_tm);
+
+               strftime (timestamp_str, sizeof (timestamp_str), "%Y-%m-%d %H:%M:%S",
+                               &timestamp_tm);
+               timestamp_str[sizeof (timestamp_str) - 1] = '\0';
+       }
+
+       pthread_mutex_lock (&file_lock);
+
+       if (log_file == NULL)
+       {
+               fh = fopen (DEFAULT_LOGFILE, "a");
+               do_close = 1;
+       }
+       else if (strcasecmp (log_file, "stderr") == 0)
+               fh = stderr;
+       else if (strcasecmp (log_file, "stdout") == 0)
+               fh = stdout;
+       else
+       {
+               fh = fopen (log_file, "a");
+               do_close = 1;
+       }
+
+       if (fh == NULL)
+       {
+                       char errbuf[1024];
+                       fprintf (stderr, "logfile plugin: fopen (%s) failed: %s\n",
+                                       (log_file == NULL) ? DEFAULT_LOGFILE : log_file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+       else
+       {
+               if (print_timestamp)
+                       fprintf (fh, "[%s] %s%s\n", timestamp_str, level_str, msg);
+               else
+                       fprintf (fh, "%s%s\n", level_str, msg);
+
+               if (do_close) {
+                       fclose (fh);
+               } else {
+                       fflush(fh);
+               }
+       }
+
+       pthread_mutex_unlock (&file_lock);
+
+       return;
+} /* void logfile_print */
+
+static void logfile_log (int severity, const char *msg,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       if (severity > log_level)
+               return;
+
+       logfile_print (msg, severity, cdtime ());
+} /* void logfile_log (int, const char *) */
+
+static int logfile_notification (const notification_t *n,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       char  buf[1024] = "";
+       char *buf_ptr = buf;
+       int   buf_len = sizeof (buf);
+       int status;
+
+       status = ssnprintf (buf_ptr, buf_len, "Notification: severity = %s",
+                       (n->severity == NOTIF_FAILURE) ? "FAILURE"
+                       : ((n->severity == NOTIF_WARNING) ? "WARNING"
+                               : ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
+       if (status > 0)
+       {
+               buf_ptr += status;
+               buf_len -= status;
+       }
+
+#define APPEND(bufptr, buflen, key, value) \
+       if ((buflen > 0) && (strlen (value) > 0)) { \
+               int status = ssnprintf (bufptr, buflen, ", %s = %s", key, value); \
+               if (status > 0) { \
+                       bufptr += status; \
+                       buflen -= status; \
+               } \
+       }
+       APPEND (buf_ptr, buf_len, "host", n->host);
+       APPEND (buf_ptr, buf_len, "plugin", n->plugin);
+       APPEND (buf_ptr, buf_len, "plugin_instance", n->plugin_instance);
+       APPEND (buf_ptr, buf_len, "type", n->type);
+       APPEND (buf_ptr, buf_len, "type_instance", n->type_instance);
+       APPEND (buf_ptr, buf_len, "message", n->message);
+
+       buf[sizeof (buf) - 1] = '\0';
+
+       logfile_print (buf, LOG_INFO,
+                       (n->time != 0) ? n->time : cdtime ());
+
+       return (0);
+} /* int logfile_notification */
+
+void module_register (void)
+{
+       plugin_register_config ("logfile", logfile_config,
+                       config_keys, config_keys_num);
+       plugin_register_log ("logfile", logfile_log, /* user_data = */ NULL);
+       plugin_register_notification ("logfile", logfile_notification,
+                       /* user_data = */ NULL);
+} /* void module_register (void) */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/lpar.c b/src/lpar.c
new file mode 100644 (file)
index 0000000..4d53447
--- /dev/null
@@ -0,0 +1,273 @@
+/**
+ * collectd - src/lpar.c
+ * Copyright (C) 2010  Aurélien Reynaud
+ *
+ * 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:
+ *   Aurélien Reynaud <collectd at wattapower.net>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <sys/protosw.h>
+#include <libperfstat.h>
+#include <sys/utsname.h>
+
+/* XINTFRAC was defined in libperfstat.h somewhere between AIX 5.3 and 6.1 */
+#ifndef XINTFRAC
+# include <sys/systemcfg.h>
+# define XINTFRAC ((double)(_system_configuration.Xint) / \
+                   (double)(_system_configuration.Xfrac))
+#endif
+
+#define CLOCKTICKS_TO_TICKS(cticks) ((cticks) / XINTFRAC)
+
+static const char *config_keys[] =
+{
+  "CpuPoolStats",
+  "ReportBySerial"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static _Bool pool_stats = 0;
+static _Bool report_by_serial = 0;
+#if PERFSTAT_SUPPORTS_DONATION
+static _Bool donate_flag = 0;
+#endif
+static char serial[SYS_NMLN];
+
+static perfstat_partition_total_t lparstats_old;
+
+static int lpar_config (const char *key, const char *value)
+{
+       if (strcasecmp ("CpuPoolStats", key) == 0)
+       {
+               if (IS_TRUE (value))
+                       pool_stats = 1;
+               else
+                       pool_stats = 0;
+       }
+       else if (strcasecmp ("ReportBySerial", key) == 0)
+       {
+               if (IS_TRUE (value))
+                       report_by_serial = 1;
+               else
+                       report_by_serial = 0;
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+} /* int lpar_config */
+
+static int lpar_init (void)
+{
+       int status;
+
+       /* Retrieve the initial metrics. Returns the number of structures filled. */
+       status = perfstat_partition_total (/* name = */ NULL, /* (must be NULL) */
+                       &lparstats_old, sizeof (perfstat_partition_total_t),
+                       /* number = */ 1 /* (must be 1) */);
+       if (status != 1)
+       {
+               char errbuf[1024];
+               ERROR ("lpar plugin: perfstat_partition_total failed: %s (%i)",
+                               sstrerror (errno, errbuf, sizeof (errbuf)),
+                               status);
+               return (-1);
+       }
+
+#if PERFSTAT_SUPPORTS_DONATION
+       if (!lparstats_old.type.b.shared_enabled
+                       && lparstats_old.type.b.donate_enabled)
+       {
+               donate_flag = 1;
+       }
+#endif
+
+       if (pool_stats && !lparstats_old.type.b.pool_util_authority)
+       {
+               WARNING ("lpar plugin: This partition does not have pool authority. "
+                               "Disabling CPU pool statistics collection.");
+               pool_stats = 0;
+       }
+
+       return (0);
+} /* int lpar_init */
+
+static void lpar_submit (const char *type_instance, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = (gauge_t)value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       if (report_by_serial)
+       {
+               sstrncpy (vl.host, serial, sizeof (vl.host));
+               sstrncpy (vl.plugin_instance, hostname_g, sizeof (vl.plugin));
+       }
+       else
+       {
+               sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       }
+       sstrncpy (vl.plugin, "lpar", sizeof (vl.plugin));
+       sstrncpy (vl.type, "vcpu", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void lpar_submit */
+
+static int lpar_read (void)
+{
+       perfstat_partition_total_t lparstats;
+       int status;
+       struct utsname name;
+       u_longlong_t ticks;
+       u_longlong_t user_ticks, syst_ticks, wait_ticks, idle_ticks;
+       u_longlong_t consumed_ticks;
+       double entitled_proc_capacity;
+
+       /* An LPAR has the same serial number as the physical system it is currently
+          running on. It is a convenient way of tracking LPARs as they are moved
+          from chassis to chassis through Live Partition Mobility (LPM). */
+       if (uname (&name) != 0)
+       {
+               ERROR ("lpar plugin: uname failed.");
+               return (-1);
+       }
+       sstrncpy (serial, name.machine, sizeof (serial));
+
+       /* Retrieve the current metrics. Returns the number of structures filled. */
+       status = perfstat_partition_total (/* name = */ NULL, /* (must be NULL) */
+                       &lparstats, sizeof (perfstat_partition_total_t),
+                       /* number = */ 1 /* (must be 1) */);
+       if (status != 1)
+       {
+               char errbuf[1024];
+               ERROR ("lpar plugin: perfstat_partition_total failed: %s (%i)",
+                               sstrerror (errno, errbuf, sizeof (errbuf)),
+                               status);
+               return (-1);
+       }
+
+       /* Number of ticks since we last run. */
+       ticks = lparstats.timebase_last - lparstats_old.timebase_last;
+       if (ticks == 0)
+       {
+               /* The stats have not been updated. Return now to avoid
+                * dividing by zero */
+               return (0);
+       }
+
+       /*
+        * On a shared partition, we're "entitled" to a certain amount of
+        * processing power, for example 250/100 of a physical CPU. Processing
+        * capacity not used by the partition may be assigned to a different
+        * partition by the hypervisor, so "idle" is hopefully a very small
+        * number.
+        *
+        * A dedicated partition may donate its CPUs to another partition and
+        * may steal ticks from somewhere else (another partition or maybe the
+        * shared pool, I don't know --octo).
+        */
+
+       /* entitled_proc_capacity is in 1/100th of a CPU */
+       entitled_proc_capacity = 0.01 * ((double) lparstats.entitled_proc_capacity);
+       lpar_submit ("entitled", entitled_proc_capacity);
+
+       /* The number of ticks actually spent in the various states */
+       user_ticks = lparstats.puser - lparstats_old.puser;
+       syst_ticks = lparstats.psys  - lparstats_old.psys;
+       wait_ticks = lparstats.pwait - lparstats_old.pwait;
+       idle_ticks = lparstats.pidle - lparstats_old.pidle;
+       consumed_ticks = user_ticks + syst_ticks + wait_ticks + idle_ticks;
+
+       lpar_submit ("user", (double) user_ticks / (double) ticks);
+       lpar_submit ("system", (double) syst_ticks / (double) ticks);
+       lpar_submit ("wait", (double) wait_ticks / (double) ticks);
+       lpar_submit ("idle", (double) idle_ticks / (double) ticks);
+
+#if PERFSTAT_SUPPORTS_DONATION
+       if (donate_flag)
+       {
+               /* donated => ticks given to another partition
+                * stolen  => ticks received from another partition */
+               u_longlong_t idle_donated_ticks, busy_donated_ticks;
+               u_longlong_t idle_stolen_ticks, busy_stolen_ticks;
+
+               /* FYI:  PURR == Processor Utilization of Resources Register
+                *      SPURR == Scaled PURR */
+               idle_donated_ticks = lparstats.idle_donated_purr - lparstats_old.idle_donated_purr;
+               busy_donated_ticks = lparstats.busy_donated_purr - lparstats_old.busy_donated_purr;
+               idle_stolen_ticks  = lparstats.idle_stolen_purr  - lparstats_old.idle_stolen_purr;
+               busy_stolen_ticks  = lparstats.busy_stolen_purr  - lparstats_old.busy_stolen_purr;
+
+               lpar_submit ("idle_donated", (double) idle_donated_ticks / (double) ticks);
+               lpar_submit ("busy_donated", (double) busy_donated_ticks / (double) ticks);
+               lpar_submit ("idle_stolen",  (double) idle_stolen_ticks  / (double) ticks);
+               lpar_submit ("busy_stolen",  (double) busy_stolen_ticks  / (double) ticks);
+
+               /* Donated ticks will be accounted for as stolen ticks in other LPARs */
+               consumed_ticks += idle_stolen_ticks + busy_stolen_ticks;
+       }
+#endif
+
+       lpar_submit ("consumed", (double) consumed_ticks / (double) ticks);
+
+       if (pool_stats)
+       {
+               char typinst[DATA_MAX_NAME_LEN];
+               u_longlong_t pool_idle_cticks;
+               double pool_idle_cpus;
+               double pool_busy_cpus;
+
+               /* We're calculating "busy" from "idle" and the total number of
+                * CPUs, because the "busy" member didn't exist in early versions
+                * of libperfstat. It was added somewhere between AIX 5.3 ML5 and ML9. */
+               pool_idle_cticks = lparstats.pool_idle_time - lparstats_old.pool_idle_time;
+               pool_idle_cpus = CLOCKTICKS_TO_TICKS ((double) pool_idle_cticks) / (double) ticks;
+               pool_busy_cpus = ((double) lparstats.phys_cpus_pool) - pool_idle_cpus;
+               if (pool_busy_cpus < 0.0)
+                       pool_busy_cpus = 0.0;
+
+               ssnprintf (typinst, sizeof (typinst), "pool-%X-busy", lparstats.pool_id);
+               lpar_submit (typinst, pool_busy_cpus);
+
+               ssnprintf (typinst, sizeof (typinst), "pool-%X-idle", lparstats.pool_id);
+               lpar_submit (typinst, pool_idle_cpus);
+       }
+
+       memcpy (&lparstats_old, &lparstats, sizeof (lparstats_old));
+
+       return (0);
+} /* int lpar_read */
+
+void module_register (void)
+{
+       plugin_register_config ("lpar", lpar_config,
+                               config_keys, config_keys_num);
+       plugin_register_init ("lpar", lpar_init);
+       plugin_register_read ("lpar", lpar_read);
+} /* void module_register */
+
+/* vim: set sw=8 noet : */
+
diff --git a/src/lvm.c b/src/lvm.c
new file mode 100644 (file)
index 0000000..9e24542
--- /dev/null
+++ b/src/lvm.c
@@ -0,0 +1,201 @@
+/**
+ * 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 cs.cmu.edu>
+ **/
+
+#include <lvm2app.h>
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.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_t v;
+    value_list_t vl = VALUE_LIST_INIT;
+
+    v.gauge = (gauge_t) ivalue;
+
+    vl.values = &v;
+    vl.values_len = 1;
+
+    sstrncpy(vl.host, hostname_g, sizeof (vl.host));
+    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);
+
+    ssnprintf(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 */
+
+void module_register(void)
+{
+    plugin_register_read("lvm", lvm_read);
+} /* void module_register */
diff --git a/src/madwifi.c b/src/madwifi.c
new file mode 100644 (file)
index 0000000..13301ff
--- /dev/null
@@ -0,0 +1,975 @@
+/**
+ * collectd - src/madwifi.c
+ * Copyright (C) 2009  Ondrej 'SanTiago' Zajicek
+ *
+ * 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:
+ *   Ondrej 'SanTiago' Zajicek <santiago@crfreenet.org>
+ *
+ *   based on some code from interfaces.c (collectd) and Madwifi driver
+ **/
+
+
+/**
+ * There are several data streams provided by Madwifi plugin, some are 
+ * connected to network interface, some are connected to each node
+ * associated to that interface. Nodes represents other sides in
+ * wireless communication, for example on network interface in AP mode,
+ * there is one node for each associated station. Node data streams
+ * contain MAC address of the node as the last part  of the type_instance
+ * field.
+ *
+ * Inteface data streams:
+ *     ath_nodes       The number of associated nodes
+ *     ath_stat        Device statistic counters
+ *
+ * Node data streams:
+ *     node_octets     RX and TX data count (octets/bytes)
+ *     node_rssi       Received RSSI of the node
+ *     node_tx_rate    Reported TX rate to that node
+ *     node_stat       Node statistic counters
+ *
+ * Both statistic counters have type instances for each counter returned
+ * by Madwifi. See madwifi.h for content of ieee80211_nodestats, 
+ * ieee80211_stats and ath_stats structures. Type instances use the same
+ * name as fields in these structures (like ns_rx_dup). Some fields are
+ * not reported, because they are not counters (like ns_tx_deauth_code
+ * or ast_tx_rssi). Fields ns_rx_bytes and ns_tx_bytes are reported as
+ * node_octets data stream instead of type instance of node_stat.
+ * Statistics are not logged when they are zero.
+ * 
+ * There are two sets of these counters - the first 'WatchList' is a
+ * set of counters that are individually logged. The second 'MiscList'
+ * is a set of counters that are summed together and the sum is logged.
+ * By default, the most important statistics are in the WatchList and 
+ * many error statistics are in MiscList. There are also many statistics
+ * that are not in any of these sets, so they are not monitored by default.
+ * It is possible to alter these lists using configuration options:
+ *
+ *     WatchAdd X      Adds X to WachList
+ *     WatchRemove X   Removes X from WachList
+ *     WatchSet All    Adds all statistics to WatchList
+ *     WatchSet None   Removes all statistics from WachList
+ *
+ * There are also Misc* variants fo these options, they modifies MiscList
+ * instead of WatchList.
+ *
+ * Example:
+ *
+ *     WatchSet None
+ *     WatchAdd node_octets
+ *     WatchAdd node_rssi
+ *     WatchAdd is_rx_acl
+ *     WatchAdd is_scan_active
+ *
+ * That causes that just the four mentioned data streams are logged.
+ *
+ *
+ * By default, madwifi plugin enumerates network interfaces using /sys
+ * filesystem. Configuration option `Source' can change this to use
+ * /proc filesystem (which is useful for example when running on Linux
+ * 2.4). But without /sys filesystem, Madwifi plugin cannot check whether
+ * given interface is madwifi interface and there are private ioctls used,
+ * which may do something completely different on non-madwifi devices.
+ * Therefore, the /proc filesystem should always be used together with option
+ * `Interface', to limit found interfaces to madwifi interfaces only.
+ **/
+
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_ignorelist.h"
+
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+#include <linux/wireless.h>
+#include "madwifi.h"
+
+
+
+struct stat_spec {
+       uint16_t flags;
+       uint16_t offset;
+       const char *name;
+};
+
+
+#define OFFSETOF(s, i) ((size_t)&((s *)0)->i)
+
+#define FLAG(i)  (((uint32_t) 1) << ((i) % 32))
+
+#define SPC_STAT 0
+#define NOD_STAT 1
+#define IFA_STAT 2
+#define ATH_STAT 3
+#define SRC_MASK 3
+
+/* By default, the item is disabled */
+#define D 0
+
+/* By default, the item is logged */
+#define LOG 4
+
+/* By default, the item is summed with other such items and logged together */
+#define SU 8
+
+#define SS_STAT(flags, name) { flags | SPC_STAT, 0, #name }
+#define NS_STAT(flags, name) { flags | NOD_STAT, OFFSETOF(struct ieee80211_nodestats, name), #name }
+#define IS_STAT(flags, name) { flags | IFA_STAT, OFFSETOF(struct ieee80211_stats, name), #name }
+#define AS_STAT(flags, name) { flags | ATH_STAT, OFFSETOF(struct ath_stats, name), #name }
+
+
+/*
+ * (Module-)Global variables
+ */
+
+/* Indices of special stats in specs array */
+#define STAT_NODE_OCTETS       0
+#define STAT_NODE_RSSI         1
+#define STAT_NODE_TX_RATE      2
+#define STAT_ATH_NODES         3
+#define STAT_NS_RX_BEACONS     4
+#define STAT_AST_ANT_RX                5
+#define STAT_AST_ANT_TX                6
+
+static struct stat_spec specs[] = {
+
+/* Special statistics */
+SS_STAT(LOG, node_octets),             /* rx and tx data count (bytes) */
+SS_STAT(LOG, node_rssi),               /* received RSSI of the node */
+SS_STAT(LOG, node_tx_rate),            /* used tx rate to the node */
+SS_STAT(LOG, ath_nodes),               /* the number of associated nodes */
+SS_STAT(D,   ns_rx_beacons),           /* rx beacon frames */
+SS_STAT(LOG, ast_ant_rx),              /* rx frames with antenna */
+SS_STAT(LOG, ast_ant_tx),              /* tx frames with antenna */
+
+/* Node statistics */
+NS_STAT(LOG, ns_rx_data),              /* rx data frames */
+NS_STAT(LOG, ns_rx_mgmt),              /* rx management frames */
+NS_STAT(LOG, ns_rx_ctrl),              /* rx control frames */
+NS_STAT(D,   ns_rx_ucast),             /* rx unicast frames */
+NS_STAT(D,   ns_rx_mcast),             /* rx multi/broadcast frames */
+NS_STAT(D,   ns_rx_proberesp),         /* rx probe response frames */
+NS_STAT(LOG, ns_rx_dup),               /* rx discard because it's a dup */
+NS_STAT(SU,  ns_rx_noprivacy),         /* rx w/ wep but privacy off */
+NS_STAT(SU,  ns_rx_wepfail),           /* rx wep processing failed */
+NS_STAT(SU,  ns_rx_demicfail),         /* rx demic failed */
+NS_STAT(SU,  ns_rx_decap),             /* rx decapsulation failed */
+NS_STAT(SU,  ns_rx_defrag),            /* rx defragmentation failed */
+NS_STAT(D,   ns_rx_disassoc),          /* rx disassociation */
+NS_STAT(D,   ns_rx_deauth),            /* rx deauthentication */
+NS_STAT(SU,  ns_rx_decryptcrc),                /* rx decrypt failed on crc */
+NS_STAT(SU,  ns_rx_unauth),            /* rx on unauthorized port */
+NS_STAT(SU,  ns_rx_unencrypted),       /* rx unecrypted w/ privacy */
+NS_STAT(LOG, ns_tx_data),              /* tx data frames */
+NS_STAT(LOG, ns_tx_mgmt),              /* tx management frames */
+NS_STAT(D,   ns_tx_ucast),             /* tx unicast frames */
+NS_STAT(D,   ns_tx_mcast),             /* tx multi/broadcast frames */
+NS_STAT(D,   ns_tx_probereq),          /* tx probe request frames */
+NS_STAT(D,   ns_tx_uapsd),             /* tx on uapsd queue */
+NS_STAT(SU,  ns_tx_novlantag),         /* tx discard due to no tag */
+NS_STAT(SU,  ns_tx_vlanmismatch),      /* tx discard due to of bad tag */
+NS_STAT(D,   ns_tx_eosplost),          /* uapsd EOSP retried out */
+NS_STAT(D,   ns_ps_discard),           /* ps discard due to of age */
+NS_STAT(D,   ns_uapsd_triggers),       /* uapsd triggers */
+NS_STAT(LOG, ns_tx_assoc),             /* [re]associations */
+NS_STAT(LOG, ns_tx_auth),              /* [re]authentications */
+NS_STAT(D,   ns_tx_deauth),            /* deauthentications */
+NS_STAT(D,   ns_tx_disassoc),          /* disassociations */
+NS_STAT(D,   ns_psq_drops),            /* power save queue drops */
+
+/* Iface statistics */
+IS_STAT(SU,  is_rx_badversion),                /* rx frame with bad version */
+IS_STAT(SU,  is_rx_tooshort),          /* rx frame too short */
+IS_STAT(LOG, is_rx_wrongbss),          /* rx from wrong bssid */
+IS_STAT(LOG, is_rx_dup),               /* rx discard due to it's a dup */
+IS_STAT(SU,  is_rx_wrongdir),          /* rx w/ wrong direction */
+IS_STAT(D,   is_rx_mcastecho),         /* rx discard due to of mcast echo */
+IS_STAT(SU,  is_rx_notassoc),          /* rx discard due to sta !assoc */
+IS_STAT(SU,  is_rx_noprivacy),         /* rx w/ wep but privacy off */
+IS_STAT(SU,  is_rx_unencrypted),       /* rx w/o wep and privacy on */
+IS_STAT(SU,  is_rx_wepfail),           /* rx wep processing failed */
+IS_STAT(SU,  is_rx_decap),             /* rx decapsulation failed */
+IS_STAT(D,   is_rx_mgtdiscard),                /* rx discard mgt frames */
+IS_STAT(D,   is_rx_ctl),               /* rx discard ctrl frames */
+IS_STAT(D,   is_rx_beacon),            /* rx beacon frames */
+IS_STAT(D,   is_rx_rstoobig),          /* rx rate set truncated */
+IS_STAT(SU,  is_rx_elem_missing),      /* rx required element missing*/
+IS_STAT(SU,  is_rx_elem_toobig),       /* rx element too big */
+IS_STAT(SU,  is_rx_elem_toosmall),     /* rx element too small */
+IS_STAT(LOG, is_rx_elem_unknown),      /* rx element unknown */
+IS_STAT(SU,  is_rx_badchan),           /* rx frame w/ invalid chan */
+IS_STAT(SU,  is_rx_chanmismatch),      /* rx frame chan mismatch */
+IS_STAT(SU,  is_rx_nodealloc),         /* rx frame dropped */
+IS_STAT(LOG, is_rx_ssidmismatch),      /* rx frame ssid mismatch  */
+IS_STAT(SU,  is_rx_auth_unsupported),  /* rx w/ unsupported auth alg */
+IS_STAT(SU,  is_rx_auth_fail),         /* rx sta auth failure */
+IS_STAT(SU,  is_rx_auth_countermeasures),/* rx auth discard due to CM */
+IS_STAT(SU,  is_rx_assoc_bss),         /* rx assoc from wrong bssid */
+IS_STAT(SU,  is_rx_assoc_notauth),     /* rx assoc w/o auth */
+IS_STAT(SU,  is_rx_assoc_capmismatch), /* rx assoc w/ cap mismatch */
+IS_STAT(SU,  is_rx_assoc_norate),      /* rx assoc w/ no rate match */
+IS_STAT(SU,  is_rx_assoc_badwpaie),    /* rx assoc w/ bad WPA IE */
+IS_STAT(LOG, is_rx_deauth),            /* rx deauthentication */
+IS_STAT(LOG, is_rx_disassoc),          /* rx disassociation */
+IS_STAT(SU,  is_rx_badsubtype),                /* rx frame w/ unknown subtype*/
+IS_STAT(SU,  is_rx_nobuf),             /* rx failed for lack of buf */
+IS_STAT(SU,  is_rx_decryptcrc),                /* rx decrypt failed on crc */
+IS_STAT(D,   is_rx_ahdemo_mgt),                /* rx discard ahdemo mgt frame*/
+IS_STAT(SU,  is_rx_bad_auth),          /* rx bad auth request */
+IS_STAT(SU,  is_rx_unauth),            /* rx on unauthorized port */
+IS_STAT(SU,  is_rx_badkeyid),          /* rx w/ incorrect keyid */
+IS_STAT(D,   is_rx_ccmpreplay),                /* rx seq# violation (CCMP), */
+IS_STAT(D,   is_rx_ccmpformat),                /* rx format bad (CCMP), */
+IS_STAT(D,   is_rx_ccmpmic),           /* rx MIC check failed (CCMP), */
+IS_STAT(D,   is_rx_tkipreplay),                /* rx seq# violation (TKIP), */
+IS_STAT(D,   is_rx_tkipformat),                /* rx format bad (TKIP), */
+IS_STAT(D,   is_rx_tkipmic),           /* rx MIC check failed (TKIP), */
+IS_STAT(D,   is_rx_tkipicv),           /* rx ICV check failed (TKIP), */
+IS_STAT(D,   is_rx_badcipher),         /* rx failed due to of key type */
+IS_STAT(D,   is_rx_nocipherctx),       /* rx failed due to key !setup */
+IS_STAT(D,   is_rx_acl),               /* rx discard due to of acl policy */
+IS_STAT(D,   is_rx_ffcnt),             /* rx fast frames */
+IS_STAT(SU,  is_rx_badathtnl),         /* driver key alloc failed */
+IS_STAT(SU,  is_tx_nobuf),             /* tx failed for lack of buf */
+IS_STAT(SU,  is_tx_nonode),            /* tx failed for no node */
+IS_STAT(SU,  is_tx_unknownmgt),                /* tx of unknown mgt frame */
+IS_STAT(SU,  is_tx_badcipher),         /* tx failed due to of key type */
+IS_STAT(SU,  is_tx_nodefkey),          /* tx failed due to no defkey */
+IS_STAT(SU,  is_tx_noheadroom),                /* tx failed due to no space */
+IS_STAT(D,   is_tx_ffokcnt),           /* tx fast frames sent success */
+IS_STAT(D,   is_tx_fferrcnt),          /* tx fast frames sent success */
+IS_STAT(D,   is_scan_active),          /* active scans started */
+IS_STAT(D,   is_scan_passive),         /* passive scans started */
+IS_STAT(D,   is_node_timeout),         /* nodes timed out inactivity */
+IS_STAT(D,   is_crypto_nomem),         /* no memory for crypto ctx */
+IS_STAT(D,   is_crypto_tkip),          /* tkip crypto done in s/w */
+IS_STAT(D,   is_crypto_tkipenmic),     /* tkip en-MIC done in s/w */
+IS_STAT(D,   is_crypto_tkipdemic),     /* tkip de-MIC done in s/w */
+IS_STAT(D,   is_crypto_tkipcm),                /* tkip counter measures */
+IS_STAT(D,   is_crypto_ccmp),          /* ccmp crypto done in s/w */
+IS_STAT(D,   is_crypto_wep),           /* wep crypto done in s/w */
+IS_STAT(D,   is_crypto_setkey_cipher), /* cipher rejected key */
+IS_STAT(D,   is_crypto_setkey_nokey),  /* no key index for setkey */
+IS_STAT(D,   is_crypto_delkey),                /* driver key delete failed */
+IS_STAT(D,   is_crypto_badcipher),     /* unknown cipher */
+IS_STAT(D,   is_crypto_nocipher),      /* cipher not available */
+IS_STAT(D,   is_crypto_attachfail),    /* cipher attach failed */
+IS_STAT(D,   is_crypto_swfallback),    /* cipher fallback to s/w */
+IS_STAT(D,   is_crypto_keyfail),       /* driver key alloc failed */
+IS_STAT(D,   is_crypto_enmicfail),     /* en-MIC failed */
+IS_STAT(SU,  is_ibss_capmismatch),     /* merge failed-cap mismatch */
+IS_STAT(SU,  is_ibss_norate),          /* merge failed-rate mismatch */
+IS_STAT(D,   is_ps_unassoc),           /* ps-poll for unassoc. sta */
+IS_STAT(D,   is_ps_badaid),            /* ps-poll w/ incorrect aid */
+IS_STAT(D,   is_ps_qempty),            /* ps-poll w/ nothing to send */
+
+/* Atheros statistics */
+AS_STAT(D,   ast_watchdog),            /* device reset by watchdog */
+AS_STAT(D,   ast_hardware),            /* fatal hardware error interrupts */
+AS_STAT(D,   ast_bmiss),               /* beacon miss interrupts */
+AS_STAT(D,   ast_rxorn),               /* rx overrun interrupts */
+AS_STAT(D,   ast_rxeol),               /* rx eol interrupts */
+AS_STAT(D,   ast_txurn),               /* tx underrun interrupts */
+AS_STAT(D,   ast_mib),                 /* mib interrupts */
+AS_STAT(D,   ast_tx_packets),          /* packet sent on the interface */
+AS_STAT(D,   ast_tx_mgmt),             /* management frames transmitted */
+AS_STAT(LOG, ast_tx_discard),          /* frames discarded prior to assoc */
+AS_STAT(SU,  ast_tx_invalid),          /* frames discarded due to is device gone */
+AS_STAT(SU,  ast_tx_qstop),            /* tx queue stopped because it's full */
+AS_STAT(SU,  ast_tx_encap),            /* tx encapsulation failed */
+AS_STAT(SU,  ast_tx_nonode),           /* tx failed due to of no node */
+AS_STAT(SU,  ast_tx_nobuf),            /* tx failed due to of no tx buffer (data), */
+AS_STAT(SU,  ast_tx_nobufmgt),         /* tx failed due to of no tx buffer (mgmt),*/
+AS_STAT(LOG, ast_tx_xretries),         /* tx failed due to of too many retries */
+AS_STAT(SU,  ast_tx_fifoerr),          /* tx failed due to of FIFO underrun */
+AS_STAT(SU,  ast_tx_filtered),         /* tx failed due to xmit filtered */
+AS_STAT(LOG, ast_tx_shortretry),       /* tx on-chip retries (short), */
+AS_STAT(LOG, ast_tx_longretry),                /* tx on-chip retries (long), */
+AS_STAT(SU,  ast_tx_badrate),          /* tx failed due to of bogus xmit rate */
+AS_STAT(D,   ast_tx_noack),            /* tx frames with no ack marked */
+AS_STAT(D,   ast_tx_rts),              /* tx frames with rts enabled */
+AS_STAT(D,   ast_tx_cts),              /* tx frames with cts enabled */
+AS_STAT(D,   ast_tx_shortpre),         /* tx frames with short preamble */
+AS_STAT(LOG, ast_tx_altrate),          /* tx frames with alternate rate */
+AS_STAT(D,   ast_tx_protect),          /* tx frames with protection */
+AS_STAT(SU,  ast_rx_orn),              /* rx failed due to of desc overrun */
+AS_STAT(LOG, ast_rx_crcerr),           /* rx failed due to of bad CRC */
+AS_STAT(SU,  ast_rx_fifoerr),          /* rx failed due to of FIFO overrun */
+AS_STAT(SU,  ast_rx_badcrypt),         /* rx failed due to of decryption */
+AS_STAT(SU,  ast_rx_badmic),           /* rx failed due to of MIC failure */
+AS_STAT(LOG, ast_rx_phyerr),           /* rx PHY error summary count */
+AS_STAT(SU,  ast_rx_tooshort),         /* rx discarded due to frame too short */
+AS_STAT(SU,  ast_rx_toobig),           /* rx discarded due to frame too large */
+AS_STAT(SU,  ast_rx_nobuf),            /* rx setup failed due to of no skbuff */
+AS_STAT(D,   ast_rx_packets),          /* packet recv on the interface */
+AS_STAT(D,   ast_rx_mgt),              /* management frames received */
+AS_STAT(D,   ast_rx_ctl),              /* control frames received */
+AS_STAT(D,   ast_be_xmit),             /* beacons transmitted */
+AS_STAT(SU,  ast_be_nobuf),            /* no skbuff available for beacon */
+AS_STAT(D,   ast_per_cal),             /* periodic calibration calls */
+AS_STAT(D,   ast_per_calfail),         /* periodic calibration failed */
+AS_STAT(D,   ast_per_rfgain),          /* periodic calibration rfgain reset */
+AS_STAT(D,   ast_rate_calls),          /* rate control checks */
+AS_STAT(D,   ast_rate_raise),          /* rate control raised xmit rate */
+AS_STAT(D,   ast_rate_drop),           /* rate control dropped xmit rate */
+AS_STAT(D,   ast_ant_defswitch),       /* rx/default antenna switches */
+AS_STAT(D,   ast_ant_txswitch)         /* tx antenna switches */
+};
+
+/* Bounds between SS, NS, IS and AS stats in stats array */
+static int bounds[4];
+
+#define WL_LEN 6
+/* Bitmasks for logged and error items */
+static uint32_t watch_items[WL_LEN];
+static uint32_t misc_items[WL_LEN];
+
+
+static const char *config_keys[] =
+{
+       "Interface",
+       "IgnoreSelected",
+       "Source",
+       "WatchAdd",
+       "WatchRemove",
+       "WatchSet",
+       "MiscAdd",
+       "MiscRemove",
+       "MiscSet"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+static int use_sysfs = 1;
+static int init_state = 0;
+
+static inline int item_watched(int i)
+{
+       assert (i >= 0);
+       assert (i < ((STATIC_ARRAY_SIZE (watch_items) + 1) * 32));
+       return watch_items[i / 32] & FLAG (i);
+}
+
+static inline int item_summed(int i)
+{
+       assert (i >= 0);
+       assert (i < ((STATIC_ARRAY_SIZE (misc_items) + 1) * 32));
+       return misc_items[i / 32] & FLAG (i);
+}
+
+static inline void watchlist_add (uint32_t *wl, int item)
+{
+       assert (item >= 0);
+       assert (item < ((WL_LEN + 1) * 32));
+       wl[item / 32] |= FLAG (item);
+}
+
+static inline void watchlist_remove (uint32_t *wl, int item)
+{
+       assert (item >= 0);
+       assert (item < ((WL_LEN + 1) * 32));
+       wl[item / 32] &= ~FLAG (item);
+}
+
+static inline void watchlist_set (uint32_t *wl, uint32_t val)
+{
+       int i;
+       for (i = 0; i < WL_LEN; i++)
+               wl[i] = val;
+}
+
+/* This is horribly inefficient, but it is called only during configuration */
+static int watchitem_find (const char *name)
+{
+       int max = STATIC_ARRAY_SIZE (specs);
+       int i;
+
+       for (i = 0; i < max; i++)
+               if (strcasecmp (name, specs[i].name) == 0)
+                       return i;
+
+       return -1;
+}
+
+
+/* Collectd hooks */
+
+/* We need init function called before madwifi_config */
+
+static int madwifi_real_init (void)
+{
+       int max = STATIC_ARRAY_SIZE (specs);
+       int i;
+
+       for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
+               bounds[i] = 0;
+
+       watchlist_set(watch_items, 0);
+       watchlist_set(misc_items, 0);
+
+       for (i = 0; i < max; i++)
+       {
+               bounds[specs[i].flags & SRC_MASK] = i;
+
+               if (specs[i].flags & LOG)
+                       watch_items[i / 32] |= FLAG (i);
+
+               if (specs[i].flags & SU)
+                       misc_items[i / 32] |= FLAG (i);
+       }
+
+       for (i = 0; i < STATIC_ARRAY_SIZE (bounds); i++)
+               bounds[i]++;
+
+       return (0);
+}
+
+static int madwifi_config (const char *key, const char *value)
+{
+       if (init_state != 1)
+               madwifi_real_init();
+       init_state = 1;
+
+       if (ignorelist == NULL)
+               ignorelist = ignorelist_create (/* invert = */ 1);
+
+       if (strcasecmp (key, "Interface") == 0)
+               ignorelist_add (ignorelist, value);
+
+       else if (strcasecmp (key, "IgnoreSelected") == 0)
+               ignorelist_set_invert (ignorelist, IS_TRUE (value) ? 0 : 1);
+
+       else if (strcasecmp (key, "Source") == 0)
+       {
+               if (strcasecmp (value, "ProcFS") == 0)
+                       use_sysfs = 0;
+               else if (strcasecmp (value, "SysFS") == 0)
+                       use_sysfs = 1;
+               else
+               {
+                       ERROR ("madwifi plugin: The argument of the `Source' "
+                                       "option must either be `SysFS' or "
+                                       "`ProcFS'.");
+                       return -1;
+               }
+       }
+
+       else if (strcasecmp (key, "WatchSet") == 0)
+       {
+               if (strcasecmp (value, "All") == 0)
+                       watchlist_set (watch_items, 0xFFFFFFFF);
+               else if (strcasecmp (value, "None") == 0)
+                       watchlist_set (watch_items, 0);
+               else return -1;
+       }
+
+       else if (strcasecmp (key, "WatchAdd") == 0)
+       {
+               int id = watchitem_find (value);
+
+               if (id < 0)
+                       return (-1);
+               else
+                       watchlist_add (watch_items, id);
+       }
+
+       else if (strcasecmp (key, "WatchRemove") == 0)
+       {
+               int id = watchitem_find (value);
+
+               if (id < 0)
+                       return (-1);
+               else
+                       watchlist_remove (watch_items, id);
+       }
+
+       else if (strcasecmp (key, "MiscSet") == 0)
+       {
+               if (strcasecmp (value, "All") == 0)
+                       watchlist_set (misc_items, 0xFFFFFFFF);
+               else if (strcasecmp (value, "None") == 0)
+                       watchlist_set (misc_items, 0);
+               else return -1;
+       }
+
+       else if (strcasecmp (key, "MiscAdd") == 0)
+       {
+               int id = watchitem_find (value);
+
+               if (id < 0)
+                       return (-1);
+               else
+                       watchlist_add (misc_items, id);
+       }
+
+       else if (strcasecmp (key, "MiscRemove") == 0)
+       {
+               int id = watchitem_find (value);
+
+               if (id < 0)
+                       return (-1);
+               else
+                       watchlist_remove (misc_items, id);
+       }
+
+       else
+               return (-1);
+
+       return (0);
+}
+
+
+static void submit (const char *dev, const char *type, const char *ti1,
+                       const char *ti2, value_t *val, int len)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = val;
+       vl.values_len = len;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "madwifi", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       if ((ti1 != NULL) && (ti2 != NULL))
+               ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s", ti1, ti2);
+       else if ((ti1 != NULL) && (ti2 == NULL))
+               sstrncpy (vl.type_instance, ti1, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void submit_derive (const char *dev, const char *type, const char *ti1,
+                               const char *ti2, derive_t val)
+{
+       value_t item;
+       item.derive = val;
+       submit (dev, type, ti1, ti2, &item, 1);
+}
+
+static void submit_derive2 (const char *dev, const char *type, const char *ti1,
+                               const char *ti2, derive_t val1, derive_t val2)
+{
+       value_t items[2];
+       items[0].derive = val1;
+       items[1].derive = val2;
+       submit (dev, type, ti1, ti2, items, 2);
+}
+
+static void submit_gauge (const char *dev, const char *type, const char *ti1,
+                               const char *ti2, gauge_t val)
+{
+       value_t item;
+       item.gauge = val;
+       submit (dev, type, ti1, ti2, &item, 1);
+}
+
+static void submit_antx (const char *dev, const char *name,
+               u_int32_t *vals, int vals_num)
+{
+       char ti2[16];
+       int i;
+
+       for (i = 0; i < vals_num; i++)
+       {
+               if (vals[i] == 0)
+                       continue;
+
+               ssnprintf (ti2, sizeof (ti2), "%i", i);
+               submit_derive (dev, "ath_stat", name, ti2,
+                               (derive_t) vals[i]);
+       }
+}
+
+static inline void
+macaddr_to_str (char *buf, size_t bufsize, const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+       ssnprintf (buf, bufsize, "%02x:%02x:%02x:%02x:%02x:%02x",
+               mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static void
+process_stat_struct (int which, const void *ptr, const char *dev, const char *mac,
+                        const char *type_name, const char *misc_name)
+{
+       uint32_t misc = 0;
+       int i;
+
+       assert (which >= 1);
+       assert (which < STATIC_ARRAY_SIZE (bounds));
+
+       for (i = bounds[which - 1]; i < bounds[which]; i++)
+       {
+               uint32_t val = *(uint32_t *)(((char *) ptr) + specs[i].offset) ;
+
+               if (item_watched (i) && (val != 0))
+                       submit_derive (dev, type_name, specs[i].name, mac, val);
+
+               if (item_summed (i))
+                       misc += val;
+       }
+       
+       if (misc != 0)
+               submit_derive (dev, type_name, misc_name, mac, misc);
+
+}
+
+static int
+process_athstats (int sk, const char *dev)
+{
+       struct ifreq ifr;
+       struct ath_stats stats;
+       int status;
+
+       sstrncpy (ifr.ifr_name, dev, sizeof (ifr.ifr_name));
+       ifr.ifr_data = (void *) &stats;
+       status = ioctl (sk, SIOCGATHSTATS, &ifr);
+       if (status < 0)
+       {
+               /* Silent, because not all interfaces support all ioctls. */
+               DEBUG ("madwifi plugin: Sending IO-control "
+                               "SIOCGATHSTATS to device %s "
+                               "failed with status %i.",
+                               dev, status);
+               return (status);
+       }
+
+       /* These stats are handled as a special case, because they are
+          eight values each */
+
+       if (item_watched (STAT_AST_ANT_RX))
+               submit_antx (dev, "ast_ant_rx", stats.ast_ant_rx,
+                               STATIC_ARRAY_SIZE (stats.ast_ant_rx));
+
+       if (item_watched (STAT_AST_ANT_TX))
+               submit_antx (dev, "ast_ant_tx", stats.ast_ant_tx,
+                               STATIC_ARRAY_SIZE (stats.ast_ant_tx));
+
+       /* All other ath statistics */
+       process_stat_struct (ATH_STAT, &stats, dev, NULL, "ath_stat", "ast_misc");
+       return (0);
+}
+
+static int
+process_80211stats (int sk, const char *dev)
+{
+       struct ifreq ifr;
+       struct ieee80211_stats stats;
+       int status;
+
+       sstrncpy (ifr.ifr_name, dev, sizeof (ifr.ifr_name));
+       ifr.ifr_data = (void *) &stats;
+       status = ioctl(sk, SIOCG80211STATS, &ifr);
+       if (status < 0)
+       {
+               /* Silent, because not all interfaces support all ioctls. */
+               DEBUG ("madwifi plugin: Sending IO-control "
+                               "SIOCG80211STATS to device %s "
+                               "failed with status %i.",
+                               dev, status);
+               return (status);
+       }
+
+       process_stat_struct (IFA_STAT, &stats, dev, NULL, "ath_stat", "is_misc");
+       return (0);
+}
+
+
+static int
+process_station (int sk, const char *dev, struct ieee80211req_sta_info *si)
+{
+       struct iwreq iwr;
+       static char mac[DATA_MAX_NAME_LEN];
+       struct ieee80211req_sta_stats stats;
+       const struct ieee80211_nodestats *ns = &stats.is_stats;
+       int status;
+
+       macaddr_to_str (mac, sizeof (mac), si->isi_macaddr);
+
+       if (item_watched (STAT_NODE_TX_RATE))
+               submit_gauge (dev, "node_tx_rate", mac, NULL,
+                       (si->isi_rates[si->isi_txrate] & IEEE80211_RATE_VAL) / 2);
+
+       if (item_watched (STAT_NODE_RSSI))
+               submit_gauge (dev, "node_rssi", mac, NULL, si->isi_rssi);
+
+       memset (&iwr, 0, sizeof (iwr));
+       sstrncpy(iwr.ifr_name, dev, sizeof (iwr.ifr_name));
+       iwr.u.data.pointer = (void *) &stats;
+       iwr.u.data.length = sizeof (stats);
+       memcpy(stats.is_u.macaddr, si->isi_macaddr, IEEE80211_ADDR_LEN);
+       status = ioctl(sk, IEEE80211_IOCTL_STA_STATS, &iwr);
+       if (status < 0)
+       {
+               /* Silent, because not all interfaces support all ioctls. */
+               DEBUG ("madwifi plugin: Sending IO-control "
+                               "IEEE80211_IOCTL_STA_STATS to device %s "
+                               "failed with status %i.",
+                               dev, status);
+               return (status);
+       }
+
+       /* These two stats are handled as a special case as they are
+          a pair of 64bit values */
+       if (item_watched (STAT_NODE_OCTETS))
+               submit_derive2 (dev, "node_octets", mac, NULL,
+                       ns->ns_rx_bytes, ns->ns_tx_bytes);
+
+       /* This stat is handled as a special case, because it is stored
+          as uin64_t, but we will ignore upper half */
+       if (item_watched (STAT_NS_RX_BEACONS))
+               submit_derive (dev, "node_stat", "ns_rx_beacons", mac,
+                       (ns->ns_rx_beacons & 0xFFFFFFFF));
+
+       /* All other node statistics */
+       process_stat_struct (NOD_STAT, ns, dev, mac, "node_stat", "ns_misc");
+       return (0);
+}
+
+static int
+process_stations (int sk, const char *dev)
+{
+       uint8_t buf[24*1024];
+       struct iwreq iwr;
+       uint8_t *cp;
+       int len, nodes;
+       int status;
+
+       memset (&iwr, 0, sizeof (iwr));
+       sstrncpy (iwr.ifr_name, dev, sizeof (iwr.ifr_name));
+       iwr.u.data.pointer = (void *) buf;
+       iwr.u.data.length = sizeof (buf);
+
+       status = ioctl (sk, IEEE80211_IOCTL_STA_INFO, &iwr);
+       if (status < 0)
+       {
+               /* Silent, because not all interfaces support all ioctls. */
+               DEBUG ("madwifi plugin: Sending IO-control "
+                               "IEEE80211_IOCTL_STA_INFO to device %s "
+                               "failed with status %i.",
+                               dev, status);
+               return (status);
+       }
+
+       len = iwr.u.data.length;
+
+       cp = buf;
+       nodes = 0;
+       while (len >= sizeof (struct ieee80211req_sta_info))
+       {
+               struct ieee80211req_sta_info *si = (void *) cp;
+               process_station(sk, dev, si);
+               cp += si->isi_len;
+               len -= si->isi_len;
+               nodes++;
+       }
+
+       if (item_watched (STAT_ATH_NODES))
+               submit_gauge (dev, "ath_nodes", NULL, NULL, nodes);
+       return (0);
+}
+
+static int
+process_device (int sk, const char *dev)
+{
+       int num_success = 0;
+       int status;
+
+       status = process_athstats (sk, dev);
+       if (status == 0)
+               num_success++;
+
+       status = process_80211stats (sk, dev);
+       if (status == 0)
+               num_success++;
+
+       status = process_stations (sk, dev);
+       if (status == 0)
+               num_success++;
+
+       return ((num_success == 0) ? -1 : 0);
+}
+
+static int
+check_devname (const char *dev)
+{
+       char buf[PATH_MAX];
+       char buf2[PATH_MAX];
+       int i;
+
+       if (dev[0] == '.')
+               return 0;
+       
+       ssnprintf (buf, sizeof (buf), "/sys/class/net/%s/device/driver", dev);
+       buf[sizeof (buf) - 1] = 0;
+
+       memset (buf2, 0, sizeof (buf2));
+       i = readlink (buf, buf2, sizeof (buf2) - 1);
+       if (i < 0)
+               return 0;
+
+       if (strstr (buf2, "/drivers/ath_") == NULL)
+               return 0;
+       return 1;
+}
+
+static int
+sysfs_iterate(int sk)
+{
+       struct dirent *de;
+       DIR *nets;
+       int status;
+       int num_success;
+       int num_fail;
+
+       nets = opendir ("/sys/class/net/");
+       if (nets == NULL)
+       {
+               WARNING ("madwifi plugin: opening /sys/class/net failed");
+               return (-1);
+       }
+
+       num_success = 0;
+       num_fail = 0;
+       while ((de = readdir (nets)))
+       {
+               if (check_devname (de->d_name) == 0)
+                       continue;
+
+               if (ignorelist_match (ignorelist, de->d_name) != 0)
+                       continue;
+
+               status = process_device (sk, de->d_name);
+               if (status != 0)
+               {
+                       ERROR ("madwifi plugin: Processing interface "
+                                       "%s failed.", de->d_name);
+                       num_fail++;
+               }
+               else
+               {
+                       num_success++;
+               }
+       } /* while (readdir) */
+
+       closedir(nets);
+
+       if ((num_success == 0) && (num_fail != 0))
+               return (-1);
+       return (0);
+}
+
+static int
+procfs_iterate(int sk)
+{
+       char buffer[1024];
+       char *device, *dummy;
+       FILE *fh;
+       int status;
+       int num_success;
+       int num_fail;
+       
+       if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
+       {
+               WARNING ("madwifi plugin: opening /proc/net/dev failed");
+               return (-1);
+       }
+
+       num_success = 0;
+       num_fail = 0;
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               dummy = strchr(buffer, ':');
+               if (dummy == NULL)
+                       continue;
+               dummy[0] = 0;
+
+               device = buffer;
+               while (device[0] == ' ')
+                       device++;
+
+               if (device[0] == 0)
+                       continue;
+
+               if (ignorelist_match (ignorelist, device) != 0)
+                       continue;
+
+               status = process_device (sk, device);
+               if (status != 0)
+               {
+                       ERROR ("madwifi plugin: Processing interface "
+                                       "%s failed.", device);
+                       num_fail++;
+               }
+               else
+               {
+                       num_success++;
+               }
+       } /* while (fgets) */
+
+       fclose(fh);
+
+       if ((num_success == 0) && (num_fail != 0))
+               return (-1);
+       return 0;
+}
+
+static int madwifi_read (void)
+{
+       int rv;
+       int sk;
+
+       if (init_state == 0)
+               madwifi_real_init();
+       init_state = 2;
+
+       sk = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sk < 0)
+               return (-1);
+
+
+/* procfs iteration is not safe because it does not check whether given
+   interface is madwifi interface and there are private ioctls used, which
+   may do something completely different on non-madwifi devices.   
+   Therefore, it is not used unless explicitly enabled (and should be used
+   together with ignorelist). */
+
+       if (use_sysfs)
+               rv = sysfs_iterate(sk);
+       else
+               rv = procfs_iterate(sk);
+
+       close(sk);
+
+       return rv;
+}
+
+void module_register (void)
+{
+       plugin_register_config ("madwifi", madwifi_config,
+                       config_keys, config_keys_num);
+
+       plugin_register_read ("madwifi", madwifi_read);
+}
diff --git a/src/madwifi.h b/src/madwifi.h
new file mode 100644 (file)
index 0000000..d6a5e35
--- /dev/null
@@ -0,0 +1,307 @@
+/**
+ * This file is compiled from several Madwifi header files.
+ * Original copyright is:
+ *
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#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 */
+
+
+/*
+ * 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_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_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_ps_discard;        /* ps discard due to of age */
+
+       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 */
+};
+
+/*
+ * 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 */
+};
+
+/*
+ * 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;
+};
+
+/*
+ * Station information block; the mac address is used
+ * 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 */
+
+       /* 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 */
+};
+
+#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)
+
+
+#endif
diff --git a/src/match_empty_counter.c b/src/match_empty_counter.c
new file mode 100644 (file)
index 0000000..abde2b3
--- /dev/null
@@ -0,0 +1,121 @@
+/**
+ * collectd - src/match_empty_counter.c
+ * Copyright (C) 2009       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_cache.h"
+#include "filter_chain.h"
+
+/*
+ * private data types
+ */
+struct mec_match_s;
+typedef struct mec_match_s mec_match_t;
+struct mec_match_s
+{
+  int dummy;
+};
+
+/*
+ * internal helper functions
+ */
+static int mec_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  mec_match_t *m;
+
+  m = (mec_match_t *) malloc (sizeof (*m));
+  if (m == NULL)
+  {
+    ERROR ("mec_create: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (m, 0, sizeof (*m));
+
+  if (ci->children_num != 0)
+  {
+    ERROR ("empty_counter match: This match does not take any additional "
+        "configuration.");
+  }
+
+  *user_data = m;
+  return (0);
+} /* }}} int mec_create */
+
+static int mec_destroy (void **user_data) /* {{{ */
+{
+  if (user_data != NULL)
+  {
+    sfree (*user_data);
+  }
+
+  return (0);
+} /* }}} int mec_destroy */
+
+static int mec_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+    const value_list_t *vl,
+    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+  int num_counters;
+  int num_empty;
+  int i;
+
+  if ((user_data == NULL) || (*user_data == NULL))
+    return (-1);
+
+
+  num_counters = 0;
+  num_empty = 0;
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if (ds->ds[i].type != DS_TYPE_COUNTER)
+      continue;
+
+    num_counters++;
+    if (vl->values[i].counter == 0)
+      num_empty++;
+  }
+
+  if (num_counters == 0)
+    return (FC_MATCH_NO_MATCH);
+  else if (num_counters == num_empty)
+    return (FC_MATCH_MATCHES);
+  else
+    return (FC_MATCH_NO_MATCH);
+} /* }}} int mec_match */
+
+void module_register (void)
+{
+  match_proc_t mproc;
+
+  memset (&mproc, 0, sizeof (mproc));
+  mproc.create  = mec_create;
+  mproc.destroy = mec_destroy;
+  mproc.match   = mec_match;
+  fc_register_match ("empty_counter", mproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
diff --git a/src/match_hashed.c b/src/match_hashed.c
new file mode 100644 (file)
index 0000000..ba0c47c
--- /dev/null
@@ -0,0 +1,189 @@
+/**
+ * collectd - src/match_hashed.c
+ * Copyright (C) 2009       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_cache.h"
+#include "filter_chain.h"
+
+/*
+ * private data types
+ */
+struct mh_hash_match_s
+{
+  uint32_t match;
+  uint32_t total;
+};
+typedef struct mh_hash_match_s mh_hash_match_t;
+
+struct mh_match_s;
+typedef struct mh_match_s mh_match_t;
+struct mh_match_s
+{
+  mh_hash_match_t *matches;
+  size_t           matches_num;
+};
+
+/*
+ * internal helper functions
+ */
+static int mh_config_match (const oconfig_item_t *ci, /* {{{ */
+    mh_match_t *m)
+{
+  mh_hash_match_t *tmp;
+
+  if ((ci->values_num != 2)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER)
+      || (ci->values[1].type != OCONFIG_TYPE_NUMBER))
+  {
+    ERROR ("hashed match: The `Match' option requires "
+        "exactly two numeric arguments.");
+    return (-1);
+  }
+
+  if ((ci->values[0].value.number < 0)
+      || (ci->values[1].value.number < 0))
+  {
+    ERROR ("hashed match: The arguments of the `Match' "
+        "option must be positive.");
+    return (-1);
+  }
+
+  tmp = realloc (m->matches, sizeof (*tmp) * (m->matches_num + 1));
+  if (tmp == NULL)
+  {
+    ERROR ("hashed match: realloc failed.");
+    return (-1);
+  }
+  m->matches = tmp;
+  tmp = m->matches + m->matches_num;
+
+  tmp->match = (uint32_t) (ci->values[0].value.number + .5);
+  tmp->total = (uint32_t) (ci->values[1].value.number + .5);
+
+  if (tmp->match >= tmp->total)
+  {
+    ERROR ("hashed match: The first argument of the `Match' option "
+        "must be smaller than the second argument.");
+    return (-1);
+  }
+  assert (tmp->total != 0);
+
+  m->matches_num++;
+  return (0);
+} /* }}} int mh_config_match */
+
+static int mh_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  mh_match_t *m;
+  int i;
+
+  m = (mh_match_t *) malloc (sizeof (*m));
+  if (m == NULL)
+  {
+    ERROR ("mh_create: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (m, 0, sizeof (*m));
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Match", child->key) == 0)
+      mh_config_match (child, m);
+    else
+      ERROR ("hashed match: No such config option: %s", child->key);
+  }
+
+  if (m->matches_num == 0)
+  {
+    sfree (m->matches);
+    sfree (m);
+    ERROR ("hashed match: No matches were configured. Not creating match.");
+    return (-1);
+  }
+
+  *user_data = m;
+  return (0);
+} /* }}} int mh_create */
+
+static int mh_destroy (void **user_data) /* {{{ */
+{
+  mh_match_t *mh;
+
+  if ((user_data == NULL) || (*user_data == NULL))
+    return (0);
+
+  mh = *user_data;
+  sfree (mh->matches);
+  sfree (mh);
+
+  return (0);
+} /* }}} int mh_destroy */
+
+static int mh_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+    const value_list_t *vl,
+    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+  mh_match_t *m;
+  uint32_t hash_val;
+  const char *host_ptr;
+  size_t i;
+
+  if ((user_data == NULL) || (*user_data == NULL))
+    return (-1);
+
+  m = *user_data;
+
+  hash_val = 0;
+
+  for (host_ptr = vl->host; *host_ptr != 0; host_ptr++)
+  {
+    /* 2184401929 is some appropriately sized prime number. */
+    hash_val = (hash_val * UINT32_C (2184401929)) + ((uint32_t) *host_ptr);
+  }
+  DEBUG ("hashed match: host = %s; hash_val = %"PRIu32";", vl->host, hash_val);
+
+  for (i = 0; i < m->matches_num; i++)
+    if ((hash_val % m->matches[i].total) == m->matches[i].match)
+      return (FC_MATCH_MATCHES);
+
+  return (FC_MATCH_NO_MATCH);
+} /* }}} int mh_match */
+
+void module_register (void)
+{
+  match_proc_t mproc;
+
+  memset (&mproc, 0, sizeof (mproc));
+  mproc.create  = mh_create;
+  mproc.destroy = mh_destroy;
+  mproc.match   = mh_match;
+  fc_register_match ("hashed", mproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
diff --git a/src/match_regex.c b/src/match_regex.c
new file mode 100644 (file)
index 0000000..4fa6ce7
--- /dev/null
@@ -0,0 +1,318 @@
+/**
+ * collectd - src/match_regex.c
+ * Copyright (C) 2008       Sebastian Harl
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+/*
+ * This module allows to filter and rewrite value lists based on
+ * Perl-compatible regular expressions.
+ */
+
+#include "collectd.h"
+#include "filter_chain.h"
+
+#include <sys/types.h>
+#include <regex.h>
+
+#define log_err(...) ERROR ("`regex' match: " __VA_ARGS__)
+#define log_warn(...) WARNING ("`regex' match: " __VA_ARGS__)
+
+/*
+ * private data types
+ */
+
+struct mr_regex_s;
+typedef struct mr_regex_s mr_regex_t;
+struct mr_regex_s
+{
+       regex_t re;
+       char *re_str;
+
+       mr_regex_t *next;
+};
+
+struct mr_match_s;
+typedef struct mr_match_s mr_match_t;
+struct mr_match_s
+{
+       mr_regex_t *host;
+       mr_regex_t *plugin;
+       mr_regex_t *plugin_instance;
+       mr_regex_t *type;
+       mr_regex_t *type_instance;
+       _Bool invert;
+};
+
+/*
+ * internal helper functions
+ */
+static void mr_free_regex (mr_regex_t *r) /* {{{ */
+{
+       if (r == NULL)
+               return;
+
+       regfree (&r->re);
+       memset (&r->re, 0, sizeof (r->re));
+       free (r->re_str);
+
+       if (r->next != NULL)
+               mr_free_regex (r->next);
+} /* }}} void mr_free_regex */
+
+static void mr_free_match (mr_match_t *m) /* {{{ */
+{
+       if (m == NULL)
+               return;
+
+       mr_free_regex (m->host);
+       mr_free_regex (m->plugin);
+       mr_free_regex (m->plugin_instance);
+       mr_free_regex (m->type);
+       mr_free_regex (m->type_instance);
+
+       free (m);
+} /* }}} void mr_free_match */
+
+static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */
+               const char *string)
+{
+       mr_regex_t *re;
+
+       if (re_head == NULL)
+               return (FC_MATCH_MATCHES);
+
+       for (re = re_head; re != NULL; re = re->next)
+       {
+               int status;
+
+               status = regexec (&re->re, string,
+                               /* nmatch = */ 0, /* pmatch = */ NULL,
+                               /* eflags = */ 0);
+               if (status == 0)
+               {
+                       DEBUG ("regex match: Regular expression `%s' matches `%s'.",
+                                       re->re_str, string);
+               }
+               else
+               {
+                       DEBUG ("regex match: Regular expression `%s' does not match `%s'.",
+                                       re->re_str, string);
+                       return (FC_MATCH_NO_MATCH);
+               }
+
+       }
+
+       return (FC_MATCH_MATCHES);
+} /* }}} int mr_match_regexen */
+
+static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
+               oconfig_item_t *ci)
+{
+       mr_regex_t *re;
+       int status;
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+       {
+               log_warn ("`%s' needs exactly one string argument.", ci->key);
+               return (-1);
+       }
+
+       re = (mr_regex_t *) malloc (sizeof (*re));
+       if (re == NULL)
+       {
+               log_err ("mr_config_add_regex: malloc failed.");
+               return (-1);
+       }
+       memset (re, 0, sizeof (*re));
+       re->next = NULL;
+
+       re->re_str = strdup (ci->values[0].value.string);
+       if (re->re_str == NULL)
+       {
+               free (re);
+               log_err ("mr_config_add_regex: strdup failed.");
+               return (-1);
+       }
+
+       status = regcomp (&re->re, re->re_str, REG_EXTENDED | REG_NOSUB);
+       if (status != 0)
+       {
+               char errmsg[1024];
+               regerror (status, &re->re, errmsg, sizeof (errmsg));
+               errmsg[sizeof (errmsg) - 1] = 0;
+               log_err ("Compiling regex `%s' for `%s' failed: %s.", 
+                               re->re_str, ci->key, errmsg);
+               free (re->re_str);
+               free (re);
+               return (-1);
+       }
+
+       if (*re_head == NULL)
+       {
+               *re_head = re;
+       }
+       else
+       {
+               mr_regex_t *ptr;
+
+               ptr = *re_head;
+               while (ptr->next != NULL)
+                       ptr = ptr->next;
+
+               ptr->next = re;
+       }
+
+       return (0);
+} /* }}} int mr_config_add_regex */
+
+static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+       mr_match_t *m;
+       int status;
+       int i;
+
+       m = (mr_match_t *) malloc (sizeof (*m));
+       if (m == NULL)
+       {
+               log_err ("mr_create: malloc failed.");
+               return (-ENOMEM);
+       }
+       memset (m, 0, sizeof (*m));
+       
+       m->invert = 0;
+
+       status = 0;
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if ((strcasecmp ("Host", child->key) == 0)
+                               || (strcasecmp ("Hostname", child->key) == 0))
+                       status = mr_config_add_regex (&m->host, child);
+               else if (strcasecmp ("Plugin", child->key) == 0)
+                       status = mr_config_add_regex (&m->plugin, child);
+               else if (strcasecmp ("PluginInstance", child->key) == 0)
+                       status = mr_config_add_regex (&m->plugin_instance, child);
+               else if (strcasecmp ("Type", child->key) == 0)
+                       status = mr_config_add_regex (&m->type, child);
+               else if (strcasecmp ("TypeInstance", child->key) == 0)
+                       status = mr_config_add_regex (&m->type_instance, child);
+               else if (strcasecmp ("Invert", child->key) == 0)
+                       status = cf_util_get_boolean(child, &m->invert);
+               else
+               {
+                       log_err ("The `%s' configuration option is not understood and "
+                                       "will be ignored.", child->key);
+                       status = 0;
+               }
+
+               if (status != 0)
+                       break;
+       }
+
+       /* Additional sanity-checking */
+       while (status == 0)
+       {
+               if ((m->host == NULL)
+                               && (m->plugin == NULL)
+                               && (m->plugin_instance == NULL)
+                               && (m->type == NULL)
+                               && (m->type_instance == NULL))
+               {
+                       log_err ("No (valid) regular expressions have been configured. "
+                                       "This match will be ignored.");
+                       status = -1;
+               }
+
+               break;
+       }
+
+       if (status != 0)
+       {
+               mr_free_match (m);
+               return (status);
+       }
+
+       *user_data = m;
+       return (0);
+} /* }}} int mr_create */
+
+static int mr_destroy (void **user_data) /* {{{ */
+{
+       if ((user_data != NULL) && (*user_data != NULL))
+               mr_free_match (*user_data);
+       return (0);
+} /* }}} int mr_destroy */
+
+static int mr_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+               const value_list_t *vl,
+               notification_meta_t __attribute__((unused)) **meta,
+               void **user_data)
+{
+       mr_match_t *m;
+       int match_value = FC_MATCH_MATCHES;
+       int nomatch_value = FC_MATCH_NO_MATCH;
+
+       if ((user_data == NULL) || (*user_data == NULL))
+               return (-1);
+
+       m = *user_data;
+
+       if (m->invert)
+       {
+               match_value = FC_MATCH_NO_MATCH;
+               nomatch_value = FC_MATCH_MATCHES;
+       }
+
+       if (mr_match_regexen (m->host, vl->host) == FC_MATCH_NO_MATCH)
+               return (nomatch_value);
+       if (mr_match_regexen (m->plugin, vl->plugin) == FC_MATCH_NO_MATCH)
+               return (nomatch_value);
+       if (mr_match_regexen (m->plugin_instance,
+                               vl->plugin_instance) == FC_MATCH_NO_MATCH)
+               return (nomatch_value);
+       if (mr_match_regexen (m->type, vl->type) == FC_MATCH_NO_MATCH)
+               return (nomatch_value);
+       if (mr_match_regexen (m->type_instance,
+                               vl->type_instance) == FC_MATCH_NO_MATCH)
+               return (nomatch_value);
+
+       return (match_value);
+} /* }}} int mr_match */
+
+void module_register (void)
+{
+       match_proc_t mproc;
+
+       memset (&mproc, 0, sizeof (mproc));
+       mproc.create  = mr_create;
+       mproc.destroy = mr_destroy;
+       mproc.match   = mr_match;
+       fc_register_match ("regex", mproc);
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab fdm=marker : */
+
diff --git a/src/match_timediff.c b/src/match_timediff.c
new file mode 100644 (file)
index 0000000..996201a
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ * collectd - src/match_timediff.c
+ * Copyright (C) 2008,2009  Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_cache.h"
+#include "filter_chain.h"
+
+#define SATISFY_ALL 0
+#define SATISFY_ANY 1
+
+/*
+ * private data types
+ */
+struct mt_match_s;
+typedef struct mt_match_s mt_match_t;
+struct mt_match_s
+{
+  cdtime_t future;
+  cdtime_t past;
+};
+
+/*
+ * internal helper functions
+ */
+static int mt_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  mt_match_t *m;
+  int status;
+  int i;
+
+  m = (mt_match_t *) malloc (sizeof (*m));
+  if (m == NULL)
+  {
+    ERROR ("mt_create: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (m, 0, sizeof (*m));
+
+  m->future = 0;
+  m->past = 0;
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Future", child->key) == 0)
+      status = cf_util_get_cdtime (child, &m->future);
+    else if (strcasecmp ("Past", child->key) == 0)
+      status = cf_util_get_cdtime (child, &m->past);
+    else
+    {
+      ERROR ("timediff match: The `%s' configuration option is not "
+          "understood and will be ignored.", child->key);
+      status = 0;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Additional sanity-checking */
+  while (status == 0)
+  {
+    if ((m->future == 0) && (m->past == 0))
+    {
+      ERROR ("timediff match: Either `Future' or `Past' must be configured. "
+          "This match will be ignored.");
+      status = -1;
+    }
+
+    break;
+  }
+
+  if (status != 0)
+  {
+    free (m);
+    return (status);
+  }
+
+  *user_data = m;
+  return (0);
+} /* }}} int mt_create */
+
+static int mt_destroy (void **user_data) /* {{{ */
+{
+  if (user_data != NULL)
+  {
+    sfree (*user_data);
+  }
+
+  return (0);
+} /* }}} int mt_destroy */
+
+static int mt_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */
+    const value_list_t *vl,
+    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+  mt_match_t *m;
+  cdtime_t now;
+
+  if ((user_data == NULL) || (*user_data == NULL))
+    return (-1);
+
+  m = *user_data;
+  now = cdtime ();
+
+  if (m->future != 0)
+  {
+    if (vl->time >= (now + m->future))
+      return (FC_MATCH_MATCHES);
+  }
+
+  if (m->past != 0)
+  {
+    if (vl->time <= (now - m->past))
+      return (FC_MATCH_MATCHES);
+  }
+
+  return (FC_MATCH_NO_MATCH);
+} /* }}} int mt_match */
+
+void module_register (void)
+{
+  match_proc_t mproc;
+
+  memset (&mproc, 0, sizeof (mproc));
+  mproc.create  = mt_create;
+  mproc.destroy = mt_destroy;
+  mproc.match   = mt_match;
+  fc_register_match ("timediff", mproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
diff --git a/src/match_value.c b/src/match_value.c
new file mode 100644 (file)
index 0000000..4d49984
--- /dev/null
@@ -0,0 +1,363 @@
+/**
+ * collectd - src/match_value.c
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+/*
+ * This module allows to filter and rewrite value lists based on
+ * Perl-compatible regular expressions.
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_cache.h"
+#include "filter_chain.h"
+
+#define SATISFY_ALL 0
+#define SATISFY_ANY 1
+
+/*
+ * private data types
+ */
+struct mv_match_s;
+typedef struct mv_match_s mv_match_t;
+struct mv_match_s
+{
+  gauge_t min;
+  gauge_t max;
+  int invert;
+  int satisfy;
+
+  char **data_sources;
+  size_t data_sources_num;
+};
+
+/*
+ * internal helper functions
+ */
+static void mv_free_match (mv_match_t *m) /* {{{ */
+{
+  int i;
+  
+  if (m == NULL)
+    return;
+
+  if (m->data_sources != NULL)
+  {
+    for (i = 0; i < m->data_sources_num; ++i)
+      free(m->data_sources[i]);
+    free(m->data_sources);
+  }
+  
+  free (m);
+} /* }}} void mv_free_match */
+
+static int mv_config_add_satisfy (mv_match_t *m, /* {{{ */
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("`value' match: `%s' needs exactly one string argument.",
+        ci->key);
+    return (-1);
+  }
+
+  if (strcasecmp ("All", ci->values[0].value.string) == 0)
+    m->satisfy = SATISFY_ALL;
+  else if (strcasecmp ("Any", ci->values[0].value.string) == 0)
+    m->satisfy = SATISFY_ANY;
+  else
+  {
+    ERROR ("`value' match: Passing `%s' to the `%s' option is invalid. "
+        "The argument must either be `All' or `Any'.",
+        ci->values[0].value.string, ci->key);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int mv_config_add_satisfy */
+
+static int mv_config_add_data_source (mv_match_t *m, /* {{{ */
+    oconfig_item_t *ci)
+{
+  size_t new_data_sources_num;
+  char **temp;
+  int i;
+
+  /* Check number of arbuments. */
+  if (ci->values_num < 1)
+  {
+    ERROR ("`value' match: `%s' needs at least one argument.",
+        ci->key);
+    return (-1);
+  }
+
+  /* Check type of arguments */
+  for (i = 0; i < ci->values_num; i++)
+  {
+    if (ci->values[i].type == OCONFIG_TYPE_STRING)
+      continue;
+
+    ERROR ("`value' match: `%s' accepts only string arguments "
+        "(argument %i is a %s).",
+        ci->key, i + 1,
+        (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
+        ? "truth value" : "number");
+    return (-1);
+  }
+
+  /* Allocate space for the char pointers */
+  new_data_sources_num = m->data_sources_num + ((size_t) ci->values_num);
+  temp = (char **) realloc (m->data_sources,
+      new_data_sources_num * sizeof (char *));
+  if (temp == NULL)
+  {
+    ERROR ("`value' match: realloc failed.");
+    return (-1);
+  }
+  m->data_sources = temp;
+
+  /* Copy the strings, allocating memory as needed. */
+  for (i = 0; i < ci->values_num; i++)
+  {
+    size_t j;
+
+    /* If we get here, there better be memory for us to write to. */
+    assert (m->data_sources_num < new_data_sources_num);
+
+    j = m->data_sources_num;
+    m->data_sources[j] = sstrdup (ci->values[i].value.string);
+    if (m->data_sources[j] == NULL)
+    {
+      ERROR ("`value' match: sstrdup failed.");
+      continue;
+    }
+    m->data_sources_num++;
+  }
+
+  return (0);
+} /* }}} int mv_config_add_data_source */
+
+static int mv_config_add_gauge (gauge_t *ret_value, /* {{{ */
+    oconfig_item_t *ci)
+{
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    ERROR ("`value' match: `%s' needs exactly one numeric argument.",
+        ci->key);
+    return (-1);
+  }
+
+  *ret_value = ci->values[0].value.number;
+
+  return (0);
+} /* }}} int mv_config_add_gauge */
+
+static int mv_config_add_boolean (int *ret_value, /* {{{ */
+    oconfig_item_t *ci)
+{
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+  {
+    ERROR ("`value' match: `%s' needs exactly one boolean argument.",
+        ci->key);
+    return (-1);
+  }
+
+  if (ci->values[0].value.boolean)
+    *ret_value = 1;
+  else
+    *ret_value = 0;
+
+  return (0);
+} /* }}} int mv_config_add_boolean */
+
+static int mv_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  mv_match_t *m;
+  int status;
+  int i;
+
+  m = (mv_match_t *) malloc (sizeof (*m));
+  if (m == NULL)
+  {
+    ERROR ("mv_create: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (m, 0, sizeof (*m));
+
+  m->min = NAN;
+  m->max = NAN;
+  m->invert = 0;
+  m->satisfy = SATISFY_ALL;
+  m->data_sources = NULL;
+  m->data_sources_num = 0;
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Min", child->key) == 0)
+      status = mv_config_add_gauge (&m->min, child);
+    else if (strcasecmp ("Max", child->key) == 0)
+      status = mv_config_add_gauge (&m->max, child);
+    else if (strcasecmp ("Invert", child->key) == 0)
+      status = mv_config_add_boolean (&m->invert, child);
+    else if (strcasecmp ("Satisfy", child->key) == 0)
+      status = mv_config_add_satisfy (m, child);
+    else if (strcasecmp ("DataSource", child->key) == 0)
+      status = mv_config_add_data_source (m, child);
+    else
+    {
+      ERROR ("`value' match: The `%s' configuration option is not "
+          "understood and will be ignored.", child->key);
+      status = 0;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Additional sanity-checking */
+  while (status == 0)
+  {
+    if (isnan (m->min) && isnan (m->max))
+    {
+      ERROR ("`value' match: Neither minimum nor maximum are defined. "
+          "This match will be ignored.");
+      status = -1;
+    }
+
+    break;
+  }
+
+  if (status != 0)
+  {
+    mv_free_match (m);
+    return (status);
+  }
+
+  *user_data = m;
+  return (0);
+} /* }}} int mv_create */
+
+static int mv_destroy (void **user_data) /* {{{ */
+{
+  if ((user_data != NULL) && (*user_data != NULL))
+    mv_free_match (*user_data);
+  return (0);
+} /* }}} int mv_destroy */
+
+static int mv_match (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+  mv_match_t *m;
+  gauge_t *values;
+  int status;
+  int i;
+
+  if ((user_data == NULL) || (*user_data == NULL))
+    return (-1);
+
+  m = *user_data;
+
+  values = uc_get_rate (ds, vl);
+  if (values == NULL)
+  {
+    ERROR ("`value' match: Retrieving the current rate from the cache "
+        "failed.");
+    return (-1);
+  }
+
+  status = FC_MATCH_NO_MATCH;
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    int value_matches = 0;
+
+    /* Check if this data source is relevant. */
+    if (m->data_sources != NULL)
+    {
+      size_t j;
+
+      for (j = 0; j < m->data_sources_num; j++)
+        if (strcasecmp (ds->ds[i].name, m->data_sources[j]) == 0)
+          break;
+
+      /* No match, ignore this data source. */
+      if (j >=  m->data_sources_num)
+        continue;
+    }
+
+    DEBUG ("`value' match: current = %g; min = %g; max = %g; invert = %s;",
+        values[i], m->min, m->max,
+        m->invert ? "true" : "false");
+
+    if ((!isnan (m->min) && (values[i] < m->min))
+        || (!isnan (m->max) && (values[i] > m->max)))
+      value_matches = 0;
+    else
+      value_matches = 1;
+
+    if (m->invert)
+    {
+      if (value_matches)
+        value_matches = 0;
+      else
+        value_matches = 1;
+    }
+
+    if (value_matches != 0)
+    {
+      status = FC_MATCH_MATCHES;
+      if (m->satisfy == SATISFY_ANY)
+        break;
+    }
+    else if (value_matches == 0)
+    {
+      status = FC_MATCH_NO_MATCH;
+      if (m->satisfy == SATISFY_ALL)
+        break;
+    }
+  } /* for (i = 0; i < ds->ds_num; i++) */
+
+  free (values);
+  return (status);
+} /* }}} int mv_match */
+
+void module_register (void)
+{
+  match_proc_t mproc;
+
+  memset (&mproc, 0, sizeof (mproc));
+  mproc.create  = mv_create;
+  mproc.destroy = mv_destroy;
+  mproc.match   = mv_match;
+  fc_register_match ("value", mproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
+
diff --git a/src/mbmon.c b/src/mbmon.c
new file mode 100644 (file)
index 0000000..d23062d
--- /dev/null
@@ -0,0 +1,314 @@
+/**
+ * collectd - src/mbmon.c
+ * Copyright (C) 2006       Flavio Stanchina
+ * Copyright (C) 2006-2007  Florian octo Forster
+ * Based on the hddtemp plugin.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Flavio Stanchina <flavio at stanchina.net>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#define MBMON_DEF_HOST "127.0.0.1"
+#define MBMON_DEF_PORT "411" /* the default for Debian */
+
+static const char *config_keys[] =
+{
+       "Host",
+       "Port",
+       NULL
+};
+static int config_keys_num = 2;
+
+static char *mbmon_host = NULL;
+static char *mbmon_port = NULL;
+
+/*
+ * NAME
+ *  mbmon_query_daemon
+ *
+ * DESCRIPTION
+ * Connect to the mbmon daemon and receive data.
+ *
+ * ARGUMENTS:
+ *  `buffer'            The buffer where we put the received ascii string.
+ *  `buffer_size'       Size of the buffer
+ *
+ * RETURN VALUE:
+ *   >= 0 if ok, < 0 otherwise.
+ *
+ * NOTES:
+ *  Example of possible strings, as received from daemon:
+ *    TEMP0 : 27.0
+ *    TEMP1 : 31.0
+ *    TEMP2 : 29.5
+ *    FAN0  : 4411
+ *    FAN1  : 4470
+ *    FAN2  : 4963
+ *    VC0   :  +1.68
+ *    VC1   :  +1.73
+ *
+ * FIXME:
+ *  we need to create a new socket each time. Is there another way?
+ *  Hm, maybe we can re-use the `sockaddr' structure? -octo
+ */
+static int mbmon_query_daemon (char *buffer, int buffer_size)
+{
+       int fd;
+       ssize_t status;
+       int buffer_fill;
+
+       const char *host;
+       const char *port;
+
+       struct addrinfo  ai_hints;
+       struct addrinfo *ai_list, *ai_ptr;
+       int              ai_return;
+
+       memset (&ai_hints, '\0', sizeof (ai_hints));
+       ai_hints.ai_flags    = 0;
+#ifdef AI_ADDRCONFIG
+       ai_hints.ai_flags   |= AI_ADDRCONFIG;
+#endif
+       ai_hints.ai_family   = PF_UNSPEC;
+       ai_hints.ai_socktype = SOCK_STREAM;
+       ai_hints.ai_protocol = IPPROTO_TCP;
+
+       host = mbmon_host;
+       if (host == NULL)
+               host = MBMON_DEF_HOST;
+
+       port = mbmon_port;
+       if (port == NULL)
+               port = MBMON_DEF_PORT;
+
+       if ((ai_return = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
+       {
+               char errbuf[1024];
+               ERROR ("mbmon: getaddrinfo (%s, %s): %s",
+                               host, port,
+                               (ai_return == EAI_SYSTEM)
+                               ? sstrerror (errno, errbuf, sizeof (errbuf))
+                               : gai_strerror (ai_return));
+               return (-1);
+       }
+
+       fd = -1;
+       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               /* create our socket descriptor */
+               if ((fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol)) < 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("mbmon: socket: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       continue;
+               }
+
+               /* connect to the mbmon daemon */
+               if (connect (fd, (struct sockaddr *) ai_ptr->ai_addr, ai_ptr->ai_addrlen))
+               {
+                       char errbuf[1024];
+                       INFO ("mbmon: connect (%s, %s): %s", host, port,
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       close (fd);
+                       fd = -1;
+                       continue;
+               }
+
+               /* A socket could be opened and connecting succeeded. We're
+                * done. */
+               break;
+       }
+
+       freeaddrinfo (ai_list);
+
+       if (fd < 0)
+       {
+               ERROR ("mbmon: Could not connect to daemon.");
+               return (-1);
+       }
+
+       /* receive data from the mbmon daemon */
+       memset (buffer, '\0', buffer_size);
+
+       buffer_fill = 0;
+       while ((status = read (fd, buffer + buffer_fill, buffer_size - buffer_fill)) != 0)
+       {
+               if (status == -1)
+               {
+                       char errbuf[1024];
+
+                       if ((errno == EAGAIN) || (errno == EINTR))
+                               continue;
+
+                       ERROR ("mbmon: Error reading from socket: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       close (fd);
+                       return (-1);
+               }
+               buffer_fill += status;
+
+               if (buffer_fill >= buffer_size)
+                       break;
+       }
+
+       if (buffer_fill >= buffer_size)
+       {
+               buffer[buffer_size - 1] = '\0';
+               WARNING ("mbmon: Message from mbmon has been truncated.");
+       }
+       else if (buffer_fill == 0)
+       {
+               WARNING ("mbmon: Peer has unexpectedly shut down the socket. "
+                               "Buffer: `%s'", buffer);
+               close (fd);
+               return (-1);
+       }
+
+       close (fd);
+       return (0);
+}
+
+static int mbmon_config (const char *key, const char *value)
+{
+       if (strcasecmp (key, "host") == 0)
+       {
+               if (mbmon_host != NULL)
+                       free (mbmon_host);
+               mbmon_host = strdup (value);
+       }
+       else if (strcasecmp (key, "port") == 0)
+       {
+               if (mbmon_port != NULL)
+                       free (mbmon_port);
+               mbmon_port = strdup (value);
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+}
+
+static void mbmon_submit (const char *type, const char *type_instance,
+               double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "mbmon", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void mbmon_submit */
+
+/* Trim trailing whitespace from a string. */
+static void trim_spaces (char *s)
+{
+       size_t l;
+
+       for (l = strlen (s) - 1; (l > 0) && isspace ((int) s[l]); l--)
+               s[l] = '\0';
+}
+
+static int mbmon_read (void)
+{
+       char buf[1024];
+       char *s, *t;
+
+       /* get data from daemon */
+       if (mbmon_query_daemon (buf, sizeof (buf)) < 0)
+               return (-1);
+
+       s = buf;
+       while ((t = strchr (s, ':')) != NULL)
+       {
+               double value;
+               char *nextc;
+
+               char *type;
+               char *inst;
+
+               *t++ = '\0';
+               trim_spaces (s);
+
+               value = strtod (t, &nextc);
+               if ((*nextc != '\n') && (*nextc != '\0'))
+               {
+                       ERROR ("mbmon: value for `%s' contains invalid characters: `%s'", s, t);
+                       break;
+               }
+
+               if (strncmp (s, "TEMP", 4) == 0)
+               {
+                       inst = s + 4;
+                       type = "temperature";
+               }
+               else if (strncmp (s, "FAN", 3) == 0)
+               {
+                       inst = s + 3;
+                       type = "fanspeed";
+               }
+               else if (strncmp (s, "V", 1) == 0)
+               {
+                       inst = s + 1;
+                       type = "voltage";
+               }
+               else
+               {
+                       continue;
+               }
+
+               mbmon_submit (type, inst, value);
+
+               if (*nextc == '\0')
+                       break;
+
+               s = nextc + 1;
+       }
+
+       return (0);
+} /* void mbmon_read */
+
+/* module_register
+   Register collectd plugin. */
+void module_register (void)
+{
+       plugin_register_config ("mbmon", mbmon_config, config_keys, config_keys_num);
+       plugin_register_read ("mbmon", mbmon_read);
+} /* void module_register */
diff --git a/src/md.c b/src/md.c
new file mode 100644 (file)
index 0000000..3725f9a
--- /dev/null
+++ b/src/md.c
@@ -0,0 +1,218 @@
+/**
+ * collectd - src/md.c
+ * Copyright (C) 2010,2011  Michael Hanselmann
+ *
+ * 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:
+ *   Michael Hanselmann
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#include <sys/ioctl.h>
+
+#include <linux/major.h>
+#include <linux/raid/md_u.h>
+
+#define PROC_DISKSTATS "/proc/diskstats"
+#define DEV_DIR "/dev"
+
+static const char *config_keys[] =
+{
+  "Device",
+  "IgnoreSelected"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+static int md_config (const char *key, const char *value)
+{
+  if (ignorelist == NULL)
+    ignorelist = ignorelist_create (/* invert = */ 1);
+  if (ignorelist == NULL)
+    return (1);
+
+  if (strcasecmp (key, "Device") == 0)
+  {
+    ignorelist_add (ignorelist, value);
+  }
+  else if (strcasecmp (key, "IgnoreSelected") == 0)
+  {
+    ignorelist_set_invert (ignorelist, IS_TRUE (value) ? 0 : 1);
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+}
+
+static void md_submit (const int minor, const char *type_instance,
+    gauge_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "md", sizeof (vl.plugin));
+  ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+      "%i", minor);
+  sstrncpy (vl.type, "md_disks", sizeof (vl.type));
+  sstrncpy (vl.type_instance, type_instance,
+      sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void md_submit */
+
+static void md_process (const int minor, const char *path)
+{
+  char errbuf[1024];
+  int fd;
+  struct stat st;
+  mdu_array_info_t array;
+  gauge_t disks_missing;
+
+  fd = open (path, O_RDONLY);
+  if (fd < 0)
+  {
+    WARNING ("md: open(%s): %s", path,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return;
+  }
+
+  if (fstat (fd, &st) < 0)
+  {
+    WARNING ("md: Unable to fstat file descriptor for %s: %s", path,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    close (fd);
+    return;
+  }
+
+  if (! S_ISBLK (st.st_mode))
+  {
+    WARNING ("md: %s is no block device", path);
+    close (fd);
+    return;
+  }
+
+  if (st.st_rdev != makedev (MD_MAJOR, minor))
+  {
+    WARNING ("md: Major/minor of %s are %i:%i, should be %i:%i",
+        path, (int)major(st.st_rdev), (int)minor(st.st_rdev),
+        (int)MD_MAJOR, minor);
+    close (fd);
+    return;
+  }
+
+  /* Retrieve md information */
+  if (ioctl (fd, GET_ARRAY_INFO, &array) < 0) {
+    WARNING ("md: Unable to retrieve array info from %s: %s", path,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    close (fd);
+    return;
+  }
+
+  close (fd);
+
+  /*
+   * The mdu_array_info_t structure contains numbers of disks in the array.
+   * However, disks are accounted for more than once:
+   *
+   * active:  Number of active (in sync) disks.
+   * spare:   Number of stand-by disks.
+   * working: Number of working disks. (active + sync)
+   * failed:  Number of failed disks.
+   * nr:      Number of physically present disks. (working + failed)
+   * raid:    Number of disks in the RAID. This may be larger than "nr" if
+   *          disks are missing and smaller than "nr" when spare disks are
+   *          around.
+   */
+  md_submit (minor, "active",  (gauge_t) array.active_disks);
+  md_submit (minor, "failed",  (gauge_t) array.failed_disks);
+  md_submit (minor, "spare",   (gauge_t) array.spare_disks);
+
+  disks_missing = 0.0;
+  if (array.raid_disks > array.nr_disks)
+    disks_missing = (gauge_t) (array.raid_disks - array.nr_disks);
+  md_submit (minor, "missing", disks_missing);
+} /* void md_process */
+
+static int md_read (void)
+{
+  FILE *fh;
+  char buffer[1024];
+
+  fh = fopen (PROC_DISKSTATS, "r");
+  if (fh == NULL) {
+    char errbuf[1024];
+    WARNING ("md: Unable to open %s: %s",
+        PROC_DISKSTATS ,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  /* Iterate md devices */
+  while (fgets (buffer, sizeof (buffer), fh) != NULL)
+  {
+    char path[PATH_MAX];
+    char *fields[4];
+    char *name;
+    int major, minor;
+
+    /* Extract interesting fields */
+    if (strsplit (buffer, fields, STATIC_ARRAY_SIZE(fields)) < 3)
+      continue;
+
+    major = atoi (fields[0]);
+
+    if (major != MD_MAJOR)
+      continue;
+
+    minor = atoi (fields[1]);
+    name = fields[2];
+
+    if (ignorelist_match (ignorelist, name))
+      continue;
+
+    /* FIXME: Don't hardcode path. Walk /dev collecting major,
+     * minor and name, then use lookup table to find device.
+     * Alternatively create a temporary device file with correct
+     * major/minor, but that again can be tricky if the filesystem
+     * with the device file is mounted using the "nodev" option.
+     */
+    ssnprintf (path, sizeof (path), "%s/%s", DEV_DIR, name);
+
+    md_process (minor, path);
+  }
+
+  fclose (fh);
+
+  return (0);
+} /* int md_read */
+
+void module_register (void)
+{
+  plugin_register_config ("md", md_config, config_keys, config_keys_num);
+  plugin_register_read ("md", md_read);
+} /* void module_register */
diff --git a/src/memcachec.c b/src/memcachec.c
new file mode 100644 (file)
index 0000000..37f1894
--- /dev/null
@@ -0,0 +1,537 @@
+/**
+ * collectd - src/memcachec.c
+ * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2006-2009  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Doug MacEachern <Doug.MacEachern at hyperic.com>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_match.h"
+
+#include <libmemcached/memcached.h>
+
+/*
+ * Data types
+ */
+struct web_match_s;
+typedef struct web_match_s web_match_t;
+struct web_match_s /* {{{ */
+{
+  char *regex;
+  char *exclude_regex;
+  int dstype;
+  char *type;
+  char *instance;
+
+  cu_match_t *match;
+
+  web_match_t *next;
+}; /* }}} */
+
+struct web_page_s;
+typedef struct web_page_s web_page_t;
+struct web_page_s /* {{{ */
+{
+  char *instance;
+
+  char *server;
+  char *key;
+
+  memcached_st *memc;
+  char *buffer;
+
+  web_match_t *matches;
+
+  web_page_t *next;
+}; /* }}} */
+
+/*
+ * Global variables;
+ */
+static web_page_t *pages_g = NULL;
+
+/*
+ * Private functions
+ */
+static void cmc_web_match_free (web_match_t *wm) /* {{{ */
+{
+  if (wm == NULL)
+    return;
+
+  sfree (wm->regex);
+  sfree (wm->type);
+  sfree (wm->instance);
+  match_destroy (wm->match);
+  cmc_web_match_free (wm->next);
+  sfree (wm);
+} /* }}} void cmc_web_match_free */
+
+static void cmc_web_page_free (web_page_t *wp) /* {{{ */
+{
+  if (wp == NULL)
+    return;
+
+  if (wp->memc != NULL)
+    memcached_free(wp->memc);
+  wp->memc = NULL;
+
+  sfree (wp->instance);
+  sfree (wp->server);
+  sfree (wp->key);
+  sfree (wp->buffer);
+
+  cmc_web_match_free (wp->matches);
+  cmc_web_page_free (wp->next);
+  sfree (wp);
+} /* }}} void cmc_web_page_free */
+
+static int cmc_page_init_memc (web_page_t *wp) /* {{{ */
+{
+  memcached_server_st *server;
+
+  wp->memc = memcached_create(NULL);
+  if (wp->memc == NULL)
+  {
+    ERROR ("memcachec plugin: memcached_create failed.");
+    return (-1);
+  }
+
+  server = memcached_servers_parse (wp->server);
+  memcached_server_push (wp->memc, server);
+  memcached_server_list_free (server);
+
+  return (0);
+} /* }}} int cmc_page_init_memc */
+
+static int cmc_config_add_string (const char *name, char **dest, /* {{{ */
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("memcachec plugin: `%s' needs exactly one string argument.", name);
+    return (-1);
+  }
+
+  sfree (*dest);
+  *dest = strdup (ci->values[0].value.string);
+  if (*dest == NULL)
+    return (-1);
+
+  return (0);
+} /* }}} int cmc_config_add_string */
+
+static int cmc_config_add_match_dstype (int *dstype_ret, /* {{{ */
+    oconfig_item_t *ci)
+{
+  int dstype;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("memcachec plugin: `DSType' needs exactly one string argument.");
+    return (-1);
+  }
+
+  if (strncasecmp ("Gauge", ci->values[0].value.string,
+        strlen ("Gauge")) == 0)
+  {
+    dstype = UTILS_MATCH_DS_TYPE_GAUGE;
+    if (strcasecmp ("GaugeAverage", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_AVERAGE;
+    else if (strcasecmp ("GaugeMin", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_MIN;
+    else if (strcasecmp ("GaugeMax", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_MAX;
+    else if (strcasecmp ("GaugeLast", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_GAUGE_LAST;
+    else
+      dstype = 0;
+  }
+  else if (strncasecmp ("Counter", ci->values[0].value.string,
+        strlen ("Counter")) == 0)
+  {
+    dstype = UTILS_MATCH_DS_TYPE_COUNTER;
+    if (strcasecmp ("CounterSet", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_COUNTER_SET;
+    else if (strcasecmp ("CounterAdd", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_COUNTER_ADD;
+    else if (strcasecmp ("CounterInc", ci->values[0].value.string) == 0)
+      dstype |= UTILS_MATCH_CF_COUNTER_INC;
+    else
+      dstype = 0;
+  }
+  else
+  {
+    dstype = 0;
+  }
+
+  if (dstype == 0)
+  {
+    WARNING ("memcachec plugin: `%s' is not a valid argument to `DSType'.",
+       ci->values[0].value.string);
+    return (-1);
+  }
+
+  *dstype_ret = dstype;
+  return (0);
+} /* }}} int cmc_config_add_match_dstype */
+
+static int cmc_config_add_match (web_page_t *page, /* {{{ */
+    oconfig_item_t *ci)
+{
+  web_match_t *match;
+  int status;
+  int i;
+
+  if (ci->values_num != 0)
+  {
+    WARNING ("memcachec plugin: Ignoring arguments for the `Match' block.");
+  }
+
+  match = (web_match_t *) malloc (sizeof (*match));
+  if (match == NULL)
+  {
+    ERROR ("memcachec plugin: malloc failed.");
+    return (-1);
+  }
+  memset (match, 0, sizeof (*match));
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Regex", child->key) == 0)
+      status = cmc_config_add_string ("Regex", &match->regex, child);
+    else if (strcasecmp ("ExcludeRegex", child->key) == 0)
+      status = cmc_config_add_string ("ExcludeRegex", &match->exclude_regex, child);
+    else if (strcasecmp ("DSType", child->key) == 0)
+      status = cmc_config_add_match_dstype (&match->dstype, child);
+    else if (strcasecmp ("Type", child->key) == 0)
+      status = cmc_config_add_string ("Type", &match->type, child);
+    else if (strcasecmp ("Instance", child->key) == 0)
+      status = cmc_config_add_string ("Instance", &match->instance, child);
+    else
+    {
+      WARNING ("memcachec plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  while (status == 0)
+  {
+    if (match->regex == NULL)
+    {
+      WARNING ("memcachec plugin: `Regex' missing in `Match' block.");
+      status = -1;
+    }
+
+    if (match->type == NULL)
+    {
+      WARNING ("memcachec plugin: `Type' missing in `Match' block.");
+      status = -1;
+    }
+
+    if (match->dstype == 0)
+    {
+      WARNING ("memcachec plugin: `DSType' missing in `Match' block.");
+      status = -1;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+    return (status);
+
+  match->match = match_create_simple (match->regex, match->exclude_regex,
+      match->dstype);
+  if (match->match == NULL)
+  {
+    ERROR ("memcachec plugin: tail_match_add_match_simple failed.");
+    cmc_web_match_free (match);
+    return (-1);
+  }
+  else
+  {
+    web_match_t *prev;
+
+    prev = page->matches;
+    while ((prev != NULL) && (prev->next != NULL))
+      prev = prev->next;
+
+    if (prev == NULL)
+      page->matches = match;
+    else
+      prev->next = match;
+  }
+
+  return (0);
+} /* }}} int cmc_config_add_match */
+
+static int cmc_config_add_page (oconfig_item_t *ci) /* {{{ */
+{
+  web_page_t *page;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("memcachec plugin: `Page' blocks need exactly one string argument.");
+    return (-1);
+  }
+
+  page = (web_page_t *) malloc (sizeof (*page));
+  if (page == NULL)
+  {
+    ERROR ("memcachec plugin: malloc failed.");
+    return (-1);
+  }
+  memset (page, 0, sizeof (*page));
+  page->server = NULL;
+  page->key = NULL;
+
+  page->instance = strdup (ci->values[0].value.string);
+  if (page->instance == NULL)
+  {
+    ERROR ("memcachec plugin: strdup failed.");
+    sfree (page);
+    return (-1);
+  }
+
+  /* Process all children */
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Server", child->key) == 0)
+      status = cmc_config_add_string ("Server", &page->server, child);
+    else if (strcasecmp ("Key", child->key) == 0)
+      status = cmc_config_add_string ("Key", &page->key, child);
+    else if (strcasecmp ("Match", child->key) == 0)
+      /* Be liberal with failing matches => don't set `status'. */
+      cmc_config_add_match (page, child);
+    else
+    {
+      WARNING ("memcachec plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  /* Additionial sanity checks and libmemcached initialization. */
+  while (status == 0)
+  {
+    if (page->server == NULL)
+    {
+      WARNING ("memcachec plugin: `Server' missing in `Page' block.");
+      status = -1;
+    }
+
+    if (page->key == NULL)
+    {
+      WARNING ("memcachec plugin: `Key' missing in `Page' block.");
+      status = -1;
+    }
+
+    if (page->matches == NULL)
+    {
+      assert (page->instance != NULL);
+      WARNING ("memcachec plugin: No (valid) `Match' block "
+          "within `Page' block `%s'.", page->instance);
+      status = -1;
+    }
+
+    if (status == 0)
+      status = cmc_page_init_memc (page);
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+  {
+    cmc_web_page_free (page);
+    return (status);
+  }
+
+  /* Add the new page to the linked list */
+  if (pages_g == NULL)
+    pages_g = page;
+  else
+  {
+    web_page_t *prev;
+
+    prev = pages_g;
+    while ((prev != NULL) && (prev->next != NULL))
+      prev = prev->next;
+    prev->next = page;
+  }
+
+  return (0);
+} /* }}} int cmc_config_add_page */
+
+static int cmc_config (oconfig_item_t *ci) /* {{{ */
+{
+  int success;
+  int errors;
+  int status;
+  int i;
+
+  success = 0;
+  errors = 0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Page", child->key) == 0)
+    {
+      status = cmc_config_add_page (child);
+      if (status == 0)
+        success++;
+      else
+        errors++;
+    }
+    else
+    {
+      WARNING ("memcachec plugin: Option `%s' not allowed here.", child->key);
+      errors++;
+    }
+  }
+
+  if ((success == 0) && (errors > 0))
+  {
+    ERROR ("memcachec plugin: All statements failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int cmc_config */
+
+static int cmc_init (void) /* {{{ */
+{
+  if (pages_g == NULL)
+  {
+    INFO ("memcachec plugin: No pages have been defined.");
+    return (-1);
+  }
+  return (0);
+} /* }}} int cmc_init */
+
+static void cmc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */
+    const cu_match_value_t *mv)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0] = mv->value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "memcachec", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, wp->instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, wm->type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, wm->instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* }}} void cmc_submit */
+
+static int cmc_read_page (web_page_t *wp) /* {{{ */
+{
+  web_match_t *wm;
+  memcached_return rc;
+  size_t string_length;
+  uint32_t flags;
+  int status;
+
+  if (wp->memc == NULL)
+    return (-1);
+
+  wp->buffer = memcached_get (wp->memc, wp->key, strlen (wp->key),
+                              &string_length, &flags, &rc);
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    ERROR ("memcachec plugin: memcached_get failed: %s",
+        memcached_strerror (wp->memc, rc));
+    return (-1);
+  }
+
+  for (wm = wp->matches; wm != NULL; wm = wm->next)
+  {
+    cu_match_value_t *mv;
+
+    status = match_apply (wm->match, wp->buffer);
+    if (status != 0)
+    {
+      WARNING ("memcachec plugin: match_apply failed.");
+      continue;
+    }
+
+    mv = match_get_user_data (wm->match);
+    if (mv == NULL)
+    {
+      WARNING ("memcachec plugin: match_get_user_data returned NULL.");
+      continue;
+    }
+
+    cmc_submit (wp, wm, mv);
+    match_value_reset (mv);
+  } /* for (wm = wp->matches; wm != NULL; wm = wm->next) */
+
+  sfree (wp->buffer);
+
+  return (0);
+} /* }}} int cmc_read_page */
+
+static int cmc_read (void) /* {{{ */
+{
+  web_page_t *wp;
+
+  for (wp = pages_g; wp != NULL; wp = wp->next)
+    cmc_read_page (wp);
+
+  return (0);
+} /* }}} int cmc_read */
+
+static int cmc_shutdown (void) /* {{{ */
+{
+  cmc_web_page_free (pages_g);
+  pages_g = NULL;
+
+  return (0);
+} /* }}} int cmc_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("memcachec", cmc_config);
+  plugin_register_init ("memcachec", cmc_init);
+  plugin_register_read ("memcachec", cmc_read);
+  plugin_register_shutdown ("memcachec", cmc_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/memcached.c b/src/memcached.c
new file mode 100644 (file)
index 0000000..e2ccfee
--- /dev/null
@@ -0,0 +1,710 @@
+/**
+ * collectd - src/memcached.c, based on src/hddtemp.c
+ * Copyright (C) 2007       Antony Dovgal
+ * Copyright (C) 2007-2012  Florian Forster
+ * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2009       Franck Lombardi
+ * Copyright (C) 2012       Nicolas Szalay
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Antony Dovgal <tony at daylessday dot org>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Doug MacEachern <dougm at hyperic.com>
+ *   Franck Lombardi
+ *   Nicolas Szalay
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#define MEMCACHED_DEF_HOST "127.0.0.1"
+#define MEMCACHED_DEF_PORT "11211"
+
+struct memcached_s
+{
+  char *name;
+  char *socket;
+  char *host;
+  char *port;
+};
+typedef struct memcached_s memcached_t;
+
+static _Bool memcached_have_instances = 0;
+
+static void memcached_free (memcached_t *st)
+{
+  if (st == NULL)
+    return;
+
+  sfree (st->name);
+  sfree (st->socket);
+  sfree (st->host);
+  sfree (st->port);
+}
+
+static int memcached_connect_unix (memcached_t *st)
+{
+  struct sockaddr_un serv_addr;
+  int fd;
+
+  memset (&serv_addr, 0, sizeof (serv_addr));
+  serv_addr.sun_family = AF_UNIX;
+  sstrncpy (serv_addr.sun_path, st->socket,
+      sizeof (serv_addr.sun_path));
+
+  /* create our socket descriptor */
+  fd = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (fd < 0)
+  {
+    char errbuf[1024];
+    ERROR ("memcached plugin: memcached_connect_unix: socket(2) failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  /* connect to the memcached daemon */
+  int status = connect (fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
+  if (status != 0)
+  {
+      shutdown (fd, SHUT_RDWR);
+      close (fd);
+      fd = -1;
+  }
+
+  return (fd);
+} /* int memcached_connect_unix */
+
+static int memcached_connect_inet (memcached_t *st)
+{
+  char *host;
+  char *port;
+
+  struct addrinfo  ai_hints;
+  struct addrinfo *ai_list, *ai_ptr;
+  int status;
+  int fd = -1;
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags    = 0;
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags   |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family   = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_STREAM;
+  ai_hints.ai_protocol = 0;
+
+  host = (st->host != NULL) ? st->host : MEMCACHED_DEF_HOST;
+  port = (st->port != NULL) ? st->port : MEMCACHED_DEF_PORT;
+
+  ai_list = NULL;
+  status = getaddrinfo (host, port, &ai_hints, &ai_list);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("memcached plugin: memcached_connect_inet: "
+        "getaddrinfo(%s,%s) failed: %s",
+        host, port,
+        (status == EAI_SYSTEM)
+        ? sstrerror (errno, errbuf, sizeof (errbuf))
+        : gai_strerror (status));
+    return (-1);
+  }
+
+  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    /* create our socket descriptor */
+    fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+    if (fd < 0)
+    {
+      char errbuf[1024];
+      WARNING ("memcached plugin: memcached_connect_inet: "
+          "socket(2) failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      continue;
+    }
+
+    /* connect to the memcached daemon */
+    status = (int) connect (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    if (status != 0)
+    {
+      shutdown (fd, SHUT_RDWR);
+      close (fd);
+      fd = -1;
+      continue;
+    }
+
+    /* A socket could be opened and connecting succeeded. We're done. */
+    break;
+  }
+
+  freeaddrinfo (ai_list);
+  return (fd);
+} /* int memcached_connect_inet */
+
+static int memcached_connect (memcached_t *st)
+{
+  if (st->socket != NULL)
+    return (memcached_connect_unix (st));
+  else
+    return (memcached_connect_inet (st));
+}
+
+static int memcached_query_daemon (char *buffer, size_t buffer_size, memcached_t *st)
+{
+  int fd = -1;
+  int status;
+  size_t buffer_fill;
+
+  fd = memcached_connect (st);
+  if (fd < 0) {
+    ERROR ("memcached plugin: Instance \"%s\" could not connect to daemon.",
+        st->name);
+    return -1;
+  }
+
+  status = (int) swrite (fd, "stats\r\n", strlen ("stats\r\n"));
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("memcached plugin: write(2) failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    shutdown(fd, SHUT_RDWR);
+    close (fd);
+    return (-1);
+  }
+
+  /* receive data from the memcached daemon */
+  memset (buffer, 0, buffer_size);
+
+  buffer_fill = 0;
+  while ((status = (int) recv (fd, buffer + buffer_fill,
+          buffer_size - buffer_fill, /* flags = */ 0)) != 0)
+  {
+    char const end_token[5] = {'E', 'N', 'D', '\r', '\n'};
+    if (status < 0)
+    {
+      char errbuf[1024];
+
+      if ((errno == EAGAIN) || (errno == EINTR))
+          continue;
+
+      ERROR ("memcached: Error reading from socket: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      shutdown(fd, SHUT_RDWR);
+      close (fd);
+      return (-1);
+    }
+
+    buffer_fill += (size_t) status;
+    if (buffer_fill > buffer_size)
+    {
+      buffer_fill = buffer_size;
+      WARNING ("memcached plugin: Message was truncated.");
+      break;
+    }
+
+    /* If buffer ends in end_token, we have all the data. */
+    if (memcmp (buffer + buffer_fill - sizeof (end_token),
+          end_token, sizeof (end_token)) == 0)
+      break;
+  } /* while (recv) */
+
+  status = 0;
+  if (buffer_fill == 0)
+  {
+    WARNING ("memcached plugin: No data returned by memcached.");
+    status = -1;
+  }
+
+  shutdown(fd, SHUT_RDWR);
+  close(fd);
+  return (status);
+} /* int memcached_query_daemon */
+
+static void memcached_init_vl (value_list_t *vl, memcached_t const *st)
+{
+  sstrncpy (vl->plugin, "memcached", sizeof (vl->plugin));
+  if (strcmp (st->name, "__legacy__") == 0) /* legacy mode */
+  {
+    sstrncpy (vl->host, hostname_g, sizeof (vl->host));
+  }
+  else
+  {
+    if (st->socket != NULL)
+      sstrncpy (vl->host, hostname_g, sizeof (vl->host));
+    else
+      sstrncpy (vl->host,
+          (st->host != NULL) ? st->host : MEMCACHED_DEF_HOST,
+          sizeof (vl->host));
+    sstrncpy (vl->plugin_instance, st->name, sizeof (vl->plugin_instance));
+  }
+}
+
+static void submit_derive (const char *type, const char *type_inst,
+    derive_t value, memcached_t *st)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  memcached_init_vl (&vl, st);
+
+  values[0].derive = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_inst != NULL)
+    sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+}
+
+static void submit_derive2 (const char *type, const char *type_inst,
+    derive_t value0, derive_t value1, memcached_t *st)
+{
+  value_t values[2];
+  value_list_t vl = VALUE_LIST_INIT;
+  memcached_init_vl (&vl, st);
+
+  values[0].derive = value0;
+  values[1].derive = value1;
+
+  vl.values = values;
+  vl.values_len = 2;
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_inst != NULL)
+    sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+}
+
+static void submit_gauge (const char *type, const char *type_inst,
+    gauge_t value, memcached_t *st)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  memcached_init_vl (&vl, st);
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_inst != NULL)
+    sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+}
+
+static void submit_gauge2 (const char *type, const char *type_inst,
+    gauge_t value0, gauge_t value1, memcached_t *st)
+{
+  value_t values[2];
+  value_list_t vl = VALUE_LIST_INIT;
+  memcached_init_vl (&vl, st);
+
+  values[0].gauge = value0;
+  values[1].gauge = value1;
+
+  vl.values = values;
+  vl.values_len = 2;
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_inst != NULL)
+    sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+}
+
+static int memcached_read (user_data_t *user_data)
+{
+  char buf[4096];
+  char *fields[3];
+  char *ptr;
+  char *line;
+  char *saveptr;
+  int fields_num;
+
+  gauge_t bytes_used = NAN;
+  gauge_t bytes_total = NAN;
+  gauge_t hits = NAN;
+  gauge_t gets = NAN;
+  gauge_t incr_hits = NAN;
+  derive_t incr = 0;
+  gauge_t decr_hits = NAN;
+  derive_t decr = 0;
+  derive_t rusage_user = 0;
+  derive_t rusage_syst = 0;
+  derive_t octets_rx = 0;
+  derive_t octets_tx = 0;
+
+  memcached_t *st;
+  st = user_data->data;
+
+  /* get data from daemon */
+  if (memcached_query_daemon (buf, sizeof (buf), st) < 0) {
+    return -1;
+  }
+
+#define FIELD_IS(cnst) \
+  (((sizeof(cnst) - 1) == name_len) && (strcmp (cnst, fields[1]) == 0))
+
+  ptr = buf;
+  saveptr = NULL;
+  while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
+  {
+    int name_len;
+
+    ptr = NULL;
+
+    fields_num = strsplit(line, fields, 3);
+    if (fields_num != 3)
+      continue;
+
+    name_len = strlen(fields[1]);
+    if (name_len == 0)
+      continue;
+
+    /*
+     * For an explanation on these fields please refer to
+     * <https://github.com/memcached/memcached/blob/master/doc/protocol.txt>
+     */
+
+    /*
+     * CPU time consumed by the memcached process
+     */
+    if (FIELD_IS ("rusage_user"))
+    {
+      rusage_user = atoll (fields[2]);
+    }
+    else if (FIELD_IS ("rusage_system"))
+    {
+      rusage_syst = atoll(fields[2]);
+    }
+
+    /*
+     * Number of threads of this instance
+     */
+    else if (FIELD_IS ("threads"))
+    {
+      submit_gauge2 ("ps_count", NULL, NAN, atof (fields[2]), st);
+    }
+
+    /*
+     * Number of items stored
+     */
+    else if (FIELD_IS ("curr_items"))
+    {
+      submit_gauge ("memcached_items", "current", atof (fields[2]), st);
+    }
+
+    /*
+     * Number of bytes used and available (total - used)
+     */
+    else if (FIELD_IS ("bytes"))
+    {
+      bytes_used = atof (fields[2]);
+    }
+    else if (FIELD_IS ("limit_maxbytes"))
+    {
+      bytes_total = atof(fields[2]);
+    }
+
+    /*
+     * Connections
+     */
+    else if (FIELD_IS ("curr_connections"))
+    {
+      submit_gauge ("memcached_connections", "current", atof (fields[2]), st);
+    }
+    else if (FIELD_IS ("listen_disabled_num"))
+    {
+      submit_derive ("memcached_connections", "listen_disabled", atof (fields[2]), st);
+    }
+
+    /*
+     * Commands
+     */
+    else if ((name_len > 4) && (strncmp (fields[1], "cmd_", 4) == 0))
+    {
+      const char *name = fields[1] + 4;
+      submit_derive ("memcached_command", name, atoll (fields[2]), st);
+      if (strcmp (name, "get") == 0)
+        gets = atof (fields[2]);
+    }
+
+    /*
+     * Increment/Decrement
+     */
+    else if (FIELD_IS("incr_misses"))
+    {
+      derive_t incr_count = atoll (fields[2]);
+      submit_derive ("memcached_ops", "incr_misses", incr_count, st);
+      incr += incr_count;
+    }
+    else if (FIELD_IS ("incr_hits"))
+    {
+      derive_t incr_count = atoll (fields[2]);
+      submit_derive ("memcached_ops", "incr_hits", incr_count, st);
+      incr_hits = atof (fields[2]);
+      incr += incr_count;
+    }
+    else if (FIELD_IS ("decr_misses"))
+    {
+      derive_t decr_count = atoll (fields[2]);
+      submit_derive ("memcached_ops", "decr_misses", decr_count, st);
+      decr += decr_count;
+    }
+    else if (FIELD_IS ("decr_hits"))
+    {
+      derive_t decr_count = atoll (fields[2]);
+      submit_derive ("memcached_ops", "decr_hits", decr_count, st);
+      decr_hits = atof (fields[2]);
+      decr += decr_count;
+    }
+
+    /*
+     * Operations on the cache, i. e. cache hits, cache misses and evictions of items
+     */
+    else if (FIELD_IS ("get_hits"))
+    {
+      submit_derive ("memcached_ops", "hits", atoll (fields[2]), st);
+      hits = atof (fields[2]);
+    }
+    else if (FIELD_IS ("get_misses"))
+    {
+      submit_derive ("memcached_ops", "misses", atoll (fields[2]), st);
+    }
+    else if (FIELD_IS ("evictions"))
+    {
+      submit_derive ("memcached_ops", "evictions", atoll (fields[2]), st);
+    }
+
+    /*
+     * Network traffic
+     */
+    else if (FIELD_IS ("bytes_read"))
+    {
+      octets_rx = atoll (fields[2]);
+    }
+    else if (FIELD_IS ("bytes_written"))
+    {
+      octets_tx = atoll (fields[2]);
+    }
+  } /* while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL) */
+
+  if (!isnan (bytes_used) && !isnan (bytes_total) && (bytes_used <= bytes_total))
+    submit_gauge2 ("df", "cache", bytes_used, bytes_total - bytes_used, st);
+
+  if ((rusage_user != 0) || (rusage_syst != 0))
+    submit_derive2 ("ps_cputime", NULL, rusage_user, rusage_syst, st);
+
+  if ((octets_rx != 0) || (octets_tx != 0))
+    submit_derive2 ("memcached_octets", NULL, octets_rx, octets_tx, st);
+
+  if (!isnan (gets) && !isnan (hits))
+  {
+    gauge_t rate = NAN;
+
+    if (gets != 0.0)
+      rate = 100.0 * hits / gets;
+
+    submit_gauge ("percent", "hitratio", rate, st);
+  }
+
+  if (!isnan (incr_hits) && incr != 0)
+  {
+    gauge_t incr_rate = 100.0 * incr_hits / incr;
+    submit_gauge ("percent", "incr_hitratio", incr_rate, st);
+    submit_derive ("memcached_ops", "incr", incr, st);
+  }
+
+  if (!isnan (decr_hits) && decr != 0)
+  {
+    gauge_t decr_rate = 100.0 * decr_hits / decr;
+    submit_gauge ("percent", "decr_hitratio", decr_rate, st);
+    submit_derive ("memcached_ops", "decr", decr, st);
+  }
+
+  return 0;
+} /* int memcached_read */
+
+static int memcached_add_read_callback (memcached_t *st)
+{
+  user_data_t ud;
+  char callback_name[3*DATA_MAX_NAME_LEN];
+  int status;
+
+  memset (&ud, 0, sizeof (ud));
+  ud.data = st;
+  ud.free_func = (void *) memcached_free;
+
+  assert (st->name != NULL);
+  ssnprintf (callback_name, sizeof (callback_name), "memcached/%s", st->name);
+
+  status = plugin_register_complex_read (/* group = */ "memcached",
+      /* name      = */ callback_name,
+      /* callback  = */ memcached_read,
+      /* interval  = */ NULL,
+      /* user_data = */ &ud);
+  return (status);
+} /* int memcached_add_read_callback */
+
+/* Configuration handling functiions
+ * <Plugin memcached>
+ *   <Instance "instance_name">
+ *     Host foo.zomg.com
+ *     Port "1234"
+ *   </Instance>
+ * </Plugin>
+ */
+static int config_add_instance(oconfig_item_t *ci)
+{
+  memcached_t *st;
+  int i;
+  int status = 0;
+
+  /* Disable automatic generation of default instance in the init callback. */
+  memcached_have_instances = 1;
+
+  st = malloc (sizeof (*st));
+  if (st == NULL)
+  {
+    ERROR ("memcached plugin: malloc failed.");
+    return (-1);
+  }
+
+  memset (st, 0, sizeof (*st));
+  st->name = NULL;
+  st->socket = NULL;
+  st->host = NULL;
+  st->port = NULL;
+
+  if (strcasecmp (ci->key, "Plugin") == 0) /* default instance */
+    st->name = sstrdup ("__legacy__");
+  else /* <Instance /> block */
+    status = cf_util_get_string (ci, &st->name);
+  if (status != 0)
+  {
+    sfree (st);
+    return (status);
+  }
+  assert (st->name != NULL);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Socket", child->key) == 0)
+      status = cf_util_get_string (child, &st->socket);
+    else if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &st->host);
+    else if (strcasecmp ("Port", child->key) == 0)
+      status = cf_util_get_service (child, &st->port);
+    else
+    {
+      WARNING ("memcached plugin: Option `%s' not allowed here.",
+          child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if (status == 0)
+    status = memcached_add_read_callback (st);
+
+  if (status != 0)
+  {
+    memcached_free(st);
+    return (-1);
+  }
+
+  return (0);
+}
+
+static int memcached_config (oconfig_item_t *ci)
+{
+  int status = 0;
+  _Bool have_instance_block = 0;
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Instance", child->key) == 0)
+    {
+      config_add_instance (child);
+      have_instance_block = 1;
+    }
+    else if (!have_instance_block)
+    {
+      /* Non-instance option: Assume legacy configuration (without <Instance />
+       * blocks) and call config_add_instance() with the <Plugin /> block. */
+      return (config_add_instance (ci));
+    }
+    else
+      WARNING ("memcached plugin: The configuration option "
+          "\"%s\" is not allowed here. Did you "
+          "forget to add an <Instance /> block "
+          "around the configuration?",
+          child->key);
+  } /* for (ci->children) */
+
+  return (status);
+}
+
+static int memcached_init (void)
+{
+  memcached_t *st;
+  int status;
+
+  if (memcached_have_instances)
+    return (0);
+
+  /* No instances were configured, lets start a default instance. */
+  st = malloc (sizeof (*st));
+  if (st == NULL)
+    return (ENOMEM);
+  memset (st, 0, sizeof (*st));
+  st->name = sstrdup ("__legacy__");
+  st->socket = NULL;
+  st->host = NULL;
+  st->port = NULL;
+
+  status = memcached_add_read_callback (st);
+  if (status == 0)
+    memcached_have_instances = 1;
+  else
+    memcached_free (st);
+
+  return (status);
+} /* int memcached_init */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("memcached", memcached_config);
+  plugin_register_init ("memcached", memcached_init);
+}
diff --git a/src/memory.c b/src/memory.c
new file mode 100644 (file)
index 0000000..fb2f3d3
--- /dev/null
@@ -0,0 +1,533 @@
+/**
+ * collectd - src/memory.c
+ * Copyright (C) 2005-2014  Florian octo Forster
+ * Copyright (C) 2009       Simon Kuhnle
+ * Copyright (C) 2009       Manuel Sanmartin
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Simon Kuhnle <simon at blarzwurst.de>
+ *   Manuel Sanmartin
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#ifdef HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+#endif
+#ifdef HAVE_SYS_VMMETER_H
+# include <sys/vmmeter.h>
+#endif
+
+#ifdef HAVE_MACH_KERN_RETURN_H
+# include <mach/kern_return.h>
+#endif
+#ifdef HAVE_MACH_MACH_INIT_H
+# include <mach/mach_init.h>
+#endif
+#ifdef HAVE_MACH_MACH_HOST_H
+# include <mach/mach_host.h>
+#endif
+#ifdef HAVE_MACH_HOST_PRIV_H
+# include <mach/host_priv.h>
+#endif
+#ifdef HAVE_MACH_VM_STATISTICS_H
+# include <mach/vm_statistics.h>
+#endif
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
+
+#if HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+#endif /* HAVE_PERFSTAT */
+
+/* vm_statistics_data_t */
+#if HAVE_HOST_STATISTICS
+static mach_port_t port_host;
+static vm_size_t pagesize;
+/* #endif HAVE_HOST_STATISTICS */
+
+#elif HAVE_SYSCTLBYNAME
+/* no global variables */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif KERNEL_LINUX
+/* no global variables */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+static int pagesize;
+static kstat_t *ksp;
+/* #endif HAVE_LIBKSTAT */
+
+#elif HAVE_SYSCTL
+static int pagesize;
+/* #endif HAVE_SYSCTL */
+
+#elif HAVE_LIBSTATGRAB
+/* no global variables */
+/* endif HAVE_LIBSTATGRAB */
+#elif HAVE_PERFSTAT
+static int pagesize;
+/* endif HAVE_PERFSTAT */
+#else
+# error "No applicable input method."
+#endif
+
+static _Bool values_absolute = 1;
+static _Bool values_percentage = 0;
+
+static int memory_config (oconfig_item_t *ci) /* {{{ */
+{
+       int i;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+               if (strcasecmp ("ValuesAbsolute", child->key) == 0)
+                       cf_util_get_boolean (child, &values_absolute);
+               else if (strcasecmp ("ValuesPercentage", child->key) == 0)
+                       cf_util_get_boolean (child, &values_percentage);
+               else
+                       ERROR ("memory plugin: Invalid configuration option: "
+                                       "\"%s\".", child->key);
+       }
+
+       return (0);
+} /* }}} int memory_config */
+
+static int memory_init (void)
+{
+#if HAVE_HOST_STATISTICS
+       port_host = mach_host_self ();
+       host_page_size (port_host, &pagesize);
+/* #endif HAVE_HOST_STATISTICS */
+
+#elif HAVE_SYSCTLBYNAME
+/* no init stuff */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif defined(KERNEL_LINUX)
+/* no init stuff */
+/* #endif KERNEL_LINUX */
+
+#elif defined(HAVE_LIBKSTAT)
+       /* getpagesize(3C) tells me this does not fail.. */
+       pagesize = getpagesize ();
+       if (get_kstat (&ksp, "unix", 0, "system_pages") != 0)
+       {
+               ksp = NULL;
+               return (-1);
+       }
+/* #endif HAVE_LIBKSTAT */
+
+#elif HAVE_SYSCTL
+       pagesize = getpagesize ();
+       if (pagesize <= 0)
+       {
+               ERROR ("memory plugin: Invalid pagesize: %i", pagesize);
+               return (-1);
+       }
+/* #endif HAVE_SYSCTL */
+
+#elif HAVE_LIBSTATGRAB
+/* no init stuff */
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif HAVE_PERFSTAT
+       pagesize = getpagesize ();
+#endif /* HAVE_PERFSTAT */
+       return (0);
+} /* int memory_init */
+
+#define MEMORY_SUBMIT(...) do { \
+       if (values_absolute) \
+               plugin_dispatch_multivalue (vl, 0, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \
+       if (values_percentage) \
+               plugin_dispatch_multivalue (vl, 1, DS_TYPE_GAUGE, __VA_ARGS__, NULL); \
+} while (0)
+
+static int memory_read_internal (value_list_t *vl)
+{
+#if HAVE_HOST_STATISTICS
+       kern_return_t status;
+       vm_statistics_data_t   vm_data;
+       mach_msg_type_number_t vm_data_len;
+
+       gauge_t wired;
+       gauge_t active;
+       gauge_t inactive;
+       gauge_t free;
+
+       if (!port_host || !pagesize)
+               return (-1);
+
+       vm_data_len = sizeof (vm_data) / sizeof (natural_t);
+       if ((status = host_statistics (port_host, HOST_VM_INFO,
+                                       (host_info_t) &vm_data,
+                                       &vm_data_len)) != KERN_SUCCESS)
+       {
+               ERROR ("memory-plugin: host_statistics failed and returned the value %i", (int) status);
+               return (-1);
+       }
+
+       /*
+        * From <http://docs.info.apple.com/article.html?artnum=107918>:
+        *
+        * Wired memory
+        *   This information can't be cached to disk, so it must stay in RAM.
+        *   The amount depends on what applications you are using.
+        *
+        * Active memory
+        *   This information is currently in RAM and actively being used.
+        *
+        * Inactive memory
+        *   This information is no longer being used and has been cached to
+        *   disk, but it will remain in RAM until another application needs
+        *   the space. Leaving this information in RAM is to your advantage if
+        *   you (or a client of your computer) come back to it later.
+        *
+        * Free memory
+        *   This memory is not being used.
+        */
+
+       wired    = (gauge_t) (((uint64_t) vm_data.wire_count)     * ((uint64_t) pagesize));
+       active   = (gauge_t) (((uint64_t) vm_data.active_count)   * ((uint64_t) pagesize));
+       inactive = (gauge_t) (((uint64_t) vm_data.inactive_count) * ((uint64_t) pagesize));
+       free     = (gauge_t) (((uint64_t) vm_data.free_count)     * ((uint64_t) pagesize));
+
+       MEMORY_SUBMIT ("wired",    wired,
+                      "active",   active,
+                      "inactive", inactive,
+                      "free",     free);
+/* #endif HAVE_HOST_STATISTICS */
+
+#elif HAVE_SYSCTLBYNAME
+       /*
+        * vm.stats.vm.v_page_size: 4096
+        * vm.stats.vm.v_page_count: 246178
+        * vm.stats.vm.v_free_count: 28760
+        * vm.stats.vm.v_wire_count: 37526
+        * vm.stats.vm.v_active_count: 55239
+        * vm.stats.vm.v_inactive_count: 113730
+        * vm.stats.vm.v_cache_count: 10809
+        */
+       char *sysctl_keys[8] =
+       {
+               "vm.stats.vm.v_page_size",
+               "vm.stats.vm.v_page_count",
+               "vm.stats.vm.v_free_count",
+               "vm.stats.vm.v_wire_count",
+               "vm.stats.vm.v_active_count",
+               "vm.stats.vm.v_inactive_count",
+               "vm.stats.vm.v_cache_count",
+               NULL
+       };
+       double sysctl_vals[8];
+
+       int    i;
+
+       for (i = 0; sysctl_keys[i] != NULL; i++)
+       {
+               int value;
+               size_t value_len = sizeof (value);
+
+               if (sysctlbyname (sysctl_keys[i], (void *) &value, &value_len,
+                                       NULL, 0) == 0)
+               {
+                       sysctl_vals[i] = value;
+                       DEBUG ("memory plugin: %26s: %g", sysctl_keys[i], sysctl_vals[i]);
+               }
+               else
+               {
+                       sysctl_vals[i] = NAN;
+               }
+       } /* for (sysctl_keys) */
+
+       /* multiply all all page counts with the pagesize */
+       for (i = 1; sysctl_keys[i] != NULL; i++)
+               if (!isnan (sysctl_vals[i]))
+                       sysctl_vals[i] *= sysctl_vals[0];
+
+       MEMORY_SUBMIT ("free",     (gauge_t) sysctl_vals[2],
+                      "wired",    (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 */
+
+#elif KERNEL_LINUX
+       FILE *fh;
+       char buffer[1024];
+
+       char *fields[8];
+       int numfields;
+
+       _Bool detailed_slab_info = 0;
+
+       gauge_t mem_total = 0;
+       gauge_t mem_used = 0;
+       gauge_t mem_buffered = 0;
+       gauge_t mem_cached = 0;
+       gauge_t mem_free = 0;
+       gauge_t mem_slab_total = 0;
+       gauge_t mem_slab_reclaimable = 0;
+       gauge_t mem_slab_unreclaimable = 0;
+
+       if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("memory: fopen: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               gauge_t *val = NULL;
+
+               if (strncasecmp (buffer, "MemTotal:", 9) == 0)
+                       val = &mem_total;
+               else if (strncasecmp (buffer, "MemFree:", 8) == 0)
+                       val = &mem_free;
+               else if (strncasecmp (buffer, "Buffers:", 8) == 0)
+                       val = &mem_buffered;
+               else if (strncasecmp (buffer, "Cached:", 7) == 0)
+                       val = &mem_cached;
+               else if (strncasecmp (buffer, "Slab:", 5) == 0)
+                       val = &mem_slab_total;
+               else if (strncasecmp (buffer, "SReclaimable:", 13) == 0) {
+                       val = &mem_slab_reclaimable;
+                       detailed_slab_info = 1;
+               }
+               else if (strncasecmp (buffer, "SUnreclaim:", 11) == 0) {
+                       val = &mem_slab_unreclaimable;
+                       detailed_slab_info = 1;
+               }
+               else
+                       continue;
+
+               numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (numfields < 2)
+                       continue;
+
+               *val = 1024.0 * atof (fields[1]);
+       }
+
+       if (fclose (fh))
+       {
+               char errbuf[1024];
+               WARNING ("memory: fclose: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+
+       if (mem_total < (mem_free + mem_buffered + mem_cached + mem_slab_total))
+               return (-1);
+
+       mem_used = mem_total - (mem_free + mem_buffered + mem_cached + mem_slab_total);
+
+       /* SReclaimable and SUnreclaim were introduced in kernel 2.6.19
+        * They sum up to the value of Slab, which is available on older & newer
+        * kernels. So SReclaimable/SUnreclaim are submitted if available, and Slab
+        * if not. */
+       if (detailed_slab_info)
+               MEMORY_SUBMIT ("used",        mem_used,
+                              "buffered",    mem_buffered,
+                              "cached",      mem_cached,
+                              "free",        mem_free,
+                              "slab_unrecl", mem_slab_unreclaimable,
+                              "slab_recl",   mem_slab_reclaimable);
+       else
+               MEMORY_SUBMIT ("used",     mem_used,
+                              "buffered", mem_buffered,
+                              "cached",   mem_cached,
+                              "free",     mem_free,
+                              "slab",     mem_slab_total);
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+       /* Most of the additions here were taken as-is from the k9toolkit from
+        * Brendan Gregg and are subject to change I guess */
+       long long mem_used;
+       long long mem_free;
+       long long mem_lock;
+       long long mem_kern;
+       long long mem_unus;
+
+       long long pp_kernel;
+       long long physmem;
+       long long availrmem;
+
+       if (ksp == NULL)
+               return (-1);
+
+       mem_used = get_kstat_value (ksp, "pagestotal");
+       mem_free = get_kstat_value (ksp, "pagesfree");
+       mem_lock = get_kstat_value (ksp, "pageslocked");
+       mem_kern = 0;
+       mem_unus = 0;
+
+       pp_kernel = get_kstat_value (ksp, "pp_kernel");
+       physmem = get_kstat_value (ksp, "physmem");
+       availrmem = get_kstat_value (ksp, "availrmem");
+
+       if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
+       {
+               WARNING ("memory plugin: one of used, free or locked is negative.");
+               return (-1);
+       }
+
+       mem_unus = physmem - mem_used;
+
+       if (mem_used < (mem_free + mem_lock))
+       {
+               /* source: http://wesunsolve.net/bugid/id/4909199
+                * this seems to happen when swap space is small, e.g. 2G on a 32G system
+                * we will make some assumptions here
+                * educated solaris internals help welcome here */
+               DEBUG ("memory plugin: pages total is smaller than \"free\" "
+                               "+ \"locked\". This is probably due to small "
+                               "swap space");
+               mem_free = availrmem;
+               mem_used = 0;
+       }
+       else
+       {
+               mem_used -= mem_free + mem_lock;
+       }
+
+       /* mem_kern is accounted for in mem_lock */
+       if (pp_kernel < mem_lock)
+       {
+               mem_kern = pp_kernel;
+               mem_lock -= pp_kernel;
+       }
+       else
+       {
+               mem_kern = mem_lock;
+               mem_lock = 0;
+       }
+
+       mem_used *= pagesize; /* If this overflows you have some serious */
+       mem_free *= pagesize; /* memory.. Why not call me up and give me */
+       mem_lock *= pagesize; /* some? ;) */
+       mem_kern *= pagesize; /* it's 2011 RAM is cheap */
+       mem_unus *= pagesize;
+
+       MEMORY_SUBMIT ("used",     (gauge_t) mem_used,
+                      "free",     (gauge_t) mem_free,
+                      "locked",   (gauge_t) mem_lock,
+                      "kernel",   (gauge_t) mem_kern,
+                      "unusable", (gauge_t) mem_unus);
+/* #endif HAVE_LIBKSTAT */
+
+#elif HAVE_SYSCTL
+       int mib[] = {CTL_VM, VM_METER};
+       struct vmtotal vmtotal;
+       gauge_t mem_active;
+       gauge_t mem_inactive;
+       gauge_t mem_free;
+       size_t size;
+
+       memset (&vmtotal, 0, sizeof (vmtotal));
+       size = sizeof (vmtotal);
+
+       if (sysctl (mib, 2, &vmtotal, &size, NULL, 0) < 0) {
+               char errbuf[1024];
+               WARNING ("memory plugin: sysctl failed: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       assert (pagesize > 0);
+       mem_active   = (gauge_t) (vmtotal.t_arm * pagesize);
+       mem_inactive = (gauge_t) ((vmtotal.t_rm - vmtotal.t_arm) * pagesize);
+       mem_free     = (gauge_t) (vmtotal.t_free * pagesize);
+
+       MEMORY_SUBMIT ("active",   mem_active,
+                      "inactive", mem_inactive,
+                      "free",     mem_free);
+/* #endif HAVE_SYSCTL */
+
+#elif HAVE_LIBSTATGRAB
+       sg_mem_stats *ios;
+
+       ios = sg_get_mem_stats ();
+       if (ios == NULL)
+               return (-1);
+
+       MEMORY_SUBMIT ("used",   (gauge_t) ios->used,
+                      "cached", (gauge_t) ios->cache,
+                      "free",   (gauge_t) ios->free);
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif HAVE_PERFSTAT
+       perfstat_memory_total_t pmemory;
+
+       memset (&pmemory, 0, sizeof (pmemory));
+       if (perfstat_memory_total(NULL, &pmemory, sizeof(pmemory), 1) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("memory plugin: perfstat_memory_total failed: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       /* Unfortunately, the AIX documentation is not very clear on how these
+        * numbers relate to one another. The only thing is states explcitly
+        * is:
+        *   real_total = real_process + real_free + numperm + real_system
+        *
+        * Another segmentation, which would be closer to the numbers reported
+        * by the "svmon" utility, would be:
+        *   real_total = real_free + real_inuse
+        *   real_inuse = "active" + real_pinned + numperm
+        */
+       MEMORY_SUBMIT ("free",   (gauge_t) (pmemory.real_free    * pagesize),
+                      "cached", (gauge_t) (pmemory.numperm      * pagesize),
+                      "system", (gauge_t) (pmemory.real_system  * pagesize),
+                      "user",   (gauge_t) (pmemory.real_process * pagesize));
+#endif /* HAVE_PERFSTAT */
+
+       return (0);
+} /* }}} int memory_read_internal */
+
+static int memory_read (void) /* {{{ */
+{
+       value_t v[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = v;
+       vl.values_len = STATIC_ARRAY_SIZE (v);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "memory", sizeof (vl.plugin));
+       sstrncpy (vl.type, "memory", sizeof (vl.type));
+       vl.time = cdtime ();
+
+       return (memory_read_internal (&vl));
+} /* }}} int memory_read */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("memory", memory_config);
+       plugin_register_init ("memory", memory_init);
+       plugin_register_read ("memory", memory_read);
+} /* void module_register */
diff --git a/src/mic.c b/src/mic.c
new file mode 100644 (file)
index 0000000..570da51
--- /dev/null
+++ b/src/mic.c
@@ -0,0 +1,417 @@
+/**
+ * collectd - src/mic.c
+ * Copyright (C) 2013 Battelle Memorial Institute
+ *
+ * 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:
+ *   Evan Felix <evan.felix at pnnl.gov>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_ignorelist.h"
+
+#include <MicAccessTypes.h>
+#include <MicAccessErrorTypes.h>
+#include <MicAccessApi.h>
+#include <MicThermalAPI.h>
+#include <MicPowerManagerAPI.h>
+
+#define MAX_MICS 32
+#define MAX_CORES 256
+
+static MicDeviceOnSystem mics[MAX_MICS];
+static U32 num_mics = 0;
+static HANDLE mic_handle = NULL;
+
+static int const therm_ids[] = {
+       eMicThermalDie, eMicThermalDevMem, eMicThermalFin, eMicThermalFout,
+       eMicThermalVccp, eMicThermalVddg, eMicThermalVddq };
+static char const * const therm_names[] = {
+       "die", "devmem", "fin", "fout",
+       "vccp", "vddg", "vddq" };
+
+static const char *config_keys[] =
+{
+       "ShowCPU",
+       "ShowCPUCores",
+       "ShowMemory",
+       "ShowTemperatures",
+       "Temperature",
+       "IgnoreSelectedTemperature",
+       "ShowPower",
+       "Power",
+       "IgnoreSelectedPower"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static _Bool show_cpu = 1;
+static _Bool show_cpu_cores = 1;
+static _Bool show_memory = 1;
+static _Bool show_temps = 1;
+static ignorelist_t *temp_ignore = NULL;
+static _Bool show_power = 1;
+static ignorelist_t *power_ignore = NULL;
+
+static int mic_init (void)
+{
+       U32 ret;
+       U32 mic_count;
+
+       if (mic_handle)
+               return (0);
+
+       mic_count = (U32) STATIC_ARRAY_SIZE(mics);
+       ret = MicInitAPI(&mic_handle,  eTARGET_SCIF_DRIVER, mics, &mic_count);
+       if (ret != MIC_ACCESS_API_SUCCESS) {
+               ERROR("mic plugin: Problem initializing MicAccessAPI: %s",
+                               MicGetErrorString(ret));
+       }
+       DEBUG("mic plugin: found: %"PRIu32" MIC(s)",mic_count);
+
+       if (mic_count<0 || mic_count>=MAX_MICS) {
+               ERROR("mic plugin: No Intel MICs in system");
+               return (1);
+       }
+       else {
+               num_mics = mic_count;
+               return (0);
+       }
+}
+
+static int mic_config (const char *key, const char *value) {
+       if (temp_ignore == NULL)
+               temp_ignore = ignorelist_create(1);
+       if (power_ignore == NULL)
+               power_ignore = ignorelist_create(1);
+       if (temp_ignore == NULL || power_ignore == NULL)
+               return (1);
+
+       if (strcasecmp("ShowCPU",key) == 0)
+       {
+               show_cpu = IS_TRUE(value);
+       }
+       else if (strcasecmp("ShowCPUCores",key) == 0)
+       {
+               show_cpu_cores = IS_TRUE(value);
+       }
+       else if (strcasecmp("ShowTemperatures",key) == 0)
+       {
+               show_temps = IS_TRUE(value);
+       }
+       else if (strcasecmp("ShowMemory",key) == 0)
+       {
+               show_memory = IS_TRUE(value);
+       }
+       else if (strcasecmp("ShowPower",key) == 0)
+       {
+               show_power = IS_TRUE(value);
+       }
+       else if (strcasecmp("Temperature",key) == 0)
+       {
+               ignorelist_add(temp_ignore,value);
+       }
+       else if (strcasecmp("IgnoreSelectedTemperature",key) == 0)
+       {
+               int invert = 1;
+               if (IS_TRUE(value))
+                       invert = 0;
+               ignorelist_set_invert(temp_ignore,invert);
+       }
+       else if (strcasecmp("Power",key) == 0)
+       {
+               ignorelist_add(power_ignore,value);
+       }
+       else if (strcasecmp("IgnoreSelectedPower",key) == 0)
+       {
+               int invert = 1;
+               if (IS_TRUE(value))
+                       invert = 0;
+               ignorelist_set_invert(power_ignore,invert);
+       }
+       else
+       {
+               return (-1);
+       }
+       return (0);
+}
+
+static void mic_submit_memory_use(int micnumber, const char *type_instance, U32 val)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       /* MicAccessAPI reports KB's of memory, adjust for this */
+       DEBUG("mic plugin: Memory Value Report; %u %lf",val,((gauge_t)val)*1024.0);
+       values[0].gauge = ((gauge_t)val)*1024.0;
+
+       vl.values=values;
+       vl.values_len=1;
+
+       strncpy (vl.host, hostname_g, sizeof (vl.host));
+       strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+       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));
+
+       plugin_dispatch_values (&vl);
+}
+
+/* Gather memory Utilization */
+static int mic_read_memory(int mic)
+{
+       U32 ret;
+       U32 mem_total,mem_free,mem_bufs;
+
+       ret = MicGetMemoryUtilization(mic_handle,&mem_total,&mem_free,&mem_bufs);
+       if (ret != MIC_ACCESS_API_SUCCESS) {
+               ERROR("mic plugin: Problem getting Memory Utilization: %s",
+                               MicGetErrorString(ret));
+               return (1);
+       }
+       mic_submit_memory_use(mic,"free",mem_free);
+       mic_submit_memory_use(mic,"used",mem_total-mem_free-mem_bufs);
+       mic_submit_memory_use(mic,"buffered",mem_bufs);
+       DEBUG("mic plugin: Memory Read: %u %u %u",mem_total,mem_free,mem_bufs);
+       return (0);
+}
+
+static void mic_submit_temp(int micnumber, const char *type, gauge_t val)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = val;
+
+       vl.values=values;
+       vl.values_len=1;
+
+       strncpy (vl.host, hostname_g, sizeof (vl.host));
+       strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+       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));
+
+       plugin_dispatch_values (&vl);
+}
+
+/* Gather Temperature Information */
+static int mic_read_temps(int mic)
+{
+       size_t num_therms = STATIC_ARRAY_SIZE(therm_ids);
+       size_t j;
+
+       for (j = 0; j < num_therms; j++) {
+               U32 status;
+               U32 temp_buffer;
+               U32 buffer_size = (U32)sizeof(temp_buffer);
+               char const *name = therm_names[j];
+
+               if (ignorelist_match(temp_ignore, name) != 0)
+                       continue;
+
+               status = MicGetTemperature(mic_handle, therm_ids[j],
+                               &temp_buffer, &buffer_size);
+               if (status != MIC_ACCESS_API_SUCCESS) {
+                       ERROR("mic plugin: Error reading temperature \"%s\": "
+                                       "%s", name, MicGetErrorString(status));
+                       return (1);
+               }
+               mic_submit_temp(mic, name, temp_buffer);
+       }
+       return (0);
+}
+
+static void mic_submit_cpu(int micnumber, const char *type_instance,
+               int core, derive_t val)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = val;
+
+       vl.values=values;
+       vl.values_len=1;
+
+       strncpy (vl.host, hostname_g, sizeof (vl.host));
+       strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+       if (core < 0) /* global aggregation */
+               ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+                               "%i", micnumber);
+       else /* per-core statistics */
+               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));
+
+       plugin_dispatch_values (&vl);
+}
+
+/*Gather CPU Utilization Information */
+static int mic_read_cpu(int mic)
+{
+       MicCoreUtil core_util;
+       MicCoreJiff core_jiffs[MAX_CORES];
+       U32 core_jiffs_size;
+       U32 status;
+
+       core_jiffs_size = MAX_CORES * sizeof(MicCoreJiff);
+       status = MicGetCoreUtilization(mic_handle, &core_util,
+                       core_jiffs, &core_jiffs_size);
+       if (status != MIC_ACCESS_API_SUCCESS) {
+               ERROR("mic plugin: Problem getting CPU utilization: %s",
+                               MicGetErrorString(status));
+               return(-1);
+       }
+
+       if (show_cpu) {
+               mic_submit_cpu(mic, "user", -1, core_util.sum.user);
+               mic_submit_cpu(mic, "sys", -1, core_util.sum.sys);
+               mic_submit_cpu(mic, "nice", -1, core_util.sum.nice);
+               mic_submit_cpu(mic, "idle", -1, core_util.sum.idle);
+       }
+
+       if (show_cpu_cores) {
+               int j;
+               for (j = 0; j < core_util.core; j++) {
+                       mic_submit_cpu(mic, "user", j, core_jiffs[j].user);
+                       mic_submit_cpu(mic, "sys", j, core_jiffs[j].sys);
+                       mic_submit_cpu(mic, "nice", j, core_jiffs[j].nice);
+                       mic_submit_cpu(mic, "idle", j, core_jiffs[j].idle);
+               }
+       }
+       return (0);
+}
+
+static void mic_submit_power(int micnumber, const char *type, const char *type_instance, gauge_t val)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = val;
+
+       vl.values=values;
+       vl.values_len=1;
+
+       strncpy (vl.host, hostname_g, sizeof (vl.host));
+       strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+       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));
+
+       plugin_dispatch_values (&vl);
+}
+
+/* Gather Power Information */
+static int mic_read_power(int mic)
+{
+       U32 ret;
+       MicPwrUsage power_use;
+
+       ret = MicGetPowerUsage(mic_handle,&power_use);
+       if (ret != MIC_ACCESS_API_SUCCESS) {
+               ERROR("mic plugin: Problem getting Power Usage: %s",
+                       MicGetErrorString(ret));
+               return (1);
+       }
+
+       /* power is in uWatts, current in mA, voltage in uVolts..   convert to
+        * base unit */
+       #define SUB_POWER(name) do { if (ignorelist_match(power_ignore,#name)==0) \
+               mic_submit_power(mic,"power",#name,(gauge_t)power_use.name.prr*0.000001); \
+       } while(0)
+       #define SUB_VOLTS(name) do { if (ignorelist_match(power_ignore,#name)==0) {\
+               mic_submit_power(mic,"power",#name,(gauge_t)(power_use.name.pwr*0.000001)); \
+               mic_submit_power(mic,"current",#name,(gauge_t)(power_use.name.cur*0.001)); \
+               mic_submit_power(mic,"voltage",#name,(gauge_t)(power_use.name.volt*0.000001)); \
+       }} while(0)
+
+       SUB_POWER(total0);
+       SUB_POWER(total1);
+       SUB_POWER(inst);
+       SUB_POWER(imax);
+       SUB_POWER(pcie);
+       SUB_POWER(c2x3);
+       SUB_POWER(c2x4);
+       SUB_VOLTS(vccp);
+       SUB_VOLTS(vddg);
+       SUB_VOLTS(vddq);
+
+       return (0);
+}
+
+static int mic_read (void)
+{
+       int i;
+       U32 ret;
+       int error;
+
+       error=0;
+       for (i=0;i<num_mics;i++) {
+               ret = MicInitAdapter(&mic_handle,&mics[i]);
+               if (ret != MIC_ACCESS_API_SUCCESS) {
+                       ERROR("mic plugin: Problem initializing MicAdapter: %s",
+                                       MicGetErrorString(ret));
+                       error=1;
+               }
+
+               if (error == 0 && show_memory)
+                       error = mic_read_memory(i);
+
+               if (error == 0 && show_temps)
+                       error = mic_read_temps(i);
+
+               if (error == 0 && (show_cpu || show_cpu_cores))
+                       error = mic_read_cpu(i);
+
+               if (error == 0 && (show_power))
+                       error = mic_read_power(i);
+
+               ret = MicCloseAdapter(mic_handle);
+               if (ret != MIC_ACCESS_API_SUCCESS) {
+                       ERROR("mic plugin: Problem closing MicAdapter: %s",
+                                       MicGetErrorString(ret));
+                       error=2;
+                       break;
+               }
+       }
+       if (num_mics==0)
+               error=3;
+       return error;
+}
+
+
+static int mic_shutdown (void)
+{
+       if (mic_handle)
+               MicCloseAPI(&mic_handle);
+       mic_handle = NULL;
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_init ("mic", mic_init);
+       plugin_register_shutdown ("mic", mic_shutdown);
+       plugin_register_read ("mic", mic_read);
+       plugin_register_config ("mic",mic_config, config_keys, config_keys_num);
+} /* void module_register */
+
+/*
+ * vim: set shiftwidth=8 softtabstop=8 noet textwidth=78 :
+ */
diff --git a/src/modbus.c b/src/modbus.c
new file mode 100644 (file)
index 0000000..e24f2ec
--- /dev/null
@@ -0,0 +1,1080 @@
+/**
+ * collectd - src/modbus.c
+ * Copyright (C) 2010,2011  noris network AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; only version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Florian Forster <octo at noris.net>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <netdb.h>
+
+#include <modbus/modbus.h>
+
+#ifndef LIBMODBUS_VERSION_CHECK
+/* Assume version 2.0.3 */
+# define LEGACY_LIBMODBUS 1
+#else
+/* Assume version 2.9.2 */
+#endif
+
+#ifndef MODBUS_TCP_DEFAULT_PORT
+# ifdef MODBUS_TCP_PORT
+#  define MODBUS_TCP_DEFAULT_PORT MODBUS_TCP_PORT
+# else
+#  define MODBUS_TCP_DEFAULT_PORT 502
+# endif
+#endif
+
+/*
+ * <Data "data_name">
+ *   RegisterBase 1234
+ *   RegisterCmd ReadHolding
+ *   RegisterType float
+ *   Type gauge
+ *   Instance "..."
+ * </Data>
+ *
+ * <Host "name">
+ *   Address "addr"
+ *   Port "1234"
+ *   # Or:
+ *   # Device "/dev/ttyUSB0"
+ *   # Baudrate 38400
+ *   # (Assumes 8N1)
+ *   Interval 60
+ *
+ *   <Slave 1>
+ *     Instance "foobar" # optional
+ *     Collect "data_name"
+ *   </Slave>
+ * </Host>
+ */
+
+/*
+ * Data structures
+ */
+enum mb_register_type_e /* {{{ */
+{
+  REG_TYPE_INT16,
+  REG_TYPE_INT32,
+  REG_TYPE_UINT16,
+  REG_TYPE_UINT32,
+  REG_TYPE_FLOAT
+}; /* }}} */
+enum mb_mreg_type_e /* {{{ */ 
+{
+  MREG_HOLDING,
+  MREG_INPUT
+}; /* }}} */
+typedef enum mb_register_type_e mb_register_type_t;
+typedef enum mb_mreg_type_e mb_mreg_type_t;
+
+/* TCP or RTU depending on what is specified in host config block */
+enum mb_conntype_e /* {{{ */
+{
+  MBCONN_TCP,
+  MBCONN_RTU
+}; /* }}} */
+typedef enum mb_conntype_e mb_conntype_t;
+
+struct mb_data_s;
+typedef struct mb_data_s mb_data_t;
+struct mb_data_s /* {{{ */
+{
+  char *name;
+  int register_base;
+  mb_register_type_t register_type;
+  mb_mreg_type_t modbus_register_type;
+  char type[DATA_MAX_NAME_LEN];
+  char instance[DATA_MAX_NAME_LEN];
+
+  mb_data_t *next;
+}; /* }}} */
+
+struct mb_slave_s /* {{{ */
+{
+  int id;
+  char instance[DATA_MAX_NAME_LEN];
+  mb_data_t *collect;
+}; /* }}} */
+typedef struct mb_slave_s mb_slave_t;
+
+struct mb_host_s /* {{{ */
+{
+  char host[DATA_MAX_NAME_LEN];
+  char node[NI_MAXHOST];       /* TCP hostname or RTU serial device */
+  /* char service[NI_MAXSERV]; */
+  int port;                    /* for Modbus/TCP */
+  int baudrate;                        /* for Modbus/RTU */
+  mb_conntype_t conntype;
+  cdtime_t interval;
+
+  mb_slave_t *slaves;
+  size_t slaves_num;
+
+#if LEGACY_LIBMODBUS
+  modbus_param_t connection;
+#else
+  modbus_t *connection;
+#endif
+  _Bool is_connected;
+}; /* }}} */
+typedef struct mb_host_s mb_host_t;
+
+struct mb_data_group_s;
+typedef struct mb_data_group_s mb_data_group_t;
+struct mb_data_group_s /* {{{ */
+{
+  mb_data_t *registers;
+  size_t registers_num;
+
+  mb_data_group_t *next;
+}; /* }}} */
+
+/*
+ * Global variables
+ */
+static mb_data_t *data_definitions = NULL;
+
+/*
+ * Functions
+ */
+static mb_data_t *data_get_by_name (mb_data_t *src, /* {{{ */
+    const char *name)
+{
+  mb_data_t *ptr;
+
+  if (name == NULL)
+    return (NULL);
+
+  for (ptr = src; ptr != NULL; ptr = ptr->next)
+    if (strcasecmp (ptr->name, name) == 0)
+      return (ptr);
+
+  return (NULL);
+} /* }}} mb_data_t *data_get_by_name */
+
+static int data_append (mb_data_t **dst, mb_data_t *src) /* {{{ */
+{
+  mb_data_t *ptr;
+
+  if ((dst == NULL) || (src == NULL))
+    return (EINVAL);
+
+  ptr = *dst;
+
+  if (ptr == NULL)
+  {
+    *dst = src;
+    return (0);
+  }
+
+  while (ptr->next != NULL)
+    ptr = ptr->next;
+
+  ptr->next = src;
+
+  return (0);
+} /* }}} int data_append */
+
+/* Copy a single mb_data_t and append it to another list. */
+static int data_copy (mb_data_t **dst, const mb_data_t *src) /* {{{ */
+{
+  mb_data_t *tmp;
+  int status;
+
+  if ((dst == NULL) || (src == NULL))
+    return (EINVAL);
+
+  tmp = malloc (sizeof (*tmp));
+  if (tmp == NULL)
+    return (ENOMEM);
+  memcpy (tmp, src, sizeof (*tmp));
+  tmp->name = NULL;
+  tmp->next = NULL;
+
+  tmp->name = strdup (src->name);
+  if (tmp->name == NULL)
+  {
+    sfree (tmp);
+    return (ENOMEM);
+  }
+
+  status = data_append (dst, tmp);
+  if (status != 0)
+  {
+    sfree (tmp->name);
+    sfree (tmp);
+    return (status);
+  }
+
+  return (0);
+} /* }}} int data_copy */
+
+/* Lookup a single mb_data_t instance, copy it and append the copy to another
+ * list. */
+static int data_copy_by_name (mb_data_t **dst, mb_data_t *src, /* {{{ */
+    const char *name)
+{
+  mb_data_t *ptr;
+
+  if ((dst == NULL) || (src == NULL) || (name == NULL))
+    return (EINVAL);
+
+  ptr = data_get_by_name (src, name);
+  if (ptr == NULL)
+    return (ENOENT);
+
+  return (data_copy (dst, ptr));
+} /* }}} int data_copy_by_name */
+
+/* Read functions */
+
+static int mb_submit (mb_host_t *host, mb_slave_t *slave, /* {{{ */
+    mb_data_t *data, value_t value)
+{
+  value_list_t vl = VALUE_LIST_INIT;
+
+  if ((host == NULL) || (slave == NULL) || (data == NULL))
+    return (EINVAL);
+
+  if (host->interval <= 0)
+    host->interval = plugin_get_interval ();
+
+  if (slave->instance[0] == 0)
+    ssnprintf (slave->instance, sizeof (slave->instance), "slave_%i",
+        slave->id);
+
+  vl.values = &value;
+  vl.values_len = 1;
+  vl.interval = host->interval;
+  sstrncpy (vl.host, host->host, sizeof (vl.host));
+  sstrncpy (vl.plugin, "modbus", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, slave->instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, data->type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, data->instance, sizeof (vl.type_instance));
+
+  return (plugin_dispatch_values (&vl));
+} /* }}} int mb_submit */
+
+static float mb_register_to_float (uint16_t hi, uint16_t lo) /* {{{ */
+{
+  union
+  {
+    uint8_t b[4];
+    uint16_t s[2];
+    float f;
+  } conv;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+  /* little endian */
+  conv.b[0] = lo & 0x00ff;
+  conv.b[1] = (lo >> 8) & 0x00ff;
+  conv.b[2] = hi & 0x00ff;
+  conv.b[3] = (hi >> 8) & 0x00ff;
+#else
+  conv.b[3] = lo & 0x00ff;
+  conv.b[2] = (lo >> 8) & 0x00ff;
+  conv.b[1] = hi & 0x00ff;
+  conv.b[0] = (hi >> 8) & 0x00ff;
+#endif
+
+  return (conv.f);
+} /* }}} float mb_register_to_float */
+
+#if LEGACY_LIBMODBUS
+/* Version 2.0.3 */
+static int mb_init_connection (mb_host_t *host) /* {{{ */
+{
+  int status;
+
+  if (host == NULL)
+    return (EINVAL);
+
+  modbus_set_debug (&host->connection, 1);
+
+  /* We'll do the error handling ourselves. */
+  modbus_set_error_handling (&host->connection, NOP_ON_ERROR);
+
+  if (host->conntype == MBCONN_TCP)
+  {
+    if ((host->port < 1) || (host->port > 65535))
+      host->port = MODBUS_TCP_DEFAULT_PORT;
+
+    DEBUG ("Modbus plugin: Trying to connect to \"%s\", port %i.",
+        host->node, host->port);
+
+    modbus_init_tcp (&host->connection,
+        /* host = */ host->node,
+        /* port = */ host->port);
+  }
+  else /* MBCONN_RTU */
+  {
+    DEBUG ("Modbus plugin: Trying to connect to \"%s\".", host->node);
+
+    modbus_init_rtu (&host->connection,
+       /* device = */ host->node,
+     /* baudrate = */ host->baudrate,
+                      'N', 8, 1, 0);
+  }
+
+  status = modbus_connect (&host->connection);
+  if (status != 0)
+  {
+    ERROR ("Modbus plugin: modbus_connect (%s, %i) failed with status %i.",
+        host->node, host->port ? host->port : host->baudrate, status);
+    return (status);
+  }
+
+  host->is_connected = 1;
+  return (0);
+} /* }}} int mb_init_connection */
+/* #endif LEGACY_LIBMODBUS */
+
+#else /* if !LEGACY_LIBMODBUS */
+/* Version 2.9.2 */
+static int mb_init_connection (mb_host_t *host) /* {{{ */
+{
+  int status;
+
+  if (host == NULL)
+    return (EINVAL);
+
+  if (host->connection != NULL)
+    return (0);
+
+  if (host->conntype == MBCONN_TCP)
+  {
+    if ((host->port < 1) || (host->port > 65535))
+      host->port = MODBUS_TCP_DEFAULT_PORT;
+
+    DEBUG ("Modbus plugin: Trying to connect to \"%s\", port %i.",
+        host->node, host->port);
+
+    host->connection = modbus_new_tcp (host->node, host->port);
+    if (host->connection == NULL)
+    {
+      ERROR ("Modbus plugin: Creating new Modbus/TCP object failed.");
+      return (-1);
+    }
+  }
+  else
+  {
+    DEBUG ("Modbus plugin: Trying to connect to \"%s\", baudrate %i.",
+        host->node, host->baudrate);
+
+    host->connection = modbus_new_rtu (host->node, host->baudrate, 'N', 8, 1);
+    if (host->connection == NULL)
+    {
+      ERROR ("Modbus plugin: Creating new Modbus/RTU object failed.");
+      return (-1);
+    }
+  }
+
+  modbus_set_debug (host->connection, 1);
+
+  /* We'll do the error handling ourselves. */
+  modbus_set_error_recovery (host->connection, 0);
+
+  status = modbus_connect (host->connection);
+  if (status != 0)
+  {
+    ERROR ("Modbus plugin: modbus_connect (%s, %i) failed with status %i.",
+        host->node, host->port ? host->port : host->baudrate, status);
+    modbus_free (host->connection);
+    host->connection = NULL;
+    return (status);
+  }
+
+  return (0);
+} /* }}} int mb_init_connection */
+#endif /* !LEGACY_LIBMODBUS */
+
+#define CAST_TO_VALUE_T(ds,vt,raw) do { \
+  if ((ds)->ds[0].type == DS_TYPE_COUNTER) \
+    (vt).counter = (counter_t) (raw); \
+  else if ((ds)->ds[0].type == DS_TYPE_GAUGE) \
+    (vt).gauge = (gauge_t) (raw); \
+  else if ((ds)->ds[0].type == DS_TYPE_DERIVE) \
+    (vt).derive = (derive_t) (raw); \
+  else /* if (ds->ds[0].type == DS_TYPE_ABSOLUTE) */ \
+    (vt).absolute = (absolute_t) (raw); \
+} while (0)
+
+static int mb_read_data (mb_host_t *host, mb_slave_t *slave, /* {{{ */
+    mb_data_t *data)
+{
+  uint16_t values[2];
+  int values_num;
+  const data_set_t *ds;
+  int status;
+
+  if ((host == NULL) || (slave == NULL) || (data == NULL))
+    return (EINVAL);
+
+  ds = plugin_get_ds (data->type);
+  if (ds == NULL)
+  {
+    ERROR ("Modbus plugin: Type \"%s\" is not defined.", data->type);
+    return (-1);
+  }
+
+  if (ds->ds_num != 1)
+  {
+    ERROR ("Modbus plugin: The type \"%s\" has %i data sources. "
+        "I can only handle data sets with only one data source.",
+        data->type, ds->ds_num);
+    return (-1);
+  }
+
+  if ((ds->ds[0].type != DS_TYPE_GAUGE)
+      && (data->register_type != REG_TYPE_INT32)
+      && (data->register_type != REG_TYPE_UINT32))
+  {
+    NOTICE ("Modbus plugin: The data source of type \"%s\" is %s, not gauge. "
+        "This will most likely result in problems, because the register type "
+        "is not UINT32.", data->type, DS_TYPE_TO_STRING (ds->ds[0].type));
+  }
+
+  memset (values, 0, sizeof (values));
+  if ((data->register_type == REG_TYPE_INT32)
+      || (data->register_type == REG_TYPE_UINT32)
+      || (data->register_type == REG_TYPE_FLOAT))
+    values_num = 2;
+  else
+    values_num = 1;
+
+  status = 0;
+  if (host->connection == NULL)
+  {
+    status = EBADF;
+  }
+  else if (host->conntype == MBCONN_TCP)
+  {
+    struct sockaddr sockaddr;
+    socklen_t saddrlen = sizeof (sockaddr);
+
+    status = getpeername (modbus_get_socket (host->connection),
+        &sockaddr, &saddrlen);
+    if (status != 0)
+      status = errno;
+  }
+
+  if ((status == EBADF) || (status == ENOTSOCK) || (status == ENOTCONN))
+  {
+    status = mb_init_connection (host);
+    if (status != 0)
+    {
+      ERROR ("Modbus plugin: mb_init_connection (%s/%s) failed. ",
+          host->host, host->node);
+      host->is_connected = 0;
+      host->connection = NULL;
+      return (-1);
+    }
+  }
+  else if (status != 0)
+  {
+#if LEGACY_LIBMODBUS
+    modbus_close (&host->connection);
+#else
+    modbus_close (host->connection);
+    modbus_free (host->connection);
+#endif
+  }
+#if LEGACY_LIBMODBUS
+  /* Version 2.0.3: Pass the connection struct as a pointer and pass the slave
+   * id to each call of "read_holding_registers". */
+# define modbus_read_registers(ctx, addr, nb, dest) \
+  read_holding_registers (&(ctx), slave->id, (addr), (nb), (dest))
+#else /* if !LEGACY_LIBMODBUS */
+  /* Version 2.9.2: Set the slave id once before querying the registers. */
+  status = modbus_set_slave (host->connection, slave->id);
+  if (status != 0)
+  {
+    ERROR ("Modbus plugin: modbus_set_slave (%i) failed with status %i.",
+        slave->id, status);
+    return (-1);
+  }
+#endif
+  if (data->modbus_register_type == MREG_INPUT){
+    status = modbus_read_input_registers (host->connection,
+        /* start_addr = */ data->register_base,
+        /* num_registers = */ values_num, /* buffer = */ values);
+  }
+  else{
+    status = modbus_read_registers (host->connection,
+        /* start_addr = */ data->register_base,
+        /* num_registers = */ values_num, /* buffer = */ values);
+  }
+  if (status != values_num)
+  {
+    ERROR ("Modbus plugin: modbus read function (%s/%s) failed. "
+           " status = %i, values_num = %i. Giving up.",
+           host->host, host->node, status, values_num);
+#if LEGACY_LIBMODBUS
+    modbus_close (&host->connection);
+#else
+    modbus_close (host->connection);
+    modbus_free (host->connection);
+#endif
+    host->connection = NULL;
+    return (-1);
+  }
+
+  DEBUG ("Modbus plugin: mb_read_data: Success! "
+      "modbus_read_registers returned with status %i.", status);
+
+  if (data->register_type == REG_TYPE_FLOAT)
+  {
+    float float_value;
+    value_t vt;
+
+    float_value = mb_register_to_float (values[0], values[1]);
+    DEBUG ("Modbus plugin: mb_read_data: "
+        "Returned float value is %g", (double) float_value);
+
+    CAST_TO_VALUE_T (ds, vt, float_value);
+    mb_submit (host, slave, data, vt);
+  }
+  else if (data->register_type == REG_TYPE_INT32)
+  {
+    union
+    {
+      uint32_t u32;
+      int32_t  i32;
+    } v;
+    value_t vt;
+
+    v.u32 = (((uint32_t) values[0]) << 16)
+      | ((uint32_t) values[1]);
+    DEBUG ("Modbus plugin: mb_read_data: "
+        "Returned int32 value is %"PRIi32, v.i32);
+
+    CAST_TO_VALUE_T (ds, vt, v.i32);
+    mb_submit (host, slave, data, vt);
+  }
+  else if (data->register_type == REG_TYPE_INT16)
+  {
+    union
+    {
+      uint16_t u16;
+      int16_t  i16;
+    } v;
+    value_t vt;
+
+    v.u16 = values[0];
+
+    DEBUG ("Modbus plugin: mb_read_data: "
+        "Returned int16 value is %"PRIi16, v.i16);
+
+    CAST_TO_VALUE_T (ds, vt, v.i16);
+    mb_submit (host, slave, data, vt);
+  }
+  else if (data->register_type == REG_TYPE_UINT32)
+  {
+    uint32_t v32;
+    value_t vt;
+
+    v32 = (((uint32_t) values[0]) << 16)
+      | ((uint32_t) values[1]);
+    DEBUG ("Modbus plugin: mb_read_data: "
+        "Returned uint32 value is %"PRIu32, v32);
+
+    CAST_TO_VALUE_T (ds, vt, v32);
+    mb_submit (host, slave, data, vt);
+  }
+  else /* if (data->register_type == REG_TYPE_UINT16) */
+  {
+    value_t vt;
+
+    DEBUG ("Modbus plugin: mb_read_data: "
+        "Returned uint16 value is %"PRIu16, values[0]);
+
+    CAST_TO_VALUE_T (ds, vt, values[0]);
+    mb_submit (host, slave, data, vt);
+  }
+
+  return (0);
+} /* }}} int mb_read_data */
+
+static int mb_read_slave (mb_host_t *host, mb_slave_t *slave) /* {{{ */
+{
+  mb_data_t *data;
+  int success;
+  int status;
+
+  if ((host == NULL) || (slave == NULL))
+    return (EINVAL);
+
+  success = 0;
+  for (data = slave->collect; data != NULL; data = data->next)
+  {
+    status = mb_read_data (host, slave, data);
+    if (status == 0)
+      success++;
+  }
+
+  if (success == 0)
+    return (-1);
+  else
+    return (0);
+} /* }}} int mb_read_slave */
+
+static int mb_read (user_data_t *user_data) /* {{{ */
+{
+  mb_host_t *host;
+  size_t i;
+  int success;
+  int status;
+
+  if ((user_data == NULL) || (user_data->data == NULL))
+    return (EINVAL);
+
+  host = user_data->data;
+
+  success = 0;
+  for (i = 0; i < host->slaves_num; i++)
+  {
+    status = mb_read_slave (host, host->slaves + i);
+    if (status == 0)
+      success++;
+  }
+
+  if (success == 0)
+    return (-1);
+  else
+    return (0);
+} /* }}} int mb_read */
+
+/* Free functions */
+
+static void data_free_one (mb_data_t *data) /* {{{ */
+{
+  if (data == NULL)
+    return;
+
+  sfree (data->name);
+  sfree (data);
+} /* }}} void data_free_one */
+
+static void data_free_all (mb_data_t *data) /* {{{ */
+{
+  mb_data_t *next;
+
+  if (data == NULL)
+    return;
+
+  next = data->next;
+  data_free_one (data);
+
+  data_free_all (next);
+} /* }}} void data_free_all */
+
+static void slaves_free_all (mb_slave_t *slaves, size_t slaves_num) /* {{{ */
+{
+  size_t i;
+
+  if (slaves == NULL)
+    return;
+
+  for (i = 0; i < slaves_num; i++)
+    data_free_all (slaves[i].collect);
+  sfree (slaves);
+} /* }}} void slaves_free_all */
+
+static void host_free (void *void_host) /* {{{ */
+{
+  mb_host_t *host = void_host;
+
+  if (host == NULL)
+    return;
+
+  slaves_free_all (host->slaves, host->slaves_num);
+  sfree (host);
+} /* }}} void host_free */
+
+/* Config functions */
+
+static int mb_config_add_data (oconfig_item_t *ci) /* {{{ */
+{
+  mb_data_t data;
+  int status;
+  int i;
+
+  memset (&data, 0, sizeof (data));
+  data.name = NULL;
+  data.register_type = REG_TYPE_UINT16;
+  data.next = NULL;
+
+  status = cf_util_get_string (ci, &data.name);
+  if (status != 0)
+    return (status);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Type", child->key) == 0)
+      status = cf_util_get_string_buffer (child,
+          data.type, sizeof (data.type));
+    else if (strcasecmp ("Instance", child->key) == 0)
+      status = cf_util_get_string_buffer (child,
+          data.instance, sizeof (data.instance));
+    else if (strcasecmp ("RegisterBase", child->key) == 0)
+      status = cf_util_get_int (child, &data.register_base);
+    else if (strcasecmp ("RegisterType", child->key) == 0)
+    {
+      char tmp[16];
+      status = cf_util_get_string_buffer (child, tmp, sizeof (tmp));
+      if (status != 0)
+        /* do nothing */;
+      else if (strcasecmp ("Int16", tmp) == 0)
+        data.register_type = REG_TYPE_INT16;
+      else if (strcasecmp ("Int32", tmp) == 0)
+        data.register_type = REG_TYPE_INT32;
+      else if (strcasecmp ("Uint16", tmp) == 0)
+        data.register_type = REG_TYPE_UINT16;
+      else if (strcasecmp ("Uint32", tmp) == 0)
+        data.register_type = REG_TYPE_UINT32;
+      else if (strcasecmp ("Float", tmp) == 0)
+        data.register_type = REG_TYPE_FLOAT;
+      else
+      {
+        ERROR ("Modbus plugin: The register type \"%s\" is unknown.", tmp);
+        status = -1;
+      }
+    }
+    else if (strcasecmp ("RegisterCmd", child->key) == 0)
+    {
+#if LEGACY_LIBMODBUS
+      ERROR("Modbus plugin: RegisterCmd parameter can not be used "
+            "with your libmodbus version");
+#else
+      char tmp[16];
+      status = cf_util_get_string_buffer (child, tmp, sizeof (tmp));
+      if (status != 0)
+        /* do nothing */;
+      else if (strcasecmp ("ReadHolding", tmp) == 0)
+        data.modbus_register_type = MREG_HOLDING;
+      else if (strcasecmp ("ReadInput", tmp) == 0)
+        data.modbus_register_type = MREG_INPUT;
+      else
+      {
+        ERROR ("Modbus plugin: The modbus_register_type \"%s\" is unknown.",
+               tmp);
+        status = -1;
+      }
+#endif
+    }
+    else
+    {
+      ERROR ("Modbus plugin: Unknown configuration option: %s", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  assert (data.name != NULL);
+  if (data.type[0] == 0)
+  {
+    ERROR ("Modbus plugin: Data block \"%s\": No type has been specified.",
+        data.name);
+    status = -1;
+  }
+
+  if (status == 0)
+    data_copy (&data_definitions, &data);
+
+  sfree (data.name);
+
+  return (status);
+} /* }}} int mb_config_add_data */
+
+static int mb_config_set_host_address (mb_host_t *host, /* {{{ */
+    const char *address)
+{
+  struct addrinfo *ai_list;
+  struct addrinfo *ai_ptr;
+  struct addrinfo  ai_hints;
+  int status;
+
+  if ((host == NULL) || (address == NULL))
+    return (EINVAL);
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+#if AI_ADDRCONFIG
+  ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+  /* XXX: libmodbus can only handle IPv4 addresses. */
+  ai_hints.ai_family = AF_INET;
+  ai_hints.ai_addr = NULL;
+  ai_hints.ai_canonname = NULL;
+  ai_hints.ai_next = NULL;
+
+  ai_list = NULL;
+  status = getaddrinfo (address, /* service = */ NULL,
+      &ai_hints, &ai_list);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("Modbus plugin: getaddrinfo failed: %s",
+        (status == EAI_SYSTEM)
+        ? sstrerror (errno, errbuf, sizeof (errbuf))
+        : gai_strerror (status));
+    return (status);
+  }
+
+  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    status = getnameinfo (ai_ptr->ai_addr, ai_ptr->ai_addrlen,
+        host->node, sizeof (host->node),
+        /* service = */ NULL, /* length = */ 0,
+        /* flags = */ NI_NUMERICHOST);
+    if (status == 0)
+      break;
+  } /* for (ai_ptr) */
+
+  freeaddrinfo (ai_list);
+
+  if (status != 0)
+    ERROR ("Modbus plugin: Unable to translate node name: \"%s\"", address);
+  else /* if (status == 0) */
+  {
+    DEBUG ("Modbus plugin: mb_config_set_host_address: %s -> %s",
+        address, host->node);
+  }
+
+  return (status);
+} /* }}} int mb_config_set_host_address */
+
+static int mb_config_add_slave (mb_host_t *host, oconfig_item_t *ci) /* {{{ */
+{
+  mb_slave_t *slave;
+  int status;
+  int i;
+
+  if ((host == NULL) || (ci == NULL))
+    return (EINVAL);
+
+  slave = realloc (host->slaves, sizeof (*slave) * (host->slaves_num + 1));
+  if (slave == NULL)
+    return (ENOMEM);
+  host->slaves = slave;
+  slave = host->slaves + host->slaves_num;
+  memset (slave, 0, sizeof (*slave));
+  slave->collect = NULL;
+
+  status = cf_util_get_int (ci, &slave->id);
+  if (status != 0)
+    return (status);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Instance", child->key) == 0)
+      status = cf_util_get_string_buffer (child,
+          slave->instance, sizeof (slave->instance));
+    else if (strcasecmp ("Collect", child->key) == 0)
+    {
+      char buffer[1024];
+      status = cf_util_get_string_buffer (child, buffer, sizeof (buffer));
+      if (status == 0)
+        data_copy_by_name (&slave->collect, data_definitions, buffer);
+      status = 0; /* continue after failure. */
+    }
+    else
+    {
+      ERROR ("Modbus plugin: Unknown configuration option: %s", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if ((status == 0) && (slave->collect == NULL))
+    status = EINVAL;
+
+  if (slave->id < 0)
+    status = EINVAL;
+
+  if (status == 0)
+    host->slaves_num++;
+  else /* if (status != 0) */
+    data_free_all (slave->collect);
+
+  return (status);
+} /* }}} int mb_config_add_slave */
+
+static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */
+{
+  mb_host_t *host;
+  int status;
+  int i;
+
+  host = malloc (sizeof (*host));
+  if (host == NULL)
+    return (ENOMEM);
+  memset (host, 0, sizeof (*host));
+  host->slaves = NULL;
+
+  status = cf_util_get_string_buffer (ci, host->host, sizeof (host->host));
+  if (status != 0)
+    return (status);
+  if (host->host[0] == 0)
+    return (EINVAL);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Address", child->key) == 0)
+    {
+      char buffer[NI_MAXHOST];
+      status = cf_util_get_string_buffer (child, buffer, sizeof (buffer));
+      if (status == 0)
+        status = mb_config_set_host_address (host, buffer);
+      if (status == 0)
+        host->conntype = MBCONN_TCP;
+    }
+    else if (strcasecmp ("Port", child->key) == 0)
+    {
+      host->port = cf_util_get_port_number (child);
+      if (host->port <= 0)
+        status = -1;
+    }
+    else if (strcasecmp ("Device", child->key) == 0)
+    {
+      status = cf_util_get_string_buffer (child, host->node, sizeof (host->node));
+      if (status == 0)
+        host->conntype = MBCONN_RTU;
+    }
+    else if (strcasecmp ("Baudrate", child->key) == 0)
+      status = cf_util_get_int(child, &host->baudrate);
+    else if (strcasecmp ("Interval", child->key) == 0)
+      status = cf_util_get_cdtime (child, &host->interval);
+    else if (strcasecmp ("Slave", child->key) == 0)
+      /* Don't set status: Gracefully continue if a slave fails. */
+      mb_config_add_slave (host, child);
+    else
+    {
+      ERROR ("Modbus plugin: Unknown configuration option: %s", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  assert (host->host[0] != 0);
+  if (host->node[0] == 0)
+  {
+    ERROR ("Modbus plugin: Data block \"%s\": No address or device has been specified.",
+        host->host);
+    status = -1;
+  }
+  if (host->conntype == MBCONN_RTU && !host->baudrate)
+  {
+    ERROR ("Modbus plugin: Data block \"%s\": No serial baudrate has been specified.",
+        host->host);
+    status = -1;
+  }
+  if ((host->conntype == MBCONN_TCP && host->baudrate) ||
+      (host->conntype == MBCONN_RTU && host->port))
+  {
+    ERROR ("Modbus plugin: Data block \"%s\": You've mixed up RTU and TCP options.",
+        host->host);
+    status = -1;
+  }
+
+  if (status == 0)
+  {
+    user_data_t ud;
+    char name[1024];
+    struct timespec interval = { 0, 0 };
+
+    ud.data = host;
+    ud.free_func = host_free;
+
+    ssnprintf (name, sizeof (name), "modbus-%s", host->host);
+
+    CDTIME_T_TO_TIMESPEC (host->interval, &interval);
+
+    plugin_register_complex_read (/* group = */ NULL, name,
+        /* callback = */ mb_read,
+        /* interval = */ (host->interval > 0) ? &interval : NULL,
+        &ud);
+  }
+  else
+  {
+    host_free (host);
+  }
+
+  return (status);
+} /* }}} int mb_config_add_host */
+
+static int mb_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  if (ci == NULL)
+    return (EINVAL);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Data", child->key) == 0)
+      mb_config_add_data (child);
+    else if (strcasecmp ("Host", child->key) == 0)
+      mb_config_add_host (child);
+    else
+      ERROR ("Modbus plugin: Unknown configuration option: %s", child->key);
+  }
+
+  return (0);
+} /* }}} int mb_config */
+
+/* ========= */
+
+static int mb_shutdown (void) /* {{{ */
+{
+  data_free_all (data_definitions);
+  data_definitions = NULL;
+
+  return (0);
+} /* }}} int mb_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("modbus", mb_config);
+  plugin_register_shutdown ("modbus", mb_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/multimeter.c b/src/multimeter.c
new file mode 100644 (file)
index 0000000..775eb57
--- /dev/null
@@ -0,0 +1,240 @@
+/**
+ * collectd - src/multimeter.c
+ * Copyright (C) 2005,2006  Peter Holik
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Peter Holik <peter at holik.at>
+ *
+ * Used multimeter: Metex M-4650CR
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if HAVE_TERMIOS_H && HAVE_SYS_IOCTL_H && HAVE_MATH_H
+# include <termios.h>
+# include <sys/ioctl.h>
+# include <math.h>
+#else
+# error "No applicable input method."
+#endif
+
+static int fd = -1;
+
+#define LINE_LENGTH 14
+static int multimeter_read_value(double *value)
+{
+       int retry = 3; /* sometimes we receive garbadge */
+
+       do
+       {
+               struct timeval time_end;
+
+               tcflush(fd, TCIFLUSH);
+
+               if (gettimeofday (&time_end, NULL) < 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("multimeter plugin: gettimeofday failed: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       return (-1);
+               }
+               time_end.tv_sec++;      
+
+               while (1)
+               {
+                       char buf[LINE_LENGTH];
+                       char *range;
+                       int status;
+                       fd_set rfds;
+                       struct timeval timeout;
+                       struct timeval time_now;
+
+                       status = swrite (fd, "D", 1);
+                       if (status < 0)
+                       {
+                               ERROR ("multimeter plugin: swrite failed.");
+                               return (-1);
+                       }
+
+                       FD_ZERO(&rfds);
+                       FD_SET(fd, &rfds);
+
+                       if (gettimeofday (&time_now, NULL) < 0)
+                       {
+                               char errbuf[1024];
+                               ERROR ("multimeter plugin: "
+                                               "gettimeofday failed: %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+                       if (timeval_cmp (time_end, time_now, &timeout) < 0)
+                               break;
+
+                       status = select(fd+1, &rfds, NULL, NULL, &timeout);
+
+                       if (status > 0) /* usually we succeed */
+                       {
+                               status = read(fd, buf, LINE_LENGTH);
+
+                               if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+                                       continue;
+
+                               /* Format: "DC 00.000mV  \r" */
+                               if (status > 0 && status == LINE_LENGTH)
+                               {
+                                       *value = strtod(buf + 2, &range);
+
+                                       if ( range > (buf + 6) )
+                                       {
+                                               range = buf + 9;
+
+                                               switch ( *range )
+                                               {
+                                                       case 'p': *value *= 1.0E-12; break;
+                                                       case 'n': *value *= 1.0E-9; break;
+                                                       case 'u': *value *= 1.0E-6; break;
+                                                       case 'm': *value *= 1.0E-3; break;
+                                                       case 'k': *value *= 1.0E3; break;
+                                                       case 'M': *value *= 1.0E6; break;
+                                                       case 'G': *value *= 1.0E9; break;
+                                               }
+                                       }
+                                       else
+                                               return (-1); /* Overflow */
+
+                                       return (0); /* value received */
+                               }
+                               else break;
+                       }
+                       else if (!status) /* Timeout */
+                       {
+                               break;
+                       }
+                       else if ((status == -1) && ((errno == EAGAIN) || (errno == EINTR)))
+                       {
+                               continue;
+                       }
+                       else /* status == -1 */
+                       {
+                               char errbuf[1024];
+                               ERROR ("multimeter plugin: "
+                                               "select failed: %s",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                               break;
+                       }
+               }
+       } while (--retry);
+
+       return (-2);  /* no value received */
+} /* int multimeter_read_value */
+
+static int multimeter_init (void)
+{
+       int i;
+       char device[] = "/dev/ttyS ";
+
+       for (i = 0; i < 10; i++)
+       {
+               device[strlen(device)-1] = i + '0'; 
+
+               if ((fd = open(device, O_RDWR | O_NOCTTY)) > 0)
+               {
+                       struct termios tios;
+                       int rts = TIOCM_RTS;
+                       double value;
+
+                       tios.c_cflag = B1200 | CS7 | CSTOPB | CREAD | CLOCAL;
+                       tios.c_iflag = IGNBRK | IGNPAR;
+                       tios.c_oflag = 0;
+                       tios.c_lflag = 0;
+                       tios.c_cc[VTIME] = 3;
+                       tios.c_cc[VMIN]  = LINE_LENGTH;
+
+                       tcflush(fd, TCIFLUSH);
+                       tcsetattr(fd, TCSANOW, &tios);
+                       ioctl(fd, TIOCMBIC, &rts);
+                       
+                       if (multimeter_read_value (&value) < -1)
+                       {
+                               close (fd);
+                               fd = -1;
+                       }
+                       else
+                       {
+                               INFO ("multimeter plugin: Device "
+                                               "found at %s", device);
+                               return (0);
+                       }
+               }
+       }
+
+       ERROR ("multimeter plugin: No device found");
+       return (-1);
+}
+#undef LINE_LENGTH
+
+static void multimeter_submit (double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "multimeter", sizeof (vl.plugin));
+       sstrncpy (vl.type, "multimeter", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int multimeter_read (void)
+{
+       double value;
+
+       if (fd < 0)
+               return (-1);
+
+       if (multimeter_read_value (&value) != 0)
+               return (-1);
+
+       multimeter_submit (value);
+       return (0);
+} /* int multimeter_read */
+
+static int multimeter_shutdown (void)
+{
+       if (fd >= 0)
+       {
+               close (fd);
+               fd = -1;
+       }
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_init ("multimeter", multimeter_init);
+       plugin_register_read ("multimeter", multimeter_read);
+       plugin_register_shutdown ("multimeter", multimeter_shutdown);
+} /* void module_register */
diff --git a/src/mysql.c b/src/mysql.c
new file mode 100644 (file)
index 0000000..00cba09
--- /dev/null
@@ -0,0 +1,957 @@
+/**
+ * collectd - src/mysql.c
+ * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2008       Mirko Buffoni
+ * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2009       Sebastian tokkee Harl
+ * Copyright (C) 2009       Rodolphe Quiédeville
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Mirko Buffoni <briareos at eswat.org>
+ *   Doug MacEachern <dougm at hyperic.com>
+ *   Sebastian tokkee Harl <sh at tokkee.org>
+ *   Rodolphe Quiédeville <rquiedeville at bearstech.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#ifdef HAVE_MYSQL_H
+#include <mysql.h>
+#elif defined(HAVE_MYSQL_MYSQL_H)
+#include <mysql/mysql.h>
+#endif
+
+struct mysql_database_s /* {{{ */
+{
+       char *instance;
+       char *alias;
+       char *host;
+       char *user;
+       char *pass;
+       char *database;
+       char *socket;
+       int   port;
+       int   timeout;
+
+       _Bool master_stats;
+       _Bool slave_stats;
+       _Bool innodb_stats;
+
+       _Bool slave_notif;
+       _Bool slave_io_running;
+       _Bool slave_sql_running;
+
+       MYSQL *con;
+       _Bool  is_connected;
+};
+typedef struct mysql_database_s mysql_database_t; /* }}} */
+
+static int mysql_read (user_data_t *ud);
+
+void mysql_read_default_options(struct st_mysql_options *options,
+               const char *filename,const char *group);
+
+static void mysql_database_free (void *arg) /* {{{ */
+{
+       mysql_database_t *db;
+
+       DEBUG ("mysql plugin: mysql_database_free (arg = %p);", arg);
+
+       db = (mysql_database_t *) arg;
+
+       if (db == NULL)
+               return;
+
+       if (db->con != NULL)
+               mysql_close (db->con);
+
+       sfree (db->alias);
+       sfree (db->host);
+       sfree (db->user);
+       sfree (db->pass);
+       sfree (db->socket);
+       sfree (db->instance);
+       sfree (db->database);
+       sfree (db);
+} /* }}} void mysql_database_free */
+
+/* Configuration handling functions {{{
+ *
+ * <Plugin mysql>
+ *   <Database "plugin_instance1">
+ *     Host "localhost"
+ *     Port 22000
+ *     ...
+ *   </Database>
+ * </Plugin>
+ */
+static int mysql_config_database (oconfig_item_t *ci) /* {{{ */
+{
+       mysql_database_t *db;
+       int status = 0;
+       int i;
+
+       if ((ci->values_num != 1)
+           || (ci->values[0].type != OCONFIG_TYPE_STRING))
+       {
+               WARNING ("mysql plugin: The `Database' block "
+                        "needs exactly one string argument.");
+               return (-1);
+       }
+
+       db = (mysql_database_t *) malloc (sizeof (*db));
+       if (db == NULL)
+       {
+               ERROR ("mysql plugin: malloc failed.");
+               return (-1);
+       }
+       memset (db, 0, sizeof (*db));
+
+       /* initialize all the pointers */
+       db->alias    = NULL;
+       db->host     = NULL;
+       db->user     = NULL;
+       db->pass     = NULL;
+       db->database = NULL;
+       db->socket   = NULL;
+       db->con      = NULL;
+       db->timeout  = 0;
+
+       /* trigger a notification, if it's not running */
+       db->slave_io_running  = 1;
+       db->slave_sql_running = 1;
+
+       status = cf_util_get_string (ci, &db->instance);
+       if (status != 0)
+       {
+               sfree (db);
+               return (status);
+       }
+       assert (db->instance != NULL);
+
+       /* Fill the `mysql_database_t' structure.. */
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Alias", child->key) == 0)
+                       status = cf_util_get_string (child, &db->alias);
+               else if (strcasecmp ("Host", child->key) == 0)
+                       status = cf_util_get_string (child, &db->host);
+               else if (strcasecmp ("User", child->key) == 0)
+                       status = cf_util_get_string (child, &db->user);
+               else if (strcasecmp ("Password", child->key) == 0)
+                       status = cf_util_get_string (child, &db->pass);
+               else if (strcasecmp ("Port", child->key) == 0)
+               {
+                       status = cf_util_get_port_number (child);
+                       if (status > 0)
+                       {
+                               db->port = status;
+                               status = 0;
+                       }
+               }
+               else if (strcasecmp ("Socket", child->key) == 0)
+                       status = cf_util_get_string (child, &db->socket);
+               else if (strcasecmp ("Database", child->key) == 0)
+                       status = cf_util_get_string (child, &db->database);
+               else if (strcasecmp ("ConnectTimeout", child->key) == 0)
+                       status = cf_util_get_int (child, &db->timeout);
+               else if (strcasecmp ("MasterStats", child->key) == 0)
+                       status = cf_util_get_boolean (child, &db->master_stats);
+               else if (strcasecmp ("SlaveStats", child->key) == 0)
+                       status = cf_util_get_boolean (child, &db->slave_stats);
+               else if (strcasecmp ("SlaveNotifications", child->key) == 0)
+                       status = cf_util_get_boolean (child, &db->slave_notif);
+               else if (strcasecmp ("InnodbStats", child->key) == 0)
+                       status = cf_util_get_boolean (child, &db->innodb_stats);
+               else
+               {
+                       WARNING ("mysql plugin: Option `%s' not allowed here.", child->key);
+                       status = -1;
+               }
+
+               if (status != 0)
+                       break;
+       }
+
+       /* If all went well, register this database for reading */
+       if (status == 0)
+       {
+               user_data_t ud;
+               char cb_name[DATA_MAX_NAME_LEN];
+
+               DEBUG ("mysql plugin: Registering new read callback: %s",
+                               (db->database != NULL) ? db->database : "<default>");
+
+               memset (&ud, 0, sizeof (ud));
+               ud.data = (void *) db;
+               ud.free_func = mysql_database_free;
+
+               if (db->instance != NULL)
+                       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 = */ NULL, &ud);
+       }
+       else
+       {
+               mysql_database_free (db);
+               return (-1);
+       }
+
+       return (0);
+} /* }}} int mysql_config_database */
+
+static int mysql_config (oconfig_item_t *ci) /* {{{ */
+{
+       int i;
+
+       if (ci == NULL)
+               return (EINVAL);
+
+       /* Fill the `mysql_database_t' structure.. */
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Database", child->key) == 0)
+                       mysql_config_database (child);
+               else
+                       WARNING ("mysql plugin: Option \"%s\" not allowed here.",
+                                       child->key);
+       }
+
+       return (0);
+} /* }}} int mysql_config */
+
+/* }}} End of configuration handling functions */
+
+static MYSQL *getconnection (mysql_database_t *db)
+{
+       if (db->is_connected)
+       {
+               int status;
+
+               status = mysql_ping (db->con);
+               if (status == 0)
+                       return (db->con);
+
+               WARNING ("mysql plugin: Lost connection to instance \"%s\": %s",
+                               db->instance, mysql_error (db->con));
+       }
+       db->is_connected = 0;
+
+       if (db->con == NULL)
+       {
+               db->con = mysql_init (NULL);
+               if (db->con == NULL)
+               {
+                       ERROR ("mysql plugin: mysql_init failed: %s",
+                                       mysql_error (db->con));
+                       return (NULL);
+               }
+       }
+
+       /* Configure TCP connect timeout (default: 0) */
+       db->con->options.connect_timeout = db->timeout;
+
+       if (mysql_real_connect (db->con, db->host, db->user, db->pass,
+                               db->database, db->port, db->socket, 0) == NULL)
+       {
+               ERROR ("mysql plugin: Failed to connect to database %s "
+                               "at server %s: %s",
+                               (db->database != NULL) ? db->database : "<none>",
+                               (db->host != NULL) ? db->host : "localhost",
+                               mysql_error (db->con));
+               return (NULL);
+       }
+
+       INFO ("mysql plugin: Successfully connected to database %s "
+                       "at server %s (server version: %s, protocol version: %d)",
+                       (db->database != NULL) ? db->database : "<none>",
+                       mysql_get_host_info (db->con),
+                       mysql_get_server_info (db->con),
+                       mysql_get_proto_info (db->con));
+
+       db->is_connected = 1;
+       return (db->con);
+} /* static MYSQL *getconnection (mysql_database_t *db) */
+
+static void set_host (mysql_database_t *db, char *buf, size_t buflen)
+{
+       if (db->alias)
+               sstrncpy (buf, db->alias, buflen);
+       else if ((db->host == NULL)
+                       || (strcmp ("", db->host) == 0)
+                       || (strcmp ("127.0.0.1", db->host) == 0)
+                       || (strcmp ("localhost", db->host) == 0))
+               sstrncpy (buf, hostname_g, buflen);
+       else
+               sstrncpy (buf, db->host, buflen);
+} /* void set_host */
+
+static void submit (const char *type, const char *type_instance,
+               value_t *values, size_t values_len, mysql_database_t *db)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values     = values;
+       vl.values_len = values_len;
+
+       set_host (db, vl.host, sizeof (vl.host));
+
+       sstrncpy (vl.plugin, "mysql", sizeof (vl.plugin));
+
+       /* Assured by "mysql_config_database" */
+       assert (db->instance != NULL);
+       sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
+
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* submit */
+
+static void counter_submit (const char *type, const char *type_instance,
+               derive_t value, mysql_database_t *db)
+{
+       value_t values[1];
+
+       values[0].derive = value;
+       submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
+} /* void counter_submit */
+
+static void gauge_submit (const char *type, const char *type_instance,
+               gauge_t value, mysql_database_t *db)
+{
+       value_t values[1];
+
+       values[0].gauge = value;
+       submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
+} /* void gauge_submit */
+
+static void derive_submit (const char *type, const char *type_instance,
+               derive_t value, mysql_database_t *db)
+{
+       value_t values[1];
+
+       values[0].derive = value;
+       submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db);
+} /* void derive_submit */
+
+static void traffic_submit (derive_t rx, derive_t tx, mysql_database_t *db)
+{
+       value_t values[2];
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       submit ("mysql_octets", NULL, values, STATIC_ARRAY_SIZE (values), db);
+} /* void traffic_submit */
+
+static MYSQL_RES *exec_query (MYSQL *con, const char *query)
+{
+       MYSQL_RES *res;
+
+       int query_len = strlen (query);
+
+       if (mysql_real_query (con, query, query_len))
+       {
+               ERROR ("mysql plugin: Failed to execute query: %s",
+                               mysql_error (con));
+               INFO ("mysql plugin: SQL query was: %s", query);
+               return (NULL);
+       }
+
+       res = mysql_store_result (con);
+       if (res == NULL)
+       {
+               ERROR ("mysql plugin: Failed to store query result: %s",
+                               mysql_error (con));
+               INFO ("mysql plugin: SQL query was: %s", query);
+               return (NULL);
+       }
+
+       return (res);
+} /* exec_query */
+
+static int mysql_read_master_stats (mysql_database_t *db, MYSQL *con)
+{
+       MYSQL_RES *res;
+       MYSQL_ROW  row;
+
+       char *query;
+       int   field_num;
+       unsigned long long position;
+
+       query = "SHOW MASTER STATUS";
+
+       res = exec_query (con, query);
+       if (res == NULL)
+               return (-1);
+
+       row = mysql_fetch_row (res);
+       if (row == NULL)
+       {
+               ERROR ("mysql plugin: Failed to get master statistics: "
+                               "`%s' did not return any rows.", query);
+               mysql_free_result (res);
+               return (-1);
+       }
+
+       field_num = mysql_num_fields (res);
+       if (field_num < 2)
+       {
+               ERROR ("mysql plugin: Failed to get master statistics: "
+                               "`%s' returned less than two columns.", query);
+               mysql_free_result (res);
+               return (-1);
+       }
+
+       position = atoll (row[1]);
+       counter_submit ("mysql_log_position", "master-bin", position, db);
+
+       row = mysql_fetch_row (res);
+       if (row != NULL)
+               WARNING ("mysql plugin: `%s' returned more than one row - "
+                               "ignoring further results.", query);
+
+       mysql_free_result (res);
+
+       return (0);
+} /* mysql_read_master_stats */
+
+static int mysql_read_slave_stats (mysql_database_t *db, MYSQL *con)
+{
+       MYSQL_RES *res;
+       MYSQL_ROW  row;
+
+       char *query;
+       int   field_num;
+
+       /* WTF? libmysqlclient does not seem to provide any means to
+        * translate a column name to a column index ... :-/ */
+       const int READ_MASTER_LOG_POS_IDX   = 6;
+       const int SLAVE_IO_RUNNING_IDX      = 10;
+       const int SLAVE_SQL_RUNNING_IDX     = 11;
+       const int EXEC_MASTER_LOG_POS_IDX   = 21;
+       const int SECONDS_BEHIND_MASTER_IDX = 32;
+
+       query = "SHOW SLAVE STATUS";
+
+       res = exec_query (con, query);
+       if (res == NULL)
+               return (-1);
+
+       row = mysql_fetch_row (res);
+       if (row == NULL)
+       {
+               ERROR ("mysql plugin: Failed to get slave statistics: "
+                               "`%s' did not return any rows.", query);
+               mysql_free_result (res);
+               return (-1);
+       }
+
+       field_num = mysql_num_fields (res);
+       if (field_num < 33)
+       {
+               ERROR ("mysql plugin: Failed to get slave statistics: "
+                               "`%s' returned less than 33 columns.", query);
+               mysql_free_result (res);
+               return (-1);
+       }
+
+       if (db->slave_stats)
+       {
+               unsigned long long counter;
+               double gauge;
+
+               counter = atoll (row[READ_MASTER_LOG_POS_IDX]);
+               counter_submit ("mysql_log_position", "slave-read", counter, db);
+
+               counter = atoll (row[EXEC_MASTER_LOG_POS_IDX]);
+               counter_submit ("mysql_log_position", "slave-exec", counter, db);
+
+               if (row[SECONDS_BEHIND_MASTER_IDX] != NULL)
+               {
+                       gauge = atof (row[SECONDS_BEHIND_MASTER_IDX]);
+                       gauge_submit ("time_offset", NULL, gauge, db);
+               }
+       }
+
+       if (db->slave_notif)
+       {
+               notification_t n = { 0, cdtime (), "", "",
+                       "mysql", "", "time_offset", "", NULL };
+
+               char *io, *sql;
+
+               io  = row[SLAVE_IO_RUNNING_IDX];
+               sql = row[SLAVE_SQL_RUNNING_IDX];
+
+               set_host (db, n.host, sizeof (n.host));
+
+               /* Assured by "mysql_config_database" */
+               assert (db->instance != NULL);
+               sstrncpy (n.plugin_instance, db->instance, sizeof (n.plugin_instance));
+
+               if (((io == NULL) || (strcasecmp (io, "yes") != 0))
+                               && (db->slave_io_running))
+               {
+                       n.severity = NOTIF_WARNING;
+                       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 = 0;
+               }
+               else if (((io != NULL) && (strcasecmp (io, "yes") == 0))
+                               && (! db->slave_io_running))
+               {
+                       n.severity = NOTIF_OKAY;
+                       ssnprintf (n.message, sizeof (n.message),
+                                       "slave I/O thread started and connected to master");
+                       plugin_dispatch_notification (&n);
+                       db->slave_io_running = 1;
+               }
+
+               if (((sql == NULL) || (strcasecmp (sql, "yes") != 0))
+                               && (db->slave_sql_running))
+               {
+                       n.severity = NOTIF_WARNING;
+                       ssnprintf (n.message, sizeof (n.message),
+                                       "slave SQL thread not started");
+                       plugin_dispatch_notification (&n);
+                       db->slave_sql_running = 0;
+               }
+               else if (((sql != NULL) && (strcasecmp (sql, "yes") == 0))
+                               && (! db->slave_sql_running))
+               {
+                       n.severity = NOTIF_OKAY;
+                       ssnprintf (n.message, sizeof (n.message),
+                                       "slave SQL thread started");
+                       plugin_dispatch_notification (&n);
+                       db->slave_sql_running = 1;
+               }
+       }
+
+       row = mysql_fetch_row (res);
+       if (row != NULL)
+               WARNING ("mysql plugin: `%s' returned more than one row - "
+                               "ignoring further results.", query);
+
+       mysql_free_result (res);
+
+       return (0);
+} /* mysql_read_slave_stats */
+
+static int mysql_read_innodb_stats (mysql_database_t *db, MYSQL *con)
+{
+       MYSQL_RES *res;
+       MYSQL_ROW  row;
+
+       char *query;
+    struct {
+        char *key;
+        char *type;
+        int ds_type;
+    } metrics[] = {
+        { "metadata_mem_pool_size",         "bytes",        DS_TYPE_GAUGE },
+        { "lock_deadlocks",                 "mysql_locks",  DS_TYPE_DERIVE },
+        { "lock_timeouts",                  "mysql_locks",  DS_TYPE_DERIVE },
+        { "lock_row_lock_current_waits",    "mysql_locks",  DS_TYPE_DERIVE },
+        { "buffer_pool_size",               "bytes",        DS_TYPE_GAUGE },
+
+        { "buffer_pool_reads",              "operations",   DS_TYPE_DERIVE },
+        { "buffer_pool_read_requests",      "operations",   DS_TYPE_DERIVE },
+        { "buffer_pool_write_requests",     "operations",   DS_TYPE_DERIVE },
+        { "buffer_pool_wait_free",          "operations",   DS_TYPE_DERIVE },
+        { "buffer_pool_read_ahead",         "operations",   DS_TYPE_DERIVE },
+        { "buffer_pool_read_ahead_evicted", "operations",   DS_TYPE_DERIVE },
+
+        { "buffer_pool_pages_total",        "gauge",        DS_TYPE_GAUGE },
+        { "buffer_pool_pages_misc",         "gauge",        DS_TYPE_GAUGE },
+        { "buffer_pool_pages_data",         "gauge",        DS_TYPE_GAUGE },
+        { "buffer_pool_bytes_data",         "gauge",        DS_TYPE_GAUGE },
+        { "buffer_pool_pages_dirty",        "gauge",        DS_TYPE_GAUGE },
+        { "buffer_pool_bytes_dirty",        "gauge",        DS_TYPE_GAUGE },
+        { "buffer_pool_pages_free",         "gauge",        DS_TYPE_GAUGE },
+
+        { "buffer_pages_created",           "operations",   DS_TYPE_DERIVE },
+        { "buffer_pages_written",           "operations",   DS_TYPE_DERIVE },
+        { "buffer_pages_read",              "operations",   DS_TYPE_DERIVE },
+        { "buffer_data_reads",              "operations",   DS_TYPE_DERIVE },
+        { "buffer_data_written",            "operations",   DS_TYPE_DERIVE },
+
+        { "os_data_reads",                  "operations",   DS_TYPE_DERIVE },
+        { "os_data_writes",                 "operations",   DS_TYPE_DERIVE },
+        { "os_data_fsyncs",                 "operations",   DS_TYPE_DERIVE },
+        { "os_log_bytes_written",           "operations",   DS_TYPE_DERIVE },
+        { "os_log_fsyncs",                  "operations",   DS_TYPE_DERIVE },
+        { "os_log_pending_fsyncs",          "operations",   DS_TYPE_DERIVE },
+        { "os_log_pending_writes",          "operations",   DS_TYPE_DERIVE },
+
+        { "trx_rseg_history_len",           "gauge",        DS_TYPE_GAUGE },
+
+        { "log_waits",                      "operations",   DS_TYPE_DERIVE },
+        { "log_write_requests",             "operations",   DS_TYPE_DERIVE },
+        { "log_writes",                     "operations",   DS_TYPE_DERIVE },
+        { "adaptive_hash_searches",         "operations",   DS_TYPE_DERIVE },
+
+        { "file_num_open_files",            "gauge",        DS_TYPE_GAUGE },
+
+        { "ibuf_merges_insert",             "operations",   DS_TYPE_DERIVE },
+        { "ibuf_merges_delete_mark",        "operations",   DS_TYPE_DERIVE },
+        { "ibuf_merges_delete",             "operations",   DS_TYPE_DERIVE },
+        { "ibuf_merges_discard_insert",     "operations",   DS_TYPE_DERIVE },
+        { "ibuf_merges_discard_delete_mark","operations",   DS_TYPE_DERIVE },
+        { "ibuf_merges_discard_delete",     "operations",   DS_TYPE_DERIVE },
+        { "ibuf_merges_discard_merges",     "operations",   DS_TYPE_DERIVE },
+        { "ibuf_size",                      "bytes",        DS_TYPE_GAUGE },
+
+        { "innodb_activity_count",          "gauge",        DS_TYPE_GAUGE },
+        { "innodb_dblwr_writes",            "operations",   DS_TYPE_DERIVE },
+        { "innodb_dblwr_pages_written",     "operations",   DS_TYPE_DERIVE },
+        { "innodb_dblwr_page_size",         "gauge",        DS_TYPE_GAUGE },
+
+        { "innodb_rwlock_s_spin_waits",     "operations",   DS_TYPE_DERIVE },
+        { "innodb_rwlock_x_spin_waits",     "operations",   DS_TYPE_DERIVE },
+        { "innodb_rwlock_s_spin_rounds",    "operations",   DS_TYPE_DERIVE },
+        { "innodb_rwlock_x_spin_rounds",    "operations",   DS_TYPE_DERIVE },
+        { "innodb_rwlock_s_os_waits",       "operations",   DS_TYPE_DERIVE },
+        { "innodb_rwlock_x_os_waits",       "operations",   DS_TYPE_DERIVE },
+
+        { "dml_reads",                      "operations",   DS_TYPE_DERIVE },
+        { "dml_inserts",                    "operations",   DS_TYPE_DERIVE },
+        { "dml_deletes",                    "operations",   DS_TYPE_DERIVE },
+        { "dml_updates",                    "operations",   DS_TYPE_DERIVE },
+
+        { NULL,                     NULL,           0}
+    };
+
+       query = "SELECT name, count, type FROM information_schema.innodb_metrics WHERE status = 'enabled'";
+
+       res = exec_query (con, query);
+       if (res == NULL)
+               return (-1);
+
+       while ((row = mysql_fetch_row (res)))
+       {
+        int i;
+               char *key;
+               unsigned long long val;
+
+               key = row[0];
+               val = atoll (row[1]);
+
+        for (i = 0;
+             metrics[i].key != NULL && strcmp(metrics[i].key, key) != 0;
+             i++)
+            ;
+
+        if (metrics[i].key == NULL)
+            continue;
+
+        switch (metrics[i].ds_type) {
+        case DS_TYPE_COUNTER:
+            counter_submit(metrics[i].type, key, (counter_t)val, db);
+            break;
+        case DS_TYPE_GAUGE:
+            gauge_submit(metrics[i].type, key, (gauge_t)val, db);
+            break;
+        case DS_TYPE_DERIVE:
+            derive_submit(metrics[i].type, key, (derive_t)val, db);
+            break;
+        }
+    }
+
+    mysql_free_result(res);
+    return (0);
+}
+
+static int mysql_read (user_data_t *ud)
+{
+       mysql_database_t *db;
+       MYSQL     *con;
+       MYSQL_RES *res;
+       MYSQL_ROW  row;
+       char      *query;
+
+       derive_t qcache_hits          = 0;
+       derive_t qcache_inserts       = 0;
+       derive_t qcache_not_cached    = 0;
+       derive_t qcache_lowmem_prunes = 0;
+       gauge_t qcache_queries_in_cache = NAN;
+
+       gauge_t threads_running   = NAN;
+       gauge_t threads_connected = NAN;
+       gauge_t threads_cached    = NAN;
+       derive_t threads_created = 0;
+
+       unsigned long long traffic_incoming = 0ULL;
+       unsigned long long traffic_outgoing = 0ULL;
+    unsigned long mysql_version = 0ULL;
+
+       if ((ud == NULL) || (ud->data == NULL))
+       {
+               ERROR ("mysql plugin: mysql_database_read: Invalid user data.");
+               return (-1);
+       }
+
+       db = (mysql_database_t *) ud->data;
+
+       /* An error message will have been printed in this case */
+       if ((con = getconnection (db)) == NULL)
+               return (-1);
+
+  mysql_version = mysql_get_server_version(con);
+
+       query = "SHOW STATUS";
+       if (mysql_version >= 50002)
+               query = "SHOW GLOBAL STATUS";
+
+       res = exec_query (con, query);
+       if (res == NULL)
+               return (-1);
+
+       while ((row = mysql_fetch_row (res)))
+       {
+               char *key;
+               unsigned long long val;
+
+               key = row[0];
+               val = atoll (row[1]);
+
+               if (strncmp (key, "Com_", 
+                                 strlen ("Com_")) == 0)
+               {
+                       if (val == 0ULL)
+                               continue;
+
+                       /* Ignore `prepared statements' */
+                       if (strncmp (key, "Com_stmt_", strlen ("Com_stmt_")) != 0)
+                               counter_submit ("mysql_commands", 
+                                               key + strlen ("Com_"), 
+                                               val, db);
+               }
+               else if (strncmp (key, "Handler_", 
+                                       strlen ("Handler_")) == 0)
+               {
+                       if (val == 0ULL)
+                               continue;
+
+                       counter_submit ("mysql_handler", 
+                                       key + strlen ("Handler_"), 
+                                       val, db);
+               }
+               else if (strncmp (key, "Qcache_",
+                                               strlen ("Qcache_")) == 0)
+               {
+                       if (strcmp (key, "Qcache_hits") == 0)
+                               qcache_hits = (derive_t) val;
+                       else if (strcmp (key, "Qcache_inserts") == 0)
+                               qcache_inserts = (derive_t) val;
+                       else if (strcmp (key, "Qcache_not_cached") == 0)
+                               qcache_not_cached = (derive_t) val;
+                       else if (strcmp (key, "Qcache_lowmem_prunes") == 0)
+                               qcache_lowmem_prunes = (derive_t) val;
+                       else if (strcmp (key, "Qcache_queries_in_cache") == 0)
+                               qcache_queries_in_cache = (gauge_t) val;
+               }
+               else if (strncmp (key, "Bytes_", 
+                                       strlen ("Bytes_")) == 0)
+               {
+                       if (strcmp (key, "Bytes_received") == 0)
+                               traffic_incoming += val;
+                       else if (strcmp (key, "Bytes_sent") == 0)
+                               traffic_outgoing += val;
+               }
+               else if (strncmp (key, "Threads_", 
+                                               strlen ("Threads_")) == 0)
+               {
+                       if (strcmp (key, "Threads_running") == 0)
+                               threads_running = (gauge_t) val;
+                       else if (strcmp (key, "Threads_connected") == 0)
+                               threads_connected = (gauge_t) val;
+                       else if (strcmp (key, "Threads_cached") == 0)
+                               threads_cached = (gauge_t) val;
+                       else if (strcmp (key, "Threads_created") == 0)
+                               threads_created = (derive_t) val;
+               }
+               else if (strncmp (key, "Table_locks_",
+                                       strlen ("Table_locks_")) == 0)
+               {
+                       counter_submit ("mysql_locks",
+                                       key + strlen ("Table_locks_"),
+                                       val, db);
+               }
+               else if (db->innodb_stats && strncmp (key, "Innodb_", strlen ("Innodb_")) == 0)
+               {
+                       /* buffer pool */
+                       if (strcmp (key, "Innodb_buffer_pool_pages_data") == 0)
+                               gauge_submit ("mysql_bpool_pages", "data", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_pages_dirty") == 0)
+                               gauge_submit ("mysql_bpool_pages", "dirty", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_pages_flushed") == 0)
+                               counter_submit ("mysql_bpool_pages", "flushed", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_pages_free") == 0)
+                               gauge_submit ("mysql_bpool_pages", "free", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_pages_misc") == 0)
+                               gauge_submit ("mysql_bpool_pages", "misc", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_pages_total") == 0)
+                               gauge_submit ("mysql_bpool_pages", "total", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_read_ahead_rnd") == 0)
+                               counter_submit ("mysql_bpool_counters", "read_ahead_rnd", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_read_ahead") == 0)
+                               counter_submit ("mysql_bpool_counters", "read_ahead", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_read_ahead_evicted") == 0)
+                               counter_submit ("mysql_bpool_counters", "read_ahead_evicted", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_read_requests") == 0)
+                               counter_submit ("mysql_bpool_counters", "read_requests", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_reads") == 0)
+                               counter_submit ("mysql_bpool_counters", "reads", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_write_requests") == 0)
+                               counter_submit ("mysql_bpool_counters", "write_requests", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_bytes_data") == 0)
+                               gauge_submit ("mysql_bpool_bytes", "data", val, db);
+                       else if (strcmp (key, "Innodb_buffer_pool_bytes_dirty") == 0)
+                               gauge_submit ("mysql_bpool_bytes", "dirty", val, db);
+
+                       /* data */
+                       if (strcmp (key, "Innodb_data_fsyncs") == 0)
+                               counter_submit ("mysql_innodb_data", "fsyncs", val, db);
+                       else if (strcmp (key, "Innodb_data_read") == 0)
+                               counter_submit ("mysql_innodb_data", "read", val, db);
+                       else if (strcmp (key, "Innodb_data_reads") == 0)
+                               counter_submit ("mysql_innodb_data", "reads", val, db);
+                       else if (strcmp (key, "Innodb_data_writes") == 0)
+                               counter_submit ("mysql_innodb_data", "writes", val, db);
+                       else if (strcmp (key, "Innodb_data_written") == 0)
+                               counter_submit ("mysql_innodb_data", "written", val, db);
+
+                       /* double write */
+                       else if (strcmp (key, "Innodb_dblwr_writes") == 0)
+                               counter_submit ("mysql_innodb_dblwr", "writes", val, db);
+                       else if (strcmp (key, "Innodb_dblwr_pages_written") == 0)
+                               counter_submit ("mysql_innodb_dblwr", "written", val, db);
+
+                       /* log */
+                       else if (strcmp (key, "Innodb_log_waits") == 0)
+                               counter_submit ("mysql_innodb_log", "waits", val, db);
+                       else if (strcmp (key, "Innodb_log_write_requests") == 0)
+                               counter_submit ("mysql_innodb_log", "write_requests", val, db);
+                       else if (strcmp (key, "Innodb_log_writes") == 0)
+                               counter_submit ("mysql_innodb_log", "writes", val, db);
+                       else if (strcmp (key, "Innodb_os_log_fsyncs") == 0)
+                               counter_submit ("mysql_innodb_log", "fsyncs", val, db);
+                       else if (strcmp (key, "Innodb_os_log_written") == 0)
+                               counter_submit ("mysql_innodb_log", "written", val, db);
+
+                       /* pages */
+                       else if (strcmp (key, "Innodb_pages_created") == 0)
+                               counter_submit ("mysql_innodb_pages", "created", val, db);
+                       else if (strcmp (key, "Innodb_pages_read") == 0)
+                               counter_submit ("mysql_innodb_pages", "read", val, db);
+                       else if (strcmp (key, "Innodb_pages_written") == 0)
+                               counter_submit ("mysql_innodb_pages", "written", val, db);
+
+                       /* row lock */
+                       else if (strcmp (key, "Innodb_row_lock_time") == 0)
+                               counter_submit ("mysql_innodb_row_lock", "time", val, db);
+                       else if (strcmp (key, "Innodb_row_lock_waits") == 0)
+                               counter_submit ("mysql_innodb_row_lock", "waits", val, db);
+
+                       /* rows */
+                       else if (strcmp (key, "Innodb_rows_deleted") == 0)
+                               counter_submit ("mysql_innodb_rows", "deleted", val, db);
+                       else if (strcmp (key, "Innodb_rows_inserted") == 0)
+                               counter_submit ("mysql_innodb_rows", "inserted", val, db);
+                       else if (strcmp (key, "Innodb_rows_read") == 0)
+                               counter_submit ("mysql_innodb_rows", "read", val, db);
+                       else if (strcmp (key, "Innodb_rows_updated") == 0)
+                               counter_submit ("mysql_innodb_rows", "updated", val, db);
+               }
+               else if (strncmp (key, "Select_", strlen ("Select_")) == 0)
+               {
+                       counter_submit ("mysql_select", key + strlen ("Select_"),
+                                       val, db);
+               }
+               else if (strncmp (key, "Sort_", strlen ("Sort_")) == 0)
+               {
+                       counter_submit ("mysql_sort", key + strlen ("Sort_"),
+                                       val, db);
+               }
+       }
+       mysql_free_result (res); res = NULL;
+
+       if ((qcache_hits != 0)
+                       || (qcache_inserts != 0)
+                       || (qcache_not_cached != 0)
+                       || (qcache_lowmem_prunes != 0))
+       {
+               derive_submit ("cache_result", "qcache-hits",
+                               qcache_hits, db);
+               derive_submit ("cache_result", "qcache-inserts",
+                               qcache_inserts, db);
+               derive_submit ("cache_result", "qcache-not_cached",
+                               qcache_not_cached, db);
+               derive_submit ("cache_result", "qcache-prunes",
+                               qcache_lowmem_prunes, db);
+
+               gauge_submit ("cache_size", "qcache",
+                               qcache_queries_in_cache, db);
+       }
+
+       if (threads_created != 0)
+       {
+               gauge_submit ("threads", "running",
+                               threads_running, db);
+               gauge_submit ("threads", "connected",
+                               threads_connected, db);
+               gauge_submit ("threads", "cached",
+                               threads_cached, db);
+
+               derive_submit ("total_threads", "created",
+                               threads_created, db);
+       }
+
+       traffic_submit  (traffic_incoming, traffic_outgoing, db);
+
+       if (mysql_version >= 50600 && db->innodb_stats)
+        mysql_read_innodb_stats (db, con);
+
+       if (db->master_stats)
+               mysql_read_master_stats (db, con);
+
+       if ((db->slave_stats) || (db->slave_notif))
+               mysql_read_slave_stats (db, con);
+
+       return (0);
+} /* int mysql_read */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("mysql", mysql_config);
+} /* void module_register */
diff --git a/src/netapp.c b/src/netapp.c
new file mode 100644 (file)
index 0000000..f446d59
--- /dev/null
@@ -0,0 +1,3207 @@
+/**
+ * collectd - src/netapp.c
+ * Copyright (C) 2009,2010  Sven Trenkel
+ * Copyright (C) 2012-2013  teamix GmbH
+ *
+ * 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:
+ *   Sven Trenkel <collectd at semidefinite.de>
+ *   Sebastian 'tokkee' Harl <sh@teamix.net>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_ignorelist.h"
+
+#include <netapp_api.h>
+#include <netapp_errno.h>
+
+#define HAS_ALL_FLAGS(has,needs) (((has) & (needs)) == (needs))
+
+typedef struct host_config_s host_config_t;
+typedef void service_handler_t(host_config_t *host, na_elem_t *result, void *data);
+
+struct cna_interval_s
+{
+       cdtime_t interval;
+       cdtime_t last_read;
+};
+typedef struct cna_interval_s cna_interval_t;
+
+/*! Data types for WAFL statistics {{{
+ *
+ * \brief Persistent data for WAFL performance counters. (a.k.a. cache performance)
+ *
+ * The cache counters use old counter values to calculate a hit ratio for each
+ * counter. The "cfg_wafl_t" struct therefore contains old counter values along
+ * with flags, which are set if the counter is valid.
+ *
+ * The function "cna_handle_wafl_data" will fill a new structure of this kind
+ * with new values, then pass both, new and old data, to "submit_wafl_data".
+ * That function calculates the hit ratios, submits the calculated values and
+ * updates the old counter values for the next iteration.
+ */
+#define CFG_WAFL_NAME_CACHE        0x0001
+#define CFG_WAFL_DIR_CACHE         0x0002
+#define CFG_WAFL_BUF_CACHE         0x0004
+#define CFG_WAFL_INODE_CACHE       0x0008
+#define CFG_WAFL_ALL               0x000F
+#define HAVE_WAFL_NAME_CACHE_HIT   0x0100
+#define HAVE_WAFL_NAME_CACHE_MISS  0x0200
+#define HAVE_WAFL_NAME_CACHE       (HAVE_WAFL_NAME_CACHE_HIT | HAVE_WAFL_NAME_CACHE_MISS)
+#define HAVE_WAFL_FIND_DIR_HIT     0x0400
+#define HAVE_WAFL_FIND_DIR_MISS    0x0800
+#define HAVE_WAFL_FIND_DIR         (HAVE_WAFL_FIND_DIR_HIT | HAVE_WAFL_FIND_DIR_MISS)
+#define HAVE_WAFL_BUF_HASH_HIT     0x1000
+#define HAVE_WAFL_BUF_HASH_MISS    0x2000
+#define HAVE_WAFL_BUF_HASH         (HAVE_WAFL_BUF_HASH_HIT | HAVE_WAFL_BUF_HASH_MISS)
+#define HAVE_WAFL_INODE_CACHE_HIT  0x4000
+#define HAVE_WAFL_INODE_CACHE_MISS 0x8000
+#define HAVE_WAFL_INODE_CACHE      (HAVE_WAFL_INODE_CACHE_HIT | HAVE_WAFL_INODE_CACHE_MISS)
+#define HAVE_WAFL_ALL              0xff00
+typedef struct {
+       uint32_t flags;
+       cna_interval_t interval;
+       na_elem_t *query;
+
+       cdtime_t timestamp;
+       uint64_t name_cache_hit;
+       uint64_t name_cache_miss;
+       uint64_t find_dir_hit;
+       uint64_t find_dir_miss;
+       uint64_t buf_hash_hit;
+       uint64_t buf_hash_miss;
+       uint64_t inode_cache_hit;
+       uint64_t inode_cache_miss;
+} cfg_wafl_t;
+/* }}} cfg_wafl_t */
+
+/*! Data types for disk statistics {{{
+ *
+ * \brief A disk in the NetApp.
+ *
+ * A disk doesn't have any more information than its name at the moment.
+ * The name includes the "disk_" prefix.
+ */
+#define HAVE_DISK_BUSY   0x10
+#define HAVE_DISK_BASE   0x20
+#define HAVE_DISK_ALL    0x30
+typedef struct disk_s {
+       char *name;
+       uint32_t flags;
+       cdtime_t timestamp;
+       uint64_t disk_busy;
+       uint64_t base_for_disk_busy;
+       double disk_busy_percent;
+       struct disk_s *next;
+} disk_t;
+
+#define CFG_DISK_BUSIEST 0x01
+#define CFG_DISK_ALL     0x01
+typedef struct {
+       uint32_t flags;
+       cna_interval_t interval;
+       na_elem_t *query;
+       disk_t *disks;
+} cfg_disk_t;
+/* }}} cfg_disk_t */
+
+/*! Data types for volume performance statistics {{{
+ *
+ * \brief Persistent data for volume performance data.
+ *
+ * The code below uses the difference of the operations and latency counters to
+ * calculate an average per-operation latency. For this, old counters need to
+ * be stored in the "data_volume_perf_t" structure. The byte-counters are just
+ * kept for completeness sake. The "flags" member indicates if each counter is
+ * valid or not.
+ *
+ * The "cna_handle_volume_perf_data" function will fill a new struct of this
+ * type and pass both, old and new data, to "submit_volume_perf_data". In that
+ * function, the per-operation latency is calculated and dispatched, then the
+ * old counters are updated.
+ */
+#define CFG_VOLUME_PERF_INIT           0x0001
+#define CFG_VOLUME_PERF_IO             0x0002
+#define CFG_VOLUME_PERF_OPS            0x0003
+#define CFG_VOLUME_PERF_LATENCY        0x0008
+#define CFG_VOLUME_PERF_ALL            0x000F
+#define HAVE_VOLUME_PERF_BYTES_READ    0x0010
+#define HAVE_VOLUME_PERF_BYTES_WRITE   0x0020
+#define HAVE_VOLUME_PERF_OPS_READ      0x0040
+#define HAVE_VOLUME_PERF_OPS_WRITE     0x0080
+#define HAVE_VOLUME_PERF_LATENCY_READ  0x0100
+#define HAVE_VOLUME_PERF_LATENCY_WRITE 0x0200
+#define HAVE_VOLUME_PERF_ALL           0x03F0
+struct data_volume_perf_s;
+typedef struct data_volume_perf_s data_volume_perf_t;
+struct data_volume_perf_s {
+       char *name;
+       uint32_t flags;
+       cdtime_t timestamp;
+
+       uint64_t read_bytes;
+       uint64_t write_bytes;
+       uint64_t read_ops;
+       uint64_t write_ops;
+       uint64_t read_latency;
+       uint64_t write_latency;
+
+       data_volume_perf_t *next;
+};
+
+typedef struct {
+       cna_interval_t interval;
+       na_elem_t *query;
+
+       ignorelist_t *il_octets;
+       ignorelist_t *il_operations;
+       ignorelist_t *il_latency;
+
+       data_volume_perf_t *volumes;
+} cfg_volume_perf_t;
+/* }}} data_volume_perf_t */
+
+/*! Data types for volume usage statistics {{{
+ *
+ * \brief Configuration struct for volume usage data (free / used).
+ */
+#define CFG_VOLUME_USAGE_DF              0x0002
+#define CFG_VOLUME_USAGE_SNAP            0x0004
+#define CFG_VOLUME_USAGE_ALL             0x0006
+#define HAVE_VOLUME_USAGE_NORM_FREE      0x0010
+#define HAVE_VOLUME_USAGE_NORM_USED      0x0020
+#define HAVE_VOLUME_USAGE_SNAP_RSVD      0x0040
+#define HAVE_VOLUME_USAGE_SNAP_USED      0x0080
+#define HAVE_VOLUME_USAGE_SIS_SAVED      0x0100
+#define HAVE_VOLUME_USAGE_COMPRESS_SAVED 0x0200
+#define HAVE_VOLUME_USAGE_DEDUP_SAVED    0x0400
+#define HAVE_VOLUME_USAGE_ALL            0x07f0
+#define IS_VOLUME_USAGE_OFFLINE          0x0800
+struct data_volume_usage_s;
+typedef struct data_volume_usage_s data_volume_usage_t;
+struct data_volume_usage_s {
+       char *name;
+       uint32_t flags;
+
+       na_elem_t *snap_query;
+
+       uint64_t norm_free;
+       uint64_t norm_used;
+       uint64_t snap_reserved;
+       uint64_t snap_used;
+       uint64_t sis_saved;
+       uint64_t compress_saved;
+       uint64_t dedup_saved;
+
+       data_volume_usage_t *next;
+};
+
+typedef struct {
+       cna_interval_t interval;
+       na_elem_t *query;
+
+       ignorelist_t *il_capacity;
+       ignorelist_t *il_snapshot;
+
+       data_volume_usage_t *volumes;
+} cfg_volume_usage_t;
+/* }}} cfg_volume_usage_t */
+
+/*! Data types for quota statistics {{{
+ *
+ * \brief Persistent data for quota statistics
+ */
+typedef struct {
+       cna_interval_t interval;
+       na_elem_t *query;
+} cfg_quota_t;
+/* }}} cfg_quota_t */
+
+/*! Data types for SnapVault statistics {{{
+ *
+ * \brief Persistent data for SnapVault(R) statistics
+ */
+typedef struct {
+       cna_interval_t interval;
+       na_elem_t *query;
+} cfg_snapvault_t;
+/* }}} cfg_snapvault_t */
+
+/*! Data types for system statistics {{{
+ *
+ * \brief Persistent data for system performance counters
+ */
+#define CFG_SYSTEM_CPU  0x01
+#define CFG_SYSTEM_NET  0x02
+#define CFG_SYSTEM_OPS  0x04
+#define CFG_SYSTEM_DISK 0x08
+#define CFG_SYSTEM_ALL  0x0F
+typedef struct {
+       uint32_t flags;
+       cna_interval_t interval;
+       na_elem_t *query;
+} cfg_system_t;
+/* }}} cfg_system_t */
+
+struct host_config_s {
+       char *name;
+       na_server_transport_t protocol;
+       char *host;
+       int port;
+       char *username;
+       char *password;
+       char *vfiler;
+       cdtime_t interval;
+
+       na_server_t *srv;
+       cfg_wafl_t *cfg_wafl;
+       cfg_disk_t *cfg_disk;
+       cfg_volume_perf_t *cfg_volume_perf;
+       cfg_volume_usage_t *cfg_volume_usage;
+       cfg_quota_t *cfg_quota;
+       cfg_snapvault_t *cfg_snapvault;
+       cfg_system_t *cfg_system;
+
+       struct host_config_s *next;
+};
+
+/*
+ * Free functions
+ *
+ * Used to free the various structures above.
+ */
+static void free_disk (disk_t *disk) /* {{{ */
+{
+       disk_t *next;
+
+       if (disk == NULL)
+               return;
+
+       next = disk->next;
+
+       sfree (disk->name);
+       sfree (disk);
+
+       free_disk (next);
+} /* }}} void free_disk */
+
+static void free_cfg_wafl (cfg_wafl_t *cw) /* {{{ */
+{
+       if (cw == NULL)
+               return;
+
+       if (cw->query != NULL)
+               na_elem_free (cw->query);
+
+       sfree (cw);
+} /* }}} void free_cfg_wafl */
+
+static void free_cfg_disk (cfg_disk_t *cfg_disk) /* {{{ */
+{
+       if (cfg_disk == NULL)
+               return;
+
+       if (cfg_disk->query != NULL)
+               na_elem_free (cfg_disk->query);
+
+       free_disk (cfg_disk->disks);
+       sfree (cfg_disk);
+} /* }}} void free_cfg_disk */
+
+static void free_cfg_volume_perf (cfg_volume_perf_t *cvp) /* {{{ */
+{
+       data_volume_perf_t *data;
+
+       if (cvp == NULL)
+               return;
+
+       /* Free the ignorelists */
+       ignorelist_free (cvp->il_octets);
+       ignorelist_free (cvp->il_operations);
+       ignorelist_free (cvp->il_latency);
+
+       /* Free the linked list of volumes */
+       data = cvp->volumes;
+       while (data != NULL)
+       {
+               data_volume_perf_t *next = data->next;
+               sfree (data->name);
+               sfree (data);
+               data = next;
+       }
+
+       if (cvp->query != NULL)
+               na_elem_free (cvp->query);
+
+       sfree (cvp);
+} /* }}} void free_cfg_volume_perf */
+
+static void free_cfg_volume_usage (cfg_volume_usage_t *cvu) /* {{{ */
+{
+       data_volume_usage_t *data;
+
+       if (cvu == NULL)
+               return;
+
+       /* Free the ignorelists */
+       ignorelist_free (cvu->il_capacity);
+       ignorelist_free (cvu->il_snapshot);
+
+       /* Free the linked list of volumes */
+       data = cvu->volumes;
+       while (data != NULL)
+       {
+               data_volume_usage_t *next = data->next;
+               sfree (data->name);
+               if (data->snap_query != NULL)
+                       na_elem_free(data->snap_query);
+               sfree (data);
+               data = next;
+       }
+
+       if (cvu->query != NULL)
+               na_elem_free (cvu->query);
+
+       sfree (cvu);
+} /* }}} void free_cfg_volume_usage */
+
+static void free_cfg_quota (cfg_quota_t *q) /* {{{ */
+{
+       if (q == NULL)
+               return;
+
+       if (q->query != NULL)
+               na_elem_free (q->query);
+
+       sfree (q);
+} /* }}} void free_cfg_quota */
+
+static void free_cfg_snapvault (cfg_snapvault_t *sv) /* {{{ */
+{
+       if (sv == NULL)
+               return;
+
+       if (sv->query != NULL)
+               na_elem_free (sv->query);
+
+       sfree (sv);
+} /* }}} void free_cfg_snapvault */
+
+static void free_cfg_system (cfg_system_t *cs) /* {{{ */
+{
+       if (cs == NULL)
+               return;
+
+       if (cs->query != NULL)
+               na_elem_free (cs->query);
+
+       sfree (cs);
+} /* }}} void free_cfg_system */
+
+static void free_host_config (host_config_t *hc) /* {{{ */
+{
+       host_config_t *next;
+
+       if (hc == NULL)
+               return;
+
+       next = hc->next;
+
+       sfree (hc->name);
+       sfree (hc->host);
+       sfree (hc->username);
+       sfree (hc->password);
+       sfree (hc->vfiler);
+
+       free_cfg_disk (hc->cfg_disk);
+       free_cfg_wafl (hc->cfg_wafl);
+       free_cfg_volume_perf (hc->cfg_volume_perf);
+       free_cfg_volume_usage (hc->cfg_volume_usage);
+       free_cfg_quota (hc->cfg_quota);
+       free_cfg_snapvault (hc->cfg_snapvault);
+       free_cfg_system (hc->cfg_system);
+
+       if (hc->srv != NULL)
+               na_server_close (hc->srv);
+
+       sfree (hc);
+
+       free_host_config (next);
+} /* }}} void free_host_config */
+
+/*
+ * Auxiliary functions
+ *
+ * Used to look up volumes and disks or to handle flags.
+ */
+static disk_t *get_disk(cfg_disk_t *cd, const char *name) /* {{{ */
+{
+       disk_t *d;
+
+       if ((cd == NULL) || (name == NULL))
+               return (NULL);
+
+       for (d = cd->disks; d != NULL; d = d->next) {
+               if (strcmp(d->name, name) == 0)
+                       return d;
+       }
+
+       d = malloc(sizeof(*d));
+       if (d == NULL)
+               return (NULL);
+       memset (d, 0, sizeof (*d));
+       d->next = NULL;
+
+       d->name = strdup(name);
+       if (d->name == NULL) {
+               sfree (d);
+               return (NULL);
+       }
+
+       d->next = cd->disks;
+       cd->disks = d;
+
+       return d;
+} /* }}} disk_t *get_disk */
+
+static data_volume_usage_t *get_volume_usage (cfg_volume_usage_t *cvu, /* {{{ */
+               const char *name)
+{
+       data_volume_usage_t *last;
+       data_volume_usage_t *new;
+
+       int ignore_capacity = 0;
+       int ignore_snapshot = 0;
+
+       if ((cvu == NULL) || (name == NULL))
+               return (NULL);
+
+       last = cvu->volumes;
+       while (last != NULL)
+       {
+               if (strcmp (last->name, name) == 0)
+                       return (last);
+
+               if (last->next == NULL)
+                       break;
+
+               last = last->next;
+       }
+
+       /* Check the ignorelists. If *both* tell us to ignore a volume, return NULL. */
+       ignore_capacity = ignorelist_match (cvu->il_capacity, name);
+       ignore_snapshot = ignorelist_match (cvu->il_snapshot, name);
+       if ((ignore_capacity != 0) && (ignore_snapshot != 0))
+               return (NULL);
+
+       /* Not found: allocate. */
+       new = malloc (sizeof (*new));
+       if (new == NULL)
+               return (NULL);
+       memset (new, 0, sizeof (*new));
+       new->next = NULL;
+
+       new->name = strdup (name);
+       if (new->name == NULL)
+       {
+               sfree (new);
+               return (NULL);
+       }
+
+       if (ignore_capacity == 0)
+               new->flags |= CFG_VOLUME_USAGE_DF;
+       if (ignore_snapshot == 0) {
+               new->flags |= CFG_VOLUME_USAGE_SNAP;
+               new->snap_query = na_elem_new ("snapshot-list-info");
+               na_child_add_string(new->snap_query, "target-type", "volume");
+               na_child_add_string(new->snap_query, "target-name", name);
+       } else {
+               new->snap_query = NULL;
+       }
+
+       /* Add to end of list. */
+       if (last == NULL)
+               cvu->volumes = new;
+       else
+               last->next = new;
+
+       return (new);
+} /* }}} data_volume_usage_t *get_volume_usage */
+
+static data_volume_perf_t *get_volume_perf (cfg_volume_perf_t *cvp, /* {{{ */
+               const char *name)
+{
+       data_volume_perf_t *last;
+       data_volume_perf_t *new;
+
+       int ignore_octets = 0;
+       int ignore_operations = 0;
+       int ignore_latency = 0;
+
+       if ((cvp == NULL) || (name == NULL))
+               return (NULL);
+
+       last = cvp->volumes;
+       while (last != NULL)
+       {
+               if (strcmp (last->name, name) == 0)
+                       return (last);
+
+               if (last->next == NULL)
+                       break;
+
+               last = last->next;
+       }
+
+       /* Check the ignorelists. If *all three* tell us to ignore a volume, return
+        * NULL. */
+       ignore_octets = ignorelist_match (cvp->il_octets, name);
+       ignore_operations = ignorelist_match (cvp->il_operations, name);
+       ignore_latency = ignorelist_match (cvp->il_latency, name);
+       if ((ignore_octets != 0) || (ignore_operations != 0)
+                       || (ignore_latency != 0))
+               return (NULL);
+
+       /* Not found: allocate. */
+       new = malloc (sizeof (*new));
+       if (new == NULL)
+               return (NULL);
+       memset (new, 0, sizeof (*new));
+       new->next = NULL;
+
+       new->name = strdup (name);
+       if (new->name == NULL)
+       {
+               sfree (new);
+               return (NULL);
+       }
+
+       if (ignore_octets == 0)
+               new->flags |= CFG_VOLUME_PERF_IO;
+       if (ignore_operations == 0)
+               new->flags |= CFG_VOLUME_PERF_OPS;
+       if (ignore_latency == 0)
+               new->flags |= CFG_VOLUME_PERF_LATENCY;
+
+       /* Add to end of list. */
+       if (last == NULL)
+               cvp->volumes = new;
+       else
+               last->next = new;
+
+       return (new);
+} /* }}} data_volume_perf_t *get_volume_perf */
+
+/*
+ * Various submit functions.
+ *
+ * They all eventually call "submit_values" which creates a value_list_t and
+ * dispatches it to the daemon.
+ */
+static int submit_values (const char *host, /* {{{ */
+               const char *plugin_inst,
+               const char *type, const char *type_inst,
+               value_t *values, int values_len,
+               cdtime_t timestamp, cdtime_t interval)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = values;
+       vl.values_len = values_len;
+
+       if (timestamp > 0)
+               vl.time = timestamp;
+
+       if (interval > 0)
+               vl.interval = interval;
+
+       if (host != NULL)
+               sstrncpy (vl.host, host, sizeof (vl.host));
+       else
+               sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "netapp", sizeof (vl.plugin));
+       if (plugin_inst != NULL)
+               sstrncpy (vl.plugin_instance, plugin_inst, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_inst != NULL)
+               sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+       return (plugin_dispatch_values (&vl));
+} /* }}} int submit_uint64 */
+
+static int submit_two_derive (const char *host, const char *plugin_inst, /* {{{ */
+               const char *type, const char *type_inst, derive_t val0, derive_t val1,
+               cdtime_t timestamp, cdtime_t interval)
+{
+       value_t values[2];
+
+       values[0].derive = val0;
+       values[1].derive = val1;
+
+       return (submit_values (host, plugin_inst, type, type_inst,
+                               values, 2, timestamp, interval));
+} /* }}} int submit_two_derive */
+
+static int submit_derive (const char *host, const char *plugin_inst, /* {{{ */
+               const char *type, const char *type_inst, derive_t counter,
+               cdtime_t timestamp, cdtime_t interval)
+{
+       value_t v;
+
+       v.derive = counter;
+
+       return (submit_values (host, plugin_inst, type, type_inst,
+                               &v, 1, timestamp, interval));
+} /* }}} int submit_derive */
+
+static int submit_two_gauge (const char *host, const char *plugin_inst, /* {{{ */
+               const char *type, const char *type_inst, gauge_t val0, gauge_t val1,
+               cdtime_t timestamp, cdtime_t interval)
+{
+       value_t values[2];
+
+       values[0].gauge = val0;
+       values[1].gauge = val1;
+
+       return (submit_values (host, plugin_inst, type, type_inst,
+                               values, 2, timestamp, interval));
+} /* }}} int submit_two_gauge */
+
+static int submit_double (const char *host, const char *plugin_inst, /* {{{ */
+               const char *type, const char *type_inst, double d,
+               cdtime_t timestamp, cdtime_t interval)
+{
+       value_t v;
+
+       v.gauge = (gauge_t) d;
+
+       return (submit_values (host, plugin_inst, type, type_inst,
+                               &v, 1, timestamp, interval));
+} /* }}} int submit_uint64 */
+
+/* Calculate hit ratio from old and new counters and submit the resulting
+ * percentage. Used by "submit_wafl_data". */
+static int submit_cache_ratio (const char *host, /* {{{ */
+               const char *plugin_inst,
+               const char *type_inst,
+               uint64_t new_hits,
+               uint64_t new_misses,
+               uint64_t old_hits,
+               uint64_t old_misses,
+               cdtime_t timestamp,
+               cdtime_t interval)
+{
+       value_t v;
+
+       if ((new_hits >= old_hits) && (new_misses >= old_misses)) {
+               uint64_t hits;
+               uint64_t misses;
+
+               hits = new_hits - old_hits;
+               misses = new_misses - old_misses;
+
+               v.gauge = 100.0 * ((gauge_t) hits) / ((gauge_t) (hits + misses));
+       } else {
+               v.gauge = NAN;
+       }
+
+       return (submit_values (host, plugin_inst, "cache_ratio", type_inst,
+                               &v, 1, timestamp, interval));
+} /* }}} int submit_cache_ratio */
+
+/* Submits all the caches used by WAFL. Uses "submit_cache_ratio". */
+static int submit_wafl_data (const char *hostname, const char *instance, /* {{{ */
+               cfg_wafl_t *old_data, const cfg_wafl_t *new_data, cdtime_t interval)
+{
+       /* Submit requested counters */
+       if (HAS_ALL_FLAGS (old_data->flags, CFG_WAFL_NAME_CACHE | HAVE_WAFL_NAME_CACHE)
+                       && HAS_ALL_FLAGS (new_data->flags, HAVE_WAFL_NAME_CACHE))
+               submit_cache_ratio (hostname, instance, "name_cache_hit",
+                               new_data->name_cache_hit, new_data->name_cache_miss,
+                               old_data->name_cache_hit, old_data->name_cache_miss,
+                               new_data->timestamp, interval);
+
+       if (HAS_ALL_FLAGS (old_data->flags, CFG_WAFL_DIR_CACHE | HAVE_WAFL_FIND_DIR)
+                       && HAS_ALL_FLAGS (new_data->flags, HAVE_WAFL_FIND_DIR))
+               submit_cache_ratio (hostname, instance, "find_dir_hit",
+                               new_data->find_dir_hit, new_data->find_dir_miss,
+                               old_data->find_dir_hit, old_data->find_dir_miss,
+                               new_data->timestamp, interval);
+
+       if (HAS_ALL_FLAGS (old_data->flags, CFG_WAFL_BUF_CACHE | HAVE_WAFL_BUF_HASH)
+                       && HAS_ALL_FLAGS (new_data->flags, HAVE_WAFL_BUF_HASH))
+               submit_cache_ratio (hostname, instance, "buf_hash_hit",
+                               new_data->buf_hash_hit, new_data->buf_hash_miss,
+                               old_data->buf_hash_hit, old_data->buf_hash_miss,
+                               new_data->timestamp, interval);
+
+       if (HAS_ALL_FLAGS (old_data->flags, CFG_WAFL_INODE_CACHE | HAVE_WAFL_INODE_CACHE)
+                       && HAS_ALL_FLAGS (new_data->flags, HAVE_WAFL_INODE_CACHE))
+               submit_cache_ratio (hostname, instance, "inode_cache_hit",
+                               new_data->inode_cache_hit, new_data->inode_cache_miss,
+                               old_data->inode_cache_hit, old_data->inode_cache_miss,
+                               new_data->timestamp, interval);
+
+       /* Clear old HAVE_* flags */
+       old_data->flags &= ~HAVE_WAFL_ALL;
+
+       /* Copy all counters */
+       old_data->timestamp        = new_data->timestamp;
+       old_data->name_cache_hit   = new_data->name_cache_hit;
+       old_data->name_cache_miss  = new_data->name_cache_miss;
+       old_data->find_dir_hit     = new_data->find_dir_hit;
+       old_data->find_dir_miss    = new_data->find_dir_miss;
+       old_data->buf_hash_hit     = new_data->buf_hash_hit;
+       old_data->buf_hash_miss    = new_data->buf_hash_miss;
+       old_data->inode_cache_hit  = new_data->inode_cache_hit;
+       old_data->inode_cache_miss = new_data->inode_cache_miss;
+
+       /* Copy HAVE_* flags */
+       old_data->flags |= (new_data->flags & HAVE_WAFL_ALL);
+
+       return (0);
+} /* }}} int submit_wafl_data */
+
+/* Submits volume performance data to the daemon, taking care to honor and
+ * update flags appropriately. */
+static int submit_volume_perf_data (const char *hostname, /* {{{ */
+               data_volume_perf_t *old_data,
+               const data_volume_perf_t *new_data, int interval)
+{
+       char plugin_instance[DATA_MAX_NAME_LEN];
+
+       if ((hostname == NULL) || (old_data == NULL) || (new_data == NULL))
+               return (-1);
+
+       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))
+       {
+               submit_two_derive (hostname, plugin_instance, "disk_octets", /* type instance = */ NULL,
+                               (derive_t) new_data->read_bytes, (derive_t) new_data->write_bytes, new_data->timestamp, interval);
+       }
+
+       /* Check for and submit disk-operations values */
+       if (HAS_ALL_FLAGS (old_data->flags, CFG_VOLUME_PERF_OPS)
+                       && HAS_ALL_FLAGS (new_data->flags, HAVE_VOLUME_PERF_OPS_READ | HAVE_VOLUME_PERF_OPS_WRITE))
+       {
+               submit_two_derive (hostname, plugin_instance, "disk_ops", /* type instance = */ NULL,
+                               (derive_t) new_data->read_ops, (derive_t) new_data->write_ops, new_data->timestamp, interval);
+       }
+
+       /* 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))
+       {
+               gauge_t latency_per_op_read;
+               gauge_t latency_per_op_write;
+
+               latency_per_op_read = NAN;
+               latency_per_op_write = NAN;
+
+               /* Check if a counter wrapped around. */
+               if ((new_data->read_ops > old_data->read_ops)
+                               && (new_data->read_latency > old_data->read_latency))
+               {
+                       uint64_t diff_ops_read;
+                       uint64_t diff_latency_read;
+
+                       diff_ops_read = new_data->read_ops - old_data->read_ops;
+                       diff_latency_read = new_data->read_latency - old_data->read_latency;
+
+                       if (diff_ops_read > 0)
+                               latency_per_op_read = ((gauge_t) diff_latency_read) / ((gauge_t) diff_ops_read);
+               }
+
+               if ((new_data->write_ops > old_data->write_ops)
+                               && (new_data->write_latency > old_data->write_latency))
+               {
+                       uint64_t diff_ops_write;
+                       uint64_t diff_latency_write;
+
+                       diff_ops_write = new_data->write_ops - old_data->write_ops;
+                       diff_latency_write = new_data->write_latency - old_data->write_latency;
+
+                       if (diff_ops_write > 0)
+                               latency_per_op_write = ((gauge_t) diff_latency_write) / ((gauge_t) diff_ops_write);
+               }
+
+               submit_two_gauge (hostname, plugin_instance, "disk_latency", /* type instance = */ NULL,
+                               latency_per_op_read, latency_per_op_write, new_data->timestamp, interval);
+       }
+
+       /* Clear all HAVE_* flags. */
+       old_data->flags &= ~HAVE_VOLUME_PERF_ALL;
+
+       /* Copy all counters */
+       old_data->timestamp = new_data->timestamp;
+       old_data->read_bytes = new_data->read_bytes;
+       old_data->write_bytes = new_data->write_bytes;
+       old_data->read_ops = new_data->read_ops;
+       old_data->write_ops = new_data->write_ops;
+       old_data->read_latency = new_data->read_latency;
+       old_data->write_latency = new_data->write_latency;
+
+       /* Copy the HAVE_* flags */
+       old_data->flags |= (new_data->flags & HAVE_VOLUME_PERF_ALL);
+
+       return (0);
+} /* }}} int submit_volume_perf_data */
+
+static cdtime_t cna_child_get_cdtime (na_elem_t *data) /* {{{ */
+{
+       time_t t;
+
+       t = (time_t) na_child_get_uint64 (data, "timestamp", /* default = */ 0);
+
+       return (TIME_T_TO_CDTIME_T (t));
+} /* }}} cdtime_t cna_child_get_cdtime */
+
+
+/* 
+ * Query functions
+ *
+ * These functions are called with appropriate data returned by the libnetapp
+ * interface which is parsed and submitted with the above functions.
+ */
+/* Data corresponding to <WAFL /> */
+static int cna_handle_wafl_data (const char *hostname, cfg_wafl_t *cfg_wafl, /* {{{ */
+               na_elem_t *data, cdtime_t interval)
+{
+       cfg_wafl_t perf_data;
+       const char *plugin_inst;
+
+       na_elem_t *instances;
+       na_elem_t *counter;
+       na_elem_iter_t counter_iter;
+
+       memset (&perf_data, 0, sizeof (perf_data));
+       
+       perf_data.timestamp = cna_child_get_cdtime (data);
+
+       instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
+       if (instances == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_wafl_data: "
+                               "na_elem_child (\"instances\") failed "
+                               "for host %s.", hostname);
+               return (-1);
+       }
+
+       plugin_inst = na_child_get_string(instances, "name");
+       if (plugin_inst == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_wafl_data: "
+                               "na_child_get_string (\"name\") failed "
+                               "for host %s.", hostname);
+               return (-1);
+       }
+
+       /* Iterate over all counters */
+       counter_iter = na_child_iterator (na_elem_child (instances, "counters"));
+       for (counter = na_iterator_next (&counter_iter);
+                       counter != NULL;
+                       counter = na_iterator_next (&counter_iter))
+       {
+               const char *name;
+               uint64_t value;
+
+               name = na_child_get_string(counter, "name");
+               if (name == NULL)
+                       continue;
+
+               value = na_child_get_uint64(counter, "value", UINT64_MAX);
+               if (value == UINT64_MAX)
+                       continue;
+
+               if (!strcmp(name, "name_cache_hit")) {
+                       perf_data.name_cache_hit = value;
+                       perf_data.flags |= HAVE_WAFL_NAME_CACHE_HIT;
+               } else if (!strcmp(name, "name_cache_miss")) {
+                       perf_data.name_cache_miss = value;
+                       perf_data.flags |= HAVE_WAFL_NAME_CACHE_MISS;
+               } else if (!strcmp(name, "find_dir_hit")) {
+                       perf_data.find_dir_hit = value;
+                       perf_data.flags |= HAVE_WAFL_FIND_DIR_HIT;
+               } else if (!strcmp(name, "find_dir_miss")) {
+                       perf_data.find_dir_miss = value;
+                       perf_data.flags |= HAVE_WAFL_FIND_DIR_MISS;
+               } else if (!strcmp(name, "buf_hash_hit")) {
+                       perf_data.buf_hash_hit = value;
+                       perf_data.flags |= HAVE_WAFL_BUF_HASH_HIT;
+               } else if (!strcmp(name, "buf_hash_miss")) {
+                       perf_data.buf_hash_miss = value;
+                       perf_data.flags |= HAVE_WAFL_BUF_HASH_MISS;
+               } else if (!strcmp(name, "inode_cache_hit")) {
+                       perf_data.inode_cache_hit = value;
+                       perf_data.flags |= HAVE_WAFL_INODE_CACHE_HIT;
+               } else if (!strcmp(name, "inode_cache_miss")) {
+                       perf_data.inode_cache_miss = value;
+                       perf_data.flags |= HAVE_WAFL_INODE_CACHE_MISS;
+               } else {
+                       DEBUG("netapp plugin: cna_handle_wafl_data: "
+                                       "Found unexpected child: %s "
+                                       "for host %s.", name, hostname);
+               }
+       }
+
+       return (submit_wafl_data (hostname, plugin_inst, cfg_wafl, &perf_data, interval));
+} /* }}} void cna_handle_wafl_data */
+
+static int cna_setup_wafl (cfg_wafl_t *cw) /* {{{ */
+{
+       na_elem_t *e;
+
+       if (cw == NULL)
+               return (EINVAL);
+
+       if (cw->query != NULL)
+               return (0);
+
+       cw->query = na_elem_new("perf-object-get-instances");
+       if (cw->query == NULL)
+       {
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+       na_child_add_string (cw->query, "objectname", "wafl");
+
+       e = na_elem_new("counters");
+       if (e == NULL)
+       {
+               na_elem_free (cw->query);
+               cw->query = NULL;
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+       na_child_add_string(e, "counter", "name_cache_hit");
+       na_child_add_string(e, "counter", "name_cache_miss");
+       na_child_add_string(e, "counter", "find_dir_hit");
+       na_child_add_string(e, "counter", "find_dir_miss");
+       na_child_add_string(e, "counter", "buf_hash_hit");
+       na_child_add_string(e, "counter", "buf_hash_miss");
+       na_child_add_string(e, "counter", "inode_cache_hit");
+       na_child_add_string(e, "counter", "inode_cache_miss");
+
+       na_child_add(cw->query, e);
+
+       return (0);
+} /* }}} int cna_setup_wafl */
+
+static int cna_query_wafl (host_config_t *host) /* {{{ */
+{
+       na_elem_t *data;
+       int status;
+       cdtime_t now;
+
+       if (host == NULL)
+               return (EINVAL);
+
+       /* If WAFL was not configured, return without doing anything. */
+       if (host->cfg_wafl == NULL)
+               return (0);
+
+       now = cdtime ();
+       if ((host->cfg_wafl->interval.interval + host->cfg_wafl->interval.last_read) > now)
+               return (0);
+
+       status = cna_setup_wafl (host->cfg_wafl);
+       if (status != 0)
+               return (status);
+       assert (host->cfg_wafl->query != NULL);
+
+       data = na_server_invoke_elem(host->srv, host->cfg_wafl->query);
+       if (na_results_status (data) != NA_OK)
+       {
+               ERROR ("netapp plugin: cna_query_wafl: na_server_invoke_elem failed for host %s: %s",
+                               host->name, na_results_reason (data));
+               na_elem_free (data);
+               return (-1);
+       }
+
+       status = cna_handle_wafl_data (host->name, host->cfg_wafl, data,
+                       host->cfg_wafl->interval.interval);
+
+       if (status == 0)
+               host->cfg_wafl->interval.last_read = now;
+
+       na_elem_free (data);
+       return (status);
+} /* }}} int cna_query_wafl */
+
+/* Data corresponding to <Disks /> */
+static int cna_handle_disk_data (const char *hostname, /* {{{ */
+               cfg_disk_t *cfg_disk, na_elem_t *data, cdtime_t interval)
+{
+       cdtime_t timestamp;
+       na_elem_t *instances;
+       na_elem_t *instance;
+       na_elem_iter_t instance_iter;
+       disk_t *worst_disk = NULL;
+
+       if ((cfg_disk == NULL) || (data == NULL))
+               return (EINVAL);
+       
+       timestamp = cna_child_get_cdtime (data);
+
+       instances = na_elem_child (data, "instances");
+       if (instances == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_disk_data: "
+                               "na_elem_child (\"instances\") failed "
+                               "for host %s.", hostname);
+               return (-1);
+       }
+
+       /* Iterate over all children */
+       instance_iter = na_child_iterator (instances);
+       for (instance = na_iterator_next (&instance_iter);
+                       instance != NULL;
+                       instance = na_iterator_next(&instance_iter))
+       {
+               disk_t *old_data;
+               disk_t  new_data;
+
+               na_elem_iter_t counter_iterator;
+               na_elem_t *counter;
+
+               memset (&new_data, 0, sizeof (new_data));
+               new_data.timestamp = timestamp;
+               new_data.disk_busy_percent = NAN;
+
+               old_data = get_disk(cfg_disk, na_child_get_string (instance, "name"));
+               if (old_data == NULL)
+                       continue;
+
+               /* Look for the "disk_busy" and "base_for_disk_busy" counters */
+               counter_iterator = na_child_iterator(na_elem_child(instance, "counters"));
+               for (counter = na_iterator_next(&counter_iterator);
+                               counter != NULL;
+                               counter = na_iterator_next(&counter_iterator))
+               {
+                       const char *name;
+                       uint64_t value;
+
+                       name = na_child_get_string(counter, "name");
+                       if (name == NULL)
+                               continue;
+
+                       value = na_child_get_uint64(counter, "value", UINT64_MAX);
+                       if (value == UINT64_MAX)
+                               continue;
+
+                       if (strcmp(name, "disk_busy") == 0)
+                       {
+                               new_data.disk_busy = value;
+                               new_data.flags |= HAVE_DISK_BUSY;
+                       }
+                       else if (strcmp(name, "base_for_disk_busy") == 0)
+                       {
+                               new_data.base_for_disk_busy = value;
+                               new_data.flags |= HAVE_DISK_BASE;
+                       }
+                       else
+                       {
+                               DEBUG ("netapp plugin: cna_handle_disk_data: "
+                                               "Counter not handled: %s = %"PRIu64,
+                                               name, value);
+                       }
+               }
+
+               /* If all required counters are available and did not just wrap around,
+                * calculate the busy percentage. Otherwise, the value is initialized to
+                * NAN at the top of the for-loop. */
+               if (HAS_ALL_FLAGS (old_data->flags, HAVE_DISK_BUSY | HAVE_DISK_BASE)
+                               && HAS_ALL_FLAGS (new_data.flags, HAVE_DISK_BUSY | HAVE_DISK_BASE)
+                               && (new_data.disk_busy >= old_data->disk_busy)
+                               && (new_data.base_for_disk_busy > old_data->base_for_disk_busy))
+               {
+                       uint64_t busy_diff;
+                       uint64_t base_diff;
+
+                       busy_diff = new_data.disk_busy - old_data->disk_busy;
+                       base_diff = new_data.base_for_disk_busy - old_data->base_for_disk_busy;
+
+                       new_data.disk_busy_percent = 100.0
+                               * ((gauge_t) busy_diff) / ((gauge_t) base_diff);
+               }
+
+               /* Clear HAVE_* flags */
+               old_data->flags &= ~HAVE_DISK_ALL;
+
+               /* Copy data */
+               old_data->timestamp = new_data.timestamp;
+               old_data->disk_busy = new_data.disk_busy;
+               old_data->base_for_disk_busy = new_data.base_for_disk_busy;
+               old_data->disk_busy_percent = new_data.disk_busy_percent;
+
+               /* Copy flags */
+               old_data->flags |= (new_data.flags & HAVE_DISK_ALL);
+
+               if ((worst_disk == NULL)
+                               || (worst_disk->disk_busy_percent < old_data->disk_busy_percent))
+                       worst_disk = old_data;
+       } /* for (all disks) */
+
+       if ((cfg_disk->flags & CFG_DISK_BUSIEST) && (worst_disk != NULL))
+               submit_double (hostname, "system", "percent", "disk_busy",
+                               worst_disk->disk_busy_percent, timestamp, interval);
+
+       return (0);
+} /* }}} int cna_handle_disk_data */
+
+static int cna_setup_disk (cfg_disk_t *cd) /* {{{ */
+{
+       na_elem_t *e;
+
+       if (cd == NULL)
+               return (EINVAL);
+
+       if (cd->query != NULL)
+               return (0);
+
+       cd->query = na_elem_new ("perf-object-get-instances");
+       if (cd->query == NULL)
+       {
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+       na_child_add_string (cd->query, "objectname", "disk");
+
+       e = na_elem_new("counters");
+       if (e == NULL)
+       {
+               na_elem_free (cd->query);
+               cd->query = NULL;
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+       na_child_add_string(e, "counter", "disk_busy");
+       na_child_add_string(e, "counter", "base_for_disk_busy");
+       na_child_add(cd->query, e);
+
+       return (0);
+} /* }}} int cna_setup_disk */
+
+static int cna_query_disk (host_config_t *host) /* {{{ */
+{
+       na_elem_t *data;
+       int status;
+       cdtime_t now;
+
+       if (host == NULL)
+               return (EINVAL);
+
+       /* If the user did not configure disk statistics, return without doing
+        * anything. */
+       if (host->cfg_disk == NULL)
+               return (0);
+
+       now = cdtime ();
+       if ((host->cfg_disk->interval.interval + host->cfg_disk->interval.last_read) > now)
+               return (0);
+
+       status = cna_setup_disk (host->cfg_disk);
+       if (status != 0)
+               return (status);
+       assert (host->cfg_disk->query != NULL);
+
+       data = na_server_invoke_elem(host->srv, host->cfg_disk->query);
+       if (na_results_status (data) != NA_OK)
+       {
+               ERROR ("netapp plugin: cna_query_disk: na_server_invoke_elem failed for host %s: %s",
+                               host->name, na_results_reason (data));
+               na_elem_free (data);
+               return (-1);
+       }
+
+       status = cna_handle_disk_data (host->name, host->cfg_disk, data,
+                       host->cfg_disk->interval.interval);
+
+       if (status == 0)
+               host->cfg_disk->interval.last_read = now;
+
+       na_elem_free (data);
+       return (status);
+} /* }}} int cna_query_disk */
+
+/* Data corresponding to <VolumePerf /> */
+static int cna_handle_volume_perf_data (const char *hostname, /* {{{ */
+               cfg_volume_perf_t *cvp, na_elem_t *data, cdtime_t interval)
+{
+       cdtime_t timestamp;
+       na_elem_t *elem_instances;
+       na_elem_iter_t iter_instances;
+       na_elem_t *elem_instance;
+       
+       timestamp = cna_child_get_cdtime (data);
+
+       elem_instances = na_elem_child(data, "instances");
+       if (elem_instances == NULL)
+       {
+               ERROR ("netapp plugin: handle_volume_perf_data: "
+                               "na_elem_child (\"instances\") failed "
+                               "for host %s.", hostname);
+               return (-1);
+       }
+
+       iter_instances = na_child_iterator (elem_instances);
+       for (elem_instance = na_iterator_next(&iter_instances);
+                       elem_instance != NULL;
+                       elem_instance = na_iterator_next(&iter_instances))
+       {
+               const char *name;
+
+               data_volume_perf_t perf_data;
+               data_volume_perf_t *v;
+
+               na_elem_t *elem_counters;
+               na_elem_iter_t iter_counters;
+               na_elem_t *elem_counter;
+
+               memset (&perf_data, 0, sizeof (perf_data));
+               perf_data.timestamp = timestamp;
+
+               name = na_child_get_string (elem_instance, "name");
+               if (name == NULL)
+                       continue;
+
+               /* get_volume_perf may return NULL if this volume is to be ignored. */
+               v = get_volume_perf (cvp, name);
+               if (v == NULL)
+                       continue;
+
+               elem_counters = na_elem_child (elem_instance, "counters");
+               if (elem_counters == NULL)
+                       continue;
+
+               iter_counters = na_child_iterator (elem_counters);
+               for (elem_counter = na_iterator_next(&iter_counters);
+                               elem_counter != NULL;
+                               elem_counter = na_iterator_next(&iter_counters))
+               {
+                       const char *name;
+                       uint64_t value;
+
+                       name = na_child_get_string (elem_counter, "name");
+                       if (name == NULL)
+                               continue;
+
+                       value = na_child_get_uint64 (elem_counter, "value", UINT64_MAX);
+                       if (value == UINT64_MAX)
+                               continue;
+
+                       if (!strcmp(name, "read_data")) {
+                               perf_data.read_bytes = value;
+                               perf_data.flags |= HAVE_VOLUME_PERF_BYTES_READ;
+                       } else if (!strcmp(name, "write_data")) {
+                               perf_data.write_bytes = value;
+                               perf_data.flags |= HAVE_VOLUME_PERF_BYTES_WRITE;
+                       } else if (!strcmp(name, "read_ops")) {
+                               perf_data.read_ops = value;
+                               perf_data.flags |= HAVE_VOLUME_PERF_OPS_READ;
+                       } else if (!strcmp(name, "write_ops")) {
+                               perf_data.write_ops = value;
+                               perf_data.flags |= HAVE_VOLUME_PERF_OPS_WRITE;
+                       } else if (!strcmp(name, "read_latency")) {
+                               perf_data.read_latency = value;
+                               perf_data.flags |= HAVE_VOLUME_PERF_LATENCY_READ;
+                       } else if (!strcmp(name, "write_latency")) {
+                               perf_data.write_latency = value;
+                               perf_data.flags |= HAVE_VOLUME_PERF_LATENCY_WRITE;
+                       }
+               } /* for (elem_counter) */
+
+               submit_volume_perf_data (hostname, v, &perf_data, interval);
+       } /* for (volume) */
+
+       return (0);
+} /* }}} int cna_handle_volume_perf_data */
+
+static int cna_setup_volume_perf (cfg_volume_perf_t *cd) /* {{{ */
+{
+       na_elem_t *e;
+
+       if (cd == NULL)
+               return (EINVAL);
+
+       if (cd->query != NULL)
+               return (0);
+
+       cd->query = na_elem_new ("perf-object-get-instances");
+       if (cd->query == NULL)
+       {
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+       na_child_add_string (cd->query, "objectname", "volume");
+
+       e = na_elem_new("counters");
+       if (e == NULL)
+       {
+               na_elem_free (cd->query);
+               cd->query = NULL;
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+       na_child_add_string(e, "counter", "read_ops");
+       na_child_add_string(e, "counter", "write_ops");
+       na_child_add_string(e, "counter", "read_data");
+       na_child_add_string(e, "counter", "write_data");
+       na_child_add_string(e, "counter", "read_latency");
+       na_child_add_string(e, "counter", "write_latency");
+       na_child_add(cd->query, e);
+
+       return (0);
+} /* }}} int cna_setup_volume_perf */
+
+static int cna_query_volume_perf (host_config_t *host) /* {{{ */
+{
+       na_elem_t *data;
+       int status;
+       cdtime_t now;
+
+       if (host == NULL)
+               return (EINVAL);
+
+       /* If the user did not configure volume performance statistics, return
+        * without doing anything. */
+       if (host->cfg_volume_perf == NULL)
+               return (0);
+
+       now = cdtime ();
+       if ((host->cfg_volume_perf->interval.interval + host->cfg_volume_perf->interval.last_read) > now)
+               return (0);
+
+       status = cna_setup_volume_perf (host->cfg_volume_perf);
+       if (status != 0)
+               return (status);
+       assert (host->cfg_volume_perf->query != NULL);
+
+       data = na_server_invoke_elem (host->srv, host->cfg_volume_perf->query);
+       if (na_results_status (data) != NA_OK)
+       {
+               ERROR ("netapp plugin: cna_query_volume_perf: na_server_invoke_elem failed for host %s: %s",
+                               host->name, na_results_reason (data));
+               na_elem_free (data);
+               return (-1);
+       }
+
+       status = cna_handle_volume_perf_data (host->name, host->cfg_volume_perf, data,
+                       host->cfg_volume_perf->interval.interval);
+
+       if (status == 0)
+               host->cfg_volume_perf->interval.last_read = now;
+
+       na_elem_free (data);
+       return (status);
+} /* }}} int cna_query_volume_perf */
+
+/* Data corresponding to <VolumeUsage /> */
+static int cna_submit_volume_usage_data (const char *hostname, /* {{{ */
+               cfg_volume_usage_t *cfg_volume, int interval)
+{
+       data_volume_usage_t *v;
+
+       for (v = cfg_volume->volumes; v != NULL; v = v->next)
+       {
+               char plugin_instance[DATA_MAX_NAME_LEN];
+
+               uint64_t norm_used = v->norm_used;
+               uint64_t norm_free = v->norm_free;
+               uint64_t sis_saved = v->sis_saved;
+               uint64_t compress_saved = v->compress_saved;
+               uint64_t dedup_saved = v->dedup_saved;
+               uint64_t snap_reserve_used = 0;
+               uint64_t snap_reserve_free = v->snap_reserved;
+               uint64_t snap_norm_used = v->snap_used;
+
+               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 (v->snap_reserved > v->snap_used) {
+                               snap_reserve_free = v->snap_reserved - v->snap_used;
+                               snap_reserve_used = v->snap_used;
+                               snap_norm_used = 0;
+                       } else {
+                               snap_reserve_free = 0;
+                               snap_reserve_used = v->snap_reserved;
+                               snap_norm_used = v->snap_used - v->snap_reserved;
+                       }
+               }
+
+               /* 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 (norm_used >= snap_norm_used)
+                               norm_used -= snap_norm_used;
+                       else
+                       {
+                               ERROR ("netapp plugin: (norm_used = %"PRIu64") < (snap_norm_used = "
+                                               "%"PRIu64") for host %s. Invalidating both.",
+                                               norm_used, snap_norm_used, hostname);
+                               v->flags &= ~(HAVE_VOLUME_USAGE_NORM_USED | HAVE_VOLUME_USAGE_SNAP_USED);
+                       }
+               }
+
+               if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_NORM_FREE))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "df_complex", "free",
+                                       (double) norm_free, /* timestamp = */ 0, interval);
+
+               if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SIS_SAVED))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "df_complex", "sis_saved",
+                                       (double) sis_saved, /* timestamp = */ 0, interval);
+
+               if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_COMPRESS_SAVED))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "df_complex", "compression_saved",
+                                       (double) compress_saved, /* timestamp = */ 0, interval);
+
+               if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_DEDUP_SAVED))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "df_complex", "dedup_saved",
+                                       (double) dedup_saved, /* timestamp = */ 0, interval);
+
+               if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_NORM_USED))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "df_complex", "used",
+                                       (double) norm_used, /* timestamp = */ 0, interval);
+
+               if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SNAP_RSVD))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "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))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "df_complex", "snap_reserve_used",
+                                       (double) snap_reserve_used, /* timestamp = */ 0, interval);
+
+               if (HAS_ALL_FLAGS (v->flags, HAVE_VOLUME_USAGE_SNAP_USED))
+                       submit_double (hostname, /* plugin instance = */ plugin_instance,
+                                       "df_complex", "snap_normal_used",
+                                       (double) snap_norm_used, /* timestamp = */ 0, interval);
+
+               /* Clear all the HAVE_* flags */
+               v->flags &= ~HAVE_VOLUME_USAGE_ALL;
+       } /* for (v = cfg_volume->volumes) */
+
+       return (0);
+} /* }}} int cna_submit_volume_usage_data */
+
+/* Switch the state of a volume between online and offline and send out a
+ * notification. */
+static int cna_change_volume_status (const char *hostname, /* {{{ */
+               data_volume_usage_t *v)
+{
+       notification_t n;
+
+       memset (&n, 0, sizeof (&n));
+       n.time = cdtime ();
+       sstrncpy (n.host, hostname, sizeof (n.host));
+       sstrncpy (n.plugin, "netapp", sizeof (n.plugin));
+       sstrncpy (n.plugin_instance, v->name, sizeof (n.plugin_instance));
+
+       if ((v->flags & IS_VOLUME_USAGE_OFFLINE) != 0) {
+               n.severity = NOTIF_OKAY;
+               ssnprintf (n.message, sizeof (n.message),
+                               "Volume %s is now online.", v->name);
+               v->flags &= ~IS_VOLUME_USAGE_OFFLINE;
+       } else {
+               n.severity = NOTIF_WARNING;
+               ssnprintf (n.message, sizeof (n.message),
+                               "Volume %s is now offline.", v->name);
+               v->flags |= IS_VOLUME_USAGE_OFFLINE;
+       }
+
+       return (plugin_dispatch_notification (&n));
+} /* }}} int cna_change_volume_status */
+
+static void cna_handle_volume_snap_usage(const host_config_t *host, /* {{{ */
+               data_volume_usage_t *v)
+{
+       uint64_t snap_used = 0, value;
+       na_elem_t *data, *elem_snap, *elem_snapshots;
+       na_elem_iter_t iter_snap;
+
+       data = na_server_invoke_elem(host->srv, v->snap_query);
+       if (na_results_status(data) != NA_OK)
+       {
+               if (na_results_errno(data) == EVOLUMEOFFLINE) {
+                       if ((v->flags & IS_VOLUME_USAGE_OFFLINE) == 0)
+                               cna_change_volume_status (host->name, v);
+               } else {
+                       ERROR ("netapp plugin: cna_handle_volume_snap_usage: na_server_invoke_elem for "
+                                       "volume \"%s\" on host %s failed with error %d: %s", v->name,
+                                       host->name, na_results_errno(data), na_results_reason(data));
+               }
+               na_elem_free(data);
+               return;
+       }
+
+       if ((v->flags & IS_VOLUME_USAGE_OFFLINE) != 0)
+               cna_change_volume_status (host->name, v);
+
+       elem_snapshots = na_elem_child (data, "snapshots");
+       if (elem_snapshots == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_volume_snap_usage: "
+                               "na_elem_child (\"snapshots\") failed "
+                               "for host %s.", host->name);
+               na_elem_free(data);
+               return;
+       }
+
+       iter_snap = na_child_iterator (elem_snapshots);
+       for (elem_snap = na_iterator_next (&iter_snap);
+                       elem_snap != NULL;
+                       elem_snap = na_iterator_next (&iter_snap))
+       {
+               value = na_child_get_uint64(elem_snap, "cumulative-total", 0);
+               /* "cumulative-total" is the total size of the oldest snapshot plus all
+                * newer ones in blocks (1KB). We therefore are looking for the highest
+                * number of all snapshots - that's the size required for the snapshots. */
+               if (value > snap_used)
+                       snap_used = value;
+       }
+       na_elem_free (data);
+       /* snap_used is in 1024 byte blocks */
+       v->snap_used = snap_used * 1024;
+       v->flags |= HAVE_VOLUME_USAGE_SNAP_USED;
+} /* }}} void cna_handle_volume_snap_usage */
+
+static void cna_handle_volume_sis_data (const host_config_t *host, /* {{{ */
+               data_volume_usage_t *v, na_elem_t *sis)
+{
+       const char *sis_state;
+       uint64_t sis_saved_reported;
+
+       if (na_elem_child(sis, "sis-info"))
+               sis = na_elem_child(sis, "sis-info");
+
+       sis_state = na_child_get_string(sis, "state");
+       if (sis_state == NULL)
+               return;
+
+       /* If SIS is not enabled, there's nothing left to do for this volume. */
+       if (strcmp ("enabled", sis_state) != 0)
+               return;
+
+       sis_saved_reported = na_child_get_uint64(sis, "size-saved", UINT64_MAX);
+       if (sis_saved_reported == UINT64_MAX)
+               return;
+
+       /* size-saved is actually a 32 bit number, so ... time for some guesswork. */
+       if ((sis_saved_reported >> 32) != 0) {
+               /* In case they ever fix this bug. */
+               v->sis_saved = sis_saved_reported;
+               v->flags |= HAVE_VOLUME_USAGE_SIS_SAVED;
+       } else { /* really hacky work-around code. {{{ */
+               uint64_t sis_saved_percent;
+               uint64_t sis_saved_guess;
+               uint64_t overflow_guess;
+               uint64_t guess1, guess2, guess3;
+
+               /* Check if we have v->norm_used. Without it, we cannot calculate
+                * sis_saved_guess. */
+               if ((v->flags & HAVE_VOLUME_USAGE_NORM_USED) == 0)
+                       return;
+
+               sis_saved_percent = na_child_get_uint64(sis, "percentage-saved", UINT64_MAX);
+               if (sis_saved_percent > 100)
+                       return;
+
+               /* The "size-saved" value is a 32bit unsigned integer. This is a bug and
+                * will hopefully be fixed in later versions. To work around the bug, try
+                * to figure out how often the 32bit integer wrapped around by using the
+                * "percentage-saved" value. Because the percentage is in the range
+                * [0-100], this should work as long as the saved space does not exceed
+                * 400 GBytes. */
+               /* percentage-saved = size-saved / (size-saved + size-used) */
+               if (sis_saved_percent < 100)
+                       sis_saved_guess = v->norm_used * sis_saved_percent / (100 - sis_saved_percent);
+               else
+                       sis_saved_guess = v->norm_used;
+
+               overflow_guess = sis_saved_guess >> 32;
+               guess1 = overflow_guess ? ((overflow_guess - 1) << 32) + sis_saved_reported : sis_saved_reported;
+               guess2 = (overflow_guess << 32) + sis_saved_reported;
+               guess3 = ((overflow_guess + 1) << 32) + sis_saved_reported;
+
+               if (sis_saved_guess < guess2) {
+                       if ((sis_saved_guess - guess1) < (guess2 - sis_saved_guess))
+                               v->sis_saved = guess1;
+                       else
+                               v->sis_saved = guess2;
+               } else {
+                       if ((sis_saved_guess - guess2) < (guess3 - sis_saved_guess))
+                               v->sis_saved = guess2;
+                       else
+                               v->sis_saved = guess3;
+               }
+               v->flags |= HAVE_VOLUME_USAGE_SIS_SAVED;
+       } /* }}} end of 32-bit workaround */
+} /* }}} void cna_handle_volume_sis_data */
+
+/* ONTAP >= 8.1 uses SIS for managing dedup and compression */
+static void cna_handle_volume_sis_saved (const host_config_t *host, /* {{{ */
+               data_volume_usage_t *v, na_elem_t *sis)
+{
+       uint64_t saved;
+
+       if (na_elem_child(sis, "sis-info"))
+               sis = na_elem_child(sis, "sis-info");
+
+       saved = na_child_get_uint64(sis, "compress-saved", UINT64_MAX);
+       if (saved != UINT64_MAX) {
+               v->compress_saved = saved;
+               v->flags |= HAVE_VOLUME_USAGE_COMPRESS_SAVED;
+       }
+
+       saved = na_child_get_uint64(sis, "dedup-saved", UINT64_MAX);
+       if (saved != UINT64_MAX) {
+               v->dedup_saved = saved;
+               v->flags |= HAVE_VOLUME_USAGE_DEDUP_SAVED;
+       }
+} /* }}} void cna_handle_volume_sis_saved */
+
+static int cna_handle_volume_usage_data (const host_config_t *host, /* {{{ */
+               cfg_volume_usage_t *cfg_volume, na_elem_t *data)
+{
+       na_elem_t *elem_volume;
+       na_elem_t *elem_volumes;
+       na_elem_iter_t iter_volume;
+
+       elem_volumes = na_elem_child (data, "volumes");
+       if (elem_volumes == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_volume_usage_data: "
+                               "na_elem_child (\"volumes\") failed "
+                               "for host %s.", host->name);
+               return (-1);
+       }
+
+       iter_volume = na_child_iterator (elem_volumes);
+       for (elem_volume = na_iterator_next (&iter_volume);
+                       elem_volume != NULL;
+                       elem_volume = na_iterator_next (&iter_volume))
+       {
+               const char *volume_name, *state;
+
+               data_volume_usage_t *v;
+               uint64_t value;
+
+               na_elem_t *sis;
+
+               volume_name = na_child_get_string (elem_volume, "name");
+               if (volume_name == NULL)
+                       continue;
+
+               state = na_child_get_string (elem_volume, "state");
+               if ((state == NULL) || (strcmp(state, "online") != 0))
+                       continue;
+
+               /* get_volume_usage may return NULL if the volume is to be ignored. */
+               v = get_volume_usage (cfg_volume, volume_name);
+               if (v == NULL)
+                       continue;
+
+               if ((v->flags & CFG_VOLUME_USAGE_SNAP) != 0)
+                       cna_handle_volume_snap_usage(host, v);
+               
+               if ((v->flags & CFG_VOLUME_USAGE_DF) == 0)
+                       continue;
+
+               /* 2^4 exa-bytes? This will take a while ;) */
+               value = na_child_get_uint64(elem_volume, "size-available", UINT64_MAX);
+               if (value != UINT64_MAX) {
+                       v->norm_free = value;
+                       v->flags |= HAVE_VOLUME_USAGE_NORM_FREE;
+               }
+
+               value = na_child_get_uint64(elem_volume, "size-used", UINT64_MAX);
+               if (value != UINT64_MAX) {
+                       v->norm_used = value;
+                       v->flags |= HAVE_VOLUME_USAGE_NORM_USED;
+               }
+
+               value = na_child_get_uint64(elem_volume, "snapshot-blocks-reserved", UINT64_MAX);
+               if (value != UINT64_MAX) {
+                       /* 1 block == 1024 bytes  as per API docs */
+                       v->snap_reserved = 1024 * value;
+                       v->flags |= HAVE_VOLUME_USAGE_SNAP_RSVD;
+               }
+
+               sis = na_elem_child(elem_volume, "sis");
+               if (sis != NULL) {
+                       cna_handle_volume_sis_data (host, v, sis);
+                       cna_handle_volume_sis_saved (host, v, sis);
+               }
+       } /* for (elem_volume) */
+
+       return (cna_submit_volume_usage_data (host->name, cfg_volume,
+                               host->cfg_volume_usage->interval.interval));
+} /* }}} int cna_handle_volume_usage_data */
+
+static int cna_setup_volume_usage (cfg_volume_usage_t *cvu) /* {{{ */
+{
+       if (cvu == NULL)
+               return (EINVAL);
+
+       if (cvu->query != NULL)
+               return (0);
+
+       cvu->query = na_elem_new ("volume-list-info");
+       if (cvu->query == NULL)
+       {
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+
+       return (0);
+} /* }}} int cna_setup_volume_usage */
+
+static int cna_query_volume_usage (host_config_t *host) /* {{{ */
+{
+       na_elem_t *data;
+       int status;
+       cdtime_t now;
+
+       if (host == NULL)
+               return (EINVAL);
+
+       /* If the user did not configure volume_usage statistics, return without
+        * doing anything. */
+       if (host->cfg_volume_usage == NULL)
+               return (0);
+
+       now = cdtime ();
+       if ((host->cfg_volume_usage->interval.interval + host->cfg_volume_usage->interval.last_read) > now)
+               return (0);
+
+       status = cna_setup_volume_usage (host->cfg_volume_usage);
+       if (status != 0)
+               return (status);
+       assert (host->cfg_volume_usage->query != NULL);
+
+       data = na_server_invoke_elem(host->srv, host->cfg_volume_usage->query);
+       if (na_results_status (data) != NA_OK)
+       {
+               ERROR ("netapp plugin: cna_query_volume_usage: na_server_invoke_elem failed for host %s: %s",
+                               host->name, na_results_reason (data));
+               na_elem_free (data);
+               return (-1);
+       }
+
+       status = cna_handle_volume_usage_data (host, host->cfg_volume_usage, data);
+
+       if (status == 0)
+               host->cfg_volume_usage->interval.last_read = now;
+
+       na_elem_free (data);
+       return (status);
+} /* }}} int cna_query_volume_usage */
+
+/* Data corresponding to <Quota /> */
+static int cna_handle_quota_data (const host_config_t *host, /* {{{ */
+               cfg_quota_t *cfg_quota, na_elem_t *data)
+{
+       na_elem_t *elem_quota;
+       na_elem_t *elem_quotas;
+       na_elem_iter_t iter_quota;
+
+       elem_quotas = na_elem_child (data, "quotas");
+       if (elem_quotas == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_quota_data: "
+                               "na_elem_child (\"quotas\") failed "
+                               "for host %s.", host->name);
+               return (-1);
+       }
+
+       iter_quota = na_child_iterator (elem_quotas);
+       for (elem_quota = na_iterator_next (&iter_quota);
+                       elem_quota != NULL;
+                       elem_quota = na_iterator_next (&iter_quota))
+       {
+               const char *quota_type, *volume_name, *tree_name;
+               uint64_t value;
+
+               char plugin_instance[DATA_MAX_NAME_LEN];
+
+               quota_type = na_child_get_string (elem_quota, "quota-type");
+               if (quota_type == NULL)
+                       continue;
+
+               /* possible TODO: support other types as well */
+               if (strcmp (quota_type, "tree") != 0)
+                       continue;
+
+               tree_name = na_child_get_string (elem_quota, "tree");
+               if ((tree_name == NULL) || (*tree_name == '\0'))
+                       continue;
+
+               volume_name = na_child_get_string (elem_quota, "volume");
+               if (volume_name == NULL)
+                       continue;
+
+               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) {
+                       value *= 1024; /* disk-used reports kilobytes */
+                       submit_double (host->name, plugin_instance,
+                                       /* type = */ "df_complex", /* type instance = */ NULL,
+                                       (double)value, /* timestamp = */ 0,
+                                       host->cfg_quota->interval.interval);
+               }
+
+               value = na_child_get_uint64 (elem_quota, "files-used", UINT64_MAX);
+               if (value != UINT64_MAX) {
+                       submit_double (host->name, plugin_instance,
+                                       /* type = */ "files", /* type instance = */ NULL,
+                                       (double)value, /* timestamp = */ 0,
+                                       host->cfg_quota->interval.interval);
+               }
+       } /* for (elem_quota) */
+
+       return (0);
+} /* }}} int cna_handle_volume_usage_data */
+
+static int cna_setup_quota (cfg_quota_t *cq) /* {{{ */
+{
+       if (cq == NULL)
+               return (EINVAL);
+
+       if (cq->query != NULL)
+               return (0);
+
+       cq->query = na_elem_new ("quota-report");
+       if (cq->query == NULL)
+       {
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+
+       return (0);
+} /* }}} int cna_setup_quota */
+
+static int cna_query_quota (host_config_t *host) /* {{{ */
+{
+       na_elem_t *data;
+       int status;
+       cdtime_t now;
+
+       if (host == NULL)
+               return (EINVAL);
+
+       /* If the user did not configure quota statistics, return without
+        * doing anything. */
+       if (host->cfg_quota == NULL)
+               return (0);
+
+       now = cdtime ();
+       if ((host->cfg_quota->interval.interval + host->cfg_quota->interval.last_read) > now)
+               return (0);
+
+       status = cna_setup_quota (host->cfg_quota);
+       if (status != 0)
+               return (status);
+       assert (host->cfg_quota->query != NULL);
+
+       data = na_server_invoke_elem (host->srv, host->cfg_quota->query);
+       if (na_results_status (data) != NA_OK)
+       {
+               ERROR ("netapp plugin: cna_query_quota: na_server_invoke_elem failed for host %s: %s",
+                               host->name, na_results_reason (data));
+               na_elem_free (data);
+               return (-1);
+       }
+
+       status = cna_handle_quota_data (host, host->cfg_quota, data);
+
+       if (status == 0)
+               host->cfg_quota->interval.last_read = now;
+
+       na_elem_free (data);
+       return (status);
+} /* }}} int cna_query_quota */
+
+/* Data corresponding to <SnapVault /> */
+static int cna_handle_snapvault_data (const char *hostname, /* {{{ */
+               cfg_snapvault_t *cfg_snapvault, na_elem_t *data, cdtime_t interval)
+{
+       na_elem_t *status;
+       na_elem_iter_t status_iter;
+
+       status = na_elem_child (data, "status-list");
+       if (! status) {
+               ERROR ("netapp plugin: SnapVault status record missing status-list");
+               return (0);
+       }
+
+       status_iter = na_child_iterator (status);
+       for (status = na_iterator_next (&status_iter);
+                       status != NULL;
+                       status = na_iterator_next (&status_iter))
+       {
+               const char *dest_sys, *dest_path, *src_sys, *src_path;
+               char plugin_instance[DATA_MAX_NAME_LEN];
+               uint64_t value;
+
+               dest_sys  = na_child_get_string (status, "destination-system");
+               dest_path = na_child_get_string (status, "destination-path");
+               src_sys   = na_child_get_string (status, "source-system");
+               src_path  = na_child_get_string (status, "source-path");
+
+               if ((! dest_sys) || (! dest_path) || (! src_sys) || (! src_path))
+                       continue;
+
+               value = na_child_get_uint64 (status, "lag-time", UINT64_MAX);
+               if (value == UINT64_MAX) /* no successful baseline transfer yet */
+                       continue;
+
+               /* possible TODO: make plugin instance configurable */
+               ssnprintf (plugin_instance, sizeof (plugin_instance),
+                               "snapvault-%s", dest_path);
+               submit_double (hostname, plugin_instance, /* type = */ "delay", NULL,
+                               (double)value, /* timestamp = */ 0, interval);
+
+               value = na_child_get_uint64 (status, "last-transfer-duration", UINT64_MAX);
+               if (value != UINT64_MAX)
+                       submit_double (hostname, plugin_instance, /* type = */ "duration", "last_transfer",
+                                       (double)value, /* timestamp = */ 0, interval);
+
+               value = na_child_get_uint64 (status, "transfer-progress", UINT64_MAX);
+               if (value == UINT64_MAX)
+                       value = na_child_get_uint64 (status, "last-transfer-size", UINT64_MAX);
+               if (value != UINT64_MAX) {
+                       value *= 1024; /* this is kilobytes */
+                       submit_derive (hostname, plugin_instance, /* type = */ "if_rx_octets", "transferred",
+                                       value, /* timestamp = */ 0, interval);
+               }
+       } /* for (status) */
+
+       return (0);
+} /* }}} int cna_handle_snapvault_data */
+
+static int cna_handle_snapvault_iter (host_config_t *host, /* {{{ */
+               na_elem_t *data)
+{
+       const char *tag;
+
+       uint32_t records_count;
+       uint32_t i;
+
+       records_count = na_child_get_uint32 (data, "records", UINT32_MAX);
+       if (records_count == UINT32_MAX)
+               return 0;
+
+       tag = na_child_get_string (data, "tag");
+       if (! tag)
+               return 0;
+
+       DEBUG ("netapp plugin: Iterating %u SV records (tag = %s)", records_count, tag);
+
+       for (i = 0; i < records_count; ++i) {
+               na_elem_t *elem;
+
+               elem = na_server_invoke (host->srv,
+                               "snapvault-secondary-relationship-status-list-iter-next",
+                               "maximum", "1", "tag", tag, NULL);
+
+               if (na_results_status (elem) != NA_OK)
+               {
+                       ERROR ("netapp plugin: cna_handle_snapvault_iter: "
+                                       "na_server_invoke failed for host %s: %s",
+                                       host->name, na_results_reason (data));
+                       na_elem_free (elem);
+                       return (-1);
+               }
+
+               cna_handle_snapvault_data (host->name, host->cfg_snapvault, elem,
+                               host->cfg_snapvault->interval.interval);
+               na_elem_free (elem);
+       }
+
+       na_elem_free (na_server_invoke (host->srv,
+                       "snapvault-secondary-relationship-status-list-iter-end",
+                       "tag", tag, NULL));
+       return (0);
+} /* }}} int cna_handle_snapvault_iter */
+
+static int cna_setup_snapvault (cfg_snapvault_t *sv) /* {{{ */
+{
+       if (sv == NULL)
+               return (EINVAL);
+
+       if (sv->query != NULL)
+               return (0);
+
+       sv->query = na_elem_new ("snapvault-secondary-relationship-status-list-iter-start");
+       if (sv->query == NULL)
+       {
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+
+       return (0);
+} /* }}} int cna_setup_snapvault */
+
+static int cna_query_snapvault (host_config_t *host) /* {{{ */
+{
+       na_elem_t *data;
+       int status;
+       cdtime_t now;
+
+       if (host == NULL)
+               return EINVAL;
+
+       if (host->cfg_snapvault == NULL)
+               return 0;
+
+       now = cdtime ();
+       if ((host->cfg_snapvault->interval.interval + host->cfg_snapvault->interval.last_read) > now)
+               return (0);
+
+       status = cna_setup_snapvault (host->cfg_snapvault);
+       if (status != 0)
+               return (status);
+       assert (host->cfg_snapvault->query != NULL);
+
+       data = na_server_invoke_elem (host->srv, host->cfg_snapvault->query);
+       if (na_results_status (data) != NA_OK)
+       {
+               ERROR ("netapp plugin: cna_query_snapvault: na_server_invoke_elem failed for host %s: %s",
+                               host->name, na_results_reason (data));
+               na_elem_free (data);
+               return (-1);
+       }
+
+       status = cna_handle_snapvault_iter (host, data);
+
+       if (status == 0)
+               host->cfg_snapvault->interval.last_read = now;
+
+       na_elem_free (data);
+       return (status);
+} /* }}} int cna_query_snapvault */
+
+/* Data corresponding to <System /> */
+static int cna_handle_system_data (const char *hostname, /* {{{ */
+               cfg_system_t *cfg_system, na_elem_t *data, int interval)
+{
+       na_elem_t *instances;
+       na_elem_t *counter;
+       na_elem_iter_t counter_iter;
+
+       derive_t disk_read = 0, disk_written = 0;
+       derive_t net_recv = 0, net_sent = 0;
+       derive_t cpu_busy = 0, cpu_total = 0;
+       uint32_t counter_flags = 0;
+
+       const char *instance;
+       cdtime_t timestamp;
+       
+       timestamp = cna_child_get_cdtime (data);
+
+       instances = na_elem_child(na_elem_child (data, "instances"), "instance-data");
+       if (instances == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_system_data: "
+                               "na_elem_child (\"instances\") failed "
+                               "for host %s.", hostname);
+               return (-1);
+       }
+
+       instance = na_child_get_string (instances, "name");
+       if (instance == NULL)
+       {
+               ERROR ("netapp plugin: cna_handle_system_data: "
+                               "na_child_get_string (\"name\") failed "
+                               "for host %s.", hostname);
+               return (-1);
+       }
+
+       counter_iter = na_child_iterator (na_elem_child (instances, "counters"));
+       for (counter = na_iterator_next (&counter_iter);
+                       counter != NULL;
+                       counter = na_iterator_next (&counter_iter))
+       {
+               const char *name;
+               uint64_t value;
+
+               name = na_child_get_string(counter, "name");
+               if (name == NULL)
+                       continue;
+
+               value = na_child_get_uint64(counter, "value", UINT64_MAX);
+               if (value == UINT64_MAX)
+                       continue;
+
+               if (!strcmp(name, "disk_data_read")) {
+                       disk_read = (derive_t) (value * 1024);
+                       counter_flags |= 0x01;
+               } else if (!strcmp(name, "disk_data_written")) {
+                       disk_written = (derive_t) (value * 1024);
+                       counter_flags |= 0x02;
+               } else if (!strcmp(name, "net_data_recv")) {
+                       net_recv = (derive_t) (value * 1024);
+                       counter_flags |= 0x04;
+               } else if (!strcmp(name, "net_data_sent")) {
+                       net_sent = (derive_t) (value * 1024);
+                       counter_flags |= 0x08;
+               } else if (!strcmp(name, "cpu_busy")) {
+                       cpu_busy = (derive_t) value;
+                       counter_flags |= 0x10;
+               } else if (!strcmp(name, "cpu_elapsed_time")) {
+                       cpu_total = (derive_t) value;
+                       counter_flags |= 0x20;
+               } else if ((cfg_system->flags & CFG_SYSTEM_OPS)
+                               && (value > 0) && (strlen(name) > 4)
+                               && (!strcmp(name + strlen(name) - 4, "_ops"))) {
+                       submit_derive (hostname, instance, "disk_ops_complex", name,
+                                       (derive_t) value, timestamp, interval);
+               }
+       } /* for (counter) */
+
+       if ((cfg_system->flags & CFG_SYSTEM_DISK)
+                       && (HAS_ALL_FLAGS (counter_flags, 0x01 | 0x02)))
+               submit_two_derive (hostname, instance, "disk_octets", NULL,
+                               disk_read, disk_written, timestamp, interval);
+                               
+       if ((cfg_system->flags & CFG_SYSTEM_NET)
+                       && (HAS_ALL_FLAGS (counter_flags, 0x04 | 0x08)))
+               submit_two_derive (hostname, instance, "if_octets", NULL,
+                               net_recv, net_sent, timestamp, interval);
+
+       if ((cfg_system->flags & CFG_SYSTEM_CPU)
+                       && (HAS_ALL_FLAGS (counter_flags, 0x10 | 0x20)))
+       {
+               submit_derive (hostname, instance, "cpu", "system",
+                               cpu_busy, timestamp, interval);
+               submit_derive (hostname, instance, "cpu", "idle",
+                               cpu_total - cpu_busy, timestamp, interval);
+       }
+
+       return (0);
+} /* }}} int cna_handle_system_data */
+
+static int cna_setup_system (cfg_system_t *cs) /* {{{ */
+{
+       if (cs == NULL)
+               return (EINVAL);
+
+       if (cs->query != NULL)
+               return (0);
+
+       cs->query = na_elem_new ("perf-object-get-instances");
+       if (cs->query == NULL)
+       {
+               ERROR ("netapp plugin: na_elem_new failed.");
+               return (-1);
+       }
+       na_child_add_string (cs->query, "objectname", "system");
+
+       return (0);
+} /* }}} int cna_setup_system */
+
+static int cna_query_system (host_config_t *host) /* {{{ */
+{
+       na_elem_t *data;
+       int status;
+       cdtime_t now;
+
+       if (host == NULL)
+               return (EINVAL);
+
+       /* If system statistics were not configured, return without doing anything. */
+       if (host->cfg_system == NULL)
+               return (0);
+
+       now = cdtime ();
+       if ((host->cfg_system->interval.interval + host->cfg_system->interval.last_read) > now)
+               return (0);
+
+       status = cna_setup_system (host->cfg_system);
+       if (status != 0)
+               return (status);
+       assert (host->cfg_system->query != NULL);
+
+       data = na_server_invoke_elem(host->srv, host->cfg_system->query);
+       if (na_results_status (data) != NA_OK)
+       {
+               ERROR ("netapp plugin: cna_query_system: na_server_invoke_elem failed for host %s: %s",
+                               host->name, na_results_reason (data));
+               na_elem_free (data);
+               return (-1);
+       }
+
+       status = cna_handle_system_data (host->name, host->cfg_system, data,
+                       host->cfg_system->interval.interval);
+
+       if (status == 0)
+               host->cfg_system->interval.last_read = now;
+
+       na_elem_free (data);
+       return (status);
+} /* }}} int cna_query_system */
+
+/*
+ * Configuration handling
+ */
+/* Sets a given flag if the boolean argument is true and unsets the flag if it
+ * is false. On error, the flag-field is not changed. */
+static int cna_config_bool_to_flag (const oconfig_item_t *ci, /* {{{ */
+               uint32_t *flags, uint32_t flag)
+{
+       if ((ci == NULL) || (flags == NULL))
+               return (EINVAL);
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+       {
+               WARNING ("netapp plugin: The %s option needs exactly one boolean argument.",
+                               ci->key);
+               return (-1);
+       }
+
+       if (ci->values[0].value.boolean)
+               *flags |= flag;
+       else
+               *flags &= ~flag;
+
+       return (0);
+} /* }}} int cna_config_bool_to_flag */
+
+/* Handling of the "Interval" option which is allowed in every block. */
+static int cna_config_get_interval (const oconfig_item_t *ci, /* {{{ */
+               cna_interval_t *out_interval)
+{
+       cdtime_t tmp = 0;
+       int status;
+
+       status = cf_util_get_cdtime (ci, &tmp);
+       if (status != 0)
+               return (status);
+
+       out_interval->interval = tmp;
+       out_interval->last_read = 0;
+
+       return (0);
+} /* }}} int cna_config_get_interval */
+
+/* Handling of the "GetIO", "GetOps" and "GetLatency" options within a
+ * <VolumePerf /> block. */
+static void cna_config_volume_perf_option (cfg_volume_perf_t *cvp, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       char *name;
+       ignorelist_t * il;
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+       {
+               WARNING ("netapp plugin: The %s option requires exactly one string argument.",
+                               ci->key);
+               return;
+       }
+
+       name = ci->values[0].value.string;
+
+       if (strcasecmp ("GetIO", ci->key) == 0)
+               il = cvp->il_octets;
+       else if (strcasecmp ("GetOps", ci->key) == 0)
+               il = cvp->il_operations;
+       else if (strcasecmp ("GetLatency", ci->key) == 0)
+               il = cvp->il_latency;
+       else
+               return;
+
+       ignorelist_add (il, name);
+} /* }}} void cna_config_volume_perf_option */
+
+/* Handling of the "IgnoreSelectedIO", "IgnoreSelectedOps" and
+ * "IgnoreSelectedLatency" options within a <VolumePerf /> block. */
+static void cna_config_volume_perf_default (cfg_volume_perf_t *cvp, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       ignorelist_t *il;
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+       {
+               WARNING ("netapp plugin: The %s option requires exactly one string argument.",
+                               ci->key);
+               return;
+       }
+
+       if (strcasecmp ("IgnoreSelectedIO", ci->key) == 0)
+               il = cvp->il_octets;
+       else if (strcasecmp ("IgnoreSelectedOps", ci->key) == 0)
+               il = cvp->il_operations;
+       else if (strcasecmp ("IgnoreSelectedLatency", ci->key) == 0)
+               il = cvp->il_latency;
+       else
+               return;
+
+       if (ci->values[0].value.boolean)
+               ignorelist_set_invert (il, /* invert = */ 0);
+       else
+               ignorelist_set_invert (il, /* invert = */ 1);
+} /* }}} void cna_config_volume_perf_default */
+
+/* Corresponds to a <Disks /> block */
+/*
+ * <VolumePerf>
+ *   GetIO "vol0"
+ *   GetIO "vol1"
+ *   IgnoreSelectedIO false
+ *
+ *   GetOps "vol0"
+ *   GetOps "vol2"
+ *   IgnoreSelectedOps false
+ *
+ *   GetLatency "vol2"
+ *   GetLatency "vol3"
+ *   IgnoreSelectedLatency false
+ * </VolumePerf>
+ */
+/* Corresponds to a <VolumePerf /> block */
+static int cna_config_volume_performance (host_config_t *host, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       cfg_volume_perf_t *cfg_volume_perf;
+       int i;
+
+       if ((host == NULL) || (ci == NULL))
+               return (EINVAL);
+
+       if (host->cfg_volume_perf == NULL)
+       {
+               cfg_volume_perf = malloc (sizeof (*cfg_volume_perf));
+               if (cfg_volume_perf == NULL)
+                       return (ENOMEM);
+               memset (cfg_volume_perf, 0, sizeof (*cfg_volume_perf));
+
+               /* Set default flags */
+               cfg_volume_perf->query = NULL;
+               cfg_volume_perf->volumes = NULL;
+
+               cfg_volume_perf->il_octets = ignorelist_create (/* invert = */ 1);
+               if (cfg_volume_perf->il_octets == NULL)
+               {
+                       sfree (cfg_volume_perf);
+                       return (ENOMEM);
+               }
+
+               cfg_volume_perf->il_operations = ignorelist_create (/* invert = */ 1);
+               if (cfg_volume_perf->il_operations == NULL)
+               {
+                       ignorelist_free (cfg_volume_perf->il_octets);
+                       sfree (cfg_volume_perf);
+                       return (ENOMEM);
+               }
+
+               cfg_volume_perf->il_latency = ignorelist_create (/* invert = */ 1);
+               if (cfg_volume_perf->il_latency == NULL)
+               {
+                       ignorelist_free (cfg_volume_perf->il_octets);
+                       ignorelist_free (cfg_volume_perf->il_operations);
+                       sfree (cfg_volume_perf);
+                       return (ENOMEM);
+               }
+
+               host->cfg_volume_perf = cfg_volume_perf;
+       }
+       cfg_volume_perf = host->cfg_volume_perf;
+       
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+               
+               /* if (!item || !item->key || !*item->key) continue; */
+               if (strcasecmp(item->key, "Interval") == 0)
+                       cna_config_get_interval (item, &cfg_volume_perf->interval);
+               else if (!strcasecmp(item->key, "GetIO"))
+                       cna_config_volume_perf_option (cfg_volume_perf, item);
+               else if (!strcasecmp(item->key, "GetOps"))
+                       cna_config_volume_perf_option (cfg_volume_perf, item);
+               else if (!strcasecmp(item->key, "GetLatency"))
+                       cna_config_volume_perf_option (cfg_volume_perf, item);
+               else if (!strcasecmp(item->key, "IgnoreSelectedIO"))
+                       cna_config_volume_perf_default (cfg_volume_perf, item);
+               else if (!strcasecmp(item->key, "IgnoreSelectedOps"))
+                       cna_config_volume_perf_default (cfg_volume_perf, item);
+               else if (!strcasecmp(item->key, "IgnoreSelectedLatency"))
+                       cna_config_volume_perf_default (cfg_volume_perf, item);
+               else
+                       WARNING ("netapp plugin: The option %s is not allowed within "
+                                       "`VolumePerf' blocks.", item->key);
+       }
+
+       return (0);
+} /* }}} int cna_config_volume_performance */
+
+/* Handling of the "GetCapacity" and "GetSnapshot" options within a
+ * <VolumeUsage /> block. */
+static void cna_config_volume_usage_option (cfg_volume_usage_t *cvu, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       char *name;
+       ignorelist_t * il;
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+       {
+               WARNING ("netapp plugin: The %s option requires exactly one string argument.",
+                               ci->key);
+               return;
+       }
+
+       name = ci->values[0].value.string;
+
+       if (strcasecmp ("GetCapacity", ci->key) == 0)
+               il = cvu->il_capacity;
+       else if (strcasecmp ("GetSnapshot", ci->key) == 0)
+               il = cvu->il_snapshot;
+       else
+               return;
+
+       ignorelist_add (il, name);
+} /* }}} void cna_config_volume_usage_option */
+
+/* Handling of the "IgnoreSelectedCapacity" and "IgnoreSelectedSnapshot"
+ * options within a <VolumeUsage /> block. */
+static void cna_config_volume_usage_default (cfg_volume_usage_t *cvu, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       ignorelist_t *il;
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+       {
+               WARNING ("netapp plugin: The %s option requires exactly one string argument.",
+                               ci->key);
+               return;
+       }
+
+       if (strcasecmp ("IgnoreSelectedCapacity", ci->key) == 0)
+               il = cvu->il_capacity;
+       else if (strcasecmp ("IgnoreSelectedSnapshot", ci->key) == 0)
+               il = cvu->il_snapshot;
+       else
+               return;
+
+       if (ci->values[0].value.boolean)
+               ignorelist_set_invert (il, /* invert = */ 0);
+       else
+               ignorelist_set_invert (il, /* invert = */ 1);
+} /* }}} void cna_config_volume_usage_default */
+
+/* Corresponds to a <Quota /> block */
+static int cna_config_quota (host_config_t *host, oconfig_item_t *ci) /* {{{ */
+{
+       cfg_quota_t *cfg_quota;
+       int i;
+
+       if ((host == NULL) || (ci == NULL))
+               return (EINVAL);
+
+       if (host->cfg_quota == NULL)
+       {
+               cfg_quota = malloc (sizeof (*cfg_quota));
+               if (cfg_quota == NULL)
+                       return (ENOMEM);
+               memset (cfg_quota, 0, sizeof (*cfg_quota));
+               cfg_quota->query = NULL;
+
+               host->cfg_quota = cfg_quota;
+       }
+       cfg_quota = host->cfg_quota;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+
+               if (strcasecmp (item->key, "Interval") == 0)
+                       cna_config_get_interval (item, &cfg_quota->interval);
+               else
+                       WARNING ("netapp plugin: The option %s is not allowed within "
+                                       "`Quota' blocks.", item->key);
+       }
+
+       return (0);
+} /* }}} int cna_config_quota */
+
+/* Corresponds to a <Disks /> block */
+static int cna_config_disk(host_config_t *host, oconfig_item_t *ci) { /* {{{ */
+       cfg_disk_t *cfg_disk;
+       int i;
+
+       if ((host == NULL) || (ci == NULL))
+               return (EINVAL);
+
+       if (host->cfg_disk == NULL)
+       {
+               cfg_disk = malloc (sizeof (*cfg_disk));
+               if (cfg_disk == NULL)
+                       return (ENOMEM);
+               memset (cfg_disk, 0, sizeof (*cfg_disk));
+
+               /* Set default flags */
+               cfg_disk->flags = CFG_DISK_ALL;
+               cfg_disk->query = NULL;
+               cfg_disk->disks = NULL;
+
+               host->cfg_disk = cfg_disk;
+       }
+       cfg_disk = host->cfg_disk;
+       
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+               
+               /* if (!item || !item->key || !*item->key) continue; */
+               if (strcasecmp(item->key, "Interval") == 0)
+                       cna_config_get_interval (item, &cfg_disk->interval);
+               else if (strcasecmp(item->key, "GetBusy") == 0)
+                       cna_config_bool_to_flag (item, &cfg_disk->flags, CFG_DISK_BUSIEST);
+       }
+
+       if ((cfg_disk->flags & CFG_DISK_ALL) == 0)
+       {
+               NOTICE ("netapp plugin: All disk related values have been disabled. "
+                               "Collection of per-disk data will be disabled entirely.");
+               free_cfg_disk (host->cfg_disk);
+               host->cfg_disk = NULL;
+       }
+
+       return (0);
+} /* }}} int cna_config_disk */
+
+/* Corresponds to a <WAFL /> block */
+static int cna_config_wafl(host_config_t *host, oconfig_item_t *ci) /* {{{ */
+{
+       cfg_wafl_t *cfg_wafl;
+       int i;
+
+       if ((host == NULL) || (ci == NULL))
+               return (EINVAL);
+
+       if (host->cfg_wafl == NULL)
+       {
+               cfg_wafl = malloc (sizeof (*cfg_wafl));
+               if (cfg_wafl == NULL)
+                       return (ENOMEM);
+               memset (cfg_wafl, 0, sizeof (*cfg_wafl));
+
+               /* Set default flags */
+               cfg_wafl->flags = CFG_WAFL_ALL;
+
+               host->cfg_wafl = cfg_wafl;
+       }
+       cfg_wafl = host->cfg_wafl;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+               
+               if (strcasecmp(item->key, "Interval") == 0)
+                       cna_config_get_interval (item, &cfg_wafl->interval);
+               else if (!strcasecmp(item->key, "GetNameCache"))
+                       cna_config_bool_to_flag (item, &cfg_wafl->flags, CFG_WAFL_NAME_CACHE);
+               else if (!strcasecmp(item->key, "GetDirCache"))
+                       cna_config_bool_to_flag (item, &cfg_wafl->flags, CFG_WAFL_DIR_CACHE);
+               else if (!strcasecmp(item->key, "GetBufferCache"))
+                       cna_config_bool_to_flag (item, &cfg_wafl->flags, CFG_WAFL_BUF_CACHE);
+               else if (!strcasecmp(item->key, "GetInodeCache"))
+                       cna_config_bool_to_flag (item, &cfg_wafl->flags, CFG_WAFL_INODE_CACHE);
+               else
+                       WARNING ("netapp plugin: The %s config option is not allowed within "
+                                       "`WAFL' blocks.", item->key);
+       }
+
+       if ((cfg_wafl->flags & CFG_WAFL_ALL) == 0)
+       {
+               NOTICE ("netapp plugin: All WAFL related values have been disabled. "
+                               "Collection of WAFL data will be disabled entirely.");
+               free_cfg_wafl (host->cfg_wafl);
+               host->cfg_wafl = NULL;
+       }
+
+       return (0);
+} /* }}} int cna_config_wafl */
+
+/*
+ * <VolumeUsage>
+ *   GetCapacity "vol0"
+ *   GetCapacity "vol1"
+ *   GetCapacity "vol2"
+ *   GetCapacity "vol3"
+ *   GetCapacity "vol4"
+ *   IgnoreSelectedCapacity false
+ *
+ *   GetSnapshot "vol0"
+ *   GetSnapshot "vol3"
+ *   GetSnapshot "vol4"
+ *   GetSnapshot "vol7"
+ *   IgnoreSelectedSnapshot false
+ * </VolumeUsage>
+ */
+/* Corresponds to a <VolumeUsage /> block */
+static int cna_config_volume_usage(host_config_t *host, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       cfg_volume_usage_t *cfg_volume_usage;
+       int i;
+
+       if ((host == NULL) || (ci == NULL))
+               return (EINVAL);
+
+       if (host->cfg_volume_usage == NULL)
+       {
+               cfg_volume_usage = malloc (sizeof (*cfg_volume_usage));
+               if (cfg_volume_usage == NULL)
+                       return (ENOMEM);
+               memset (cfg_volume_usage, 0, sizeof (*cfg_volume_usage));
+
+               /* Set default flags */
+               cfg_volume_usage->query = NULL;
+               cfg_volume_usage->volumes = NULL;
+
+               cfg_volume_usage->il_capacity = ignorelist_create (/* invert = */ 1);
+               if (cfg_volume_usage->il_capacity == NULL)
+               {
+                       sfree (cfg_volume_usage);
+                       return (ENOMEM);
+               }
+
+               cfg_volume_usage->il_snapshot = ignorelist_create (/* invert = */ 1);
+               if (cfg_volume_usage->il_snapshot == NULL)
+               {
+                       ignorelist_free (cfg_volume_usage->il_capacity);
+                       sfree (cfg_volume_usage);
+                       return (ENOMEM);
+               }
+
+               host->cfg_volume_usage = cfg_volume_usage;
+       }
+       cfg_volume_usage = host->cfg_volume_usage;
+       
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+               
+               /* if (!item || !item->key || !*item->key) continue; */
+               if (strcasecmp(item->key, "Interval") == 0)
+                       cna_config_get_interval (item, &cfg_volume_usage->interval);
+               else if (!strcasecmp(item->key, "GetCapacity"))
+                       cna_config_volume_usage_option (cfg_volume_usage, item);
+               else if (!strcasecmp(item->key, "GetSnapshot"))
+                       cna_config_volume_usage_option (cfg_volume_usage, item);
+               else if (!strcasecmp(item->key, "IgnoreSelectedCapacity"))
+                       cna_config_volume_usage_default (cfg_volume_usage, item);
+               else if (!strcasecmp(item->key, "IgnoreSelectedSnapshot"))
+                       cna_config_volume_usage_default (cfg_volume_usage, item);
+               else
+                       WARNING ("netapp plugin: The option %s is not allowed within "
+                                       "`VolumeUsage' blocks.", item->key);
+       }
+
+       return (0);
+} /* }}} int cna_config_volume_usage */
+
+/* Corresponds to a <SnapVault /> block */
+static int cna_config_snapvault (host_config_t *host, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       cfg_snapvault_t *cfg_snapvault;
+       int i;
+
+       if ((host == NULL) || (ci == NULL))
+               return EINVAL;
+
+       if (host->cfg_snapvault == NULL)
+       {
+               cfg_snapvault = malloc (sizeof (*cfg_snapvault));
+               if (cfg_snapvault == NULL)
+                       return ENOMEM;
+               memset (cfg_snapvault, 0, sizeof (*cfg_snapvault));
+               cfg_snapvault->query = NULL;
+
+               host->cfg_snapvault = cfg_snapvault;
+       }
+
+       cfg_snapvault = host->cfg_snapvault;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+
+               if (strcasecmp (item->key, "Interval") == 0)
+                       cna_config_get_interval (item, &cfg_snapvault->interval);
+               else
+                       WARNING ("netapp plugin: The option %s is not allowed within "
+                                       "`SnapVault' blocks.", item->key);
+       }
+
+       return 0;
+} /* }}} int cna_config_snapvault */
+
+/* Corresponds to a <System /> block */
+static int cna_config_system (host_config_t *host, /* {{{ */
+               oconfig_item_t *ci)
+{
+       cfg_system_t *cfg_system;
+       int i;
+       
+       if ((host == NULL) || (ci == NULL))
+               return (EINVAL);
+
+       if (host->cfg_system == NULL)
+       {
+               cfg_system = malloc (sizeof (*cfg_system));
+               if (cfg_system == NULL)
+                       return (ENOMEM);
+               memset (cfg_system, 0, sizeof (*cfg_system));
+
+               /* Set default flags */
+               cfg_system->flags = CFG_SYSTEM_ALL;
+               cfg_system->query = NULL;
+
+               host->cfg_system = cfg_system;
+       }
+       cfg_system = host->cfg_system;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+
+               if (strcasecmp(item->key, "Interval") == 0) {
+                       cna_config_get_interval (item, &cfg_system->interval);
+               } else if (!strcasecmp(item->key, "GetCPULoad")) {
+                       cna_config_bool_to_flag (item, &cfg_system->flags, CFG_SYSTEM_CPU);
+               } else if (!strcasecmp(item->key, "GetInterfaces")) {
+                       cna_config_bool_to_flag (item, &cfg_system->flags, CFG_SYSTEM_NET);
+               } else if (!strcasecmp(item->key, "GetDiskOps")) {
+                       cna_config_bool_to_flag (item, &cfg_system->flags, CFG_SYSTEM_OPS);
+               } else if (!strcasecmp(item->key, "GetDiskIO")) {
+                       cna_config_bool_to_flag (item, &cfg_system->flags, CFG_SYSTEM_DISK);
+               } else {
+                       WARNING ("netapp plugin: The %s config option is not allowed within "
+                                       "`System' blocks.", item->key);
+               }
+       }
+
+       if ((cfg_system->flags & CFG_SYSTEM_ALL) == 0)
+       {
+               NOTICE ("netapp plugin: All system related values have been disabled. "
+                               "Collection of system data will be disabled entirely.");
+               free_cfg_system (host->cfg_system);
+               host->cfg_system = NULL;
+       }
+
+       return (0);
+} /* }}} int cna_config_system */
+
+/* Corresponds to a <Host /> block. */
+static host_config_t *cna_alloc_host (void) /* {{{ */
+{
+       host_config_t *host;
+
+       host = malloc(sizeof(*host));
+       if (! host)
+               return (NULL);
+       memset (host, 0, sizeof (*host));
+
+       host->name = NULL;
+       host->protocol = NA_SERVER_TRANSPORT_HTTPS;
+       host->host = NULL;
+       host->username = NULL;
+       host->password = NULL;
+       host->vfiler = NULL;
+       host->srv = NULL;
+       host->cfg_wafl = NULL;
+       host->cfg_disk = NULL;
+       host->cfg_volume_perf = NULL;
+       host->cfg_volume_usage = NULL;
+       host->cfg_quota = NULL;
+       host->cfg_snapvault = NULL;
+       host->cfg_system = NULL;
+
+       return (host);
+} /* }}} host_config_t *cna_alloc_host */
+
+static host_config_t *cna_shallow_clone_host (host_config_t *host) /* {{{ */
+{
+       host_config_t *clone;
+
+       if (host == NULL)
+               return (NULL);
+
+       clone = cna_alloc_host ();
+       if (clone == NULL)
+               return (NULL);
+
+       if (host->name != NULL) {
+               clone->name = strdup (host->name);
+               if (clone->name == NULL) {
+                       free_host_config (clone);
+                       return NULL;
+               }
+       }
+
+       clone->protocol = host->protocol;
+
+       if (host->host != NULL) {
+               clone->host = strdup (host->host);
+               if (clone->host == NULL) {
+                       free_host_config (clone);
+                       return NULL;
+               }
+       }
+
+       clone->port = host->port;
+
+       if (host->username != NULL) {
+               clone->username = strdup (host->username);
+               if (clone->username == NULL) {
+                       free_host_config (clone);
+                       return NULL;
+               }
+       }
+       if (host->password != NULL) {
+               clone->password = strdup (host->password);
+               if (clone->password == NULL) {
+                       free_host_config (clone);
+                       return NULL;
+               }
+       }
+
+       clone->interval = host->interval;
+
+       return (clone);
+} /* }}} host_config_t *cna_shallow_clone_host */
+
+static int cna_read (user_data_t *ud);
+
+static int cna_register_host (host_config_t *host) /* {{{ */
+{
+       char cb_name[256];
+       struct timespec interval;
+       user_data_t ud;
+
+       if (host->vfiler)
+               ssnprintf (cb_name, sizeof (cb_name), "netapp-%s-%s",
+                               host->name, host->vfiler);
+       else
+               ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
+
+       CDTIME_T_TO_TIMESPEC (host->interval, &interval);
+
+       memset (&ud, 0, sizeof (ud));
+       ud.data = host;
+       ud.free_func = (void (*) (void *)) free_host_config;
+
+       plugin_register_complex_read (/* group = */ NULL, cb_name,
+                       /* callback  = */ cna_read,
+                       /* interval  = */ (host->interval > 0) ? &interval : NULL,
+                       /* user data = */ &ud);
+
+       return (0);
+} /* }}} int cna_register_host */
+
+static int cna_config_host (host_config_t *host, /* {{{ */
+               const oconfig_item_t *ci)
+{
+       oconfig_item_t *item;
+       _Bool is_vfiler = 0;
+       int status;
+       int i;
+
+       if (! strcasecmp (ci->key, "VFiler"))
+               is_vfiler = 1;
+
+       if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
+               WARNING ("netapp plugin: \"%s\" needs exactly one string argument. Ignoring host block.", ci->key);
+               return (1);
+       }
+
+       status = cf_util_get_string (ci, &host->name);
+       if (status != 0)
+               return (1);
+
+       for (i = 0; i < ci->children_num; ++i) {
+               item = ci->children + i;
+
+               status = 0;
+
+               if (!strcasecmp(item->key, "Address")) {
+                       status = cf_util_get_string (item, &host->host);
+               } else if (!strcasecmp(item->key, "Port")) {
+                       int tmp;
+
+                       tmp = cf_util_get_port_number (item);
+                       if (tmp > 0)
+                               host->port = tmp;
+               } else if (!strcasecmp(item->key, "Protocol")) {
+                       if ((item->values_num != 1) || (item->values[0].type != OCONFIG_TYPE_STRING) || (strcasecmp(item->values[0].value.string, "http") && strcasecmp(item->values[0].value.string, "https"))) {
+                               WARNING("netapp plugin: \"Protocol\" needs to be either \"http\" or \"https\". Ignoring host block \"%s\".", ci->values[0].value.string);
+                               return (1);
+                       }
+                       if (!strcasecmp(item->values[0].value.string, "http")) host->protocol = NA_SERVER_TRANSPORT_HTTP;
+                       else host->protocol = NA_SERVER_TRANSPORT_HTTPS;
+               } else if (!strcasecmp(item->key, "User")) {
+                       status = cf_util_get_string (item, &host->username);
+               } else if (!strcasecmp(item->key, "Password")) {
+                       status = cf_util_get_string (item, &host->password);
+               } else if (!strcasecmp(item->key, "Interval")) {
+                       status = cf_util_get_cdtime (item, &host->interval);
+               } else if (!strcasecmp(item->key, "WAFL")) {
+                       cna_config_wafl(host, item);
+               } else if (!strcasecmp(item->key, "Disks")) {
+                       cna_config_disk(host, item);
+               } else if (!strcasecmp(item->key, "VolumePerf")) {
+                       cna_config_volume_performance(host, item);
+               } else if (!strcasecmp(item->key, "VolumeUsage")) {
+                       cna_config_volume_usage(host, item);
+               } else if (!strcasecmp(item->key, "Quota")) {
+                       cna_config_quota(host, item);
+               } else if (!strcasecmp(item->key, "SnapVault")) {
+                       cna_config_snapvault(host, item);
+               } else if (!strcasecmp(item->key, "System")) {
+                       cna_config_system(host, item);
+               } else if ((!strcasecmp(item->key, "VFiler")) && (! is_vfiler)) {
+                       host_config_t *vfiler;
+
+                       vfiler = cna_shallow_clone_host (host);
+                       if (! vfiler) {
+                               ERROR ("netapp plugin: Failed to allocate host object for vfiler.");
+                               continue;
+                       }
+
+                       if (cna_config_host (vfiler, item)) {
+                               free_host_config (vfiler);
+                               continue;
+                       }
+
+                       cna_register_host (vfiler);
+               } else if ((!strcasecmp(item->key, "VFilerName")) && is_vfiler) {
+                       status = cf_util_get_string (item, &host->vfiler);
+               } else {
+                       WARNING ("netapp plugin: Ignoring unknown config option \"%s\" in %s block \"%s\".",
+                                       item->key, is_vfiler ? "vfiler" : "host", ci->values[0].value.string);
+               }
+
+               if (status != 0)
+                       break;
+       }
+
+       if (host->host == NULL)
+               host->host = strdup (host->name);
+
+       if (is_vfiler && (! host->vfiler))
+               host->vfiler = strdup (host->name);
+
+       if (host->host == NULL)
+               status = -1;
+
+       if (host->port <= 0)
+               host->port = (host->protocol == NA_SERVER_TRANSPORT_HTTP) ? 80 : 443;
+
+       if ((host->username == NULL) || (host->password == NULL)) {
+               WARNING("netapp plugin: Please supply login information for host \"%s\". "
+                               "Ignoring host block.", host->name);
+               status = -1;
+       }
+
+       if (status != 0)
+               return status;
+
+       return (0);
+} /* }}} host_config_t *cna_config_host */
+
+/*
+ * Callbacks registered with the daemon
+ *
+ * Pretty standard stuff here.
+ */
+static int cna_init_host (host_config_t *host) /* {{{ */
+{
+       /* Request version 1.1 of the ONTAP API */
+       int major_version = 1, minor_version = 1;
+
+       if (host == NULL)
+               return (EINVAL);
+
+       if (host->srv != NULL)
+               return (0);
+
+       if (host->vfiler != NULL) /* Request version 1.7 of the ONTAP API */
+               minor_version = 7;
+
+       host->srv = na_server_open (host->host, major_version, minor_version);
+       if (host->srv == NULL) {
+               ERROR ("netapp plugin: na_server_open (%s) failed.", host->host);
+               return (-1);
+       }
+
+       na_server_set_transport_type(host->srv, host->protocol,
+                       /* transportarg = */ NULL);
+       na_server_set_port(host->srv, host->port);
+       na_server_style(host->srv, NA_STYLE_LOGIN_PASSWORD);
+       na_server_adminuser(host->srv, host->username, host->password);
+       na_server_set_timeout(host->srv, 5 /* seconds */);
+
+       if (host->vfiler != NULL) {
+               if (! na_server_set_vfiler (host->srv, host->vfiler)) {
+                       ERROR ("netapp plugin: Failed to connect to VFiler '%s' on host '%s'.",
+                                       host->vfiler, host->host);
+                       return (-1);
+               }
+               else {
+                       INFO ("netapp plugin: Connected to VFiler '%s' on host '%s'.",
+                                       host->vfiler, host->host);
+               }
+       }
+
+       return (0);
+} /* }}} int cna_init_host */
+
+static int cna_init (void) /* {{{ */
+{
+       char err[256];
+
+       memset (err, 0, sizeof (err));
+       if (!na_startup(err, sizeof(err))) {
+               err[sizeof (err) - 1] = 0;
+               ERROR("netapp plugin: Error initializing netapp API: %s", err);
+               return 1;
+       }
+
+       return (0);
+} /* }}} cna_init */
+
+static int cna_read_internal (host_config_t *host) { /* {{{ */
+       int status;
+
+       status = cna_query_wafl (host);
+       if (status != 0)
+               return (status);
+
+       status = cna_query_disk (host);
+       if (status != 0)
+               return (status);
+
+       status = cna_query_volume_perf (host);
+       if (status != 0)
+               return (status);
+
+       status = cna_query_volume_usage (host);
+       if (status != 0)
+               return (status);
+
+       status = cna_query_quota (host);
+       if (status != 0)
+               return (status);
+
+       status = cna_query_snapvault (host);
+       if (status != 0)
+               return (status);
+
+       status = cna_query_system (host);
+       if (status != 0)
+               return (status);
+
+       return 0;
+} /* }}} int cna_read_internal */
+
+static int cna_read (user_data_t *ud) { /* {{{ */
+       host_config_t *host;
+       int status;
+
+       if ((ud == NULL) || (ud->data == NULL))
+               return (-1);
+
+       host = ud->data;
+
+       status = cna_init_host (host);
+       if (status != 0)
+               return (status);
+
+       status = cna_read_internal (host);
+       if (status != 0)
+       {
+               if (host->srv != NULL)
+                       na_server_close (host->srv);
+               host->srv = NULL;
+       }
+
+       return 0;
+} /* }}} int cna_read */
+
+static int cna_config (oconfig_item_t *ci) { /* {{{ */
+       int i;
+       oconfig_item_t *item;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               item = ci->children + i;
+
+               if (strcasecmp(item->key, "Host") == 0)
+               {
+                       host_config_t *host;
+
+                       host = cna_alloc_host ();
+                       if (host == NULL) {
+                               ERROR ("netapp plugin: Failed to allocate host object.");
+                               continue;
+                       }
+
+                       if (cna_config_host (host, item) != 0) {
+                               free_host_config (host);
+                               continue;
+                       }
+
+                       cna_register_host (host);
+               }
+               else /* if (item->key != "Host") */
+               {
+                       WARNING("netapp plugin: Ignoring unknown config option \"%s\".", item->key);
+               }
+       }
+       return 0;
+} /* }}} int cna_config */
+
+static int cna_shutdown (void) /* {{{ */
+{
+       /* Clean up system resources and stuff. */
+       na_shutdown ();
+
+       return (0);
+} /* }}} int cna_shutdown */
+
+void module_register(void) {
+       plugin_register_complex_config("netapp", cna_config);
+       plugin_register_init("netapp", cna_init);
+       plugin_register_shutdown("netapp", cna_shutdown);
+}
+
+/* vim: set sw=2 ts=2 noet fdm=marker : */
diff --git a/src/netlink.c b/src/netlink.c
new file mode 100644 (file)
index 0000000..aa9760f
--- /dev/null
@@ -0,0 +1,841 @@
+/**
+ * collectd - src/netlink.c
+ * Copyright (C) 2007-2010  Florian octo Forster
+ * Copyright (C) 2008-2012  Sebastian Harl
+ * Copyright (C) 2013       Andreas Henriksson
+ * Copyright (C) 2013       Marc Fournier
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Andreas Henriksson <andreas at fatal.se>
+ *   Marc Fournier <marc.fournier at camptocamp.com>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+
+#include <asm/types.h>
+#include <sys/socket.h>
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#if HAVE_LINUX_GEN_STATS_H
+# include <linux/gen_stats.h>
+#endif
+#if HAVE_LINUX_PKT_SCHED_H
+# include <linux/pkt_sched.h>
+#endif
+
+#include <libmnl/libmnl.h>
+
+struct ir_link_stats_storage_s {
+
+  uint64_t rx_packets;
+  uint64_t tx_packets;
+  uint64_t rx_bytes;
+  uint64_t tx_bytes;
+  uint64_t rx_errors;
+  uint64_t tx_errors;
+
+  uint64_t rx_dropped;
+  uint64_t tx_dropped;
+  uint64_t multicast;
+  uint64_t collisions;
+
+  uint64_t rx_length_errors;
+  uint64_t rx_over_errors;
+  uint64_t rx_crc_errors;
+  uint64_t rx_frame_errors;
+  uint64_t rx_fifo_errors;
+  uint64_t rx_missed_errors;
+
+  uint64_t tx_aborted_errors;
+  uint64_t tx_carrier_errors;
+  uint64_t tx_fifo_errors;
+  uint64_t tx_heartbeat_errors;
+  uint64_t tx_window_errors;
+};
+
+union ir_link_stats_u {
+  struct rtnl_link_stats *stats32;
+#ifdef HAVE_RTNL_LINK_STATS64
+  struct rtnl_link_stats64 *stats64;
+#endif
+};
+
+typedef struct ir_ignorelist_s
+{
+  char *device;
+  char *type;
+  char *inst;
+  struct ir_ignorelist_s *next;
+} ir_ignorelist_t;
+
+static int ir_ignorelist_invert = 1;
+static ir_ignorelist_t *ir_ignorelist_head = NULL;
+
+static struct mnl_socket *nl;
+
+static char **iflist = NULL;
+static size_t iflist_len = 0;
+
+static const char *config_keys[] =
+{
+        "Interface",
+        "VerboseInterface",
+        "QDisc",
+        "Class",
+        "Filter",
+        "IgnoreSelected"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int add_ignorelist (const char *dev, const char *type,
+    const char *inst)
+{
+  ir_ignorelist_t *entry;
+
+  entry = (ir_ignorelist_t *) malloc (sizeof (ir_ignorelist_t));
+  if (entry == NULL)
+    return (-1);
+
+  memset (entry, '\0', sizeof (ir_ignorelist_t));
+
+  if (strcasecmp (dev, "All") != 0)
+  {
+    entry->device = strdup (dev);
+    if (entry->device == NULL)
+    {
+      sfree (entry);
+      return (-1);
+    }
+  }
+
+  entry->type = strdup (type);
+  if (entry->type == NULL)
+  {
+    sfree (entry->device);
+    sfree (entry);
+    return (-1);
+  }
+
+  if (inst != NULL)
+  {
+    entry->inst = strdup (inst);
+    if (entry->inst == NULL)
+    {
+      sfree (entry->type);
+      sfree (entry->device);
+      sfree (entry);
+      return (-1);
+    }
+  }
+
+  entry->next = ir_ignorelist_head;
+  ir_ignorelist_head = entry;
+
+  return (0);
+} /* int add_ignorelist */
+
+/*
+ * Checks wether a data set should be ignored. Returns `true' is the value
+ * should be ignored, `false' otherwise.
+ */
+static int check_ignorelist (const char *dev,
+    const char *type, const char *type_instance)
+{
+  ir_ignorelist_t *i;
+
+  assert ((dev != NULL) && (type != NULL));
+
+  if (ir_ignorelist_head == NULL)
+    return (ir_ignorelist_invert ? 0 : 1);
+
+  for (i = ir_ignorelist_head; i != NULL; i = i->next)
+  {
+    /* i->device == NULL  =>  match all devices */
+    if ((i->device != NULL)
+        && (strcasecmp (i->device, dev) != 0))
+      continue;
+
+    if (strcasecmp (i->type, type) != 0)
+      continue;
+
+    if ((i->inst != NULL) && (type_instance != NULL)
+        && (strcasecmp (i->inst, type_instance) != 0))
+      continue;
+
+    DEBUG ("netlink plugin: check_ignorelist: "
+        "(dev = %s; type = %s; inst = %s) matched "
+        "(dev = %s; type = %s; inst = %s)",
+        dev, type,
+        type_instance == NULL ? "(nil)" : type_instance,
+        i->device == NULL ? "(nil)" : i->device,
+        i->type,
+        i->inst == NULL ? "(nil)" : i->inst);
+
+    return (ir_ignorelist_invert ? 0 : 1);
+  } /* for i */
+
+  return (ir_ignorelist_invert);
+} /* int check_ignorelist */
+
+static void submit_one (const char *dev, const char *type,
+    const char *type_instance, derive_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].derive = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void submit_one */
+
+static void submit_two (const char *dev, const char *type,
+    const char *type_instance,
+    derive_t rx, derive_t tx)
+{
+  value_t values[2];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].derive = rx;
+  values[1].derive = tx;
+
+  vl.values = values;
+  vl.values_len = 2;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void submit_two */
+
+static int update_iflist (struct ifinfomsg *msg, const char *dev)
+{
+  /* Update the `iflist'. It's used to know which interfaces exist and query
+   * them later for qdiscs and classes. */
+  if ((msg->ifi_index >= 0) && ((size_t) msg->ifi_index >= iflist_len))
+  {
+    char **temp;
+
+    temp = (char **) realloc (iflist, (msg->ifi_index + 1) * sizeof (char *));
+    if (temp == NULL)
+    {
+      ERROR ("netlink plugin: update_iflist: realloc failed.");
+      return (-1);
+    }
+
+    memset (temp + iflist_len, '\0',
+        (msg->ifi_index + 1 - iflist_len) * sizeof (char *));
+    iflist = temp;
+    iflist_len = msg->ifi_index + 1;
+  }
+  if ((iflist[msg->ifi_index] == NULL)
+      || (strcmp (iflist[msg->ifi_index], dev) != 0))
+  {
+    sfree (iflist[msg->ifi_index]);
+    iflist[msg->ifi_index] = strdup (dev);
+  }
+
+  return (0);
+} /* int update_iflist */
+
+static void check_ignorelist_and_submit (const char *dev,
+    struct ir_link_stats_storage_s *stats)
+{
+
+  if (check_ignorelist (dev, "interface", NULL) == 0)
+  {
+    submit_two (dev, "if_octets", NULL, stats->rx_bytes, stats->tx_bytes);
+    submit_two (dev, "if_packets", NULL, stats->rx_packets, stats->tx_packets);
+    submit_two (dev, "if_errors", NULL, stats->rx_errors, stats->tx_errors);
+  }
+  else
+  {
+    DEBUG ("netlink plugin: Ignoring %s/interface.", dev);
+  }
+
+  if (check_ignorelist (dev, "if_detail", NULL) == 0)
+  {
+    submit_two (dev, "if_dropped", NULL, stats->rx_dropped, stats->tx_dropped);
+    submit_one (dev, "if_multicast", NULL, stats->multicast);
+    submit_one (dev, "if_collisions", NULL, stats->collisions);
+
+    submit_one (dev, "if_rx_errors", "length", stats->rx_length_errors);
+    submit_one (dev, "if_rx_errors", "over", stats->rx_over_errors);
+    submit_one (dev, "if_rx_errors", "crc", stats->rx_crc_errors);
+    submit_one (dev, "if_rx_errors", "frame", stats->rx_frame_errors);
+    submit_one (dev, "if_rx_errors", "fifo", stats->rx_fifo_errors);
+    submit_one (dev, "if_rx_errors", "missed", stats->rx_missed_errors);
+
+    submit_one (dev, "if_tx_errors", "aborted", stats->tx_aborted_errors);
+    submit_one (dev, "if_tx_errors", "carrier", stats->tx_carrier_errors);
+    submit_one (dev, "if_tx_errors", "fifo", stats->tx_fifo_errors);
+    submit_one (dev, "if_tx_errors", "heartbeat", stats->tx_heartbeat_errors);
+    submit_one (dev, "if_tx_errors", "window", stats->tx_window_errors);
+  }
+  else
+  {
+    DEBUG ("netlink plugin: Ignoring %s/if_detail.", dev);
+  }
+
+} /* void check_ignorelist_and_submit */
+
+#define COPY_RTNL_LINK_VALUE(dst_stats, src_stats, value_name) \
+  (dst_stats)->value_name = (src_stats)->value_name
+
+#define COPY_RTNL_LINK_STATS(dst_stats, src_stats) \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_packets); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_packets); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_bytes); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_bytes); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_dropped); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_dropped); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, multicast); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, collisions); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_length_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_over_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_crc_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_frame_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_fifo_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_missed_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_aborted_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_carrier_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_fifo_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_heartbeat_errors); \
+  COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_window_errors)
+
+#ifdef HAVE_RTNL_LINK_STATS64
+static void check_ignorelist_and_submit64 (const char *dev,
+    struct rtnl_link_stats64 *stats)
+{
+  struct ir_link_stats_storage_s s;
+
+  COPY_RTNL_LINK_STATS (&s, stats);
+
+  check_ignorelist_and_submit (dev, &s);
+}
+#endif
+
+static void check_ignorelist_and_submit32 (const char *dev,
+    struct rtnl_link_stats *stats)
+{
+  struct ir_link_stats_storage_s s;
+
+  COPY_RTNL_LINK_STATS(&s, stats);
+
+  check_ignorelist_and_submit (dev, &s);
+}
+
+static int link_filter_cb (const struct nlmsghdr *nlh,
+    void *args __attribute__((unused)))
+{
+  struct ifinfomsg *ifm = mnl_nlmsg_get_payload (nlh);
+  struct nlattr *attr;
+  const char *dev = NULL;
+  union ir_link_stats_u stats;
+
+  if (nlh->nlmsg_type != RTM_NEWLINK)
+  {
+    ERROR ("netlink plugin: link_filter_cb: Don't know how to handle type %i.",
+        nlh->nlmsg_type);
+    return MNL_CB_ERROR;
+  }
+
+  /* Scan attribute list for device name. */
+  mnl_attr_for_each (attr, nlh, sizeof (*ifm))
+  {
+    if (mnl_attr_get_type (attr) != IFLA_IFNAME)
+      continue;
+
+    if (mnl_attr_validate (attr, MNL_TYPE_STRING) < 0)
+    {
+      ERROR ("netlink plugin: link_filter_cb: IFLA_IFNAME mnl_attr_validate failed.");
+      return MNL_CB_ERROR;
+    }
+
+    dev = mnl_attr_get_str (attr);
+    if (update_iflist (ifm, dev) < 0)
+      return MNL_CB_ERROR;
+    break;
+  }
+
+  if (dev == NULL)
+  {
+    ERROR ("netlink plugin: link_filter_cb: dev == NULL");
+    return MNL_CB_ERROR;
+  }
+#ifdef HAVE_RTNL_LINK_STATS64
+  mnl_attr_for_each (attr, nlh, sizeof (*ifm))
+  {
+    if (mnl_attr_get_type (attr) != IFLA_STATS64)
+      continue;
+
+    if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats.stats64)) < 0)
+    {
+      ERROR ("netlink plugin: link_filter_cb: IFLA_STATS64 mnl_attr_validate2 failed.");
+      return MNL_CB_ERROR;
+    }
+    stats.stats64 = mnl_attr_get_payload (attr);
+
+    check_ignorelist_and_submit64 (dev, stats.stats64);
+
+    return MNL_CB_OK;
+  }
+#endif
+  mnl_attr_for_each (attr, nlh, sizeof (*ifm))
+  {
+    if (mnl_attr_get_type (attr) != IFLA_STATS)
+      continue;
+
+    if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats.stats32)) < 0)
+    {
+      ERROR ("netlink plugin: link_filter_cb: IFLA_STATS mnl_attr_validate2 failed.");
+      return MNL_CB_ERROR;
+    }
+    stats.stats32 = mnl_attr_get_payload (attr);
+
+    check_ignorelist_and_submit32 (dev, stats.stats32);
+
+    return MNL_CB_OK;
+  }
+
+  DEBUG ("netlink plugin: link_filter: No statistics for interface %s.", dev);
+  return MNL_CB_OK;
+
+} /* int link_filter_cb */
+
+#if HAVE_TCA_STATS2
+static int qos_attr_cb (const struct nlattr *attr, void *data)
+{
+  struct gnet_stats_basic **bs = (struct gnet_stats_basic **)data;
+
+  /* skip unsupported attribute in user-space */
+  if (mnl_attr_type_valid (attr, TCA_STATS_MAX) < 0)
+    return MNL_CB_OK;
+
+  if (mnl_attr_get_type (attr) == TCA_STATS_BASIC)
+  {
+    if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (**bs)) < 0)
+    {
+      ERROR ("netlink plugin: qos_attr_cb: TCA_STATS_BASIC mnl_attr_validate2 failed.");
+      return MNL_CB_ERROR;
+    }
+    *bs = mnl_attr_get_payload (attr);
+    return MNL_CB_STOP;
+  }
+
+  return MNL_CB_OK;
+} /* qos_attr_cb */
+#endif
+
+static int qos_filter_cb (const struct nlmsghdr *nlh, void *args)
+{
+  struct tcmsg *tm = mnl_nlmsg_get_payload (nlh);
+  struct nlattr *attr;
+
+  int wanted_ifindex = *((int *) args);
+
+  const char *dev;
+  const char *kind = NULL;
+
+  /* char *type_instance; */
+  char *tc_type;
+  char tc_inst[DATA_MAX_NAME_LEN];
+
+  _Bool stats_submitted = 0;
+
+  if (nlh->nlmsg_type == RTM_NEWQDISC)
+    tc_type = "qdisc";
+  else if (nlh->nlmsg_type == RTM_NEWTCLASS)
+    tc_type = "class";
+  else if (nlh->nlmsg_type == RTM_NEWTFILTER)
+    tc_type = "filter";
+  else
+  {
+    ERROR ("netlink plugin: qos_filter_cb: Don't know how to handle type %i.",
+        nlh->nlmsg_type);
+    return MNL_CB_ERROR;
+  }
+
+  if (tm->tcm_ifindex != wanted_ifindex)
+  {
+    DEBUG ("netlink plugin: qos_filter_cb: Got %s for interface #%i, "
+        "but expected #%i.",
+        tc_type, tm->tcm_ifindex, wanted_ifindex);
+    return MNL_CB_OK;
+  }
+
+  if ((tm->tcm_ifindex >= 0)
+      && ((size_t) tm->tcm_ifindex >= iflist_len))
+  {
+    ERROR ("netlink plugin: qos_filter_cb: tm->tcm_ifindex = %i "
+        ">= iflist_len = %zu",
+        tm->tcm_ifindex, iflist_len);
+    return MNL_CB_ERROR;
+  }
+
+  dev = iflist[tm->tcm_ifindex];
+  if (dev == NULL)
+  {
+    ERROR ("netlink plugin: qos_filter_cb: iflist[%i] == NULL",
+        tm->tcm_ifindex);
+    return MNL_CB_ERROR;
+  }
+
+  mnl_attr_for_each (attr, nlh, sizeof (*tm))
+  {
+    if (mnl_attr_get_type (attr) != TCA_KIND)
+      continue;
+
+    if (mnl_attr_validate (attr, MNL_TYPE_STRING) < 0)
+    {
+      ERROR ("netlink plugin: qos_filter_cb: TCA_KIND mnl_attr_validate failed.");
+      return MNL_CB_ERROR;
+    }
+
+    kind = mnl_attr_get_str (attr);
+    break;
+  }
+
+  if (kind == NULL)
+  {
+    ERROR ("netlink plugin: qos_filter_cb: kind == NULL");
+    return (-1);
+  }
+
+  { /* The ID */
+    uint32_t numberic_id;
+
+    numberic_id = tm->tcm_handle;
+    if (strcmp (tc_type, "filter") == 0)
+      numberic_id = tm->tcm_parent;
+
+    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, tm->tcm_ifindex);
+
+  if (check_ignorelist (dev, tc_type, tc_inst))
+    return MNL_CB_OK;
+
+#if HAVE_TCA_STATS2
+  mnl_attr_for_each (attr, nlh, sizeof (*tm))
+  {
+    struct gnet_stats_basic *bs = NULL;
+
+    if (mnl_attr_get_type (attr) != TCA_STATS2)
+      continue;
+
+    if (mnl_attr_validate (attr, MNL_TYPE_NESTED) < 0)
+    {
+      ERROR ("netlink plugin: qos_filter_cb: TCA_STATS2 mnl_attr_validate failed.");
+      return MNL_CB_ERROR;
+    }
+
+    mnl_attr_parse_nested (attr, qos_attr_cb, &bs);
+
+    if (bs != NULL)
+    {
+      char type_instance[DATA_MAX_NAME_LEN];
+
+      stats_submitted = 1;
+
+      ssnprintf (type_instance, sizeof (type_instance), "%s-%s",
+          tc_type, tc_inst);
+
+      submit_one (dev, "ipt_bytes", type_instance, bs->bytes);
+      submit_one (dev, "ipt_packets", type_instance, bs->packets);
+    }
+
+    break;
+  }
+#endif /* TCA_STATS2 */
+
+#if HAVE_TCA_STATS
+  mnl_attr_for_each (attr, nlh, sizeof (*tm))
+  {
+    struct tc_stats *ts = NULL;
+
+    if (mnl_attr_get_type (attr) != TCA_STATS)
+      continue;
+
+    if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*ts)) < 0)
+    {
+      ERROR ("netlink plugin: qos_filter_cb: TCA_STATS mnl_attr_validate2 failed.");
+      return MNL_CB_ERROR;
+    }
+    ts = mnl_attr_get_payload (attr);
+
+    if (!stats_submitted && ts != NULL)
+    {
+      char type_instance[DATA_MAX_NAME_LEN];
+
+      ssnprintf (type_instance, sizeof (type_instance), "%s-%s",
+          tc_type, tc_inst);
+
+      submit_one (dev, "ipt_bytes", type_instance, ts->bytes);
+      submit_one (dev, "ipt_packets", type_instance, ts->packets);
+    }
+
+    break;
+  }
+
+#endif /* TCA_STATS */
+
+#if !(HAVE_TCA_STATS && HAVE_TCA_STATS2)
+  DEBUG ("netlink plugin: qos_filter_cb: Have neither TCA_STATS2 nor "
+      "TCA_STATS.");
+#endif
+
+  return MNL_CB_OK;
+} /* int qos_filter_cb */
+
+static int ir_config (const char *key, const char *value)
+{
+  char *new_val;
+  char *fields[8];
+  int fields_num;
+  int status = 1;
+
+  new_val = strdup (value);
+  if (new_val == NULL)
+    return (-1);
+
+  fields_num = strsplit (new_val, fields, STATIC_ARRAY_SIZE (fields));
+  if ((fields_num < 1) || (fields_num > 8))
+  {
+    sfree (new_val);
+    return (-1);
+  }
+
+  if ((strcasecmp (key, "Interface") == 0)
+      || (strcasecmp (key, "VerboseInterface") == 0))
+  {
+    if (fields_num != 1)
+    {
+      ERROR ("netlink plugin: Invalid number of fields for option "
+          "`%s'. Got %i, expected 1.", key, fields_num);
+      status = -1;
+    }
+    else
+    {
+      add_ignorelist (fields[0], "interface", NULL);
+      if (strcasecmp (key, "VerboseInterface") == 0)
+        add_ignorelist (fields[0], "if_detail", NULL);
+      status = 0;
+    }
+  }
+  else if ((strcasecmp (key, "QDisc") == 0)
+      || (strcasecmp (key, "Class") == 0)
+      || (strcasecmp (key, "Filter") == 0))
+  {
+    if ((fields_num < 1) || (fields_num > 2))
+    {
+      ERROR ("netlink plugin: Invalid number of fields for option "
+          "`%s'. Got %i, expected 1 or 2.", key, fields_num);
+      return (-1);
+    }
+    else
+    {
+      add_ignorelist (fields[0], key,
+          (fields_num == 2) ? fields[1] : NULL);
+      status = 0;
+    }
+  }
+  else if (strcasecmp (key, "IgnoreSelected") == 0)
+  {
+    if (fields_num != 1)
+    {
+      ERROR ("netlink plugin: Invalid number of fields for option "
+          "`IgnoreSelected'. Got %i, expected 1.", fields_num);
+      status = -1;
+    }
+    else
+    {
+      if (IS_TRUE (fields[0]))
+        ir_ignorelist_invert = 0;
+      else
+        ir_ignorelist_invert = 1;
+      status = 0;
+    }
+  }
+
+  sfree (new_val);
+
+  return (status);
+} /* int ir_config */
+
+static int ir_init (void)
+{
+  nl = mnl_socket_open (NETLINK_ROUTE);
+  if (nl == NULL)
+  {
+    ERROR ("netlink plugin: ir_init: mnl_socket_open failed.");
+    return (-1);
+  }
+
+  if (mnl_socket_bind (nl, 0, MNL_SOCKET_AUTOPID) < 0)
+  {
+    ERROR ("netlink plugin: ir_init: mnl_socket_bind failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* int ir_init */
+
+static int ir_read (void)
+{
+  char buf[MNL_SOCKET_BUFFER_SIZE];
+  struct nlmsghdr *nlh;
+  struct rtgenmsg *rt;
+  int ret;
+  unsigned int seq, portid;
+
+  size_t ifindex;
+
+  static const int type_id[] = { RTM_GETQDISC, RTM_GETTCLASS, RTM_GETTFILTER };
+  static const char *type_name[] = { "qdisc", "class", "filter" };
+
+  portid = mnl_socket_get_portid (nl);
+
+  nlh = mnl_nlmsg_put_header (buf);
+  nlh->nlmsg_type = RTM_GETLINK;
+  nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+  nlh->nlmsg_seq = seq = time (NULL);
+  rt = mnl_nlmsg_put_extra_header (nlh, sizeof (*rt));
+  rt->rtgen_family = AF_PACKET;
+
+  if (mnl_socket_sendto (nl, nlh, nlh->nlmsg_len) < 0)
+  {
+    ERROR ("netlink plugin: ir_read: rtnl_wilddump_request failed.");
+    return (-1);
+  }
+
+  ret = mnl_socket_recvfrom (nl, buf, sizeof (buf));
+  while (ret > 0)
+  {
+    ret = mnl_cb_run (buf, ret, seq, portid, link_filter_cb, NULL);
+    if (ret <= MNL_CB_STOP)
+      break;
+    ret = mnl_socket_recvfrom (nl, buf, sizeof (buf));
+  }
+  if (ret < 0)
+  {
+    ERROR ("netlink plugin: ir_read: mnl_socket_recvfrom failed.");
+    return (-1);
+  }
+
+  /* `link_filter_cb' will update `iflist' which is used here to iterate
+   * over all interfaces. */
+  for (ifindex = 1; ifindex < iflist_len; ifindex++)
+  {
+    struct tcmsg *tm;
+    size_t type_index;
+
+    if (iflist[ifindex] == NULL)
+      continue;
+
+    for (type_index = 0; type_index < STATIC_ARRAY_SIZE (type_id); type_index++)
+    {
+      if (check_ignorelist (iflist[ifindex], type_name[type_index], NULL))
+      {
+        DEBUG ("netlink plugin: ir_read: check_ignorelist (%s, %s, (nil)) "
+            "== TRUE", iflist[ifindex], type_name[type_index]);
+        continue;
+      }
+
+      DEBUG ("netlink plugin: ir_read: querying %s from %s (%zu).",
+          type_name[type_index], iflist[ifindex], ifindex);
+
+      nlh = mnl_nlmsg_put_header (buf);
+      nlh->nlmsg_type = type_id[type_index];
+      nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+      nlh->nlmsg_seq = seq = time (NULL);
+      tm = mnl_nlmsg_put_extra_header (nlh, sizeof (*tm));
+      tm->tcm_family = AF_PACKET;
+      tm->tcm_ifindex = ifindex;
+
+      if (mnl_socket_sendto (nl, nlh, nlh->nlmsg_len) < 0)
+      {
+        ERROR ("netlink plugin: ir_read: mnl_socket_sendto failed.");
+        continue;
+      }
+
+      ret = mnl_socket_recvfrom (nl, buf, sizeof (buf));
+      while (ret > 0)
+      {
+        ret = mnl_cb_run (buf, ret, seq, portid, qos_filter_cb, &ifindex);
+        if (ret <= MNL_CB_STOP)
+          break;
+        ret = mnl_socket_recvfrom (nl, buf, sizeof (buf));
+      }
+      if (ret < 0)
+      {
+        ERROR ("netlink plugin: ir_read:mnl_socket_recvfrom failed.");
+        continue;
+      }
+
+    } /* for (type_index) */
+  } /* for (if_index) */
+
+  return (0);
+} /* int ir_read */
+
+static int ir_shutdown (void)
+{
+  if (nl)
+  {
+    mnl_socket_close (nl);
+    nl = NULL;
+  }
+
+  return (0);
+} /* int ir_shutdown */
+
+void module_register (void)
+{
+  plugin_register_config ("netlink", ir_config, config_keys, config_keys_num);
+  plugin_register_init ("netlink", ir_init);
+  plugin_register_read ("netlink", ir_read);
+  plugin_register_shutdown ("netlink", ir_shutdown);
+} /* void module_register */
+
+/*
+ * vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
+ */
diff --git a/src/network.c b/src/network.c
new file mode 100644 (file)
index 0000000..551bd5c
--- /dev/null
@@ -0,0 +1,3630 @@
+/**
+ * collectd - src/network.c
+ * Copyright (C) 2005-2013  Florian octo Forster
+ * Copyright (C) 2009       Aman Gupta
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; only version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Aman Gupta <aman at tmm1.net>
+ **/
+
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE /* For struct ip_mreq */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "utils_fbhash.h"
+#include "utils_avltree.h"
+#include "utils_cache.h"
+#include "utils_complain.h"
+
+#include "network.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#if HAVE_POLL_H
+# include <poll.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+#if HAVE_LIBGCRYPT
+# include <pthread.h>
+# if defined __APPLE__
+/* default xcode compiler throws warnings even when deprecated functionality
+ * is not used. -Werror breaks the build because of erroneous warnings.
+ * http://stackoverflow.com/questions/10556299/compiler-warnings-with-libgcrypt-v1-5-0/12830209#12830209
+ */
+#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+# endif
+/* FreeBSD's copy of libgcrypt extends the existing GCRYPT_NO_DEPRECATED
+ * to properly hide all deprecated functionality.
+ * http://svnweb.freebsd.org/ports/head/security/libgcrypt/files/patch-src__gcrypt.h.in
+ */
+# define GCRYPT_NO_DEPRECATED
+# include <gcrypt.h>
+# if defined __APPLE__
+/* Re enable deprecation warnings */
+#  pragma GCC diagnostic warning "-Wdeprecated-declarations"
+# endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
+#endif
+
+#ifndef IPV6_ADD_MEMBERSHIP
+# ifdef IPV6_JOIN_GROUP
+#  define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
+# else
+#  error "Neither IP_ADD_MEMBERSHIP nor IPV6_JOIN_GROUP is defined"
+# endif
+#endif /* !IP_ADD_MEMBERSHIP */
+
+/*
+ * Maximum size required for encryption / signing:
+ *
+ *    42 bytes for the encryption header
+ * +  64 bytes for the username
+ * -----------
+ * = 106 bytes
+ */
+#define BUFF_SIG_SIZE 106
+
+/*
+ * Private data types
+ */
+#define SECURITY_LEVEL_NONE     0
+#if HAVE_LIBGCRYPT
+# define SECURITY_LEVEL_SIGN    1
+# define SECURITY_LEVEL_ENCRYPT 2
+#endif
+struct sockent_client
+{
+       int fd;
+       struct sockaddr_storage *addr;
+       socklen_t                addrlen;
+#if HAVE_LIBGCRYPT
+       int security_level;
+       char *username;
+       char *password;
+       gcry_cipher_hd_t cypher;
+       unsigned char password_hash[32];
+#endif
+       cdtime_t next_resolve_reconnect;
+       cdtime_t resolve_interval;
+};
+
+struct sockent_server
+{
+       int *fd;
+       size_t fd_num;
+#if HAVE_LIBGCRYPT
+       int security_level;
+       char *auth_file;
+       fbhash_t *userdb;
+       gcry_cipher_hd_t cypher;
+#endif
+};
+
+typedef struct sockent
+{
+#define SOCKENT_TYPE_CLIENT 1
+#define SOCKENT_TYPE_SERVER 2
+       int type;
+
+       char *node;
+       char *service;
+       int interface;
+
+       union
+       {
+               struct sockent_client client;
+               struct sockent_server server;
+       } data;
+
+       struct sockent *next;
+} sockent_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------+-----------------------+-------------------------------+
+ * ! Ver.  !                       ! Length                        !
+ * +-------+-----------------------+-------------------------------+
+ */
+struct part_header_s
+{
+       uint16_t type;
+       uint16_t length;
+};
+typedef struct part_header_s part_header_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4) Bytes                                            :
+ * +---------------------------------------------------------------+
+ */
+struct part_string_s
+{
+       part_header_t *head;
+       char *value;
+};
+typedef struct part_string_s part_string_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4 == 2 || 4 || 8) Bytes                             :
+ * +---------------------------------------------------------------+
+ */
+struct part_number_s
+{
+       part_header_t *head;
+       uint64_t *value;
+};
+typedef struct part_number_s part_number_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+---------------+---------------+
+ * ! Num of values                 ! Type0         ! Type1         !
+ * +-------------------------------+---------------+---------------+
+ * ! Value0                                                        !
+ * !                                                               !
+ * +---------------------------------------------------------------+
+ * ! Value1                                                        !
+ * !                                                               !
+ * +---------------------------------------------------------------+
+ */
+struct part_values_s
+{
+       part_header_t *head;
+       uint16_t *num_values;
+       uint8_t  *values_types;
+       value_t  *values;
+};
+typedef struct part_values_s part_values_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+-------------------------------+
+ * ! Hash (Bits   0 -  31)                                         !
+ * : :                                                             :
+ * ! Hash (Bits 224 - 255)                                         !
+ * +---------------------------------------------------------------+
+ */
+/* Minimum size */
+#define PART_SIGNATURE_SHA256_SIZE 36
+struct part_signature_sha256_s
+{
+  part_header_t head;
+  unsigned char hash[32];
+  char *username;
+};
+typedef struct part_signature_sha256_s part_signature_sha256_t;
+
+/*                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type                          ! Length                        !
+ * +-------------------------------+-------------------------------+
+ * ! Original length               ! Padding (0 - 15 bytes)        !
+ * +-------------------------------+-------------------------------+
+ * ! Hash (Bits   0 -  31)                                         !
+ * : :                                                             :
+ * ! Hash (Bits 128 - 159)                                         !
+ * +---------------------------------------------------------------+
+ */
+/* Minimum size */
+#define PART_ENCRYPTION_AES256_SIZE 42
+struct part_encryption_aes256_s
+{
+  part_header_t head;
+  uint16_t username_length;
+  char *username;
+  unsigned char iv[16];
+  /* <encrypted> */
+  unsigned char hash[20];
+  /*   <payload /> */
+  /* </encrypted> */
+};
+typedef struct part_encryption_aes256_s part_encryption_aes256_t;
+
+struct receive_list_entry_s
+{
+  char *data;
+  int  data_len;
+  int  fd;
+  struct receive_list_entry_s *next;
+};
+typedef struct receive_list_entry_s receive_list_entry_t;
+
+/*
+ * Private variables
+ */
+static int network_config_ttl = 0;
+/* Ethernet - (IPv6 + UDP) = 1500 - (40 + 8) = 1452 */
+static size_t network_config_packet_size = 1452;
+static int network_config_forward = 0;
+static int network_config_stats = 0;
+
+static sockent_t *sending_sockets = NULL;
+
+static receive_list_entry_t *receive_list_head = NULL;
+static receive_list_entry_t *receive_list_tail = NULL;
+static pthread_mutex_t       receive_list_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t        receive_list_cond = PTHREAD_COND_INITIALIZER;
+static uint64_t              receive_list_length = 0;
+
+static sockent_t     *listen_sockets = NULL;
+static struct pollfd *listen_sockets_pollfd = NULL;
+static size_t         listen_sockets_num = 0;
+
+/* The receive and dispatch threads will run as long as `listen_loop' is set to
+ * zero. */
+static int       listen_loop = 0;
+static int       receive_thread_running = 0;
+static pthread_t receive_thread_id;
+static int       dispatch_thread_running = 0;
+static pthread_t dispatch_thread_id;
+
+/* Buffer in which to-be-sent network packets are constructed. */
+static char            *send_buffer;
+static char            *send_buffer_ptr;
+static int              send_buffer_fill;
+static value_list_t     send_buffer_vl = VALUE_LIST_STATIC;
+static pthread_mutex_t  send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* XXX: These counters are incremented from one place only. The spot in which
+ * the values are incremented is either only reachable by one thread (the
+ * dispatch thread, for example) or locked by some lock (send_buffer_lock for
+ * example). Only if neither is true, the stats_lock is acquired. The counters
+ * are always read without holding a lock in the hope that writing 8 bytes to
+ * memory is an atomic operation. */
+static derive_t stats_octets_rx  = 0;
+static derive_t stats_octets_tx  = 0;
+static derive_t stats_packets_rx = 0;
+static derive_t stats_packets_tx = 0;
+static derive_t stats_values_dispatched = 0;
+static derive_t stats_values_not_dispatched = 0;
+static derive_t stats_values_sent = 0;
+static derive_t stats_values_not_sent = 0;
+static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Private functions
+ */
+static _Bool check_receive_okay (const value_list_t *vl) /* {{{ */
+{
+  uint64_t time_sent = 0;
+  int status;
+
+  status = uc_meta_data_get_unsigned_int (vl,
+      "network:time_sent", &time_sent);
+
+  /* This is a value we already sent. Don't allow it to be received again in
+   * order to avoid looping. */
+  if ((status == 0) && (time_sent >= ((uint64_t) vl->time)))
+    return (0);
+
+  return (1);
+} /* }}} _Bool check_receive_okay */
+
+static _Bool check_send_okay (const value_list_t *vl) /* {{{ */
+{
+  _Bool received = 0;
+  int status;
+
+  if (network_config_forward != 0)
+    return (1);
+
+  if (vl->meta == NULL)
+    return (1);
+
+  status = meta_data_get_boolean (vl->meta, "network:received", &received);
+  if (status == -ENOENT)
+    return (1);
+  else if (status != 0)
+  {
+    ERROR ("network plugin: check_send_okay: meta_data_get_boolean failed "
+       "with status %i.", status);
+    return (1);
+  }
+
+  /* By default, only *send* value lists that were not *received* by the
+   * network plugin. */
+  return (!received);
+} /* }}} _Bool check_send_okay */
+
+static _Bool check_notify_received (const notification_t *n) /* {{{ */
+{
+  notification_meta_t *ptr;
+
+  for (ptr = n->meta; ptr != NULL; ptr = ptr->next)
+    if ((strcmp ("network:received", ptr->name) == 0)
+        && (ptr->type == NM_TYPE_BOOLEAN))
+      return ((_Bool) ptr->nm_value.nm_boolean);
+
+  return (0);
+} /* }}} _Bool check_notify_received */
+
+static _Bool check_send_notify_okay (const notification_t *n) /* {{{ */
+{
+  static c_complain_t complain_forwarding = C_COMPLAIN_INIT_STATIC;
+  _Bool received = 0;
+
+  if (n->meta == NULL)
+    return (1);
+
+  received = check_notify_received (n);
+
+  if (network_config_forward && received)
+  {
+    c_complain_once (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. "
+        "Please contact the collectd mailing list if you need this "
+        "feature.");
+  }
+
+  /* By default, only *send* value lists that were not *received* by the
+   * network plugin. */
+  return (!received);
+} /* }}} _Bool check_send_notify_okay */
+
+static int network_dispatch_values (value_list_t *vl, /* {{{ */
+    const char *username)
+{
+  int status;
+
+  if ((vl->time <= 0)
+      || (strlen (vl->host) <= 0)
+      || (strlen (vl->plugin) <= 0)
+      || (strlen (vl->type) <= 0))
+    return (-EINVAL);
+
+  if (!check_receive_okay (vl))
+  {
+#if COLLECT_DEBUG
+    char name[6*DATA_MAX_NAME_LEN];
+    FORMAT_VL (name, sizeof (name), vl);
+    name[sizeof (name) - 1] = 0;
+    DEBUG ("network plugin: network_dispatch_values: "
+       "NOT dispatching %s.", name);
+#endif
+    stats_values_not_dispatched++;
+    return (0);
+  }
+
+  assert (vl->meta == NULL);
+
+  vl->meta = meta_data_create ();
+  if (vl->meta == NULL)
+  {
+    ERROR ("network plugin: meta_data_create failed.");
+    return (-ENOMEM);
+  }
+
+  status = meta_data_add_boolean (vl->meta, "network:received", 1);
+  if (status != 0)
+  {
+    ERROR ("network plugin: meta_data_add_boolean failed.");
+    meta_data_destroy (vl->meta);
+    vl->meta = NULL;
+    return (status);
+  }
+
+  if (username != NULL)
+  {
+    status = meta_data_add_string (vl->meta, "network:username", username);
+    if (status != 0)
+    {
+      ERROR ("network plugin: meta_data_add_string failed.");
+      meta_data_destroy (vl->meta);
+      vl->meta = NULL;
+      return (status);
+    }
+  }
+
+  plugin_dispatch_values (vl);
+  stats_values_dispatched++;
+
+  meta_data_destroy (vl->meta);
+  vl->meta = NULL;
+
+  return (0);
+} /* }}} int network_dispatch_values */
+
+static int network_dispatch_notification (notification_t *n) /* {{{ */
+{
+  int status;
+
+  assert (n->meta == NULL);
+
+  status = plugin_notification_meta_add_boolean (n, "network:received", 1);
+  if (status != 0)
+  {
+    ERROR ("network plugin: plugin_notification_meta_add_boolean failed.");
+    plugin_notification_meta_free (n->meta);
+    n->meta = NULL;
+    return (status);
+  }
+
+  status = plugin_dispatch_notification (n);
+
+  plugin_notification_meta_free (n->meta);
+  n->meta = NULL;
+
+  return (status);
+} /* }}} int network_dispatch_notification */
+
+#if HAVE_LIBGCRYPT
+static void network_init_gcrypt (void) /* {{{ */
+{
+  /* http://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html
+   * Because you can't know in a library whether another library has
+   * already initialized the library */
+  if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
+    return;
+
+ /* http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
+  * To ensure thread-safety, it's important to set GCRYCTL_SET_THREAD_CBS
+  * *before* initalizing Libgcrypt with gcry_check_version(), which itself must
+  * be called before any other gcry_* function. GCRYCTL_ANY_INITIALIZATION_P
+  * above doesn't count, as it doesn't implicitly initalize Libgcrypt.
+  *
+  * tl;dr: keep all these gry_* statements in this exact order please. */
+# if GCRYPT_VERSION_NUMBER < 0x010600
+  gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
+  gcry_check_version (NULL);
+  gcry_control (GCRYCTL_INIT_SECMEM, 32768);
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
+} /* }}} void network_init_gcrypt */
+
+static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */
+    const void *iv, size_t iv_size, const char *username)
+{
+  gcry_error_t err;
+  gcry_cipher_hd_t *cyper_ptr;
+  unsigned char password_hash[32];
+
+  if (se->type == SOCKENT_TYPE_CLIENT)
+  {
+         cyper_ptr = &se->data.client.cypher;
+         memcpy (password_hash, se->data.client.password_hash,
+                         sizeof (password_hash));
+  }
+  else
+  {
+         char *secret;
+
+         cyper_ptr = &se->data.server.cypher;
+
+         if (username == NULL)
+                 return (NULL);
+
+         secret = fbh_get (se->data.server.userdb, username);
+         if (secret == NULL)
+                 return (NULL);
+
+         gcry_md_hash_buffer (GCRY_MD_SHA256,
+                         password_hash,
+                         secret, strlen (secret));
+
+         sfree (secret);
+  }
+
+  if (*cyper_ptr == NULL)
+  {
+    err = gcry_cipher_open (cyper_ptr,
+        GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB, /* flags = */ 0);
+    if (err != 0)
+    {
+      ERROR ("network plugin: gcry_cipher_open returned: %s",
+          gcry_strerror (err));
+      *cyper_ptr = NULL;
+      return (NULL);
+    }
+  }
+  else
+  {
+    gcry_cipher_reset (*cyper_ptr);
+  }
+  assert (*cyper_ptr != NULL);
+
+  err = gcry_cipher_setkey (*cyper_ptr,
+      password_hash, sizeof (password_hash));
+  if (err != 0)
+  {
+    ERROR ("network plugin: gcry_cipher_setkey returned: %s",
+        gcry_strerror (err));
+    gcry_cipher_close (*cyper_ptr);
+    *cyper_ptr = NULL;
+    return (NULL);
+  }
+
+  err = gcry_cipher_setiv (*cyper_ptr, iv, iv_size);
+  if (err != 0)
+  {
+    ERROR ("network plugin: gcry_cipher_setkey returned: %s",
+        gcry_strerror (err));
+    gcry_cipher_close (*cyper_ptr);
+    *cyper_ptr = NULL;
+    return (NULL);
+  }
+
+  return (*cyper_ptr);
+} /* }}} int network_get_aes256_cypher */
+#endif /* HAVE_LIBGCRYPT */
+
+static int write_part_values (char **ret_buffer, int *ret_buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       char *packet_ptr;
+       int packet_len;
+       int num_values;
+
+       part_header_t pkg_ph;
+       uint16_t      pkg_num_values;
+       uint8_t      *pkg_values_types;
+       value_t      *pkg_values;
+
+       int offset;
+       int i;
+
+       num_values = vl->values_len;
+       packet_len = sizeof (part_header_t) + sizeof (uint16_t)
+               + (num_values * sizeof (uint8_t))
+               + (num_values * sizeof (value_t));
+
+       if (*ret_buffer_len < packet_len)
+               return (-1);
+
+       pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t));
+       if (pkg_values_types == NULL)
+       {
+               ERROR ("network plugin: write_part_values: malloc failed.");
+               return (-1);
+       }
+
+       pkg_values = (value_t *) malloc (num_values * sizeof (value_t));
+       if (pkg_values == NULL)
+       {
+               free (pkg_values_types);
+               ERROR ("network plugin: write_part_values: malloc failed.");
+               return (-1);
+       }
+
+       pkg_ph.type = htons (TYPE_VALUES);
+       pkg_ph.length = htons (packet_len);
+
+       pkg_num_values = htons ((uint16_t) vl->values_len);
+
+       for (i = 0; i < num_values; i++)
+       {
+               pkg_values_types[i] = (uint8_t) ds->ds[i].type;
+               switch (ds->ds[i].type)
+               {
+                       case DS_TYPE_COUNTER:
+                               pkg_values[i].counter = htonll (vl->values[i].counter);
+                               break;
+
+                       case DS_TYPE_GAUGE:
+                               pkg_values[i].gauge = htond (vl->values[i].gauge);
+                               break;
+
+                       case DS_TYPE_DERIVE:
+                               pkg_values[i].derive = htonll (vl->values[i].derive);
+                               break;
+
+                       case DS_TYPE_ABSOLUTE:
+                               pkg_values[i].absolute = htonll (vl->values[i].absolute);
+                               break;
+
+                       default:
+                               free (pkg_values_types);
+                               free (pkg_values);
+                               ERROR ("network plugin: write_part_values: "
+                                               "Unknown data source type: %i",
+                                               ds->ds[i].type);
+                               return (-1);
+               } /* switch (ds->ds[i].type) */
+       } /* for (num_values) */
+
+       /*
+        * Use `memcpy' to write everything to the buffer, because the pointer
+        * may be unaligned and some architectures, such as SPARC, can't handle
+        * that.
+        */
+       packet_ptr = *ret_buffer;
+       offset = 0;
+       memcpy (packet_ptr + offset, &pkg_ph, sizeof (pkg_ph));
+       offset += sizeof (pkg_ph);
+       memcpy (packet_ptr + offset, &pkg_num_values, sizeof (pkg_num_values));
+       offset += sizeof (pkg_num_values);
+       memcpy (packet_ptr + offset, pkg_values_types, num_values * sizeof (uint8_t));
+       offset += num_values * sizeof (uint8_t);
+       memcpy (packet_ptr + offset, pkg_values, num_values * sizeof (value_t));
+       offset += num_values * sizeof (value_t);
+
+       assert (offset == packet_len);
+
+       *ret_buffer = packet_ptr + packet_len;
+       *ret_buffer_len -= packet_len;
+
+       free (pkg_values_types);
+       free (pkg_values);
+
+       return (0);
+} /* int write_part_values */
+
+static int write_part_number (char **ret_buffer, int *ret_buffer_len,
+               int type, uint64_t value)
+{
+       char *packet_ptr;
+       int packet_len;
+
+       part_header_t pkg_head;
+       uint64_t pkg_value;
+
+       int offset;
+
+       packet_len = sizeof (pkg_head) + sizeof (pkg_value);
+
+       if (*ret_buffer_len < packet_len)
+               return (-1);
+
+       pkg_head.type = htons (type);
+       pkg_head.length = htons (packet_len);
+       pkg_value = htonll (value);
+
+       packet_ptr = *ret_buffer;
+       offset = 0;
+       memcpy (packet_ptr + offset, &pkg_head, sizeof (pkg_head));
+       offset += sizeof (pkg_head);
+       memcpy (packet_ptr + offset, &pkg_value, sizeof (pkg_value));
+       offset += sizeof (pkg_value);
+
+       assert (offset == packet_len);
+
+       *ret_buffer = packet_ptr + packet_len;
+       *ret_buffer_len -= packet_len;
+
+       return (0);
+} /* int write_part_number */
+
+static int write_part_string (char **ret_buffer, int *ret_buffer_len,
+               int type, const char *str, int str_len)
+{
+       char *buffer;
+       int buffer_len;
+
+       uint16_t pkg_type;
+       uint16_t pkg_length;
+
+       int offset;
+
+       buffer_len = 2 * sizeof (uint16_t) + str_len + 1;
+       if (*ret_buffer_len < buffer_len)
+               return (-1);
+
+       pkg_type = htons (type);
+       pkg_length = htons (buffer_len);
+
+       buffer = *ret_buffer;
+       offset = 0;
+       memcpy (buffer + offset, (void *) &pkg_type, sizeof (pkg_type));
+       offset += sizeof (pkg_type);
+       memcpy (buffer + offset, (void *) &pkg_length, sizeof (pkg_length));
+       offset += sizeof (pkg_length);
+       memcpy (buffer + offset, str, str_len);
+       offset += str_len;
+       memset (buffer + offset, '\0', 1);
+       offset += 1;
+
+       assert (offset == buffer_len);
+
+       *ret_buffer = buffer + buffer_len;
+       *ret_buffer_len -= buffer_len;
+
+       return (0);
+} /* int write_part_string */
+
+static int parse_part_values (void **ret_buffer, size_t *ret_buffer_len,
+               value_t **ret_values, int *ret_num_values)
+{
+       char *buffer = *ret_buffer;
+       size_t buffer_len = *ret_buffer_len;
+
+       uint16_t tmp16;
+       size_t exp_size;
+       int   i;
+
+       uint16_t pkg_length;
+       uint16_t pkg_type;
+       uint16_t pkg_numval;
+
+       uint8_t *pkg_types;
+       value_t *pkg_values;
+
+       if (buffer_len < 15)
+       {
+               NOTICE ("network plugin: packet is too short: "
+                               "buffer_len = %zu", buffer_len);
+               return (-1);
+       }
+
+       memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
+       buffer += sizeof (tmp16);
+       pkg_type = ntohs (tmp16);
+
+       memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
+       buffer += sizeof (tmp16);
+       pkg_length = ntohs (tmp16);
+
+       memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
+       buffer += sizeof (tmp16);
+       pkg_numval = ntohs (tmp16);
+
+       assert (pkg_type == TYPE_VALUES);
+
+       exp_size = 3 * sizeof (uint16_t)
+               + pkg_numval * (sizeof (uint8_t) + sizeof (value_t));
+       if (buffer_len < exp_size)
+       {
+               WARNING ("network plugin: parse_part_values: "
+                               "Packet too short: "
+                               "Chunk of size %zu expected, "
+                               "but buffer has only %zu bytes left.",
+                               exp_size, buffer_len);
+               return (-1);
+       }
+
+       if (pkg_length != exp_size)
+       {
+               WARNING ("network plugin: parse_part_values: "
+                               "Length and number of values "
+                               "in the packet don't match.");
+               return (-1);
+       }
+
+       pkg_types = (uint8_t *) malloc (pkg_numval * sizeof (uint8_t));
+       pkg_values = (value_t *) malloc (pkg_numval * sizeof (value_t));
+       if ((pkg_types == NULL) || (pkg_values == NULL))
+       {
+               sfree (pkg_types);
+               sfree (pkg_values);
+               ERROR ("network plugin: parse_part_values: malloc failed.");
+               return (-1);
+       }
+
+       memcpy ((void *) pkg_types, (void *) buffer, pkg_numval * sizeof (uint8_t));
+       buffer += pkg_numval * sizeof (uint8_t);
+       memcpy ((void *) pkg_values, (void *) buffer, pkg_numval * sizeof (value_t));
+       buffer += pkg_numval * sizeof (value_t);
+
+       for (i = 0; i < pkg_numval; i++)
+       {
+               switch (pkg_types[i])
+               {
+                 case DS_TYPE_COUNTER:
+                   pkg_values[i].counter = (counter_t) ntohll (pkg_values[i].counter);
+                   break;
+
+                 case DS_TYPE_GAUGE:
+                   pkg_values[i].gauge = (gauge_t) ntohd (pkg_values[i].gauge);
+                   break;
+
+                 case DS_TYPE_DERIVE:
+                   pkg_values[i].derive = (derive_t) ntohll (pkg_values[i].derive);
+                   break;
+
+                 case DS_TYPE_ABSOLUTE:
+                   pkg_values[i].absolute = (absolute_t) ntohll (pkg_values[i].absolute);
+                   break;
+
+                 default:
+                   NOTICE ("network plugin: parse_part_values: "
+                       "Don't know how to handle data source type %"PRIu8,
+                       pkg_types[i]);
+                   sfree (pkg_types);
+                   sfree (pkg_values);
+                   return (-1);
+               } /* switch (pkg_types[i]) */
+       }
+
+       *ret_buffer     = buffer;
+       *ret_buffer_len = buffer_len - pkg_length;
+       *ret_num_values = pkg_numval;
+       *ret_values     = pkg_values;
+
+       sfree (pkg_types);
+
+       return (0);
+} /* int parse_part_values */
+
+static int parse_part_number (void **ret_buffer, size_t *ret_buffer_len,
+               uint64_t *value)
+{
+       char *buffer = *ret_buffer;
+       size_t buffer_len = *ret_buffer_len;
+
+       uint16_t tmp16;
+       uint64_t tmp64;
+       size_t exp_size = 2 * sizeof (uint16_t) + sizeof (uint64_t);
+
+       uint16_t pkg_length;
+
+       if (buffer_len < exp_size)
+       {
+               WARNING ("network plugin: parse_part_number: "
+                               "Packet too short: "
+                               "Chunk of size %zu expected, "
+                               "but buffer has only %zu bytes left.",
+                               exp_size, buffer_len);
+               return (-1);
+       }
+
+       memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
+       buffer += sizeof (tmp16);
+       /* pkg_type = ntohs (tmp16); */
+
+       memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
+       buffer += sizeof (tmp16);
+       pkg_length = ntohs (tmp16);
+
+       memcpy ((void *) &tmp64, buffer, sizeof (tmp64));
+       buffer += sizeof (tmp64);
+       *value = ntohll (tmp64);
+
+       *ret_buffer = buffer;
+       *ret_buffer_len = buffer_len - pkg_length;
+
+       return (0);
+} /* int parse_part_number */
+
+static int parse_part_string (void **ret_buffer, size_t *ret_buffer_len,
+               char *output, size_t const output_len)
+{
+       char *buffer = *ret_buffer;
+       size_t buffer_len = *ret_buffer_len;
+
+       uint16_t tmp16;
+       size_t const header_size = 2 * sizeof (uint16_t);
+
+       uint16_t pkg_length;
+       size_t payload_size;
+
+       if (output_len <= 0)
+               return (EINVAL);
+
+       if (buffer_len < header_size)
+       {
+               WARNING ("network plugin: parse_part_string: "
+                               "Packet too short: "
+                               "Chunk of at least size %zu expected, "
+                               "but buffer has only %zu bytes left.",
+                               header_size, buffer_len);
+               return (-1);
+       }
+
+       memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
+       buffer += sizeof (tmp16);
+       /* pkg_type = ntohs (tmp16); */
+
+       memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
+       buffer += sizeof (tmp16);
+       pkg_length = ntohs (tmp16);
+       payload_size = ((size_t) pkg_length) - header_size;
+
+       /* Check that packet fits in the input buffer */
+       if (pkg_length > buffer_len)
+       {
+               WARNING ("network plugin: parse_part_string: "
+                               "Packet too big: "
+                               "Chunk of size %"PRIu16" received, "
+                               "but buffer has only %zu bytes left.",
+                               pkg_length, buffer_len);
+               return (-1);
+       }
+
+       /* Check that pkg_length is in the valid range */
+       if (pkg_length <= header_size)
+       {
+               WARNING ("network plugin: parse_part_string: "
+                               "Packet too short: "
+                               "Header claims this packet is only %hu "
+                               "bytes long.", pkg_length);
+               return (-1);
+       }
+
+       /* Check that the package data fits into the output buffer.
+        * The previous if-statement ensures that:
+        * `pkg_length > header_size' */
+       if (output_len < payload_size)
+       {
+               WARNING ("network plugin: parse_part_string: "
+                               "Buffer too small: "
+                               "Output buffer holds %zu bytes, "
+                               "which is too small to hold the received "
+                               "%zu byte string.",
+                               output_len, payload_size);
+               return (-1);
+       }
+
+       /* All sanity checks successfull, let's copy the data over */
+       memcpy ((void *) output, (void *) buffer, payload_size);
+       buffer += payload_size;
+
+       /* For some very weird reason '\0' doesn't do the trick on SPARC in
+        * this statement. */
+       if (output[payload_size - 1] != 0)
+       {
+               WARNING ("network plugin: parse_part_string: "
+                               "Received string does not end "
+                               "with a NULL-byte.");
+               return (-1);
+       }
+
+       *ret_buffer = buffer;
+       *ret_buffer_len = buffer_len - pkg_length;
+
+       return (0);
+} /* int parse_part_string */
+
+/* Forward declaration: parse_part_sign_sha256 and parse_part_encr_aes256 call
+ * parse_packet and vice versa. */
+#define PP_SIGNED    0x01
+#define PP_ENCRYPTED 0x02
+static int parse_packet (sockent_t *se,
+               void *buffer, size_t buffer_size, int flags,
+               const char *username);
+
+#define BUFFER_READ(p,s) do { \
+  memcpy ((p), buffer + buffer_offset, (s)); \
+  buffer_offset += (s); \
+} while (0)
+
+#if HAVE_LIBGCRYPT
+static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
+    void **ret_buffer, size_t *ret_buffer_len, int flags)
+{
+  static c_complain_t complain_no_users = C_COMPLAIN_INIT_STATIC;
+
+  char *buffer;
+  size_t buffer_len;
+  size_t buffer_offset;
+
+  size_t username_len;
+  char *secret;
+
+  part_signature_sha256_t pss;
+  uint16_t pss_head_length;
+  char hash[sizeof (pss.hash)];
+
+  gcry_md_hd_t hd;
+  gcry_error_t err;
+  unsigned char *hash_ptr;
+
+  buffer = *ret_buffer;
+  buffer_len = *ret_buffer_len;
+  buffer_offset = 0;
+
+  if (se->data.server.userdb == NULL)
+  {
+    c_complain (LOG_NOTICE, &complain_no_users,
+        "network plugin: Received signed network packet but can't verify it "
+        "because no user DB has been configured. Will accept it.");
+    return (0);
+  }
+
+  /* Check if the buffer has enough data for this structure. */
+  if (buffer_len <= PART_SIGNATURE_SHA256_SIZE)
+    return (-ENOMEM);
+
+  /* Read type and length header */
+  BUFFER_READ (&pss.head.type, sizeof (pss.head.type));
+  BUFFER_READ (&pss.head.length, sizeof (pss.head.length));
+  pss_head_length = ntohs (pss.head.length);
+
+  /* Check if the `pss_head_length' is within bounds. */
+  if ((pss_head_length <= PART_SIGNATURE_SHA256_SIZE)
+      || (pss_head_length > buffer_len))
+  {
+    ERROR ("network plugin: HMAC-SHA-256 with invalid length received.");
+    return (-1);
+  }
+
+  /* Copy the hash. */
+  BUFFER_READ (pss.hash, sizeof (pss.hash));
+
+  /* Calculate username length (without null byte) and allocate memory */
+  username_len = pss_head_length - PART_SIGNATURE_SHA256_SIZE;
+  pss.username = malloc (username_len + 1);
+  if (pss.username == NULL)
+    return (-ENOMEM);
+
+  /* Read the username */
+  BUFFER_READ (pss.username, username_len);
+  pss.username[username_len] = 0;
+
+  assert (buffer_offset == pss_head_length);
+
+  /* Query the password */
+  secret = fbh_get (se->data.server.userdb, pss.username);
+  if (secret == NULL)
+  {
+    ERROR ("network plugin: Unknown user: %s", pss.username);
+    sfree (pss.username);
+    return (-ENOENT);
+  }
+
+  /* Create a hash device and check the HMAC */
+  hd = NULL;
+  err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+  if (err != 0)
+  {
+    ERROR ("network plugin: Creating HMAC-SHA-256 object failed: %s",
+        gcry_strerror (err));
+    sfree (secret);
+    sfree (pss.username);
+    return (-1);
+  }
+
+  err = gcry_md_setkey (hd, secret, strlen (secret));
+  if (err != 0)
+  {
+    ERROR ("network plugin: gcry_md_setkey failed: %s", gcry_strerror (err));
+    gcry_md_close (hd);
+    sfree (secret);
+    sfree (pss.username);
+    return (-1);
+  }
+
+  gcry_md_write (hd,
+      buffer     + PART_SIGNATURE_SHA256_SIZE,
+      buffer_len - PART_SIGNATURE_SHA256_SIZE);
+  hash_ptr = gcry_md_read (hd, GCRY_MD_SHA256);
+  if (hash_ptr == NULL)
+  {
+    ERROR ("network plugin: gcry_md_read failed.");
+    gcry_md_close (hd);
+    sfree (secret);
+    sfree (pss.username);
+    return (-1);
+  }
+  memcpy (hash, hash_ptr, sizeof (hash));
+
+  /* Clean up */
+  gcry_md_close (hd);
+  hd = NULL;
+
+  if (memcmp (pss.hash, hash, sizeof (pss.hash)) != 0)
+  {
+    WARNING ("network plugin: Verifying HMAC-SHA-256 signature failed: "
+        "Hash mismatch.");
+  }
+  else
+  {
+    parse_packet (se, buffer + buffer_offset, buffer_len - buffer_offset,
+        flags | PP_SIGNED, pss.username);
+  }
+
+  sfree (secret);
+  sfree (pss.username);
+
+  *ret_buffer = buffer + buffer_len;
+  *ret_buffer_len = 0;
+
+  return (0);
+} /* }}} int parse_part_sign_sha256 */
+/* #endif HAVE_LIBGCRYPT */
+
+#else /* if !HAVE_LIBGCRYPT */
+static int parse_part_sign_sha256 (sockent_t *se, /* {{{ */
+    void **ret_buffer, size_t *ret_buffer_size, int flags)
+{
+  static int warning_has_been_printed = 0;
+
+  char *buffer;
+  size_t buffer_size;
+  size_t buffer_offset;
+  uint16_t part_len;
+
+  part_signature_sha256_t pss;
+
+  buffer = *ret_buffer;
+  buffer_size = *ret_buffer_size;
+  buffer_offset = 0;
+
+  if (buffer_size <= PART_SIGNATURE_SHA256_SIZE)
+    return (-ENOMEM);
+
+  BUFFER_READ (&pss.head.type, sizeof (pss.head.type));
+  BUFFER_READ (&pss.head.length, sizeof (pss.head.length));
+  part_len = ntohs (pss.head.length);
+
+  if ((part_len <= PART_SIGNATURE_SHA256_SIZE)
+      || (part_len > buffer_size))
+    return (-EINVAL);
+
+  if (warning_has_been_printed == 0)
+  {
+    WARNING ("network plugin: Received signed packet, but the network "
+        "plugin was not linked with libgcrypt, so I cannot "
+        "verify the signature. The packet will be accepted.");
+    warning_has_been_printed = 1;
+  }
+
+  parse_packet (se, buffer + part_len, buffer_size - part_len, flags,
+      /* username = */ NULL);
+
+  *ret_buffer = buffer + buffer_size;
+  *ret_buffer_size = 0;
+
+  return (0);
+} /* }}} int parse_part_sign_sha256 */
+#endif /* !HAVE_LIBGCRYPT */
+
+#if HAVE_LIBGCRYPT
+static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
+               void **ret_buffer, size_t *ret_buffer_len,
+               int flags)
+{
+  char  *buffer = *ret_buffer;
+  size_t buffer_len = *ret_buffer_len;
+  size_t payload_len;
+  size_t part_size;
+  size_t buffer_offset;
+  uint16_t username_len;
+  part_encryption_aes256_t pea;
+  unsigned char hash[sizeof (pea.hash)];
+
+  gcry_cipher_hd_t cypher;
+  gcry_error_t err;
+
+  /* Make sure at least the header if available. */
+  if (buffer_len <= PART_ENCRYPTION_AES256_SIZE)
+  {
+    NOTICE ("network plugin: parse_part_encr_aes256: "
+        "Discarding short packet.");
+    return (-1);
+  }
+
+  buffer_offset = 0;
+
+  /* Copy the unencrypted information into `pea'. */
+  BUFFER_READ (&pea.head.type, sizeof (pea.head.type));
+  BUFFER_READ (&pea.head.length, sizeof (pea.head.length));
+
+  /* Check the `part size'. */
+  part_size = ntohs (pea.head.length);
+  if ((part_size <= PART_ENCRYPTION_AES256_SIZE)
+      || (part_size > buffer_len))
+  {
+    NOTICE ("network plugin: parse_part_encr_aes256: "
+        "Discarding part with invalid size.");
+    return (-1);
+  }
+
+  /* Read the username */
+  BUFFER_READ (&username_len, sizeof (username_len));
+  username_len = ntohs (username_len);
+
+  if ((username_len <= 0)
+      || (username_len > (part_size - (PART_ENCRYPTION_AES256_SIZE + 1))))
+  {
+    NOTICE ("network plugin: parse_part_encr_aes256: "
+        "Discarding part with invalid username length.");
+    return (-1);
+  }
+
+  assert (username_len > 0);
+  pea.username = malloc (username_len + 1);
+  if (pea.username == NULL)
+    return (-ENOMEM);
+  BUFFER_READ (pea.username, username_len);
+  pea.username[username_len] = 0;
+
+  /* Last but not least, the initialization vector */
+  BUFFER_READ (pea.iv, sizeof (pea.iv));
+
+  /* Make sure we are at the right position */
+  assert (buffer_offset == (username_len +
+        PART_ENCRYPTION_AES256_SIZE - sizeof (pea.hash)));
+
+  cypher = network_get_aes256_cypher (se, pea.iv, sizeof (pea.iv),
+      pea.username);
+  if (cypher == NULL)
+  {
+    sfree (pea.username);
+    return (-1);
+  }
+
+  payload_len = part_size - (PART_ENCRYPTION_AES256_SIZE + username_len);
+  assert (payload_len > 0);
+
+  /* Decrypt the packet in-place */
+  err = gcry_cipher_decrypt (cypher,
+      buffer    + buffer_offset,
+      part_size - buffer_offset,
+      /* in = */ NULL, /* in len = */ 0);
+  if (err != 0)
+  {
+    sfree (pea.username);
+    ERROR ("network plugin: gcry_cipher_decrypt returned: %s",
+        gcry_strerror (err));
+    return (-1);
+  }
+
+  /* Read the hash */
+  BUFFER_READ (pea.hash, sizeof (pea.hash));
+
+  /* Make sure we're at the right position - again */
+  assert (buffer_offset == (username_len + PART_ENCRYPTION_AES256_SIZE));
+  assert (buffer_offset == (part_size - payload_len));
+
+  /* Check hash sum */
+  memset (hash, 0, sizeof (hash));
+  gcry_md_hash_buffer (GCRY_MD_SHA1, hash,
+      buffer + buffer_offset, payload_len);
+  if (memcmp (hash, pea.hash, sizeof (hash)) != 0)
+  {
+    sfree (pea.username);
+    ERROR ("network plugin: Decryption failed: Checksum mismatch.");
+    return (-1);
+  }
+
+  parse_packet (se, buffer + buffer_offset, payload_len,
+      flags | PP_ENCRYPTED, pea.username);
+
+  /* XXX: Free pea.username?!? */
+
+  /* Update return values */
+  *ret_buffer =     buffer     + part_size;
+  *ret_buffer_len = buffer_len - part_size;
+
+  sfree (pea.username);
+
+  return (0);
+} /* }}} int parse_part_encr_aes256 */
+/* #endif HAVE_LIBGCRYPT */
+
+#else /* if !HAVE_LIBGCRYPT */
+static int parse_part_encr_aes256 (sockent_t *se, /* {{{ */
+    void **ret_buffer, size_t *ret_buffer_size, int flags)
+{
+  static int warning_has_been_printed = 0;
+
+  char *buffer;
+  size_t buffer_size;
+  size_t buffer_offset;
+
+  part_header_t ph;
+  size_t ph_length;
+
+  buffer = *ret_buffer;
+  buffer_size = *ret_buffer_size;
+  buffer_offset = 0;
+
+  /* parse_packet assures this minimum size. */
+  assert (buffer_size >= (sizeof (ph.type) + sizeof (ph.length)));
+
+  BUFFER_READ (&ph.type, sizeof (ph.type));
+  BUFFER_READ (&ph.length, sizeof (ph.length));
+  ph_length = ntohs (ph.length);
+
+  if ((ph_length <= PART_ENCRYPTION_AES256_SIZE)
+      || (ph_length > buffer_size))
+  {
+    ERROR ("network plugin: AES-256 encrypted part "
+        "with invalid length received.");
+    return (-1);
+  }
+
+  if (warning_has_been_printed == 0)
+  {
+    WARNING ("network plugin: Received encrypted packet, but the network "
+        "plugin was not linked with libgcrypt, so I cannot "
+        "decrypt it. The part will be discarded.");
+    warning_has_been_printed = 1;
+  }
+
+  *ret_buffer += ph_length;
+  *ret_buffer_size -= ph_length;
+
+  return (0);
+} /* }}} int parse_part_encr_aes256 */
+#endif /* !HAVE_LIBGCRYPT */
+
+#undef BUFFER_READ
+
+static int parse_packet (sockent_t *se, /* {{{ */
+               void *buffer, size_t buffer_size, int flags,
+               const char *username)
+{
+       int status;
+
+       value_list_t vl = VALUE_LIST_INIT;
+       notification_t n;
+
+#if HAVE_LIBGCRYPT
+       int packet_was_signed = (flags & PP_SIGNED);
+        int packet_was_encrypted = (flags & PP_ENCRYPTED);
+       int printed_ignore_warning = 0;
+#endif /* HAVE_LIBGCRYPT */
+
+
+       memset (&vl, '\0', sizeof (vl));
+       memset (&n, '\0', sizeof (n));
+       status = 0;
+
+       while ((status == 0) && (0 < buffer_size)
+                       && ((unsigned int) buffer_size > sizeof (part_header_t)))
+       {
+               uint16_t pkg_length;
+               uint16_t pkg_type;
+
+               memcpy ((void *) &pkg_type,
+                               (void *) buffer,
+                               sizeof (pkg_type));
+               memcpy ((void *) &pkg_length,
+                               (void *) (buffer + sizeof (pkg_type)),
+                               sizeof (pkg_length));
+
+               pkg_length = ntohs (pkg_length);
+               pkg_type = ntohs (pkg_type);
+
+               if (pkg_length > buffer_size)
+                       break;
+               /* Ensure that this loop terminates eventually */
+               if (pkg_length < (2 * sizeof (uint16_t)))
+                       break;
+
+               if (pkg_type == TYPE_ENCR_AES256)
+               {
+                       status = parse_part_encr_aes256 (se,
+                                       &buffer, &buffer_size, flags);
+                       if (status != 0)
+                       {
+                               ERROR ("network plugin: Decrypting AES256 "
+                                               "part failed "
+                                               "with status %i.", status);
+                               break;
+                       }
+               }
+#if HAVE_LIBGCRYPT
+               else if ((se->data.server.security_level == SECURITY_LEVEL_ENCRYPT)
+                               && (packet_was_encrypted == 0))
+               {
+                       if (printed_ignore_warning == 0)
+                       {
+                               INFO ("network plugin: Unencrypted packet or "
+                                               "part has been ignored.");
+                               printed_ignore_warning = 1;
+                       }
+                       buffer = ((char *) buffer) + pkg_length;
+                       continue;
+               }
+#endif /* HAVE_LIBGCRYPT */
+               else if (pkg_type == TYPE_SIGN_SHA256)
+               {
+                       status = parse_part_sign_sha256 (se,
+                                        &buffer, &buffer_size, flags);
+                       if (status != 0)
+                       {
+                               ERROR ("network plugin: Verifying HMAC-SHA-256 "
+                                               "signature failed "
+                                               "with status %i.", status);
+                               break;
+                       }
+               }
+#if HAVE_LIBGCRYPT
+               else if ((se->data.server.security_level == SECURITY_LEVEL_SIGN)
+                               && (packet_was_encrypted == 0)
+                               && (packet_was_signed == 0))
+               {
+                       if (printed_ignore_warning == 0)
+                       {
+                               INFO ("network plugin: Unsigned packet or "
+                                               "part has been ignored.");
+                               printed_ignore_warning = 1;
+                       }
+                       buffer = ((char *) buffer) + pkg_length;
+                       continue;
+               }
+#endif /* HAVE_LIBGCRYPT */
+               else if (pkg_type == TYPE_VALUES)
+               {
+                       status = parse_part_values (&buffer, &buffer_size,
+                                       &vl.values, &vl.values_len);
+                       if (status != 0)
+                               break;
+
+                       network_dispatch_values (&vl, username);
+
+                       sfree (vl.values);
+               }
+               else if (pkg_type == TYPE_TIME)
+               {
+                       uint64_t tmp = 0;
+                       status = parse_part_number (&buffer, &buffer_size,
+                                       &tmp);
+                       if (status == 0)
+                       {
+                               vl.time = TIME_T_TO_CDTIME_T (tmp);
+                               n.time  = TIME_T_TO_CDTIME_T (tmp);
+                       }
+               }
+               else if (pkg_type == TYPE_TIME_HR)
+               {
+                       uint64_t tmp = 0;
+                       status = parse_part_number (&buffer, &buffer_size,
+                                       &tmp);
+                       if (status == 0)
+                       {
+                               vl.time = (cdtime_t) tmp;
+                               n.time  = (cdtime_t) tmp;
+                       }
+               }
+               else if (pkg_type == TYPE_INTERVAL)
+               {
+                       uint64_t tmp = 0;
+                       status = parse_part_number (&buffer, &buffer_size,
+                                       &tmp);
+                       if (status == 0)
+                               vl.interval = TIME_T_TO_CDTIME_T (tmp);
+               }
+               else if (pkg_type == TYPE_INTERVAL_HR)
+               {
+                       uint64_t tmp = 0;
+                       status = parse_part_number (&buffer, &buffer_size,
+                                       &tmp);
+                       if (status == 0)
+                               vl.interval = (cdtime_t) tmp;
+               }
+               else if (pkg_type == TYPE_HOST)
+               {
+                       status = parse_part_string (&buffer, &buffer_size,
+                                       vl.host, sizeof (vl.host));
+                       if (status == 0)
+                               sstrncpy (n.host, vl.host, sizeof (n.host));
+               }
+               else if (pkg_type == TYPE_PLUGIN)
+               {
+                       status = parse_part_string (&buffer, &buffer_size,
+                                       vl.plugin, sizeof (vl.plugin));
+                       if (status == 0)
+                               sstrncpy (n.plugin, vl.plugin,
+                                               sizeof (n.plugin));
+               }
+               else if (pkg_type == TYPE_PLUGIN_INSTANCE)
+               {
+                       status = parse_part_string (&buffer, &buffer_size,
+                                       vl.plugin_instance,
+                                       sizeof (vl.plugin_instance));
+                       if (status == 0)
+                               sstrncpy (n.plugin_instance,
+                                               vl.plugin_instance,
+                                               sizeof (n.plugin_instance));
+               }
+               else if (pkg_type == TYPE_TYPE)
+               {
+                       status = parse_part_string (&buffer, &buffer_size,
+                                       vl.type, sizeof (vl.type));
+                       if (status == 0)
+                               sstrncpy (n.type, vl.type, sizeof (n.type));
+               }
+               else if (pkg_type == TYPE_TYPE_INSTANCE)
+               {
+                       status = parse_part_string (&buffer, &buffer_size,
+                                       vl.type_instance,
+                                       sizeof (vl.type_instance));
+                       if (status == 0)
+                               sstrncpy (n.type_instance, vl.type_instance,
+                                               sizeof (n.type_instance));
+               }
+               else if (pkg_type == TYPE_MESSAGE)
+               {
+                       status = parse_part_string (&buffer, &buffer_size,
+                                       n.message, sizeof (n.message));
+
+                       if (status != 0)
+                       {
+                               /* do nothing */
+                       }
+                       else if ((n.severity != NOTIF_FAILURE)
+                                       && (n.severity != NOTIF_WARNING)
+                                       && (n.severity != NOTIF_OKAY))
+                       {
+                               INFO ("network plugin: "
+                                               "Ignoring notification with "
+                                               "unknown severity %i.",
+                                               n.severity);
+                       }
+                       else if (n.time <= 0)
+                       {
+                               INFO ("network plugin: "
+                                               "Ignoring notification with "
+                                               "time == 0.");
+                       }
+                       else if (strlen (n.message) <= 0)
+                       {
+                               INFO ("network plugin: "
+                                               "Ignoring notification with "
+                                               "an empty message.");
+                       }
+                       else
+                       {
+                               network_dispatch_notification (&n);
+                       }
+               }
+               else if (pkg_type == TYPE_SEVERITY)
+               {
+                       uint64_t tmp = 0;
+                       status = parse_part_number (&buffer, &buffer_size,
+                                       &tmp);
+                       if (status == 0)
+                               n.severity = (int) tmp;
+               }
+               else
+               {
+                       DEBUG ("network plugin: parse_packet: Unknown part"
+                                       " type: 0x%04hx", pkg_type);
+                       buffer = ((char *) buffer) + pkg_length;
+               }
+       } /* while (buffer_size > sizeof (part_header_t)) */
+
+       if (status == 0 && buffer_size > 0)
+               WARNING ("network plugin: parse_packet: Received truncated "
+                               "packet, try increasing `MaxPacketSize'");
+
+       return (status);
+} /* }}} int parse_packet */
+
+static void free_sockent_client (struct sockent_client *sec) /* {{{ */
+{
+  if (sec->fd >= 0)
+  {
+    close (sec->fd);
+    sec->fd = -1;
+  }
+  sfree (sec->addr);
+#if HAVE_LIBGCRYPT
+  sfree (sec->username);
+  sfree (sec->password);
+  if (sec->cypher != NULL)
+    gcry_cipher_close (sec->cypher);
+#endif
+} /* }}} void free_sockent_client */
+
+static void free_sockent_server (struct sockent_server *ses) /* {{{ */
+{
+  size_t i;
+
+  for (i = 0; i < ses->fd_num; i++)
+  {
+    if (ses->fd[i] >= 0)
+    {
+      close (ses->fd[i]);
+      ses->fd[i] = -1;
+    }
+  }
+
+  sfree (ses->fd);
+#if HAVE_LIBGCRYPT
+  sfree (ses->auth_file);
+  fbh_destroy (ses->userdb);
+  if (ses->cypher != NULL)
+    gcry_cipher_close (ses->cypher);
+#endif
+} /* }}} void free_sockent_server */
+
+static void sockent_destroy (sockent_t *se) /* {{{ */
+{
+  sockent_t *next;
+
+  DEBUG ("network plugin: sockent_destroy (se = %p);", (void *) se);
+
+  while (se != NULL)
+  {
+    next = se->next;
+
+    sfree (se->node);
+    sfree (se->service);
+
+    if (se->type == SOCKENT_TYPE_CLIENT)
+      free_sockent_client (&se->data.client);
+    else
+      free_sockent_server (&se->data.server);
+
+    sfree (se);
+    se = next;
+  }
+} /* }}} void sockent_destroy */
+
+/*
+ * int network_set_ttl
+ *
+ * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
+ * `IPV6_UNICAST_HOPS', depending on which option is applicable.
+ *
+ * The `struct addrinfo' is used to destinguish between unicast and multicast
+ * sockets.
+ */
+static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
+{
+       DEBUG ("network plugin: network_set_ttl: network_config_ttl = %i;",
+                       network_config_ttl);
+
+        assert (se->type == SOCKENT_TYPE_CLIENT);
+
+       if ((network_config_ttl < 1) || (network_config_ttl > 255))
+               return (-1);
+
+       if (ai->ai_family == AF_INET)
+       {
+               struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
+               int optname;
+
+               if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+                       optname = IP_MULTICAST_TTL;
+               else
+                       optname = IP_TTL;
+
+               if (setsockopt (se->data.client.fd, IPPROTO_IP, optname,
+                                       &network_config_ttl,
+                                       sizeof (network_config_ttl)) != 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("network plugin: setsockopt (ipv4-ttl): %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+       }
+       else if (ai->ai_family == AF_INET6)
+       {
+               /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
+               int optname;
+
+               if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+                       optname = IPV6_MULTICAST_HOPS;
+               else
+                       optname = IPV6_UNICAST_HOPS;
+
+               if (setsockopt (se->data.client.fd, IPPROTO_IPV6, optname,
+                                       &network_config_ttl,
+                                       sizeof (network_config_ttl)) != 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("network plugin: setsockopt(ipv6-ttl): %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       return (-1);
+               }
+       }
+
+       return (0);
+} /* int network_set_ttl */
+
+static int network_set_interface (const sockent_t *se, const struct addrinfo *ai) /* {{{ */
+{
+       DEBUG ("network plugin: network_set_interface: interface index = %i;",
+                       se->interface);
+
+        assert (se->type == SOCKENT_TYPE_CLIENT);
+
+       if (ai->ai_family == AF_INET)
+       {
+               struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
+
+               if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+               {
+#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+                       /* If possible, use the "ip_mreqn" structure which has
+                        * an "interface index" member. Using the interface
+                        * index is preferred here, because of its similarity
+                        * to the way IPv6 handles this. Unfortunately, it
+                        * appears not to be portable. */
+                       struct ip_mreqn mreq;
+
+                       memset (&mreq, 0, sizeof (mreq));
+                       mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+                       mreq.imr_address.s_addr = ntohl (INADDR_ANY);
+                       mreq.imr_ifindex = se->interface;
+#else
+                       struct ip_mreq mreq;
+
+                       memset (&mreq, 0, sizeof (mreq));
+                       mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+                       mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+#endif
+
+                       if (setsockopt (se->data.client.fd, IPPROTO_IP, IP_MULTICAST_IF,
+                                               &mreq, sizeof (mreq)) != 0)
+                       {
+                               char errbuf[1024];
+                               ERROR ("network plugin: setsockopt (ipv4-multicast-if): %s",
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                               return (-1);
+                       }
+
+                       return (0);
+               }
+       }
+       else if (ai->ai_family == AF_INET6)
+       {
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
+
+               if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+               {
+                       if (setsockopt (se->data.client.fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+                                               &se->interface,
+                                               sizeof (se->interface)) != 0)
+                       {
+                               char errbuf[1024];
+                               ERROR ("network plugin: setsockopt (ipv6-multicast-if): %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+
+                       return (0);
+               }
+       }
+
+       /* else: Not a multicast interface. */
+       if (se->interface != 0)
+       {
+#if defined(HAVE_IF_INDEXTONAME) && HAVE_IF_INDEXTONAME && defined(SO_BINDTODEVICE)
+               char interface_name[IFNAMSIZ];
+
+               if (if_indextoname (se->interface, interface_name) == NULL)
+                       return (-1);
+
+               DEBUG ("network plugin: Binding socket to interface %s", interface_name);
+
+               if (setsockopt (se->data.client.fd, SOL_SOCKET, SO_BINDTODEVICE,
+                                       interface_name,
+                                       sizeof(interface_name)) == -1 )
+               {
+                       char errbuf[1024];
+                       ERROR ("network plugin: setsockopt (bind-if): %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+/* #endif HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */
+
+#else
+               WARNING ("network plugin: Cannot set the interface on a unicast "
+                       "socket because "
+# if !defined(SO_BINDTODEVICE)
+                       "the \"SO_BINDTODEVICE\" socket option "
+# else
+                       "the \"if_indextoname\" function "
+# endif
+                       "is not available on your system.");
+#endif
+
+       }
+
+       return (0);
+} /* }}} network_set_interface */
+
+static int network_bind_socket (int fd, const struct addrinfo *ai, const int interface_idx)
+{
+#if KERNEL_SOLARIS
+       char loop   = 0;
+#else
+       int loop = 0;
+#endif
+       int yes  = 1;
+
+       /* allow multiple sockets to use the same PORT number */
+       if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
+                               &yes, sizeof(yes)) == -1) {
+                char errbuf[1024];
+                ERROR ("network plugin: setsockopt (reuseaddr): %s",
+                                sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       DEBUG ("fd = %i; calling `bind'", fd);
+
+       if (bind (fd, ai->ai_addr, ai->ai_addrlen) == -1)
+       {
+               char errbuf[1024];
+               ERROR ("bind: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       if (ai->ai_family == AF_INET)
+       {
+               struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
+               if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+               {
+#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+                       struct ip_mreqn mreq;
+#else
+                       struct ip_mreq mreq;
+#endif
+
+                       DEBUG ("fd = %i; IPv4 multicast address found", fd);
+
+                       mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+                       /* Set the interface using the interface index if
+                        * possible (available). Unfortunately, the struct
+                        * ip_mreqn is not portable. */
+                       mreq.imr_address.s_addr = ntohl (INADDR_ANY);
+                       mreq.imr_ifindex = interface_idx;
+#else
+                       mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+#endif
+
+                       if (setsockopt (fd, IPPROTO_IP, IP_MULTICAST_LOOP,
+                                               &loop, sizeof (loop)) == -1)
+                       {
+                               char errbuf[1024];
+                               ERROR ("network plugin: setsockopt (multicast-loop): %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+
+                       if (setsockopt (fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+                                               &mreq, sizeof (mreq)) == -1)
+                       {
+                               char errbuf[1024];
+                               ERROR ("network plugin: setsockopt (add-membership): %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+
+                       return (0);
+               }
+       }
+       else if (ai->ai_family == AF_INET6)
+       {
+               /* Useful example: http://gsyc.escet.urjc.es/~eva/IPv6-web/examples/mcast.html */
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
+               if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+               {
+                       struct ipv6_mreq mreq;
+
+                       DEBUG ("fd = %i; IPv6 multicast address found", fd);
+
+                       memcpy (&mreq.ipv6mr_multiaddr,
+                                       &addr->sin6_addr,
+                                       sizeof (addr->sin6_addr));
+
+                       /* http://developer.apple.com/documentation/Darwin/Reference/ManPages/man4/ip6.4.html
+                        * ipv6mr_interface may be set to zeroes to
+                        * choose the default multicast interface or to
+                        * the index of a particular multicast-capable
+                        * interface if the host is multihomed.
+                        * Membership is associ-associated with a
+                        * single interface; programs running on
+                        * multihomed hosts may need to join the same
+                        * group on more than one interface.*/
+                       mreq.ipv6mr_interface = interface_idx;
+
+                       if (setsockopt (fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+                                               &loop, sizeof (loop)) == -1)
+                       {
+                               char errbuf[1024];
+                               ERROR ("network plugin: setsockopt (ipv6-multicast-loop): %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+
+                       if (setsockopt (fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
+                                               &mreq, sizeof (mreq)) == -1)
+                       {
+                               char errbuf[1024];
+                               ERROR ("network plugin: setsockopt (ipv6-add-membership): %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+
+                       return (0);
+               }
+       }
+
+#if defined(HAVE_IF_INDEXTONAME) && HAVE_IF_INDEXTONAME && defined(SO_BINDTODEVICE)
+       /* if a specific interface was set, bind the socket to it. But to avoid
+        * possible problems with multicast routing, only do that for non-multicast
+        * addresses */
+       if (interface_idx != 0)
+       {
+               char interface_name[IFNAMSIZ];
+
+               if (if_indextoname (interface_idx, interface_name) == NULL)
+                       return (-1);
+
+               DEBUG ("fd = %i; Binding socket to interface %s", fd, interface_name);
+
+               if (setsockopt (fd, SOL_SOCKET, SO_BINDTODEVICE,
+                                       interface_name,
+                                       sizeof(interface_name)) == -1 )
+               {
+                       char errbuf[1024];
+                       ERROR ("network plugin: setsockopt (bind-if): %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+       }
+#endif /* HAVE_IF_INDEXTONAME && SO_BINDTODEVICE */
+
+       return (0);
+} /* int network_bind_socket */
+
+/* Initialize a sockent structure. `type' must be either `SOCKENT_TYPE_CLIENT'
+ * or `SOCKENT_TYPE_SERVER' */
+static sockent_t *sockent_create (int type) /* {{{ */
+{
+       sockent_t *se;
+
+       if ((type != SOCKENT_TYPE_CLIENT) && (type != SOCKENT_TYPE_SERVER))
+               return (NULL);
+
+       se = malloc (sizeof (*se));
+       if (se == NULL)
+               return (NULL);
+       memset (se, 0, sizeof (*se));
+
+       se->type = type;
+       se->node = NULL;
+       se->service = NULL;
+       se->interface = 0;
+       se->next = NULL;
+
+       if (type == SOCKENT_TYPE_SERVER)
+       {
+               se->data.server.fd = NULL;
+#if HAVE_LIBGCRYPT
+               se->data.server.security_level = SECURITY_LEVEL_NONE;
+               se->data.server.auth_file = NULL;
+               se->data.server.userdb = NULL;
+               se->data.server.cypher = NULL;
+#endif
+       }
+       else
+       {
+               se->data.client.fd = -1;
+               se->data.client.addr = NULL;
+               se->data.client.resolve_interval = 0;
+               se->data.client.next_resolve_reconnect = 0;
+#if HAVE_LIBGCRYPT
+               se->data.client.security_level = SECURITY_LEVEL_NONE;
+               se->data.client.username = NULL;
+               se->data.client.password = NULL;
+               se->data.client.cypher = NULL;
+#endif
+       }
+
+       return (se);
+} /* }}} sockent_t *sockent_create */
+
+static int sockent_init_crypto (sockent_t *se) /* {{{ */
+{
+#if HAVE_LIBGCRYPT /* {{{ */
+       if (se->type == SOCKENT_TYPE_CLIENT)
+       {
+               if (se->data.client.security_level > SECURITY_LEVEL_NONE)
+               {
+                       network_init_gcrypt ();
+
+                       if ((se->data.client.username == NULL)
+                                       || (se->data.client.password == NULL))
+                       {
+                               ERROR ("network plugin: Client socket with "
+                                               "security requested, but no "
+                                               "credentials are configured.");
+                               return (-1);
+                       }
+                       gcry_md_hash_buffer (GCRY_MD_SHA256,
+                                       se->data.client.password_hash,
+                                       se->data.client.password,
+                                       strlen (se->data.client.password));
+               }
+       }
+       else /* (se->type == SOCKENT_TYPE_SERVER) */
+       {
+               if (se->data.server.security_level > SECURITY_LEVEL_NONE)
+               {
+                       network_init_gcrypt ();
+
+                       if (se->data.server.auth_file == NULL)
+                       {
+                               ERROR ("network plugin: Server socket with "
+                                               "security requested, but no "
+                                               "password file is configured.");
+                               return (-1);
+                       }
+               }
+               if (se->data.server.auth_file != NULL)
+               {
+                       se->data.server.userdb = fbh_create (se->data.server.auth_file);
+                       if (se->data.server.userdb == NULL)
+                       {
+                               ERROR ("network plugin: Reading password file "
+                                               "`%s' failed.",
+                                               se->data.server.auth_file);
+                               if (se->data.server.security_level > SECURITY_LEVEL_NONE)
+                                       return (-1);
+                       }
+               }
+       }
+#endif /* }}} HAVE_LIBGCRYPT */
+
+       return (0);
+} /* }}} int sockent_init_crypto */
+
+static int sockent_client_disconnect (sockent_t *se) /* {{{ */
+{
+       struct sockent_client *client;
+
+       if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT))
+               return (EINVAL);
+
+       client = &se->data.client;
+       if (client->fd >= 0) /* connected */
+       {
+               close (client->fd);
+               client->fd = -1;
+       }
+
+       sfree (client->addr);
+       client->addrlen = 0;
+
+       return (0);
+} /* }}} int sockent_client_disconnect */
+
+static int sockent_client_connect (sockent_t *se) /* {{{ */
+{
+       static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
+
+       struct sockent_client *client;
+       struct addrinfo  ai_hints;
+       struct addrinfo *ai_list = NULL, *ai_ptr;
+       int status;
+       _Bool reconnect = 0;
+       cdtime_t now;
+
+       if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT))
+               return (EINVAL);
+
+       client = &se->data.client;
+
+       now = cdtime ();
+       if (client->resolve_interval != 0 && client->next_resolve_reconnect < now) {
+               DEBUG("network plugin: Reconnecting socket, resolve_interval = %lf, next_resolve_reconnect = %lf",
+                       CDTIME_T_TO_DOUBLE(client->resolve_interval), CDTIME_T_TO_DOUBLE(client->next_resolve_reconnect));
+               reconnect = 1;
+       }
+
+       if (client->fd >= 0 && !reconnect) /* already connected and not stale*/
+               return (0);
+
+       memset (&ai_hints, 0, sizeof (ai_hints));
+#ifdef AI_ADDRCONFIG
+       ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+       ai_hints.ai_family   = AF_UNSPEC;
+       ai_hints.ai_socktype = SOCK_DGRAM;
+       ai_hints.ai_protocol = IPPROTO_UDP;
+
+       status = getaddrinfo (se->node,
+                       (se->service != NULL) ? se->service : NET_DEFAULT_PORT,
+                       &ai_hints, &ai_list);
+       if (status != 0)
+       {
+               c_complain (LOG_ERR, &complaint,
+                               "network plugin: getaddrinfo (%s, %s) failed: %s",
+                               (se->node == NULL) ? "(null)" : se->node,
+                               (se->service == NULL) ? "(null)" : se->service,
+                               gai_strerror (status));
+               return (-1);
+       }
+       else
+       {
+               c_release (LOG_NOTICE, &complaint,
+                               "network plugin: Successfully resolved \"%s\".",
+                               se->node);
+       }
+
+       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               if (client->fd >= 0) /* when we reconnect */
+                       sockent_client_disconnect(se);
+
+               client->fd = socket (ai_ptr->ai_family,
+                               ai_ptr->ai_socktype,
+                               ai_ptr->ai_protocol);
+               if (client->fd < 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("network plugin: socket(2) failed: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       continue;
+               }
+
+               client->addr = malloc (sizeof (*client->addr));
+               if (client->addr == NULL)
+               {
+                       ERROR ("network plugin: malloc failed.");
+                       close (client->fd);
+                       client->fd = -1;
+                       continue;
+               }
+
+               memset (client->addr, 0, sizeof (*client->addr));
+               assert (sizeof (*client->addr) >= ai_ptr->ai_addrlen);
+               memcpy (client->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+               client->addrlen = ai_ptr->ai_addrlen;
+
+               network_set_ttl (se, ai_ptr);
+               network_set_interface (se, ai_ptr);
+
+               /* We don't open more than one write-socket per
+                * node/service pair.. */
+               break;
+       }
+
+       freeaddrinfo (ai_list);
+       if (client->fd < 0)
+               return (-1);
+
+       if (client->resolve_interval > 0)
+               client->next_resolve_reconnect = now + client->resolve_interval;
+       return (0);
+} /* }}} int sockent_client_connect */
+
+/* Open the file descriptors for a initialized sockent structure. */
+static int sockent_server_listen (sockent_t *se) /* {{{ */
+{
+       struct addrinfo  ai_hints;
+       struct addrinfo *ai_list, *ai_ptr;
+       int              status;
+
+        const char *node;
+        const char *service;
+
+       if (se == NULL)
+               return (-1);
+
+        node = se->node;
+        service = se->service;
+
+        if (service == NULL)
+          service = NET_DEFAULT_PORT;
+
+        DEBUG ("network plugin: sockent_server_listen: node = %s; service = %s;",
+            node, service);
+
+       memset (&ai_hints, 0, sizeof (ai_hints));
+       ai_hints.ai_flags  = 0;
+#ifdef AI_PASSIVE
+       ai_hints.ai_flags |= AI_PASSIVE;
+#endif
+#ifdef AI_ADDRCONFIG
+       ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+       ai_hints.ai_family   = AF_UNSPEC;
+       ai_hints.ai_socktype = SOCK_DGRAM;
+       ai_hints.ai_protocol = IPPROTO_UDP;
+
+       status = getaddrinfo (node, service, &ai_hints, &ai_list);
+       if (status != 0)
+       {
+               ERROR ("network plugin: getaddrinfo (%s, %s) failed: %s",
+                               (se->node == NULL) ? "(null)" : se->node,
+                               (se->service == NULL) ? "(null)" : se->service,
+                               gai_strerror (status));
+               return (-1);
+       }
+
+       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               int *tmp;
+
+               tmp = realloc (se->data.server.fd,
+                               sizeof (*tmp) * (se->data.server.fd_num + 1));
+               if (tmp == NULL)
+               {
+                       ERROR ("network plugin: realloc failed.");
+                       continue;
+               }
+               se->data.server.fd = tmp;
+               tmp = se->data.server.fd + se->data.server.fd_num;
+
+               *tmp = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
+                               ai_ptr->ai_protocol);
+               if (*tmp < 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("network plugin: socket(2) failed: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       continue;
+               }
+
+               status = network_bind_socket (*tmp, ai_ptr, se->interface);
+               if (status != 0)
+               {
+                       close (*tmp);
+                       *tmp = -1;
+                       continue;
+               }
+
+               se->data.server.fd_num++;
+               continue;
+       } /* for (ai_list) */
+
+       freeaddrinfo (ai_list);
+
+       if (se->data.server.fd_num <= 0)
+               return (-1);
+       return (0);
+} /* }}} int sockent_server_listen */
+
+/* Add a sockent to the global list of sockets */
+static int sockent_add (sockent_t *se) /* {{{ */
+{
+       sockent_t *last_ptr;
+
+       if (se == NULL)
+               return (-1);
+
+       if (se->type == SOCKENT_TYPE_SERVER)
+       {
+               struct pollfd *tmp;
+               size_t i;
+
+               tmp = realloc (listen_sockets_pollfd,
+                               sizeof (*tmp) * (listen_sockets_num
+                                       + se->data.server.fd_num));
+               if (tmp == NULL)
+               {
+                       ERROR ("network plugin: realloc failed.");
+                       return (-1);
+               }
+               listen_sockets_pollfd = tmp;
+               tmp = listen_sockets_pollfd + listen_sockets_num;
+
+               for (i = 0; i < se->data.server.fd_num; i++)
+               {
+                       memset (tmp + i, 0, sizeof (*tmp));
+                       tmp[i].fd = se->data.server.fd[i];
+                       tmp[i].events = POLLIN | POLLPRI;
+                       tmp[i].revents = 0;
+               }
+
+               listen_sockets_num += se->data.server.fd_num;
+
+               if (listen_sockets == NULL)
+               {
+                       listen_sockets = se;
+                       return (0);
+               }
+               last_ptr = listen_sockets;
+       }
+       else /* if (se->type == SOCKENT_TYPE_CLIENT) */
+       {
+               if (sending_sockets == NULL)
+               {
+                       sending_sockets = se;
+                       return (0);
+               }
+               last_ptr = sending_sockets;
+       }
+
+       while (last_ptr->next != NULL)
+               last_ptr = last_ptr->next;
+       last_ptr->next = se;
+
+       return (0);
+} /* }}} int sockent_add */
+
+static void *dispatch_thread (void __attribute__((unused)) *arg) /* {{{ */
+{
+  while (42)
+  {
+    receive_list_entry_t *ent;
+    sockent_t *se;
+
+    /* Lock and wait for more data to come in */
+    pthread_mutex_lock (&receive_list_lock);
+    while ((listen_loop == 0)
+        && (receive_list_head == NULL))
+      pthread_cond_wait (&receive_list_cond, &receive_list_lock);
+
+    /* Remove the head entry and unlock */
+    ent = receive_list_head;
+    if (ent != NULL)
+      receive_list_head = ent->next;
+    receive_list_length--;
+    pthread_mutex_unlock (&receive_list_lock);
+
+    /* Check whether we are supposed to exit. We do NOT check `listen_loop'
+     * because we dispatch all missing packets before shutting down. */
+    if (ent == NULL)
+      break;
+
+    /* Look for the correct `sockent_t' */
+    se = listen_sockets;
+    while (se != NULL)
+    {
+      size_t i;
+
+      for (i = 0; i < se->data.server.fd_num; i++)
+        if (se->data.server.fd[i] == ent->fd)
+          break;
+
+      if (i < se->data.server.fd_num)
+        break;
+
+      se = se->next;
+    }
+
+    if (se == NULL)
+    {
+      ERROR ("network plugin: Got packet from FD %i, but can't "
+          "find an appropriate socket entry.",
+          ent->fd);
+      sfree (ent->data);
+      sfree (ent);
+      continue;
+    }
+
+    parse_packet (se, ent->data, ent->data_len, /* flags = */ 0,
+       /* username = */ NULL);
+    sfree (ent->data);
+    sfree (ent);
+  } /* while (42) */
+
+  return (NULL);
+} /* }}} void *dispatch_thread */
+
+static int network_receive (void) /* {{{ */
+{
+       char buffer[network_config_packet_size];
+       int  buffer_len;
+
+       int i;
+       int status;
+
+       receive_list_entry_t *private_list_head;
+       receive_list_entry_t *private_list_tail;
+       uint64_t              private_list_length;
+
+        assert (listen_sockets_num > 0);
+
+       private_list_head = NULL;
+       private_list_tail = NULL;
+       private_list_length = 0;
+
+       while (listen_loop == 0)
+       {
+               status = poll (listen_sockets_pollfd, listen_sockets_num, -1);
+
+               if (status <= 0)
+               {
+                       char errbuf[1024];
+                       if (errno == EINTR)
+                               continue;
+                       ERROR ("poll failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+
+               for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
+               {
+                       receive_list_entry_t *ent;
+
+                       if ((listen_sockets_pollfd[i].revents
+                                               & (POLLIN | POLLPRI)) == 0)
+                               continue;
+                       status--;
+
+                       buffer_len = recv (listen_sockets_pollfd[i].fd,
+                                       buffer, sizeof (buffer),
+                                       0 /* no flags */);
+                       if (buffer_len < 0)
+                       {
+                               char errbuf[1024];
+                               ERROR ("recv failed: %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               return (-1);
+                       }
+
+                       stats_octets_rx += ((uint64_t) buffer_len);
+                       stats_packets_rx++;
+
+                       /* TODO: Possible performance enhancement: Do not free
+                        * these entries in the dispatch thread but put them in
+                        * another list, so we don't have to allocate more and
+                        * more of these structures. */
+                       ent = malloc (sizeof (receive_list_entry_t));
+                       if (ent == NULL)
+                       {
+                               ERROR ("network plugin: malloc failed.");
+                               return (-1);
+                       }
+                       memset (ent, 0, sizeof (receive_list_entry_t));
+                       ent->data = malloc (network_config_packet_size);
+                       if (ent->data == NULL)
+                       {
+                               sfree (ent);
+                               ERROR ("network plugin: malloc failed.");
+                               return (-1);
+                       }
+                       ent->fd = listen_sockets_pollfd[i].fd;
+                       ent->next = NULL;
+
+                       memcpy (ent->data, buffer, buffer_len);
+                       ent->data_len = buffer_len;
+
+                       if (private_list_head == NULL)
+                               private_list_head = ent;
+                       else
+                               private_list_tail->next = ent;
+                       private_list_tail = ent;
+                       private_list_length++;
+
+                       /* Do not block here. Blocking here has led to
+                        * insufficient performance in the past. */
+                       if (pthread_mutex_trylock (&receive_list_lock) == 0)
+                       {
+                               assert (((receive_list_head == NULL) && (receive_list_length == 0))
+                                               || ((receive_list_head != NULL) && (receive_list_length != 0)));
+
+                               if (receive_list_head == NULL)
+                                       receive_list_head = private_list_head;
+                               else
+                                       receive_list_tail->next = private_list_head;
+                               receive_list_tail = private_list_tail;
+                               receive_list_length += private_list_length;
+
+                               pthread_cond_signal (&receive_list_cond);
+                               pthread_mutex_unlock (&receive_list_lock);
+
+                               private_list_head = NULL;
+                               private_list_tail = NULL;
+                               private_list_length = 0;
+                       }
+               } /* for (listen_sockets_pollfd) */
+       } /* while (listen_loop == 0) */
+
+       /* Make sure everything is dispatched before exiting. */
+       if (private_list_head != NULL)
+       {
+               pthread_mutex_lock (&receive_list_lock);
+
+               if (receive_list_head == NULL)
+                       receive_list_head = private_list_head;
+               else
+                       receive_list_tail->next = private_list_head;
+               receive_list_tail = private_list_tail;
+               receive_list_length += private_list_length;
+
+               private_list_head = NULL;
+               private_list_tail = NULL;
+               private_list_length = 0;
+
+               pthread_cond_signal (&receive_list_cond);
+               pthread_mutex_unlock (&receive_list_lock);
+       }
+
+       return (0);
+} /* }}} int network_receive */
+
+static void *receive_thread (void __attribute__((unused)) *arg)
+{
+       return (network_receive () ? (void *) 1 : (void *) 0);
+} /* void *receive_thread */
+
+static void network_init_buffer (void)
+{
+       memset (send_buffer, 0, network_config_packet_size);
+       send_buffer_ptr = send_buffer;
+       send_buffer_fill = 0;
+
+       memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
+} /* int network_init_buffer */
+
+static void networt_send_buffer_plain (sockent_t *se, /* {{{ */
+               const char *buffer, size_t buffer_size)
+{
+       int status;
+
+       while (42)
+       {
+               status = sockent_client_connect (se);
+               if (status != 0)
+                       return;
+
+               status = sendto (se->data.client.fd, buffer, buffer_size,
+                               /* flags = */ 0,
+                               (struct sockaddr *) se->data.client.addr,
+                               se->data.client.addrlen);
+               if (status < 0)
+               {
+                       char errbuf[1024];
+
+                       if ((errno == EINTR) || (errno == EAGAIN))
+                               continue;
+
+                       ERROR ("network plugin: sendto failed: %s. Closing sending socket.",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       sockent_client_disconnect (se);
+                       return;
+               }
+
+               break;
+       } /* while (42) */
+} /* }}} void networt_send_buffer_plain */
+
+#if HAVE_LIBGCRYPT
+#define BUFFER_ADD(p,s) do { \
+  memcpy (buffer + buffer_offset, (p), (s)); \
+  buffer_offset += (s); \
+} while (0)
+
+static void networt_send_buffer_signed (sockent_t *se, /* {{{ */
+               const char *in_buffer, size_t in_buffer_size)
+{
+  part_signature_sha256_t ps;
+  char buffer[BUFF_SIG_SIZE + in_buffer_size];
+  size_t buffer_offset;
+  size_t username_len;
+
+  gcry_md_hd_t hd;
+  gcry_error_t err;
+  unsigned char *hash;
+
+  hd = NULL;
+  err = gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+  if (err != 0)
+  {
+    ERROR ("network plugin: Creating HMAC object failed: %s",
+        gcry_strerror (err));
+    return;
+  }
+
+  err = gcry_md_setkey (hd, se->data.client.password,
+      strlen (se->data.client.password));
+  if (err != 0)
+  {
+    ERROR ("network plugin: gcry_md_setkey failed: %s",
+        gcry_strerror (err));
+    gcry_md_close (hd);
+    return;
+  }
+
+  username_len = strlen (se->data.client.username);
+  if (username_len > (BUFF_SIG_SIZE - PART_SIGNATURE_SHA256_SIZE))
+  {
+    ERROR ("network plugin: Username too long: %s",
+        se->data.client.username);
+    return;
+  }
+
+  memcpy (buffer + PART_SIGNATURE_SHA256_SIZE,
+      se->data.client.username, username_len);
+  memcpy (buffer + PART_SIGNATURE_SHA256_SIZE + username_len,
+      in_buffer, in_buffer_size);
+
+  /* Initialize the `ps' structure. */
+  memset (&ps, 0, sizeof (ps));
+  ps.head.type = htons (TYPE_SIGN_SHA256);
+  ps.head.length = htons (PART_SIGNATURE_SHA256_SIZE + username_len);
+
+  /* Calculate the hash value. */
+  gcry_md_write (hd, buffer + PART_SIGNATURE_SHA256_SIZE,
+      username_len + in_buffer_size);
+  hash = gcry_md_read (hd, GCRY_MD_SHA256);
+  if (hash == NULL)
+  {
+    ERROR ("network plugin: gcry_md_read failed.");
+    gcry_md_close (hd);
+    return;
+  }
+  memcpy (ps.hash, hash, sizeof (ps.hash));
+
+  /* Add the header */
+  buffer_offset = 0;
+
+  BUFFER_ADD (&ps.head.type, sizeof (ps.head.type));
+  BUFFER_ADD (&ps.head.length, sizeof (ps.head.length));
+  BUFFER_ADD (ps.hash, sizeof (ps.hash));
+
+  assert (buffer_offset == PART_SIGNATURE_SHA256_SIZE);
+
+  gcry_md_close (hd);
+  hd = NULL;
+
+  buffer_offset = PART_SIGNATURE_SHA256_SIZE + username_len + in_buffer_size;
+  networt_send_buffer_plain (se, buffer, buffer_offset);
+} /* }}} void networt_send_buffer_signed */
+
+static void networt_send_buffer_encrypted (sockent_t *se, /* {{{ */
+               const char *in_buffer, size_t in_buffer_size)
+{
+  part_encryption_aes256_t pea;
+  char buffer[BUFF_SIG_SIZE + in_buffer_size];
+  size_t buffer_size;
+  size_t buffer_offset;
+  size_t header_size;
+  size_t username_len;
+  gcry_error_t err;
+  gcry_cipher_hd_t cypher;
+
+  /* Initialize the header fields */
+  memset (&pea, 0, sizeof (pea));
+  pea.head.type = htons (TYPE_ENCR_AES256);
+
+  pea.username = se->data.client.username;
+
+  username_len = strlen (pea.username);
+  if ((PART_ENCRYPTION_AES256_SIZE + username_len) > BUFF_SIG_SIZE)
+  {
+    ERROR ("network plugin: Username too long: %s", pea.username);
+    return;
+  }
+
+  buffer_size = PART_ENCRYPTION_AES256_SIZE + username_len + in_buffer_size;
+  header_size = PART_ENCRYPTION_AES256_SIZE + username_len
+    - sizeof (pea.hash);
+
+  assert (buffer_size <= sizeof (buffer));
+  DEBUG ("network plugin: networt_send_buffer_encrypted: "
+      "buffer_size = %zu;", buffer_size);
+
+  pea.head.length = htons ((uint16_t) (PART_ENCRYPTION_AES256_SIZE
+        + username_len + in_buffer_size));
+  pea.username_length = htons ((uint16_t) username_len);
+
+  /* Chose a random initialization vector. */
+  gcry_randomize ((void *) &pea.iv, sizeof (pea.iv), GCRY_STRONG_RANDOM);
+
+  /* Create hash of the payload */
+  gcry_md_hash_buffer (GCRY_MD_SHA1, pea.hash, in_buffer, in_buffer_size);
+
+  /* Initialize the buffer */
+  buffer_offset = 0;
+  memset (buffer, 0, sizeof (buffer));
+
+
+  BUFFER_ADD (&pea.head.type, sizeof (pea.head.type));
+  BUFFER_ADD (&pea.head.length, sizeof (pea.head.length));
+  BUFFER_ADD (&pea.username_length, sizeof (pea.username_length));
+  BUFFER_ADD (pea.username, username_len);
+  BUFFER_ADD (pea.iv, sizeof (pea.iv));
+  assert (buffer_offset == header_size);
+  BUFFER_ADD (pea.hash, sizeof (pea.hash));
+  BUFFER_ADD (in_buffer, in_buffer_size);
+
+  assert (buffer_offset == buffer_size);
+
+  cypher = network_get_aes256_cypher (se, pea.iv, sizeof (pea.iv),
+      se->data.client.password);
+  if (cypher == NULL)
+    return;
+
+  /* Encrypt the buffer in-place */
+  err = gcry_cipher_encrypt (cypher,
+      buffer      + header_size,
+      buffer_size - header_size,
+      /* in = */ NULL, /* in len = */ 0);
+  if (err != 0)
+  {
+    ERROR ("network plugin: gcry_cipher_encrypt returned: %s",
+        gcry_strerror (err));
+    return;
+  }
+
+  /* Send it out without further modifications */
+  networt_send_buffer_plain (se, buffer, buffer_size);
+} /* }}} void networt_send_buffer_encrypted */
+#undef BUFFER_ADD
+#endif /* HAVE_LIBGCRYPT */
+
+static void network_send_buffer (char *buffer, size_t buffer_len) /* {{{ */
+{
+  sockent_t *se;
+
+  DEBUG ("network plugin: network_send_buffer: buffer_len = %zu", buffer_len);
+
+  for (se = sending_sockets; se != NULL; se = se->next)
+  {
+#if HAVE_LIBGCRYPT
+    if (se->data.client.security_level == SECURITY_LEVEL_ENCRYPT)
+      networt_send_buffer_encrypted (se, buffer, buffer_len);
+    else if (se->data.client.security_level == SECURITY_LEVEL_SIGN)
+      networt_send_buffer_signed (se, buffer, buffer_len);
+    else /* if (se->data.client.security_level == SECURITY_LEVEL_NONE) */
+#endif /* HAVE_LIBGCRYPT */
+      networt_send_buffer_plain (se, buffer, buffer_len);
+  } /* for (sending_sockets) */
+} /* }}} void network_send_buffer */
+
+static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */
+               value_list_t *vl_def,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       char *buffer_orig = buffer;
+
+       if (strcmp (vl_def->host, vl->host) != 0)
+       {
+               if (write_part_string (&buffer, &buffer_size, TYPE_HOST,
+                                       vl->host, strlen (vl->host)) != 0)
+                       return (-1);
+               sstrncpy (vl_def->host, vl->host, sizeof (vl_def->host));
+       }
+
+       if (vl_def->time != vl->time)
+       {
+               if (write_part_number (&buffer, &buffer_size, TYPE_TIME_HR,
+                                       (uint64_t) vl->time))
+                       return (-1);
+               vl_def->time = vl->time;
+       }
+
+       if (vl_def->interval != vl->interval)
+       {
+               if (write_part_number (&buffer, &buffer_size, TYPE_INTERVAL_HR,
+                                       (uint64_t) vl->interval))
+                       return (-1);
+               vl_def->interval = vl->interval;
+       }
+
+       if (strcmp (vl_def->plugin, vl->plugin) != 0)
+       {
+               if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN,
+                                       vl->plugin, strlen (vl->plugin)) != 0)
+                       return (-1);
+               sstrncpy (vl_def->plugin, vl->plugin, sizeof (vl_def->plugin));
+       }
+
+       if (strcmp (vl_def->plugin_instance, vl->plugin_instance) != 0)
+       {
+               if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+                                       vl->plugin_instance,
+                                       strlen (vl->plugin_instance)) != 0)
+                       return (-1);
+               sstrncpy (vl_def->plugin_instance, vl->plugin_instance, sizeof (vl_def->plugin_instance));
+       }
+
+       if (strcmp (vl_def->type, vl->type) != 0)
+       {
+               if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
+                                       vl->type, strlen (vl->type)) != 0)
+                       return (-1);
+               sstrncpy (vl_def->type, ds->type, sizeof (vl_def->type));
+       }
+
+       if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
+       {
+               if (write_part_string (&buffer, &buffer_size, TYPE_TYPE_INSTANCE,
+                                       vl->type_instance,
+                                       strlen (vl->type_instance)) != 0)
+                       return (-1);
+               sstrncpy (vl_def->type_instance, vl->type_instance, sizeof (vl_def->type_instance));
+       }
+
+       if (write_part_values (&buffer, &buffer_size, ds, vl) != 0)
+               return (-1);
+
+       return (buffer - buffer_orig);
+} /* }}} int add_to_buffer */
+
+static void flush_buffer (void)
+{
+       DEBUG ("network plugin: flush_buffer: send_buffer_fill = %i",
+                       send_buffer_fill);
+
+       network_send_buffer (send_buffer, (size_t) send_buffer_fill);
+
+       stats_octets_tx += ((uint64_t) send_buffer_fill);
+       stats_packets_tx++;
+
+       network_init_buffer ();
+}
+
+static int network_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       int status;
+
+       if (!check_send_okay (vl))
+       {
+#if COLLECT_DEBUG
+         char name[6*DATA_MAX_NAME_LEN];
+         FORMAT_VL (name, sizeof (name), vl);
+         name[sizeof (name) - 1] = 0;
+         DEBUG ("network plugin: network_write: "
+             "NOT sending %s.", name);
+#endif
+         /* Counter is not protected by another lock and may be reached by
+          * multiple threads */
+         pthread_mutex_lock (&stats_lock);
+         stats_values_not_sent++;
+         pthread_mutex_unlock (&stats_lock);
+         return (0);
+       }
+
+       uc_meta_data_add_unsigned_int (vl,
+           "network:time_sent", (uint64_t) vl->time);
+
+       pthread_mutex_lock (&send_buffer_lock);
+
+       status = add_to_buffer (send_buffer_ptr,
+                       network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
+                       &send_buffer_vl,
+                       ds, vl);
+       if (status >= 0)
+       {
+               /* status == bytes added to the buffer */
+               send_buffer_fill += status;
+               send_buffer_ptr  += status;
+
+               stats_values_sent++;
+       }
+       else
+       {
+               flush_buffer ();
+
+               status = add_to_buffer (send_buffer_ptr,
+                               network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
+                               &send_buffer_vl,
+                               ds, vl);
+
+               if (status >= 0)
+               {
+                       send_buffer_fill += status;
+                       send_buffer_ptr  += status;
+
+                       stats_values_sent++;
+               }
+       }
+
+       if (status < 0)
+       {
+               ERROR ("network plugin: Unable to append to the "
+                               "buffer for some weird reason");
+       }
+       else if ((network_config_packet_size - send_buffer_fill) < 15)
+       {
+               flush_buffer ();
+       }
+
+       pthread_mutex_unlock (&send_buffer_lock);
+
+       return ((status < 0) ? -1 : 0);
+} /* int network_write */
+
+static int network_config_set_boolean (const oconfig_item_t *ci, /* {{{ */
+    int *retval)
+{
+  if ((ci->values_num != 1)
+      || ((ci->values[0].type != OCONFIG_TYPE_BOOLEAN)
+        && (ci->values[0].type != OCONFIG_TYPE_STRING)))
+  {
+    ERROR ("network plugin: The `%s' config option needs "
+        "exactly one boolean argument.", ci->key);
+    return (-1);
+  }
+
+  if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
+  {
+    if (ci->values[0].value.boolean)
+      *retval = 1;
+    else
+      *retval = 0;
+  }
+  else
+  {
+    char *str = ci->values[0].value.string;
+
+    if (IS_TRUE (str))
+      *retval = 1;
+    else if (IS_FALSE (str))
+      *retval = 0;
+    else
+    {
+      ERROR ("network plugin: Cannot parse string value `%s' of the `%s' "
+          "option as boolean value.",
+          str, ci->key);
+      return (-1);
+    }
+  }
+
+  return (0);
+} /* }}} int network_config_set_boolean */
+
+static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
+{
+  int tmp;
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("network plugin: The `TimeToLive' config option needs exactly "
+        "one numeric argument.");
+    return (-1);
+  }
+
+  tmp = (int) ci->values[0].value.number;
+  if ((tmp > 0) && (tmp <= 255))
+    network_config_ttl = tmp;
+  else {
+    WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int network_config_set_ttl */
+
+static int network_config_set_interface (const oconfig_item_t *ci, /* {{{ */
+    int *interface)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("network plugin: The `Interface' config option needs exactly "
+        "one string argument.");
+    return (-1);
+  }
+
+  if (interface == NULL)
+    return (-1);
+
+  *interface = if_nametoindex (ci->values[0].value.string);
+
+  return (0);
+} /* }}} int network_config_set_interface */
+
+static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
+{
+  int tmp;
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
+        "one numeric argument.");
+    return (-1);
+  }
+
+  tmp = (int) ci->values[0].value.number;
+  if ((tmp >= 1024) && (tmp <= 65535))
+    network_config_packet_size = tmp;
+
+  return (0);
+} /* }}} int network_config_set_buffer_size */
+
+#if HAVE_LIBGCRYPT
+static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
+    char **ret_string)
+{
+  char *tmp;
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("network plugin: The `%s' config option needs exactly "
+        "one string argument.", ci->key);
+    return (-1);
+  }
+
+  tmp = strdup (ci->values[0].value.string);
+  if (tmp == NULL)
+    return (-1);
+
+  sfree (*ret_string);
+  *ret_string = tmp;
+
+  return (0);
+} /* }}} int network_config_set_string */
+#endif /* HAVE_LIBGCRYPT */
+
+#if HAVE_LIBGCRYPT
+static int network_config_set_security_level (oconfig_item_t *ci, /* {{{ */
+    int *retval)
+{
+  char *str;
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("network plugin: The `SecurityLevel' config option needs exactly "
+        "one string argument.");
+    return (-1);
+  }
+
+  str = ci->values[0].value.string;
+  if (strcasecmp ("Encrypt", str) == 0)
+    *retval = SECURITY_LEVEL_ENCRYPT;
+  else if (strcasecmp ("Sign", str) == 0)
+    *retval = SECURITY_LEVEL_SIGN;
+  else if (strcasecmp ("None", str) == 0)
+    *retval = SECURITY_LEVEL_NONE;
+  else
+  {
+    WARNING ("network plugin: Unknown security level: %s.", str);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int network_config_set_security_level */
+#endif /* HAVE_LIBGCRYPT */
+
+static int network_config_add_listen (const oconfig_item_t *ci) /* {{{ */
+{
+  sockent_t *se;
+  int status;
+  int i;
+
+  if ((ci->values_num < 1) || (ci->values_num > 2)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || ((ci->values_num > 1) && (ci->values[1].type != OCONFIG_TYPE_STRING)))
+  {
+    ERROR ("network plugin: The `%s' config option needs "
+        "one or two string arguments.", ci->key);
+    return (-1);
+  }
+
+  se = sockent_create (SOCKENT_TYPE_SERVER);
+  if (se == NULL)
+  {
+    ERROR ("network plugin: sockent_create failed.");
+    return (-1);
+  }
+
+  se->node = strdup (ci->values[0].value.string);
+  if (ci->values_num >= 2)
+    se->service = strdup (ci->values[1].value.string);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+#if HAVE_LIBGCRYPT
+    if (strcasecmp ("AuthFile", child->key) == 0)
+      network_config_set_string (child, &se->data.server.auth_file);
+    else if (strcasecmp ("SecurityLevel", child->key) == 0)
+      network_config_set_security_level (child,
+          &se->data.server.security_level);
+    else
+#endif /* HAVE_LIBGCRYPT */
+    if (strcasecmp ("Interface", child->key) == 0)
+      network_config_set_interface (child,
+          &se->interface);
+    else
+    {
+      WARNING ("network plugin: Option `%s' is not allowed here.",
+          child->key);
+    }
+  }
+
+#if HAVE_LIBGCRYPT
+  if ((se->data.server.security_level > SECURITY_LEVEL_NONE)
+      && (se->data.server.auth_file == NULL))
+  {
+    ERROR ("network plugin: A security level higher than `none' was "
+        "requested, but no AuthFile option was given. Cowardly refusing to "
+        "open this socket!");
+    sockent_destroy (se);
+    return (-1);
+  }
+#endif /* HAVE_LIBGCRYPT */
+
+  status = sockent_init_crypto (se);
+  if (status != 0)
+  {
+    ERROR ("network plugin: network_config_add_listen: sockent_init_crypto() failed.");
+    sockent_destroy (se);
+    return (-1);
+  }
+
+  status = sockent_server_listen (se);
+  if (status != 0)
+  {
+    ERROR ("network plugin: network_config_add_server: sockent_server_listen failed.");
+    sockent_destroy (se);
+    return (-1);
+  }
+
+  status = sockent_add (se);
+  if (status != 0)
+  {
+    ERROR ("network plugin: network_config_add_listen: sockent_add failed.");
+    sockent_destroy (se);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int network_config_add_listen */
+
+static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */
+{
+  sockent_t *se;
+  int status;
+  int i;
+
+  if ((ci->values_num < 1) || (ci->values_num > 2)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || ((ci->values_num > 1) && (ci->values[1].type != OCONFIG_TYPE_STRING)))
+  {
+    ERROR ("network plugin: The `%s' config option needs "
+        "one or two string arguments.", ci->key);
+    return (-1);
+  }
+
+  se = sockent_create (SOCKENT_TYPE_CLIENT);
+  if (se == NULL)
+  {
+    ERROR ("network plugin: sockent_create failed.");
+    return (-1);
+  }
+
+  se->node = strdup (ci->values[0].value.string);
+  if (ci->values_num >= 2)
+    se->service = strdup (ci->values[1].value.string);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+#if HAVE_LIBGCRYPT
+    if (strcasecmp ("Username", child->key) == 0)
+      network_config_set_string (child, &se->data.client.username);
+    else if (strcasecmp ("Password", child->key) == 0)
+      network_config_set_string (child, &se->data.client.password);
+    else if (strcasecmp ("SecurityLevel", child->key) == 0)
+      network_config_set_security_level (child,
+          &se->data.client.security_level);
+    else
+#endif /* HAVE_LIBGCRYPT */
+    if (strcasecmp ("Interface", child->key) == 0)
+      network_config_set_interface (child,
+          &se->interface);
+               else if (strcasecmp ("ResolveInterval", child->key) == 0)
+                       cf_util_get_cdtime(child, &se->data.client.resolve_interval);
+    else
+    {
+      WARNING ("network plugin: Option `%s' is not allowed here.",
+          child->key);
+    }
+  }
+
+#if HAVE_LIBGCRYPT
+  if ((se->data.client.security_level > SECURITY_LEVEL_NONE)
+      && ((se->data.client.username == NULL)
+        || (se->data.client.password == NULL)))
+  {
+    ERROR ("network plugin: A security level higher than `none' was "
+        "requested, but no Username or Password option was given. "
+        "Cowardly refusing to open this socket!");
+    sockent_destroy (se);
+    return (-1);
+  }
+#endif /* HAVE_LIBGCRYPT */
+
+  status = sockent_init_crypto (se);
+  if (status != 0)
+  {
+    ERROR ("network plugin: network_config_add_server: sockent_init_crypto() failed.");
+    sockent_destroy (se);
+    return (-1);
+  }
+
+  /* No call to sockent_client_connect() here -- it is called from
+   * networt_send_buffer_plain(). */
+
+  status = sockent_add (se);
+  if (status != 0)
+  {
+    ERROR ("network plugin: network_config_add_server: sockent_add failed.");
+    sockent_destroy (se);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int network_config_add_server */
+
+static int network_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  /* The options need to be applied first */
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp ("TimeToLive", child->key) == 0)
+      network_config_set_ttl (child);
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Listen", child->key) == 0)
+      network_config_add_listen (child);
+    else if (strcasecmp ("Server", child->key) == 0)
+      network_config_add_server (child);
+    else if (strcasecmp ("TimeToLive", child->key) == 0) {
+      /* Handled earlier */
+    }
+    else if (strcasecmp ("MaxPacketSize", child->key) == 0)
+      network_config_set_buffer_size (child);
+    else if (strcasecmp ("Forward", child->key) == 0)
+      network_config_set_boolean (child, &network_config_forward);
+    else if (strcasecmp ("ReportStats", child->key) == 0)
+      network_config_set_boolean (child, &network_config_stats);
+    else
+    {
+      WARNING ("network plugin: Option `%s' is not allowed here.",
+          child->key);
+    }
+  }
+
+  return (0);
+} /* }}} int network_config */
+
+static int network_notification (const notification_t *n,
+    user_data_t __attribute__((unused)) *user_data)
+{
+  char  buffer[network_config_packet_size];
+  char *buffer_ptr = buffer;
+  int   buffer_free = sizeof (buffer);
+  int   status;
+
+  if (!check_send_notify_okay (n))
+    return (0);
+
+  memset (buffer, 0, sizeof (buffer));
+
+  status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME_HR,
+      (uint64_t) n->time);
+  if (status != 0)
+    return (-1);
+
+  status = write_part_number (&buffer_ptr, &buffer_free, TYPE_SEVERITY,
+      (uint64_t) n->severity);
+  if (status != 0)
+    return (-1);
+
+  if (strlen (n->host) > 0)
+  {
+    status = write_part_string (&buffer_ptr, &buffer_free, TYPE_HOST,
+        n->host, strlen (n->host));
+    if (status != 0)
+      return (-1);
+  }
+
+  if (strlen (n->plugin) > 0)
+  {
+    status = write_part_string (&buffer_ptr, &buffer_free, TYPE_PLUGIN,
+        n->plugin, strlen (n->plugin));
+    if (status != 0)
+      return (-1);
+  }
+
+  if (strlen (n->plugin_instance) > 0)
+  {
+    status = write_part_string (&buffer_ptr, &buffer_free,
+        TYPE_PLUGIN_INSTANCE,
+        n->plugin_instance, strlen (n->plugin_instance));
+    if (status != 0)
+      return (-1);
+  }
+
+  if (strlen (n->type) > 0)
+  {
+    status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE,
+        n->type, strlen (n->type));
+    if (status != 0)
+      return (-1);
+  }
+
+  if (strlen (n->type_instance) > 0)
+  {
+    status = write_part_string (&buffer_ptr, &buffer_free, TYPE_TYPE_INSTANCE,
+        n->type_instance, strlen (n->type_instance));
+    if (status != 0)
+      return (-1);
+  }
+
+  status = write_part_string (&buffer_ptr, &buffer_free, TYPE_MESSAGE,
+      n->message, strlen (n->message));
+  if (status != 0)
+    return (-1);
+
+  network_send_buffer (buffer, sizeof (buffer) - buffer_free);
+
+  return (0);
+} /* int network_notification */
+
+static int network_shutdown (void)
+{
+       sockent_t *se;
+
+       listen_loop++;
+
+       /* Kill the listening thread */
+       if (receive_thread_running != 0)
+       {
+               INFO ("network plugin: Stopping receive thread.");
+               pthread_kill (receive_thread_id, SIGTERM);
+               pthread_join (receive_thread_id, NULL /* no return value */);
+               memset (&receive_thread_id, 0, sizeof (receive_thread_id));
+               receive_thread_running = 0;
+       }
+
+       /* Shutdown the dispatching thread */
+       if (dispatch_thread_running != 0)
+       {
+               INFO ("network plugin: Stopping dispatch thread.");
+               pthread_mutex_lock (&receive_list_lock);
+               pthread_cond_broadcast (&receive_list_cond);
+               pthread_mutex_unlock (&receive_list_lock);
+               pthread_join (dispatch_thread_id, /* ret = */ NULL);
+               dispatch_thread_running = 0;
+       }
+
+       sockent_destroy (listen_sockets);
+
+       if (send_buffer_fill > 0)
+               flush_buffer ();
+
+       sfree (send_buffer);
+
+       for (se = sending_sockets; se != NULL; se = se->next)
+               sockent_client_disconnect (se);
+       sockent_destroy (sending_sockets);
+
+       plugin_unregister_config ("network");
+       plugin_unregister_init ("network");
+       plugin_unregister_write ("network");
+       plugin_unregister_shutdown ("network");
+
+       return (0);
+} /* int network_shutdown */
+
+static int network_stats_read (void) /* {{{ */
+{
+       derive_t copy_octets_rx;
+       derive_t copy_octets_tx;
+       derive_t copy_packets_rx;
+       derive_t copy_packets_tx;
+       derive_t copy_values_dispatched;
+       derive_t copy_values_not_dispatched;
+       derive_t copy_values_sent;
+       derive_t copy_values_not_sent;
+       derive_t copy_receive_list_length;
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t values[2];
+
+       copy_octets_rx = stats_octets_rx;
+       copy_octets_tx = stats_octets_tx;
+       copy_packets_rx = stats_packets_rx;
+       copy_packets_tx = stats_packets_tx;
+       copy_values_dispatched = stats_values_dispatched;
+       copy_values_not_dispatched = stats_values_not_dispatched;
+       copy_values_sent = stats_values_sent;
+       copy_values_not_sent = stats_values_not_sent;
+       copy_receive_list_length = receive_list_length;
+
+       /* Initialize `vl' */
+       vl.values = values;
+       vl.values_len = 2;
+       vl.time = 0;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "network", sizeof (vl.plugin));
+
+       /* Octets received / sent */
+       vl.values[0].derive = (derive_t) copy_octets_rx;
+       vl.values[1].derive = (derive_t) copy_octets_tx;
+       sstrncpy (vl.type, "if_octets", sizeof (vl.type));
+       plugin_dispatch_values (&vl);
+
+       /* Packets received / send */
+       vl.values[0].derive = (derive_t) copy_packets_rx;
+       vl.values[1].derive = (derive_t) copy_packets_tx;
+       sstrncpy (vl.type, "if_packets", sizeof (vl.type));
+       plugin_dispatch_values (&vl);
+
+       /* Values (not) dispatched and (not) send */
+       sstrncpy (vl.type, "total_values", sizeof (vl.type));
+       vl.values_len = 1;
+
+       vl.values[0].derive = (derive_t) copy_values_dispatched;
+       sstrncpy (vl.type_instance, "dispatch-accepted",
+                       sizeof (vl.type_instance));
+       plugin_dispatch_values (&vl);
+
+       vl.values[0].derive = (derive_t) copy_values_not_dispatched;
+       sstrncpy (vl.type_instance, "dispatch-rejected",
+                       sizeof (vl.type_instance));
+       plugin_dispatch_values (&vl);
+
+       vl.values[0].derive = (derive_t) copy_values_sent;
+       sstrncpy (vl.type_instance, "send-accepted",
+                       sizeof (vl.type_instance));
+       plugin_dispatch_values (&vl);
+
+       vl.values[0].derive = (derive_t) copy_values_not_sent;
+       sstrncpy (vl.type_instance, "send-rejected",
+                       sizeof (vl.type_instance));
+       plugin_dispatch_values (&vl);
+
+       /* Receive queue length */
+       vl.values[0].gauge = (gauge_t) copy_receive_list_length;
+       sstrncpy (vl.type, "queue_length", sizeof (vl.type));
+       vl.type_instance[0] = 0;
+       plugin_dispatch_values (&vl);
+
+       return (0);
+} /* }}} int network_stats_read */
+
+static int network_init (void)
+{
+       static _Bool have_init = 0;
+
+       /* Check if we were already initialized. If so, just return - there's
+        * nothing more to do (for now, that is). */
+       if (have_init)
+               return (0);
+       have_init = 1;
+
+#if HAVE_LIBGCRYPT
+       network_init_gcrypt ();
+#endif
+
+       if (network_config_stats != 0)
+               plugin_register_read ("network", network_stats_read);
+
+       plugin_register_shutdown ("network", network_shutdown);
+
+       send_buffer = malloc (network_config_packet_size);
+       if (send_buffer == NULL)
+       {
+               ERROR ("network plugin: malloc failed.");
+               return (-1);
+       }
+       network_init_buffer ();
+
+       /* setup socket(s) and so on */
+       if (sending_sockets != NULL)
+       {
+               plugin_register_write ("network", network_write,
+                               /* user_data = */ NULL);
+               plugin_register_notification ("network", network_notification,
+                               /* user_data = */ NULL);
+       }
+
+       /* If no threads need to be started, return here. */
+       if ((listen_sockets_num == 0)
+                       || ((dispatch_thread_running != 0)
+                               && (receive_thread_running != 0)))
+               return (0);
+
+       if (dispatch_thread_running == 0)
+       {
+               int status;
+               status = plugin_thread_create (&dispatch_thread_id,
+                               NULL /* no attributes */,
+                               dispatch_thread,
+                               NULL /* no argument */);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("network: pthread_create failed: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+               }
+               else
+               {
+                       dispatch_thread_running = 1;
+               }
+       }
+
+       if (receive_thread_running == 0)
+       {
+               int status;
+               status = plugin_thread_create (&receive_thread_id,
+                               NULL /* no attributes */,
+                               receive_thread,
+                               NULL /* no argument */);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("network: pthread_create failed: %s",
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+               }
+               else
+               {
+                       receive_thread_running = 1;
+               }
+       }
+
+       return (0);
+} /* int network_init */
+
+/*
+ * The flush option of the network plugin cannot flush individual identifiers.
+ * All the values are added to a buffer and sent when the buffer is full, the
+ * requested value may or may not be in there, it's not worth finding out. We
+ * just send the buffer if `flush'  is called - if the requested value was in
+ * there, good. If not, well, then there is nothing to flush.. -octo
+ */
+static int network_flush (__attribute__((unused)) cdtime_t timeout,
+               __attribute__((unused)) const char *identifier,
+               __attribute__((unused)) user_data_t *user_data)
+{
+       pthread_mutex_lock (&send_buffer_lock);
+
+       if (send_buffer_fill > 0)
+         flush_buffer ();
+
+       pthread_mutex_unlock (&send_buffer_lock);
+
+       return (0);
+} /* int network_flush */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("network", network_config);
+       plugin_register_init   ("network", network_init);
+       plugin_register_flush   ("network", network_flush,
+                       /* user_data = */ NULL);
+} /* void module_register */
+
+/* vim: set fdm=marker : */
diff --git a/src/network.h b/src/network.h
new file mode 100644 (file)
index 0000000..5457722
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * collectd - src/network.h
+ * Copyright (C) 2005-2008  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+/*
+ * From RFC2365: Administratively Scoped IP Multicast
+ *
+ * The IPv4 Organization Local Scope -- 239.192.0.0/14
+ *
+ * 239.192.0.0/14 is defined to be the IPv4 Organization Local Scope, and is
+ * the space from which an organization should allocate sub-ranges when
+ * defining scopes for private use.
+ *
+ * Port 25826 is not assigned as of 2005-09-12
+ */
+
+/*
+ * From RFC2373: IP Version 6 Addressing Architecture
+ *
+ * 2.7 Multicast Addresses
+ *
+ *  |   8    |  4 |  4 |          80 bits          |     32 bits     |
+ *  +--------+----+----+---------------------------+-----------------+
+ *  |11111111|flgs|scop|   reserved must be zero   |    group ID     |
+ *  +--------+----+----+---------------------------+-----------------+
+ *
+ * flgs = 1 => non-permanently-assigned ("transient") multicast address.
+ * scop = 8 => organization-local scope
+ *
+ * group = efc0:4a42 = 239.192.74.66
+ */
+
+#define NET_DEFAULT_V4_ADDR "239.192.74.66"
+#define NET_DEFAULT_V6_ADDR "ff18::efc0:4a42"
+#define NET_DEFAULT_PORT    "25826"
+
+#define TYPE_HOST            0x0000
+#define TYPE_TIME            0x0001
+#define TYPE_TIME_HR         0x0008
+#define TYPE_PLUGIN          0x0002
+#define TYPE_PLUGIN_INSTANCE 0x0003
+#define TYPE_TYPE            0x0004
+#define TYPE_TYPE_INSTANCE   0x0005
+#define TYPE_VALUES          0x0006
+#define TYPE_INTERVAL        0x0007
+#define TYPE_INTERVAL_HR     0x0009
+
+/* Types to transmit notifications */
+#define TYPE_MESSAGE         0x0100
+#define TYPE_SEVERITY        0x0101
+
+#define TYPE_SIGN_SHA256     0x0200
+#define TYPE_ENCR_AES256     0x0210
+
+#endif /* NETWORK_H */
diff --git a/src/nfs.c b/src/nfs.c
new file mode 100644 (file)
index 0000000..4285d76
--- /dev/null
+++ b/src/nfs.c
@@ -0,0 +1,680 @@
+/**
+ * collectd - src/nfs.c
+ * Copyright (C) 2005,2006  Jason Pepas
+ * Copyright (C) 2012,2013  Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Jason Pepas <cell at ices.utexas.edu>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Cosmin Ioiart <cioiart at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
+/*
+see /proc/net/rpc/nfs
+see http://www.missioncriticallinux.com/orph/NFS-Statistics
+
+net x x x x
+rpc_stat.netcnt         Not used; always zero.
+rpc_stat.netudpcnt      Not used; always zero.
+rpc_stat.nettcpcnt      Not used; always zero.
+rpc_stat.nettcpconn     Not used; always zero.
+
+rpc x x x
+rpc_stat.rpccnt             The number of RPC calls.
+rpc_stat.rpcretrans         The number of retransmitted RPC calls.
+rpc_stat.rpcauthrefresh     The number of credential refreshes.
+
+proc2 x x x...
+proc3 x x x...
+
+Procedure   NFS Version NFS Version 3
+Number      Procedures  Procedures
+
+0           null        null
+1           getattr     getattr
+2           setattr     setattr
+3           root        lookup
+4           lookup      access
+5           readlink    readlink
+6           read        read
+7           wrcache     write
+8           write       create
+9           create      mkdir
+10          remove      symlink
+11          rename      mknod
+12          link        remove
+13          symlink     rmdir
+14          mkdir       rename
+15          rmdir       link
+16          readdir     readdir
+17          fsstat      readdirplus
+18                      fsstat
+19                      fsinfo
+20                      pathconf
+21                      commit
+*/
+
+static const char *nfs2_procedures_names[] =
+{
+       "null",
+       "getattr",
+       "setattr",
+       "root",
+       "lookup",
+       "readlink",
+       "read",
+       "wrcache",
+       "write",
+       "create",
+       "remove",
+       "rename",
+       "link",
+       "symlink",
+       "mkdir",
+       "rmdir",
+       "readdir",
+       "fsstat"
+};
+static size_t nfs2_procedures_names_num = STATIC_ARRAY_SIZE (nfs2_procedures_names);
+
+static const char *nfs3_procedures_names[] =
+{
+       "null",
+       "getattr",
+       "setattr",
+       "lookup",
+       "access",
+       "readlink",
+       "read",
+       "write",
+       "create",
+       "mkdir",
+       "symlink",
+       "mknod",
+       "remove",
+       "rmdir",
+       "rename",
+       "link",
+       "readdir",
+       "readdirplus",
+       "fsstat",
+       "fsinfo",
+       "pathconf",
+       "commit"
+};
+static size_t nfs3_procedures_names_num = STATIC_ARRAY_SIZE (nfs3_procedures_names);
+
+#if HAVE_LIBKSTAT
+static const char *nfs4_procedures_names[] =
+{
+       "null",
+       "compound",
+       "reserved",
+       "access",
+       "close",
+       "commit",
+       "create",
+       "delegpurge",
+       "delegreturn",
+       "getattr",
+       "getfh",
+       "link",
+       "lock",
+       "lockt",
+       "locku",
+       "lookup",
+       "lookupp",
+       "nverify",
+       "open",
+       "openattr",
+       "open_confirm",
+       "open_downgrade",
+       "putfh",
+       "putpubfh",
+       "putrootfh",
+       "read",
+       "readdir",
+       "readlink",
+       "remove",
+       "rename",
+       "renew",
+       "restorefh",
+       "savefh",
+       "secinfo",
+       "setattr",
+       "setclientid",
+       "setclientid_confirm",
+       "verify",
+       "write"
+};
+static size_t nfs4_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_procedures_names);
+#endif
+
+#if KERNEL_LINUX
+static const char *nfs4_server40_procedures_names[] =
+{
+       "null",
+       "compound",
+       "reserved",
+       "access",
+       "close",
+       "commit",
+       "create",
+       "delegpurge",
+       "delegreturn",
+       "getattr",
+       "getfh",
+       "link",
+       "lock",
+       "lockt",
+       "locku",
+       "lookup",
+       "lookupp",
+       "nverify",
+       "open",
+       "openattr",
+       "open_confirm",
+       "open_downgrade",
+       "putfh",
+       "putpubfh",
+       "putrootfh",
+       "read",
+       "readdir",
+       "readlink",
+       "remove",
+       "rename",
+       "renew",
+       "restorefh",
+       "savefh",
+       "secinfo",
+       "setattr",
+       "setclientid",
+       "setcltid_confirm",
+       "verify",
+       "write",
+       "release_lockowner"
+};
+
+static size_t nfs4_server40_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_server40_procedures_names);
+
+static const char *nfs4_server41_procedures_names[] =
+{
+       "backchannel_ctl",
+       "bind_conn_to_session", 
+       "exchange_id",
+       "create_session",
+       "destroy_session",
+       "free_stateid",
+       "get_dir_delegation",
+       "getdeviceinfo",
+       "getdevicelist",
+       "layoutcommit",
+       "layoutget",
+       "layoutreturn",
+       "secinfo_no_name",
+       "sequence",
+       "set_ssv",
+       "test_stateid",
+       "want_delegation",
+       "destroy_clientid",
+       "reclaim_complete",
+};
+
+static size_t nfs4_server41_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_server41_procedures_names);
+
+#define NFS4_SERVER40_NUM_PROC ( \
+       STATIC_ARRAY_SIZE (nfs4_server40_procedures_names) )
+
+#define NFS4_SERVER41_NUM_PROC ( \
+       STATIC_ARRAY_SIZE (nfs4_server40_procedures_names) + \
+       STATIC_ARRAY_SIZE (nfs4_server41_procedures_names) )
+
+#define NFS4_SERVER_MAX_PROC (NFS4_SERVER41_NUM_PROC)
+
+static const char *nfs4_client40_procedures_names[] =
+{
+       "null",
+       "read",
+       "write",
+       "commit",
+       "open",
+       "open_confirm",
+       "open_noattr",
+       "open_downgrade",
+       "close",
+       "setattr",
+       "fsinfo",
+       "renew",
+       "setclientid",
+       "setclientid_confirm",
+       "lock",
+       "lockt",
+       "locku",
+       "access",
+       "getattr",
+       "lookup",
+       "lookupp",
+       "remove",
+       "rename",
+       "link",
+       "symlink",
+       "create",
+       "pathconf",
+       "statfs",
+       "readlink",
+       "readdir",
+       "server_caps",
+       "delegreturn",
+       "getacl",
+       "setacl",
+       "fs_locations",         /* |35| 2.6.18 */
+       "release_lockowner",    /* |42| 2.6.36 */
+       "secinfo",              /* |46| 2.6.39 */
+       "fsid_present"          /* |54| 3.13 */
+};
+
+static const char *nfs4_client41_procedures_names[] =
+{
+       "exchange_id",          /* |40| 2.6.30 */
+       "create_session",       /* |40| 2.6.30 */
+       "destroy_session",      /* |40| 2.6.30 */
+       "sequence",             /* |40| 2.6.30 */
+       "get_lease_time",       /* |40| 2.6.30 */
+       "reclaim_complete",     /* |41| 2.6.33 */
+       "layoutget",            /* |44| 2.6.37 */
+       "getdeviceinfo",        /* |44| 2.6.37 */
+       "layoutcommit",         /* |46| 2.6.39 */
+       "layoutreturn",         /* |47| 3.0 */
+       "secinfo_no_name",      /* |51| 3.1 */
+       "test_stateid",         /* |51| 3.1 */
+       "free_stateid",         /* |51| 3.1 */
+       "getdevicelist",        /* |51| 3.1 */
+       "bind_conn_to_session", /* |53| 3.5 */
+       "destroy_clientid"      /* |53| 3.5 */
+};
+
+#define NFS4_CLIENT40_NUM_PROC ( \
+       STATIC_ARRAY_SIZE (nfs4_client40_procedures_names) )
+
+#define NFS4_CLIENT41_NUM_PROC ( \
+       STATIC_ARRAY_SIZE (nfs4_client40_procedures_names) + \
+       STATIC_ARRAY_SIZE (nfs4_client41_procedures_names) )
+
+#define NFS4_CLIENT_MAX_PROC (NFS4_CLIENT41_NUM_PROC)
+
+#endif
+
+#if HAVE_LIBKSTAT
+extern kstat_ctl_t *kc;
+static kstat_t *nfs2_ksp_client;
+static kstat_t *nfs2_ksp_server;
+static kstat_t *nfs3_ksp_client;
+static kstat_t *nfs3_ksp_server;
+static kstat_t *nfs4_ksp_client;
+static kstat_t *nfs4_ksp_server;
+#endif
+
+#if KERNEL_LINUX
+static int nfs_init (void)
+{
+       return (0);
+}
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+static int nfs_init (void)
+{
+       kstat_t *ksp_chain = NULL;
+
+       nfs2_ksp_client = NULL;
+       nfs2_ksp_server = NULL;
+       nfs3_ksp_client = NULL;
+       nfs3_ksp_server = NULL;
+       nfs4_ksp_client = NULL;
+       nfs4_ksp_server = NULL;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
+                       ksp_chain = ksp_chain->ks_next)
+       {
+               if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
+                       continue;
+               else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
+                       nfs2_ksp_server = ksp_chain;
+               else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
+                       nfs3_ksp_server = ksp_chain;
+               else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
+                       nfs4_ksp_server = ksp_chain;
+               else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
+                       nfs2_ksp_client = ksp_chain;
+               else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
+                       nfs3_ksp_client = ksp_chain;
+               else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
+                       nfs4_ksp_client = ksp_chain;
+       }
+
+       return (0);
+} /* int nfs_init */
+#endif
+
+static void nfs_procedures_submit (const char *plugin_instance,
+               const char **type_instances,
+               value_t *values, size_t values_num)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+       size_t i;
+
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "nfs", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
+
+       for (i = 0; i < values_num; i++)
+       {
+               vl.values = values + i;
+               sstrncpy (vl.type_instance, type_instances[i],
+                               sizeof (vl.type_instance));
+               plugin_dispatch_values (&vl);
+       }
+} /* void nfs_procedures_submit */
+
+#if KERNEL_LINUX
+static void nfs_submit_fields (int nfs_version, const char *instance, 
+               char **fields, size_t fields_num, const char **proc_names)
+{
+       char plugin_instance[DATA_MAX_NAME_LEN];
+       value_t values[fields_num];
+       size_t i;
+
+       ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
+                       nfs_version, instance);
+
+       for (i = 0; i < fields_num; i++)
+               (void) parse_value (fields[i], &values[i], DS_TYPE_DERIVE);
+
+       nfs_procedures_submit (plugin_instance, proc_names, values,
+                       fields_num);
+}
+
+static int nfs_submit_fields_safe (int nfs_version, const char *instance,
+               char **fields, size_t fields_num,
+               const char **proc_names, size_t proc_names_num)
+{
+       if (fields_num != proc_names_num)
+       {
+               WARNING ("nfs plugin: Wrong number of fields for "
+                               "NFSv%i %s statistics. Expected %zu, got %zu.",
+                               nfs_version, instance,
+                               proc_names_num, fields_num);
+               return (EINVAL);
+       }
+
+       nfs_submit_fields (nfs_version, instance, fields, fields_num, 
+                       proc_names);
+
+       return (0);
+}
+
+static int nfs_submit_nfs4_server (const char *instance, char **fields, 
+               size_t fields_num)
+{
+       static int suppress_warning = 0;
+
+       if (fields_num != NFS4_SERVER40_NUM_PROC &&
+               fields_num != NFS4_SERVER41_NUM_PROC) 
+       {
+               if (!suppress_warning)
+               {
+                       WARNING ("nfs plugin: Unexpected number of fields for "
+                                       "NFSv4 %s statistics: %zu. ",
+                                       instance, fields_num);
+               }
+
+               if (fields_num > NFS4_SERVER_MAX_PROC)
+               {
+                       fields_num = NFS4_SERVER_MAX_PROC;
+                       suppress_warning = 1;
+               }
+               else
+               {
+                       return (EINVAL);
+               }
+       }
+
+        nfs_submit_fields (4, instance, fields, 
+                       nfs4_server40_procedures_names_num,
+                       nfs4_server40_procedures_names);
+
+       if (fields_num >= NFS4_SERVER41_NUM_PROC)
+       {
+               fields += nfs4_server40_procedures_names_num;
+
+               nfs_submit_fields (4, instance, fields, 
+                               nfs4_server41_procedures_names_num, 
+                               nfs4_server41_procedures_names);
+       }
+
+       return (0);
+}
+
+static int nfs_submit_nfs4_client (const char *instance, char **fields, 
+               size_t fields_num)
+{
+       size_t proc40_names_num, proc41_names_num;
+
+       static int suppress_warning = 0;
+
+       switch (fields_num)
+       {
+               case 34:
+               case 35:
+               case 36:
+               case 37:
+               case 38:
+                       /* 4.0-only configuration */
+                       proc40_names_num = fields_num;
+                       break;
+               case 40:
+               case 41:
+                       proc40_names_num = 35;
+                       break;
+               case 42:
+               case 44:
+                       proc40_names_num = 36;
+               case 46:
+               case 47:
+               case 51:
+               case 53:
+                       proc40_names_num = 37;
+                       break;
+               case 54:
+                       proc40_names_num = 38;
+                       break;
+               default:
+                       if (!suppress_warning)
+                       {
+                               WARNING ("nfs plugin: Unexpected number of "
+                                               "fields for NFSv4 %s "
+                                               "statistics: %zu. ",
+                                               instance, fields_num);
+                       }
+
+                       if (fields_num > 34)
+                       {
+                               /* safe fallback to basic nfs40 procedures */
+                               fields_num = 34;
+                               proc40_names_num = 34;
+
+                               suppress_warning = 1;
+                       }
+                       else
+                       {
+                               return (EINVAL);
+                       }
+       }
+
+       nfs_submit_fields (4, instance, fields, proc40_names_num,
+                       nfs4_client40_procedures_names);
+
+       if (fields_num > proc40_names_num)
+       {
+               proc41_names_num = fields_num - proc40_names_num;
+               fields += proc40_names_num;
+
+               nfs_submit_fields (4, instance, fields,proc41_names_num,
+                                nfs4_client41_procedures_names);
+       }
+
+       return (0);
+}
+
+static void nfs_read_linux (FILE *fh, char *inst)
+{
+       char buffer[1024];
+
+       char *fields[64];
+       int fields_num = 0;
+
+       if (fh == NULL)
+               return;
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               fields_num = strsplit (buffer,
+                               fields, STATIC_ARRAY_SIZE (fields));
+
+               if (fields_num < 3)
+                       continue;
+
+               if (strcmp (fields[0], "proc2") == 0)
+               {
+                       nfs_submit_fields_safe (/* version = */ 2, inst,
+                                       fields + 2, (size_t) (fields_num - 2),
+                                       nfs2_procedures_names,
+                                       nfs2_procedures_names_num);
+               }
+               else if (strncmp (fields[0], "proc3", 5) == 0)
+               {
+                       nfs_submit_fields_safe (/* version = */ 3, inst,
+                                       fields + 2, (size_t) (fields_num - 2),
+                                       nfs3_procedures_names,
+                                       nfs3_procedures_names_num);
+               }
+               else if (strcmp (fields[0], "proc4ops") == 0)
+               {
+                       if (inst[0] == 's')
+                               nfs_submit_nfs4_server (inst, fields + 2, 
+                                               (size_t) (fields_num - 2));
+               }
+               else if (strcmp (fields[0], "proc4") == 0)
+               {
+                       if (inst[0] == 'c')
+                               nfs_submit_nfs4_client (inst, fields + 2,
+                                               (size_t) (fields_num - 2));                     
+               }
+       } /* while (fgets) */
+} /* void nfs_read_linux */
+#endif /* KERNEL_LINUX */
+
+#if HAVE_LIBKSTAT
+static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst,
+               char const **proc_names, size_t proc_names_num)
+{
+       char plugin_instance[DATA_MAX_NAME_LEN];
+       value_t values[proc_names_num];
+       size_t i;
+
+       if (ksp == NULL)
+               return (EINVAL);
+
+       ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
+                       nfs_version, inst);
+
+       kstat_read(kc, ksp, NULL);
+       for (i = 0; i < proc_names_num; i++)
+       {
+               /* The name passed to kstat_data_lookup() doesn't have the
+                * "const" modifier, so we need to copy the name here. */
+               char name[32];
+               sstrncpy (name, proc_names[i], sizeof (name));
+
+               values[i].counter = (derive_t) get_kstat_value (ksp, name);
+       }
+
+       nfs_procedures_submit (plugin_instance, proc_names, values,
+                       proc_names_num);
+       return (0);
+}
+#endif
+
+#if KERNEL_LINUX
+static int nfs_read (void)
+{
+       FILE *fh;
+
+       if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
+       {
+               nfs_read_linux (fh, "client");
+               fclose (fh);
+       }
+
+       if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
+       {
+               nfs_read_linux (fh, "server");
+               fclose (fh);
+       }
+
+       return (0);
+}
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+static int nfs_read (void)
+{
+       nfs_read_kstat (nfs2_ksp_client, /* version = */ 2, "client",
+                       nfs2_procedures_names, nfs2_procedures_names_num);
+       nfs_read_kstat (nfs2_ksp_server, /* version = */ 2, "server",
+                       nfs2_procedures_names, nfs2_procedures_names_num);
+       nfs_read_kstat (nfs3_ksp_client, /* version = */ 3, "client",
+                       nfs3_procedures_names, nfs3_procedures_names_num);
+       nfs_read_kstat (nfs3_ksp_server, /* version = */ 3, "server",
+                       nfs3_procedures_names, nfs3_procedures_names_num);
+       nfs_read_kstat (nfs4_ksp_client, /* version = */ 4, "client",
+                       nfs4_procedures_names, nfs4_procedures_names_num);
+       nfs_read_kstat (nfs4_ksp_server, /* version = */ 4, "server",
+                       nfs4_procedures_names, nfs4_procedures_names_num);
+
+       return (0);
+}
+#endif /* HAVE_LIBKSTAT */
+
+void module_register (void)
+{
+       plugin_register_init ("nfs", nfs_init);
+       plugin_register_read ("nfs", nfs_read);
+} /* void module_register */
diff --git a/src/nginx.c b/src/nginx.c
new file mode 100644 (file)
index 0000000..4e4ce3b
--- /dev/null
@@ -0,0 +1,315 @@
+/**
+ * collectd - src/nginx.c
+ * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2008       Sebastian Harl
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <curl/curl.h>
+
+static char *url         = NULL;
+static char *user        = NULL;
+static char *pass        = NULL;
+static char *verify_peer = NULL;
+static char *verify_host = NULL;
+static char *cacert      = NULL;
+static char *timeout     = NULL;
+
+static CURL *curl = NULL;
+
+static char   nginx_buffer[16384];
+static size_t nginx_buffer_len = 0;
+static char   nginx_curl_error[CURL_ERROR_SIZE];
+
+static const char *config_keys[] =
+{
+  "URL",
+  "User",
+  "Password",
+  "VerifyPeer",
+  "VerifyHost",
+  "CACert",
+  "Timeout"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static size_t nginx_curl_callback (void *buf, size_t size, size_t nmemb,
+    void __attribute__((unused)) *stream)
+{
+  size_t len = size * nmemb;
+
+  /* Check if the data fits into the memory. If not, truncate it. */
+  if ((nginx_buffer_len + len) >= sizeof (nginx_buffer))
+  {
+    assert (sizeof (nginx_buffer) > nginx_buffer_len);
+    len = (sizeof (nginx_buffer) - 1) - nginx_buffer_len;
+  }
+
+  if (len <= 0)
+    return (len);
+
+  memcpy (&nginx_buffer[nginx_buffer_len], buf, len);
+  nginx_buffer_len += len;
+  nginx_buffer[nginx_buffer_len] = 0;
+
+  return (len);
+}
+
+static int config_set (char **var, const char *value)
+{
+  if (*var != NULL)
+  {
+    free (*var);
+    *var = NULL;
+  }
+
+  if ((*var = strdup (value)) == NULL)
+    return (1);
+  else
+    return (0);
+}
+
+static int config (const char *key, const char *value)
+{
+  if (strcasecmp (key, "url") == 0)
+    return (config_set (&url, value));
+  else if (strcasecmp (key, "user") == 0)
+    return (config_set (&user, value));
+  else if (strcasecmp (key, "password") == 0)
+    return (config_set (&pass, value));
+  else if (strcasecmp (key, "verifypeer") == 0)
+    return (config_set (&verify_peer, value));
+  else if (strcasecmp (key, "verifyhost") == 0)
+    return (config_set (&verify_host, value));
+  else if (strcasecmp (key, "cacert") == 0)
+    return (config_set (&cacert, value));
+  else if (strcasecmp (key, "timeout") == 0)
+    return (config_set (&timeout, value));
+  else
+    return (-1);
+} /* int config */
+
+static int init (void)
+{
+  if (curl != NULL)
+    curl_easy_cleanup (curl);
+
+  if ((curl = curl_easy_init ()) == NULL)
+  {
+    ERROR ("nginx plugin: curl_easy_init failed.");
+    return (-1);
+  }
+
+  curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L);
+  curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, nginx_curl_callback);
+  curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+  curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, nginx_curl_error);
+
+  if (user != NULL)
+  {
+#ifdef HAVE_CURLOPT_USERNAME
+    curl_easy_setopt (curl, CURLOPT_USERNAME, user);
+    curl_easy_setopt (curl, CURLOPT_PASSWORD, (pass == NULL) ? "" : pass);
+#else
+    static char credentials[1024];
+    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);
+    }
+
+    curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
+#endif
+  }
+
+  if (url != NULL)
+  {
+    curl_easy_setopt (curl, CURLOPT_URL, url);
+  }
+
+  curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
+  curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 50L);
+
+  if ((verify_peer == NULL) || IS_TRUE (verify_peer))
+  {
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1L);
+  }
+  else
+  {
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0L);
+  }
+
+  if ((verify_host == NULL) || IS_TRUE (verify_host))
+  {
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2L);
+  }
+  else
+  {
+    curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0L);
+  }
+
+  if (cacert != NULL)
+  {
+    curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
+  }
+
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+  if (timeout != NULL)
+  {
+    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, atol(timeout));
+  }
+  else
+  {
+    curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS,
+       CDTIME_T_TO_MS(plugin_get_interval()));
+  }
+#endif
+
+  return (0);
+} /* void init */
+
+static void submit (char *type, char *inst, long long value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  if (strcmp (type, "nginx_connections") == 0)
+    values[0].gauge = value;
+  else if (strcmp (type, "nginx_requests") == 0)
+    values[0].derive = value;
+  else if (strcmp (type, "connections") == 0)
+    values[0].derive = value;
+  else
+    return;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "nginx", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+
+  if (inst != NULL)
+    sstrncpy (vl.type_instance, inst, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void submit */
+
+static int nginx_read (void)
+{
+  int i;
+
+  char *ptr;
+  char *lines[16];
+  int   lines_num = 0;
+  char *saveptr;
+
+  char *fields[16];
+  int   fields_num;
+
+  if (curl == NULL)
+    return (-1);
+  if (url == NULL)
+    return (-1);
+
+  nginx_buffer_len = 0;
+  if (curl_easy_perform (curl) != CURLE_OK)
+  {
+    WARNING ("nginx plugin: curl_easy_perform failed: %s", nginx_curl_error);
+    return (-1);
+  }
+
+  ptr = nginx_buffer;
+  saveptr = NULL;
+  while ((lines[lines_num] = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
+  {
+    ptr = NULL;
+    lines_num++;
+
+    if (lines_num >= 16)
+      break;
+  }
+
+  /*
+   * Active connections: 291
+   * server accepts handled requests
+   *  16630948 16630948 31070465
+   * Reading: 6 Writing: 179 Waiting: 106
+   */
+  for (i = 0; i < lines_num; i++)
+  {
+    fields_num = strsplit (lines[i], fields,
+       (sizeof (fields) / sizeof (fields[0])));
+
+    if (fields_num == 3)
+    {
+      if ((strcmp (fields[0], "Active") == 0)
+         && (strcmp (fields[1], "connections:") == 0))
+      {
+       submit ("nginx_connections", "active", atoll (fields[2]));
+      }
+      else if ((atoll (fields[0]) != 0)
+         && (atoll (fields[1]) != 0)
+         && (atoll (fields[2]) != 0))
+      {
+       submit ("connections", "accepted", atoll (fields[0]));
+       submit ("connections", "handled", atoll (fields[1]));
+       submit ("nginx_requests", NULL, atoll (fields[2]));
+      }
+    }
+    else if (fields_num == 6)
+    {
+      if ((strcmp (fields[0], "Reading:") == 0)
+         && (strcmp (fields[2], "Writing:") == 0)
+         && (strcmp (fields[4], "Waiting:") == 0))
+      {
+       submit ("nginx_connections", "reading", atoll (fields[1]));
+       submit ("nginx_connections", "writing", atoll (fields[3]));
+       submit ("nginx_connections", "waiting", atoll (fields[5]));
+      }
+    }
+  }
+
+  nginx_buffer_len = 0;
+
+  return (0);
+} /* int nginx_read */
+
+void module_register (void)
+{
+  plugin_register_config ("nginx", config, config_keys, config_keys_num);
+  plugin_register_init ("nginx", init);
+  plugin_register_read ("nginx", nginx_read);
+} /* void module_register */
+
+/*
+ * vim: set shiftwidth=2 softtabstop=2 tabstop=8 :
+ */
diff --git a/src/notify_desktop.c b/src/notify_desktop.c
new file mode 100644 (file)
index 0000000..c2d9752
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ * collectd - src/notify_desktop.c
+ * Copyright (C) 2008       Sebastian Harl
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This plugin sends desktop notifications to a notification daemon.
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <glib.h>
+#include <libnotify/notify.h>
+
+#ifndef NOTIFY_CHECK_VERSION
+# define NOTIFY_CHECK_VERSION(x,y,z) 0
+#endif
+
+#define log_info(...) INFO ("notify_desktop: " __VA_ARGS__)
+#define log_warn(...) WARNING ("notify_desktop: " __VA_ARGS__)
+#define log_err(...) ERROR ("notify_desktop: " __VA_ARGS__)
+
+#define DEFAULT_TIMEOUT 5000
+
+static int okay_timeout = DEFAULT_TIMEOUT;
+static int warn_timeout = DEFAULT_TIMEOUT;
+static int fail_timeout = DEFAULT_TIMEOUT;
+
+static int set_timeout (oconfig_item_t *ci, int *timeout)
+{
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_NUMBER != ci->values[0].type)) {
+               log_err ("%s expects a single number argument.", ci->key);
+               return 1;
+       }
+
+       *timeout = (int)ci->values[0].value.number;
+       if (0 > *timeout)
+               *timeout = DEFAULT_TIMEOUT;
+       return 0;
+} /* set_timeout */
+
+static int c_notify_config (oconfig_item_t *ci)
+{
+       int i = 0;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (0 == strcasecmp (c->key, "OkayTimeout"))
+                       set_timeout (c, &okay_timeout);
+               else if (0 == strcasecmp (c->key, "WarningTimeout"))
+                       set_timeout (c, &warn_timeout);
+               else if (0 == strcasecmp (c->key, "FailureTimeout"))
+                       set_timeout (c, &fail_timeout);
+       }
+       return 0;
+} /* c_notify_config */
+
+static int c_notify (const notification_t *n,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       NotifyNotification *notification = NULL;
+       NotifyUrgency       urgency      = NOTIFY_URGENCY_LOW;
+       int                 timeout      = okay_timeout;
+
+       char summary[1024];
+
+       if (NOTIF_WARNING == n->severity) {
+               urgency = NOTIFY_URGENCY_NORMAL;
+               timeout = warn_timeout;
+       }
+       else if (NOTIF_FAILURE == n->severity) {
+               urgency = NOTIFY_URGENCY_CRITICAL;
+               timeout = fail_timeout;
+       }
+
+       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);
+#endif
+       if (NULL == notification) {
+               log_err ("Failed to create a new notification.");
+               return -1;
+       }
+
+       notify_notification_set_urgency (notification, urgency);
+       notify_notification_set_timeout (notification, timeout);
+
+       if (! notify_notification_show (notification, NULL))
+               log_err ("Failed to display notification.");
+
+       g_object_unref (G_OBJECT (notification));
+       return 0;
+} /* c_notify */
+
+static int c_notify_shutdown (void)
+{
+       plugin_unregister_init ("notify_desktop");
+       plugin_unregister_notification ("notify_desktop");
+       plugin_unregister_shutdown ("notify_desktop");
+
+       if (notify_is_initted ())
+               notify_uninit ();
+       return 0;
+} /* c_notify_shutdown */
+
+static int c_notify_init (void)
+{
+       char *name         = NULL;
+       char *vendor       = NULL;
+       char *version      = NULL;
+       char *spec_version = NULL;
+
+       if (! notify_init (PACKAGE_STRING)) {
+               log_err ("Failed to initialize libnotify.");
+               return -1;
+       }
+
+       if (! notify_get_server_info (&name, &vendor, &version, &spec_version))
+               log_warn ("Failed to get the notification server info. "
+                               "Check if you have a notification daemon running.");
+       else {
+               log_info ("Found notification daemon: %s (%s) %s (spec version %s)",
+                               name, vendor, version, spec_version);
+               free (name);
+               free (vendor);
+               free (version);
+               free (spec_version);
+       }
+
+       plugin_register_notification ("notify_desktop", c_notify,
+                       /* user_data = */ NULL);
+       plugin_register_shutdown ("notify_desktop", c_notify_shutdown);
+       return 0;
+} /* c_notify_init */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("notify_desktop", c_notify_config);
+       plugin_register_init ("notify_desktop", c_notify_init);
+       return;
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/notify_email.c b/src/notify_email.c
new file mode 100644 (file)
index 0000000..24c66ec
--- /dev/null
@@ -0,0 +1,326 @@
+/**
+ * collectd - src/notify_email.c
+ * Copyright (C) 2008  Oleg King
+ * Copyright (C) 2010  Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Oleg King <king2 at kaluga.ru>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <auth-client.h>
+#include <libesmtp.h>
+#include <pthread.h>
+
+#define MAXSTRING               256
+
+static const char *config_keys[] =
+{
+  "SMTPServer",
+  "SMTPPort",
+  "SMTPUser",
+  "SMTPPassword",
+  "From",
+  "Recipient",
+  "Subject"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char **recipients;
+static int recipients_len = 0;
+
+static smtp_session_t session;
+static pthread_mutex_t session_lock = PTHREAD_MUTEX_INITIALIZER;
+static smtp_message_t message;
+static auth_context_t authctx = NULL;
+
+static int smtp_port = 25;
+static char *smtp_host = NULL;
+static char *smtp_user = NULL;
+static char *smtp_password = NULL;
+static char *email_from = NULL;
+static char *email_subject = NULL;
+
+#define DEFAULT_SMTP_HOST      "localhost"
+#define DEFAULT_SMTP_FROM      "root@localhost"
+#define DEFAULT_SMTP_SUBJECT   "Collectd notify: %s@%s"
+
+/* Callback to get username and password */
+static int authinteract (auth_client_request_t request, char **result,
+    int fields, void __attribute__((unused)) *arg)
+{               
+  int i;
+  for (i = 0; i < fields; i++)
+  {
+    if (request[i].flags & AUTH_USER)
+      result[i] = smtp_user;
+    else if (request[i].flags & AUTH_PASS)
+      result[i] = smtp_password;
+    else
+      return 0;
+  }
+  return 1;
+} /* int authinteract */
+
+/* Callback to print the recipient status */
+static void print_recipient_status (smtp_recipient_t recipient,
+    const char *mailbox, void __attribute__((unused)) *arg)
+{
+  const smtp_status_t *status;
+
+  status = smtp_recipient_status (recipient);
+  if (status->text[strlen(status->text) - 2] == '\r')
+    status->text[strlen(status->text) - 2] = 0;
+  INFO ("notify_email: notify sent to %s: %d %s", mailbox, status->code,
+      status->text);
+} /* void print_recipient_status */
+
+/* Callback to monitor SMTP activity */
+static void monitor_cb (const char *buf, int buflen, int writing,
+    void __attribute__((unused)) *arg)
+{
+  char log_str[MAXSTRING];
+
+  sstrncpy (log_str, buf, sizeof (log_str));
+  if (buflen > 2)
+    log_str[buflen - 2] = 0; /* replace \n with \0 */
+
+  if (writing == SMTP_CB_HEADERS) {
+    DEBUG ("notify_email plugin: SMTP --- H: %s", log_str);
+    return;
+  }
+  DEBUG (writing
+      ? "notify_email plugin: SMTP >>> C: %s"
+      : "notify_email plugin: SMTP <<< S: %s",
+      log_str);
+} /* void monitor_cb */
+
+static int notify_email_init (void)
+{
+  char server[MAXSTRING];
+
+  ssnprintf(server, sizeof (server), "%s:%i",
+      (smtp_host == NULL) ? DEFAULT_SMTP_HOST : smtp_host,
+      smtp_port);
+
+  pthread_mutex_lock (&session_lock);
+
+  auth_client_init();
+
+  session = smtp_create_session ();
+  if (session == NULL) {
+    pthread_mutex_unlock (&session_lock);
+    ERROR ("notify_email plugin: cannot create SMTP session");
+    return (-1);
+  }
+
+  smtp_set_monitorcb (session, monitor_cb, NULL, 1);
+  smtp_set_hostname (session, hostname_g);
+  smtp_set_server (session, server);
+
+  if (smtp_user && smtp_password) {
+    authctx = auth_create_context ();
+    auth_set_mechanism_flags (authctx, AUTH_PLUGIN_PLAIN, 0);
+    auth_set_interact_cb (authctx, authinteract, NULL);
+  }
+
+  if ( !smtp_auth_set_context (session, authctx)) {
+    pthread_mutex_unlock (&session_lock);
+    ERROR ("notify_email plugin: cannot set SMTP auth context");
+    return (-1);   
+  }
+
+  pthread_mutex_unlock (&session_lock);
+  return (0);
+} /* int notify_email_init */
+
+static int notify_email_shutdown (void)
+{
+  pthread_mutex_lock (&session_lock);
+
+  if (session != NULL)
+    smtp_destroy_session (session);
+  session = NULL;
+
+  if (authctx != NULL)
+    auth_destroy_context (authctx);
+  authctx = NULL;
+
+  auth_client_exit();
+
+  pthread_mutex_unlock (&session_lock);
+  return (0);
+} /* int notify_email_shutdown */
+
+static int notify_email_config (const char *key, const char *value)
+{
+  if (strcasecmp (key, "Recipient") == 0)
+  {
+    char **tmp;
+
+    tmp = (char **) realloc ((void *) recipients, (recipients_len + 1) * sizeof (char *));
+    if (tmp == NULL) {
+      ERROR ("notify_email: realloc failed.");
+      return (-1);
+    }
+
+    recipients = tmp;
+    recipients[recipients_len] = strdup (value);
+    if (recipients[recipients_len] == NULL) {
+      ERROR ("notify_email: strdup failed.");
+      return (-1);
+    }
+    recipients_len++;
+  }
+  else if (0 == strcasecmp (key, "SMTPServer")) {
+    sfree (smtp_host);
+    smtp_host = strdup (value);
+  }
+  else if (0 == strcasecmp (key, "SMTPPort")) {
+    int port_tmp = atoi (value);
+    if (port_tmp < 1 || port_tmp > 65535)
+    {
+      WARNING ("notify_email plugin: Invalid SMTP port: %i", port_tmp);
+      return (1);
+    }
+    smtp_port = port_tmp;
+  }
+  else if (0 == strcasecmp (key, "SMTPUser")) {
+    sfree (smtp_user);
+    smtp_user = strdup (value);
+  }
+  else if (0 == strcasecmp (key, "SMTPPassword")) {
+    sfree (smtp_password);
+    smtp_password = strdup (value);
+  }
+  else if (0 == strcasecmp (key, "From")) {
+    sfree (email_from);
+    email_from = strdup (value);
+  }
+  else if (0 == strcasecmp (key, "Subject")) {
+    sfree (email_subject);
+    email_subject = strdup (value);
+  }
+  else {
+    return -1;
+  }
+  return 0;
+} /* int notify_email_config (const char *, const char *) */
+
+static int notify_email_notification (const notification_t *n,
+    user_data_t __attribute__((unused)) *user_data)
+{
+
+  time_t tt;
+  struct tm timestamp_tm;
+  char timestamp_str[64];
+
+  char severity[32];
+  char subject[MAXSTRING];
+
+  char buf[4096] = "";
+  int  buf_len = sizeof (buf);
+  int i;
+
+  ssnprintf (severity, sizeof (severity), "%s",
+      (n->severity == NOTIF_FAILURE) ? "FAILURE"
+      : ((n->severity == NOTIF_WARNING) ? "WARNING"
+        : ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
+
+  ssnprintf (subject, sizeof (subject),
+      (email_subject == NULL) ? DEFAULT_SMTP_SUBJECT : email_subject,
+      severity, n->host);
+
+  tt = CDTIME_T_TO_TIME_T (n->time);
+  localtime_r (&tt, &timestamp_tm);
+  strftime (timestamp_str, sizeof (timestamp_str), "%Y-%m-%d %H:%M:%S",
+      &timestamp_tm);
+  timestamp_str[sizeof (timestamp_str) - 1] = '\0';
+
+  /* Let's make RFC822 message text with \r\n EOLs */
+  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"
+      "Message: %s",
+      subject,
+      timestamp_str,
+      severity,
+      n->host,
+      n->message);
+
+  pthread_mutex_lock (&session_lock);
+
+  if (session == NULL) {
+    /* Initialization failed or we're in the process of shutting down. */
+    pthread_mutex_unlock (&session_lock);
+    return (-1);
+  }
+
+  if (!(message = smtp_add_message (session))) {
+    pthread_mutex_unlock (&session_lock);
+    ERROR ("notify_email plugin: cannot set SMTP message");
+    return (-1);   
+  }
+  smtp_set_reverse_path (message, email_from);
+  smtp_set_header (message, "To", NULL, NULL);
+  smtp_set_message_str (message, buf);
+
+  for (i = 0; i < recipients_len; i++)
+    smtp_add_recipient (message, recipients[i]);
+
+  /* Initiate a connection to the SMTP server and transfer the message. */
+  if (!smtp_start_session (session)) {
+    char buf[MAXSTRING];
+    ERROR ("notify_email plugin: SMTP server problem: %s",
+        smtp_strerror (smtp_errno (), buf, sizeof buf));
+    pthread_mutex_unlock (&session_lock);
+    return (-1);
+  } else {
+    #if COLLECT_DEBUG
+    const smtp_status_t *status;
+    /* Report on the success or otherwise of the mail transfer. */
+    status = smtp_message_transfer_status (message);
+    DEBUG ("notify_email plugin: SMTP server report: %d %s",
+      status->code, (status->text != NULL) ? status->text : "\n");
+    #endif
+    smtp_enumerate_recipients (message, print_recipient_status, NULL);
+  }
+
+  pthread_mutex_unlock (&session_lock);
+  return (0);
+} /* int notify_email_notification */
+
+void module_register (void)
+{
+  plugin_register_init ("notify_email", notify_email_init);
+  plugin_register_shutdown ("notify_email", notify_email_shutdown);
+  plugin_register_config ("notify_email", notify_email_config,
+      config_keys, config_keys_num);
+  plugin_register_notification ("notify_email", notify_email_notification,
+      /* user_data = */ NULL);
+} /* void module_register (void) */
+
+/* vim: set sw=2 sts=2 ts=8 et : */
diff --git a/src/ntpd.c b/src/ntpd.c
new file mode 100644 (file)
index 0000000..15b12f9
--- /dev/null
@@ -0,0 +1,1029 @@
+/**
+ * collectd - src/ntpd.c
+ * Copyright (C) 2006-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE /* For NI_MAXHOST */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h> /* inet_ntoa */
+#endif
+#if HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+#if HAVE_POLL_H
+# include <poll.h>
+#endif
+
+static const char *config_keys[] =
+{
+       "Host",
+       "Port",
+       "ReverseLookups",
+       "IncludeUnitID"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static _Bool do_reverse_lookups = 1;
+
+/* This option only exists for backward compatibility. If it is false and two
+ * ntpd peers use the same refclock driver, the plugin will try to write
+ * simultaneous measurements from both to the same type instance. */
+static _Bool include_unit_id = 0;
+
+# define NTPD_DEFAULT_HOST "localhost"
+# define NTPD_DEFAULT_PORT "123"
+static int   sock_descr = -1;
+static char *ntpd_host = NULL;
+static char  ntpd_port[16];
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * The following definitions were copied from the NTPd distribution  *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#define MAXFILENAME 128
+#define MAXSEQ  127
+#define MODE_PRIVATE 7
+#define NTP_OLDVERSION ((uint8_t) 1) /* oldest credible version */
+#define IMPL_XNTPD 3
+#define FP_FRAC 65536.0
+
+#define REFCLOCK_ADDR 0x7f7f0000 /* 127.127.0.0 */
+#define REFCLOCK_MASK 0xffff0000 /* 255.255.0.0 */
+
+/* This structure is missing the message authentication code, since collectd
+ * doesn't use it. */
+struct req_pkt
+{
+       uint8_t  rm_vn_mode;
+       uint8_t  auth_seq;
+       uint8_t  implementation;                /* implementation number */
+       uint8_t  request;                       /* request number */
+       uint16_t err_nitems;            /* error code/number of data items */
+       uint16_t mbz_itemsize;          /* item size */
+       char     data[MAXFILENAME + 48];        /* data area [32 prev](176 byte max) */
+                                       /* struct conf_peer must fit */
+};
+#define REQ_LEN_NOMAC (sizeof(struct req_pkt))
+
+/*
+ * A response packet.  The length here is variable, this is a
+ * maximally sized one.  Note that this implementation doesn't
+ * authenticate responses.
+ */
+#define        RESP_HEADER_SIZE        (8)
+#define        RESP_DATA_SIZE          (500)
+
+struct resp_pkt
+{
+       uint8_t  rm_vn_mode;           /* response, more, version, mode */
+       uint8_t  auth_seq;             /* key, sequence number */
+       uint8_t  implementation;       /* implementation number */
+       uint8_t  request;              /* request number */
+       uint16_t err_nitems;           /* error code/number of data items */
+       uint16_t mbz_itemsize;         /* item size */
+       char     data[RESP_DATA_SIZE]; /* data area */
+};
+
+/*
+ * Bit setting macros for multifield items.
+ */
+#define        RESP_BIT        0x80
+#define        MORE_BIT        0x40
+
+#define        ISRESPONSE(rm_vn_mode)  (((rm_vn_mode)&RESP_BIT)!=0)
+#define        ISMORE(rm_vn_mode)      (((rm_vn_mode)&MORE_BIT)!=0)
+#define INFO_VERSION(rm_vn_mode) ((uint8_t)(((rm_vn_mode)>>3)&0x7))
+#define        INFO_MODE(rm_vn_mode)   ((rm_vn_mode)&0x7)
+
+#define        RM_VN_MODE(resp, more, version)         \
+                               ((uint8_t)(((resp)?RESP_BIT:0)\
+                               |((more)?MORE_BIT:0)\
+                               |((version?version:(NTP_OLDVERSION+1))<<3)\
+                               |(MODE_PRIVATE)))
+
+#define        INFO_IS_AUTH(auth_seq)  (((auth_seq) & 0x80) != 0)
+#define        INFO_SEQ(auth_seq)      ((auth_seq)&0x7f)
+#define        AUTH_SEQ(auth, seq)     ((uint8_t)((((auth)!=0)?0x80:0)|((seq)&0x7f)))
+
+#define        INFO_ERR(err_nitems)    ((uint16_t)((ntohs(err_nitems)>>12)&0xf))
+#define        INFO_NITEMS(err_nitems) ((uint16_t)(ntohs(err_nitems)&0xfff))
+#define        ERR_NITEMS(err, nitems) (htons((uint16_t)((((uint16_t)(err)<<12)&0xf000)\
+                               |((uint16_t)(nitems)&0xfff))))
+
+#define        INFO_MBZ(mbz_itemsize)  ((ntohs(mbz_itemsize)>>12)&0xf)
+#define        INFO_ITEMSIZE(mbz_itemsize)     ((uint16_t)(ntohs(mbz_itemsize)&0xfff))
+#define        MBZ_ITEMSIZE(itemsize)  (htons((uint16_t)(itemsize)))
+
+/* negate a long float type */
+#define M_NEG(v_i, v_f) \
+       do { \
+               if ((v_f) == 0) \
+               (v_i) = -((uint32_t)(v_i)); \
+               else { \
+                       (v_f) = -((uint32_t)(v_f)); \
+                       (v_i) = ~(v_i); \
+               } \
+       } while(0)
+/* l_fp to double */
+#define M_LFPTOD(r_i, r_uf, d) \
+       do { \
+               register int32_t  i; \
+               register uint32_t f; \
+               \
+               i = (r_i); \
+               f = (r_uf); \
+               if (i < 0) { \
+                       M_NEG(i, f); \
+                       (d) = -((double) i + ((double) f) / 4294967296.0); \
+               } else { \
+                       (d) = (double) i + ((double) f) / 4294967296.0; \
+               } \
+       } while (0)
+
+#define REQ_PEER_LIST_SUM 1
+struct info_peer_summary
+{
+       uint32_t dstadr;         /* local address (zero for undetermined) */
+       uint32_t srcadr;         /* source address */
+       uint16_t srcport;        /* source port */
+       uint8_t stratum;         /* stratum of peer */
+       int8_t hpoll;            /* host polling interval */
+       int8_t ppoll;            /* peer polling interval */
+       uint8_t reach;           /* reachability register */
+       uint8_t flags;           /* flags, from above */
+       uint8_t hmode;           /* peer mode */
+       int32_t  delay;          /* peer.estdelay; s_fp */
+       int32_t  offset_int;     /* peer.estoffset; integral part */
+       int32_t  offset_frc;     /* peer.estoffset; fractional part */
+       uint32_t dispersion;     /* peer.estdisp; u_fp */
+       uint32_t v6_flag;        /* is this v6 or not */
+       uint32_t unused1;        /* (unused) padding for dstadr6 */
+       struct in6_addr dstadr6; /* local address (v6) */
+       struct in6_addr srcadr6; /* source address (v6) */
+};
+
+#define REQ_SYS_INFO 4
+struct info_sys
+{
+       uint32_t peer;           /* system peer address (v4) */
+       uint8_t  peer_mode;      /* mode we are syncing to peer in */
+       uint8_t  leap;           /* system leap bits */
+       uint8_t  stratum;        /* our stratum */
+       int8_t   precision;      /* local clock precision */
+       int32_t  rootdelay;      /* distance from sync source */
+       uint32_t rootdispersion; /* dispersion from sync source */
+       uint32_t refid;          /* reference ID of sync source */
+       uint64_t reftime;        /* system reference time */
+       uint32_t poll;           /* system poll interval */
+       uint8_t  flags;          /* system flags */
+       uint8_t  unused1;        /* unused */
+       uint8_t  unused2;        /* unused */
+       uint8_t  unused3;        /* unused */
+       int32_t  bdelay;         /* default broadcast offset */
+       int32_t  frequency;      /* frequency residual (scaled ppm)  */
+       uint64_t authdelay;      /* default authentication delay */
+       uint32_t stability;      /* clock stability (scaled ppm) */
+       int32_t  v6_flag;        /* is this v6 or not */
+       int32_t  unused4;        /* unused, padding for peer6 */
+       struct in6_addr peer6;   /* system peer address (v6) */
+};
+
+#define REQ_GET_KERNEL 38
+struct info_kernel
+{
+       int32_t  offset;
+       int32_t  freq;
+       int32_t  maxerror;
+       int32_t  esterror;
+       uint16_t status;
+       uint16_t shift;
+       int32_t  constant;
+       int32_t  precision;
+       int32_t  tolerance;
+       /* pps stuff */
+       int32_t  ppsfreq;
+       int32_t  jitter;
+       int32_t  stabil;
+       int32_t  jitcnt;
+       int32_t  calcnt;
+       int32_t  errcnt;
+       int32_t  stbcnt;
+};
+
+/* List of reference clock names */
+static char *refclock_names[] =
+{
+       "UNKNOWN",    "LOCAL",        "GPS_TRAK",   "WWV_PST",     /*  0- 3 */
+       "SPECTRACOM", "TRUETIME",     "IRIG_AUDIO", "CHU_AUDIO",   /*  4- 7 */
+       "GENERIC",    "GPS_MX4200",   "GPS_AS2201", "GPS_ARBITER", /*  8-11 */
+       "IRIG_TPRO",  "ATOM_LEITCH",  "MSF_EES",    "GPSTM_TRUE",  /* 12-15 */
+       "GPS_BANC",   "GPS_DATUM",    "ACTS_NIST",  "WWV_HEATH",   /* 16-19 */
+       "GPS_NMEA",   "GPS_VME",      "PPS",        "ACTS_PTB",    /* 20-23 */
+       "ACTS_USNO",  "TRUETIME",     "GPS_HP",     "MSF_ARCRON",  /* 24-27 */
+       "SHM",        "GPS_PALISADE", "GPS_ONCORE", "GPS_JUPITER", /* 28-31 */
+       "CHRONOLOG",  "DUMBCLOCK",    "ULINK_M320", "PCF",         /* 32-35 */
+       "WWV_AUDIO",  "GPS_FG",       "HOPF_S",     "HOPF_P",      /* 36-39 */
+       "JJY",        "TT_IRIG",      "GPS_ZYFER",  "GPS_RIPENCC", /* 40-43 */
+       "NEOCLK4X"                                                 /* 44    */
+};
+static int refclock_names_num = STATIC_ARRAY_SIZE (refclock_names);
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * End of the copied stuff..                                         *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+static int ntpd_config (const char *key, const char *value)
+{
+       if (strcasecmp (key, "Host") == 0)
+       {
+               if (ntpd_host != NULL)
+                       free (ntpd_host);
+               if ((ntpd_host = strdup (value)) == NULL)
+                       return (1);
+       }
+       else if (strcasecmp (key, "Port") == 0)
+       {
+               int port = (int) (atof (value));
+               if ((port > 0) && (port <= 65535))
+                       ssnprintf (ntpd_port, sizeof (ntpd_port),
+                                       "%i", port);
+               else
+                       sstrncpy (ntpd_port, value, sizeof (ntpd_port));
+       }
+       else if (strcasecmp (key, "ReverseLookups") == 0)
+       {
+               if (IS_TRUE (value))
+                       do_reverse_lookups = 1;
+               else
+                       do_reverse_lookups = 0;
+       }
+       else if (strcasecmp (key, "IncludeUnitID") == 0)
+       {
+               if (IS_TRUE (value))
+                       include_unit_id = 1;
+               else
+                       include_unit_id = 0;
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+}
+
+static void ntpd_submit (char *type, char *type_inst, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "ntpd", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+/* Each time a peer is polled, ntpd shifts the reach register to the left and
+ * sets the LSB based on whether the peer was reachable. If the LSB is zero,
+ * the values are out of date. */
+static void ntpd_submit_reach (char *type, char *type_inst, uint8_t reach,
+               double value)
+{
+       if (!(reach & 1))
+               value = NAN;
+
+       ntpd_submit (type, type_inst, value);
+}
+
+static int ntpd_connect (void)
+{
+       char *host;
+       char *port;
+
+       struct addrinfo  ai_hints;
+       struct addrinfo *ai_list;
+       struct addrinfo *ai_ptr;
+       int              status;
+
+       if (sock_descr >= 0)
+               return (sock_descr);
+
+       DEBUG ("Opening a new socket");
+
+       host = ntpd_host;
+       if (host == NULL)
+               host = NTPD_DEFAULT_HOST;
+
+       port = ntpd_port;
+       if (strlen (port) == 0)
+               port = NTPD_DEFAULT_PORT;
+
+       memset (&ai_hints, '\0', sizeof (ai_hints));
+       ai_hints.ai_flags    = 0;
+#ifdef AI_ADDRCONFIG
+       ai_hints.ai_flags   |= AI_ADDRCONFIG;
+#endif
+       ai_hints.ai_family   = PF_UNSPEC;
+       ai_hints.ai_socktype = SOCK_DGRAM;
+       ai_hints.ai_protocol = IPPROTO_UDP;
+
+       if ((status = getaddrinfo (host, port, &ai_hints, &ai_list)) != 0)
+       {
+               char errbuf[1024];
+               ERROR ("ntpd plugin: getaddrinfo (%s, %s): %s",
+                               host, port,
+                               (status == EAI_SYSTEM)
+                               ? sstrerror (errno, errbuf, sizeof (errbuf))
+                               : gai_strerror (status));
+               return (-1);
+       }
+
+       for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               /* create our socket descriptor */
+               if ((sock_descr = socket (ai_ptr->ai_family,
+                                               ai_ptr->ai_socktype,
+                                               ai_ptr->ai_protocol)) < 0)
+                       continue;
+
+               /* connect to the ntpd */
+               if (connect (sock_descr, ai_ptr->ai_addr, ai_ptr->ai_addrlen))
+               {
+                       close (sock_descr);
+                       sock_descr = -1;
+                       continue;
+               }
+
+               break;
+       }
+
+       freeaddrinfo (ai_list);
+
+       if (sock_descr < 0)
+       {
+               ERROR ("ntpd plugin: Unable to connect to server.");
+       }
+
+       return (sock_descr);
+}
+
+/* For a description of the arguments see `ntpd_do_query' below. */
+static int ntpd_receive_response (int *res_items, int *res_size,
+               char **res_data, int res_item_size)
+{
+       int              sd;
+       struct pollfd    poll_s;
+       struct resp_pkt  res;
+       int              status;
+       int              done;
+       int              i;
+
+       char            *items;
+       size_t           items_num;
+
+       struct timeval   time_end;
+       struct timeval   time_now;
+       int              timeout;
+
+       int              pkt_item_num;        /* items in this packet */
+       int              pkt_item_len;        /* size of the items in this packet */
+       int              pkt_sequence;
+       char             pkt_recvd[MAXSEQ+1]; /* sequence numbers that have been received */
+       int              pkt_recvd_num;       /* number of packets that have been received */
+       int              pkt_lastseq;         /* the last sequence number */
+       ssize_t          pkt_padding;         /* Padding in this packet */
+
+       if ((sd = ntpd_connect ()) < 0)
+               return (-1);
+
+       items = NULL;
+       items_num = 0;
+
+       memset (pkt_recvd, '\0', sizeof (pkt_recvd));
+       pkt_recvd_num = 0;
+       pkt_lastseq   = -1;
+
+       *res_items = 0;
+       *res_size  = 0;
+       *res_data  = NULL;
+
+       if (gettimeofday (&time_end, NULL) < 0)
+       {
+               char errbuf[1024];
+               ERROR ("ntpd plugin: gettimeofday failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+       time_end.tv_sec++; /* wait for a most one second */
+
+       done = 0;
+       while (done == 0)
+       {
+               struct timeval time_left;
+
+               if (gettimeofday (&time_now, NULL) < 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("ntpd plugin: gettimeofday failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+
+               if (timeval_cmp (time_end, time_now, &time_left) <= 0)
+                       timeout = 0;
+               else
+                       timeout = 1000 * time_left.tv_sec
+                               + ((time_left.tv_usec + 500) / 1000);
+
+               /* timeout reached */
+               if (timeout <= 0)
+                       break;
+
+               poll_s.fd      = sd;
+               poll_s.events  = POLLIN | POLLPRI;
+               poll_s.revents = 0;
+
+               DEBUG ("Polling for %ims", timeout);
+               status = poll (&poll_s, 1, timeout);
+
+               if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+                       continue;
+
+               if (status < 0)
+               {
+                       char errbuf[1024];
+                       ERROR ("ntpd plugin: poll failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+
+               if (status == 0) /* timeout */
+               {
+                       DEBUG ("timeout reached.");
+                       break;
+               }
+
+               memset ((void *) &res, '\0', sizeof (res));
+               status = recv (sd, (void *) &res, sizeof (res), 0 /* no flags */);
+
+               if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+                       continue;
+
+               if (status < 0)
+               {
+                       char errbuf[1024];
+                       INFO ("recv(2) failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       DEBUG ("Closing socket #%i", sd);
+                       close (sd);
+                       sock_descr = sd = -1;
+                       return (-1);
+               }
+
+               DEBUG ("recv'd %i bytes", status);
+
+               /*
+                * Do some sanity checks first
+                */
+               if (status < RESP_HEADER_SIZE)
+               {
+                       WARNING ("ntpd plugin: Short (%i bytes) packet received",
+                                       (int) status);
+                       continue;
+               }
+               if (INFO_MODE (res.rm_vn_mode) != MODE_PRIVATE)
+               {
+                       NOTICE ("ntpd plugin: Packet received with mode %i",
+                                       INFO_MODE (res.rm_vn_mode));
+                       continue;
+               }
+               if (INFO_IS_AUTH (res.auth_seq))
+               {
+                       NOTICE ("ntpd plugin: Encrypted packet received");
+                       continue;
+               }
+               if (!ISRESPONSE (res.rm_vn_mode))
+               {
+                       NOTICE ("ntpd plugin: Received request packet, "
+                                       "wanted response");
+                       continue;
+               }
+               if (INFO_MBZ (res.mbz_itemsize))
+               {
+                       WARNING ("ntpd plugin: Received packet with nonzero "
+                                       "MBZ field!");
+                       continue;
+               }
+               if (res.implementation != IMPL_XNTPD)
+               {
+                       WARNING ("ntpd plugin: Asked for request of type %i, "
+                                       "got %i", (int) IMPL_XNTPD, (int) res.implementation);
+                       continue;
+               }
+
+               /* Check for error code */
+               if (INFO_ERR (res.err_nitems) != 0)
+               {
+                       ERROR ("ntpd plugin: Received error code %i",
+                                       (int) INFO_ERR(res.err_nitems));
+                       return ((int) INFO_ERR (res.err_nitems));
+               }
+
+               /* extract number of items in this packet and the size of these items */
+               pkt_item_num = INFO_NITEMS (res.err_nitems);
+               pkt_item_len = INFO_ITEMSIZE (res.mbz_itemsize);
+               DEBUG ("pkt_item_num = %i; pkt_item_len = %i;",
+                               pkt_item_num, pkt_item_len);
+
+               /* Check if the reported items fit in the packet */
+               if ((pkt_item_num * pkt_item_len) > (status - RESP_HEADER_SIZE))
+               {
+                       ERROR ("ntpd plugin: %i items * %i bytes > "
+                                       "%i bytes - %i bytes header",
+                                       (int) pkt_item_num, (int) pkt_item_len,
+                                       (int) status, (int) RESP_HEADER_SIZE);
+                       continue;
+               }
+
+               if (pkt_item_len > res_item_size)
+               {
+                       ERROR ("ntpd plugin: (pkt_item_len = %i) "
+                                       ">= (res_item_size = %i)",
+                                       pkt_item_len, res_item_size);
+                       continue;
+               }
+
+               /* If this is the first packet (time wise, not sequence wise),
+                * set `res_size'. If it's not the first packet check if the
+                * items have the same size. Discard invalid packets. */
+               if (items_num == 0) /* first packet */
+               {
+                       DEBUG ("*res_size = %i", pkt_item_len);
+                       *res_size = pkt_item_len;
+               }
+               else if (*res_size != pkt_item_len)
+               {
+                       DEBUG ("Error: *res_size = %i; pkt_item_len = %i;",
+                                       *res_size, pkt_item_len);
+                       ERROR ("Item sizes differ.");
+                       continue;
+               }
+
+               /*
+                * Because the items in the packet may be smaller than the
+                * items requested, the following holds true:
+                */
+               assert ((*res_size == pkt_item_len)
+                               && (pkt_item_len <= res_item_size));
+
+               /* Calculate the padding. No idea why there might be any padding.. */
+               pkt_padding = 0;
+               if (pkt_item_len < res_item_size)
+                       pkt_padding = res_item_size - pkt_item_len;
+               DEBUG ("res_item_size = %i; pkt_padding = %zi;",
+                               res_item_size, pkt_padding);
+
+               /* Extract the sequence number */
+               pkt_sequence = INFO_SEQ (res.auth_seq);
+               if ((pkt_sequence < 0) || (pkt_sequence > MAXSEQ))
+               {
+                       ERROR ("ntpd plugin: Received packet with sequence %i",
+                                       pkt_sequence);
+                       continue;
+               }
+
+               /* Check if this sequence has been received before. If so, discard it. */
+               if (pkt_recvd[pkt_sequence] != '\0')
+               {
+                       NOTICE ("ntpd plugin: Sequence %i received twice",
+                                       pkt_sequence);
+                       continue;
+               }
+
+               /* If `pkt_lastseq != -1' another packet without `more bit' has
+                * been received. */
+               if (!ISMORE (res.rm_vn_mode))
+               {
+                       if (pkt_lastseq != -1)
+                       {
+                               ERROR ("ntpd plugin: Two packets which both "
+                                               "claim to be the last one in the "
+                                               "sequence have been received.");
+                               continue;
+                       }
+                       pkt_lastseq = pkt_sequence;
+                       DEBUG ("Last sequence = %i;", pkt_lastseq);
+               }
+
+               /*
+                * Enough with the checks. Copy the data now.
+                * We start by allocating some more memory.
+                */
+               DEBUG ("realloc (%p, %zu)", (void *) *res_data,
+                               (items_num + pkt_item_num) * res_item_size);
+               items = realloc ((void *) *res_data,
+                               (items_num + pkt_item_num) * res_item_size);
+               if (items == NULL)
+               {
+                       items = *res_data;
+                       ERROR ("ntpd plugin: realloc failed.");
+                       continue;
+               }
+               items_num += pkt_item_num;
+               *res_data = items;
+
+               for (i = 0; i < pkt_item_num; i++)
+               {
+                       /* dst: There are already `*res_items' items with
+                        *      res_item_size bytes each in in `*res_data'. Set
+                        *      dst to the first byte after that. */
+                       void *dst = (void *) (*res_data + ((*res_items) * res_item_size));
+                       /* src: We use `pkt_item_len' to calculate the offset
+                        *      from the beginning of the packet, because the
+                        *      items in the packet may be smaller than the
+                        *      items that were requested. We skip `i' such
+                        *      items. */
+                       void *src = (void *) (((char *) res.data) + (i * pkt_item_len));
+
+                       /* Set the padding to zeros */
+                       if (pkt_padding != 0)
+                               memset (dst, '\0', res_item_size);
+                       memcpy (dst, src, (size_t) pkt_item_len);
+
+                       /* Increment `*res_items' by one, so `dst' will end up
+                        * one further in the next round. */
+                       (*res_items)++;
+               } /* for (pkt_item_num) */
+
+               pkt_recvd[pkt_sequence] = (char) 1;
+               pkt_recvd_num++;
+
+               if ((pkt_recvd_num - 1) == pkt_lastseq)
+                       done = 1;
+       } /* while (done == 0) */
+
+       return (0);
+} /* int ntpd_receive_response */
+
+/* For a description of the arguments see `ntpd_do_query' below. */
+static int ntpd_send_request (int req_code, int req_items, int req_size, char *req_data)
+{
+       int             sd;
+       struct req_pkt  req;
+       size_t          req_data_len;
+       int             status;
+
+       assert (req_items >= 0);
+       assert (req_size  >= 0);
+
+       if ((sd = ntpd_connect ()) < 0)
+               return (-1);
+
+       memset ((void *) &req, '\0', sizeof (req));
+       req.rm_vn_mode = RM_VN_MODE(0, 0, 0);
+       req.auth_seq   = AUTH_SEQ (0, 0);
+       req.implementation = IMPL_XNTPD;
+       req.request = (unsigned char) req_code;
+
+       req_data_len = (size_t) (req_items * req_size);
+
+       assert (((req_data != NULL) && (req_data_len > 0))
+                       || ((req_data == NULL) && (req_items == 0) && (req_size == 0)));
+
+       req.err_nitems   = ERR_NITEMS (0, req_items);
+       req.mbz_itemsize = MBZ_ITEMSIZE (req_size);
+
+       if (req_data != NULL)
+               memcpy ((void *) req.data, (const void *) req_data, req_data_len);
+
+       DEBUG ("req_items = %i; req_size = %i; req_data = %p;",
+                       req_items, req_size, (void *) req_data);
+
+       status = swrite (sd, (const char *) &req, REQ_LEN_NOMAC);
+       if (status < 0)
+       {
+               DEBUG ("`swrite' failed. Closing socket #%i", sd);
+               close (sd);
+               sock_descr = sd = -1;
+               return (status);
+       }
+
+       return (0);
+}
+
+/*
+ * ntpd_do_query:
+ *
+ * req_code:      Type of request packet
+ * req_items:     Numver of items in the request
+ * req_size:      Size of one item in the request
+ * req_data:      Data of the request packet
+ * res_items:     Pointer to where the number returned items will be stored.
+ * res_size:      Pointer to where the size of one returned item will be stored.
+ * res_data:      This is where a pointer to the (allocated) data will be stored.
+ * res_item_size: Size of one returned item. (used to calculate padding)
+ *
+ * returns:       zero upon success, non-zero otherwise.
+ */
+static int ntpd_do_query (int req_code, int req_items, int req_size, char *req_data,
+               int *res_items, int *res_size, char **res_data, int res_item_size)
+{
+       int status;
+
+       status = ntpd_send_request (req_code, req_items, req_size, req_data);
+       if (status != 0)
+               return (status);
+
+       status = ntpd_receive_response (res_items, res_size, res_data,
+                       res_item_size);
+       return (status);
+}
+
+static double ntpd_read_fp (int32_t val_int)
+{
+       double val_double;
+
+       val_int = ntohl (val_int);
+       val_double = ((double) val_int) / FP_FRAC;
+
+       return (val_double);
+}
+
+static uint32_t ntpd_get_refclock_id (struct info_peer_summary const *peer_info)
+{
+       uint32_t addr = ntohl (peer_info->srcadr);
+       uint32_t refclock_id = (addr >> 8) & 0x00FF;
+
+       return (refclock_id);
+}
+
+static int ntpd_get_name_from_address (char *buffer, size_t buffer_size,
+               struct info_peer_summary const *peer_info, _Bool do_reverse_lookup)
+{
+       struct sockaddr_storage sa;
+       socklen_t sa_len;
+       int flags = 0;
+       int status;
+
+       memset (&sa, 0, sizeof (sa));
+
+       if (peer_info->v6_flag)
+       {
+               struct sockaddr_in6 sa6;
+
+               assert (sizeof (sa) >= sizeof (sa6));
+
+               memset (&sa6, 0, sizeof (sa6));
+               sa6.sin6_family = AF_INET6;
+               sa6.sin6_port = htons (123);
+               memcpy (&sa6.sin6_addr, &peer_info->srcadr6,
+                               sizeof (struct in6_addr));
+               sa_len = sizeof (sa6);
+
+               memcpy (&sa, &sa6, sizeof (sa6));
+       }
+       else
+       {
+               struct sockaddr_in sa4;
+
+               assert (sizeof (sa) >= sizeof (sa4));
+
+               memset (&sa4, 0, sizeof (sa4));
+               sa4.sin_family = AF_INET;
+               sa4.sin_port = htons (123);
+               memcpy (&sa4.sin_addr, &peer_info->srcadr,
+                               sizeof (struct in_addr));
+               sa_len = sizeof (sa4);
+
+               memcpy (&sa, &sa4, sizeof (sa4));
+       }
+
+       if (!do_reverse_lookup)
+               flags |= NI_NUMERICHOST;
+
+       status = getnameinfo ((struct sockaddr const *) &sa, sa_len,
+                       buffer, buffer_size,
+                       NULL, 0, /* No port name */
+                       flags);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("ntpd plugin: getnameinfo failed: %s",
+                               (status == EAI_SYSTEM)
+                               ? sstrerror (errno, errbuf, sizeof (errbuf))
+                               : gai_strerror (status));
+               return (-1);
+       }
+
+       return (0);
+} /* ntpd_get_name_from_address */
+
+static int ntpd_get_name_refclock (char *buffer, size_t buffer_size,
+               struct info_peer_summary const *peer_info)
+{
+       uint32_t refclock_id = ntpd_get_refclock_id (peer_info);
+       uint32_t unit_id = ntohl (peer_info->srcadr) & 0x00FF;
+
+       if (refclock_id >= refclock_names_num)
+               return (ntpd_get_name_from_address (buffer, buffer_size,
+                                       peer_info,
+                                       /* do_reverse_lookup = */ 0));
+
+       if (include_unit_id)
+               ssnprintf (buffer, buffer_size, "%s-%"PRIu32,
+                               refclock_names[refclock_id], unit_id);
+       else
+               sstrncpy (buffer, refclock_names[refclock_id], buffer_size);
+
+       return (0);
+} /* int ntpd_get_name_refclock */
+
+static int ntpd_get_name (char *buffer, size_t buffer_size,
+               struct info_peer_summary const *peer_info)
+{
+       uint32_t addr = ntohl (peer_info->srcadr);
+
+       if (!peer_info->v6_flag && ((addr & REFCLOCK_MASK) == REFCLOCK_ADDR))
+               return (ntpd_get_name_refclock (buffer, buffer_size,
+                                       peer_info));
+       else
+               return (ntpd_get_name_from_address (buffer, buffer_size,
+                                       peer_info, do_reverse_lookups));
+} /* int ntpd_addr_to_name */
+
+static int ntpd_read (void)
+{
+       struct info_kernel *ik;
+       int                 ik_num;
+       int                 ik_size;
+
+       struct info_peer_summary *ps;
+       int                       ps_num;
+       int                       ps_size;
+
+       int status;
+       int i;
+
+       ik      = NULL;
+       ik_num  = 0;
+       ik_size = 0;
+
+       status = ntpd_do_query (REQ_GET_KERNEL,
+                       0, 0, NULL, /* request data */
+                       &ik_num, &ik_size, (char **) ((void *) &ik), /* response data */
+                       sizeof (struct info_kernel));
+       if (status != 0)
+       {
+               ERROR ("ntpd plugin: ntpd_do_query (REQ_GET_KERNEL) failed with status %i", status);
+               return (status);
+       }
+       else if ((ik == NULL) || (ik_num == 0) || (ik_size == 0))
+       {
+               ERROR ("ntpd plugin: ntpd_do_query returned unexpected data. "
+                               "(ik = %p; ik_num = %i; ik_size = %i)",
+                               (void *) ik, ik_num, ik_size);
+               return (-1);
+       }
+
+       /* kerninfo -> estimated error */
+
+       DEBUG ("info_kernel:\n"
+                       "  pll offset    = %.8f\n"
+                       "  pll frequency = %.8f\n" /* drift compensation */
+                       "  est error     = %.8f\n",
+                       ntpd_read_fp (ik->offset),
+                       ntpd_read_fp (ik->freq),
+                       ntpd_read_fp (ik->esterror));
+
+       ntpd_submit ("frequency_offset", "loop",  ntpd_read_fp (ik->freq));
+       ntpd_submit ("time_offset",      "loop",  ntpd_read_fp (ik->offset));
+       ntpd_submit ("time_offset",      "error", ntpd_read_fp (ik->esterror));
+
+       free (ik);
+       ik = NULL;
+
+       status = ntpd_do_query (REQ_PEER_LIST_SUM,
+                       0, 0, NULL, /* request data */
+                       &ps_num, &ps_size, (char **) ((void *) &ps), /* response data */
+                       sizeof (struct info_peer_summary));
+       if (status != 0)
+       {
+               ERROR ("ntpd plugin: ntpd_do_query (REQ_PEER_LIST_SUM) failed with status %i", status);
+               return (status);
+       }
+       else if ((ps == NULL) || (ps_num == 0) || (ps_size == 0))
+       {
+               ERROR ("ntpd plugin: ntpd_do_query returned unexpected data. "
+                               "(ps = %p; ps_num = %i; ps_size = %i)",
+                               (void *) ps, ps_num, ps_size);
+               return (-1);
+       }
+
+       for (i = 0; i < ps_num; i++)
+       {
+               struct info_peer_summary *ptr;
+               double offset;
+
+               char peername[NI_MAXHOST];
+               uint32_t refclock_id;
+
+               ptr = ps + i;
+
+               status = ntpd_get_name (peername, sizeof (peername), ptr);
+               if (status != 0)
+               {
+                       ERROR ("ntpd plugin: Determining name of peer failed.");
+                       continue;
+               }
+
+               refclock_id = ntpd_get_refclock_id (ptr);
+
+               /* Convert the `long floating point' offset value to double */
+               M_LFPTOD (ntohl (ptr->offset_int), ntohl (ptr->offset_frc), offset);
+
+               DEBUG ("peer %i:\n"
+                               "  peername   = %s\n"
+                               "  srcadr     = 0x%08x\n"
+                               "  reach      = 0%03o\n"
+                               "  delay      = %f\n"
+                               "  offset_int = %i\n"
+                               "  offset_frc = %i\n"
+                               "  offset     = %f\n"
+                               "  dispersion = %f\n",
+                               i,
+                               peername,
+                               ntohl (ptr->srcadr),
+                               ptr->reach,
+                               ntpd_read_fp (ptr->delay),
+                               ntohl (ptr->offset_int),
+                               ntohl (ptr->offset_frc),
+                               offset,
+                               ntpd_read_fp (ptr->dispersion));
+
+               if (refclock_id != 1) /* not the system clock (offset will always be zero.. */
+                       ntpd_submit_reach ("time_offset", peername, ptr->reach,
+                                       offset);
+               ntpd_submit_reach ("time_dispersion", peername, ptr->reach,
+                               ntpd_read_fp (ptr->dispersion));
+               if (refclock_id == 0) /* not a reference clock */
+                       ntpd_submit_reach ("delay", peername, ptr->reach,
+                                       ntpd_read_fp (ptr->delay));
+       }
+
+       free (ps);
+       ps = NULL;
+
+       return (0);
+} /* int ntpd_read */
+
+void module_register (void)
+{
+       plugin_register_config ("ntpd", ntpd_config,
+                       config_keys, config_keys_num);
+       plugin_register_read ("ntpd", ntpd_read);
+} /* void module_register */
diff --git a/src/numa.c b/src/numa.c
new file mode 100644 (file)
index 0000000..a87a17e
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * collectd - src/numa.c
+ * Copyright (C) 2012       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+#ifndef NUMA_ROOT_DIR
+# define NUMA_ROOT_DIR "/sys/devices/system/node"
+#endif
+
+static int max_node = -1;
+
+static void numa_dispatch_value (int node, /* {{{ */
+    const char *type_instance, value_t v)
+{
+  value_list_t vl = VALUE_LIST_INIT;
+
+  vl.values = &v;
+  vl.values_len = 1;
+
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "numa", sizeof (vl.plugin));
+  ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance), "node%i", node);
+  sstrncpy (vl.type, "vmpage_action", sizeof (vl.type));
+  sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* }}} void numa_dispatch_value */
+
+static int numa_read_node (int node) /* {{{ */
+{
+  char path[PATH_MAX];
+  FILE *fh;
+  char buffer[128];
+  int status;
+  int success;
+
+  ssnprintf (path, sizeof (path), NUMA_ROOT_DIR "/node%i/numastat", node);
+
+  fh = fopen (path, "r");
+  if (fh == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("numa plugin: Reading node %i failed: open(%s): %s",
+        node, path, sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  success = 0;
+  while (fgets (buffer, sizeof (buffer), fh) != NULL)
+  {
+    char *fields[4];
+    value_t v;
+
+    status = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+    if (status != 2)
+    {
+      WARNING ("numa plugin: Ignoring line with unexpected "
+          "number of fields (node %i).", node);
+      continue;
+    }
+
+    v.derive = 0;
+    status = parse_value (fields[1], &v, DS_TYPE_DERIVE);
+    if (status != 0)
+      continue;
+
+    numa_dispatch_value (node, fields[0], v);
+    success++;
+  }
+
+  fclose (fh);
+  return (success ? 0 : -1);
+} /* }}} int numa_read_node */
+
+static int numa_read (void) /* {{{ */
+{
+  int i;
+  int status;
+  int success;
+
+  if (max_node < 0)
+  {
+    WARNING ("numa plugin: No NUMA nodes were detected.");
+    return (-1);
+  }
+
+  success = 0;
+  for (i = 0; i <= max_node; i++)
+  {
+    status = numa_read_node (i);
+    if (status == 0)
+      success++;
+  }
+
+  return (success ? 0 : -1);
+} /* }}} int numa_read */
+
+static int numa_init (void) /* {{{ */
+{
+  /* Determine the number of nodes on this machine. */
+  while (42)
+  {
+    char path[PATH_MAX];
+    struct stat statbuf;
+    int status;
+
+    ssnprintf (path, sizeof (path), NUMA_ROOT_DIR "/node%i", max_node + 1);
+    memset (&statbuf, 0, sizeof (statbuf));
+
+    status = stat (path, &statbuf);
+    if (status == 0)
+    {
+      max_node++;
+      continue;
+    }
+    else if (errno == ENOENT)
+    {
+      break;
+    }
+    else /* ((status != 0) && (errno != ENOENT)) */
+    {
+      char errbuf[1024];
+      ERROR ("numa plugin: stat(%s) failed: %s", path,
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (-1);
+    }
+  }
+
+  DEBUG ("numa plugin: Found %i nodes.", max_node + 1);
+  return (0);
+} /* }}} int numa_init */
+
+void module_register (void)
+{
+  plugin_register_init ("numa", numa_init);
+  plugin_register_read ("numa", numa_read);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/nut.c b/src/nut.c
new file mode 100644 (file)
index 0000000..d5ecc98
--- /dev/null
+++ b/src/nut.c
@@ -0,0 +1,297 @@
+/**
+ * collectd - src/nut.c
+ * Copyright (C) 2007       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <pthread.h>
+#include <upsclient.h>
+
+#if HAVE_UPSCONN_T
+typedef UPSCONN_t collectd_upsconn_t;
+#elif HAVE_UPSCONN
+typedef UPSCONN collectd_upsconn_t;
+#else
+# error "Unable to determine the UPS connection type."
+#endif
+
+struct nut_ups_s;
+typedef struct nut_ups_s nut_ups_t;
+struct nut_ups_s
+{
+  collectd_upsconn_t *conn;
+  char      *upsname;
+  char      *hostname;
+  int        port;
+  nut_ups_t *next;
+};
+
+static nut_ups_t *upslist_head = NULL;
+
+static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER;
+static int read_busy = 0;
+
+static const char *config_keys[] =
+{
+  "UPS"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+
+static void free_nut_ups_t (nut_ups_t *ups)
+{
+  if (ups->conn != NULL)
+  {
+    upscli_disconnect (ups->conn);
+    sfree (ups->conn);
+  }
+  sfree (ups->hostname);
+  sfree (ups->upsname);
+  sfree (ups);
+} /* void free_nut_ups_t */
+
+static int nut_add_ups (const char *name)
+{
+  nut_ups_t *ups;
+  int status;
+
+  DEBUG ("nut plugin: nut_add_ups (name = %s);", name);
+
+  ups = (nut_ups_t *) malloc (sizeof (nut_ups_t));
+  if (ups == NULL)
+  {
+    ERROR ("nut plugin: nut_add_ups: malloc failed.");
+    return (1);
+  }
+  memset (ups, '\0', sizeof (nut_ups_t));
+
+  status = upscli_splitname (name, &ups->upsname, &ups->hostname,
+      &ups->port);
+  if (status != 0)
+  {
+    ERROR ("nut plugin: nut_add_ups: upscli_splitname (%s) failed.", name);
+    free_nut_ups_t (ups);
+    return (1);
+  }
+
+  if (upslist_head == NULL)
+    upslist_head = ups;
+  else
+  {
+    nut_ups_t *last = upslist_head;
+    while (last->next != NULL)
+      last = last->next;
+    last->next = ups;
+  }
+
+  return (0);
+} /* int nut_add_ups */
+
+static int nut_config (const char *key, const char *value)
+{
+  if (strcasecmp (key, "UPS") == 0)
+    return (nut_add_ups (value));
+  else
+    return (-1);
+} /* int nut_config */
+
+static void nut_submit (nut_ups_t *ups, const char *type,
+    const char *type_instance, gauge_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = STATIC_ARRAY_SIZE (values);
+  sstrncpy (vl.host,
+      (strcasecmp (ups->hostname, "localhost") == 0)
+      ? hostname_g
+      : ups->hostname,
+      sizeof (vl.host));
+  sstrncpy (vl.plugin, "nut", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, ups->upsname, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void nut_submit */
+
+static int nut_read_one (nut_ups_t *ups)
+{
+  const char *query[3] = {"VAR", ups->upsname, NULL};
+  unsigned int query_num = 2;
+  char **answer;
+  unsigned int answer_num;
+  int status;
+
+  /* (Re-)Connect if we have no connection */
+  if (ups->conn == NULL)
+  {
+    ups->conn = (collectd_upsconn_t *) malloc (sizeof (collectd_upsconn_t));
+    if (ups->conn == NULL)
+    {
+      ERROR ("nut plugin: malloc failed.");
+      return (-1);
+    }
+
+    status = upscli_connect (ups->conn, ups->hostname, ups->port,
+       UPSCLI_CONN_TRYSSL);
+    if (status != 0)
+    {
+      ERROR ("nut plugin: nut_read_one: upscli_connect (%s, %i) failed: %s",
+         ups->hostname, ups->port, upscli_strerror (ups->conn));
+      sfree (ups->conn);
+      return (-1);
+    }
+
+    INFO ("nut plugin: Connection to (%s, %i) established.",
+       ups->hostname, ups->port);
+  } /* if (ups->conn == NULL) */
+
+  /* nut plugin: nut_read_one: upscli_list_start (adpos) failed: Protocol
+   * error */
+  status = upscli_list_start (ups->conn, query_num, query);
+  if (status != 0)
+  {
+    ERROR ("nut plugin: nut_read_one: upscli_list_start (%s) failed: %s",
+       ups->upsname, upscli_strerror (ups->conn));
+    upscli_disconnect (ups->conn);
+    sfree (ups->conn);
+    return (-1);
+  }
+
+  while ((status = upscli_list_next (ups->conn, query_num, query,
+         &answer_num, &answer)) == 1)
+  {
+    char  *key;
+    double value;
+
+    if (answer_num < 4)
+      continue;
+
+    key = answer[2];
+    value = atof (answer[3]);
+
+    if (strncmp ("ambient.", key, 8) == 0)
+    {
+      if (strcmp ("ambient.humidity", key) == 0)
+       nut_submit (ups, "humidity", "ambient", value);
+      else if (strcmp ("ambient.temperature", key) == 0)
+       nut_submit (ups, "temperature", "ambient", value);
+    }
+    else if (strncmp ("battery.", key, 8) == 0)
+    {
+      if (strcmp ("battery.charge", key) == 0)
+       nut_submit (ups, "percent", "charge", value);
+      else if (strcmp ("battery.current", key) == 0)
+       nut_submit (ups, "current", "battery", value);
+      else if (strcmp ("battery.runtime", key) == 0)
+       nut_submit (ups, "timeleft", "battery", value);
+      else if (strcmp ("battery.temperature", key) == 0)
+       nut_submit (ups, "temperature", "battery", value);
+      else if (strcmp ("battery.voltage", key) == 0)
+       nut_submit (ups, "voltage", "battery", value);
+    }
+    else if (strncmp ("input.", key, 6) == 0)
+    {
+      if (strcmp ("input.frequency", key) == 0)
+       nut_submit (ups, "frequency", "input", value);
+      else if (strcmp ("input.voltage", key) == 0)
+       nut_submit (ups, "voltage", "input", value);
+    }
+    else if (strncmp ("output.", key, 7) == 0)
+    {
+      if (strcmp ("output.current", key) == 0)
+       nut_submit (ups, "current", "output", value);
+      else if (strcmp ("output.frequency", key) == 0)
+       nut_submit (ups, "frequency", "output", value);
+      else if (strcmp ("output.voltage", key) == 0)
+       nut_submit (ups, "voltage", "output", value);
+    }
+    else if (strncmp ("ups.", key, 4) == 0)
+    {
+      if (strcmp ("ups.load", key) == 0)
+       nut_submit (ups, "percent", "load", value);
+      else if (strcmp ("ups.power", key) == 0)
+       nut_submit (ups, "power", "ups", value);
+      else if (strcmp ("ups.temperature", key) == 0)
+       nut_submit (ups, "temperature", "ups", value);
+    }
+  } /* while (upscli_list_next) */
+
+  return (0);
+} /* int nut_read_one */
+
+static int nut_read (void)
+{
+  nut_ups_t *ups;
+  int success = 0;
+
+  pthread_mutex_lock (&read_lock);
+  success = read_busy;
+  read_busy = 1;
+  pthread_mutex_unlock (&read_lock);
+
+  if (success != 0)
+    return (0);
+
+  for (ups = upslist_head; ups != NULL; ups = ups->next)
+    if (nut_read_one (ups) == 0)
+      success++;
+
+  pthread_mutex_lock (&read_lock);
+  read_busy = 0;
+  pthread_mutex_unlock (&read_lock);
+
+  return ((success != 0) ? 0 : -1);
+} /* int nut_read */
+
+static int nut_shutdown (void)
+{
+  nut_ups_t *this;
+  nut_ups_t *next;
+
+  this = upslist_head;
+  while (this != NULL)
+  {
+    next = this->next;
+    free_nut_ups_t (this);
+    this = next;
+  }
+
+  return (0);
+} /* int nut_shutdown */
+
+void module_register (void)
+{
+  plugin_register_config ("nut", nut_config, config_keys, config_keys_num);
+  plugin_register_read ("nut", nut_read);
+  plugin_register_shutdown ("nut", nut_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 ts=8 sts=2 tw=78 : */
diff --git a/src/olsrd.c b/src/olsrd.c
new file mode 100644 (file)
index 0000000..6d0576c
--- /dev/null
@@ -0,0 +1,714 @@
+/**
+ * collectd - src/olsrd.c
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <sys/types.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#define OLSRD_DEFAULT_NODE "localhost"
+#define OLSRD_DEFAULT_SERVICE "2006"
+
+static const char *config_keys[] =
+{
+  "Host",
+  "Port",
+  "CollectLinks",
+  "CollectRoutes",
+  "CollectTopology"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char *config_node = NULL;
+static char *config_service = NULL;
+
+#define OLSRD_WANT_NOT     0
+#define OLSRD_WANT_SUMMARY 1
+#define OLSRD_WANT_DETAIL  2
+static int config_want_links    = OLSRD_WANT_DETAIL;
+static int config_want_routes   = OLSRD_WANT_SUMMARY;
+static int config_want_topology = OLSRD_WANT_SUMMARY;
+
+static const char *olsrd_get_node (void) /* {{{ */
+{
+  if (config_node != NULL)
+    return (config_node);
+  return (OLSRD_DEFAULT_NODE);
+} /* }}} const char *olsrd_get_node */
+
+static const char *olsrd_get_service (void) /* {{{ */
+{
+  if (config_service != NULL)
+    return (config_service);
+  return (OLSRD_DEFAULT_SERVICE);
+} /* }}} const char *olsrd_get_service */
+
+static void olsrd_set_node (const char *node) /* {{{ */
+{
+  char *tmp;
+  if (node == NULL)
+    return;
+  tmp = strdup (node);
+  if (tmp == NULL)
+    return;
+  config_node = tmp;
+} /* }}} void olsrd_set_node */
+
+static void olsrd_set_service (const char *service) /* {{{ */
+{
+  char *tmp;
+  if (service == NULL)
+    return;
+  tmp = strdup (service);
+  if (tmp == NULL)
+    return;
+  config_service = tmp;
+} /* }}} void olsrd_set_service */
+
+static void olsrd_set_detail (int *varptr, const char *detail, /* {{{ */
+    const char *key)
+{
+  if (strcasecmp ("No", detail) == 0)
+    *varptr = OLSRD_WANT_NOT;
+  else if (strcasecmp ("Summary", detail) == 0)
+    *varptr = OLSRD_WANT_SUMMARY;
+  else if (strcasecmp ("Detail", detail) == 0)
+    *varptr = OLSRD_WANT_DETAIL;
+  else
+  {
+    ERROR ("olsrd plugin: Invalid argument given to the `%s' configuration "
+        "option: `%s'. Expected: `No', `Summary', or `Detail'.",
+        key, detail);
+  }
+} /* }}} void olsrd_set_detail */
+
+/* Strip trailing newline characters. Returns length of string. */
+static size_t strchomp (char *buffer) /* {{{ */
+{
+  size_t buffer_len;
+
+  buffer_len = strlen (buffer);
+  while ((buffer_len > 0)
+      && ((buffer[buffer_len - 1] == '\r')
+        || (buffer[buffer_len - 1] == '\n')))
+  {
+    buffer_len--;
+    buffer[buffer_len] = 0;
+  }
+
+  return (buffer_len);
+} /* }}} size_t strchomp */
+
+static size_t strtabsplit (char *string, char **fields, size_t size) /* {{{ */
+{
+  size_t i;
+  char *ptr;
+  char *saveptr;
+
+  i = 0;
+  ptr = string;
+  saveptr = NULL;
+  while ((fields[i] = strtok_r (ptr, " \t\r\n", &saveptr)) != NULL)
+  {
+    ptr = NULL;
+    i++;
+
+    if (i >= size)
+      break;
+  }
+
+  return (i);
+} /* }}} size_t strtabsplit */
+
+static FILE *olsrd_connect (void) /* {{{ */
+{
+  struct addrinfo  ai_hints;
+  struct addrinfo *ai_list, *ai_ptr;
+  int              ai_return;
+
+  FILE *fh;
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags    = 0;
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags   |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family   = PF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_STREAM;
+  ai_hints.ai_protocol = IPPROTO_TCP;
+
+  ai_list = NULL;
+  ai_return = getaddrinfo (olsrd_get_node (), olsrd_get_service (),
+      &ai_hints, &ai_list);
+  if (ai_return != 0)
+  {
+    ERROR ("olsrd plugin: getaddrinfo (%s, %s) failed: %s",
+        olsrd_get_node (), olsrd_get_service (),
+        gai_strerror (ai_return));
+    return (NULL);
+  }
+
+  fh = NULL;
+  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    int fd;
+    int status;
+    char errbuf[1024];
+
+    fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+    if (fd < 0)
+    {
+      ERROR ("olsrd plugin: socket failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      continue;
+    }
+
+    status = connect (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    if (status != 0)
+    {
+      ERROR ("olsrd plugin: connect failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      close (fd);
+      continue;
+    }
+
+    fh = fdopen (fd, "r+");
+    if (fh == NULL)
+    {
+      ERROR ("olsrd plugin: fdopen failed.");
+      close (fd);
+      continue;
+    }
+
+    break;
+  } /* for (ai_ptr) */
+
+  freeaddrinfo (ai_list);
+
+  return (fh);
+} /* }}} FILE *olsrd_connect */
+
+__attribute__ ((nonnull(2)))
+static void olsrd_submit (const char *plugin_instance, /* {{{ */
+    const char *type, const char *type_instance, gauge_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "olsrd", sizeof (vl.plugin));
+  if (plugin_instance != NULL)
+    sstrncpy (vl.plugin_instance, plugin_instance,
+        sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance,
+        sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* }}} void olsrd_submit */
+
+static int olsrd_cb_ignore (int lineno, /* {{{ */
+    size_t fields_num, char **fields)
+{
+  return (0);
+} /* }}} int olsrd_cb_ignore */
+
+static int olsrd_cb_links (int lineno, /* {{{ */
+    size_t fields_num, char **fields)
+{
+  /* Fields:
+   *  0 = Local IP
+   *  1 = Remote IP
+   *  2 = Hyst.
+   *  3 = LQ
+   *  4 = NLQ
+   *  5 = Cost */
+
+  static uint32_t links_num;
+  static double    lq_sum;
+  static uint32_t  lq_num;
+  static double   nlq_sum;
+  static uint32_t nlq_num;
+
+  double lq;
+  double nlq;
+
+  char *endptr;
+
+  if (config_want_links == OLSRD_WANT_NOT)
+    return (0);
+
+  /* Special handling of the first line. */
+  if (lineno <= 0)
+  {
+    links_num = 0;
+    lq_sum = 0.0;
+    lq_num = 0;
+    nlq_sum = 0.0;
+    nlq_num = 0;
+
+    return (0);
+  }
+
+  /* Special handling of the last line. */
+  if (fields_num == 0)
+  {
+    DEBUG ("olsrd plugin: Number of links: %"PRIu32, links_num);
+    olsrd_submit (/* p.-inst = */ "links", /* type = */ "links",
+        /* t.-inst = */ NULL, (gauge_t) links_num);
+
+    lq = NAN;
+    if (lq_num > 0)
+      lq = lq_sum / ((double) lq_num);
+    DEBUG ("olsrd plugin: Average  LQ: %g", lq);
+    olsrd_submit (/* p.-inst = */ "links", /* type = */ "signal_quality",
+        "average-lq", lq);
+
+    nlq = NAN;
+    if (nlq_num > 0)
+      nlq = nlq_sum / ((double) nlq_num);
+    DEBUG ("olsrd plugin: Average NLQ: %g", nlq);
+    olsrd_submit (/* p.-inst = */ "links", /* type = */ "signal_quality",
+        "average-nlq", nlq);
+
+    return (0);
+  }
+
+  if (fields_num != 6)
+    return (-1);
+
+  links_num++;
+
+  errno = 0;
+  endptr = NULL;
+  lq = strtod (fields[3], &endptr);
+  if ((errno != 0) || (endptr == fields[3]))
+  {
+    ERROR ("olsrd plugin: Cannot parse link quality: %s", fields[3]);
+  }
+  else
+  {
+    if (!isnan (lq))
+    {
+      lq_sum += lq;
+      lq_num++;
+    }
+
+    if (config_want_links == OLSRD_WANT_DETAIL)
+    {
+      char type_instance[DATA_MAX_NAME_LEN];
+
+      ssnprintf (type_instance, sizeof (type_instance), "%s-%s-lq",
+          fields[0], fields[1]);
+
+      DEBUG ("olsrd plugin: links: type_instance = %s;  lq = %g;",
+          type_instance, lq);
+      olsrd_submit (/* p.-inst = */ "links", /* type = */ "signal_quality",
+          type_instance, lq);
+    }
+  }
+
+  errno = 0;
+  endptr = NULL;
+  nlq = strtod (fields[4], &endptr);
+  if ((errno != 0) || (endptr == fields[4]))
+  {
+    ERROR ("olsrd plugin: Cannot parse neighbor link quality: %s", fields[4]);
+  }
+  else
+  {
+    if (!isnan (nlq))
+    {
+      nlq_sum += nlq;
+      nlq_num++;
+    }
+
+    if (config_want_links == OLSRD_WANT_DETAIL)
+    {
+      char type_instance[DATA_MAX_NAME_LEN];
+
+      ssnprintf (type_instance, sizeof (type_instance), "%s-%s-rx",
+          fields[0], fields[1]);
+
+      DEBUG ("olsrd plugin: links: type_instance = %s; nlq = %g;",
+          type_instance, lq);
+      olsrd_submit (/* p.-inst = */ "links", /* type = */ "signal_quality",
+          type_instance, nlq);
+    }
+  }
+
+  return (0);
+} /* }}} int olsrd_cb_links */
+
+static int olsrd_cb_routes (int lineno, /* {{{ */
+    size_t fields_num, char **fields)
+{
+  /* Fields:
+   *  0 = Destination
+   *  1 = Gateway IP
+   *  2 = Metric
+   *  3 = ETX
+   *  4 = Interface */
+
+  static uint32_t routes_num;
+  static uint32_t metric_sum;
+  static uint32_t metric_num;
+  static double   etx_sum;
+  static uint32_t etx_num;
+
+  uint32_t metric;
+  double etx;
+  char *endptr;
+
+  if (config_want_routes == OLSRD_WANT_NOT)
+    return (0);
+
+  /* Special handling of the first line */
+  if (lineno <= 0)
+  {
+    routes_num = 0;
+    metric_num = 0;
+    metric_sum = 0;
+    etx_sum = 0.0;
+    etx_num = 0;
+
+    return (0);
+  }
+
+  /* Special handling after the last line */
+  if (fields_num == 0)
+  {
+    double metric_avg;
+
+    DEBUG ("olsrd plugin: Number of routes: %"PRIu32, routes_num);
+    olsrd_submit (/* p.-inst = */ "routes", /* type = */ "routes",
+        /* t.-inst = */ NULL, (gauge_t) routes_num);
+
+    metric_avg = NAN;
+    if (metric_num > 0)
+      metric_avg = ((double) metric_sum) / ((double) metric_num);
+    DEBUG ("olsrd plugin: Average metric: %g", metric_avg);
+    olsrd_submit (/* p.-inst = */ "routes", /* type = */ "route_metric",
+        "average", metric_avg);
+
+    etx = NAN;
+    if (etx_num > 0)
+      etx = etx_sum / ((double) etx_sum);
+    DEBUG ("olsrd plugin: Average ETX: %g", etx);
+    olsrd_submit (/* p.-inst = */ "routes", /* type = */ "route_etx",
+        "average", etx);
+
+    return (0);
+  }
+
+  if (fields_num != 5)
+    return (-1);
+
+  routes_num++;
+
+  errno = 0;
+  endptr = NULL;
+  metric = (uint32_t) strtoul (fields[2], &endptr, 0);
+  if ((errno != 0) || (endptr == fields[2]))
+  {
+    ERROR ("olsrd plugin: Unable to parse metric: %s", fields[2]);
+  }
+  else
+  {
+    metric_num++;
+    metric_sum += metric;
+
+    if (config_want_routes == OLSRD_WANT_DETAIL)
+    {
+      DEBUG ("olsrd plugin: destination = %s; metric = %"PRIu32";",
+          fields[0], metric);
+      olsrd_submit (/* p.-inst = */ "routes", /* type = */ "route_metric",
+          /* t.-inst = */ fields[0], (gauge_t) metric);
+    }
+  }
+
+  errno = 0;
+  endptr = NULL;
+  etx = strtod (fields[3], &endptr);
+  if ((errno != 0) || (endptr == fields[3]))
+  {
+    ERROR ("olsrd plugin: Unable to parse ETX: %s", fields[3]);
+  }
+  else
+  {
+    if (!isnan (etx))
+    {
+      etx_sum += etx;
+      etx_num++;
+    }
+
+    if (config_want_routes == OLSRD_WANT_DETAIL)
+    {
+      DEBUG ("olsrd plugin: destination = %s; etx = %g;",
+          fields[0], etx);
+      olsrd_submit (/* p.-inst = */ "routes", /* type = */ "route_etx",
+          /* t.-inst = */ fields[0], etx);
+    }
+  }
+
+  return (0);
+} /* }}} int olsrd_cb_routes */
+
+static int olsrd_cb_topology (int lineno, /* {{{ */
+    size_t fields_num, char **fields)
+{
+  /* Fields:
+   *  0 = Dest. IP
+   *  1 = Last hop IP
+   *  2 = LQ
+   *  3 = NLQ
+   *  4 = Cost */
+
+  static double   lq_sum;
+  static uint32_t lq_num;
+
+  static uint32_t links_num;
+
+  double lq;
+  char *endptr;
+
+  if (config_want_topology == OLSRD_WANT_NOT)
+    return (0);
+
+  /* Special handling of the first line */
+  if (lineno <= 0)
+  {
+    lq_sum = 0.0;
+    lq_num = 0;
+    links_num = 0;
+
+    return (0);
+  }
+
+  /* Special handling after the last line */
+  if (fields_num == 0)
+  {
+    DEBUG ("olsrd plugin: topology: Number of links: %"PRIu32, links_num);
+    olsrd_submit (/* p.-inst = */ "topology", /* type = */ "links",
+        /* t.-inst = */ NULL, (gauge_t) links_num);
+
+    lq = NAN;
+    if (lq_num > 0)
+      lq = lq_sum / ((double) lq_sum);
+    DEBUG ("olsrd plugin: topology: Average link quality: %g", lq);
+    olsrd_submit (/* p.-inst = */ "topology", /* type = */ "signal_quality",
+        /* t.-inst = */ "average", lq);
+
+    return (0);
+  }
+
+  if (fields_num != 5)
+    return (-1);
+
+  links_num++;
+
+  errno = 0;
+  endptr = NULL;
+  lq = strtod (fields[2], &endptr);
+  if ((errno != 0) || (endptr == fields[2]))
+  {
+    ERROR ("olsrd plugin: Unable to parse LQ: %s", fields[2]);
+  }
+  else
+  {
+    if (!isnan (lq))
+    {
+      lq_sum += lq;
+      lq_num++;
+    }
+
+    if (config_want_topology == OLSRD_WANT_DETAIL)
+    {
+      char type_instance[DATA_MAX_NAME_LEN];
+
+      memset (type_instance, 0, sizeof (type_instance));
+      ssnprintf (type_instance, sizeof (type_instance), "%s-%s-lq",
+          fields[0], fields[1]);
+      DEBUG ("olsrd plugin: type_instance = %s; lq = %g;", type_instance, lq);
+      olsrd_submit (/* p.-inst = */ "topology", /* type = */ "signal_quality",
+          type_instance, lq);
+    }
+  }
+
+  if (config_want_topology == OLSRD_WANT_DETAIL)
+  {
+    double nlq;
+
+    errno = 0;
+    endptr = NULL;
+    nlq = strtod (fields[3], &endptr);
+    if ((errno != 0) || (endptr == fields[3]))
+    {
+      ERROR ("olsrd plugin: Unable to parse NLQ: %s", fields[3]);
+    }
+    else
+    {
+      char type_instance[DATA_MAX_NAME_LEN];
+
+      memset (type_instance, 0, sizeof (type_instance));
+      ssnprintf (type_instance, sizeof (type_instance), "%s-%s-nlq",
+          fields[0], fields[1]);
+      DEBUG ("olsrd plugin: type_instance = %s; nlq = %g;", type_instance, nlq);
+      olsrd_submit (/* p.-inst = */ "topology", /* type = */ "signal_quality",
+          type_instance, nlq);
+    }
+  }
+
+  return (0);
+} /* }}} int olsrd_cb_topology */
+
+static int olsrd_read_table (FILE *fh, /* {{{ */
+    int (*callback) (int lineno, size_t fields_num, char **fields))
+{
+  char buffer[1024];
+  size_t buffer_len;
+
+  char *fields[32];
+  size_t fields_num;
+
+  int lineno;
+
+  lineno = 0;
+  while (fgets (buffer, sizeof (buffer), fh) != NULL)
+  {
+    /* An empty line ends the table. */
+    buffer_len = strchomp (buffer);
+    if (buffer_len <= 0)
+    {
+      (*callback) (lineno, /* fields_num = */ 0, /* fields = */ NULL);
+      break;
+    }
+
+    fields_num = strtabsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+
+    (*callback) (lineno, fields_num, fields);
+    lineno++;
+  } /* while (fgets) */
+  
+  return (0);
+} /* }}} int olsrd_read_table */
+
+static int olsrd_config (const char *key, const char *value) /* {{{ */
+{
+  if (strcasecmp ("Host", key) == 0)
+    olsrd_set_node (value);
+  else if (strcasecmp ("Port", key) == 0)
+    olsrd_set_service (value);
+  else if (strcasecmp ("CollectLinks", key) == 0)
+    olsrd_set_detail (&config_want_links, value, key);
+  else if (strcasecmp ("CollectRoutes", key) == 0)
+    olsrd_set_detail (&config_want_routes, value, key);
+  else if (strcasecmp ("CollectTopology", key) == 0)
+    olsrd_set_detail (&config_want_topology, value, key);
+  else
+  {
+    ERROR ("olsrd plugin: Unknown configuration option given: %s", key);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int olsrd_config */
+
+static int olsrd_read (void) /* {{{ */
+{
+  FILE *fh;
+  char buffer[1024];
+  size_t buffer_len;
+
+  fh = olsrd_connect ();
+  if (fh == NULL)
+    return (-1);
+
+  fputs ("\r\n", fh);
+  fflush (fh);
+
+  while (fgets (buffer, sizeof (buffer), fh) != NULL)
+  {
+    buffer_len = strchomp (buffer);
+    if (buffer_len <= 0)
+      continue;
+    
+    if (strcmp ("Table: Links", buffer) == 0)
+      olsrd_read_table (fh, olsrd_cb_links);
+    else if (strcmp ("Table: Neighbors", buffer) == 0)
+      olsrd_read_table (fh, olsrd_cb_ignore);
+    else if (strcmp ("Table: Topology", buffer) == 0)
+      olsrd_read_table (fh, olsrd_cb_topology);
+    else if (strcmp ("Table: HNA", buffer) == 0)
+      olsrd_read_table (fh, olsrd_cb_ignore);
+    else if (strcmp ("Table: MID", buffer) == 0)
+      olsrd_read_table (fh, olsrd_cb_ignore);
+    else if (strcmp ("Table: Routes", buffer) == 0)
+      olsrd_read_table (fh, olsrd_cb_routes);
+    else if ((strcmp ("HTTP/1.0 200 OK", buffer) == 0)
+        || (strcmp ("Content-type: text/plain", buffer) == 0))
+    {
+      /* ignore */
+    }
+    else
+    {
+      DEBUG ("olsrd plugin: Unable to handle line: %s", buffer);
+    }
+  } /* while (fgets) */
+
+  fclose (fh);
+  
+  return (0);
+} /* }}} int olsrd_read */
+
+static int olsrd_shutdown (void) /* {{{ */
+{
+  sfree (config_node);
+  sfree (config_service);
+
+  return (0);
+} /* }}} int olsrd_shutdown */
+
+void module_register (void)
+{
+  plugin_register_config ("olsrd", olsrd_config,
+      config_keys, config_keys_num);
+  plugin_register_read ("olsrd", olsrd_read);
+  plugin_register_shutdown ("olsrd", olsrd_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/onewire.c b/src/onewire.c
new file mode 100644 (file)
index 0000000..1383fc5
--- /dev/null
@@ -0,0 +1,628 @@
+/**
+ * collectd - src/onewire.c
+ * Copyright (C) 2008  noris network AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at noris.net>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <owcapi.h>
+
+#define OW_FAMILY_LENGTH 8
+#define OW_FAMILY_MAX_FEATURES 2
+struct ow_family_features_s
+{
+  char family[OW_FAMILY_LENGTH];
+  struct
+  {
+    char filename[DATA_MAX_NAME_LEN];
+    char type[DATA_MAX_NAME_LEN];
+    char type_instance[DATA_MAX_NAME_LEN];
+  } features[OW_FAMILY_MAX_FEATURES];
+  size_t features_num;
+};
+typedef struct ow_family_features_s ow_family_features_t;
+
+/* internal timing info collected in debug version only */
+#if COLLECT_DEBUG
+static struct timeval tv_begin, tv_end, tv_diff;
+#endif /* COLLECT_DEBUG */
+
+/* regexp to extract address (without family) and file from the owfs path */
+static const char *regexp_to_match = "[A-Fa-f0-9]{2}\\.([A-Fa-f0-9]{12})/([[:alnum:]]+)$";
+
+/* see http://owfs.sourceforge.net/ow_table.html for a list of families */
+static ow_family_features_t ow_family_features[] =
+{
+  { /* DS18S20 Precision Thermometer and DS1920 ibutton */
+    /* family = */ "10.",
+    {
+      {
+        /* filename = */ "temperature",
+        /* type = */ "temperature",
+        /* type_instance = */ ""
+      }
+    },
+    /* features_num = */ 1
+  },
+  { /* DS1822 Econo Thermometer */
+    /* family = */ "22.",
+    {
+      {
+        /* filename = */ "temperature",
+        /* type = */ "temperature",
+        /* type_instance = */ ""
+      }
+    },
+    /* features_num = */ 1
+  },
+  { /* DS18B20 Programmable Resolution Thermometer */
+    /* family = */ "28.",
+    {
+      {
+        /* filename = */ "temperature",
+        /* type = */ "temperature",
+        /* type_instance = */ ""
+      }
+    },
+    /* features_num = */ 1
+  },
+  { /* DS2436 Volts/Temp */
+    /* family = */ "1B.",
+    {
+      {
+        /* filename = */ "temperature",
+        /* type = */ "temperature",
+        /* type_instance = */ ""
+      }
+    },
+    /* features_num = */ 1
+  },
+  { /* DS2438 Volts/Temp */
+    /* family = */ "26.",
+    {
+      {
+        /* filename = */ "temperature",
+        /* type = */ "temperature",
+        /* type_instance = */ ""
+      }
+    },
+    /* features_num = */ 1
+  }
+};
+static int ow_family_features_num = STATIC_ARRAY_SIZE (ow_family_features);
+
+static char *device_g = NULL;
+static cdtime_t ow_interval = 0;
+static _Bool direct_access = 0;
+
+static const char *config_keys[] =
+{
+  "Device",
+  "IgnoreSelected",
+  "Sensor",
+  "Interval"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *sensor_list;
+
+static _Bool   regex_direct_initialized = 0;
+static regex_t regex_direct;
+
+/**
+ * List of onewire owfs "files" to be directly read
+ */
+typedef struct direct_access_element_s
+{
+       char *path;                 /**< The whole owfs path */
+    char *address;              /**< 1-wire address without family */
+    char *file;                 /**< owfs file - e.g. temperature */
+       struct direct_access_element_s *next; /**< Next in the list */
+} direct_access_element_t;
+
+static direct_access_element_t * direct_list = NULL;
+
+/* =================================================================================== */
+
+#if COLLECT_DEBUG
+/* Return 1 if the difference is negative, otherwise 0.  */
+static int timeval_subtract(struct timeval *result, struct timeval *t2, struct timeval *t1)
+{
+    long int diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec);
+    result->tv_sec = diff / 1000000;
+    result->tv_usec = diff % 1000000;
+
+    return (diff<0);
+}
+#endif /* COLLECT_DEBUG */
+
+/* =================================================================================== */
+
+static void direct_list_element_free(direct_access_element_t *el)
+{
+    if (el != NULL)
+    {
+        DEBUG ("onewire plugin: direct_list_element_free - deleting <%s>", el->path);
+        sfree (el->path);
+        sfree (el->address);
+        sfree (el->file);
+        free (el);
+    }
+}
+
+static int direct_list_insert(const char * config)
+{
+    regmatch_t               pmatch[3];
+    size_t                   nmatch = 3;
+    direct_access_element_t *element = NULL;
+
+    DEBUG ("onewire plugin: direct_list_insert <%s>", config);
+
+    element = (direct_access_element_t *) malloc (sizeof(*element));
+    if (element == NULL)
+    {
+        ERROR ("onewire plugin: direct_list_insert - cannot allocate element");
+        return 1;
+    }
+    element->path    = NULL;
+    element->address = NULL;
+    element->file    = NULL;
+
+    element->path = strdup (config);
+    if (element->path == NULL)
+    {
+        ERROR ("onewire plugin: direct_list_insert - cannot allocate path");
+        direct_list_element_free (element);
+        return 1;
+    }
+
+    DEBUG ("onewire plugin: direct_list_insert - about to match %s", config);
+
+    if (!regex_direct_initialized)
+    {
+        if (regcomp (&regex_direct, regexp_to_match, REG_EXTENDED))
+        {
+            ERROR ("onewire plugin: Cannot compile regex");
+            direct_list_element_free (element);
+            return (1);
+        }
+        regex_direct_initialized = 1;
+        DEBUG ("onewire plugin: Compiled regex!!");
+    }
+
+    if (regexec (&regex_direct, config, nmatch, pmatch, 0))
+    {
+        ERROR ("onewire plugin: direct_list_insert - no regex  match");
+        direct_list_element_free (element);
+        return 1;
+    }
+
+    if (pmatch[1].rm_so<0)
+    {
+        ERROR ("onewire plugin: direct_list_insert - no address regex match");
+        direct_list_element_free (element);
+        return 1;
+    }
+    element->address = strndup (config+pmatch[1].rm_so,
+                                pmatch[1].rm_eo - pmatch[1].rm_so);
+    if (element->address == NULL)
+    {
+        ERROR ("onewire plugin: direct_list_insert - cannot allocate address");
+        direct_list_element_free (element);
+        return 1;
+    }
+    DEBUG ("onewire plugin: direct_list_insert - found address <%s>",
+           element->address);
+
+    if (pmatch[2].rm_so<0)
+    {
+        ERROR ("onewire plugin: direct_list_insert - no file regex match");
+        direct_list_element_free (element);
+        return 1;
+    }
+    element->file = strndup (config+pmatch[2].rm_so,
+                             pmatch[2].rm_eo - pmatch[2].rm_so);
+    if (element->file == NULL)
+    {
+        ERROR ("onewire plugin: direct_list_insert - cannot allocate file");
+        direct_list_element_free (element);
+        return 1;
+    }
+    DEBUG ("onewire plugin: direct_list_insert - found file <%s>", element->file);
+
+    element->next = direct_list;
+    direct_list = element;
+
+    return 0;
+}
+
+static void direct_list_free(void)
+{
+    direct_access_element_t *traverse = direct_list;
+    direct_access_element_t *tmp = NULL;;
+
+    while(traverse != NULL)
+    {
+        tmp = traverse;
+        traverse = traverse->next;
+        direct_list_element_free (tmp);
+        tmp = NULL;
+    }
+}
+
+/* =================================================================================== */
+
+static int cow_load_config (const char *key, const char *value)
+{
+  if (sensor_list == NULL)
+    sensor_list = ignorelist_create (1);
+
+  if (strcasecmp (key, "Sensor") == 0)
+  {
+    if (direct_list_insert (value))
+    {
+        DEBUG ("onewire plugin: Cannot add %s to direct_list_insert.", value);
+
+        if (ignorelist_add (sensor_list, value))
+        {
+            ERROR ("onewire plugin: Cannot add value to ignorelist.");
+            return (1);
+        }
+    }
+    else
+    {
+        DEBUG ("onewire plugin: %s is a direct access", value);
+        direct_access = 1;
+    }
+  }
+  else if (strcasecmp (key, "IgnoreSelected") == 0)
+  {
+    ignorelist_set_invert (sensor_list, 1);
+    if (IS_TRUE (value))
+      ignorelist_set_invert (sensor_list, 0);
+  }
+  else if (strcasecmp (key, "Device") == 0)
+  {
+    char *temp;
+    temp = strdup (value);
+    if (temp == NULL)
+    {
+      ERROR ("onewire plugin: strdup failed.");
+      return (1);
+    }
+    sfree (device_g);
+    device_g = temp;
+  }
+  else if (strcasecmp ("Interval", key) == 0)
+  {
+    double tmp;
+    tmp = atof (value);
+    if (tmp > 0.0)
+      ow_interval = DOUBLE_TO_CDTIME_T (tmp);
+    else
+      ERROR ("onewire plugin: Invalid `Interval' setting: %s", value);
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+}
+
+static int cow_read_values (const char *path, const char *name,
+    const ow_family_features_t *family_info)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  int success = 0;
+  size_t i;
+
+  if (sensor_list != NULL)
+  {
+    DEBUG ("onewire plugin: Checking ignorelist for `%s'", name);
+    if (ignorelist_match (sensor_list, name) != 0)
+      return 0;
+  }
+
+  vl.values = values;
+  vl.values_len = 1;
+
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, name, sizeof (vl.plugin_instance));
+
+  for (i = 0; i < family_info->features_num; i++)
+  {
+    char *buffer;
+    size_t buffer_size;
+    int status;
+
+    char file[4096];
+    char *endptr;
+
+    snprintf (file, sizeof (file), "%s/%s",
+        path, family_info->features[i].filename);
+    file[sizeof (file) - 1] = 0;
+
+    buffer = NULL;
+    buffer_size = 0;
+    DEBUG ("Start reading onewire device %s", file);
+    status = OW_get (file, &buffer, &buffer_size);
+    if (status < 0)
+    {
+      ERROR ("onewire plugin: OW_get (%s/%s) failed. status = %#x;",
+          path, family_info->features[i].filename, status);
+      return (-1);
+    }
+    DEBUG ("Read onewire device %s as %s", file, buffer);
+
+    endptr = NULL;
+    values[0].gauge = strtod (buffer, &endptr);
+    if (endptr == NULL)
+    {
+      ERROR ("onewire plugin: Buffer is not a number: %s", buffer);
+      status = -1;
+      continue;
+    }
+
+    sstrncpy (vl.type, family_info->features[i].type, sizeof (vl.type));
+    sstrncpy (vl.type_instance, family_info->features[i].type_instance,
+        sizeof (vl.type_instance));
+
+    plugin_dispatch_values (&vl);
+    success++;
+
+    free (buffer);
+  } /* for (i = 0; i < features_num; i++) */
+
+  return ((success > 0) ? 0 : -1);
+} /* int cow_read_values */
+
+/* Forward declaration so the recursion below works */
+static int cow_read_bus (const char *path);
+
+/*
+ * cow_read_ds2409
+ *
+ * Handles:
+ * - DS2409 - MicroLAN Coupler
+ */
+static int cow_read_ds2409 (const char *path)
+{
+  char subpath[4096];
+  int status;
+
+  status = ssnprintf (subpath, sizeof (subpath), "%s/main", path);
+  if ((status > 0) && (status < sizeof (subpath)))
+    cow_read_bus (subpath);
+
+  status = ssnprintf (subpath, sizeof (subpath), "%s/aux", path);
+  if ((status > 0) && (status < sizeof (subpath)))
+    cow_read_bus (subpath);
+
+  return (0);
+} /* int cow_read_ds2409 */
+
+static int cow_read_bus (const char *path)
+{
+  char *buffer;
+  size_t buffer_size;
+  int status;
+
+  char *buffer_ptr;
+  char *dummy;
+  char *saveptr;
+  char subpath[4096];
+
+  status = OW_get (path, &buffer, &buffer_size);
+  if (status < 0)
+  {
+    ERROR ("onewire plugin: OW_get (%s) failed. status = %#x;",
+        path, status);
+    return (-1);
+  }
+  DEBUG ("onewire plugin: OW_get (%s) returned: %s",
+      path, buffer);
+
+  dummy = buffer;
+  saveptr = NULL;
+  while ((buffer_ptr = strtok_r (dummy, ",/", &saveptr)) != NULL)
+  {
+    int i;
+
+    dummy = NULL;
+
+    if (strcmp ("/", path) == 0)
+      status = ssnprintf (subpath, sizeof (subpath), "/%s", buffer_ptr);
+    else
+      status = ssnprintf (subpath, sizeof (subpath), "%s/%s",
+          path, buffer_ptr);
+    if ((status <= 0) || (status >= sizeof (subpath)))
+      continue;
+
+    for (i = 0; i < ow_family_features_num; i++)
+    {
+      if (strncmp (ow_family_features[i].family, buffer_ptr,
+            strlen (ow_family_features[i].family)) != 0)
+        continue;
+
+      cow_read_values (subpath,
+          buffer_ptr + strlen (ow_family_features[i].family),
+          ow_family_features + i);
+      break;
+    }
+    if (i < ow_family_features_num)
+      continue;
+
+    /* DS2409 */
+    if (strncmp ("1F.", buffer_ptr, strlen ("1F.")) == 0)
+    {
+      cow_read_ds2409 (subpath);
+      continue;
+    }
+  } /* while (strtok_r) */
+
+  free (buffer);
+  return (0);
+} /* int cow_read_bus */
+
+
+/* =================================================================================== */
+
+static int cow_simple_read (void)
+{
+  value_t      values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  char        *buffer;
+  size_t       buffer_size;
+  int          status;
+  char        *endptr;
+  direct_access_element_t *traverse;
+
+  /* traverse list and check entries */
+  for (traverse = direct_list; traverse != NULL; traverse = traverse->next)
+  {
+      vl.values = values;
+      vl.values_len = 1;
+
+      sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+      sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin));
+      sstrncpy (vl.plugin_instance, traverse->address, sizeof (vl.plugin_instance));
+
+      status = OW_get (traverse->path, &buffer, &buffer_size);
+      if (status < 0)
+      {
+          ERROR ("onewire plugin: OW_get (%s) failed. status = %#x;",
+                 traverse->path,
+                 status);
+          return (-1);
+      }
+      DEBUG ("onewire plugin: Read onewire device %s as %s", traverse->path, buffer);
+
+
+      endptr = NULL;
+      values[0].gauge = strtod (buffer, &endptr);
+      if (endptr == NULL)
+      {
+          ERROR ("onewire plugin: Buffer is not a number: %s", buffer);
+          status = -1;
+          continue;
+      }
+
+      sstrncpy (vl.type, traverse->file, sizeof (vl.type));
+      sstrncpy (vl.type_instance, "",   sizeof (""));
+
+      plugin_dispatch_values (&vl);
+      free (buffer);
+  } /* for (traverse) */
+
+  return 0;
+} /* int cow_simple_read */
+
+/* =================================================================================== */
+
+static int cow_read (user_data_t *ud __attribute__((unused)))
+{
+    int result=0;
+
+#if COLLECT_DEBUG
+    gettimeofday (&tv_begin, NULL);
+#endif /* COLLECT_DEBUG */
+
+    if (direct_access)
+    {
+        DEBUG ("onewire plugin: Direct access read");
+        result = cow_simple_read ();
+    }
+    else
+    {
+        DEBUG ("onewire plugin: Standard access read");
+        result = cow_read_bus ("/");
+    }
+
+#if COLLECT_DEBUG
+    gettimeofday (&tv_end, NULL);
+    timeval_subtract (&tv_diff, &tv_end, &tv_begin);
+    DEBUG ("onewire plugin: Onewire read took us %ld.%06ld s",
+           tv_diff.tv_sec,
+           tv_diff.tv_usec);
+#endif /* COLLECT_DEBUG */
+
+    return result;
+} /* int cow_read */
+
+static int cow_shutdown (void)
+{
+    OW_finish ();
+    ignorelist_free (sensor_list);
+
+    direct_list_free ();
+
+    if (regex_direct_initialized)
+    {
+        regfree(&regex_direct);
+    }
+
+    return (0);
+} /* int cow_shutdown */
+
+static int cow_init (void)
+{
+  int status;
+  struct timespec cb_interval;
+
+  if (device_g == NULL)
+  {
+    ERROR ("onewire plugin: cow_init: No device configured.");
+    return (-1);
+  }
+
+  DEBUG ("onewire plugin: about to init device <%s>.", device_g);
+  status = (int) OW_init (device_g);
+  if (status != 0)
+  {
+    ERROR ("onewire plugin: OW_init(%s) failed: %i.", device_g, status);
+    return (1);
+  }
+
+  CDTIME_T_TO_TIMESPEC (ow_interval, &cb_interval);
+
+  plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read,
+      (ow_interval != 0) ? &cb_interval : NULL,
+      /* user data = */ NULL);
+  plugin_register_shutdown ("onewire", cow_shutdown);
+
+  return (0);
+} /* int cow_init */
+
+void module_register (void)
+{
+  plugin_register_init ("onewire", cow_init);
+  plugin_register_config ("onewire", cow_load_config,
+                          config_keys, config_keys_num);
+}
+
+/* vim: set sw=2 sts=2 ts=8 et fdm=marker cindent : */
diff --git a/src/openldap.c b/src/openldap.c
new file mode 100644 (file)
index 0000000..bca686e
--- /dev/null
@@ -0,0 +1,682 @@
+/**
+ * collectd - src/openldap.c
+ * Copyright (C) 2011       Kimo Rosenbaum
+ * Copyright (C) 2014       Marc Fournier
+ *
+ * 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:
+ *   Kimo Rosenbaum <kimor79 at yahoo.com>
+ *   Marc Fournier <marc.fournier at camptocamp.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <lber.h>
+#include <ldap.h>
+
+struct cldap_s /* {{{ */
+{
+       char *name;
+
+       char *cacert;
+       char *host;
+       int   state;
+       _Bool starttls;
+       int   timeout;
+       char *url;
+       _Bool verifyhost;
+       int   version;
+
+       LDAP *ld;
+};
+typedef struct cldap_s cldap_t; /* }}} */
+
+static void cldap_free (cldap_t *st) /* {{{ */
+{
+       if (st == NULL)
+               return;
+
+       sfree (st->cacert);
+       sfree (st->host);
+       sfree (st->name);
+       sfree (st->url);
+       if (st->ld)
+               ldap_memfree (st->ld);
+       sfree (st);
+} /* }}} void cldap_free */
+
+/* initialize ldap for each host */
+static int cldap_init_host (cldap_t *st) /* {{{ */
+{
+       LDAP *ld;
+       int rc;
+       rc = ldap_initialize (&ld, st->url);
+       if (rc != LDAP_SUCCESS)
+       {
+               ERROR ("openldap plugin: ldap_initialize failed: %s",
+                       ldap_err2string (rc));
+               st->state = 0;
+               ldap_unbind_ext_s (ld, NULL, NULL);
+               return (-1);
+       }
+
+       st->ld = ld;
+
+       ldap_set_option (st->ld, LDAP_OPT_PROTOCOL_VERSION, &st->version);
+
+       ldap_set_option (st->ld, LDAP_OPT_TIMEOUT,
+               &(const struct timeval){st->timeout, 0});
+
+       if (st->cacert != NULL)
+               ldap_set_option (st->ld, LDAP_OPT_X_TLS_CACERTFILE, st->cacert);
+
+       if (st->verifyhost == 0)
+       {
+               int never = LDAP_OPT_X_TLS_NEVER;
+               ldap_set_option (st->ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &never);
+       }
+
+       if (st->starttls != 0)
+       {
+               rc = ldap_start_tls_s (ld, NULL, NULL);
+               if (rc != LDAP_SUCCESS)
+               {
+                       ERROR ("openldap plugin: Failed to start tls on %s: %s",
+                                       st->url, ldap_err2string (rc));
+                       st->state = 0;
+                       ldap_unbind_ext_s (st->ld, NULL, NULL);
+                       return (-1);
+               }
+       }
+
+       struct berval cred;
+       cred.bv_val = "";
+       cred.bv_len = 0;
+
+       rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL);
+       if (rc != LDAP_SUCCESS)
+       {
+               ERROR ("openldap plugin: Failed to bind to %s: %s",
+                               st->url, ldap_err2string (rc));
+               st->state = 0;
+               ldap_unbind_ext_s (st->ld, NULL, NULL);
+               return (-1);
+       }
+       else
+       {
+               DEBUG ("openldap plugin: Successfully connected to %s",
+                               st->url);
+               st->state = 1;
+               return (0);
+       }
+} /* }}} static cldap_init_host */
+
+static void cldap_submit_value (const char *type, const char *type_instance, /* {{{ */
+               value_t value, cldap_t *st)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values     = &value;
+       vl.values_len = 1;
+
+       if ((st->host == NULL)
+                       || (strcmp ("", st->host) == 0)
+                       || (strcmp ("localhost", st->host) == 0))
+       {
+               sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       }
+       else
+       {
+               sstrncpy (vl.host, st->host, sizeof (vl.host));
+       }
+
+       sstrncpy (vl.plugin, "openldap", sizeof (vl.plugin));
+       if (st->name != NULL)
+               sstrncpy (vl.plugin_instance, st->name,
+                               sizeof (vl.plugin_instance));
+
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance,
+                               sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* }}} void cldap_submit_value */
+
+static void cldap_submit_derive (const char *type, const char *type_instance, /* {{{ */
+               derive_t d, cldap_t *st)
+{
+       value_t v;
+       v.derive = d;
+       cldap_submit_value (type, type_instance, v, st);
+} /* }}} void cldap_submit_derive */
+
+static void cldap_submit_gauge (const char *type, const char *type_instance, /* {{{ */
+               gauge_t g, cldap_t *st)
+{
+       value_t v;
+       v.gauge = g;
+       cldap_submit_value (type, type_instance, v, st);
+} /* }}} void cldap_submit_gauge */
+
+static int cldap_read_host (user_data_t *ud) /* {{{ */
+{
+       cldap_t *st;
+       LDAPMessage *e, *result;
+       char *dn;
+       int rc;
+       int status;
+
+       char *attrs[9] = { "monitorCounter",
+                               "monitorOpCompleted",
+                               "monitorOpInitiated",
+                               "monitoredInfo",
+                               "olmBDBEntryCache",
+                               "olmBDBDNCache",
+                               "olmBDBIDLCache",
+                               "namingContexts",
+                               NULL };
+
+       if ((ud == NULL) || (ud->data == NULL))
+       {
+               ERROR ("openldap plugin: cldap_read_host: Invalid user data.");
+               return (-1);
+       }
+
+       st = (cldap_t *) ud->data;
+
+       status = cldap_init_host (st);
+       if (status != 0)
+               return (-1);
+
+       rc = ldap_search_ext_s (st->ld, "cn=Monitor", LDAP_SCOPE_SUBTREE,
+               "(|(!(cn=* *))(cn=Database*))", attrs, 0,
+               NULL, NULL, NULL, 0, &result);
+
+       if (rc != LDAP_SUCCESS)
+       {
+               ERROR ("openldap plugin: Failed to execute search: %s",
+                               ldap_err2string (rc));
+               ldap_msgfree (result);
+               ldap_unbind_ext_s (st->ld, NULL, NULL);
+               return (-1);
+       }
+
+       for (e = ldap_first_entry (st->ld, result); e != NULL;
+               e = ldap_next_entry (st->ld, e))
+       {
+               if ((dn = ldap_get_dn (st->ld, e)) != NULL)
+               {
+                       unsigned long long counter = 0;
+                       unsigned long long opc = 0;
+                       unsigned long long opi = 0;
+                       unsigned long long info = 0;
+
+                       struct berval counter_data;
+                       struct berval opc_data;
+                       struct berval opi_data;
+                       struct berval info_data;
+                       struct berval olmbdb_data;
+                       struct berval nc_data;
+
+                       struct berval **counter_list;
+                       struct berval **opc_list;
+                       struct berval **opi_list;
+                       struct berval **info_list;
+                       struct berval **olmbdb_list;
+                       struct berval **nc_list;
+
+                       if ((counter_list = ldap_get_values_len (st->ld, e,
+                               "monitorCounter")) != NULL)
+                       {
+                               counter_data = *counter_list[0];
+                               counter = atoll (counter_data.bv_val);
+                       }
+
+                       if ((opc_list = ldap_get_values_len (st->ld, e,
+                               "monitorOpCompleted")) != NULL)
+                       {
+                               opc_data = *opc_list[0];
+                               opc = atoll (opc_data.bv_val);
+                       }
+
+                       if ((opi_list = ldap_get_values_len (st->ld, e,
+                               "monitorOpInitiated")) != NULL)
+                       {
+                               opi_data = *opi_list[0];
+                               opi = atoll (opi_data.bv_val);
+                       }
+
+                       if ((info_list = ldap_get_values_len (st->ld, e,
+                               "monitoredInfo")) != NULL)
+                       {
+                               info_data = *info_list[0];
+                               info = atoll (info_data.bv_val);
+                       }
+
+                       if (strcmp (dn, "cn=Total,cn=Connections,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("total_connections", NULL,
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Current,cn=Connections,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_gauge ("current_connections", NULL,
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Operations,cn=Monitor") == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Bind,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "bind-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "bind-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=UnBind,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "unbind-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "unbind-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Search,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "search-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "search-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Compare,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "compare-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "compare-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Modify,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "modify-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "modify-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Modrdn,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "modrdn-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "modrdn-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Add,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "add-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "add-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Delete,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "delete-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "delete-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Abandon,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "abandon-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "abandon-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Extended,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("operations",
+                                       "extended-completed", opc, st);
+                               cldap_submit_derive ("operations",
+                                       "extended-initiated", opi, st);
+                       }
+                       else if ((strncmp (dn, "cn=Database", 11) == 0)
+                               && ((nc_list = ldap_get_values_len
+                                               (st->ld, e, "namingContexts")) != NULL))
+                       {
+                               nc_data = *nc_list[0];
+                               char typeinst[DATA_MAX_NAME_LEN];
+
+                               if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+                                       "olmBDBEntryCache")) != NULL)
+                               {
+                                       olmbdb_data = *olmbdb_list[0];
+                                       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);
+                               }
+
+                               if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+                                       "olmBDBDNCache")) != NULL)
+                               {
+                                       olmbdb_data = *olmbdb_list[0];
+                                       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);
+                               }
+
+                               if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+                                       "olmBDBIDLCache")) != NULL)
+                               {
+                                       olmbdb_data = *olmbdb_list[0];
+                                       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);
+                               }
+
+                               ldap_value_free_len (nc_list);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Bytes,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("derive", "statistics-bytes",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=PDU,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("derive", "statistics-pdu",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Entries,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("derive", "statistics-entries",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Referrals,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("derive", "statistics-referrals",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Open,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_gauge ("threads", "threads-open",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Starting,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_gauge ("threads", "threads-starting",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Active,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_gauge ("threads", "threads-active",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Pending,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_gauge ("threads", "threads-pending",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Backload,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_gauge ("threads", "threads-backload",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Read,cn=Waiters,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("derive", "waiters-read",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Write,cn=Waiters,cn=Monitor")
+                                       == 0)
+                       {
+                               cldap_submit_derive ("derive", "waiters-write",
+                                       counter, st);
+                       }
+
+                       ldap_value_free_len (counter_list);
+                       ldap_value_free_len (opc_list);
+                       ldap_value_free_len (opi_list);
+                       ldap_value_free_len (info_list);
+               }
+
+               ldap_memfree (dn);
+       }
+
+       ldap_msgfree (result);
+       ldap_unbind_ext_s (st->ld, NULL, NULL);
+       return (0);
+} /* }}} int cldap_read_host */
+
+/* Configuration handling functions {{{
+ *
+ * <Plugin ldap>
+ *   <Instance "plugin_instance1">
+ *     URL "ldap://localhost"
+ *     ...
+ *   </Instance>
+ * </Plugin>
+ */
+
+static int cldap_config_add (oconfig_item_t *ci) /* {{{ */
+{
+       cldap_t *st;
+       int i;
+       int status;
+
+       st = malloc (sizeof (*st));
+       if (st == NULL)
+       {
+               ERROR ("openldap plugin: malloc failed.");
+               return (-1);
+       }
+       memset (st, 0, sizeof (*st));
+
+       status = cf_util_get_string (ci, &st->name);
+       if (status != 0)
+       {
+               sfree (st);
+               return (status);
+       }
+
+       st->starttls = 0;
+       st->timeout = -1;
+       st->verifyhost = 1;
+       st->version = LDAP_VERSION3;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("CACert", child->key) == 0)
+                       status = cf_util_get_string (child, &st->cacert);
+               else if (strcasecmp ("StartTLS", child->key) == 0)
+                       status = cf_util_get_boolean (child, &st->starttls);
+               else if (strcasecmp ("Timeout", child->key) == 0)
+                       status = cf_util_get_int (child, &st->timeout);
+               else if (strcasecmp ("URL", child->key) == 0)
+                       status = cf_util_get_string (child, &st->url);
+               else if (strcasecmp ("VerifyHost", child->key) == 0)
+                       status = cf_util_get_boolean (child, &st->verifyhost);
+               else if (strcasecmp ("Version", child->key) == 0)
+                       status = cf_util_get_int (child, &st->version);
+               else
+               {
+                       WARNING ("openldap plugin: Option `%s' not allowed here.",
+                                       child->key);
+                       status = -1;
+               }
+
+               if (status != 0)
+                       break;
+       }
+
+       /* Check if struct is complete.. */
+       if ((status == 0) && (st->url == NULL))
+       {
+               ERROR ("openldap plugin: Instance `%s': "
+                               "No URL has been configured.",
+                               st->name);
+               status = -1;
+       }
+
+       /* Check if URL is valid */
+       if ((status == 0) && (st->url != NULL))
+       {
+               LDAPURLDesc *ludpp;
+               int rc;
+
+               if ((rc = ldap_url_parse (st->url, &ludpp)) != 0)
+               {
+                       ERROR ("openldap plugin: Instance `%s': "
+                               "Invalid URL: `%s'",
+                               st->name, st->url);
+                       status = -1;
+               }
+               else
+               {
+                       st->host = strdup (ludpp->lud_host);
+               }
+
+               ldap_free_urldesc (ludpp);
+       }
+
+       if (status == 0)
+       {
+               user_data_t ud;
+               char callback_name[3*DATA_MAX_NAME_LEN];
+
+               memset (&ud, 0, sizeof (ud));
+               ud.data = st;
+
+               memset (callback_name, 0, sizeof (callback_name));
+               ssnprintf (callback_name, sizeof (callback_name),
+                               "openldap/%s/%s",
+                               (st->host != NULL) ? st->host : hostname_g,
+                               (st->name != NULL) ? st->name : "default"),
+
+               status = plugin_register_complex_read (/* group = */ NULL,
+                               /* name      = */ callback_name,
+                               /* callback  = */ cldap_read_host,
+                               /* interval  = */ NULL,
+                               /* user_data = */ &ud);
+       }
+
+       if (status != 0)
+       {
+               cldap_free (st);
+               return (-1);
+       }
+
+       return (0);
+} /* }}} int cldap_config_add */
+
+static int cldap_config (oconfig_item_t *ci) /* {{{ */
+{
+       int i;
+       int status = 0;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Instance", child->key) == 0)
+                       cldap_config_add (child);
+               else
+                       WARNING ("openldap plugin: The configuration option "
+                                       "\"%s\" is not allowed here. Did you "
+                                       "forget to add an <Instance /> block "
+                                       "around the configuration?",
+                                       child->key);
+       } /* for (ci->children) */
+
+       return (status);
+} /* }}} int cldap_config */
+
+/* }}} End of configuration handling functions */
+
+static int cldap_init (void) /* {{{ */
+{
+       /* Initialize LDAP library while still single-threaded as recommended in
+        * ldap_initialize(3) */
+       int debug_level;
+       ldap_get_option (NULL, LDAP_OPT_DEBUG_LEVEL, &debug_level);
+       return (0);
+} /* }}} int cldap_init */
+
+void module_register (void) /* {{{ */
+{
+       plugin_register_complex_config ("openldap", cldap_config);
+       plugin_register_init ("openldap", cldap_init);
+} /* }}} void module_register */
diff --git a/src/openvpn.c b/src/openvpn.c
new file mode 100644 (file)
index 0000000..0fd9405
--- /dev/null
@@ -0,0 +1,805 @@
+/**
+ * collectd - src/openvpn.c
+ * Copyright (C) 2008       Doug MacEachern
+ * Copyright (C) 2009,2010  Florian octo Forster
+ * Copyright (C) 2009       Marco Chiappero
+ * Copyright (C) 2009       Fabian Schuh
+ *
+ * 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:
+ *   Doug MacEachern <dougm at hyperic.com>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Marco Chiappero <marco at absence.it>
+ *   Fabian Schuh <mail at xeroc.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#define V1STRING "Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since\n"
+#define V2STRING "HEADER,CLIENT_LIST,Common Name,Real Address,Virtual Address,Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t)\n"
+#define V3STRING "HEADER CLIENT_LIST Common Name Real Address Virtual Address Bytes Received Bytes Sent Connected Since Connected Since (time_t)\n"
+#define V4STRING "HEADER,CLIENT_LIST,Common Name,Real Address,Virtual Address,Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t),Username\n"
+#define VSSTRING "OpenVPN STATISTICS\n"
+
+
+struct vpn_status_s
+{
+       char *file;
+       enum
+       {
+               MULTI1 = 1, /* status-version 1 */
+               MULTI2,     /* status-version 2 */
+               MULTI3,     /* status-version 3 */
+               MULTI4,     /* status-version 4 */
+               SINGLE = 10 /* currently no versions for single mode, maybe in the future */
+       } version;
+       char *name;
+};
+typedef struct vpn_status_s vpn_status_t;
+
+static vpn_status_t **vpn_list = NULL;
+static int vpn_num = 0;
+
+static _Bool new_naming_schema = 0;
+static _Bool collect_compression = 1;
+static _Bool collect_user_count  = 0;
+static _Bool collect_individual_users  = 1;
+
+static const char *config_keys[] =
+{
+       "StatusFile",
+       "Compression", /* old, deprecated name */
+       "ImprovedNamingSchema",
+       "CollectCompression",
+       "CollectUserCount",
+       "CollectIndividualUsers"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+
+/* Helper function
+ * copy-n-pasted from common.c - changed delim to ","  */
+static int openvpn_strsplit (char *string, char **fields, size_t size)
+{
+       size_t i;
+       char *ptr;
+       char *saveptr;
+
+       i = 0;
+       ptr = string;
+       saveptr = NULL;
+       while ((fields[i] = strtok_r (ptr, ",", &saveptr)) != NULL)
+       {
+               ptr = NULL;
+               i++;
+
+               if (i >= size)
+                       break;
+       }
+
+       return (i);
+} /* int openvpn_strsplit */
+
+/* dispatches number of users */
+static void numusers_submit (char *pinst, char *tinst, gauge_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin));
+       sstrncpy (vl.type, "users", sizeof (vl.type));
+       if (pinst != NULL)
+               sstrncpy (vl.plugin_instance, pinst, sizeof (vl.plugin_instance));
+       if (tinst != NULL)
+               sstrncpy (vl.type_instance, tinst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void numusers_submit */
+
+/* dispatches stats about traffic (TCP or UDP) generated by the tunnel per single endpoint */
+static void iostats_submit (char *pinst, char *tinst, derive_t rx, derive_t tx)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       /* NOTE ON THE NEW NAMING SCHEMA:
+        *       using plugin_instance to identify each vpn config (and
+        *       status) file; using type_instance to identify the endpoint
+        *       host when in multimode, traffic or overhead when in single.
+        */
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin));
+       if (pinst != NULL)
+               sstrncpy (vl.plugin_instance, pinst,
+                               sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "if_octets", sizeof (vl.type));
+       if (tinst != NULL)
+               sstrncpy (vl.type_instance, tinst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void traffic_submit */
+
+/* dispatches stats about data compression shown when in single mode */
+static void compression_submit (char *pinst, char *tinst,
+               derive_t uncompressed, derive_t compressed)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = uncompressed;
+       values[1].derive = compressed;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin));
+       if (pinst != NULL)
+               sstrncpy (vl.plugin_instance, pinst,
+                               sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "compression", sizeof (vl.type));
+       if (tinst != NULL)
+               sstrncpy (vl.type_instance, tinst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void compression_submit */
+
+static int single_read (char *name, FILE *fh)
+{
+       char buffer[1024];
+       char *fields[4];
+       const int max_fields = STATIC_ARRAY_SIZE (fields);
+       int  fields_num, read = 0;
+
+       derive_t link_rx, link_tx;
+       derive_t tun_rx, tun_tx;
+       derive_t pre_compress, post_compress;
+       derive_t pre_decompress, post_decompress;
+       derive_t overhead_rx, overhead_tx;
+
+       link_rx = 0;
+       link_tx = 0;
+       tun_rx = 0;
+       tun_tx = 0;
+       pre_compress = 0;
+       post_compress = 0;
+       pre_decompress = 0;
+       post_decompress = 0;
+       overhead_rx = 0;
+       overhead_tx = 0;
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               fields_num = openvpn_strsplit (buffer, fields, max_fields);
+
+               /* status file is generated by openvpn/sig.c:print_status()
+                * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/sig.c
+                *
+                * The line we're expecting has 2 fields. We ignore all lines
+                *  with more or less fields.
+                */
+               if (fields_num != 2)
+               {
+                       continue;
+               }
+
+               if (strcmp (fields[0], "TUN/TAP read bytes") == 0)
+               {
+                       /* read from the system and sent over the tunnel */
+                       tun_tx = atoll (fields[1]);
+               }
+               else if (strcmp (fields[0], "TUN/TAP write bytes") == 0)
+               {
+                       /* read from the tunnel and written in the system */
+                       tun_rx = atoll (fields[1]);
+               }
+               else if (strcmp (fields[0], "TCP/UDP read bytes") == 0)
+               {
+                       link_rx = atoll (fields[1]);
+               }
+               else if (strcmp (fields[0], "TCP/UDP write bytes") == 0)
+               {
+                       link_tx = atoll (fields[1]);
+               }
+               else if (strcmp (fields[0], "pre-compress bytes") == 0)
+               {
+                       pre_compress = atoll (fields[1]);
+               }
+               else if (strcmp (fields[0], "post-compress bytes") == 0)
+               {
+                       post_compress = atoll (fields[1]);
+               }
+               else if (strcmp (fields[0], "pre-decompress bytes") == 0)
+               {
+                       pre_decompress = atoll (fields[1]);
+               }
+               else if (strcmp (fields[0], "post-decompress bytes") == 0)
+               {
+                       post_decompress = atoll (fields[1]);
+               }
+       }
+
+       iostats_submit (name, "traffic", link_rx, link_tx);
+
+       /* we need to force this order to avoid negative values with these unsigned */
+       overhead_rx = (((link_rx - pre_decompress) + post_decompress) - tun_rx);
+       overhead_tx = (((link_tx - post_compress) + pre_compress) - tun_tx);
+
+       iostats_submit (name, "overhead", overhead_rx, overhead_tx);
+
+       if (collect_compression)
+       {
+               compression_submit (name, "data_in", post_decompress, pre_decompress);
+               compression_submit (name, "data_out", pre_compress, post_compress);
+       }
+
+       read = 1;
+
+       return (read);
+} /* int single_read */
+
+/* for reading status version 1 */
+static int multi1_read (char *name, FILE *fh)
+{
+       char buffer[1024];
+       char *fields[10];
+       int  fields_num, found_header = 0;
+       long long sum_users = 0;
+
+       /* read the file until the "ROUTING TABLE" line is found (no more info after) */
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               if (strcmp (buffer, "ROUTING TABLE\n") == 0)
+                       break;
+
+               if (strcmp (buffer, V1STRING) == 0)
+               {
+                       found_header = 1;
+                       continue;
+               }
+
+               /* skip the first lines until the client list section is found */
+               if (found_header == 0)
+                       /* we can't start reading data until this string is found */
+                       continue;
+
+               fields_num = openvpn_strsplit (buffer,
+                               fields, STATIC_ARRAY_SIZE (fields));
+               if (fields_num < 4)
+                       continue;
+
+               if (collect_user_count)
+                       /* If so, sum all users, ignore the individuals*/
+               {
+                       sum_users += 1;
+               }
+               if (collect_individual_users)
+               {
+                       if (new_naming_schema)
+                       {
+                               iostats_submit (name,               /* vpn instance */
+                                               fields[0],          /* "Common Name" */
+                                               atoll (fields[2]),  /* "Bytes Received" */
+                                               atoll (fields[3])); /* "Bytes Sent" */
+                       }
+                       else
+                       {
+                               iostats_submit (fields[0],          /* "Common Name" */
+                                               NULL,               /* unused when in multimode */
+                                               atoll (fields[2]),  /* "Bytes Received" */
+                                               atoll (fields[3])); /* "Bytes Sent" */
+                       }
+               }
+       }
+
+       if (ferror (fh))
+               return (0);
+
+       if (collect_user_count)
+               numusers_submit(name, name, sum_users);
+
+       return (1);
+} /* int multi1_read */
+
+/* for reading status version 2 */
+static int multi2_read (char *name, FILE *fh)
+{
+       char buffer[1024];
+       char *fields[10];
+       const int max_fields = STATIC_ARRAY_SIZE (fields);
+       int  fields_num, read = 0;
+       long long sum_users    = 0;
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               fields_num = openvpn_strsplit (buffer, fields, max_fields);
+
+               /* status file is generated by openvpn/multi.c:multi_print_status()
+                * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c
+                *
+                * The line we're expecting has 8 fields. We ignore all lines
+                *  with more or less fields.
+                */
+               if (fields_num != 8)
+                       continue;
+
+               if (strcmp (fields[0], "CLIENT_LIST") != 0)
+                       continue;
+
+               if (collect_user_count)
+                       /* If so, sum all users, ignore the individuals*/
+               {
+                       sum_users += 1;
+               }
+               if (collect_individual_users)
+               {
+                       if (new_naming_schema)
+                       {
+                               /* plugin inst = file name, type inst = fields[1] */
+                               iostats_submit (name,               /* vpn instance */
+                                               fields[1],          /* "Common Name" */
+                                               atoll (fields[4]),  /* "Bytes Received" */
+                                               atoll (fields[5])); /* "Bytes Sent" */
+                       }
+                       else
+                       {
+                               /* plugin inst = fields[1], type inst = "" */
+                               iostats_submit (fields[1],          /* "Common Name" */
+                                               NULL,               /* unused when in multimode */
+                                               atoll (fields[4]),  /* "Bytes Received" */
+                                               atoll (fields[5])); /* "Bytes Sent" */
+                       }
+               }
+
+               read = 1;
+       }
+
+       if (collect_user_count)
+       {
+               numusers_submit(name, name, sum_users);
+               read = 1;
+       }
+
+       return (read);
+} /* int multi2_read */
+
+/* for reading status version 3 */
+static int multi3_read (char *name, FILE *fh)
+{
+       char buffer[1024];
+       char *fields[15];
+       const int max_fields = STATIC_ARRAY_SIZE (fields);
+       int  fields_num, read = 0;
+       long long sum_users    = 0;
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               fields_num = strsplit (buffer, fields, max_fields);
+
+               /* status file is generated by openvpn/multi.c:multi_print_status()
+                * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c
+                *
+                * The line we're expecting has 12 fields. We ignore all lines
+                *  with more or less fields.
+                */
+               if (fields_num != 12)
+               {
+                       continue;
+               }
+               else
+               {
+                       if (strcmp (fields[0], "CLIENT_LIST") != 0)
+                               continue;
+
+                       if (collect_user_count)
+                               /* If so, sum all users, ignore the individuals*/
+                       {
+                               sum_users += 1;
+                       }
+
+                       if (collect_individual_users)
+                       {
+                               if (new_naming_schema)
+                               {
+                                       iostats_submit (name,               /* vpn instance */
+                                                       fields[1],          /* "Common Name" */
+                                                       atoll (fields[4]),  /* "Bytes Received" */
+                                                       atoll (fields[5])); /* "Bytes Sent" */
+                               }
+                               else
+                               {
+                                       iostats_submit (fields[1],          /* "Common Name" */
+                                                       NULL,               /* unused when in multimode */
+                                                       atoll (fields[4]),  /* "Bytes Received" */
+                                                       atoll (fields[5])); /* "Bytes Sent" */
+                               }
+                       }
+
+                       read = 1;
+               }
+       }
+
+       if (collect_user_count)
+       {
+               numusers_submit(name, name, sum_users);
+               read = 1;
+       }
+
+       return (read);
+} /* int multi3_read */
+
+/* for reading status version 4 */
+static int multi4_read (char *name, FILE *fh)
+{
+       char buffer[1024];
+       char *fields[11];
+       const int max_fields = STATIC_ARRAY_SIZE (fields);
+       int  fields_num, read = 0;
+       long long sum_users    = 0;
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               fields_num = openvpn_strsplit (buffer, fields, max_fields);
+
+               /* status file is generated by openvpn/multi.c:multi_print_status()
+                * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c
+                *
+                * The line we're expecting has 9 fields. We ignore all lines
+                *  with more or less fields.
+                */
+               if (fields_num != 9)
+                       continue;
+
+
+               if (strcmp (fields[0], "CLIENT_LIST") != 0)
+                       continue;
+
+
+               if (collect_user_count)
+                       /* If so, sum all users, ignore the individuals*/
+               {
+                       sum_users += 1;
+               }
+               if (collect_individual_users)
+               {
+                       if (new_naming_schema)
+                       {
+                               /* plugin inst = file name, type inst = fields[1] */
+                               iostats_submit (name,               /* vpn instance */
+                                               fields[1],          /* "Common Name" */
+                                               atoll (fields[4]),  /* "Bytes Received" */
+                                               atoll (fields[5])); /* "Bytes Sent" */
+                       }
+                       else
+                       {
+                               /* plugin inst = fields[1], type inst = "" */
+                               iostats_submit (fields[1],          /* "Common Name" */
+                                               NULL,               /* unused when in multimode */
+                                               atoll (fields[4]),  /* "Bytes Received" */
+                                               atoll (fields[5])); /* "Bytes Sent" */
+                       }
+               }
+
+               read = 1;
+       }
+
+       if (collect_user_count)
+       {
+               numusers_submit(name, name, sum_users);
+               read = 1;
+       }
+
+       return (read);
+} /* int multi4_read */
+
+/* read callback */
+static int openvpn_read (void)
+{
+       FILE *fh;
+       int  i, vpn_read, read;
+
+       vpn_read = read = 0;
+
+       /* call the right read function for every status entry in the list */
+       for (i = 0; i < vpn_num; i++)
+       {
+               fh = fopen (vpn_list[i]->file, "r");
+               if (fh == NULL)
+               {
+                       char errbuf[1024];
+                       WARNING ("openvpn plugin: fopen(%s) failed: %s", vpn_list[i]->file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+
+                       continue;
+               }
+
+               switch (vpn_list[i]->version)
+               {
+                       case SINGLE:
+                               vpn_read = single_read(vpn_list[i]->name, fh);
+                               break;
+
+                       case MULTI1:
+                               vpn_read = multi1_read(vpn_list[i]->name, fh);
+                               break;
+
+                       case MULTI2:
+                               vpn_read = multi2_read(vpn_list[i]->name, fh);
+                               break;
+
+                       case MULTI3:
+                               vpn_read = multi3_read(vpn_list[i]->name, fh);
+                               break;
+
+                       case MULTI4:
+                               vpn_read = multi4_read(vpn_list[i]->name, fh);
+                               break;
+               }
+
+               fclose (fh);
+               read += vpn_read;
+       }
+
+       return (read ? 0 : -1);
+} /* int openvpn_read */
+
+static int version_detect (const char *filename)
+{
+       FILE *fh;
+       char buffer[1024];
+       int version = 0;
+
+       /* Sanity checking. We're called from the config handling routine, so
+        * better play it save. */
+       if ((filename == NULL) || (*filename == 0))
+               return (0);
+
+       fh = fopen (filename, "r");
+       if (fh == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("openvpn plugin: Unable to read \"%s\": %s", filename,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (0);
+       }
+
+       /* now search for the specific multimode data format */
+       while ((fgets (buffer, sizeof (buffer), fh)) != NULL)
+       {
+               /* we look at the first line searching for SINGLE mode configuration */
+               if (strcmp (buffer, VSSTRING) == 0)
+               {
+                       DEBUG ("openvpn plugin: found status file version SINGLE");
+                       version = SINGLE;
+                       break;
+               }
+               /* searching for multi version 1 */
+               else if (strcmp (buffer, V1STRING) == 0)
+               {
+                       DEBUG ("openvpn plugin: found status file version MULTI1");
+                       version = MULTI1;
+                       break;
+               }
+               /* searching for multi version 2 */
+               else if (strcmp (buffer, V2STRING) == 0)
+               {
+                       DEBUG ("openvpn plugin: found status file version MULTI2");
+                       version = MULTI2;
+                       break;
+               }
+               /* searching for multi version 3 */
+               else if (strcmp (buffer, V3STRING) == 0)
+               {
+                       DEBUG ("openvpn plugin: found status file version MULTI3");
+                       version = MULTI3;
+                       break;
+               }
+               /* searching for multi version 4 */
+               else if (strcmp (buffer, V4STRING) == 0)
+               {
+                       DEBUG ("openvpn plugin: found status file version MULTI4");
+                       version = MULTI4;
+                       break;
+               }
+       }
+
+       if (version == 0)
+       {
+               /* This is only reached during configuration, so complaining to
+                * the user is in order. */
+               NOTICE ("openvpn plugin: %s: Unknown file format, please "
+                               "report this as bug. Make sure to include "
+                               "your status file, so the plugin can "
+                               "be adapted.", filename);
+       }
+
+       fclose (fh);
+
+       return version;
+} /* int version_detect */
+
+static int openvpn_config (const char *key, const char *value)
+{
+       if (strcasecmp ("StatusFile", key) == 0)
+       {
+               char    *status_file, *status_name, *filename;
+               int     status_version, i;
+               vpn_status_t *temp;
+
+               /* try to detect the status file format */
+               status_version = version_detect (value);
+
+               if (status_version == 0)
+               {
+                       WARNING ("openvpn plugin: unable to detect status version, \
+                                       discarding status file \"%s\".", value);
+                       return (1);
+               }
+
+               status_file = sstrdup (value);
+               if (status_file == NULL)
+               {
+                       char errbuf[1024];
+                       WARNING ("openvpn plugin: sstrdup failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (1);
+               }
+
+               /* it determines the file name as string starting at location filename + 1 */
+               filename = strrchr (status_file, (int) '/');
+               if (filename == NULL)
+               {
+                       /* status_file is already the file name only */
+                       status_name = status_file;
+               }
+               else
+               {
+                       /* doesn't waste memory, uses status_file starting at filename + 1 */
+                       status_name = filename + 1;
+               }
+
+               /* scan the list looking for a clone */
+               for (i = 0; i < vpn_num; i++)
+               {
+                       if (strcasecmp (vpn_list[i]->name, status_name) == 0)
+                       {
+                               WARNING ("openvpn plugin: status filename \"%s\" "
+                                               "already used, please choose a "
+                                               "different one.", status_name);
+                               sfree (status_file);
+                               return (1);
+                       }
+               }
+
+               /* create a new vpn element since file, version and name are ok */
+               temp = (vpn_status_t *) malloc (sizeof (vpn_status_t));
+               temp->file = status_file;
+               temp->version = status_version;
+               temp->name = status_name;
+
+               vpn_list = (vpn_status_t **) realloc (vpn_list, (vpn_num + 1) * sizeof (vpn_status_t *));
+               if (vpn_list == NULL)
+               {
+                       char errbuf[1024];
+                       ERROR ("openvpn plugin: malloc failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+
+                       sfree (temp->file);
+                       sfree (temp);
+                       return (1);
+               }
+
+               vpn_list[vpn_num] = temp;
+               vpn_num++;
+
+               DEBUG ("openvpn plugin: status file \"%s\" added", temp->file);
+
+       } /* if (strcasecmp ("StatusFile", key) == 0) */
+       else if ((strcasecmp ("CollectCompression", key) == 0)
+               || (strcasecmp ("Compression", key) == 0)) /* old, deprecated name */
+       {
+               if (IS_FALSE (value))
+                       collect_compression = 0;
+               else
+                       collect_compression = 1;
+       } /* if (strcasecmp ("CollectCompression", key) == 0) */
+       else if (strcasecmp ("ImprovedNamingSchema", key) == 0)
+       {
+               if (IS_TRUE (value))
+               {
+                       DEBUG ("openvpn plugin: using the new naming schema");
+                       new_naming_schema = 1;
+               }
+               else
+               {
+                       new_naming_schema = 0;
+               }
+       } /* if (strcasecmp ("ImprovedNamingSchema", key) == 0) */
+       else if (strcasecmp("CollectUserCount", key) == 0)
+       {
+               if (IS_TRUE(value))
+                       collect_user_count = 1;
+               else
+                       collect_user_count = 0;
+       } /* if (strcasecmp("CollectUserCount", key) == 0) */
+       else if (strcasecmp("CollectIndividualUsers", key) == 0)
+       {
+               if (IS_FALSE (value))
+                       collect_individual_users = 0;
+               else
+                       collect_individual_users = 1;
+       } /* if (strcasecmp("CollectIndividualUsers", key) == 0) */
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+} /* int openvpn_config */
+
+/* shutdown callback */
+static int openvpn_shutdown (void)
+{
+       int i;
+
+       for (i = 0; i < vpn_num; i++)
+       {
+               sfree (vpn_list[i]->file);
+               sfree (vpn_list[i]);
+       }
+
+       sfree (vpn_list);
+
+       return (0);
+} /* int openvpn_shutdown */
+
+static int openvpn_init (void)
+{
+       if (!collect_individual_users
+                       && !collect_compression
+                       && !collect_user_count)
+       {
+               WARNING ("OpenVPN plugin: Neither `CollectIndividualUsers', "
+                               "`CollectCompression', nor `CollectUserCount' is true. There's no "
+                               "data left to collect.");
+               return (-1);
+       }
+
+       plugin_register_read ("openvpn", openvpn_read);
+       plugin_register_shutdown ("openvpn", openvpn_shutdown);
+
+       return (0);
+} /* int openvpn_init */
+
+void module_register (void)
+{
+       plugin_register_config ("openvpn", openvpn_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("openvpn", openvpn_init);
+} /* void module_register */
+
+/* vim: set sw=2 ts=2 : */
diff --git a/src/oracle.c b/src/oracle.c
new file mode 100644 (file)
index 0000000..ab0812b
--- /dev/null
@@ -0,0 +1,781 @@
+/**
+ * collectd - src/oracle.c
+ * Copyright (C) 2008,2009  noris network AG
+ * Copyright (C) 2012       Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Linking src/oracle.c ("the oracle plugin") statically or dynamically with
+ * other modules is making a combined work based on the oracle plugin. Thus,
+ * the terms and conditions of the GNU General Public License cover the whole
+ * combination.
+ *
+ * In addition, as a special exception, the copyright holders of the oracle
+ * plugin give you permission to combine the oracle plugin with free software
+ * programs or libraries that are released under the GNU LGPL and with code
+ * included in the standard release of the Oracle® Call Interface (OCI) under
+ * the Oracle® Technology Network (OTN) License (or modified versions of such
+ * code, with unchanged license). You may copy and distribute such a system
+ * following the terms of the GNU GPL for the oracle plugin and the licenses of
+ * the other code concerned.
+ *
+ * Note that people who make modified versions of the oracle plugin are not
+ * obligated to grant this special exception for their modified versions; it is
+ * their choice whether to do so. The GNU General Public License gives
+ * permission to release a modified version without this exception; this
+ * exception also makes it possible to release a modified version which carries
+ * forward this exception. However, without this exception the OTN License does
+ * not allow linking with code licensed under the GNU General Public License.
+ *
+ * Oracle® is a registered trademark of Oracle Corporation and/or its
+ * affiliates. Other names may be trademarks of their respective owners.
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_db_query.h"
+
+#include <oci.h>
+
+/*
+ * Data types
+ */
+struct o_database_s
+{
+  char *name;
+  char *host;
+  char *connect_id;
+  char *username;
+  char *password;
+
+  udb_query_preparation_area_t **q_prep_areas;
+  udb_query_t **queries;
+  size_t        queries_num;
+
+  OCISvcCtx *oci_service_context;
+};
+typedef struct o_database_s o_database_t;
+
+/*
+ * Global variables
+ */
+static udb_query_t  **queries       = NULL;
+static size_t         queries_num   = 0;
+static o_database_t **databases     = NULL;
+static size_t         databases_num = 0;
+
+OCIEnv   *oci_env = NULL;
+OCIError *oci_error = NULL;
+
+/*
+ * Functions
+ */
+static void o_report_error (const char *where, /* {{{ */
+    const char *db_name, const char *query_name,
+    const char *what, OCIError *eh)
+{
+  char buffer[2048];
+  sb4 error_code;
+  int status;
+  unsigned int record_number;
+
+  if (db_name == NULL)
+    db_name = "(none)";
+  if (query_name == NULL)
+    query_name = "(none)";
+
+  /* An operation may cause / return multiple errors. Loop until we have
+   * handled all errors available (with a fail-save limit of 16). */
+  for (record_number = 1; record_number <= 16; record_number++)
+  {
+    memset (buffer, 0, sizeof (buffer));
+    error_code = -1;
+
+    status = OCIErrorGet (eh, (ub4) record_number,
+        /* sqlstate = */ NULL,
+        &error_code,
+        (text *) &buffer[0],
+        (ub4) sizeof (buffer),
+        OCI_HTYPE_ERROR);
+    buffer[sizeof (buffer) - 1] = 0;
+
+    if (status == OCI_NO_DATA)
+      return;
+
+    if (status == OCI_SUCCESS)
+    {
+      size_t buffer_length;
+
+      buffer_length = strlen (buffer);
+      while ((buffer_length > 0) && (buffer[buffer_length - 1] < 32))
+      {
+        buffer_length--;
+        buffer[buffer_length] = 0;
+      }
+
+      ERROR ("oracle plugin: %s (db = %s, query = %s): %s failed: %s",
+          where, db_name, query_name, what, buffer);
+    }
+    else
+    {
+      ERROR ("oracle plugin: %s (db = %s, query = %s): %s failed. "
+          "Additionally, OCIErrorGet failed with status %i.",
+          where, db_name, query_name, what, status);
+      return;
+    }
+  }
+} /* }}} void o_report_error */
+
+static void o_database_free (o_database_t *db) /* {{{ */
+{
+  size_t i;
+
+  if (db == NULL)
+    return;
+
+  sfree (db->name);
+  sfree (db->connect_id);
+  sfree (db->username);
+  sfree (db->password);
+  sfree (db->queries);
+
+  if (db->q_prep_areas != NULL)
+    for (i = 0; i < db->queries_num; ++i)
+      udb_query_delete_preparation_area (db->q_prep_areas[i]);
+  free (db->q_prep_areas);
+
+  sfree (db);
+} /* }}} void o_database_free */
+
+/* Configuration handling functions {{{
+ *
+ * <Plugin oracle>
+ *   <Query "plugin_instance0">
+ *     Statement "SELECT name, value FROM table"
+ *     <Result>
+ *       Type "gauge"
+ *       InstancesFrom "name"
+ *       ValuesFrom "value"
+ *     </Result>
+ *   </Query>
+ *     
+ *   <Database "plugin_instance1">
+ *     ConnectID "db01"
+ *     Username "oracle"
+ *     Password "secret"
+ *     Query "plugin_instance0"
+ *   </Database>
+ * </Plugin>
+ */
+
+static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
+{
+  o_database_t *db;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("oracle plugin: The `Database' block "
+        "needs exactly one string argument.");
+    return (-1);
+  }
+
+  db = (o_database_t *) malloc (sizeof (*db));
+  if (db == NULL)
+  {
+    ERROR ("oracle plugin: malloc failed.");
+    return (-1);
+  }
+  memset (db, 0, sizeof (*db));
+  db->name = NULL;
+  db->host = NULL;
+  db->connect_id = NULL;
+  db->username = NULL;
+  db->password = NULL;
+
+  status = cf_util_get_string (ci, &db->name);
+  if (status != 0)
+  {
+    sfree (db);
+    return (status);
+  }
+
+  /* Fill the `o_database_t' structure.. */
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("ConnectID", child->key) == 0)
+      status = cf_util_get_string (child, &db->connect_id);
+    else if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &db->host);
+    else if (strcasecmp ("Username", child->key) == 0)
+      status = cf_util_get_string (child, &db->username);
+    else if (strcasecmp ("Password", child->key) == 0)
+      status = cf_util_get_string (child, &db->password);
+    else if (strcasecmp ("Query", child->key) == 0)
+      status = udb_query_pick_from_list (child, queries, queries_num,
+          &db->queries, &db->queries_num);
+    else
+    {
+      WARNING ("oracle plugin: Option `%s' not allowed here.", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Check that all necessary options have been given. */
+  while (status == 0)
+  {
+    if (db->connect_id == NULL)
+    {
+      WARNING ("oracle plugin: `ConnectID' not given for query `%s'", db->name);
+      status = -1;
+    }
+    if (db->username == NULL)
+    {
+      WARNING ("oracle plugin: `Username' not given for query `%s'", db->name);
+      status = -1;
+    }
+    if (db->password == NULL)
+    {
+      WARNING ("oracle plugin: `Password' not given for query `%s'", db->name);
+      status = -1;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  while ((status == 0) && (db->queries_num > 0))
+  {
+    db->q_prep_areas = (udb_query_preparation_area_t **) calloc (
+        db->queries_num, sizeof (*db->q_prep_areas));
+
+    if (db->q_prep_areas == NULL)
+    {
+      WARNING ("oracle plugin: malloc failed");
+      status = -1;
+      break;
+    }
+
+    for (i = 0; i < db->queries_num; ++i)
+    {
+      db->q_prep_areas[i]
+        = udb_query_allocate_preparation_area (db->queries[i]);
+
+      if (db->q_prep_areas[i] == NULL)
+      {
+        WARNING ("oracle plugin: udb_query_allocate_preparation_area failed");
+        status = -1;
+        break;
+      }
+    }
+
+    break;
+  }
+
+  /* If all went well, add this query to the list of queries within the
+   * database structure. */
+  if (status == 0)
+  {
+    o_database_t **temp;
+
+    temp = (o_database_t **) realloc (databases,
+        sizeof (*databases) * (databases_num + 1));
+    if (temp == NULL)
+    {
+      ERROR ("oracle plugin: realloc failed");
+      status = -1;
+    }
+    else
+    {
+      databases = temp;
+      databases[databases_num] = db;
+      databases_num++;
+    }
+  }
+
+  if (status != 0)
+  {
+    o_database_free (db);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int o_config_add_database */
+
+static int o_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp ("Query", child->key) == 0)
+      udb_query_create (&queries, &queries_num, child,
+          /* callback = */ NULL);
+    else if (strcasecmp ("Database", child->key) == 0)
+      o_config_add_database (child);
+    else
+    {
+      WARNING ("oracle plugin: Ignoring unknown config option `%s'.", child->key);
+    }
+
+    if (queries_num > 0)
+    {
+      DEBUG ("oracle plugin: o_config: queries_num = %zu; queries[0] = %p; udb_query_get_user_data (queries[0]) = %p;",
+          queries_num, (void *) queries[0], udb_query_get_user_data (queries[0]));
+    }
+  } /* for (ci->children) */
+
+  return (0);
+} /* }}} int o_config */
+
+/* }}} End of configuration handling functions */
+
+static int o_init (void) /* {{{ */
+{
+  int status;
+
+  if (oci_env != NULL)
+    return (0);
+
+  status = OCIEnvCreate (&oci_env,
+      /* mode = */ OCI_THREADED,
+      /* context        = */ NULL,
+      /* malloc         = */ NULL,
+      /* realloc        = */ NULL,
+      /* free           = */ NULL,
+      /* user_data_size = */ 0,
+      /* user_data_ptr  = */ NULL);
+  if (status != 0)
+  {
+    ERROR ("oracle plugin: OCIEnvCreate failed with status %i.", status);
+    return (-1);
+  }
+
+  status = OCIHandleAlloc (oci_env, (void *) &oci_error, OCI_HTYPE_ERROR,
+      /* user_data_size = */ 0, /* user_data = */ NULL);
+  if (status != OCI_SUCCESS)
+  {
+    ERROR ("oracle plugin: OCIHandleAlloc (OCI_HTYPE_ERROR) failed "
+        "with status %i.", status);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int o_init */
+
+static int o_read_database_query (o_database_t *db, /* {{{ */
+    udb_query_t *q, udb_query_preparation_area_t *prep_area)
+{
+  char **column_names;
+  char **column_values;
+  size_t column_num;
+
+  OCIStmt *oci_statement;
+
+  /* List of `OCIDefine' pointers. These defines map columns to the buffer
+   * space declared above. */
+  OCIDefine **oci_defines;
+
+  int status;
+  size_t i;
+
+  oci_statement = udb_query_get_user_data (q);
+
+  /* Prepare the statement */
+  if (oci_statement == NULL) /* {{{ */
+  {
+    const char *statement;
+
+    statement = udb_query_get_statement (q);
+    assert (statement != NULL);
+
+    status = OCIHandleAlloc (oci_env, (void *) &oci_statement,
+        OCI_HTYPE_STMT, /* user_data_size = */ 0, /* user_data = */ NULL);
+    if (status != OCI_SUCCESS)
+    {
+      o_report_error ("o_read_database_query", db->name,
+          udb_query_get_name (q), "OCIHandleAlloc", oci_error);
+      oci_statement = NULL;
+      return (-1);
+    }
+
+    status = OCIStmtPrepare (oci_statement, oci_error,
+        (text *) statement, (ub4) strlen (statement),
+        /* language = */ OCI_NTV_SYNTAX,
+        /* mode     = */ OCI_DEFAULT);
+    if (status != OCI_SUCCESS)
+    {
+      o_report_error ("o_read_database_query", db->name,
+          udb_query_get_name (q), "OCIStmtPrepare", oci_error);
+      OCIHandleFree (oci_statement, OCI_HTYPE_STMT);
+      oci_statement = NULL;
+      return (-1);
+    }
+    udb_query_set_user_data (q, oci_statement);
+
+    DEBUG ("oracle plugin: o_read_database_query (%s, %s): "
+        "Successfully allocated statement handle.",
+        db->name, udb_query_get_name (q));
+  } /* }}} */
+
+  assert (oci_statement != NULL);
+
+  /* Execute the statement */
+  status = OCIStmtExecute (db->oci_service_context, /* {{{ */
+      oci_statement,
+      oci_error,
+      /* iters = */ 0,
+      /* rowoff = */ 0,
+      /* snap_in = */ NULL, /* snap_out = */ NULL,
+      /* mode = */ OCI_DEFAULT);
+  if (status != OCI_SUCCESS)
+  {
+    o_report_error ("o_read_database_query", db->name, udb_query_get_name (q),
+        "OCIStmtExecute", oci_error);
+    return (-1);
+  } /* }}} */
+
+  /* Acquire the number of columns returned. */
+  do /* {{{ */
+  {
+    ub4 param_counter = 0;
+    status = OCIAttrGet (oci_statement, OCI_HTYPE_STMT, /* {{{ */
+        &param_counter, /* size pointer = */ NULL, 
+        OCI_ATTR_PARAM_COUNT, oci_error);
+    if (status != OCI_SUCCESS)
+    {
+      o_report_error ("o_read_database_query", db->name,
+          udb_query_get_name (q), "OCIAttrGet", oci_error);
+      return (-1);
+    } /* }}} */
+
+    column_num = (size_t) param_counter;
+  } while (0); /* }}} */
+
+  /* Allocate the following buffers:
+   * 
+   *  +---------------+-----------------------------------+
+   *  ! Name          ! Size                              !
+   *  +---------------+-----------------------------------+
+   *  ! column_names  ! column_num x DATA_MAX_NAME_LEN    !
+   *  ! column_values ! column_num x DATA_MAX_NAME_LEN    !
+   *  ! oci_defines   ! column_num x sizeof (OCIDefine *) !
+   *  +---------------+-----------------------------------+
+   *
+   * {{{ */
+#define NUMBER_BUFFER_SIZE 64
+
+#define FREE_ALL \
+  if (column_names != NULL) { \
+    sfree (column_names[0]); \
+    sfree (column_names); \
+  } \
+  if (column_values != NULL) { \
+    sfree (column_values[0]); \
+    sfree (column_values); \
+  } \
+  sfree (oci_defines)
+
+#define ALLOC_OR_FAIL(ptr, ptr_size) \
+  do { \
+    size_t alloc_size = (size_t) ((ptr_size)); \
+    (ptr) = malloc (alloc_size); \
+    if ((ptr) == NULL) { \
+      FREE_ALL; \
+      ERROR ("oracle plugin: o_read_database_query: malloc failed."); \
+      return (-1); \
+    } \
+    memset ((ptr), 0, alloc_size); \
+  } while (0)
+
+  /* Initialize everything to NULL so the above works. */
+  column_names  = NULL;
+  column_values = NULL;
+  oci_defines   = NULL;
+
+  ALLOC_OR_FAIL (column_names, column_num * sizeof (char *));
+  ALLOC_OR_FAIL (column_names[0], column_num * DATA_MAX_NAME_LEN
+      * sizeof (char));
+  for (i = 1; i < column_num; i++)
+    column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;
+
+  ALLOC_OR_FAIL (column_values, column_num * sizeof (char *));
+  ALLOC_OR_FAIL (column_values[0], column_num * DATA_MAX_NAME_LEN
+      * sizeof (char));
+  for (i = 1; i < column_num; i++)
+    column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
+
+  ALLOC_OR_FAIL (oci_defines, column_num * sizeof (OCIDefine *));
+  /* }}} End of buffer allocations. */
+
+  /* ``Define'' the returned data, i. e. bind the columns to the buffers
+   * allocated above. */
+  for (i = 0; i < column_num; i++) /* {{{ */
+  {
+    char *column_name;
+    ub4 column_name_length;
+    OCIParam *oci_param;
+
+    oci_param = NULL;
+
+    status = OCIParamGet (oci_statement, OCI_HTYPE_STMT, oci_error,
+        (void *) &oci_param, (ub4) (i + 1));
+    if (status != OCI_SUCCESS)
+    {
+      /* This is probably alright */
+      DEBUG ("oracle plugin: o_read_database_query: status = %#x (= %i);",
+          status, status);
+      o_report_error ("o_read_database_query", db->name,
+          udb_query_get_name (q), "OCIParamGet", oci_error);
+      status = OCI_SUCCESS;
+      break;
+    }
+
+    column_name = NULL;
+    column_name_length = 0;
+    status = OCIAttrGet (oci_param, OCI_DTYPE_PARAM,
+        &column_name, &column_name_length, OCI_ATTR_NAME, oci_error);
+    if (status != OCI_SUCCESS)
+    {
+      OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
+      o_report_error ("o_read_database_query", db->name,
+          udb_query_get_name (q), "OCIAttrGet (OCI_ATTR_NAME)", oci_error);
+      continue;
+    }
+
+    OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
+    oci_param = NULL;
+
+    /* Copy the name to column_names. Warning: The ``string'' returned by OCI
+     * may not be null terminated! */
+    memset (column_names[i], 0, DATA_MAX_NAME_LEN);
+    if (column_name_length >= DATA_MAX_NAME_LEN)
+      column_name_length = DATA_MAX_NAME_LEN - 1;
+    memcpy (column_names[i], column_name, column_name_length);
+    column_names[i][column_name_length] = 0;
+
+    DEBUG ("oracle plugin: o_read_database_query: column_names[%zu] = %s; "
+        "column_name_length = %"PRIu32";",
+        i, column_names[i], (uint32_t) column_name_length);
+
+    status = OCIDefineByPos (oci_statement,
+        &oci_defines[i], oci_error, (ub4) (i + 1),
+        column_values[i], DATA_MAX_NAME_LEN, SQLT_STR,
+        NULL, NULL, NULL, OCI_DEFAULT);
+    if (status != OCI_SUCCESS)
+    {
+      o_report_error ("o_read_database_query", db->name,
+          udb_query_get_name (q), "OCIDefineByPos", oci_error);
+      continue;
+    }
+  } /* for (j = 1; j <= param_counter; j++) */
+  /* }}} End of the ``define'' stuff. */
+
+  status = udb_query_prepare_result (q, prep_area,
+      (db->host != NULL) ? db->host : hostname_g,
+      /* plugin = */ "oracle", db->name, column_names, column_num,
+      /* interval = */ 0);
+  if (status != 0)
+  {
+    ERROR ("oracle plugin: o_read_database_query (%s, %s): "
+        "udb_query_prepare_result failed.",
+        db->name, udb_query_get_name (q));
+    FREE_ALL;
+    return (-1);
+  }
+
+  /* Fetch and handle all the rows that matched the query. */
+  while (42) /* {{{ */
+  {
+    status = OCIStmtFetch2 (oci_statement, oci_error,
+        /* nrows = */ 1, /* orientation = */ OCI_FETCH_NEXT,
+        /* fetch offset = */ 0, /* mode = */ OCI_DEFAULT);
+    if (status == OCI_NO_DATA)
+    {
+      status = OCI_SUCCESS;
+      break;
+    }
+    else if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO))
+    {
+      o_report_error ("o_read_database_query", db->name,
+          udb_query_get_name (q), "OCIStmtFetch2", oci_error);
+      break;
+    }
+
+    status = udb_query_handle_result (q, prep_area, column_values);
+    if (status != 0)
+    {
+      WARNING ("oracle plugin: o_read_database_query (%s, %s): "
+          "udb_query_handle_result failed.",
+          db->name, udb_query_get_name (q));
+    }
+  } /* }}} while (42) */
+
+  /* DEBUG ("oracle plugin: o_read_database_query: This statement succeeded: %s", q->statement); */
+  FREE_ALL;
+
+  return (0);
+#undef FREE_ALL
+#undef ALLOC_OR_FAIL
+} /* }}} int o_read_database_query */
+
+static int o_read_database (o_database_t *db) /* {{{ */
+{
+  size_t i;
+  int status;
+
+  if (db->oci_service_context != NULL)
+  {
+    OCIServer *server_handle;
+    ub4 connection_status;
+
+    server_handle = NULL;
+    status = OCIAttrGet ((void *) db->oci_service_context, OCI_HTYPE_SVCCTX, 
+        (void *) &server_handle, /* size pointer = */ NULL,
+        OCI_ATTR_SERVER, oci_error);
+    if (status != OCI_SUCCESS)
+    {
+      o_report_error ("o_read_database", db->name, NULL, "OCIAttrGet",
+          oci_error);
+      return (-1);
+    }
+
+    if (server_handle == NULL)
+    {
+      connection_status = OCI_SERVER_NOT_CONNECTED;
+    }
+    else /* if (server_handle != NULL) */
+    {
+      connection_status = 0;
+      status = OCIAttrGet ((void *) server_handle, OCI_HTYPE_SERVER,
+          (void *) &connection_status, /* size pointer = */ NULL,
+          OCI_ATTR_SERVER_STATUS, oci_error);
+      if (status != OCI_SUCCESS)
+      {
+        o_report_error ("o_read_database", db->name, NULL, "OCIAttrGet",
+            oci_error);
+        return (-1);
+      }
+    }
+
+    if (connection_status != OCI_SERVER_NORMAL)
+    {
+      INFO ("oracle plugin: Connection to %s lost. Trying to reconnect.",
+          db->name);
+      OCIHandleFree (db->oci_service_context, OCI_HTYPE_SVCCTX);
+      db->oci_service_context = NULL;
+    }
+  } /* if (db->oci_service_context != NULL) */
+
+  if (db->oci_service_context == NULL)
+  {
+    status = OCILogon (oci_env, oci_error,
+        &db->oci_service_context,
+        (OraText *) db->username, (ub4) strlen (db->username),
+        (OraText *) db->password, (ub4) strlen (db->password),
+        (OraText *) db->connect_id, (ub4) strlen (db->connect_id));
+    if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO))
+    {
+      char errfunc[256];
+
+      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;",
+          db->connect_id, db->oci_service_context);
+      db->oci_service_context = NULL;
+      return (-1);
+    }
+    else if (status == OCI_SUCCESS_WITH_INFO)
+    {
+      /* TODO: Print NOTIFY message. */
+    }
+    assert (db->oci_service_context != NULL);
+  }
+
+  DEBUG ("oracle plugin: o_read_database: db->connect_id = %s; db->oci_service_context = %p;",
+      db->connect_id, db->oci_service_context);
+
+  for (i = 0; i < db->queries_num; i++)
+    o_read_database_query (db, db->queries[i], db->q_prep_areas[i]);
+
+  return (0);
+} /* }}} int o_read_database */
+
+static int o_read (void) /* {{{ */
+{
+  size_t i;
+
+  for (i = 0; i < databases_num; i++)
+    o_read_database (databases[i]);
+
+  return (0);
+} /* }}} int o_read */
+
+static int o_shutdown (void) /* {{{ */
+{
+  size_t i;
+
+  for (i = 0; i < databases_num; i++)
+    if (databases[i]->oci_service_context != NULL)
+    {
+      OCIHandleFree (databases[i]->oci_service_context, OCI_HTYPE_SVCCTX);
+      databases[i]->oci_service_context = NULL;
+    }
+  
+  for (i = 0; i < queries_num; i++)
+  {
+    OCIStmt *oci_statement;
+
+    oci_statement = udb_query_get_user_data (queries[i]);
+    if (oci_statement != NULL)
+    {
+      OCIHandleFree (oci_statement, OCI_HTYPE_STMT);
+      udb_query_set_user_data (queries[i], NULL);
+    }
+  }
+  
+  OCIHandleFree (oci_env, OCI_HTYPE_ENV);
+  oci_env = NULL;
+
+  udb_query_free (queries, queries_num);
+  queries = NULL;
+  queries_num = 0;
+
+  return (0);
+} /* }}} int o_shutdown */
+
+void module_register (void) /* {{{ */
+{
+  plugin_register_complex_config ("oracle", o_config);
+  plugin_register_init ("oracle", o_init);
+  plugin_register_read ("oracle", o_read);
+  plugin_register_shutdown ("oracle", o_shutdown);
+} /* }}} void module_register */
+
+/*
+ * vim: shiftwidth=2 softtabstop=2 et fdm=marker
+ */
diff --git a/src/perl.c b/src/perl.c
new file mode 100644 (file)
index 0000000..cc8faeb
--- /dev/null
@@ -0,0 +1,2566 @@
+/**
+ * collectd - src/perl.c
+ * Copyright (C) 2007-2009  Sebastian Harl
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This plugin embeds a Perl interpreter into collectd and provides an
+ * interface for collectd plugins written in perl.
+ */
+
+/* do not automatically get the thread specific perl interpreter */
+#define PERL_NO_GET_CONTEXT
+
+#define DONT_POISON_SPRINTF_YET 1
+#include "collectd.h"
+#undef DONT_POISON_SPRINTF_YET
+
+#include "configfile.h"
+
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#endif
+
+#include <EXTERN.h>
+#include <perl.h>
+
+#if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
+# undef sprintf
+# pragma GCC poison sprintf
+#endif
+
+#include <XSUB.h>
+
+/* Some versions of Perl define their own version of DEBUG... :-/ */
+#ifdef DEBUG
+# undef DEBUG
+#endif /* DEBUG */
+
+/* ... while we want the definition found in plugin.h. */
+#include "plugin.h"
+#include "common.h"
+
+#include "filter_chain.h"
+
+#include <pthread.h>
+
+#if !defined(USE_ITHREADS)
+# error "Perl does not support ithreads!"
+#endif /* !defined(USE_ITHREADS) */
+
+/* clear the Perl sub's stack frame
+ * (this should only be used inside an XSUB) */
+#define CLEAR_STACK_FRAME PL_stack_sp = PL_stack_base + *PL_markstack_ptr
+
+#define PLUGIN_INIT     0
+#define PLUGIN_READ     1
+#define PLUGIN_WRITE    2
+#define PLUGIN_SHUTDOWN 3
+#define PLUGIN_LOG      4
+#define PLUGIN_NOTIF    5
+#define PLUGIN_FLUSH    6
+
+#define PLUGIN_TYPES    7
+
+#define PLUGIN_CONFIG   254
+#define PLUGIN_DATASET  255
+
+#define FC_MATCH  0
+#define FC_TARGET 1
+
+#define FC_TYPES  2
+
+#define FC_CB_CREATE  0
+#define FC_CB_DESTROY 1
+#define FC_CB_EXEC    2
+
+#define FC_CB_TYPES   3
+
+#define log_debug(...) DEBUG ("perl: " __VA_ARGS__)
+#define log_info(...) INFO ("perl: " __VA_ARGS__)
+#define log_warn(...) WARNING ("perl: " __VA_ARGS__)
+#define log_err(...) ERROR ("perl: " __VA_ARGS__)
+
+/* this is defined in DynaLoader.a */
+void boot_DynaLoader (PerlInterpreter *, CV *);
+
+static XS (Collectd_plugin_register_ds);
+static XS (Collectd_plugin_unregister_ds);
+static XS (Collectd_plugin_dispatch_values);
+static XS (Collectd_plugin_get_interval);
+static XS (Collectd__plugin_write);
+static XS (Collectd__plugin_flush);
+static XS (Collectd_plugin_dispatch_notification);
+static XS (Collectd_plugin_log);
+static XS (Collectd__fc_register);
+static XS (Collectd_call_by_name);
+
+/*
+ * private data types
+ */
+
+typedef struct c_ithread_s {
+       /* the thread's Perl interpreter */
+       PerlInterpreter *interp;
+
+       /* double linked list of threads */
+       struct c_ithread_s *prev;
+       struct c_ithread_s *next;
+} c_ithread_t;
+
+typedef struct {
+       c_ithread_t *head;
+       c_ithread_t *tail;
+
+#if COLLECT_DEBUG
+       /* some usage stats */
+       int number_of_threads;
+#endif /* COLLECT_DEBUG */
+
+       pthread_mutex_t mutex;
+} c_ithread_list_t;
+
+/* name / user_data for Perl matches / targets */
+typedef struct {
+       char *name;
+       SV   *user_data;
+} pfc_user_data_t;
+
+#define PFC_USER_DATA_FREE(data) \
+       do { \
+               sfree ((data)->name); \
+               if (NULL != (data)->user_data) \
+                       sv_free ((data)->user_data); \
+               sfree (data); \
+       } while (0)
+
+/*
+ * Public variable
+ */
+extern char **environ;
+
+/*
+ * private variables
+ */
+
+/* if perl_threads != NULL perl_threads->head must
+ * point to the "base" thread */
+static c_ithread_list_t *perl_threads = NULL;
+
+/* the key used to store each pthread's ithread */
+static pthread_key_t perl_thr_key;
+
+static int    perl_argc = 0;
+static char **perl_argv = NULL;
+
+static char base_name[DATA_MAX_NAME_LEN] = "";
+
+static struct {
+       char name[64];
+       XS ((*f));
+} api[] =
+{
+       { "Collectd::plugin_register_data_set",   Collectd_plugin_register_ds },
+       { "Collectd::plugin_unregister_data_set", Collectd_plugin_unregister_ds },
+       { "Collectd::plugin_dispatch_values",     Collectd_plugin_dispatch_values },
+       { "Collectd::plugin_get_interval",        Collectd_plugin_get_interval },
+       { "Collectd::_plugin_write",              Collectd__plugin_write },
+       { "Collectd::_plugin_flush",              Collectd__plugin_flush },
+       { "Collectd::plugin_dispatch_notification",
+               Collectd_plugin_dispatch_notification },
+       { "Collectd::plugin_log",                 Collectd_plugin_log },
+       { "Collectd::_fc_register",               Collectd__fc_register },
+       { "Collectd::call_by_name",               Collectd_call_by_name },
+       { "", NULL }
+};
+
+struct {
+       char name[64];
+       int  value;
+} constants[] =
+{
+       { "Collectd::TYPE_INIT",          PLUGIN_INIT },
+       { "Collectd::TYPE_READ",          PLUGIN_READ },
+       { "Collectd::TYPE_WRITE",         PLUGIN_WRITE },
+       { "Collectd::TYPE_SHUTDOWN",      PLUGIN_SHUTDOWN },
+       { "Collectd::TYPE_LOG",           PLUGIN_LOG },
+       { "Collectd::TYPE_NOTIF",         PLUGIN_NOTIF },
+       { "Collectd::TYPE_FLUSH",         PLUGIN_FLUSH },
+       { "Collectd::TYPE_CONFIG",        PLUGIN_CONFIG },
+       { "Collectd::TYPE_DATASET",       PLUGIN_DATASET },
+       { "Collectd::DS_TYPE_COUNTER",    DS_TYPE_COUNTER },
+       { "Collectd::DS_TYPE_GAUGE",      DS_TYPE_GAUGE },
+       { "Collectd::DS_TYPE_DERIVE",     DS_TYPE_DERIVE },
+       { "Collectd::DS_TYPE_ABSOLUTE",   DS_TYPE_ABSOLUTE },
+       { "Collectd::LOG_ERR",            LOG_ERR },
+       { "Collectd::LOG_WARNING",        LOG_WARNING },
+       { "Collectd::LOG_NOTICE",         LOG_NOTICE },
+       { "Collectd::LOG_INFO",           LOG_INFO },
+       { "Collectd::LOG_DEBUG",          LOG_DEBUG },
+       { "Collectd::FC_MATCH",           FC_MATCH },
+       { "Collectd::FC_TARGET",          FC_TARGET },
+       { "Collectd::FC_CB_CREATE",       FC_CB_CREATE },
+       { "Collectd::FC_CB_DESTROY",      FC_CB_DESTROY },
+       { "Collectd::FC_CB_EXEC",         FC_CB_EXEC },
+       { "Collectd::FC_MATCH_NO_MATCH",  FC_MATCH_NO_MATCH },
+       { "Collectd::FC_MATCH_MATCHES",   FC_MATCH_MATCHES },
+       { "Collectd::FC_TARGET_CONTINUE", FC_TARGET_CONTINUE },
+       { "Collectd::FC_TARGET_STOP",     FC_TARGET_STOP },
+       { "Collectd::FC_TARGET_RETURN",   FC_TARGET_RETURN },
+       { "Collectd::NOTIF_FAILURE",      NOTIF_FAILURE },
+       { "Collectd::NOTIF_WARNING",      NOTIF_WARNING },
+       { "Collectd::NOTIF_OKAY",         NOTIF_OKAY },
+       { "", 0 }
+};
+
+struct {
+       char  name[64];
+       char *var;
+} g_strings[] =
+{
+       { "Collectd::hostname_g", hostname_g },
+       { "", NULL }
+};
+
+/*
+ * Helper functions for data type conversion.
+ */
+
+/*
+ * data source:
+ * [
+ *   {
+ *     name => $ds_name,
+ *     type => $ds_type,
+ *     min  => $ds_min,
+ *     max  => $ds_max
+ *   },
+ *   ...
+ * ]
+ */
+static int hv2data_source (pTHX_ HV *hash, data_source_t *ds)
+{
+       SV **tmp = NULL;
+
+       if ((NULL == hash) || (NULL == ds))
+               return -1;
+
+       if (NULL != (tmp = hv_fetch (hash, "name", 4, 0))) {
+               sstrncpy (ds->name, SvPV_nolen (*tmp), sizeof (ds->name));
+       }
+       else {
+               log_err ("hv2data_source: No DS name given.");
+               return -1;
+       }
+
+       if (NULL != (tmp = hv_fetch (hash, "type", 4, 0))) {
+               ds->type = SvIV (*tmp);
+
+               if ((DS_TYPE_COUNTER != ds->type)
+                               && (DS_TYPE_GAUGE != ds->type)
+                               && (DS_TYPE_DERIVE != ds->type)
+                               && (DS_TYPE_ABSOLUTE != ds->type)) {
+                       log_err ("hv2data_source: Invalid DS type.");
+                       return -1;
+               }
+       }
+       else {
+               ds->type = DS_TYPE_COUNTER;
+       }
+
+       if (NULL != (tmp = hv_fetch (hash, "min", 3, 0)))
+               ds->min = SvNV (*tmp);
+       else
+               ds->min = NAN;
+
+       if (NULL != (tmp = hv_fetch (hash, "max", 3, 0)))
+               ds->max = SvNV (*tmp);
+       else
+               ds->max = NAN;
+       return 0;
+} /* static int hv2data_source (HV *, data_source_t *) */
+
+static int av2value (pTHX_ char *name, AV *array, value_t *value, int len)
+{
+       const data_set_t *ds;
+
+       int i = 0;
+
+       if ((NULL == name) || (NULL == array) || (NULL == value))
+               return -1;
+
+       if (av_len (array) < len - 1)
+               len = av_len (array) + 1;
+
+       if (0 >= len)
+               return -1;
+
+       ds = plugin_get_ds (name);
+       if (NULL == ds) {
+               log_err ("av2value: Unknown dataset \"%s\"", name);
+               return -1;
+       }
+
+       if (ds->ds_num < len) {
+               log_warn ("av2value: Value length exceeds data set length.");
+               len = ds->ds_num;
+       }
+
+       for (i = 0; i < len; ++i) {
+               SV **tmp = av_fetch (array, i, 0);
+
+               if (NULL != tmp) {
+                       if (DS_TYPE_COUNTER == ds->ds[i].type)
+                               value[i].counter = SvIV (*tmp);
+                       else if (DS_TYPE_GAUGE == ds->ds[i].type)
+                               value[i].gauge = SvNV (*tmp);
+                       else if (DS_TYPE_DERIVE == ds->ds[i].type)
+                               value[i].derive = SvIV (*tmp);
+                       else if (DS_TYPE_ABSOLUTE == ds->ds[i].type)
+                               value[i].absolute = SvIV (*tmp);
+               }
+               else {
+                       return -1;
+               }
+       }
+       return len;
+} /* static int av2value (char *, AV *, value_t *, int) */
+
+/*
+ * value list:
+ * {
+ *   values => [ @values ],
+ *   time   => $time,
+ *   host   => $host,
+ *   plugin => $plugin,
+ *   plugin_instance => $pinstance,
+ *   type_instance   => $tinstance,
+ * }
+ */
+static int hv2value_list (pTHX_ HV *hash, value_list_t *vl)
+{
+       SV **tmp;
+
+       if ((NULL == hash) || (NULL == vl))
+               return -1;
+
+       if (NULL == (tmp = hv_fetch (hash, "type", 4, 0))) {
+               log_err ("hv2value_list: No type given.");
+               return -1;
+       }
+
+       sstrncpy (vl->type, SvPV_nolen (*tmp), sizeof (vl->type));
+
+       if ((NULL == (tmp = hv_fetch (hash, "values", 6, 0)))
+                       || (! (SvROK (*tmp) && (SVt_PVAV == SvTYPE (SvRV (*tmp)))))) {
+               log_err ("hv2value_list: No valid values given.");
+               return -1;
+       }
+
+       {
+               AV  *array = (AV *)SvRV (*tmp);
+               int len    = av_len (array) + 1;
+
+               if (len <= 0)
+                       return -1;
+
+               vl->values     = (value_t *)smalloc (len * sizeof (value_t));
+               vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp),
+                               vl->values, len);
+
+               if (-1 == vl->values_len) {
+                       sfree (vl->values);
+                       return -1;
+               }
+       }
+
+       if (NULL != (tmp = hv_fetch (hash, "time", 4, 0)))
+       {
+               double t = SvNV (*tmp);
+               vl->time = DOUBLE_TO_CDTIME_T (t);
+       }
+
+       if (NULL != (tmp = hv_fetch (hash, "interval", 8, 0)))
+       {
+               double t = SvNV (*tmp);
+               vl->interval = DOUBLE_TO_CDTIME_T (t);
+       }
+
+       if (NULL != (tmp = hv_fetch (hash, "host", 4, 0)))
+               sstrncpy (vl->host, SvPV_nolen (*tmp), sizeof (vl->host));
+       else
+               sstrncpy (vl->host, hostname_g, sizeof (vl->host));
+
+       if (NULL != (tmp = hv_fetch (hash, "plugin", 6, 0)))
+               sstrncpy (vl->plugin, SvPV_nolen (*tmp), sizeof (vl->plugin));
+
+       if (NULL != (tmp = hv_fetch (hash, "plugin_instance", 15, 0)))
+               sstrncpy (vl->plugin_instance, SvPV_nolen (*tmp),
+                               sizeof (vl->plugin_instance));
+
+       if (NULL != (tmp = hv_fetch (hash, "type_instance", 13, 0)))
+               sstrncpy (vl->type_instance, SvPV_nolen (*tmp),
+                               sizeof (vl->type_instance));
+       return 0;
+} /* static int hv2value_list (pTHX_ HV *, value_list_t *) */
+
+static int av2data_set (pTHX_ AV *array, char *name, data_set_t *ds)
+{
+       int len, i;
+
+       if ((NULL == array) || (NULL == name) || (NULL == ds))
+               return -1;
+
+       len = av_len (array);
+
+       if (-1 == len) {
+               log_err ("av2data_set: Invalid data set.");
+               return -1;
+       }
+
+       ds->ds = (data_source_t *)smalloc ((len + 1) * sizeof (data_source_t));
+       ds->ds_num = len + 1;
+
+       for (i = 0; i <= len; ++i) {
+               SV **elem = av_fetch (array, i, 0);
+
+               if (NULL == elem) {
+                       log_err ("av2data_set: Failed to fetch data source %i.", i);
+                       return -1;
+               }
+
+               if (! (SvROK (*elem) && (SVt_PVHV == SvTYPE (SvRV (*elem))))) {
+                       log_err ("av2data_set: Invalid data source.");
+                       return -1;
+               }
+
+               if (-1 == hv2data_source (aTHX_ (HV *)SvRV (*elem), &ds->ds[i]))
+                       return -1;
+
+               log_debug ("av2data_set: "
+                               "DS.name = \"%s\", DS.type = %i, DS.min = %f, DS.max = %f",
+                               ds->ds[i].name, ds->ds[i].type, ds->ds[i].min, ds->ds[i].max);
+       }
+
+       sstrncpy (ds->type, name, sizeof (ds->type));
+       return 0;
+} /* static int av2data_set (pTHX_ AV *, data_set_t *) */
+
+/*
+ * notification:
+ * {
+ *   severity => $severity,
+ *   time     => $time,
+ *   message  => $msg,
+ *   host     => $host,
+ *   plugin   => $plugin,
+ *   type     => $type,
+ *   plugin_instance => $instance,
+ *   type_instance   => $type_instance,
+ *   meta     => [ { name => <name>, value => <value> }, ... ]
+ * }
+ */
+static int av2notification_meta (pTHX_ AV *array, notification_meta_t **meta)
+{
+       notification_meta_t **m = meta;
+
+       int len = av_len (array);
+       int i;
+
+       for (i = 0; i <= len; ++i) {
+               SV **tmp = av_fetch (array, i, 0);
+               HV  *hash;
+
+               if (NULL == tmp)
+                       return -1;
+
+               if (! (SvROK (*tmp) && (SVt_PVHV == SvTYPE (SvRV (*tmp))))) {
+                       log_warn ("av2notification_meta: Skipping invalid "
+                                       "meta information.");
+                       continue;
+               }
+
+               hash = (HV *)SvRV (*tmp);
+
+               *m = (notification_meta_t *)smalloc (sizeof (**m));
+
+               if (NULL == (tmp = hv_fetch (hash, "name", 4, 0))) {
+                       log_warn ("av2notification_meta: Skipping invalid "
+                                       "meta information.");
+                       free (*m);
+                       continue;
+               }
+               sstrncpy ((*m)->name, SvPV_nolen (*tmp), sizeof ((*m)->name));
+
+               if (NULL == (tmp = hv_fetch (hash, "value", 5, 0))) {
+                       log_warn ("av2notification_meta: Skipping invalid "
+                                       "meta information.");
+                       free ((*m)->name);
+                       free (*m);
+                       continue;
+               }
+
+               if (SvNOK (*tmp)) {
+                       (*m)->nm_value.nm_double = SvNVX (*tmp);
+                       (*m)->type = NM_TYPE_DOUBLE;
+               }
+               else if (SvUOK (*tmp)) {
+                       (*m)->nm_value.nm_unsigned_int = SvUVX (*tmp);
+                       (*m)->type = NM_TYPE_UNSIGNED_INT;
+               }
+               else if (SvIOK (*tmp)) {
+                       (*m)->nm_value.nm_signed_int = SvIVX (*tmp);
+                       (*m)->type = NM_TYPE_SIGNED_INT;
+               }
+               else {
+                       (*m)->nm_value.nm_string = sstrdup (SvPV_nolen (*tmp));
+                       (*m)->type = NM_TYPE_STRING;
+               }
+
+               (*m)->next = NULL;
+               m = &((*m)->next);
+       }
+       return 0;
+} /* static int av2notification_meta (AV *, notification_meta_t *) */
+
+static int hv2notification (pTHX_ HV *hash, notification_t *n)
+{
+       SV **tmp = NULL;
+
+       if ((NULL == hash) || (NULL == n))
+               return -1;
+
+       if (NULL != (tmp = hv_fetch (hash, "severity", 8, 0)))
+               n->severity = SvIV (*tmp);
+       else
+               n->severity = NOTIF_FAILURE;
+
+       if (NULL != (tmp = hv_fetch (hash, "time", 4, 0)))
+       {
+               double t = SvNV (*tmp);
+               n->time = DOUBLE_TO_CDTIME_T (t);
+       }
+       else
+               n->time = cdtime ();
+
+       if (NULL != (tmp = hv_fetch (hash, "message", 7, 0)))
+               sstrncpy (n->message, SvPV_nolen (*tmp), sizeof (n->message));
+
+       if (NULL != (tmp = hv_fetch (hash, "host", 4, 0)))
+               sstrncpy (n->host, SvPV_nolen (*tmp), sizeof (n->host));
+       else
+               sstrncpy (n->host, hostname_g, sizeof (n->host));
+
+       if (NULL != (tmp = hv_fetch (hash, "plugin", 6, 0)))
+               sstrncpy (n->plugin, SvPV_nolen (*tmp), sizeof (n->plugin));
+
+       if (NULL != (tmp = hv_fetch (hash, "plugin_instance", 15, 0)))
+               sstrncpy (n->plugin_instance, SvPV_nolen (*tmp),
+                               sizeof (n->plugin_instance));
+
+       if (NULL != (tmp = hv_fetch (hash, "type", 4, 0)))
+               sstrncpy (n->type, SvPV_nolen (*tmp), sizeof (n->type));
+
+       if (NULL != (tmp = hv_fetch (hash, "type_instance", 13, 0)))
+               sstrncpy (n->type_instance, SvPV_nolen (*tmp),
+                               sizeof (n->type_instance));
+
+       n->meta = NULL;
+       while (NULL != (tmp = hv_fetch (hash, "meta", 4, 0))) {
+               if (! (SvROK (*tmp) && (SVt_PVAV == SvTYPE (SvRV (*tmp))))) {
+                       log_warn ("hv2notification: Ignoring invalid meta information.");
+                       break;
+               }
+
+               if (0 != av2notification_meta (aTHX_ (AV *)SvRV (*tmp), &n->meta)) {
+                       plugin_notification_meta_free (n->meta);
+                       n->meta = NULL;
+                       return -1;
+               }
+               break;
+       }
+       return 0;
+} /* static int hv2notification (pTHX_ HV *, notification_t *) */
+
+static int data_set2av (pTHX_ data_set_t *ds, AV *array)
+{
+       int i = 0;
+
+       if ((NULL == ds) || (NULL == array))
+               return -1;
+
+       av_extend (array, ds->ds_num);
+
+       for (i = 0; i < ds->ds_num; ++i) {
+               HV *source = newHV ();
+
+               if (NULL == hv_store (source, "name", 4,
+                               newSVpv (ds->ds[i].name, 0), 0))
+                       return -1;
+
+               if (NULL == hv_store (source, "type", 4, newSViv (ds->ds[i].type), 0))
+                       return -1;
+
+               if (! isnan (ds->ds[i].min))
+                       if (NULL == hv_store (source, "min", 3,
+                                       newSVnv (ds->ds[i].min), 0))
+                               return -1;
+
+               if (! isnan (ds->ds[i].max))
+                       if (NULL == hv_store (source, "max", 3,
+                                       newSVnv (ds->ds[i].max), 0))
+                               return -1;
+
+               if (NULL == av_store (array, i, newRV_noinc ((SV *)source)))
+                       return -1;
+       }
+       return 0;
+} /* static int data_set2av (data_set_t *, AV *) */
+
+static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash)
+{
+       AV *values = NULL;
+
+       int i   = 0;
+       int len = 0;
+
+       if ((NULL == vl) || (NULL == ds) || (NULL == hash))
+               return -1;
+
+       len = vl->values_len;
+
+       if (ds->ds_num < len) {
+               log_warn ("value2av: Value length exceeds data set length.");
+               len = ds->ds_num;
+       }
+
+       values = newAV ();
+       av_extend (values, len - 1);
+
+       for (i = 0; i < len; ++i) {
+               SV *val = NULL;
+
+               if (DS_TYPE_COUNTER == ds->ds[i].type)
+                       val = newSViv (vl->values[i].counter);
+               else if (DS_TYPE_GAUGE == ds->ds[i].type)
+                       val = newSVnv (vl->values[i].gauge);
+               else if (DS_TYPE_DERIVE == ds->ds[i].type)
+                       val = newSViv (vl->values[i].derive);
+               else if (DS_TYPE_ABSOLUTE == ds->ds[i].type)
+                       val = newSViv (vl->values[i].absolute);
+
+               if (NULL == av_store (values, i, val)) {
+                       av_undef (values);
+                       return -1;
+               }
+       }
+
+       if (NULL == hv_store (hash, "values", 6, newRV_noinc ((SV *)values), 0))
+               return -1;
+
+       if (0 != vl->time)
+       {
+               double t = CDTIME_T_TO_DOUBLE (vl->time);
+               if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0))
+                       return -1;
+       }
+
+       {
+               double t = CDTIME_T_TO_DOUBLE (vl->interval);
+               if (NULL == hv_store (hash, "interval", 8, newSVnv (t), 0))
+                       return -1;
+       }
+
+       if ('\0' != vl->host[0])
+               if (NULL == hv_store (hash, "host", 4, newSVpv (vl->host, 0), 0))
+                       return -1;
+
+       if ('\0' != vl->plugin[0])
+               if (NULL == hv_store (hash, "plugin", 6, newSVpv (vl->plugin, 0), 0))
+                       return -1;
+
+       if ('\0' != vl->plugin_instance[0])
+               if (NULL == hv_store (hash, "plugin_instance", 15,
+                               newSVpv (vl->plugin_instance, 0), 0))
+                       return -1;
+
+       if ('\0' != vl->type[0])
+               if (NULL == hv_store (hash, "type", 4, newSVpv (vl->type, 0), 0))
+                       return -1;
+
+       if ('\0' != vl->type_instance[0])
+               if (NULL == hv_store (hash, "type_instance", 13,
+                               newSVpv (vl->type_instance, 0), 0))
+                       return -1;
+       return 0;
+} /* static int value2av (value_list_t *, data_set_t *, HV *) */
+
+static int notification_meta2av (pTHX_ notification_meta_t *meta, AV *array)
+{
+       int meta_num = 0;
+       int i;
+
+       while (meta) {
+               ++meta_num;
+               meta = meta->next;
+       }
+
+       av_extend (array, meta_num);
+
+       for (i = 0; NULL != meta; meta = meta->next, ++i) {
+               HV *m = newHV ();
+               SV *value;
+
+               if (NULL == hv_store (m, "name", 4, newSVpv (meta->name, 0), 0))
+                       return -1;
+
+               if (NM_TYPE_STRING == meta->type)
+                       value = newSVpv (meta->nm_value.nm_string, 0);
+               else if (NM_TYPE_SIGNED_INT == meta->type)
+                       value = newSViv (meta->nm_value.nm_signed_int);
+               else if (NM_TYPE_UNSIGNED_INT == meta->type)
+                       value = newSVuv (meta->nm_value.nm_unsigned_int);
+               else if (NM_TYPE_DOUBLE == meta->type)
+                       value = newSVnv (meta->nm_value.nm_double);
+               else if (NM_TYPE_BOOLEAN == meta->type)
+                       value = meta->nm_value.nm_boolean ? &PL_sv_yes : &PL_sv_no;
+               else
+                       return -1;
+
+               if (NULL == hv_store (m, "value", 5, value, 0)) {
+                       sv_free (value);
+                       return -1;
+               }
+
+               if (NULL == av_store (array, i, newRV_noinc ((SV *)m))) {
+                       hv_clear (m);
+                       hv_undef (m);
+                       return -1;
+               }
+       }
+       return 0;
+} /* static int notification_meta2av (notification_meta_t *, AV *) */
+
+static int notification2hv (pTHX_ notification_t *n, HV *hash)
+{
+       if (NULL == hv_store (hash, "severity", 8, newSViv (n->severity), 0))
+               return -1;
+
+       if (0 != n->time)
+       {
+               double t = CDTIME_T_TO_DOUBLE (n->time);
+               if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0))
+                       return -1;
+       }
+
+       if ('\0' != *n->message)
+               if (NULL == hv_store (hash, "message", 7, newSVpv (n->message, 0), 0))
+                       return -1;
+
+       if ('\0' != *n->host)
+               if (NULL == hv_store (hash, "host", 4, newSVpv (n->host, 0), 0))
+                       return -1;
+
+       if ('\0' != *n->plugin)
+               if (NULL == hv_store (hash, "plugin", 6, newSVpv (n->plugin, 0), 0))
+                       return -1;
+
+       if ('\0' != *n->plugin_instance)
+               if (NULL == hv_store (hash, "plugin_instance", 15,
+                               newSVpv (n->plugin_instance, 0), 0))
+                       return -1;
+
+       if ('\0' != *n->type)
+               if (NULL == hv_store (hash, "type", 4, newSVpv (n->type, 0), 0))
+                       return -1;
+
+       if ('\0' != *n->type_instance)
+               if (NULL == hv_store (hash, "type_instance", 13,
+                               newSVpv (n->type_instance, 0), 0))
+                       return -1;
+
+       if (NULL != n->meta) {
+               AV *meta = newAV ();
+               if ((0 != notification_meta2av (aTHX_ n->meta, meta))
+                               || (NULL == hv_store (hash, "meta", 4,
+                                               newRV_noinc ((SV *)meta), 0))) {
+                       av_clear (meta);
+                       av_undef (meta);
+                       return -1;
+               }
+       }
+       return 0;
+} /* static int notification2hv (notification_t *, HV *) */
+
+static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash)
+{
+       int i;
+
+       AV *values;
+       AV *children;
+
+       if (NULL == hv_store (hash, "key", 3, newSVpv (ci->key, 0), 0))
+               return -1;
+
+       values = newAV ();
+       if (0 < ci->values_num)
+               av_extend (values, ci->values_num);
+
+       if (NULL == hv_store (hash, "values", 6, newRV_noinc ((SV *)values), 0)) {
+               av_clear (values);
+               av_undef (values);
+               return -1;
+       }
+
+       for (i = 0; i < ci->values_num; ++i) {
+               SV *value;
+
+               switch (ci->values[i].type) {
+                       case OCONFIG_TYPE_STRING:
+                               value = newSVpv (ci->values[i].value.string, 0);
+                               break;
+                       case OCONFIG_TYPE_NUMBER:
+                               value = newSVnv ((NV)ci->values[i].value.number);
+                               break;
+                       case OCONFIG_TYPE_BOOLEAN:
+                               value = ci->values[i].value.boolean ? &PL_sv_yes : &PL_sv_no;
+                               break;
+                       default:
+                               log_err ("oconfig_item2hv: Invalid value type %i.",
+                                               ci->values[i].type);
+                               value = &PL_sv_undef;
+               }
+
+               if (NULL == av_store (values, i, value)) {
+                       sv_free (value);
+                       return -1;
+               }
+       }
+
+       /* ignoring 'parent' member which is uninteresting in this case */
+
+       children = newAV ();
+       if (0 < ci->children_num)
+               av_extend (children, ci->children_num);
+
+       if (NULL == hv_store (hash, "children", 8, newRV_noinc ((SV *)children), 0)) {
+               av_clear (children);
+               av_undef (children);
+               return -1;
+       }
+
+       for (i = 0; i < ci->children_num; ++i) {
+               HV *child = newHV ();
+
+               if (0 != oconfig_item2hv (aTHX_ ci->children + i, child)) {
+                       hv_clear (child);
+                       hv_undef (child);
+                       return -1;
+               }
+
+               if (NULL == av_store (children, i, newRV_noinc ((SV *)child))) {
+                       hv_clear (child);
+                       hv_undef (child);
+                       return -1;
+               }
+       }
+       return 0;
+} /* static int oconfig_item2hv (pTHX_ oconfig_item_t *, HV *) */
+
+/*
+ * Internal functions.
+ */
+
+static char *get_module_name (char *buf, size_t buf_len, const char *module) {
+       int status = 0;
+       if (base_name[0] == '\0')
+               status = ssnprintf (buf, buf_len, "%s", module);
+       else
+               status = ssnprintf (buf, buf_len, "%s::%s", base_name, module);
+       if ((status < 0) || ((unsigned int)status >= buf_len))
+               return (NULL);
+       return (buf);
+} /* char *get_module_name */
+
+/*
+ * Add a plugin's data set definition.
+ */
+static int pplugin_register_data_set (pTHX_ char *name, AV *dataset)
+{
+       int ret = 0;
+
+       data_set_t ds;
+
+       if ((NULL == name) || (NULL == dataset))
+               return -1;
+
+       if (0 != av2data_set (aTHX_ dataset, name, &ds))
+               return -1;
+
+       ret = plugin_register_data_set (&ds);
+
+       free (ds.ds);
+       return ret;
+} /* static int pplugin_register_data_set (char *, SV *) */
+
+/*
+ * Remove a plugin's data set definition.
+ */
+static int pplugin_unregister_data_set (char *name)
+{
+       if (NULL == name)
+               return 0;
+       return plugin_unregister_data_set (name);
+} /* static int pplugin_unregister_data_set (char *) */
+
+/*
+ * Submit the values to the write functions.
+ */
+static int pplugin_dispatch_values (pTHX_ HV *values)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       int ret = 0;
+
+       if (NULL == values)
+               return -1;
+
+       if (0 != hv2value_list (aTHX_ values, &vl))
+               return -1;
+
+       ret = plugin_dispatch_values (&vl);
+
+       sfree (vl.values);
+       return ret;
+} /* static int pplugin_dispatch_values (char *, HV *) */
+
+/*
+ * Submit the values to a single write function.
+ */
+static int pplugin_write (pTHX_ const char *plugin, AV *data_set, HV *values)
+{
+       data_set_t   ds;
+       value_list_t vl = VALUE_LIST_INIT;
+
+       int ret;
+
+       if (NULL == values)
+               return -1;
+
+       if (0 != hv2value_list (aTHX_ values, &vl))
+               return -1;
+
+       if ((NULL != data_set)
+                       && (0 != av2data_set (aTHX_ data_set, vl.type, &ds)))
+               return -1;
+
+       ret = plugin_write (plugin, NULL == data_set ? NULL : &ds, &vl);
+       if (0 != ret)
+               log_warn ("Dispatching value to plugin \"%s\" failed with status %i.",
+                               NULL == plugin ? "<any>" : plugin, ret);
+
+       if (NULL != data_set)
+               sfree (ds.ds);
+       sfree (vl.values);
+       return ret;
+} /* static int pplugin_write (const char *plugin, HV *, HV *) */
+
+/*
+ * Dispatch a notification.
+ */
+static int pplugin_dispatch_notification (pTHX_ HV *notif)
+{
+       notification_t n;
+
+       int ret;
+
+       if (NULL == notif)
+               return -1;
+
+       memset (&n, 0, sizeof (n));
+
+       if (0 != hv2notification (aTHX_ notif, &n))
+               return -1;
+
+       ret = plugin_dispatch_notification (&n);
+       plugin_notification_meta_free (n.meta);
+       return ret;
+} /* static int pplugin_dispatch_notification (HV *) */
+
+/*
+ * Call all working functions of the given type.
+ */
+static int pplugin_call_all (pTHX_ int type, ...)
+{
+       int retvals = 0;
+
+       va_list ap;
+       int ret = 0;
+
+       dSP;
+
+       if ((type < 0) || (type >= PLUGIN_TYPES))
+               return -1;
+
+       va_start (ap, type);
+
+       ENTER;
+       SAVETMPS;
+
+       PUSHMARK (SP);
+
+       XPUSHs (sv_2mortal (newSViv ((IV)type)));
+
+       if (PLUGIN_WRITE == type) {
+               /*
+                * $_[0] = $plugin_type;
+                *
+                * $_[1] =
+                * [
+                *   {
+                *     name => $ds_name,
+                *     type => $ds_type,
+                *     min  => $ds_min,
+                *     max  => $ds_max
+                *   },
+                *   ...
+                * ];
+                *
+                * $_[2] =
+                * {
+                *   values => [ $v1, ... ],
+                *   time   => $time,
+                *   host   => $hostname,
+                *   plugin => $plugin,
+                *   type   => $type,
+                *   plugin_instance => $instance,
+                *   type_instance   => $type_instance
+                * };
+                */
+               data_set_t   *ds;
+               value_list_t *vl;
+
+               AV *pds = newAV ();
+               HV *pvl = newHV ();
+
+               ds = va_arg (ap, data_set_t *);
+               vl = va_arg (ap, value_list_t *);
+
+               if (-1 == data_set2av (aTHX_ ds, pds)) {
+                       av_clear (pds);
+                       av_undef (pds);
+                       pds = (AV *)&PL_sv_undef;
+                       ret = -1;
+               }
+
+               if (-1 == value_list2hv (aTHX_ vl, ds, pvl)) {
+                       hv_clear (pvl);
+                       hv_undef (pvl);
+                       pvl = (HV *)&PL_sv_undef;
+                       ret = -1;
+               }
+
+               XPUSHs (sv_2mortal (newSVpv (ds->type, 0)));
+               XPUSHs (sv_2mortal (newRV_noinc ((SV *)pds)));
+               XPUSHs (sv_2mortal (newRV_noinc ((SV *)pvl)));
+       }
+       else if (PLUGIN_LOG == type) {
+               /*
+                * $_[0] = $level;
+                *
+                * $_[1] = $message;
+                */
+               XPUSHs (sv_2mortal (newSViv (va_arg (ap, int))));
+               XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
+       }
+       else if (PLUGIN_NOTIF == type) {
+               /*
+                * $_[0] =
+                * {
+                *   severity => $severity,
+                *   time     => $time,
+                *   message  => $msg,
+                *   host     => $host,
+                *   plugin   => $plugin,
+                *   type     => $type,
+                *   plugin_instance => $instance,
+                *   type_instance   => $type_instance
+                * };
+                */
+               notification_t *n;
+               HV *notif = newHV ();
+
+               n = va_arg (ap, notification_t *);
+
+               if (-1 == notification2hv (aTHX_ n, notif)) {
+                       hv_clear (notif);
+                       hv_undef (notif);
+                       notif = (HV *)&PL_sv_undef;
+                       ret = -1;
+               }
+
+               XPUSHs (sv_2mortal (newRV_noinc ((SV *)notif)));
+       }
+       else if (PLUGIN_FLUSH == type) {
+               cdtime_t timeout;
+
+               /*
+                * $_[0] = $timeout;
+                * $_[1] = $identifier;
+                */
+               timeout = va_arg (ap, cdtime_t);
+
+               XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout))));
+               XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0)));
+       }
+
+       PUTBACK;
+
+       retvals = call_pv ("Collectd::plugin_call_all", G_SCALAR);
+
+       SPAGAIN;
+       if (0 < retvals) {
+               SV *tmp = POPs;
+               if (! SvTRUE (tmp))
+                       ret = -1;
+       }
+
+       PUTBACK;
+       FREETMPS;
+       LEAVE;
+
+       va_end (ap);
+       return ret;
+} /* static int pplugin_call_all (int, ...) */
+
+/*
+ * collectd's perl interpreter based thread implementation.
+ *
+ * This has been inspired by Perl's ithreads introduced in version 5.6.0.
+ */
+
+/* must be called with perl_threads->mutex locked */
+static void c_ithread_destroy (c_ithread_t *ithread)
+{
+       dTHXa (ithread->interp);
+
+       assert (NULL != perl_threads);
+
+       PERL_SET_CONTEXT (aTHX);
+       log_debug ("Shutting down Perl interpreter %p...", aTHX);
+
+#if COLLECT_DEBUG
+       sv_report_used ();
+
+       --perl_threads->number_of_threads;
+#endif /* COLLECT_DEBUG */
+
+       perl_destruct (aTHX);
+       perl_free (aTHX);
+
+       if (NULL == ithread->prev)
+               perl_threads->head = ithread->next;
+       else
+               ithread->prev->next = ithread->next;
+
+       if (NULL == ithread->next)
+               perl_threads->tail = ithread->prev;
+       else
+               ithread->next->prev = ithread->prev;
+
+       sfree (ithread);
+       return;
+} /* static void c_ithread_destroy (c_ithread_t *) */
+
+static void c_ithread_destructor (void *arg)
+{
+       c_ithread_t *ithread = (c_ithread_t *)arg;
+       c_ithread_t *t = NULL;
+
+       if (NULL == perl_threads)
+               return;
+
+       pthread_mutex_lock (&perl_threads->mutex);
+
+       for (t = perl_threads->head; NULL != t; t = t->next)
+               if (t == ithread)
+                       break;
+
+       /* the ithread no longer exists */
+       if (NULL == t)
+               return;
+
+       c_ithread_destroy (ithread);
+
+       pthread_mutex_unlock (&perl_threads->mutex);
+       return;
+} /* static void c_ithread_destructor (void *) */
+
+/* must be called with perl_threads->mutex locked */
+static c_ithread_t *c_ithread_create (PerlInterpreter *base)
+{
+       c_ithread_t *t = NULL;
+       dTHXa (NULL);
+
+       assert (NULL != perl_threads);
+
+       t = (c_ithread_t *)smalloc (sizeof (c_ithread_t));
+       memset (t, 0, sizeof (c_ithread_t));
+
+       t->interp = (NULL == base)
+               ? NULL
+               : perl_clone (base, CLONEf_KEEP_PTR_TABLE);
+
+       aTHX = t->interp;
+
+       if ((NULL != base) && (NULL != PL_endav)) {
+               av_clear (PL_endav);
+               av_undef (PL_endav);
+               PL_endav = Nullav;
+       }
+
+#if COLLECT_DEBUG
+       ++perl_threads->number_of_threads;
+#endif /* COLLECT_DEBUG */
+
+       t->next = NULL;
+
+       if (NULL == perl_threads->tail) {
+               perl_threads->head = t;
+               t->prev = NULL;
+       }
+       else {
+               perl_threads->tail->next = t;
+               t->prev = perl_threads->tail;
+       }
+
+       perl_threads->tail = t;
+
+       pthread_setspecific (perl_thr_key, (const void *)t);
+       return t;
+} /* static c_ithread_t *c_ithread_create (PerlInterpreter *) */
+
+/*
+ * Filter chains implementation.
+ */
+
+static int fc_call (pTHX_ int type, int cb_type, pfc_user_data_t *data, ...)
+{
+       int retvals = 0;
+
+       va_list ap;
+       int ret = 0;
+
+       notification_meta_t **meta  = NULL;
+       AV                   *pmeta = NULL;
+
+       dSP;
+
+       if ((type < 0) || (type >= FC_TYPES))
+               return -1;
+
+       if ((cb_type < 0) || (cb_type >= FC_CB_TYPES))
+               return -1;
+
+       va_start (ap, data);
+
+       ENTER;
+       SAVETMPS;
+
+       PUSHMARK (SP);
+
+       XPUSHs (sv_2mortal (newSViv ((IV)type)));
+       XPUSHs (sv_2mortal (newSVpv (data->name, 0)));
+       XPUSHs (sv_2mortal (newSViv ((IV)cb_type)));
+
+       if (FC_CB_CREATE == cb_type) {
+               /*
+                * $_[0] = $ci;
+                * $_[1] = $user_data;
+                */
+               oconfig_item_t *ci;
+               HV *config = newHV ();
+
+               ci = va_arg (ap, oconfig_item_t *);
+
+               if (0 != oconfig_item2hv (aTHX_ ci, config)) {
+                       hv_clear (config);
+                       hv_undef (config);
+                       config = (HV *)&PL_sv_undef;
+                       ret = -1;
+               }
+
+               XPUSHs (sv_2mortal (newRV_noinc ((SV *)config)));
+       }
+       else if (FC_CB_DESTROY == cb_type) {
+               /*
+                * $_[1] = $user_data;
+                */
+
+               /* nothing to be done - the user data pointer
+                * is pushed onto the stack later */
+       }
+       else if (FC_CB_EXEC == cb_type) {
+               /*
+                * $_[0] = $ds;
+                * $_[1] = $vl;
+                * $_[2] = $meta;
+                * $_[3] = $user_data;
+                */
+               data_set_t   *ds;
+               value_list_t *vl;
+
+               AV *pds = newAV ();
+               HV *pvl = newHV ();
+
+               ds   = va_arg (ap, data_set_t *);
+               vl   = va_arg (ap, value_list_t *);
+               meta = va_arg (ap, notification_meta_t **);
+
+               if (0 != data_set2av (aTHX_ ds, pds)) {
+                       av_clear (pds);
+                       av_undef (pds);
+                       pds = (AV *)&PL_sv_undef;
+                       ret = -1;
+               }
+
+               if (0 != value_list2hv (aTHX_ vl, ds, pvl)) {
+                       hv_clear (pvl);
+                       hv_undef (pvl);
+                       pvl = (HV *)&PL_sv_undef;
+                       ret = -1;
+               }
+
+               if (NULL != meta) {
+                       pmeta = newAV ();
+
+                       if (0 != notification_meta2av (aTHX_ *meta, pmeta)) {
+                               av_clear (pmeta);
+                               av_undef (pmeta);
+                               pmeta = (AV *)&PL_sv_undef;
+                               ret = -1;
+                       }
+               }
+               else {
+                       pmeta = (AV *)&PL_sv_undef;
+               }
+
+               XPUSHs (sv_2mortal (newRV_noinc ((SV *)pds)));
+               XPUSHs (sv_2mortal (newRV_noinc ((SV *)pvl)));
+               XPUSHs (sv_2mortal (newRV_noinc ((SV *)pmeta)));
+       }
+
+       XPUSHs (sv_2mortal (newRV_inc (data->user_data)));
+
+       PUTBACK;
+
+       retvals = call_pv ("Collectd::fc_call", G_SCALAR);
+
+       if ((FC_CB_EXEC == cb_type) && (meta != NULL)) {
+               assert (pmeta != NULL);
+
+               plugin_notification_meta_free (*meta);
+               av2notification_meta (aTHX_ pmeta, meta);
+       }
+
+       SPAGAIN;
+       if (0 < retvals) {
+               SV *tmp = POPs;
+
+               /* the exec callbacks return a status, while
+                * the others return a boolean value */
+               if (FC_CB_EXEC == cb_type)
+                       ret = SvIV (tmp);
+               else if (! SvTRUE (tmp))
+                       ret = -1;
+       }
+
+       PUTBACK;
+       FREETMPS;
+       LEAVE;
+
+       va_end (ap);
+       return ret;
+} /* static int fc_call (int, int, pfc_user_data_t *, ...) */
+
+static int fc_create (int type, const oconfig_item_t *ci, void **user_data)
+{
+       pfc_user_data_t *data;
+
+       int ret = 0;
+
+       dTHX;
+
+       if (NULL == perl_threads)
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       log_debug ("fc_create: c_ithread: interp = %p (active threads: %i)",
+                       aTHX, perl_threads->number_of_threads);
+
+       if ((1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_warn ("A \"%s\" block expects a single string argument.",
+                               (FC_MATCH == type) ? "Match" : "Target");
+               return -1;
+       }
+
+       data = (pfc_user_data_t *)smalloc (sizeof (*data));
+       data->name      = sstrdup (ci->values[0].value.string);
+       data->user_data = newSV (0);
+
+       ret = fc_call (aTHX_ type, FC_CB_CREATE, data, ci);
+
+       if (0 != ret)
+               PFC_USER_DATA_FREE (data);
+       else
+               *user_data = data;
+       return ret;
+} /* static int fc_create (int, const oconfig_item_t *, void **) */
+
+static int fc_destroy (int type, void **user_data)
+{
+       pfc_user_data_t *data = *(pfc_user_data_t **)user_data;
+
+       int ret = 0;
+
+       dTHX;
+
+       if ((NULL == perl_threads) || (NULL == data))
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       log_debug ("fc_destroy: c_ithread: interp = %p (active threads: %i)",
+                       aTHX, perl_threads->number_of_threads);
+
+       ret = fc_call (aTHX_ type, FC_CB_DESTROY, data);
+
+       PFC_USER_DATA_FREE (data);
+       *user_data = NULL;
+       return ret;
+} /* static int fc_destroy (int, void **) */
+
+static int fc_exec (int type, const data_set_t *ds, const value_list_t *vl,
+               notification_meta_t **meta, void **user_data)
+{
+       pfc_user_data_t *data = *(pfc_user_data_t **)user_data;
+
+       dTHX;
+
+       if (NULL == perl_threads)
+               return 0;
+
+       assert (NULL != data);
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       log_debug ("fc_exec: c_ithread: interp = %p (active threads: %i)",
+                       aTHX, perl_threads->number_of_threads);
+
+       return fc_call (aTHX_ type, FC_CB_EXEC, data, ds, vl, meta);
+} /* static int fc_exec (int, const data_set_t *, const value_list_t *,
+               notification_meta_t **, void **) */
+
+static int pmatch_create (const oconfig_item_t *ci, void **user_data)
+{
+       return fc_create (FC_MATCH, ci, user_data);
+} /* static int pmatch_create (const oconfig_item_t *, void **) */
+
+static int pmatch_destroy (void **user_data)
+{
+       return fc_destroy (FC_MATCH, user_data);
+} /* static int pmatch_destroy (void **) */
+
+static int pmatch_match (const data_set_t *ds, const value_list_t *vl,
+               notification_meta_t **meta, void **user_data)
+{
+       return fc_exec (FC_MATCH, ds, vl, meta, user_data);
+} /* static int pmatch_match (const data_set_t *, const value_list_t *,
+               notification_meta_t **, void **) */
+
+static match_proc_t pmatch = {
+       pmatch_create, pmatch_destroy, pmatch_match
+};
+
+static int ptarget_create (const oconfig_item_t *ci, void **user_data)
+{
+       return fc_create (FC_TARGET, ci, user_data);
+} /* static int ptarget_create (const oconfig_item_t *, void **) */
+
+static int ptarget_destroy (void **user_data)
+{
+       return fc_destroy (FC_TARGET, user_data);
+} /* static int ptarget_destroy (void **) */
+
+static int ptarget_invoke (const data_set_t *ds, value_list_t *vl,
+               notification_meta_t **meta, void **user_data)
+{
+       return fc_exec (FC_TARGET, ds, vl, meta, user_data);
+} /* static int ptarget_invoke (const data_set_t *, value_list_t *,
+               notification_meta_t **, void **) */
+
+static target_proc_t ptarget = {
+       ptarget_create, ptarget_destroy, ptarget_invoke
+};
+
+/*
+ * Exported Perl API.
+ */
+
+/*
+ * Collectd::plugin_register_data_set (type, dataset).
+ *
+ * type:
+ *   type of the dataset
+ *
+ * dataset:
+ *   dataset to be registered
+ */
+static XS (Collectd_plugin_register_ds)
+{
+       SV  *data = NULL;
+       int ret   = 0;
+
+       dXSARGS;
+
+       log_warn ("Using plugin_register() to register new data-sets is "
+                       "deprecated - add new entries to a custom types.db instead.");
+
+       if (2 != items) {
+               log_err ("Usage: Collectd::plugin_register_data_set(type, dataset)");
+               XSRETURN_EMPTY;
+       }
+
+       log_debug ("Collectd::plugin_register_data_set: "
+                       "type = \"%s\", dataset = \"%s\"",
+                       SvPV_nolen (ST (0)), SvPV_nolen (ST (1)));
+
+       data = ST (1);
+
+       if (SvROK (data) && (SVt_PVAV == SvTYPE (SvRV (data)))) {
+               ret = pplugin_register_data_set (aTHX_ SvPV_nolen (ST (0)),
+                               (AV *)SvRV (data));
+       }
+       else {
+               log_err ("Collectd::plugin_register_data_set: Invalid data.");
+               XSRETURN_EMPTY;
+       }
+
+       if (0 == ret)
+               XSRETURN_YES;
+       else
+               XSRETURN_EMPTY;
+} /* static XS (Collectd_plugin_register_ds) */
+
+/*
+ * Collectd::plugin_unregister_data_set (type).
+ *
+ * type:
+ *   type of the dataset
+ */
+static XS (Collectd_plugin_unregister_ds)
+{
+       dXSARGS;
+
+       if (1 != items) {
+               log_err ("Usage: Collectd::plugin_unregister_data_set(type)");
+               XSRETURN_EMPTY;
+       }
+
+       log_debug ("Collectd::plugin_unregister_data_set: type = \"%s\"",
+                       SvPV_nolen (ST (0)));
+
+       if (0 == pplugin_unregister_data_set (SvPV_nolen (ST (0))))
+               XSRETURN_YES;
+       else
+               XSRETURN_EMPTY;
+} /* static XS (Collectd_plugin_register_ds) */
+
+/*
+ * Collectd::plugin_dispatch_values (name, values).
+ *
+ * name:
+ *   name of the plugin
+ *
+ * values:
+ *   value list to submit
+ */
+static XS (Collectd_plugin_dispatch_values)
+{
+       SV *values     = NULL;
+
+       int ret = 0;
+
+       dXSARGS;
+
+       if (1 != items) {
+               log_err ("Usage: Collectd::plugin_dispatch_values(values)");
+               XSRETURN_EMPTY;
+       }
+
+       log_debug ("Collectd::plugin_dispatch_values: values=\"%s\"",
+                       SvPV_nolen (ST (/* stack index = */ 0)));
+
+       values = ST (/* stack index = */ 0);
+
+       /* Make sure the argument is a hash reference. */
+       if (! (SvROK (values) && (SVt_PVHV == SvTYPE (SvRV (values))))) {
+               log_err ("Collectd::plugin_dispatch_values: Invalid values.");
+               XSRETURN_EMPTY;
+       }
+
+       if (NULL == values)
+               XSRETURN_EMPTY;
+
+       ret = pplugin_dispatch_values (aTHX_ (HV *)SvRV (values));
+
+       if (0 == ret)
+               XSRETURN_YES;
+       else
+               XSRETURN_EMPTY;
+} /* static XS (Collectd_plugin_dispatch_values) */
+
+/*
+ * Collectd::plugin_get_interval ().
+ */
+static XS (Collectd_plugin_get_interval)
+{
+       dXSARGS;
+
+       /* make sure we don't get any unused variable warnings for 'items';
+        * don't abort, though */
+       if (items)
+               log_err ("Usage: Collectd::plugin_get_interval()");
+
+       XSRETURN_NV ((NV) CDTIME_T_TO_DOUBLE (plugin_get_interval ()));
+} /* static XS (Collectd_plugin_get_interval) */
+
+/* Collectd::plugin_write (plugin, ds, vl).
+ *
+ * plugin:
+ *   name of the plugin to call, may be 'undef'
+ *
+ * ds:
+ *   data-set that describes the submitted values, may be 'undef'
+ *
+ * vl:
+ *   value-list to be written
+ */
+static XS (Collectd__plugin_write)
+{
+       char *plugin;
+       SV   *ds, *vl;
+       AV   *ds_array;
+
+       int ret;
+
+       dXSARGS;
+
+       if (3 != items) {
+               log_err ("Usage: Collectd::plugin_write(plugin, ds, vl)");
+               XSRETURN_EMPTY;
+       }
+
+       log_debug ("Collectd::plugin_write: plugin=\"%s\", ds=\"%s\", vl=\"%s\"",
+                       SvPV_nolen (ST (0)), SvOK (ST (1)) ? SvPV_nolen (ST (1)) : "",
+                       SvPV_nolen (ST (2)));
+
+       if (! SvOK (ST (0)))
+               plugin = NULL;
+       else
+               plugin = SvPV_nolen (ST (0));
+
+       ds = ST (1);
+       if (SvROK (ds) && (SVt_PVAV == SvTYPE (SvRV (ds))))
+               ds_array = (AV *)SvRV (ds);
+       else if (! SvOK (ds))
+               ds_array = NULL;
+       else {
+               log_err ("Collectd::plugin_write: Invalid data-set.");
+               XSRETURN_EMPTY;
+       }
+
+       vl = ST (2);
+       if (! (SvROK (vl) && (SVt_PVHV == SvTYPE (SvRV (vl))))) {
+               log_err ("Collectd::plugin_write: Invalid value-list.");
+               XSRETURN_EMPTY;
+       }
+
+       ret = pplugin_write (aTHX_ plugin, ds_array, (HV *)SvRV (vl));
+
+       if (0 == ret)
+               XSRETURN_YES;
+       else
+               XSRETURN_EMPTY;
+} /* static XS (Collectd__plugin_write) */
+
+/*
+ * Collectd::_plugin_flush (plugin, timeout, identifier).
+ *
+ * plugin:
+ *   name of the plugin to flush
+ *
+ * timeout:
+ *   timeout to use when flushing the data
+ *
+ * identifier:
+ *   data-set identifier to flush
+ */
+static XS (Collectd__plugin_flush)
+{
+       char *plugin  = NULL;
+       int   timeout = -1;
+       char *id      = NULL;
+
+       dXSARGS;
+
+       if (3 != items) {
+               log_err ("Usage: Collectd::_plugin_flush(plugin, timeout, id)");
+               XSRETURN_EMPTY;
+       }
+
+       if (SvOK (ST (0)))
+               plugin = SvPV_nolen (ST (0));
+
+       if (SvOK (ST (1)))
+               timeout = (int)SvIV (ST (1));
+
+       if (SvOK (ST (2)))
+               id = SvPV_nolen (ST (2));
+
+       log_debug ("Collectd::_plugin_flush: plugin = \"%s\", timeout = %i, "
+                       "id = \"%s\"", plugin, timeout, id);
+
+       if (0 == plugin_flush (plugin, timeout, id))
+               XSRETURN_YES;
+       else
+               XSRETURN_EMPTY;
+} /* static XS (Collectd__plugin_flush) */
+
+/*
+ * Collectd::plugin_dispatch_notification (notif).
+ *
+ * notif:
+ *   notification to dispatch
+ */
+static XS (Collectd_plugin_dispatch_notification)
+{
+       SV *notif = NULL;
+
+       int ret = 0;
+
+       dXSARGS;
+
+       if (1 != items) {
+               log_err ("Usage: Collectd::plugin_dispatch_notification(notif)");
+               XSRETURN_EMPTY;
+       }
+
+       log_debug ("Collectd::plugin_dispatch_notification: notif = \"%s\"",
+                       SvPV_nolen (ST (0)));
+
+       notif = ST (0);
+
+       if (! (SvROK (notif) && (SVt_PVHV == SvTYPE (SvRV (notif))))) {
+               log_err ("Collectd::plugin_dispatch_notification: Invalid notif.");
+               XSRETURN_EMPTY;
+       }
+
+       ret = pplugin_dispatch_notification (aTHX_ (HV *)SvRV (notif));
+
+       if (0 == ret)
+               XSRETURN_YES;
+       else
+               XSRETURN_EMPTY;
+} /* static XS (Collectd_plugin_dispatch_notification) */
+
+/*
+ * Collectd::plugin_log (level, message).
+ *
+ * level:
+ *   log level (LOG_DEBUG, ... LOG_ERR)
+ *
+ * message:
+ *   log message
+ */
+static XS (Collectd_plugin_log)
+{
+       dXSARGS;
+
+       if (2 != items) {
+               log_err ("Usage: Collectd::plugin_log(level, message)");
+               XSRETURN_EMPTY;
+       }
+
+       plugin_log (SvIV (ST (0)), "%s", SvPV_nolen (ST (1)));
+       XSRETURN_YES;
+} /* static XS (Collectd_plugin_log) */
+
+/*
+ * Collectd::_fc_register (type, name)
+ *
+ * type:
+ *   match | target
+ *
+ * name:
+ *   name of the match
+ */
+static XS (Collectd__fc_register)
+{
+       int   type;
+       char *name;
+
+       int ret = 0;
+
+       dXSARGS;
+
+       if (2 != items) {
+               log_err ("Usage: Collectd::_fc_register(type, name)");
+               XSRETURN_EMPTY;
+       }
+
+       type = SvIV (ST (0));
+       name = SvPV_nolen (ST (1));
+
+       if (FC_MATCH == type)
+               ret = fc_register_match (name, pmatch);
+       else if (FC_TARGET == type)
+               ret = fc_register_target (name, ptarget);
+
+       if (0 == ret)
+               XSRETURN_YES;
+       else
+               XSRETURN_EMPTY;
+} /* static XS (Collectd_fc_register) */
+
+/*
+ * Collectd::call_by_name (...).
+ *
+ * Call a Perl sub identified by its name passed through $Collectd::cb_name.
+ */
+static XS (Collectd_call_by_name)
+{
+       SV   *tmp  = NULL;
+       char *name = NULL;
+
+       if (NULL == (tmp = get_sv ("Collectd::cb_name", 0))) {
+               sv_setpv (get_sv ("@", 1), "cb_name has not been set");
+               CLEAR_STACK_FRAME;
+               return;
+       }
+
+       name = SvPV_nolen (tmp);
+
+       if (NULL == get_cv (name, 0)) {
+               sv_setpvf (get_sv ("@", 1), "unknown callback \"%s\"", name);
+               CLEAR_STACK_FRAME;
+               return;
+       }
+
+       /* simply pass on the subroutine call without touching the stack,
+        * thus leaving any arguments and return values in place */
+       call_pv (name, 0);
+} /* static XS (Collectd_call_by_name) */
+
+/*
+ * Interface to collectd.
+ */
+
+static int perl_init (void)
+{
+       dTHX;
+
+       if (NULL == perl_threads)
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       log_debug ("perl_init: c_ithread: interp = %p (active threads: %i)",
+                       aTHX, perl_threads->number_of_threads);
+       return pplugin_call_all (aTHX_ PLUGIN_INIT);
+} /* static int perl_init (void) */
+
+static int perl_read (void)
+{
+       dTHX;
+
+       if (NULL == perl_threads)
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       /* Assert that we're not running as the base thread. Otherwise, we might
+        * run into concurrency issues with c_ithread_create(). See
+        * https://github.com/collectd/collectd/issues/9 for details. */
+       assert (aTHX != perl_threads->head->interp);
+
+       log_debug ("perl_read: c_ithread: interp = %p (active threads: %i)",
+                       aTHX, perl_threads->number_of_threads);
+       return pplugin_call_all (aTHX_ PLUGIN_READ);
+} /* static int perl_read (void) */
+
+static int perl_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       int status;
+       dTHX;
+
+       if (NULL == perl_threads)
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       /* Lock the base thread if this is not called from one of the read threads
+        * to avoid race conditions with c_ithread_create(). See
+        * https://github.com/collectd/collectd/issues/9 for details. */
+       if (aTHX == perl_threads->head->interp)
+               pthread_mutex_lock (&perl_threads->mutex);
+
+       log_debug ("perl_write: c_ithread: interp = %p (active threads: %i)",
+                       aTHX, perl_threads->number_of_threads);
+       status = pplugin_call_all (aTHX_ PLUGIN_WRITE, ds, vl);
+
+       if (aTHX == perl_threads->head->interp)
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+       return status;
+} /* static int perl_write (const data_set_t *, const value_list_t *) */
+
+static void perl_log (int level, const char *msg,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       dTHX;
+
+       if (NULL == perl_threads)
+               return;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       /* Lock the base thread if this is not called from one of the read threads
+        * to avoid race conditions with c_ithread_create(). See
+        * https://github.com/collectd/collectd/issues/9 for details. */
+       if (aTHX == perl_threads->head->interp)
+               pthread_mutex_lock (&perl_threads->mutex);
+
+       pplugin_call_all (aTHX_ PLUGIN_LOG, level, msg);
+
+       if (aTHX == perl_threads->head->interp)
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+       return;
+} /* static void perl_log (int, const char *) */
+
+static int perl_notify (const notification_t *notif,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       dTHX;
+
+       if (NULL == perl_threads)
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+       return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif);
+} /* static int perl_notify (const notification_t *) */
+
+static int perl_flush (cdtime_t timeout, const char *identifier,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       dTHX;
+
+       if (NULL == perl_threads)
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+       return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout, identifier);
+} /* static int perl_flush (const int) */
+
+static int perl_shutdown (void)
+{
+       c_ithread_t *t = NULL;
+
+       int ret = 0;
+
+       dTHX;
+
+       plugin_unregister_complex_config ("perl");
+
+       if (NULL == perl_threads)
+               return 0;
+
+       if (NULL == aTHX) {
+               c_ithread_t *t = NULL;
+
+               pthread_mutex_lock (&perl_threads->mutex);
+               t = c_ithread_create (perl_threads->head->interp);
+               pthread_mutex_unlock (&perl_threads->mutex);
+
+               aTHX = t->interp;
+       }
+
+       log_debug ("perl_shutdown: c_ithread: interp = %p (active threads: %i)",
+                       aTHX, perl_threads->number_of_threads);
+
+       plugin_unregister_log ("perl");
+       plugin_unregister_notification ("perl");
+       plugin_unregister_init ("perl");
+       plugin_unregister_read ("perl");
+       plugin_unregister_write ("perl");
+       plugin_unregister_flush ("perl");
+
+       ret = pplugin_call_all (aTHX_ PLUGIN_SHUTDOWN);
+
+       pthread_mutex_lock (&perl_threads->mutex);
+       t = perl_threads->tail;
+
+       while (NULL != t) {
+               c_ithread_t *thr = t;
+
+               /* the pointer has to be advanced before destroying
+                * the thread as this will free the memory */
+               t = t->prev;
+
+               c_ithread_destroy (thr);
+       }
+
+       pthread_mutex_unlock (&perl_threads->mutex);
+       pthread_mutex_destroy (&perl_threads->mutex);
+
+       sfree (perl_threads);
+
+       pthread_key_delete (perl_thr_key);
+
+       PERL_SYS_TERM ();
+
+       plugin_unregister_shutdown ("perl");
+       return ret;
+} /* static void perl_shutdown (void) */
+
+/*
+ * Access functions for global variables.
+ *
+ * These functions implement the "magic" used to access
+ * the global variables from Perl.
+ */
+
+static int g_pv_get (pTHX_ SV *var, MAGIC *mg)
+{
+       char *pv = mg->mg_ptr;
+       sv_setpv (var, pv);
+       return 0;
+} /* static int g_pv_get (pTHX_ SV *, MAGIC *) */
+
+static int g_pv_set (pTHX_ SV *var, MAGIC *mg)
+{
+       char *pv = mg->mg_ptr;
+       sstrncpy (pv, SvPV_nolen (var), DATA_MAX_NAME_LEN);
+       return 0;
+} /* static int g_pv_set (pTHX_ SV *, MAGIC *) */
+
+static int g_interval_get (pTHX_ SV *var, MAGIC *mg)
+{
+       log_warn ("Accessing $interval_g is deprecated (and might not "
+                       "give the desired results) - plugin_get_interval() should "
+                       "be used instead.");
+       sv_setnv (var, CDTIME_T_TO_DOUBLE (interval_g));
+       return 0;
+} /* static int g_interval_get (pTHX_ SV *, MAGIC *) */
+
+static int g_interval_set (pTHX_ SV *var, MAGIC *mg)
+{
+       double nv = (double)SvNV (var);
+       log_warn ("Accessing $interval_g is deprecated (and might not "
+                       "give the desired results) - plugin_get_interval() should "
+                       "be used instead.");
+       interval_g = DOUBLE_TO_CDTIME_T (nv);
+       return 0;
+} /* static int g_interval_set (pTHX_ SV *, MAGIC *) */
+
+static MGVTBL g_pv_vtbl = {
+       g_pv_get, g_pv_set, NULL, NULL, NULL, NULL, NULL
+#if HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL
+               , NULL
+#endif
+};
+static MGVTBL g_interval_vtbl = {
+       g_interval_get, g_interval_set, NULL, NULL, NULL, NULL, NULL
+#if HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL
+               , NULL
+#endif
+};
+
+/* bootstrap the Collectd module */
+static void xs_init (pTHX)
+{
+       HV   *stash = NULL;
+       SV   *tmp   = NULL;
+       char *file  = __FILE__;
+
+       int i = 0;
+
+       dXSUB_SYS;
+
+       /* enable usage of Perl modules using shared libraries */
+       newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
+
+       /* register API */
+       for (i = 0; NULL != api[i].f; ++i)
+               newXS (api[i].name, api[i].f, file);
+
+       stash = gv_stashpv ("Collectd", 1);
+
+       /* export "constants" */
+       for (i = 0; '\0' != constants[i].name[0]; ++i)
+               newCONSTSUB (stash, constants[i].name, newSViv (constants[i].value));
+
+       /* export global variables
+        * by adding "magic" to the SV's representing the globale variables
+        * perl is able to automagically call the get/set function when
+        * accessing any such variable (this is basically the same as using
+        * tie() in Perl) */
+       /* global strings */
+       for (i = 0; '\0' != g_strings[i].name[0]; ++i) {
+               tmp = get_sv (g_strings[i].name, 1);
+               sv_magicext (tmp, NULL, PERL_MAGIC_ext, &g_pv_vtbl,
+                               g_strings[i].var, 0);
+       }
+
+       tmp = get_sv ("Collectd::interval_g", /* create = */ 1);
+       sv_magicext (tmp, NULL, /* how = */ PERL_MAGIC_ext,
+                       /* vtbl = */ &g_interval_vtbl,
+                       /* name = */ NULL, /* namelen = */ 0);
+
+       return;
+} /* static void xs_init (pTHX) */
+
+/* Initialize the global Perl interpreter. */
+static int init_pi (int argc, char **argv)
+{
+       dTHXa (NULL);
+
+       if (NULL != perl_threads)
+               return 0;
+
+       log_info ("Initializing Perl interpreter...");
+#if COLLECT_DEBUG
+       {
+               int i = 0;
+
+               for (i = 0; i < argc; ++i)
+                       log_debug ("argv[%i] = \"%s\"", i, argv[i]);
+       }
+#endif /* COLLECT_DEBUG */
+
+       if (0 != pthread_key_create (&perl_thr_key, c_ithread_destructor)) {
+               log_err ("init_pi: pthread_key_create failed");
+
+               /* this must not happen - cowardly giving up if it does */
+               return -1;
+       }
+
+#ifdef __FreeBSD__
+       /* On FreeBSD, PERL_SYS_INIT3 expands to some expression which
+        * triggers a "value computed is not used" warning by gcc. */
+       (void)
+#endif
+       PERL_SYS_INIT3 (&argc, &argv, &environ);
+
+       perl_threads = (c_ithread_list_t *)smalloc (sizeof (c_ithread_list_t));
+       memset (perl_threads, 0, sizeof (c_ithread_list_t));
+
+       pthread_mutex_init (&perl_threads->mutex, NULL);
+       /* locking the mutex should not be necessary at this point
+        * but let's just do it for the sake of completeness */
+       pthread_mutex_lock (&perl_threads->mutex);
+
+       perl_threads->head = c_ithread_create (NULL);
+       perl_threads->tail = perl_threads->head;
+
+       if (NULL == (perl_threads->head->interp = perl_alloc ())) {
+               log_err ("init_pi: Not enough memory.");
+               exit (3);
+       }
+
+       aTHX = perl_threads->head->interp;
+       pthread_mutex_unlock (&perl_threads->mutex);
+
+       perl_construct (aTHX);
+
+       PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
+
+       if (0 != perl_parse (aTHX_ xs_init, argc, argv, NULL)) {
+               SV *err = get_sv ("@", 1);
+               log_err ("init_pi: Unable to bootstrap Collectd: %s",
+                               SvPV_nolen (err));
+
+               perl_destruct (perl_threads->head->interp);
+               perl_free (perl_threads->head->interp);
+               sfree (perl_threads);
+
+               pthread_key_delete (perl_thr_key);
+               return -1;
+       }
+
+       /* Set $0 to "collectd" because perl_parse() has to set it to "-e". */
+       sv_setpv (get_sv ("0", 0), "collectd");
+
+       perl_run (aTHX);
+
+       plugin_register_log ("perl", perl_log, /* user_data = */ NULL);
+       plugin_register_notification ("perl", perl_notify,
+                       /* user_data = */ NULL);
+       plugin_register_init ("perl", perl_init);
+
+       plugin_register_read ("perl", perl_read);
+
+       plugin_register_write ("perl", perl_write, /* user_data = */ NULL);
+       plugin_register_flush ("perl", perl_flush, /* user_data = */ NULL);
+       plugin_register_shutdown ("perl", perl_shutdown);
+       return 0;
+} /* static int init_pi (const char **, const int) */
+
+/*
+ * LoadPlugin "<Plugin>"
+ */
+static int perl_config_loadplugin (pTHX_ oconfig_item_t *ci)
+{
+       char module_name[DATA_MAX_NAME_LEN];
+
+       char *value = NULL;
+
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("LoadPlugin expects a single string argument.");
+               return 1;
+       }
+
+       value = ci->values[0].value.string;
+
+       if (NULL == get_module_name (module_name, sizeof (module_name), value)) {
+               log_err ("Invalid module name %s", value);
+               return (1);
+       }
+
+       if (0 != init_pi (perl_argc, perl_argv))
+               return -1;
+
+       assert (NULL != perl_threads);
+       assert (NULL != perl_threads->head);
+
+       aTHX = perl_threads->head->interp;
+
+       log_debug ("perl_config: loading perl plugin \"%s\"", value);
+       load_module (PERL_LOADMOD_NOIMPORT,
+                       newSVpv (module_name, strlen (module_name)), Nullsv);
+       return 0;
+} /* static int perl_config_loadplugin (oconfig_item_it *) */
+
+/*
+ * BaseName "<Name>"
+ */
+static int perl_config_basename (pTHX_ oconfig_item_t *ci)
+{
+       char *value = NULL;
+
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("BaseName expects a single string argument.");
+               return 1;
+       }
+
+       value = ci->values[0].value.string;
+
+       log_debug ("perl_config: Setting plugin basename to \"%s\"", value);
+       sstrncpy (base_name, value, sizeof (base_name));
+       return 0;
+} /* static int perl_config_basename (oconfig_item_it *) */
+
+/*
+ * EnableDebugger "<Package>"|""
+ */
+static int perl_config_enabledebugger (pTHX_ oconfig_item_t *ci)
+{
+       char *value = NULL;
+
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("EnableDebugger expects a single string argument.");
+               return 1;
+       }
+
+       if (NULL != perl_threads) {
+               log_warn ("EnableDebugger has no effects if used after LoadPlugin.");
+               return 1;
+       }
+
+       value = ci->values[0].value.string;
+
+       perl_argv = (char **)realloc (perl_argv,
+                       (++perl_argc + 1) * sizeof (char *));
+
+       if (NULL == perl_argv) {
+               log_err ("perl_config: Not enough memory.");
+               exit (3);
+       }
+
+       if ('\0' == value[0]) {
+               perl_argv[perl_argc - 1] = "-d";
+       }
+       else {
+               perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 4);
+               sstrncpy (perl_argv[perl_argc - 1], "-d:", 4);
+               sstrncpy (perl_argv[perl_argc - 1] + 3, value, strlen (value) + 1);
+       }
+
+       perl_argv[perl_argc] = NULL;
+       return 0;
+} /* static int perl_config_enabledebugger (oconfig_item_it *) */
+
+/*
+ * IncludeDir "<Dir>"
+ */
+static int perl_config_includedir (pTHX_ oconfig_item_t *ci)
+{
+       char *value = NULL;
+
+       if ((0 != ci->children_num) || (1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("IncludeDir expects a single string argument.");
+               return 1;
+       }
+
+       value = ci->values[0].value.string;
+
+       if (NULL == aTHX) {
+               perl_argv = (char **)realloc (perl_argv,
+                               (++perl_argc + 1) * sizeof (char *));
+
+               if (NULL == perl_argv) {
+                       log_err ("perl_config: Not enough memory.");
+                       exit (3);
+               }
+
+               perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 3);
+               sstrncpy(perl_argv[perl_argc - 1], "-I", 3);
+               sstrncpy(perl_argv[perl_argc - 1] + 2, value, strlen (value) + 1);
+
+               perl_argv[perl_argc] = NULL;
+       }
+       else {
+               /* prepend the directory to @INC */
+               av_unshift (GvAVn (PL_incgv), 1);
+               av_store (GvAVn (PL_incgv), 0, newSVpv (value, strlen (value)));
+       }
+       return 0;
+} /* static int perl_config_includedir (oconfig_item_it *) */
+
+/*
+ * <Plugin> block
+ */
+static int perl_config_plugin (pTHX_ oconfig_item_t *ci)
+{
+       int retvals = 0;
+       int ret     = 0;
+
+       char *plugin;
+       HV   *config;
+
+       dSP;
+
+       if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("LoadPlugin expects a single string argument.");
+               return 1;
+       }
+
+       plugin = ci->values[0].value.string;
+       config = newHV ();
+
+       if (0 != oconfig_item2hv (aTHX_ ci, config)) {
+               hv_clear (config);
+               hv_undef (config);
+
+               log_err ("Unable to convert configuration to a Perl hash value.");
+               config = (HV *)&PL_sv_undef;
+       }
+
+       ENTER;
+       SAVETMPS;
+
+       PUSHMARK (SP);
+
+       XPUSHs (sv_2mortal (newSVpv (plugin, 0)));
+       XPUSHs (sv_2mortal (newRV_noinc ((SV *)config)));
+
+       PUTBACK;
+
+       retvals = call_pv ("Collectd::_plugin_dispatch_config", G_SCALAR);
+
+       SPAGAIN;
+       if (0 < retvals) {
+               SV *tmp = POPs;
+               if (! SvTRUE (tmp))
+                       ret = 1;
+       }
+       else
+               ret = 1;
+
+       PUTBACK;
+       FREETMPS;
+       LEAVE;
+       return ret;
+} /* static int perl_config_plugin (oconfig_item_it *) */
+
+static int perl_config (oconfig_item_t *ci)
+{
+       int status = 0;
+       int i = 0;
+
+       dTHXa (NULL);
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+               int current_status = 0;
+
+               if (NULL != perl_threads)
+                       aTHX = PERL_GET_CONTEXT;
+
+               if (0 == strcasecmp (c->key, "LoadPlugin"))
+                       current_status = perl_config_loadplugin (aTHX_ c);
+               else if (0 == strcasecmp (c->key, "BaseName"))
+                       current_status = perl_config_basename (aTHX_ c);
+               else if (0 == strcasecmp (c->key, "EnableDebugger"))
+                       current_status = perl_config_enabledebugger (aTHX_ c);
+               else if (0 == strcasecmp (c->key, "IncludeDir"))
+                       current_status = perl_config_includedir (aTHX_ c);
+               else if (0 == strcasecmp (c->key, "Plugin"))
+                       current_status = perl_config_plugin (aTHX_ c);
+               else
+               {
+                       log_warn ("Ignoring unknown config key \"%s\".", c->key);
+                       current_status = 0;
+               }
+
+               /* fatal error - it's up to perl_config_* to clean up */
+               if (0 > current_status) {
+                       log_err ("Configuration failed with a fatal error - "
+                                       "plugin disabled!");
+                       return current_status;
+               }
+
+               status += current_status;
+       }
+       return status;
+} /* static int perl_config (oconfig_item_t *) */
+
+void module_register (void)
+{
+       perl_argc = 4;
+       perl_argv = (char **)smalloc ((perl_argc + 1) * sizeof (char *));
+
+       /* default options for the Perl interpreter */
+       perl_argv[0] = "";
+       perl_argv[1] = "-MCollectd";
+       perl_argv[2] = "-e";
+       perl_argv[3] = "1";
+       perl_argv[4] = NULL;
+
+       plugin_register_complex_config ("perl", perl_config);
+       return;
+} /* void module_register (void) */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/pf.c b/src/pf.c
new file mode 100644 (file)
index 0000000..29f3a3d
--- /dev/null
+++ b/src/pf.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2010 Pierre-Yves Ritschard
+ * Copyright (c) 2011 Stefan Rinkes
+ *
+ * Permission to use, copy, modify, and 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:
+ *   Pierre-Yves Ritschard <pyr at openbsd.org>
+ *   Stefan Rinkes <stefan.rinkes at gmail.org>
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+#include <net/pfvar.h>
+
+#ifndef FCNT_NAMES
+# if FCNT_MAX != 3
+#  error "Unexpected value for FCNT_MAX"
+# endif
+# define FCNT_NAMES {"search", "insert", "removals", NULL};
+#endif
+
+#ifndef SCNT_NAMES
+# if SCNT_MAX != 3
+#  error "Unexpected value for SCNT_MAX"
+# endif
+# define SCNT_NAMES {"search", "insert", "removals", NULL};
+#endif
+
+static char const *pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
+static char const *pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
+static char const *pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
+static char const *pf_scounters[SCNT_MAX+1] = SCNT_NAMES;
+
+static char const *pf_device = "/dev/pf";
+
+static void pf_submit (char const *type, char const *type_instance,
+               uint64_t val, _Bool is_gauge)
+{
+       value_t         values[1];
+       value_list_t    vl = VALUE_LIST_INIT;
+
+       if (is_gauge)
+               values[0].gauge = (gauge_t) val;
+       else
+               values[0].derive = (derive_t) val;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "pf", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof(vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof(vl.type_instance));
+
+       plugin_dispatch_values(&vl);
+} /* void pf_submit */
+
+static int pf_read (void)
+{
+       struct pf_status state;
+       int fd;
+       int status;
+       int i;
+
+       fd = open (pf_device, O_RDONLY);
+       if (fd < 0)
+       {
+               char errbuf[1024];
+               ERROR("pf plugin: Unable to open %s: %s",
+                               pf_device,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       memset (&state, 0, sizeof (state));
+       status = ioctl (fd, DIOCGETSTATUS, &state);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR("pf plugin: ioctl(DIOCGETSTATUS) failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close(fd);
+               return (-1);
+       }
+
+       close (fd);
+       fd = -1;
+
+       if (!state.running)
+       {
+               WARNING ("pf plugin: PF is not running.");
+               return (-1);
+       }
+
+       for (i = 0; i < PFRES_MAX; i++)
+               pf_submit ("pf_counters", pf_reasons[i], state.counters[i],
+                               /* is gauge = */ 0);
+       for (i = 0; i < LCNT_MAX; i++)
+               pf_submit ("pf_limits", pf_lcounters[i], state.lcounters[i],
+                               /* is gauge = */ 0);
+       for (i = 0; i < FCNT_MAX; i++)
+               pf_submit ("pf_state", pf_fcounters[i], state.fcounters[i],
+                               /* is gauge = */ 0);
+       for (i = 0; i < SCNT_MAX; i++)
+               pf_submit ("pf_source", pf_scounters[i], state.scounters[i],
+                               /* is gauge = */ 0);
+
+       pf_submit ("pf_states", "current", (uint32_t) state.states,
+                       /* is gauge = */ 1);
+
+       return (0);
+} /* int pf_read */
+
+void module_register (void)
+{
+       plugin_register_read ("pf", pf_read);
+}
diff --git a/src/pinba.c b/src/pinba.c
new file mode 100644 (file)
index 0000000..9f0a800
--- /dev/null
@@ -0,0 +1,755 @@
+/**
+ * collectd - src/pinba.c (based on code from pinba_engine 0.0.5)
+ * Copyright (c) 2007-2009  Antony Dovgal
+ * Copyright (C) 2010       Phoenix Kayo
+ * Copyright (C) 2010       Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Antony Dovgal <tony at daylessday.org>
+ *   Phoenix Kayo <kayo.k11.4 at gmail.com>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <pthread.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <poll.h>
+
+#include "pinba.pb-c.h"
+
+/* AIX doesn't have MSG_DONTWAIT */
+#ifndef MSG_DONTWAIT
+#  define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
+/*
+ * Defines
+ */
+#ifndef PINBA_UDP_BUFFER_SIZE
+# define PINBA_UDP_BUFFER_SIZE 65536
+#endif
+
+#ifndef PINBA_DEFAULT_NODE
+# define PINBA_DEFAULT_NODE "::0"
+#endif
+
+#ifndef PINBA_DEFAULT_SERVICE
+# define PINBA_DEFAULT_SERVICE "30002"
+#endif
+
+#ifndef PINBA_MAX_SOCKETS
+# define PINBA_MAX_SOCKETS 16
+#endif
+
+/*
+ * Private data structures
+ */
+/* {{{ */
+struct pinba_socket_s
+{
+  struct pollfd fd[PINBA_MAX_SOCKETS];
+  nfds_t fd_num;
+};
+typedef struct pinba_socket_s pinba_socket_t;
+
+/* Fixed point counter value. n is the decimal part multiplied by 10^9. */
+struct float_counter_s
+{
+  uint64_t i;
+  uint64_t n; /* nanos */
+};
+typedef struct float_counter_s float_counter_t;
+
+struct pinba_statnode_s
+{
+  /* collector name, used as plugin instance */
+  char *name;
+
+  /* query data */
+  char *host;
+  char *server;
+  char *script;
+
+  derive_t req_count;
+
+  float_counter_t req_time;
+  float_counter_t ru_utime;
+  float_counter_t ru_stime;
+
+  derive_t doc_size;
+  gauge_t mem_peak;
+};
+typedef struct pinba_statnode_s pinba_statnode_t;
+/* }}} */
+
+/*
+ * Module global variables
+ */
+/* {{{ */
+static pinba_statnode_t *stat_nodes = NULL;
+static unsigned int stat_nodes_num = 0;
+static pthread_mutex_t stat_nodes_lock;
+
+static char *conf_node = NULL;
+static char *conf_service = NULL;
+
+static _Bool collector_thread_running = 0;
+static _Bool collector_thread_do_shutdown = 0;
+static pthread_t collector_thread_id;
+/* }}} */
+
+/*
+ * Functions
+ */
+static void float_counter_add (float_counter_t *fc, float val) /* {{{ */
+{
+  uint64_t tmp;
+
+  if (val < 0.0)
+    return;
+
+  tmp = (uint64_t) val;
+  val -= (double) tmp;
+
+  fc->i += tmp;
+  fc->n += (uint64_t) ((val * 1000000000.0) + .5);
+
+  if (fc->n >= 1000000000)
+  {
+    fc->i += 1;
+    fc->n -= 1000000000;
+    assert (fc->n < 1000000000);
+  }
+} /* }}} void float_counter_add */
+
+static derive_t float_counter_get (const float_counter_t *fc, /* {{{ */
+    uint64_t factor)
+{
+  derive_t ret;
+
+  ret = (derive_t) (fc->i * factor);
+  ret += (derive_t) (fc->n / (1000000000 / factor));
+
+  return (ret);
+} /* }}} derive_t float_counter_get */
+
+static void strset (char **str, const char *new) /* {{{ */
+{
+  char *tmp;
+
+  if (!str || !new)
+    return;
+
+  tmp = strdup (new);
+  if (tmp == NULL)
+    return;
+
+  sfree (*str);
+  *str = tmp;
+} /* }}} void strset */
+
+static void service_statnode_add(const char *name, /* {{{ */
+    const char *host,
+    const char *server,
+    const char *script)
+{
+  pinba_statnode_t *node;
+  
+  node = realloc (stat_nodes,
+      sizeof (*stat_nodes) * (stat_nodes_num + 1));
+  if (node == NULL)
+  {
+    ERROR ("pinba plugin: realloc failed");
+    return;
+  }
+  stat_nodes = node;
+
+  node = stat_nodes + stat_nodes_num;
+  memset (node, 0, sizeof (*node));
+  
+  /* reset strings */
+  node->name   = NULL;
+  node->host   = NULL;
+  node->server = NULL;
+  node->script = NULL;
+
+  node->mem_peak = NAN;
+  
+  /* fill query data */
+  strset (&node->name, name);
+  strset (&node->host, host);
+  strset (&node->server, server);
+  strset (&node->script, script);
+  
+  /* increment counter */
+  stat_nodes_num++;
+} /* }}} void service_statnode_add */
+
+/* Copy the data from the global "stat_nodes" list into the buffer pointed to
+ * by "res", doing the derivation in the process. Returns the next index or
+ * zero if the end of the list has been reached. */
+static unsigned int service_statnode_collect (pinba_statnode_t *res, /* {{{ */
+    unsigned int index)
+{
+  pinba_statnode_t *node;
+  
+  if (stat_nodes_num == 0)
+    return 0;
+  
+  /* begin collecting */
+  if (index == 0)
+    pthread_mutex_lock (&stat_nodes_lock);
+  
+  /* end collecting */
+  if (index >= stat_nodes_num)
+  {
+    pthread_mutex_unlock (&stat_nodes_lock);
+    return 0;
+  }
+
+  node = stat_nodes + index;
+  memcpy (res, node, sizeof (*res));
+
+  /* reset node */
+  node->mem_peak = NAN;
+  
+  return (index + 1);
+} /* }}} unsigned int service_statnode_collect */
+
+static void service_statnode_process (pinba_statnode_t *node, /* {{{ */
+    Pinba__Request* request)
+{
+  node->req_count++;
+
+  float_counter_add (&node->req_time, request->request_time);
+  float_counter_add (&node->ru_utime, request->ru_utime);
+  float_counter_add (&node->ru_stime, request->ru_stime);
+
+  node->doc_size += request->document_size;
+
+  if (isnan (node->mem_peak)
+      || (node->mem_peak < ((gauge_t) request->memory_peak)))
+    node->mem_peak = (gauge_t) request->memory_peak;
+
+} /* }}} void service_statnode_process */
+
+static void service_process_request (Pinba__Request *request) /* {{{ */
+{
+  unsigned int i;
+
+  pthread_mutex_lock (&stat_nodes_lock);
+  
+  for (i = 0; i < stat_nodes_num; i++)
+  {
+    if ((stat_nodes[i].host != NULL)
+        && (strcmp (request->hostname, stat_nodes[i].host) != 0))
+      continue;
+
+    if ((stat_nodes[i].server != NULL)
+      && (strcmp (request->server_name, stat_nodes[i].server) != 0))
+      continue;
+
+    if ((stat_nodes[i].script != NULL)
+      && (strcmp (request->script_name, stat_nodes[i].script) != 0))
+      continue;
+
+    service_statnode_process(&stat_nodes[i], request);
+  }
+  
+  pthread_mutex_unlock(&stat_nodes_lock);
+} /* }}} void service_process_request */
+
+static int pb_del_socket (pinba_socket_t *s, /* {{{ */
+    nfds_t index)
+{
+  if (index >= s->fd_num)
+    return (EINVAL);
+
+  close (s->fd[index].fd);
+  s->fd[index].fd = -1;
+
+  /* When deleting the last element in the list, no memmove is necessary. */
+  if (index < (s->fd_num - 1))
+  {
+    memmove (&s->fd[index], &s->fd[index + 1],
+        sizeof (s->fd[0]) * (s->fd_num - (index + 1)));
+  }
+
+  s->fd_num--;
+  return (0);
+} /* }}} int pb_del_socket */
+
+static int pb_add_socket (pinba_socket_t *s, /* {{{ */
+    const struct addrinfo *ai)
+{
+  int fd;
+  int tmp;
+  int status;
+
+  if (s->fd_num == PINBA_MAX_SOCKETS)
+  {
+    WARNING ("pinba plugin: Sorry, you have hit the built-in limit of "
+        "%i sockets. Please complain to the collectd developers so we can "
+        "raise the limit.", PINBA_MAX_SOCKETS);
+    return (-1);
+  }
+
+  fd = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+  if (fd < 0)
+  {
+    char errbuf[1024];
+    ERROR ("pinba plugin: socket(2) failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (0);
+  }
+
+  tmp = 1;
+  status = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof (tmp));
+  if (status != 0)
+  {
+    char errbuf[1024];
+    WARNING ("pinba plugin: setsockopt(SO_REUSEADDR) failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+  }
+
+  status = bind (fd, ai->ai_addr, ai->ai_addrlen);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("pinba plugin: bind(2) failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (0);
+  }
+
+  s->fd[s->fd_num].fd = fd;
+  s->fd[s->fd_num].events = POLLIN | POLLPRI;
+  s->fd[s->fd_num].revents = 0;
+  s->fd_num++;
+
+  return (0);
+} /* }}} int pb_add_socket */
+
+static pinba_socket_t *pinba_socket_open (const char *node, /* {{{ */
+    const char *service)
+{
+  pinba_socket_t *s;
+  struct addrinfo *ai_list;
+  struct addrinfo *ai_ptr;
+  struct addrinfo  ai_hints;
+  int status;
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags = AI_PASSIVE;
+  ai_hints.ai_family = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_DGRAM;
+  ai_hints.ai_addr = NULL;
+  ai_hints.ai_canonname = NULL;
+  ai_hints.ai_next = NULL;
+
+  if (node == NULL)
+    node = PINBA_DEFAULT_NODE;
+
+  if (service == NULL)
+    service = PINBA_DEFAULT_SERVICE;
+
+  ai_list = NULL;
+  status = getaddrinfo (node, service,
+      &ai_hints, &ai_list);
+  if (status != 0)
+  {
+    ERROR ("pinba plugin: getaddrinfo(3) failed: %s",
+        gai_strerror (status));
+    return (NULL);
+  }
+  assert (ai_list != NULL);
+
+  s = malloc (sizeof (*s));
+  if (s == NULL)
+  {
+    freeaddrinfo (ai_list);
+    ERROR ("pinba plugin: malloc failed.");
+    return (NULL);
+  }
+  memset (s, 0, sizeof (*s));
+
+  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    status = pb_add_socket (s, ai_ptr);
+    if (status != 0)
+      break;
+  } /* for (ai_list) */
+  
+  freeaddrinfo (ai_list);
+
+  if (s->fd_num < 1)
+  {
+    WARNING ("pinba plugin: Unable to open socket for address %s.", node);
+    sfree (s);
+    s = NULL;
+  }
+
+  return (s);
+} /* }}} pinba_socket_open */
+
+static void pinba_socket_free (pinba_socket_t *socket) /* {{{ */
+{
+  nfds_t i;
+
+  if (!socket)
+    return;
+  
+  for (i = 0; i < socket->fd_num; i++)
+  {
+    if (socket->fd[i].fd < 0)
+      continue;
+    close (socket->fd[i].fd);
+    socket->fd[i].fd = -1;
+  }
+  
+  sfree(socket);
+} /* }}} void pinba_socket_free */
+
+static int pinba_process_stats_packet (const uint8_t *buffer, /* {{{ */
+    size_t buffer_size)
+{
+  Pinba__Request *request;  
+  
+  request = pinba__request__unpack (NULL, buffer_size, buffer);
+  
+  if (!request)
+    return (-1);
+
+  service_process_request(request);
+  pinba__request__free_unpacked (request, NULL);
+    
+  return (0);
+} /* }}} int pinba_process_stats_packet */
+
+static int pinba_udp_read_callback_fn (int sock) /* {{{ */
+{
+  uint8_t buffer[PINBA_UDP_BUFFER_SIZE];
+  size_t buffer_size;
+  int status;
+
+  while (42)
+  {
+    buffer_size = sizeof (buffer);
+    status = recvfrom (sock, buffer, buffer_size - 1, MSG_DONTWAIT, /* from = */ NULL, /* from len = */ 0);
+    if (status < 0)
+    {
+      char errbuf[1024];
+
+      if ((errno == EINTR)
+#ifdef EWOULDBLOCK
+          || (errno == EWOULDBLOCK)
+#endif
+          || (errno == EAGAIN))
+      {
+        continue;
+      }
+
+      WARNING("pinba plugin: recvfrom(2) failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (-1);
+    }
+    else if (status == 0)
+    {
+      DEBUG ("pinba plugin: recvfrom(2) returned unexpected status zero.");
+      return (-1);
+    }
+    else /* if (status > 0) */
+    {
+      assert (((size_t) status) < buffer_size);
+      buffer_size = (size_t) status;
+      buffer[buffer_size] = 0;
+
+      status = pinba_process_stats_packet (buffer, buffer_size);
+      if (status != 0)
+        DEBUG("pinba plugin: Parsing packet failed.");
+      return (status);
+    }
+  } /* while (42) */
+
+  /* not reached */
+  assert (23 == 42);
+  return (-1);
+} /* }}} void pinba_udp_read_callback_fn */
+
+static int receive_loop (void) /* {{{ */
+{
+  pinba_socket_t *s;
+
+  s = pinba_socket_open (conf_node, conf_service);
+  if (s == NULL)
+  {
+    ERROR ("pinba plugin: Collector thread is exiting prematurely.");
+    return (-1);
+  }
+
+  while (!collector_thread_do_shutdown)
+  {
+    int status;
+    nfds_t i;
+
+    if (s->fd_num < 1)
+      break;
+
+    status = poll (s->fd, s->fd_num, /* timeout = */ 1000);
+    if (status == 0) /* timeout */
+    {
+      continue;
+    }
+    else if (status < 0)
+    {
+      char errbuf[1024];
+
+      if ((errno == EINTR) || (errno == EAGAIN))
+        continue;
+
+      ERROR ("pinba plugin: poll(2) failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      pinba_socket_free (s);
+      return (-1);
+    }
+
+    for (i = 0; i < s->fd_num; i++)
+    {
+      if (s->fd[i].revents & (POLLERR | POLLHUP | POLLNVAL))
+      {
+        pb_del_socket (s, i);
+        i--;
+      }
+      else if (s->fd[i].revents & (POLLIN | POLLPRI))
+      {
+        pinba_udp_read_callback_fn (s->fd[i].fd);
+      }
+    } /* for (s->fd) */
+  } /* while (!collector_thread_do_shutdown) */
+
+  pinba_socket_free (s);
+  s = NULL;
+
+  return (0);
+} /* }}} int receive_loop */
+
+static void *collector_thread (void *arg) /* {{{ */
+{
+  receive_loop ();
+
+  memset (&collector_thread_id, 0, sizeof (collector_thread_id));
+  collector_thread_running = 0;
+  pthread_exit (NULL);
+  return (NULL);
+} /* }}} void *collector_thread */
+
+/*
+ * Plugin declaration section
+ */
+static int pinba_config_view (const oconfig_item_t *ci) /* {{{ */
+{
+  char *name   = NULL;
+  char *host   = NULL;
+  char *server = NULL;
+  char *script = NULL;
+  int status;
+  int i;
+
+  status = cf_util_get_string (ci, &name);
+  if (status != 0)
+    return (status);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &host);
+    else if (strcasecmp ("Server", child->key) == 0)
+      status = cf_util_get_string (child, &server);
+    else if (strcasecmp ("Script", child->key) == 0)
+      status = cf_util_get_string (child, &script);
+    else
+    {
+      WARNING ("pinba plugin: Unknown config option: %s", child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if (status == 0)
+    service_statnode_add (name, host, server, script);
+
+  sfree (name);
+  sfree (host);
+  sfree (server);
+  sfree (script);
+
+  return (status);
+} /* }}} int pinba_config_view */
+
+static int plugin_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+  
+  /* The lock should not be necessary in the config callback, but let's be
+   * sure.. */
+  pthread_mutex_lock (&stat_nodes_lock);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Address", child->key) == 0)
+      cf_util_get_string (child, &conf_node);
+    else if (strcasecmp ("Port", child->key) == 0)
+      cf_util_get_service (child, &conf_service);
+    else if (strcasecmp ("View", child->key) == 0)
+      pinba_config_view (child);
+    else
+      WARNING ("pinba plugin: Unknown config option: %s", child->key);
+  }
+
+  pthread_mutex_unlock(&stat_nodes_lock);
+  
+  return (0);
+} /* }}} int pinba_config */
+
+static int plugin_init (void) /* {{{ */
+{
+  int status;
+
+  if (stat_nodes == NULL)
+  {
+    /* Collect the "total" data by default. */
+    service_statnode_add ("total",
+        /* host   = */ NULL,
+        /* server = */ NULL,
+        /* script = */ NULL);
+  }
+
+  if (collector_thread_running)
+    return (0);
+
+  status = plugin_thread_create (&collector_thread_id,
+      /* attrs = */ NULL,
+      collector_thread,
+      /* args = */ NULL);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("pinba plugin: pthread_create(3) failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+  collector_thread_running = 1;
+
+  return (0);
+} /* }}} */
+
+static int plugin_shutdown (void) /* {{{ */
+{
+  if (collector_thread_running)
+  {
+    int status;
+
+    DEBUG ("pinba plugin: Shutting down collector thread.");
+    collector_thread_do_shutdown = 1;
+
+    status = pthread_join (collector_thread_id, /* retval = */ NULL);
+    if (status != 0)
+    {
+      char errbuf[1024];
+      ERROR ("pinba plugin: pthread_join(3) failed: %s",
+          sstrerror (status, errbuf, sizeof (errbuf)));
+    }
+
+    collector_thread_running = 0;
+    collector_thread_do_shutdown = 0;
+  } /* if (collector_thread_running) */
+
+  return (0);
+} /* }}} int plugin_shutdown */
+
+static int plugin_submit (const pinba_statnode_t *res) /* {{{ */
+{
+  value_t value;
+  value_list_t vl = VALUE_LIST_INIT;
+  
+  vl.values = &value;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "pinba", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, res->name, sizeof (vl.plugin_instance));
+
+  value.derive = res->req_count;
+  sstrncpy (vl.type, "total_requests", sizeof (vl.type)); 
+  plugin_dispatch_values (&vl);
+
+  value.derive = float_counter_get (&res->req_time, /* factor = */ 1000);
+  sstrncpy (vl.type, "total_time_in_ms", sizeof (vl.type)); 
+  plugin_dispatch_values (&vl);
+
+  value.derive = res->doc_size;
+  sstrncpy (vl.type, "total_bytes", sizeof (vl.type)); 
+  plugin_dispatch_values (&vl);
+
+  value.derive = float_counter_get (&res->ru_utime, /* factor = */ 100);
+  sstrncpy (vl.type, "cpu", sizeof (vl.type));
+  sstrncpy (vl.type_instance, "user", sizeof (vl.type_instance));
+  plugin_dispatch_values (&vl);
+
+  value.derive = float_counter_get (&res->ru_stime, /* factor = */ 100);
+  sstrncpy (vl.type, "cpu", sizeof (vl.type));
+  sstrncpy (vl.type_instance, "system", sizeof (vl.type_instance));
+  plugin_dispatch_values (&vl);
+
+  value.gauge = res->mem_peak;
+  sstrncpy (vl.type, "memory", sizeof (vl.type));
+  sstrncpy (vl.type_instance, "peak", sizeof (vl.type_instance));
+  plugin_dispatch_values (&vl);
+
+  return (0);
+} /* }}} int plugin_submit */
+
+static int plugin_read (void) /* {{{ */
+{
+  unsigned int i=0;
+  pinba_statnode_t data;
+  
+  while ((i = service_statnode_collect (&data, i)) != 0)
+  {
+    plugin_submit (&data);
+  }
+  
+  return 0;
+} /* }}} int plugin_read */
+
+void module_register (void) /* {{{ */
+{
+  plugin_register_complex_config ("pinba", plugin_config);
+  plugin_register_init ("pinba", plugin_init);
+  plugin_register_read ("pinba", plugin_read);
+  plugin_register_shutdown ("pinba", plugin_shutdown);
+} /* }}} void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/pinba.proto b/src/pinba.proto
new file mode 100644 (file)
index 0000000..5fd5439
--- /dev/null
@@ -0,0 +1,22 @@
+package Pinba;
+option optimize_for = SPEED;
+
+message Request {
+       required string hostname                = 1;
+       required string server_name             = 2;
+       required string script_name             = 3;
+       required uint32 request_count   = 4;
+       required uint32 document_size   = 5;
+       required uint32 memory_peak             = 6;
+       required float request_time             = 7;
+       required float ru_utime                 = 8;
+       required float ru_stime                 = 9;
+
+       repeated uint32 timer_hit_count = 10;
+       repeated float timer_value      = 11;
+       repeated uint32 timer_tag_count = 12;
+       repeated uint32 timer_tag_name  = 13;
+       repeated uint32 timer_tag_value = 14;
+       repeated string dictionary      = 15;
+       optional uint32 status          = 16;
+}
diff --git a/src/ping.c b/src/ping.c
new file mode 100644 (file)
index 0000000..216feda
--- /dev/null
@@ -0,0 +1,702 @@
+/**
+ * collectd - src/ping.c
+ * Copyright (C) 2005-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_complain.h"
+
+#include <pthread.h>
+#include <netinet/in.h>
+#if HAVE_NETDB_H
+# include <netdb.h> /* NI_MAXHOST */
+#endif
+
+#include <oping.h>
+
+#ifndef NI_MAXHOST
+# define NI_MAXHOST 1025
+#endif
+
+#if defined(OPING_VERSION) && (OPING_VERSION >= 1003000)
+# define HAVE_OPING_1_3
+#endif
+
+/*
+ * Private data types
+ */
+struct hostlist_s
+{
+  char *host;
+
+  uint32_t pkg_sent;
+  uint32_t pkg_recv;
+  uint32_t pkg_missed;
+
+  double latency_total;
+  double latency_squared;
+
+  struct hostlist_s *next;
+};
+typedef struct hostlist_s hostlist_t;
+
+/*
+ * Private variables
+ */
+static hostlist_t *hostlist_head = NULL;
+
+static char  *ping_source = NULL;
+#ifdef HAVE_OPING_1_3
+static char  *ping_device = NULL;
+#endif
+static int    ping_ttl = PING_DEF_TTL;
+static double ping_interval = 1.0;
+static double ping_timeout = 0.9;
+static int    ping_max_missed = -1;
+
+static int             ping_thread_loop = 0;
+static int             ping_thread_error = 0;
+static pthread_t       ping_thread_id;
+static pthread_mutex_t ping_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  ping_cond = PTHREAD_COND_INITIALIZER;
+
+static const char *config_keys[] =
+{
+  "Host",
+  "SourceAddress",
+#ifdef HAVE_OPING_1_3
+  "Device",
+#endif
+  "TTL",
+  "Interval",
+  "Timeout",
+  "MaxMissed"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+/*
+ * Private functions
+ */
+/* Assure that `ts->tv_nsec' is in the range 0 .. 999999999 */
+static void time_normalize (struct timespec *ts) /* {{{ */
+{
+  while (ts->tv_nsec < 0)
+  {
+    if (ts->tv_sec == 0)
+    {
+      ts->tv_nsec = 0;
+      return;
+    }
+
+    ts->tv_sec  -= 1;
+    ts->tv_nsec += 1000000000;
+  }
+
+  while (ts->tv_nsec >= 1000000000)
+  {
+    ts->tv_sec  += 1;
+    ts->tv_nsec -= 1000000000;
+  }
+} /* }}} void time_normalize */
+
+/* Add `ts_int' to `tv_begin' and store the result in `ts_dest'. If the result
+ * is larger than `tv_end', copy `tv_end' to `ts_dest' instead. */
+static void time_calc (struct timespec *ts_dest, /* {{{ */
+    const struct timespec *ts_int,
+    const struct timeval  *tv_begin,
+    const struct timeval  *tv_end)
+{
+  ts_dest->tv_sec = tv_begin->tv_sec + ts_int->tv_sec;
+  ts_dest->tv_nsec = (tv_begin->tv_usec * 1000) + ts_int->tv_nsec;
+  time_normalize (ts_dest);
+
+  /* Assure that `(begin + interval) > end'.
+   * This may seem overly complicated, but `tv_sec' is of type `time_t'
+   * which may be `unsigned. *sigh* */
+  if ((tv_end->tv_sec > ts_dest->tv_sec)
+      || ((tv_end->tv_sec == ts_dest->tv_sec)
+        && ((tv_end->tv_usec * 1000) > ts_dest->tv_nsec)))
+  {
+    ts_dest->tv_sec = tv_end->tv_sec;
+    ts_dest->tv_nsec = 1000 * tv_end->tv_usec;
+  }
+
+  time_normalize (ts_dest);
+} /* }}} void time_calc */
+
+static int ping_dispatch_all (pingobj_t *pingobj) /* {{{ */
+{
+  pingobj_iter_t *iter;
+  hostlist_t *hl;
+  int status;
+
+  for (iter = ping_iterator_get (pingobj);
+      iter != NULL;
+      iter = ping_iterator_next (iter))
+  { /* {{{ */
+    char userhost[NI_MAXHOST];
+    double latency;
+    size_t param_size;
+
+    param_size = sizeof (userhost);
+    status = ping_iterator_get_info (iter,
+#ifdef PING_INFO_USERNAME
+        PING_INFO_USERNAME,
+#else
+        PING_INFO_HOSTNAME,
+#endif
+        userhost, &param_size);
+    if (status != 0)
+    {
+      WARNING ("ping plugin: ping_iterator_get_info failed: %s",
+          ping_get_error (pingobj));
+      continue;
+    }
+
+    for (hl = hostlist_head; hl != NULL; hl = hl->next)
+      if (strcmp (userhost, hl->host) == 0)
+        break;
+
+    if (hl == NULL)
+    {
+      WARNING ("ping plugin: Cannot find host %s.", userhost);
+      continue;
+    }
+
+    param_size = sizeof (latency);
+    status = ping_iterator_get_info (iter, PING_INFO_LATENCY,
+        (void *) &latency, &param_size);
+    if (status != 0)
+    {
+      WARNING ("ping plugin: ping_iterator_get_info failed: %s",
+          ping_get_error (pingobj));
+      continue;
+    }
+
+    hl->pkg_sent++;
+    if (latency >= 0.0)
+    {
+      hl->pkg_recv++;
+      hl->latency_total += latency;
+      hl->latency_squared += (latency * latency);
+
+      /* reset missed packages counter */
+      hl->pkg_missed = 0;
+    } else
+      hl->pkg_missed++;
+
+    /* if the host did not answer our last N packages, trigger a resolv. */
+    if (ping_max_missed >= 0 && hl->pkg_missed >= ping_max_missed)
+    { /* {{{ */
+      /* we reset the missed package counter here, since we only want to
+       * trigger a resolv every N packages and not every package _AFTER_ N
+       * missed packages */
+      hl->pkg_missed = 0;
+
+      WARNING ("ping plugin: host %s has not answered %d PING requests,"
+          " triggering resolve", hl->host, ping_max_missed);
+
+      /* we trigger the resolv simply be removeing and adding the host to our
+       * ping object */
+      status = ping_host_remove (pingobj, hl->host);
+      if (status != 0)
+      {
+        WARNING ("ping plugin: ping_host_remove (%s) failed.", hl->host);
+      }
+      else
+      {
+        status = ping_host_add (pingobj, hl->host);
+        if (status != 0)
+          ERROR ("ping plugin: ping_host_add (%s) failed.", hl->host);
+      }
+    } /* }}} ping_max_missed */
+  } /* }}} for (iter) */
+
+  return (0);
+} /* }}} int ping_dispatch_all */
+
+static void *ping_thread (void *arg) /* {{{ */
+{
+  static pingobj_t *pingobj = NULL;
+
+  struct timeval  tv_begin;
+  struct timeval  tv_end;
+  struct timespec ts_wait;
+  struct timespec ts_int;
+
+  hostlist_t *hl;
+  int count;
+
+  c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
+
+  pthread_mutex_lock (&ping_lock);
+
+  pingobj = ping_construct ();
+  if (pingobj == NULL)
+  {
+    ERROR ("ping plugin: ping_construct failed.");
+    ping_thread_error = 1;
+    pthread_mutex_unlock (&ping_lock);
+    return ((void *) -1);
+  }
+
+  if (ping_source != NULL)
+    if (ping_setopt (pingobj, PING_OPT_SOURCE, (void *) ping_source) != 0)
+      ERROR ("ping plugin: Failed to set source address: %s",
+          ping_get_error (pingobj));
+
+#ifdef HAVE_OPING_1_3
+  if (ping_device != NULL)
+    if (ping_setopt (pingobj, PING_OPT_DEVICE, (void *) ping_device) != 0)
+      ERROR ("ping plugin: Failed to set device: %s",
+          ping_get_error (pingobj));
+#endif
+
+  ping_setopt (pingobj, PING_OPT_TIMEOUT, (void *) &ping_timeout);
+  ping_setopt (pingobj, PING_OPT_TTL, (void *) &ping_ttl);
+
+  /* Add all the hosts to the ping object. */
+  count = 0;
+  for (hl = hostlist_head; hl != NULL; hl = hl->next)
+  {
+    int tmp_status;
+    tmp_status = ping_host_add (pingobj, hl->host);
+    if (tmp_status != 0)
+      WARNING ("ping plugin: ping_host_add (%s) failed: %s",
+          hl->host, ping_get_error (pingobj));
+    else
+      count++;
+  }
+
+  if (count == 0)
+  {
+    ERROR ("ping plugin: No host could be added to ping object. Giving up.");
+    ping_thread_error = 1;
+    pthread_mutex_unlock (&ping_lock);
+    return ((void *) -1);
+  }
+
+  /* Set up `ts_int' */
+  {
+    double temp_sec;
+    double temp_nsec;
+
+    temp_nsec = modf (ping_interval, &temp_sec);
+    ts_int.tv_sec  = (time_t) temp_sec;
+    ts_int.tv_nsec = (long) (temp_nsec * 1000000000L);
+  }
+
+  while (ping_thread_loop > 0)
+  {
+    int status;
+    _Bool send_successful = 0;
+
+    if (gettimeofday (&tv_begin, NULL) < 0)
+    {
+      char errbuf[1024];
+      ERROR ("ping plugin: gettimeofday failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      ping_thread_error = 1;
+      break;
+    }
+
+    pthread_mutex_unlock (&ping_lock);
+
+    status = ping_send (pingobj);
+    if (status < 0)
+    {
+      c_complain (LOG_ERR, &complaint, "ping plugin: ping_send failed: %s",
+          ping_get_error (pingobj));
+    }
+    else
+    {
+      c_release (LOG_NOTICE, &complaint, "ping plugin: ping_send succeeded.");
+      send_successful = 1;
+    }
+
+    pthread_mutex_lock (&ping_lock);
+
+    if (ping_thread_loop <= 0)
+      break;
+
+    if (send_successful)
+      (void) ping_dispatch_all (pingobj);
+
+    if (gettimeofday (&tv_end, NULL) < 0)
+    {
+      char errbuf[1024];
+      ERROR ("ping plugin: gettimeofday failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      ping_thread_error = 1;
+      break;
+    }
+
+    /* Calculate the absolute time until which to wait and store it in
+     * `ts_wait'. */
+    time_calc (&ts_wait, &ts_int, &tv_begin, &tv_end);
+
+    status = pthread_cond_timedwait (&ping_cond, &ping_lock, &ts_wait);
+    if (ping_thread_loop <= 0)
+      break;
+  } /* while (ping_thread_loop > 0) */
+
+  pthread_mutex_unlock (&ping_lock);
+  ping_destroy (pingobj);
+
+  return ((void *) 0);
+} /* }}} void *ping_thread */
+
+static int start_thread (void) /* {{{ */
+{
+  int status;
+
+  pthread_mutex_lock (&ping_lock);
+
+  if (ping_thread_loop != 0)
+  {
+    pthread_mutex_unlock (&ping_lock);
+    return (-1);
+  }
+
+  ping_thread_loop = 1;
+  ping_thread_error = 0;
+  status = plugin_thread_create (&ping_thread_id, /* attr = */ NULL,
+      ping_thread, /* arg = */ (void *) 0);
+  if (status != 0)
+  {
+    ping_thread_loop = 0;
+    ERROR ("ping plugin: Starting thread failed.");
+    pthread_mutex_unlock (&ping_lock);
+    return (-1);
+  }
+    
+  pthread_mutex_unlock (&ping_lock);
+  return (0);
+} /* }}} int start_thread */
+
+static int stop_thread (void) /* {{{ */
+{
+  int status;
+
+  pthread_mutex_lock (&ping_lock);
+
+  if (ping_thread_loop == 0)
+  {
+    pthread_mutex_unlock (&ping_lock);
+    return (-1);
+  }
+
+  ping_thread_loop = 0;
+  pthread_cond_broadcast (&ping_cond);
+  pthread_mutex_unlock (&ping_lock);
+
+  status = pthread_join (ping_thread_id, /* return = */ NULL);
+  if (status != 0)
+  {
+    ERROR ("ping plugin: Stopping thread failed.");
+    status = -1;
+  }
+
+  memset (&ping_thread_id, 0, sizeof (ping_thread_id));
+  ping_thread_error = 0;
+
+  return (status);
+} /* }}} int stop_thread */
+
+static int ping_init (void) /* {{{ */
+{
+  if (hostlist_head == NULL)
+  {
+    NOTICE ("ping plugin: No hosts have been configured.");
+    return (-1);
+  }
+
+  if (ping_timeout > ping_interval)
+  {
+    ping_timeout = 0.9 * ping_interval;
+    WARNING ("ping plugin: Timeout is greater than interval. "
+        "Will use a timeout of %gs.", ping_timeout);
+  }
+
+  if (start_thread () != 0)
+    return (-1);
+
+  return (0);
+} /* }}} int ping_init */
+
+static int config_set_string (const char *name, /* {{{ */
+    char **var, const char *value)
+{
+  char *tmp;
+
+  tmp = strdup (value);
+  if (tmp == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("ping plugin: Setting `%s' to `%s' failed: strdup failed: %s",
+        name, value, sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (1);
+  }
+
+  if (*var != NULL)
+    free (*var);
+  *var = tmp;
+  return (0);
+} /* }}} int config_set_string */
+
+static int ping_config (const char *key, const char *value) /* {{{ */
+{
+  if (strcasecmp (key, "Host") == 0)
+  {
+    hostlist_t *hl;
+    char *host;
+
+    hl = (hostlist_t *) malloc (sizeof (hostlist_t));
+    if (hl == NULL)
+    {
+      char errbuf[1024];
+      ERROR ("ping plugin: malloc failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (1);
+    }
+
+    host = strdup (value);
+    if (host == NULL)
+    {
+      char errbuf[1024];
+      sfree (hl);
+      ERROR ("ping plugin: strdup failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (1);
+    }
+
+    hl->host = host;
+    hl->pkg_sent = 0;
+    hl->pkg_recv = 0;
+    hl->pkg_missed = 0;
+    hl->latency_total = 0.0;
+    hl->latency_squared = 0.0;
+    hl->next = hostlist_head;
+    hostlist_head = hl;
+  }
+  else if (strcasecmp (key, "SourceAddress") == 0)
+  {
+    int status = config_set_string (key, &ping_source, value);
+    if (status != 0)
+      return (status);
+  }
+#ifdef HAVE_OPING_1_3
+  else if (strcasecmp (key, "Device") == 0)
+  {
+    int status = config_set_string (key, &ping_device, value);
+    if (status != 0)
+      return (status);
+  }
+#endif
+  else if (strcasecmp (key, "TTL") == 0)
+  {
+    int ttl = atoi (value);
+    if ((ttl > 0) && (ttl <= 255))
+      ping_ttl = ttl;
+    else
+      WARNING ("ping plugin: Ignoring invalid TTL %i.", ttl);
+  }
+  else if (strcasecmp (key, "Interval") == 0)
+  {
+    double tmp;
+
+    tmp = atof (value);
+    if (tmp > 0.0)
+      ping_interval = tmp;
+    else
+      WARNING ("ping plugin: Ignoring invalid interval %g (%s)",
+          tmp, value);
+  }
+  else if (strcasecmp (key, "Timeout") == 0)
+  {
+    double tmp;
+
+    tmp = atof (value);
+    if (tmp > 0.0)
+      ping_timeout = tmp;
+    else
+      WARNING ("ping plugin: Ignoring invalid timeout %g (%s)",
+          tmp, value);
+  }
+  else if (strcasecmp (key, "MaxMissed") == 0)
+  {
+    ping_max_missed = atoi (value);
+    if (ping_max_missed < 0)
+      INFO ("ping plugin: MaxMissed < 0, disabled re-resolving of hosts");
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int ping_config */
+
+static void submit (const char *host, const char *type, /* {{{ */
+    gauge_t value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0].gauge = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "ping", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+  sstrncpy (vl.type_instance, host, sizeof (vl.type_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+
+  plugin_dispatch_values (&vl);
+} /* }}} void ping_submit */
+
+static int ping_read (void) /* {{{ */
+{
+  hostlist_t *hl;
+
+  if (ping_thread_error != 0)
+  {
+    ERROR ("ping plugin: The ping thread had a problem. Restarting it.");
+
+    stop_thread ();
+
+    for (hl = hostlist_head; hl != NULL; hl = hl->next)
+    {
+      hl->pkg_sent = 0;
+      hl->pkg_recv = 0;
+      hl->latency_total = 0.0;
+      hl->latency_squared = 0.0;
+    }
+
+    start_thread ();
+
+    return (-1);
+  } /* if (ping_thread_error != 0) */
+
+  for (hl = hostlist_head; hl != NULL; hl = hl->next) /* {{{ */
+  {
+    uint32_t pkg_sent;
+    uint32_t pkg_recv;
+    double latency_total;
+    double latency_squared;
+
+    double latency_average;
+    double latency_stddev;
+
+    double droprate;
+
+    /* Locking here works, because the structure of the linked list is only
+     * changed during configure and shutdown. */
+    pthread_mutex_lock (&ping_lock);
+
+    pkg_sent = hl->pkg_sent;
+    pkg_recv = hl->pkg_recv;
+    latency_total = hl->latency_total;
+    latency_squared = hl->latency_squared;
+
+    hl->pkg_sent = 0;
+    hl->pkg_recv = 0;
+    hl->latency_total = 0.0;
+    hl->latency_squared = 0.0;
+
+    pthread_mutex_unlock (&ping_lock);
+
+    /* This e. g. happens when starting up. */
+    if (pkg_sent == 0)
+    {
+      DEBUG ("ping plugin: No packages for host %s have been sent.",
+          hl->host);
+      continue;
+    }
+
+    /* Calculate average. Beware of division by zero. */
+    if (pkg_recv == 0)
+      latency_average = NAN;
+    else
+      latency_average = latency_total / ((double) pkg_recv);
+
+    /* Calculate standard deviation. Beware even more of division by zero. */
+    if (pkg_recv == 0)
+      latency_stddev = NAN;
+    else if (pkg_recv == 1)
+      latency_stddev = 0.0;
+    else
+      latency_stddev = sqrt (((((double) pkg_recv) * latency_squared)
+          - (latency_total * latency_total))
+          / ((double) (pkg_recv * (pkg_recv - 1))));
+
+    /* Calculate drop rate. */
+    droprate = ((double) (pkg_sent - pkg_recv)) / ((double) pkg_sent);
+
+    submit (hl->host, "ping", latency_average);
+    submit (hl->host, "ping_stddev", latency_stddev);
+    submit (hl->host, "ping_droprate", droprate);
+  } /* }}} for (hl = hostlist_head; hl != NULL; hl = hl->next) */
+
+  return (0);
+} /* }}} int ping_read */
+
+static int ping_shutdown (void) /* {{{ */
+{
+  hostlist_t *hl;
+
+  INFO ("ping plugin: Shutting down thread.");
+  if (stop_thread () < 0)
+    return (-1);
+
+  hl = hostlist_head;
+  while (hl != NULL)
+  {
+    hostlist_t *hl_next;
+
+    hl_next = hl->next;
+
+    sfree (hl->host);
+    sfree (hl);
+
+    hl = hl_next;
+  }
+
+  return (0);
+} /* }}} int ping_shutdown */
+
+void module_register (void)
+{
+  plugin_register_config ("ping", ping_config,
+      config_keys, config_keys_num);
+  plugin_register_init ("ping", ping_init);
+  plugin_register_read ("ping", ping_read);
+  plugin_register_shutdown ("ping", ping_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/postgresql.c b/src/postgresql.c
new file mode 100644 (file)
index 0000000..54c856d
--- /dev/null
@@ -0,0 +1,1368 @@
+/**
+ * collectd - src/postgresql.c
+ * Copyright (C) 2008-2012  Sebastian Harl
+ * Copyright (C) 2009       Florian Forster
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+/*
+ * This module collects PostgreSQL database statistics.
+ */
+
+#include "collectd.h"
+#include "common.h"
+
+#include "configfile.h"
+#include "plugin.h"
+
+#include "utils_cache.h"
+#include "utils_db_query.h"
+#include "utils_complain.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+#include <pg_config_manual.h>
+#include <libpq-fe.h>
+
+#define log_err(...) ERROR ("postgresql: " __VA_ARGS__)
+#define log_warn(...) WARNING ("postgresql: " __VA_ARGS__)
+#define log_info(...) INFO ("postgresql: " __VA_ARGS__)
+#define log_debug(...) DEBUG ("postgresql: " __VA_ARGS__)
+
+#ifndef C_PSQL_DEFAULT_CONF
+# define C_PSQL_DEFAULT_CONF PKGDATADIR "/postgresql_default.conf"
+#endif
+
+/* Appends the (parameter, value) pair to the string
+ * pointed to by 'buf' suitable to be used as argument
+ * for PQconnectdb(). If value equals NULL, the pair
+ * is ignored. */
+#define C_PSQL_PAR_APPEND(buf, buf_len, parameter, value) \
+       if ((0 < (buf_len)) && (NULL != (value)) && ('\0' != *(value))) { \
+               int s = ssnprintf (buf, buf_len, " %s = '%s'", parameter, value); \
+               if (0 < s) { \
+                       buf     += s; \
+                       buf_len -= s; \
+               } \
+       }
+
+/* Returns the tuple (major, minor, patchlevel)
+ * for the given version number. */
+#define C_PSQL_SERVER_VERSION3(server_version) \
+       (server_version) / 10000, \
+       (server_version) / 100 - (int)((server_version) / 10000) * 100, \
+       (server_version) - (int)((server_version) / 100) * 100
+
+/* Returns true if the given host specifies a
+ * UNIX domain socket. */
+#define C_PSQL_IS_UNIX_DOMAIN_SOCKET(host) \
+       ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
+
+/* Returns the tuple (host, delimiter, port) for a
+ * given (host, port) pair. Depending on the value of
+ * 'host' a UNIX domain socket or a TCP socket is
+ * assumed. */
+#define C_PSQL_SOCKET3(host, port) \
+       ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, \
+       C_PSQL_IS_UNIX_DOMAIN_SOCKET (host) ? "/.s.PGSQL." : ":", \
+       port
+
+typedef enum {
+       C_PSQL_PARAM_HOST = 1,
+       C_PSQL_PARAM_DB,
+       C_PSQL_PARAM_USER,
+       C_PSQL_PARAM_INTERVAL,
+       C_PSQL_PARAM_INSTANCE,
+} c_psql_param_t;
+
+/* Parameter configuration. Stored as `user data' in the query objects. */
+typedef struct {
+       c_psql_param_t *params;
+       int             params_num;
+} c_psql_user_data_t;
+
+typedef struct {
+       char *name;
+       char *statement;
+       _Bool store_rates;
+} c_psql_writer_t;
+
+typedef struct {
+       PGconn      *conn;
+       c_complain_t conn_complaint;
+
+       int proto_version;
+       int server_version;
+
+       int max_params_num;
+
+       /* user configuration */
+       udb_query_preparation_area_t **q_prep_areas;
+       udb_query_t    **queries;
+       size_t           queries_num;
+
+       c_psql_writer_t **writers;
+       size_t            writers_num;
+
+       /* make sure we don't access the database object in parallel */
+       pthread_mutex_t   db_lock;
+
+       cdtime_t interval;
+
+       /* writer "caching" settings */
+       cdtime_t commit_interval;
+       cdtime_t next_commit;
+       cdtime_t expire_delay;
+
+       char *host;
+       char *port;
+       char *database;
+       char *user;
+       char *password;
+
+       char *instance;
+
+       char *sslmode;
+
+       char *krbsrvname;
+
+       char *service;
+
+       int ref_cnt;
+} c_psql_database_t;
+
+static char *def_queries[] = {
+       "backends",
+       "transactions",
+       "queries",
+       "query_plans",
+       "table_states",
+       "disk_io",
+       "disk_usage"
+};
+static int def_queries_num = STATIC_ARRAY_SIZE (def_queries);
+
+static c_psql_database_t **databases     = NULL;
+static size_t              databases_num = 0;
+
+static udb_query_t       **queries       = NULL;
+static size_t              queries_num   = 0;
+
+static c_psql_writer_t    *writers       = NULL;
+static size_t              writers_num   = 0;
+
+static int c_psql_begin (c_psql_database_t *db)
+{
+       PGresult *r = PQexec (db->conn, "BEGIN");
+
+       int status = 1;
+
+       if (r != NULL) {
+               if (PGRES_COMMAND_OK == PQresultStatus (r)) {
+                       db->next_commit = cdtime() + db->commit_interval;
+                       status = 0;
+               }
+               else
+                       log_warn ("Failed to initiate ('BEGIN') transaction: %s",
+                                       PQerrorMessage (db->conn));
+               PQclear (r);
+       }
+       return status;
+} /* c_psql_begin */
+
+static int c_psql_commit (c_psql_database_t *db)
+{
+       PGresult *r = PQexec (db->conn, "COMMIT");
+
+       int status = 1;
+
+       if (r != NULL) {
+               if (PGRES_COMMAND_OK == PQresultStatus (r)) {
+                       db->next_commit = 0;
+                       log_debug ("Successfully committed transaction.");
+                       status = 0;
+               }
+               else
+                       log_warn ("Failed to commit transaction: %s",
+                                       PQerrorMessage (db->conn));
+               PQclear (r);
+       }
+       return status;
+} /* c_psql_commit */
+
+static c_psql_database_t *c_psql_database_new (const char *name)
+{
+       c_psql_database_t **tmp;
+       c_psql_database_t  *db;
+
+       db = (c_psql_database_t *)malloc (sizeof(*db));
+       if (NULL == db) {
+               log_err ("Out of memory.");
+               return NULL;
+       }
+
+       tmp = (c_psql_database_t **)realloc (databases,
+                       (databases_num + 1) * sizeof (*databases));
+       if (NULL == tmp) {
+               log_err ("Out of memory.");
+               sfree (db);
+               return NULL;
+       }
+
+       databases = tmp;
+       databases[databases_num] = db;
+       ++databases_num;
+
+       db->conn = NULL;
+
+       C_COMPLAIN_INIT (&db->conn_complaint);
+
+       db->proto_version = 0;
+       db->server_version = 0;
+
+       db->max_params_num = 0;
+
+       db->q_prep_areas   = NULL;
+       db->queries        = NULL;
+       db->queries_num    = 0;
+
+       db->writers        = NULL;
+       db->writers_num    = 0;
+
+       pthread_mutex_init (&db->db_lock, /* attrs = */ NULL);
+
+       db->interval   = 0;
+
+       db->commit_interval = 0;
+       db->next_commit     = 0;
+       db->expire_delay    = 0;
+
+       db->database   = sstrdup (name);
+       db->host       = NULL;
+       db->port       = NULL;
+       db->user       = NULL;
+       db->password   = NULL;
+
+       db->instance   = sstrdup (name);
+
+       db->sslmode    = NULL;
+
+       db->krbsrvname = NULL;
+
+       db->service    = NULL;
+
+       db->ref_cnt    = 0;
+       return db;
+} /* c_psql_database_new */
+
+static void c_psql_database_delete (void *data)
+{
+       size_t i;
+
+       c_psql_database_t *db = data;
+
+       --db->ref_cnt;
+       /* readers and writers may access this database */
+       if (db->ref_cnt > 0)
+               return;
+
+       /* wait for the lock to be released by the last writer */
+       pthread_mutex_lock (&db->db_lock);
+
+       if (db->next_commit > 0)
+               c_psql_commit (db);
+
+       PQfinish (db->conn);
+       db->conn = NULL;
+
+       if (db->q_prep_areas)
+               for (i = 0; i < db->queries_num; ++i)
+                       udb_query_delete_preparation_area (db->q_prep_areas[i]);
+       free (db->q_prep_areas);
+
+       sfree (db->queries);
+       db->queries_num = 0;
+
+       sfree (db->writers);
+       db->writers_num = 0;
+
+       pthread_mutex_unlock (&db->db_lock);
+
+       pthread_mutex_destroy (&db->db_lock);
+
+       sfree (db->database);
+       sfree (db->host);
+       sfree (db->port);
+       sfree (db->user);
+       sfree (db->password);
+
+       sfree (db->instance);
+
+       sfree (db->sslmode);
+
+       sfree (db->krbsrvname);
+
+       sfree (db->service);
+
+       /* don't care about freeing or reordering the 'databases' array
+        * this is done in 'shutdown'; also, don't free the database instance
+        * object just to make sure that in case anybody accesses it before
+        * shutdown won't segfault */
+       return;
+} /* c_psql_database_delete */
+
+static int c_psql_connect (c_psql_database_t *db)
+{
+       char  conninfo[4096];
+       char *buf     = conninfo;
+       int   buf_len = sizeof (conninfo);
+       int   status;
+
+       if ((! db) || (! db->database))
+               return -1;
+
+       status = ssnprintf (buf, buf_len, "dbname = '%s'", db->database);
+       if (0 < status) {
+               buf     += status;
+               buf_len -= status;
+       }
+
+       C_PSQL_PAR_APPEND (buf, buf_len, "host",       db->host);
+       C_PSQL_PAR_APPEND (buf, buf_len, "port",       db->port);
+       C_PSQL_PAR_APPEND (buf, buf_len, "user",       db->user);
+       C_PSQL_PAR_APPEND (buf, buf_len, "password",   db->password);
+       C_PSQL_PAR_APPEND (buf, buf_len, "sslmode",    db->sslmode);
+       C_PSQL_PAR_APPEND (buf, buf_len, "krbsrvname", db->krbsrvname);
+       C_PSQL_PAR_APPEND (buf, buf_len, "service",    db->service);
+
+       db->conn = PQconnectdb (conninfo);
+       db->proto_version = PQprotocolVersion (db->conn);
+       return 0;
+} /* c_psql_connect */
+
+static int c_psql_check_connection (c_psql_database_t *db)
+{
+       _Bool init = 0;
+
+       if (! db->conn) {
+               init = 1;
+
+               /* trigger c_release() */
+               if (0 == db->conn_complaint.interval)
+                       db->conn_complaint.interval = 1;
+
+               c_psql_connect (db);
+       }
+
+       if (CONNECTION_OK != PQstatus (db->conn)) {
+               PQreset (db->conn);
+
+               /* trigger c_release() */
+               if (0 == db->conn_complaint.interval)
+                       db->conn_complaint.interval = 1;
+
+               if (CONNECTION_OK != PQstatus (db->conn)) {
+                       c_complain (LOG_ERR, &db->conn_complaint,
+                                       "Failed to connect to database %s (%s): %s",
+                                       db->database, db->instance,
+                                       PQerrorMessage (db->conn));
+                       return -1;
+               }
+
+               db->proto_version = PQprotocolVersion (db->conn);
+       }
+
+       db->server_version = PQserverVersion (db->conn);
+
+       if (c_would_release (&db->conn_complaint)) {
+               char *server_host;
+               int   server_version;
+
+               server_host    = PQhost (db->conn);
+               server_version = PQserverVersion (db->conn);
+
+               c_do_release (LOG_INFO, &db->conn_complaint,
+                               "Successfully %sconnected to database %s (user %s) "
+                               "at server %s%s%s (server version: %d.%d.%d, "
+                               "protocol version: %d, pid: %d)", init ? "" : "re",
+                               PQdb (db->conn), PQuser (db->conn),
+                               C_PSQL_SOCKET3 (server_host, PQport (db->conn)),
+                               C_PSQL_SERVER_VERSION3 (server_version),
+                               db->proto_version, PQbackendPID (db->conn));
+
+               if (3 > db->proto_version)
+                       log_warn ("Protocol version %d does not support parameters.",
+                                       db->proto_version);
+       }
+       return 0;
+} /* c_psql_check_connection */
+
+static PGresult *c_psql_exec_query_noparams (c_psql_database_t *db,
+               udb_query_t *q)
+{
+       return PQexec (db->conn, udb_query_get_statement (q));
+} /* c_psql_exec_query_noparams */
+
+static PGresult *c_psql_exec_query_params (c_psql_database_t *db,
+               udb_query_t *q, c_psql_user_data_t *data)
+{
+       char *params[db->max_params_num];
+       char  interval[64];
+       int   i;
+
+       if ((data == NULL) || (data->params_num == 0))
+               return (c_psql_exec_query_noparams (db, q));
+
+       assert (db->max_params_num >= data->params_num);
+
+       for (i = 0; i < data->params_num; ++i) {
+               switch (data->params[i]) {
+                       case C_PSQL_PARAM_HOST:
+                               params[i] = C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
+                                       ? "localhost" : db->host;
+                               break;
+                       case C_PSQL_PARAM_DB:
+                               params[i] = db->database;
+                               break;
+                       case C_PSQL_PARAM_USER:
+                               params[i] = db->user;
+                               break;
+                       case C_PSQL_PARAM_INTERVAL:
+                               ssnprintf (interval, sizeof (interval), "%.3f",
+                                               (db->interval > 0)
+                                               ? CDTIME_T_TO_DOUBLE (db->interval)
+                                               : plugin_get_interval ());
+                               params[i] = interval;
+                               break;
+                       case C_PSQL_PARAM_INSTANCE:
+                               params[i] = db->instance;
+                               break;
+                       default:
+                               assert (0);
+               }
+       }
+
+       return PQexecParams (db->conn, udb_query_get_statement (q),
+                       data->params_num, NULL,
+                       (const char *const *) params,
+                       NULL, NULL, /* return text data */ 0);
+} /* c_psql_exec_query_params */
+
+/* db->db_lock must be locked when calling this function */
+static int c_psql_exec_query (c_psql_database_t *db, udb_query_t *q,
+               udb_query_preparation_area_t *prep_area)
+{
+       PGresult *res;
+
+       c_psql_user_data_t *data;
+
+       const char *host;
+
+       char **column_names;
+       char **column_values;
+       int    column_num;
+
+       int rows_num;
+       int status;
+       int row, col;
+
+       /* The user data may hold parameter information, but may be NULL. */
+       data = udb_query_get_user_data (q);
+
+       /* Versions up to `3' don't know how to handle parameters. */
+       if (3 <= db->proto_version)
+               res = c_psql_exec_query_params (db, q, data);
+       else if ((NULL == data) || (0 == data->params_num))
+               res = c_psql_exec_query_noparams (db, q);
+       else {
+               log_err ("Connection to database \"%s\" (%s) does not support "
+                               "parameters (protocol version %d) - "
+                               "cannot execute query \"%s\".",
+                               db->database, db->instance, db->proto_version,
+                               udb_query_get_name (q));
+               return -1;
+       }
+
+       /* give c_psql_write() a chance to acquire the lock if called recursively
+        * through dispatch_values(); this will happen if, both, queries and
+        * writers are configured for a single connection */
+       pthread_mutex_unlock (&db->db_lock);
+
+       column_names = NULL;
+       column_values = NULL;
+
+       if (PGRES_TUPLES_OK != PQresultStatus (res)) {
+               pthread_mutex_lock (&db->db_lock);
+
+               if ((CONNECTION_OK != PQstatus (db->conn))
+                               && (0 == c_psql_check_connection (db))) {
+                       PQclear (res);
+                       return c_psql_exec_query (db, q, prep_area);
+               }
+
+               log_err ("Failed to execute SQL query: %s",
+                               PQerrorMessage (db->conn));
+               log_info ("SQL query was: %s",
+                               udb_query_get_statement (q));
+               PQclear (res);
+               return -1;
+       }
+
+#define BAIL_OUT(status) \
+       sfree (column_names); \
+       sfree (column_values); \
+       PQclear (res); \
+       pthread_mutex_lock (&db->db_lock); \
+       return status
+
+       rows_num = PQntuples (res);
+       if (1 > rows_num) {
+               BAIL_OUT (0);
+       }
+
+       column_num = PQnfields (res);
+       column_names = (char **) calloc (column_num, sizeof (char *));
+       if (NULL == column_names) {
+               log_err ("calloc failed.");
+               BAIL_OUT (-1);
+       }
+
+       column_values = (char **) calloc (column_num, sizeof (char *));
+       if (NULL == column_values) {
+               log_err ("calloc failed.");
+               BAIL_OUT (-1);
+       }
+       
+       for (col = 0; col < column_num; ++col) {
+               /* Pointers returned by `PQfname' are freed by `PQclear' via
+                * `BAIL_OUT'. */
+               column_names[col] = PQfname (res, col);
+               if (NULL == column_names[col]) {
+                       log_err ("Failed to resolve name of column %i.", col);
+                       BAIL_OUT (-1);
+               }
+       }
+
+       if (C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
+                       || (0 == strcmp (db->host, "127.0.0.1"))
+                       || (0 == strcmp (db->host, "localhost")))
+               host = hostname_g;
+       else
+               host = db->host;
+
+       status = udb_query_prepare_result (q, prep_area, host, "postgresql",
+                       db->instance, column_names, (size_t) column_num, db->interval);
+       if (0 != status) {
+               log_err ("udb_query_prepare_result failed with status %i.",
+                               status);
+               BAIL_OUT (-1);
+       }
+
+       for (row = 0; row < rows_num; ++row) {
+               for (col = 0; col < column_num; ++col) {
+                       /* Pointers returned by `PQgetvalue' are freed by `PQclear' via
+                        * `BAIL_OUT'. */
+                       column_values[col] = PQgetvalue (res, row, col);
+                       if (NULL == column_values[col]) {
+                               log_err ("Failed to get value at (row = %i, col = %i).",
+                                               row, col);
+                               break;
+                       }
+               }
+
+               /* check for an error */
+               if (col < column_num)
+                       continue;
+
+               status = udb_query_handle_result (q, prep_area, column_values);
+               if (status != 0) {
+                       log_err ("udb_query_handle_result failed with status %i.",
+                                       status);
+               }
+       } /* for (row = 0; row < rows_num; ++row) */
+
+       udb_query_finish_result (q, prep_area);
+
+       BAIL_OUT (0);
+#undef BAIL_OUT
+} /* c_psql_exec_query */
+
+static int c_psql_read (user_data_t *ud)
+{
+       c_psql_database_t *db;
+
+       int success = 0;
+       int i;
+
+       if ((ud == NULL) || (ud->data == NULL)) {
+               log_err ("c_psql_read: Invalid user data.");
+               return -1;
+       }
+
+       db = ud->data;
+
+       assert (NULL != db->database);
+       assert (NULL != db->instance);
+       assert (NULL != db->queries);
+
+       pthread_mutex_lock (&db->db_lock);
+
+       if (0 != c_psql_check_connection (db)) {
+               pthread_mutex_unlock (&db->db_lock);
+               return -1;
+       }
+
+       for (i = 0; i < db->queries_num; ++i)
+       {
+               udb_query_preparation_area_t *prep_area;
+               udb_query_t *q;
+
+               prep_area = db->q_prep_areas[i];
+               q = db->queries[i];
+
+               if ((0 != db->server_version)
+                               && (udb_query_check_version (q, db->server_version) <= 0))
+                       continue;
+
+               if (0 == c_psql_exec_query (db, q, prep_area))
+                       success = 1;
+       }
+
+       pthread_mutex_unlock (&db->db_lock);
+
+       if (! success)
+               return -1;
+       return 0;
+} /* c_psql_read */
+
+static char *values_name_to_sqlarray (const data_set_t *ds,
+               char *string, size_t string_len)
+{
+       char  *str_ptr;
+       size_t str_len;
+
+       int i;
+
+       str_ptr = string;
+       str_len = string_len;
+
+       for (i = 0; i < ds->ds_num; ++i) {
+               int status = ssnprintf (str_ptr, str_len, ",'%s'", ds->ds[i].name);
+
+               if (status < 1)
+                       return NULL;
+               else if ((size_t)status >= str_len) {
+                       str_len = 0;
+                       break;
+               }
+               else {
+                       str_ptr += status;
+                       str_len -= (size_t)status;
+               }
+       }
+
+       if (str_len <= 2) {
+               log_err ("c_psql_write: Failed to stringify value names");
+               return NULL;
+       }
+
+       /* overwrite the first comma */
+       string[0] = '{';
+       str_ptr[0] = '}';
+       str_ptr[1] = '\0';
+
+       return string;
+} /* values_name_to_sqlarray */
+
+static char *values_type_to_sqlarray (const data_set_t *ds,
+               char *string, size_t string_len, _Bool store_rates)
+{
+       char  *str_ptr;
+       size_t str_len;
+
+       int i;
+
+       str_ptr = string;
+       str_len = string_len;
+
+       for (i = 0; i < ds->ds_num; ++i) {
+               int status;
+
+               if (store_rates)
+                       status = ssnprintf(str_ptr, str_len, ",'gauge'");
+               else
+                       status = ssnprintf(str_ptr, str_len, ",'%s'",
+                                       DS_TYPE_TO_STRING (ds->ds[i].type));
+
+               if (status < 1) {
+                       str_len = 0;
+                       break;
+               }
+               else if ((size_t)status >= str_len) {
+                       str_len = 0;
+                       break;
+               }
+               else {
+                       str_ptr += status;
+                       str_len -= (size_t)status;
+               }
+       }
+
+       if (str_len <= 2) {
+               log_err ("c_psql_write: Failed to stringify value types");
+               return NULL;
+       }
+
+       /* overwrite the first comma */
+       string[0] = '{';
+       str_ptr[0] = '}';
+       str_ptr[1] = '\0';
+
+       return string;
+} /* values_type_to_sqlarray */
+
+static char *values_to_sqlarray (const data_set_t *ds, const value_list_t *vl,
+               char *string, size_t string_len, _Bool store_rates)
+{
+       char  *str_ptr;
+       size_t str_len;
+
+       gauge_t *rates = NULL;
+
+       int i;
+
+       str_ptr = string;
+       str_len = string_len;
+
+       for (i = 0; i < vl->values_len; ++i) {
+               int status = 0;
+
+               if ((ds->ds[i].type != DS_TYPE_GAUGE)
+                               && (ds->ds[i].type != DS_TYPE_COUNTER)
+                               && (ds->ds[i].type != DS_TYPE_DERIVE)
+                               && (ds->ds[i].type != DS_TYPE_ABSOLUTE)) {
+                       log_err ("c_psql_write: Unknown data source type: %i",
+                                       ds->ds[i].type);
+                       sfree (rates);
+                       return NULL;
+               }
+
+               if (ds->ds[i].type == DS_TYPE_GAUGE)
+                       status = ssnprintf (str_ptr, str_len,
+                                       ","GAUGE_FORMAT, vl->values[i].gauge);
+               else if (store_rates) {
+                       if (rates == NULL)
+                               rates = uc_get_rate (ds, vl);
+
+                       if (rates == NULL) {
+                               log_err ("c_psql_write: Failed to determine rate");
+                               return NULL;
+                       }
+
+                       status = ssnprintf (str_ptr, str_len,
+                                       ",%lf", rates[i]);
+               }
+               else if (ds->ds[i].type == DS_TYPE_COUNTER)
+                       status = ssnprintf (str_ptr, str_len,
+                                       ",%llu", vl->values[i].counter);
+               else if (ds->ds[i].type == DS_TYPE_DERIVE)
+                       status = ssnprintf (str_ptr, str_len,
+                                       ",%"PRIi64, vl->values[i].derive);
+               else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+                       status = ssnprintf (str_ptr, str_len,
+                                       ",%"PRIu64, vl->values[i].absolute);
+
+               if (status < 1) {
+                       str_len = 0;
+                       break;
+               }
+               else if ((size_t)status >= str_len) {
+                       str_len = 0;
+                       break;
+               }
+               else {
+                       str_ptr += status;
+                       str_len -= (size_t)status;
+               }
+       }
+
+       sfree (rates);
+
+       if (str_len <= 2) {
+               log_err ("c_psql_write: Failed to stringify value list");
+               return NULL;
+       }
+
+       /* overwrite the first comma */
+       string[0] = '{';
+       str_ptr[0] = '}';
+       str_ptr[1] = '\0';
+
+       return string;
+} /* values_to_sqlarray */
+
+static int c_psql_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t *ud)
+{
+       c_psql_database_t *db;
+
+       char time_str[32];
+       char values_name_str[1024];
+       char values_type_str[1024];
+       char values_str[1024];
+
+       const char *params[9];
+
+       int success = 0;
+       int i;
+
+       if ((ud == NULL) || (ud->data == NULL)) {
+               log_err ("c_psql_write: Invalid user data.");
+               return -1;
+       }
+
+       db = ud->data;
+       assert (db->database != NULL);
+       assert (db->writers != NULL);
+
+       if (cdtime_to_iso8601 (time_str, sizeof (time_str), vl->time) == 0) {
+               log_err ("c_psql_write: Failed to convert time to ISO 8601 format");
+               return -1;
+       }
+
+       if (values_name_to_sqlarray (ds,
+                               values_name_str, sizeof (values_name_str)) == NULL)
+               return -1;
+
+#define VALUE_OR_NULL(v) ((((v) == NULL) || (*(v) == '\0')) ? NULL : (v))
+
+       params[0] = time_str;
+       params[1] = vl->host;
+       params[2] = vl->plugin;
+       params[3] = VALUE_OR_NULL(vl->plugin_instance);
+       params[4] = vl->type;
+       params[5] = VALUE_OR_NULL(vl->type_instance);
+       params[6] = values_name_str;
+
+#undef VALUE_OR_NULL
+
+       if( db->expire_delay > 0 && vl->time < (cdtime() - vl->interval - db->expire_delay) ) {
+               log_info ("c_psql_write: Skipped expired value @ %s - %s/%s-%s/%s-%s/%s", 
+                       params[0], params[1], params[2], params[3], params[4], params[5], params[6] );
+               return 0;
+        }
+
+       pthread_mutex_lock (&db->db_lock);
+
+       if (0 != c_psql_check_connection (db)) {
+               pthread_mutex_unlock (&db->db_lock);
+               return -1;
+       }
+
+       if ((db->commit_interval > 0)
+                       && (db->next_commit == 0))
+               c_psql_begin (db);
+
+       for (i = 0; i < db->writers_num; ++i) {
+               c_psql_writer_t *writer;
+               PGresult *res;
+
+               writer = db->writers[i];
+
+               if (values_type_to_sqlarray (ds,
+                                       values_type_str, sizeof (values_type_str),
+                                       writer->store_rates) == NULL) {
+                       pthread_mutex_unlock (&db->db_lock);
+                       return -1;
+               }
+
+               if (values_to_sqlarray (ds, vl,
+                                       values_str, sizeof (values_str),
+                                       writer->store_rates) == NULL) {
+                       pthread_mutex_unlock (&db->db_lock);
+                       return -1;
+               }
+
+               params[7] = values_type_str;
+               params[8] = values_str;
+
+               res = PQexecParams (db->conn, writer->statement,
+                               STATIC_ARRAY_SIZE (params), NULL,
+                               (const char *const *)params,
+                               NULL, NULL, /* return text data */ 0);
+
+               if ((PGRES_COMMAND_OK != PQresultStatus (res))
+                               && (PGRES_TUPLES_OK != PQresultStatus (res))) {
+                       PQclear (res);
+
+                       if ((CONNECTION_OK != PQstatus (db->conn))
+                                       && (0 == c_psql_check_connection (db))) {
+                               /* try again */
+                               res = PQexecParams (db->conn, writer->statement,
+                                               STATIC_ARRAY_SIZE (params), NULL,
+                                               (const char *const *)params,
+                                               NULL, NULL, /* return text data */ 0);
+
+                               if ((PGRES_COMMAND_OK == PQresultStatus (res))
+                                               || (PGRES_TUPLES_OK == PQresultStatus (res))) {
+                                       PQclear (res);
+                                       success = 1;
+                                       continue;
+                               }
+                       }
+
+                       log_err ("Failed to execute SQL query: %s",
+                                       PQerrorMessage (db->conn));
+                       log_info ("SQL query was: '%s', "
+                                       "params: %s, %s, %s, %s, %s, %s, %s, %s",
+                                       writer->statement,
+                                       params[0], params[1], params[2], params[3],
+                                       params[4], params[5], params[6], params[7]);
+
+                       /* this will abort any current transaction -> restart */
+                       if (db->next_commit > 0)
+                               c_psql_commit (db);
+
+                       pthread_mutex_unlock (&db->db_lock);
+                       return -1;
+               }
+
+               PQclear (res);
+               success = 1;
+       }
+
+       if ((db->next_commit > 0)
+                       && (cdtime () > db->next_commit))
+               c_psql_commit (db);
+
+       pthread_mutex_unlock (&db->db_lock);
+
+       if (! success)
+               return -1;
+       return 0;
+} /* c_psql_write */
+
+/* We cannot flush single identifiers as all we do is to commit the currently
+ * running transaction, thus making sure that all written data is actually
+ * visible to everybody. */
+static int c_psql_flush (cdtime_t timeout,
+               __attribute__((unused)) const char *ident,
+               user_data_t *ud)
+{
+       c_psql_database_t **dbs = databases;
+       size_t dbs_num = databases_num;
+       size_t i;
+
+       if ((ud != NULL) && (ud->data != NULL)) {
+               dbs = (void *)&ud->data;
+               dbs_num = 1;
+       }
+
+       for (i = 0; i < dbs_num; ++i) {
+               c_psql_database_t *db = dbs[i];
+
+               /* don't commit if the timeout is larger than the regular commit
+                * interval as in that case all requested data has already been
+                * committed */
+               if ((db->next_commit > 0) && (db->commit_interval > timeout))
+                       c_psql_commit (db);
+       }
+       return 0;
+} /* c_psql_flush */
+
+static int c_psql_shutdown (void)
+{
+       size_t i = 0;
+
+       _Bool had_flush = 0;
+
+       plugin_unregister_read_group ("postgresql");
+
+       for (i = 0; i < databases_num; ++i) {
+               c_psql_database_t *db = databases[i];
+
+               if (db->writers_num > 0) {
+                       char cb_name[DATA_MAX_NAME_LEN];
+                       ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s",
+                                       db->database);
+
+                       if (! had_flush) {
+                               plugin_unregister_flush ("postgresql");
+                               had_flush = 1;
+                       }
+
+                       plugin_unregister_flush (cb_name);
+                       plugin_unregister_write (cb_name);
+               }
+
+               sfree (db);
+       }
+
+       udb_query_free (queries, queries_num);
+       queries = NULL;
+       queries_num = 0;
+
+       sfree (writers);
+       writers = NULL;
+       writers_num = 0;
+
+       sfree (databases);
+       databases = NULL;
+       databases_num = 0;
+
+       return 0;
+} /* c_psql_shutdown */
+
+static int config_query_param_add (udb_query_t *q, oconfig_item_t *ci)
+{
+       c_psql_user_data_t *data;
+       const char *param_str;
+
+       c_psql_param_t *tmp;
+
+       data = udb_query_get_user_data (q);
+       if (NULL == data) {
+               data = (c_psql_user_data_t *) smalloc (sizeof (*data));
+               if (NULL == data) {
+                       log_err ("Out of memory.");
+                       return -1;
+               }
+               memset (data, 0, sizeof (*data));
+               data->params = NULL;
+       }
+
+       tmp = (c_psql_param_t *) realloc (data->params,
+                       (data->params_num + 1) * sizeof (c_psql_param_t));
+       if (NULL == tmp) {
+               log_err ("Out of memory.");
+               return -1;
+       }
+       data->params = tmp;
+
+       param_str = ci->values[0].value.string;
+       if (0 == strcasecmp (param_str, "hostname"))
+               data->params[data->params_num] = C_PSQL_PARAM_HOST;
+       else if (0 == strcasecmp (param_str, "database"))
+               data->params[data->params_num] = C_PSQL_PARAM_DB;
+       else if (0 == strcasecmp (param_str, "username"))
+               data->params[data->params_num] = C_PSQL_PARAM_USER;
+       else if (0 == strcasecmp (param_str, "interval"))
+               data->params[data->params_num] = C_PSQL_PARAM_INTERVAL;
+       else if (0 == strcasecmp (param_str, "instance"))
+               data->params[data->params_num] = C_PSQL_PARAM_INSTANCE;
+       else {
+               log_err ("Invalid parameter \"%s\".", param_str);
+               return 1;
+       }
+
+       data->params_num++;
+       udb_query_set_user_data (q, data);
+
+       return (0);
+} /* config_query_param_add */
+
+static int config_query_callback (udb_query_t *q, oconfig_item_t *ci)
+{
+       if (0 == strcasecmp ("Param", ci->key))
+               return config_query_param_add (q, ci);
+
+       log_err ("Option not allowed within a Query block: `%s'", ci->key);
+
+       return (-1);
+} /* config_query_callback */
+
+static int config_add_writer (oconfig_item_t *ci,
+               c_psql_writer_t *src_writers, size_t src_writers_num,
+               c_psql_writer_t ***dst_writers, size_t *dst_writers_num)
+{
+       char *name;
+
+       size_t i;
+
+       if ((ci == NULL) || (dst_writers == NULL) || (dst_writers_num == NULL))
+               return -1;
+
+       if ((ci->values_num != 1)
+                       || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
+               log_err ("`Writer' expects a single string argument.");
+               return 1;
+       }
+
+       name = ci->values[0].value.string;
+
+       for (i = 0; i < src_writers_num; ++i) {
+               c_psql_writer_t **tmp;
+
+               if (strcasecmp (name, src_writers[i].name) != 0)
+                       continue;
+
+               tmp = (c_psql_writer_t **)realloc (*dst_writers,
+                               sizeof (**dst_writers) * (*dst_writers_num + 1));
+               if (tmp == NULL) {
+                       log_err ("Out of memory.");
+                       return -1;
+               }
+
+               tmp[*dst_writers_num] = src_writers + i;
+
+               *dst_writers = tmp;
+               ++(*dst_writers_num);
+               break;
+       }
+
+       if (i >= src_writers_num) {
+               log_err ("No such writer: `%s'", name);
+               return -1;
+       }
+
+       return 0;
+} /* config_add_writer */
+
+static int c_psql_config_writer (oconfig_item_t *ci)
+{
+       c_psql_writer_t *writer;
+       c_psql_writer_t *tmp;
+
+       int status = 0;
+       int i;
+
+       if ((ci->values_num != 1)
+                       || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
+               log_err ("<Writer> expects a single string argument.");
+               return 1;
+       }
+
+       tmp = (c_psql_writer_t *)realloc (writers,
+                       sizeof (*writers) * (writers_num + 1));
+       if (tmp == NULL) {
+               log_err ("Out of memory.");
+               return -1;
+       }
+
+       writers = tmp;
+       writer  = writers + writers_num;
+       ++writers_num;
+
+       writer->name = sstrdup (ci->values[0].value.string);
+       writer->statement = NULL;
+       writer->store_rates = 1;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (strcasecmp ("Statement", c->key) == 0)
+                       status = cf_util_get_string (c, &writer->statement);
+               else if (strcasecmp ("StoreRates", c->key) == 0)
+                       status = cf_util_get_boolean (c, &writer->store_rates);
+               else
+                       log_warn ("Ignoring unknown config key \"%s\".", c->key);
+       }
+
+       if (status != 0) {
+               sfree (writer->statement);
+               sfree (writer->name);
+               sfree (writer);
+               return status;
+       }
+
+       return 0;
+} /* c_psql_config_writer */
+
+static int c_psql_config_database (oconfig_item_t *ci)
+{
+       c_psql_database_t *db;
+
+       char cb_name[DATA_MAX_NAME_LEN];
+       struct timespec cb_interval = { 0, 0 };
+       user_data_t ud;
+
+       static _Bool have_flush = 0;
+
+       int i;
+
+       if ((1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("<Database> expects a single string argument.");
+               return 1;
+       }
+
+       memset (&ud, 0, sizeof (ud));
+
+       db = c_psql_database_new (ci->values[0].value.string);
+       if (db == NULL)
+               return -1;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (0 == strcasecmp (c->key, "Host"))
+                       cf_util_get_string (c, &db->host);
+               else if (0 == strcasecmp (c->key, "Port"))
+                       cf_util_get_service (c, &db->port);
+               else if (0 == strcasecmp (c->key, "User"))
+                       cf_util_get_string (c, &db->user);
+               else if (0 == strcasecmp (c->key, "Password"))
+                       cf_util_get_string (c, &db->password);
+               else if (0 == strcasecmp (c->key, "Instance"))
+                       cf_util_get_string (c, &db->instance);
+               else if (0 == strcasecmp (c->key, "SSLMode"))
+                       cf_util_get_string (c, &db->sslmode);
+               else if (0 == strcasecmp (c->key, "KRBSrvName"))
+                       cf_util_get_string (c, &db->krbsrvname);
+               else if (0 == strcasecmp (c->key, "Service"))
+                       cf_util_get_string (c, &db->service);
+               else if (0 == strcasecmp (c->key, "Query"))
+                       udb_query_pick_from_list (c, queries, queries_num,
+                                       &db->queries, &db->queries_num);
+               else if (0 == strcasecmp (c->key, "Writer"))
+                       config_add_writer (c, writers, writers_num,
+                                       &db->writers, &db->writers_num);
+               else if (0 == strcasecmp (c->key, "Interval"))
+                       cf_util_get_cdtime (c, &db->interval);
+               else if (strcasecmp ("CommitInterval", c->key) == 0)
+                       cf_util_get_cdtime (c, &db->commit_interval);
+               else if (strcasecmp ("ExpireDelay", c->key) == 0)
+                       cf_util_get_cdtime (c, &db->expire_delay);
+               else
+                       log_warn ("Ignoring unknown config key \"%s\".", c->key);
+       }
+
+       /* If no `Query' options were given, add the default queries.. */
+       if ((db->queries_num == 0) && (db->writers_num == 0)){
+               for (i = 0; i < def_queries_num; i++)
+                       udb_query_pick_from_list_by_name (def_queries[i],
+                                       queries, queries_num,
+                                       &db->queries, &db->queries_num);
+       }
+
+       if (db->queries_num > 0) {
+               db->q_prep_areas = (udb_query_preparation_area_t **) calloc (
+                               db->queries_num, sizeof (*db->q_prep_areas));
+
+               if (db->q_prep_areas == NULL) {
+                       log_err ("Out of memory.");
+                       c_psql_database_delete (db);
+                       return -1;
+               }
+       }
+
+       for (i = 0; (size_t)i < db->queries_num; ++i) {
+               c_psql_user_data_t *data;
+               data = udb_query_get_user_data (db->queries[i]);
+               if ((data != NULL) && (data->params_num > db->max_params_num))
+                       db->max_params_num = data->params_num;
+
+               db->q_prep_areas[i]
+                       = udb_query_allocate_preparation_area (db->queries[i]);
+
+               if (db->q_prep_areas[i] == NULL) {
+                       log_err ("Out of memory.");
+                       c_psql_database_delete (db);
+                       return -1;
+               }
+       }
+
+       ud.data = db;
+       ud.free_func = c_psql_database_delete;
+
+       ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->instance);
+
+       if (db->queries_num > 0) {
+               CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval);
+
+               ++db->ref_cnt;
+               plugin_register_complex_read ("postgresql", cb_name, c_psql_read,
+                               /* interval = */ (db->interval > 0) ? &cb_interval : NULL,
+                               &ud);
+       }
+       if (db->writers_num > 0) {
+               ++db->ref_cnt;
+               plugin_register_write (cb_name, c_psql_write, &ud);
+
+               if (! have_flush) {
+                       /* flush all */
+                       plugin_register_flush ("postgresql",
+                                       c_psql_flush, /* user data = */ NULL);
+                       have_flush = 1;
+               }
+
+               /* flush this connection only */
+               ++db->ref_cnt;
+               plugin_register_flush (cb_name, c_psql_flush, &ud);
+       }
+       else if (db->commit_interval > 0) {
+               log_warn ("Database '%s': You do not have any writers assigned to "
+                               "this database connection. Setting 'CommitInterval' does "
+                               "not have any effect.", db->database);
+       }
+       return 0;
+} /* c_psql_config_database */
+
+static int c_psql_config (oconfig_item_t *ci)
+{
+       static int have_def_config = 0;
+
+       int i;
+
+       if (0 == have_def_config) {
+               oconfig_item_t *c;
+
+               have_def_config = 1;
+
+               c = oconfig_parse_file (C_PSQL_DEFAULT_CONF);
+               if (NULL == c)
+                       log_err ("Failed to read default config ("C_PSQL_DEFAULT_CONF").");
+               else
+                       c_psql_config (c);
+
+               if (NULL == queries)
+                       log_err ("Default config ("C_PSQL_DEFAULT_CONF") did not define "
+                                       "any queries - please check your installation.");
+       }
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (0 == strcasecmp (c->key, "Query"))
+                       udb_query_create (&queries, &queries_num, c,
+                                       /* callback = */ config_query_callback);
+               else if (0 == strcasecmp (c->key, "Writer"))
+                       c_psql_config_writer (c);
+               else if (0 == strcasecmp (c->key, "Database"))
+                       c_psql_config_database (c);
+               else
+                       log_warn ("Ignoring unknown config key \"%s\".", c->key);
+       }
+       return 0;
+} /* c_psql_config */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("postgresql", c_psql_config);
+       plugin_register_shutdown ("postgresql", c_psql_shutdown);
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --git a/src/postgresql_default.conf b/src/postgresql_default.conf
new file mode 100644 (file)
index 0000000..f905eb2
--- /dev/null
@@ -0,0 +1,390 @@
+# Pre-defined queries of collectd's postgresql plugin.
+#
+# Do not edit this file. If you want to change any of the query definitions,
+# overwrite them in collectd.conf instead.
+#
+# This file is distributed under the same terms as collectd itself.
+
+<Query backends>
+       Statement "SELECT count(*) AS count \
+               FROM pg_stat_activity \
+               WHERE datname = $1;"
+
+       Param database
+
+       <Result>
+               Type "pg_numbackends"
+               ValuesFrom "count"
+       </Result>
+</Query>
+
+<Query transactions>
+       Statement "SELECT xact_commit, xact_rollback \
+               FROM pg_stat_database \
+               WHERE datname = $1;"
+
+       Param database
+
+       <Result>
+               Type "pg_xact"
+               InstancePrefix "commit"
+               ValuesFrom "xact_commit"
+       </Result>
+       <Result>
+               Type "pg_xact"
+               InstancePrefix "rollback"
+               ValuesFrom "xact_rollback"
+       </Result>
+</Query>
+
+<Query queries>
+       Statement "SELECT sum(n_tup_ins) AS ins, \
+                       sum(n_tup_upd) AS upd, \
+                       sum(n_tup_del) AS del \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "ins"
+               ValuesFrom "ins"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "upd"
+               ValuesFrom "upd"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "del"
+               ValuesFrom "del"
+       </Result>
+
+       MaxVersion 80299
+</Query>
+
+<Query queries>
+       Statement "SELECT sum(n_tup_ins) AS ins, \
+                       sum(n_tup_upd) AS upd, \
+                       sum(n_tup_del) AS del, \
+                       sum(n_tup_hot_upd) AS hot_upd \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "ins"
+               ValuesFrom "ins"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "upd"
+               ValuesFrom "upd"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "del"
+               ValuesFrom "del"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "hot_upd"
+               ValuesFrom "hot_upd"
+       </Result>
+
+       MinVersion 80300
+</Query>
+
+<Query queries_by_table>
+       Statement "SELECT schemaname, relname, \
+                       n_tup_ins AS ins, \
+                       n_tup_upd AS upd, \
+                       n_tup_del AS del \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "ins"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "ins"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "upd"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "upd"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "del"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "del"
+       </Result>
+
+       MaxVersion 80299
+</Query>
+
+<Query queries_by_table>
+       Statement "SELECT schemaname, relname, \
+                       n_tup_ins AS ins, \
+                       n_tup_upd AS upd, \
+                       n_tup_del AS del, \
+                       n_tup_hot_upd AS hot_upd \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "ins"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "ins"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "upd"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "upd"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "del"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "del"
+       </Result>
+       <Result>
+               Type "pg_n_tup_c"
+               InstancePrefix "hot_upd"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "hot_upd"
+       </Result>
+
+       MinVersion 80300
+</Query>
+
+<Query query_plans>
+       Statement "SELECT sum(seq_scan) AS seq, \
+                       sum(seq_tup_read) AS seq_tup_read, \
+                       sum(idx_scan) AS idx, \
+                       sum(idx_tup_fetch) AS idx_tup_fetch \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "seq"
+               ValuesFrom "seq"
+       </Result>
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "seq_tup_read"
+               ValuesFrom "seq_tup_read"
+       </Result>
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "idx"
+               ValuesFrom "idx"
+       </Result>
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "idx_tup_fetch"
+               ValuesFrom "idx_tup_fetch"
+       </Result>
+</Query>
+
+<Query table_states>
+       Statement "SELECT sum(n_live_tup) AS live, sum(n_dead_tup) AS dead \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_n_tup_g"
+               InstancePrefix "live"
+               ValuesFrom "live"
+       </Result>
+       <Result>
+               Type "pg_n_tup_g"
+               InstancePrefix "dead"
+               ValuesFrom "dead"
+       </Result>
+
+       MinVersion 80300
+</Query>
+
+<Query query_plans_by_table>
+       Statement "SELECT schemaname, relname, \
+                       seq_scan AS seq, \
+                       seq_tup_read AS seq_tup_read, \
+                       idx_scan AS idx, \
+                       idx_tup_fetch AS idx_tup_fetch \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "seq"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "seq"
+       </Result>
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "seq_tup_read"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "seq_tup_read"
+       </Result>
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "idx"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "idx"
+       </Result>
+       <Result>
+               Type "pg_scan"
+               InstancePrefix "idx_tup_fetch"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "idx_tup_fetch"
+       </Result>
+</Query>
+
+<Query table_states_by_table>
+       Statement "SELECT schemaname, relname, \
+                       n_live_tup AS live, n_dead_tup AS dead \
+               FROM pg_stat_user_tables;"
+
+       <Result>
+               Type "pg_n_tup_g"
+               InstancePrefix "live"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "live"
+       </Result>
+       <Result>
+               Type "pg_n_tup_g"
+               InstancePrefix "dead"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "dead"
+       </Result>
+
+       MinVersion 80300
+</Query>
+
+<Query disk_io>
+       Statement "SELECT coalesce(sum(heap_blks_read), 0) AS heap_read, \
+                       coalesce(sum(heap_blks_hit), 0) AS heap_hit, \
+                       coalesce(sum(idx_blks_read), 0) AS idx_read, \
+                       coalesce(sum(idx_blks_hit), 0) AS idx_hit, \
+                       coalesce(sum(toast_blks_read), 0) AS toast_read, \
+                       coalesce(sum(toast_blks_hit), 0) AS toast_hit, \
+                       coalesce(sum(tidx_blks_read), 0) AS tidx_read, \
+                       coalesce(sum(tidx_blks_hit), 0) AS tidx_hit \
+               FROM pg_statio_user_tables;"
+
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "heap_read"
+               ValuesFrom "heap_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "heap_hit"
+               ValuesFrom "heap_hit"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "idx_read"
+               ValuesFrom "idx_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "idx_hit"
+               ValuesFrom "idx_hit"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "toast_read"
+               ValuesFrom "toast_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "toast_hit"
+               ValuesFrom "toast_hit"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "tidx_read"
+               ValuesFrom "tidx_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "tidx_hit"
+               ValuesFrom "tidx_hit"
+       </Result>
+</Query>
+
+<Query disk_io_by_table>
+       Statement "SELECT schemaname, relname, \
+                       coalesce(heap_blks_read, 0) AS heap_read, \
+                       coalesce(heap_blks_hit, 0) AS heap_hit, \
+                       coalesce(idx_blks_read, 0) AS idx_read, \
+                       coalesce(idx_blks_hit, 0) AS idx_hit, \
+                       coalesce(toast_blks_read, 0) AS toast_read, \
+                       coalesce(toast_blks_hit, 0) AS toast_hit, \
+                       coalesce(tidx_blks_read, 0) AS tidx_read, \
+                       coalesce(tidx_blks_hit, 0) AS tidx_hit \
+               FROM pg_statio_user_tables;"
+
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "heap_read"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "heap_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "heap_hit"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "heap_hit"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "idx_read"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "idx_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "idx_hit"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "idx_hit"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "toast_read"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "toast_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "toast_hit"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "toast_hit"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "tidx_read"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "tidx_read"
+       </Result>
+       <Result>
+               Type "pg_blks"
+               InstancePrefix "tidx_hit"
+               InstancesFrom "schemaname" "relname"
+               ValuesFrom "tidx_hit"
+       </Result>
+</Query>
+
+<Query disk_usage>
+       Statement "SELECT pg_database_size($1) AS size;"
+
+       Param database
+
+       <Result>
+               Type pg_db_size
+               ValuesFrom "size"
+       </Result>
+</Query>
+
+# vim: set ft=config :
+
diff --git a/src/powerdns.c b/src/powerdns.c
new file mode 100644 (file)
index 0000000..ec337bf
--- /dev/null
@@ -0,0 +1,1004 @@
+/**
+ * collectd - src/powerdns.c
+ * Copyright (C) 2007-2008  C-Ware, Inc.
+ * Copyright (C) 2008       Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Luke Heberling <lukeh at c-ware.com>
+ *   Florian Forster <octo at collectd.org>
+ *
+ * DESCRIPTION
+ *   Queries a PowerDNS control socket for statistics
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_llist.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
+#endif
+#define FUNC_ERROR(func) do { char errbuf[1024]; ERROR ("powerdns plugin: %s failed: %s", func, sstrerror (errno, errbuf, sizeof (errbuf))); } while (0)
+
+#define SERVER_SOCKET  LOCALSTATEDIR"/run/pdns.controlsocket"
+#define SERVER_COMMAND "SHOW * \n"
+
+#define RECURSOR_SOCKET  LOCALSTATEDIR"/run/pdns_recursor.controlsocket"
+#define RECURSOR_COMMAND "get noerror-answers nxdomain-answers " \
+  "servfail-answers sys-msec user-msec qa-latency cache-entries cache-hits " \
+  "cache-misses questions\n"
+
+struct list_item_s;
+typedef struct list_item_s list_item_t;
+
+struct list_item_s
+{
+  enum
+  {
+    SRV_AUTHORITATIVE,
+    SRV_RECURSOR
+  } server_type;
+  int (*func) (list_item_t *item);
+  char *instance;
+
+  char **fields;
+  int fields_num;
+  char *command;
+
+  struct sockaddr_un sockaddr;
+  int socktype;
+};
+
+struct statname_lookup_s
+{
+  char *name;
+  char *type;
+  char *type_instance;
+};
+typedef struct statname_lookup_s statname_lookup_t;
+
+/* Description of statistics returned by the recursor: {{{
+all-outqueries      counts the number of outgoing UDP queries since starting
+answers0-1          counts the number of queries answered within 1 millisecond
+answers100-1000     counts the number of queries answered within 1 second
+answers10-100       counts the number of queries answered within 100 milliseconds
+answers1-10         counts the number of queries answered within 10 milliseconds
+answers-slow        counts the number of queries answered after 1 second
+cache-entries       shows the number of entries in the cache
+cache-hits          counts the number of cache hits since starting
+cache-misses        counts the number of cache misses since 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
+negcache-entries    shows the number of entries in the Negative answer cache
+noerror-answers     counts the number of times it answered NOERROR since starting
+nsspeeds-entries    shows the number of entries in the NS speeds map
+nsset-invalidations number of times an nsset was dropped because it no longer worked
+nxdomain-answers    counts the number of times it answered NXDOMAIN since starting
+outgoing-timeouts   counts the number of timeouts on outgoing UDP queries since starting
+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
+server-parse-errors counts number of server replied packets that could not be parsed
+servfail-answers    counts the number of times it answered SERVFAIL since starting
+spoof-prevents      number of times PowerDNS considered itself spoofed, and 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
+tcp-outqueries      counts the number of outgoing TCP queries since starting
+tcp-questions       counts all incoming TCP queries (since starting)
+throttled-out       counts the number of throttled outgoing UDP queries since starting
+throttle-entries    shows the number of entries in the throttle map
+unauthorized-tcp    number of TCP questions denied because of allow-from restrictions
+unauthorized-udp    number of UDP questions denied because of allow-from restrictions
+unexpected-packets  number of answers from remote servers that were unexpected (might point to spoofing)
+uptime              number of seconds process has been running (since 3.1.5)
+user-msec           number of CPU milliseconds spent in 'user' mode
+}}} */
+
+const char* const default_server_fields[] = /* {{{ */
+{
+  "latency"
+  "packetcache-hit",
+  "packetcache-miss",
+  "packetcache-size",
+  "query-cache-hit",
+  "query-cache-miss",
+  "recursing-answers",
+  "recursing-questions",
+  "tcp-answers",
+  "tcp-queries",
+  "udp-answers",
+  "udp-queries",
+}; /* }}} */
+int default_server_fields_num = STATIC_ARRAY_SIZE (default_server_fields);
+
+statname_lookup_t lookup_table[] = /* {{{ */
+{
+  /*********************
+   * Server statistics *
+   *********************/
+  /* Questions */
+  {"recursing-questions",    "dns_question", "recurse"},
+  {"tcp-queries",            "dns_question", "tcp"},
+  {"udp-queries",            "dns_question", "udp"},
+  {"rd-queries",             "dns_question", "rd"},
+
+  /* Answers */
+  {"recursing-answers",      "dns_answer",   "recurse"},
+  {"tcp-answers",            "dns_answer",   "tcp"},
+  {"udp-answers",            "dns_answer",   "udp"},
+  {"recursion-unanswered",   "dns_answer",   "recursion-unanswered"},
+  {"udp-answers-bytes",      "total_bytes",  "udp-answers-bytes"},
+
+  /* Cache stuff */
+  {"packetcache-hit",        "cache_result", "packet-hit"},
+  {"packetcache-miss",       "cache_result", "packet-miss"},
+  {"packetcache-size",       "cache_size",   "packet"},
+  {"key-cache-size",         "cache_size",   "key"},
+  {"meta-cache-size",        "cache_size",   "meta"},
+  {"signature-cache-size",   "cache_size",   "signature"},
+  {"query-cache-hit",        "cache_result", "query-hit"},
+  {"query-cache-miss",       "cache_result", "query-miss"},
+
+  /* Latency */
+  {"latency",                "latency",      NULL},
+
+  /* DNS updates */
+  {"dnsupdate-answers",      "dns_answer",   "dnsupdate-answer"},
+  {"dnsupdate-changes",      "dns_question", "dnsupdate-changes"},
+  {"dnsupdate-queries",      "dns_question", "dnsupdate-queries"},
+  {"dnsupdate-refused",      "dns_answer",   "dnsupdate-refused"},
+
+  /* Other stuff.. */
+  {"corrupt-packets",        "ipt_packets",  "corrupt"},
+  {"deferred-cache-inserts", "counter",      "cache-deferred_insert"},
+  {"deferred-cache-lookup",  "counter",      "cache-deferred_lookup"},
+  {"qsize-a",                "cache_size",   "answers"},
+  {"qsize-q",                "cache_size",   "questions"},
+  {"servfail-packets",       "ipt_packets",  "servfail"},
+  {"timedout-packets",       "ipt_packets",  "timeout"},
+  {"udp4-answers",           "dns_answer",   "udp4"},
+  {"udp4-queries",           "dns_question", "queries-udp4"},
+  {"udp6-answers",           "dns_answer",   "udp6"},
+  {"udp6-queries",           "dns_question", "queries-udp6"},
+  {"security-status",        "dns_question", "security-status"},
+  {"udp-do-queries",         "dns_question", "udp-do_queries"},
+  {"signatures",             "counter",      "signatures"},
+
+  /***********************
+   * Recursor statistics *
+   ***********************/
+  /* Answers by return code */
+  {"noerror-answers",     "dns_rcode",    "NOERROR"},
+  {"nxdomain-answers",    "dns_rcode",    "NXDOMAIN"},
+  {"servfail-answers",    "dns_rcode",    "SERVFAIL"},
+
+  /* CPU utilization */
+  {"sys-msec",            "cpu",          "system"},
+  {"user-msec",           "cpu",          "user"},
+
+  /* Question-to-answer latency */
+  {"qa-latency",          "latency",      NULL},
+
+  /* Cache */
+  {"cache-entries",       "cache_size",   NULL},
+  {"cache-hits",          "cache_result", "hit"},
+  {"cache-misses",        "cache_result", "miss"},
+
+  /* Total number of questions.. */
+  {"questions",           "dns_qtype",    "total"},
+
+  /* All the other stuff.. */
+  {"all-outqueries",      "dns_question", "outgoing"},
+  {"answers0-1",          "dns_answer",   "0_1"},
+  {"answers1-10",         "dns_answer",   "1_10"},
+  {"answers10-100",       "dns_answer",   "10_100"},
+  {"answers100-1000",     "dns_answer",   "100_1000"},
+  {"answers-slow",        "dns_answer",   "slow"},
+  {"chain-resends",       "dns_question", "chained"},
+  {"client-parse-errors", "counter",      "drops-client_parse_error"},
+  {"concurrent-queries",  "dns_question", "concurrent"},
+  {"dlg-only-drops",      "counter",      "drops-delegation_only"},
+  {"negcache-entries",    "cache_size",   "negative"},
+  {"nsspeeds-entries",    "gauge",        "entries-ns_speeds"},
+  {"nsset-invalidations", "counter",      "ns_set_invalidation"},
+  {"outgoing-timeouts",   "counter",      "drops-timeout_outgoing"},
+  {"resource-limits",     "counter",      "drops-resource_limit"},
+  {"server-parse-errors", "counter",      "drops-server_parse_error"},
+  {"spoof-prevents",      "counter",      "drops-spoofed"},
+  {"tcp-client-overflow", "counter",      "denied-client_overflow_tcp"},
+  {"tcp-outqueries",      "dns_question", "outgoing-tcp"},
+  {"tcp-questions",       "dns_question", "incoming-tcp"},
+  {"throttled-out",       "dns_question", "outgoing-throttled"},
+  {"throttle-entries",    "gauge",        "entries-throttle"},
+  {"unauthorized-tcp",    "counter",      "denied-unauthorized_tcp"},
+  {"unauthorized-udp",    "counter",      "denied-unauthorized_udp"},
+  {"unexpected-packets",  "dns_answer",   "unexpected"},
+  {"uptime",              "uptime",       NULL}
+}; /* }}} */
+int lookup_table_length = STATIC_ARRAY_SIZE (lookup_table);
+
+static llist_t *list = NULL;
+
+#define PDNS_LOCAL_SOCKPATH LOCALSTATEDIR"/run/"PACKAGE_NAME"-powerdns"
+static char *local_sockpath = NULL;
+
+/* TODO: Do this before 4.4:
+ * - Recursor:
+ *   - Complete list of known pdns -> collectd mappings.
+ * - Update the collectd.conf(5) manpage.
+ *
+ * -octo
+ */
+
+/* <http://doc.powerdns.com/recursor-stats.html> */
+static void submit (const char *plugin_instance, /* {{{ */
+    const char *pdns_type, const char *value)
+{
+  value_list_t vl = VALUE_LIST_INIT;
+  value_t values[1];
+
+  const char *type = NULL;
+  const char *type_instance = NULL;
+  const data_set_t *ds;
+
+  int i;
+
+  for (i = 0; i < lookup_table_length; i++)
+    if (strcmp (lookup_table[i].name, pdns_type) == 0)
+      break;
+
+  if (i >= lookup_table_length)
+  {
+    INFO ("powerdns plugin: submit: Not found in lookup table: %s = %s;",
+        pdns_type, value);
+    return;
+  }
+
+  if (lookup_table[i].type == NULL)
+    return;
+
+  type = lookup_table[i].type;
+  type_instance = lookup_table[i].type_instance;
+
+  ds = plugin_get_ds (type);
+  if (ds == NULL)
+  {
+    ERROR ("powerdns plugin: The lookup table returned type `%s', "
+        "but I cannot find it via `plugin_get_ds'.",
+        type);
+    return;
+  }
+
+  if (ds->ds_num != 1)
+  {
+    ERROR ("powerdns plugin: type `%s' has %i data sources, "
+        "but I can only handle one.",
+        type, ds->ds_num);
+    return;
+  }
+
+  if (0 != parse_value (value, &values[0], ds->ds[0].type))
+  {
+    ERROR ("powerdns plugin: Cannot convert `%s' "
+        "to a number.", value);
+    return;
+  }
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "powerdns", sizeof (vl.plugin));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+  sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+
+  plugin_dispatch_values (&vl);
+} /* }}} static void submit */
+
+static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */
+    char **ret_buffer,
+    size_t *ret_buffer_size)
+{
+  int sd;
+  int status;
+
+  char temp[4096];
+  char *buffer = NULL;
+  size_t buffer_size = 0;
+
+  struct sockaddr_un sa_unix;
+
+  struct timeval stv_timeout;
+  cdtime_t cdt_timeout;
+
+  sd = socket (PF_UNIX, item->socktype, 0);
+  if (sd < 0)
+  {
+    FUNC_ERROR ("socket");
+    return (-1);
+  }
+
+  memset (&sa_unix, 0, sizeof (sa_unix));
+  sa_unix.sun_family = AF_UNIX;
+  sstrncpy (sa_unix.sun_path,
+      (local_sockpath != NULL) ? local_sockpath : PDNS_LOCAL_SOCKPATH,
+      sizeof (sa_unix.sun_path));
+
+  status = unlink (sa_unix.sun_path);
+  if ((status != 0) && (errno != ENOENT))
+  {
+    FUNC_ERROR ("unlink");
+    close (sd);
+    return (-1);
+  }
+
+  do /* while (0) */
+  {
+    /* We need to bind to a specific path, because this is a datagram socket
+     * and otherwise the daemon cannot answer. */
+    status = bind (sd, (struct sockaddr *) &sa_unix, sizeof (sa_unix));
+    if (status != 0)
+    {
+      FUNC_ERROR ("bind");
+      break;
+    }
+
+    /* Make the socket writeable by the daemon.. */
+    status = chmod (sa_unix.sun_path, 0666);
+    if (status != 0)
+    {
+      FUNC_ERROR ("chmod");
+      break;
+    }
+
+    cdt_timeout = plugin_get_interval () * 3 / 4;
+    if (cdt_timeout < TIME_T_TO_CDTIME_T (2))
+      cdt_timeout = TIME_T_TO_CDTIME_T (2);
+
+    CDTIME_T_TO_TIMEVAL (cdt_timeout, &stv_timeout);
+
+    status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &stv_timeout, sizeof (stv_timeout));
+    if (status != 0)
+    {
+      FUNC_ERROR ("setsockopt");
+      break;
+    }
+
+    status = connect (sd, (struct sockaddr *) &item->sockaddr,
+        sizeof (item->sockaddr));
+    if (status != 0)
+    {
+      FUNC_ERROR ("connect");
+      break;
+    }
+
+    status = send (sd, item->command, strlen (item->command), 0);
+    if (status < 0)
+    {
+      FUNC_ERROR ("send");
+      break;
+    }
+
+    status = recv (sd, temp, sizeof (temp), /* flags = */ 0);
+    if (status < 0)
+    {
+      FUNC_ERROR ("recv");
+      break;
+    }
+    buffer_size = status + 1;
+    status = 0;
+  } while (0);
+
+  close (sd);
+  unlink (sa_unix.sun_path);
+
+  if (status != 0)
+    return (-1);
+
+  assert (buffer_size > 0);
+  buffer = (char *) malloc (buffer_size);
+  if (buffer == NULL)
+  {
+    FUNC_ERROR ("malloc");
+    return (-1);
+  }
+
+  memcpy (buffer, temp, buffer_size - 1);
+  buffer[buffer_size - 1] = 0;
+
+  *ret_buffer = buffer;
+  *ret_buffer_size = buffer_size;
+
+  return (0);
+} /* }}} int powerdns_get_data_dgram */
+
+static int powerdns_get_data_stream (list_item_t *item, /* {{{ */
+    char **ret_buffer,
+    size_t *ret_buffer_size)
+{
+  int sd;
+  int status;
+
+  char temp[4096];
+  char *buffer = NULL;
+  size_t buffer_size = 0;
+
+  sd = socket (PF_UNIX, item->socktype, 0);
+  if (sd < 0)
+  {
+    FUNC_ERROR ("socket");
+    return (-1);
+  }
+
+  struct timeval timeout;
+  timeout.tv_sec=5;
+  timeout.tv_usec=0;
+  status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (timeout));
+
+  status = connect (sd, (struct sockaddr *) &item->sockaddr,
+      sizeof (item->sockaddr));
+  if (status != 0)
+  {
+    FUNC_ERROR ("connect");
+    close (sd);
+    return (-1);
+  }
+
+  /* strlen + 1, because we need to send the terminating NULL byte, too. */
+  status = send (sd, item->command, strlen (item->command) + 1,
+      /* flags = */ 0);
+  if (status < 0)
+  {
+    FUNC_ERROR ("send");
+    close (sd);
+    return (-1);
+  }
+
+  while (42)
+  {
+    char *buffer_new;
+
+    status = recv (sd, temp, sizeof (temp), /* flags = */ 0);
+    if (status < 0)
+    {
+      FUNC_ERROR ("recv");
+      break;
+    }
+    else if (status == 0)
+      break;
+
+    buffer_new = (char *) realloc (buffer, buffer_size + status + 1);
+    if (buffer_new == NULL)
+    {
+      FUNC_ERROR ("realloc");
+      status = -1;
+      break;
+    }
+    buffer = buffer_new;
+
+    memcpy (buffer + buffer_size, temp, status);
+    buffer_size += status;
+    buffer[buffer_size] = 0;
+  } /* while (42) */
+  close (sd);
+  sd = -1;
+
+  if (status < 0)
+  {
+    sfree (buffer);
+  }
+  else
+  {
+    assert (status == 0);
+    *ret_buffer = buffer;
+    *ret_buffer_size = buffer_size;
+  }
+
+  return (status);
+} /* }}} int powerdns_get_data_stream */
+
+static int powerdns_get_data (list_item_t *item, char **ret_buffer,
+    size_t *ret_buffer_size)
+{
+  if (item->socktype == SOCK_DGRAM)
+    return (powerdns_get_data_dgram (item, ret_buffer, ret_buffer_size));
+  else if (item->socktype == SOCK_STREAM)
+    return (powerdns_get_data_stream (item, ret_buffer, ret_buffer_size));
+  else
+  {
+    ERROR ("powerdns plugin: Unknown socket type: %i", (int) item->socktype);
+    return (-1);
+  }
+} /* int powerdns_get_data */
+
+static int powerdns_read_server (list_item_t *item) /* {{{ */
+{
+  char *buffer = NULL;
+  size_t buffer_size = 0;
+  int status;
+
+  char *dummy;
+  char *saveptr;
+
+  char *key;
+  char *value;
+
+  const char* const *fields;
+  int fields_num;
+
+  if (item->command == NULL)
+    item->command = strdup (SERVER_COMMAND);
+  if (item->command == NULL)
+  {
+    ERROR ("powerdns plugin: strdup failed.");
+    return (-1);
+  }
+
+  status = powerdns_get_data (item, &buffer, &buffer_size);
+  if (status != 0)
+    return (-1);
+
+  if (item->fields_num != 0)
+  {
+    fields = (const char* const *) item->fields;
+    fields_num = item->fields_num;
+  }
+  else
+  {
+    fields = default_server_fields;
+    fields_num = default_server_fields_num;
+  }
+
+  assert (fields != NULL);
+  assert (fields_num > 0);
+
+  /* corrupt-packets=0,deferred-cache-inserts=0,deferred-cache-lookup=0,latency=0,packetcache-hit=0,packetcache-miss=0,packetcache-size=0,qsize-q=0,query-cache-hit=0,query-cache-miss=0,recursing-answers=0,recursing-questions=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,timedout-packets=0,udp-answers=0,udp-queries=0,udp4-answers=0,udp4-queries=0,udp6-answers=0,udp6-queries=0, */
+  dummy = buffer;
+  saveptr = NULL;
+  while ((key = strtok_r (dummy, ",", &saveptr)) != NULL)
+  {
+    int i;
+
+    dummy = NULL;
+
+    value = strchr (key, '=');
+    if (value == NULL)
+      break;
+
+    *value = '\0';
+    value++;
+
+    if (value[0] == '\0')
+      continue;
+
+    /* Check if this item was requested. */
+    for (i = 0; i < fields_num; i++)
+      if (strcasecmp (key, fields[i]) == 0)
+       break;
+    if (i >= fields_num)
+      continue;
+
+    submit (item->instance, key, value);
+  } /* while (strtok_r) */
+
+  sfree (buffer);
+
+  return (0);
+} /* }}} int powerdns_read_server */
+
+/*
+ * powerdns_update_recursor_command
+ *
+ * Creates a string that holds the command to be sent to the recursor. This
+ * string is stores in the `command' member of the `list_item_t' passed to the
+ * function. This function is called by `powerdns_read_recursor'.
+ */
+static int powerdns_update_recursor_command (list_item_t *li) /* {{{ */
+{
+  char buffer[4096];
+  int status;
+
+  if (li == NULL)
+    return (0);
+
+  if (li->fields_num < 1)
+  {
+    sstrncpy (buffer, RECURSOR_COMMAND, sizeof (buffer));
+  }
+  else
+  {
+    sstrncpy (buffer, "get ", sizeof (buffer));
+    status = strjoin (&buffer[strlen("get ")], sizeof (buffer) - strlen ("get "),
+       li->fields, li->fields_num,
+       /* seperator = */ " ");
+    if (status < 0)
+    {
+      ERROR ("powerdns plugin: strjoin failed.");
+      return (-1);
+    }
+    buffer[sizeof (buffer) - 1] = 0;
+    int i = strlen (buffer);
+    if (i < sizeof (buffer) - 2)
+    {
+      buffer[i++] = ' ';
+      buffer[i++] = '\n';
+      buffer[i++] = '\0';
+    }
+  }
+
+  buffer[sizeof (buffer) - 1] = 0;
+  li->command = strdup (buffer);
+  if (li->command == NULL)
+  {
+    ERROR ("powerdns plugin: strdup failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int powerdns_update_recursor_command */
+
+static int powerdns_read_recursor (list_item_t *item) /* {{{ */
+{
+  char *buffer = NULL;
+  size_t buffer_size = 0;
+  int status;
+
+  char *dummy;
+
+  char *keys_list;
+  char *key;
+  char *key_saveptr;
+  char *value;
+  char *value_saveptr;
+
+  if (item->command == NULL)
+  {
+    status = powerdns_update_recursor_command (item);
+    if (status != 0)
+    {
+      ERROR ("powerdns plugin: powerdns_update_recursor_command failed.");
+      return (-1);
+    }
+
+    DEBUG ("powerdns plugin: powerdns_read_recursor: item->command = %s;",
+        item->command);
+  }
+  assert (item->command != NULL);
+
+  status = powerdns_get_data (item, &buffer, &buffer_size);
+  if (status != 0)
+  {
+    ERROR ("powerdns plugin: powerdns_get_data failed.");
+    return (-1);
+  }
+
+  keys_list = strdup (item->command);
+  if (keys_list == NULL)
+  {
+    FUNC_ERROR ("strdup");
+    sfree (buffer);
+    return (-1);
+  }
+
+  key_saveptr = NULL;
+  value_saveptr = NULL;
+
+  /* Skip the `get' at the beginning */
+  strtok_r (keys_list, " \t", &key_saveptr);
+
+  dummy = buffer;
+  while ((value = strtok_r (dummy, " \t\n\r", &value_saveptr)) != NULL)
+  {
+    dummy = NULL;
+
+    key = strtok_r (NULL, " \t", &key_saveptr);
+    if (key == NULL)
+      break;
+
+    submit (item->instance, key, value);
+  } /* while (strtok_r) */
+
+  sfree (buffer);
+  sfree (keys_list);
+
+  return (0);
+} /* }}} int powerdns_read_recursor */
+
+static int powerdns_config_add_string (const char *name, /* {{{ */
+    char **dest,
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("powerdns plugin: `%s' needs exactly one string argument.",
+       name);
+    return (-1);
+  }
+
+  sfree (*dest);
+  *dest = strdup (ci->values[0].value.string);
+  if (*dest == NULL)
+    return (-1);
+
+  return (0);
+} /* }}} int powerdns_config_add_string */
+
+static int powerdns_config_add_collect (list_item_t *li, /* {{{ */
+    oconfig_item_t *ci)
+{
+  int i;
+  char **temp;
+
+  if (ci->values_num < 1)
+  {
+    WARNING ("powerdns plugin: The `Collect' option needs "
+       "at least one argument.");
+    return (-1);
+  }
+
+  for (i = 0; i < ci->values_num; i++)
+    if (ci->values[i].type != OCONFIG_TYPE_STRING)
+    {
+      WARNING ("powerdns plugin: Only string arguments are allowed to "
+         "the `Collect' option.");
+      return (-1);
+    }
+
+  temp = (char **) realloc (li->fields,
+      sizeof (char *) * (li->fields_num + ci->values_num));
+  if (temp == NULL)
+  {
+    WARNING ("powerdns plugin: realloc failed.");
+    return (-1);
+  }
+  li->fields = temp;
+
+  for (i = 0; i < ci->values_num; i++)
+  {
+    li->fields[li->fields_num] = strdup (ci->values[i].value.string);
+    if (li->fields[li->fields_num] == NULL)
+    {
+      WARNING ("powerdns plugin: strdup failed.");
+      continue;
+    }
+    li->fields_num++;
+  }
+
+  /* Invalidate a previously computed command */
+  sfree (li->command);
+
+  return (0);
+} /* }}} int powerdns_config_add_collect */
+
+static int powerdns_config_add_server (oconfig_item_t *ci) /* {{{ */
+{
+  char *socket_temp;
+
+  list_item_t *item;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("powerdns plugin: `%s' needs exactly one string argument.",
+       ci->key);
+    return (-1);
+  }
+
+  item = (list_item_t *) malloc (sizeof (list_item_t));
+  if (item == NULL)
+  {
+    ERROR ("powerdns plugin: malloc failed.");
+    return (-1);
+  }
+  memset (item, '\0', sizeof (list_item_t));
+
+  item->instance = strdup (ci->values[0].value.string);
+  if (item->instance == NULL)
+  {
+    ERROR ("powerdns plugin: strdup failed.");
+    sfree (item);
+    return (-1);
+  }
+
+  /*
+   * Set default values for the members of list_item_t
+   */
+  if (strcasecmp ("Server", ci->key) == 0)
+  {
+    item->server_type = SRV_AUTHORITATIVE;
+    item->func = powerdns_read_server;
+    item->socktype = SOCK_STREAM;
+    socket_temp = strdup (SERVER_SOCKET);
+  }
+  else if (strcasecmp ("Recursor", ci->key) == 0)
+  {
+    item->server_type = SRV_RECURSOR;
+    item->func = powerdns_read_recursor;
+    item->socktype = SOCK_DGRAM;
+    socket_temp = strdup (RECURSOR_SOCKET);
+  }
+  else
+  {
+    /* We must never get here.. */
+    assert (0);
+    return (-1);
+  }
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if (strcasecmp ("Collect", option->key) == 0)
+      status = powerdns_config_add_collect (item, option);
+    else if (strcasecmp ("Socket", option->key) == 0)
+      status = powerdns_config_add_string ("Socket", &socket_temp, option);
+    else
+    {
+      ERROR ("powerdns plugin: Option `%s' not allowed here.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  while (status == 0)
+  {
+    llentry_t *e;
+
+    if (socket_temp == NULL)
+    {
+      ERROR ("powerdns plugin: socket_temp == NULL.");
+      status = -1;
+      break;
+    }
+
+    item->sockaddr.sun_family = AF_UNIX;
+    sstrncpy (item->sockaddr.sun_path, socket_temp,
+      sizeof (item->sockaddr.sun_path));
+
+    e = llentry_create (item->instance, item);
+    if (e == NULL)
+    {
+      ERROR ("powerdns plugin: llentry_create failed.");
+      status = -1;
+      break;
+    }
+    llist_append (list, e);
+
+    break;
+  }
+
+  if (status != 0)
+  {
+    sfree (item);
+    return (-1);
+  }
+
+  DEBUG ("powerdns plugin: Add server: instance = %s;", item->instance);
+
+  return (0);
+} /* }}} int powerdns_config_add_server */
+
+static int powerdns_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  DEBUG ("powerdns plugin: powerdns_config (ci = %p);", (void *) ci);
+
+  if (list == NULL)
+  {
+    list = llist_create ();
+
+    if (list == NULL)
+    {
+      ERROR ("powerdns plugin: `llist_create' failed.");
+      return (-1);
+    }
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if ((strcasecmp ("Server", option->key) == 0)
+       || (strcasecmp ("Recursor", option->key) == 0))
+      powerdns_config_add_server (option);
+    else if (strcasecmp ("LocalSocket", option->key) == 0)
+    {
+      if ((option->values_num != 1) || (option->values[0].type != OCONFIG_TYPE_STRING))
+      {
+        WARNING ("powerdns plugin: `%s' needs exactly one string argument.", option->key);
+      }
+      else
+      {
+        char *temp = strdup (option->values[0].value.string);
+        if (temp == NULL)
+          return (1);
+        sfree (local_sockpath);
+        local_sockpath = temp;
+      }
+    }
+    else
+    {
+      ERROR ("powerdns plugin: Option `%s' not allowed here.", option->key);
+    }
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  return (0);
+} /* }}} int powerdns_config */
+
+static int powerdns_read (void)
+{
+  llentry_t *e;
+
+  for (e = llist_head (list); e != NULL; e = e->next)
+  {
+    list_item_t *item = e->value;
+    item->func (item);
+  }
+
+  return (0);
+} /* static int powerdns_read */
+
+static int powerdns_shutdown (void)
+{
+  llentry_t *e;
+
+  if (list == NULL)
+    return (0);
+
+  for (e = llist_head (list); e != NULL; e = e->next)
+  {
+    list_item_t *item = (list_item_t *) e->value;
+    e->value = NULL;
+
+    sfree (item->instance);
+    sfree (item->command);
+    sfree (item);
+  }
+
+  llist_destroy (list);
+  list = NULL;
+
+  return (0);
+} /* static int powerdns_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("powerdns", powerdns_config);
+  plugin_register_read ("powerdns", powerdns_read);
+  plugin_register_shutdown ("powerdns", powerdns_shutdown );
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 ts=8 fdm=marker : */
diff --git a/src/processes.c b/src/processes.c
new file mode 100644 (file)
index 0000000..0649eab
--- /dev/null
@@ -0,0 +1,2329 @@
+/**
+ * collectd - src/processes.c
+ * Copyright (C) 2005       Lyonel Vincent
+ * Copyright (C) 2006-2010  Florian octo Forster
+ * Copyright (C) 2008       Oleg King
+ * Copyright (C) 2009       Sebastian Harl
+ * Copyright (C) 2009       Andrés J. Díaz
+ * Copyright (C) 2009       Manuel Sanmartin
+ * Copyright (C) 2010       Clément Stenac
+ * Copyright (C) 2012       Cosmin Ioiart
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Lyonel Vincent <lyonel at ezix.org>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Oleg King <king2 at kaluga.ru>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Andrés J. Díaz <ajdiaz at connectical.com>
+ *   Manuel Sanmartin
+ *   Clément Stenac <clement.stenac at diwi.org>
+ *   Cosmin Ioiart <cioiart at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+/* Include header files for the mach system, if they exist.. */
+#if HAVE_THREAD_INFO
+#  if HAVE_MACH_MACH_INIT_H
+#    include <mach/mach_init.h>
+#  endif
+#  if HAVE_MACH_HOST_PRIV_H
+#    include <mach/host_priv.h>
+#  endif
+#  if HAVE_MACH_MACH_ERROR_H
+#    include <mach/mach_error.h>
+#  endif
+#  if HAVE_MACH_MACH_HOST_H
+#    include <mach/mach_host.h>
+#  endif
+#  if HAVE_MACH_MACH_PORT_H
+#    include <mach/mach_port.h>
+#  endif
+#  if HAVE_MACH_MACH_TYPES_H
+#    include <mach/mach_types.h>
+#  endif
+#  if HAVE_MACH_MESSAGE_H
+#    include <mach/message.h>
+#  endif
+#  if HAVE_MACH_PROCESSOR_SET_H
+#    include <mach/processor_set.h>
+#  endif
+#  if HAVE_MACH_TASK_H
+#    include <mach/task.h>
+#  endif
+#  if HAVE_MACH_THREAD_ACT_H
+#    include <mach/thread_act.h>
+#  endif
+#  if HAVE_MACH_VM_REGION_H
+#    include <mach/vm_region.h>
+#  endif
+#  if HAVE_MACH_VM_MAP_H
+#    include <mach/vm_map.h>
+#  endif
+#  if HAVE_MACH_VM_PROT_H
+#    include <mach/vm_prot.h>
+#  endif
+#  if HAVE_SYS_SYSCTL_H
+#    include <sys/sysctl.h>
+#  endif
+/* #endif HAVE_THREAD_INFO */
+
+#elif KERNEL_LINUX
+#  if HAVE_LINUX_CONFIG_H
+#    include <linux/config.h>
+#  endif
+#  ifndef CONFIG_HZ
+#    define CONFIG_HZ 100
+#  endif
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
+#  include <kvm.h>
+#  include <sys/param.h>
+#  include <sys/sysctl.h>
+#  include <sys/user.h>
+#  include <sys/proc.h>
+/* #endif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD) */
+
+#elif HAVE_PROCINFO_H
+#  include <procinfo.h>
+#  include <sys/types.h>
+
+#define MAXPROCENTRY 32
+#define MAXTHRDENTRY 16
+#define MAXARGLN 1024
+/* #endif HAVE_PROCINFO_H */
+
+#elif KERNEL_SOLARIS
+/* Hack: Avoid #error when building a 32-bit binary with
+ * _FILE_OFFSET_BITS=64. There is a reason for this #error, as one
+ * of the structures in <sys/procfs.h> uses an off_t, but that
+ * isn't relevant to our usage of procfs. */
+#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  define SAVE_FOB_64
+#  undef _FILE_OFFSET_BITS
+#endif
+
+# include <procfs.h>
+
+#ifdef SAVE_FOB_64
+#  define _FILE_OFFSET_BITS 64
+#  undef SAVE_FOB_64
+#endif
+
+# include <dirent.h>
+/* #endif KERNEL_SOLARIS */
+
+#else
+# error "No applicable input method."
+#endif
+
+#if HAVE_REGEX_H
+# include <regex.h>
+#endif
+
+#if HAVE_KSTAT_H
+# include <kstat.h>
+#endif
+
+#ifndef CMDLINE_BUFFER_SIZE
+# if defined(ARG_MAX) && (ARG_MAX < 4096)
+#  define CMDLINE_BUFFER_SIZE ARG_MAX
+# else
+#  define CMDLINE_BUFFER_SIZE 4096
+# endif
+#endif
+
+typedef struct procstat_entry_s
+{
+       unsigned long id;
+       unsigned long age;
+
+       unsigned long num_proc;
+       unsigned long num_lwp;
+       unsigned long vmem_size;
+       unsigned long vmem_rss;
+       unsigned long vmem_data;
+       unsigned long vmem_code;
+       unsigned long stack_size;
+
+       unsigned long vmem_minflt;
+       unsigned long vmem_majflt;
+       derive_t      vmem_minflt_counter;
+       derive_t      vmem_majflt_counter;
+
+       unsigned long cpu_user;
+       unsigned long cpu_system;
+       derive_t      cpu_user_counter;
+       derive_t      cpu_system_counter;
+
+       /* io data */
+       derive_t io_rchar;
+       derive_t io_wchar;
+       derive_t io_syscr;
+       derive_t io_syscw;
+
+       struct procstat_entry_s *next;
+} procstat_entry_t;
+
+#define PROCSTAT_NAME_LEN 256
+typedef struct procstat
+{
+       char          name[PROCSTAT_NAME_LEN];
+#if HAVE_REGEX_H
+       regex_t *re;
+#endif
+
+       unsigned long num_proc;
+       unsigned long num_lwp;
+       unsigned long vmem_size;
+       unsigned long vmem_rss;
+       unsigned long vmem_data;
+       unsigned long vmem_code;
+       unsigned long stack_size;
+
+       derive_t vmem_minflt_counter;
+       derive_t vmem_majflt_counter;
+
+       derive_t cpu_user_counter;
+       derive_t cpu_system_counter;
+
+       /* io data */
+       derive_t io_rchar;
+       derive_t io_wchar;
+       derive_t io_syscr;
+       derive_t io_syscw;
+
+       struct procstat   *next;
+       struct procstat_entry_s *instances;
+} procstat_t;
+
+static procstat_t *list_head_g = NULL;
+
+#if HAVE_THREAD_INFO
+static mach_port_t port_host_self;
+static mach_port_t port_task_self;
+
+static processor_set_name_array_t pset_list;
+static mach_msg_type_number_t     pset_list_len;
+/* #endif HAVE_THREAD_INFO */
+
+#elif KERNEL_LINUX
+static long pagesize_g;
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
+static int pagesize;
+/* #endif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD) */
+
+#elif HAVE_PROCINFO_H
+static  struct procentry64 procentry[MAXPROCENTRY];
+static  struct thrdentry64 thrdentry[MAXTHRDENTRY];
+static int pagesize;
+
+#ifndef _AIXVERSION_610
+int     getprocs64 (void *procsinfo, int sizproc, void *fdsinfo, int sizfd, pid_t *index, int count);
+int     getthrds64( pid_t, void *, int, tid64_t *, int );
+#endif
+int getargs (void *processBuffer, int bufferLen, char *argsBuffer, int argsLen);
+#endif /* HAVE_PROCINFO_H */
+
+/* put name of process from config to list_head_g tree
+ * list_head_g is a list of 'procstat_t' structs with
+ * processes names we want to watch */
+static void ps_list_register (const char *name, const char *regexp)
+{
+       procstat_t *new;
+       procstat_t *ptr;
+       int status;
+
+       new = (procstat_t *) malloc (sizeof (procstat_t));
+       if (new == NULL)
+       {
+               ERROR ("processes plugin: ps_list_register: malloc failed.");
+               return;
+       }
+       memset (new, 0, sizeof (procstat_t));
+       sstrncpy (new->name, name, sizeof (new->name));
+
+#if HAVE_REGEX_H
+       if (regexp != NULL)
+       {
+               DEBUG ("ProcessMatch: adding \"%s\" as criteria to process %s.", regexp, name);
+               new->re = (regex_t *) malloc (sizeof (regex_t));
+               if (new->re == NULL)
+               {
+                       ERROR ("processes plugin: ps_list_register: malloc failed.");
+                       sfree (new);
+                       return;
+               }
+
+               status = regcomp (new->re, regexp, REG_EXTENDED | REG_NOSUB);
+               if (status != 0)
+               {
+                       DEBUG ("ProcessMatch: compiling the regular expression \"%s\" failed.", regexp);
+                       sfree(new->re);
+                       return;
+               }
+       }
+#else
+       if (regexp != NULL)
+       {
+               ERROR ("processes plugin: ps_list_register: "
+                               "Regular expression \"%s\" found in config "
+                               "file, but support for regular expressions "
+                               "has been disabled at compile time.",
+                               regexp);
+               sfree (new);
+               return;
+       }
+#endif
+
+       for (ptr = list_head_g; ptr != NULL; ptr = ptr->next)
+       {
+               if (strcmp (ptr->name, name) == 0)
+               {
+                       WARNING ("processes plugin: You have configured more "
+                                       "than one `Process' or "
+                                       "`ProcessMatch' with the same name. "
+                                       "All but the first setting will be "
+                                       "ignored.");
+                       sfree (new->re);
+                       sfree (new);
+                       return;
+               }
+
+               if (ptr->next == NULL)
+                       break;
+       }
+
+       if (ptr == NULL)
+               list_head_g = new;
+       else
+               ptr->next = new;
+} /* void ps_list_register */
+
+/* try to match name against entry, returns 1 if success */
+static int ps_list_match (const char *name, const char *cmdline, procstat_t *ps)
+{
+#if HAVE_REGEX_H
+       if (ps->re != NULL)
+       {
+               int status;
+               const char *str;
+
+               str = cmdline;
+               if ((str == NULL) || (str[0] == 0))
+                       str = name;
+
+               assert (str != NULL);
+
+               status = regexec (ps->re, str,
+                               /* nmatch = */ 0,
+                               /* pmatch = */ NULL,
+                               /* eflags = */ 0);
+               if (status == 0)
+                       return (1);
+       }
+       else
+#endif
+       if (strcmp (ps->name, name) == 0)
+               return (1);
+
+       return (0);
+} /* int ps_list_match */
+
+/* add process entry to 'instances' of process 'name' (or refresh it) */
+static void ps_list_add (const char *name, const char *cmdline, procstat_entry_t *entry)
+{
+       procstat_t *ps;
+       procstat_entry_t *pse;
+
+       if (entry->id == 0)
+               return;
+
+       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       {
+               if ((ps_list_match (name, cmdline, ps)) == 0)
+                       continue;
+
+               for (pse = ps->instances; pse != NULL; pse = pse->next)
+                       if ((pse->id == entry->id) || (pse->next == NULL))
+                               break;
+
+               if ((pse == NULL) || (pse->id != entry->id))
+               {
+                       procstat_entry_t *new;
+
+                       new = (procstat_entry_t *) malloc (sizeof (procstat_entry_t));
+                       if (new == NULL)
+                               return;
+                       memset (new, 0, sizeof (procstat_entry_t));
+                       new->id = entry->id;
+
+                       if (pse == NULL)
+                               ps->instances = new;
+                       else
+                               pse->next = new;
+
+                       pse = new;
+               }
+
+               pse->age = 0;
+               pse->num_proc   = entry->num_proc;
+               pse->num_lwp    = entry->num_lwp;
+               pse->vmem_size  = entry->vmem_size;
+               pse->vmem_rss   = entry->vmem_rss;
+               pse->vmem_data  = entry->vmem_data;
+               pse->vmem_code  = entry->vmem_code;
+               pse->stack_size = entry->stack_size;
+               pse->io_rchar   = entry->io_rchar;
+               pse->io_wchar   = entry->io_wchar;
+               pse->io_syscr   = entry->io_syscr;
+               pse->io_syscw   = entry->io_syscw;
+
+               ps->num_proc   += pse->num_proc;
+               ps->num_lwp    += pse->num_lwp;
+               ps->vmem_size  += pse->vmem_size;
+               ps->vmem_rss   += pse->vmem_rss;
+               ps->vmem_data  += pse->vmem_data;
+               ps->vmem_code  += pse->vmem_code;
+               ps->stack_size += pse->stack_size;
+
+               ps->io_rchar   += ((pse->io_rchar == -1)?0:pse->io_rchar);
+               ps->io_wchar   += ((pse->io_wchar == -1)?0:pse->io_wchar);
+               ps->io_syscr   += ((pse->io_syscr == -1)?0:pse->io_syscr);
+               ps->io_syscw   += ((pse->io_syscw == -1)?0:pse->io_syscw);
+
+               if ((entry->vmem_minflt_counter == 0)
+                               && (entry->vmem_majflt_counter == 0))
+               {
+                       pse->vmem_minflt_counter += entry->vmem_minflt;
+                       pse->vmem_minflt = entry->vmem_minflt;
+
+                       pse->vmem_majflt_counter += entry->vmem_majflt;
+                       pse->vmem_majflt = entry->vmem_majflt;
+               }
+               else
+               {
+                       if (entry->vmem_minflt_counter < pse->vmem_minflt_counter)
+                       {
+                               pse->vmem_minflt = entry->vmem_minflt_counter
+                                       + (ULONG_MAX - pse->vmem_minflt_counter);
+                       }
+                       else
+                       {
+                               pse->vmem_minflt = entry->vmem_minflt_counter - pse->vmem_minflt_counter;
+                       }
+                       pse->vmem_minflt_counter = entry->vmem_minflt_counter;
+
+                       if (entry->vmem_majflt_counter < pse->vmem_majflt_counter)
+                       {
+                               pse->vmem_majflt = entry->vmem_majflt_counter
+                                       + (ULONG_MAX - pse->vmem_majflt_counter);
+                       }
+                       else
+                       {
+                               pse->vmem_majflt = entry->vmem_majflt_counter - pse->vmem_majflt_counter;
+                       }
+                       pse->vmem_majflt_counter = entry->vmem_majflt_counter;
+               }
+
+               ps->vmem_minflt_counter += pse->vmem_minflt;
+               ps->vmem_majflt_counter += pse->vmem_majflt;
+
+               if ((entry->cpu_user_counter == 0)
+                               && (entry->cpu_system_counter == 0))
+               {
+                       pse->cpu_user_counter += entry->cpu_user;
+                       pse->cpu_user = entry->cpu_user;
+
+                       pse->cpu_system_counter += entry->cpu_system;
+                       pse->cpu_system = entry->cpu_system;
+               }
+               else
+               {
+                       if (entry->cpu_user_counter < pse->cpu_user_counter)
+                       {
+                               pse->cpu_user = entry->cpu_user_counter
+                                       + (ULONG_MAX - pse->cpu_user_counter);
+                       }
+                       else
+                       {
+                               pse->cpu_user = entry->cpu_user_counter - pse->cpu_user_counter;
+                       }
+                       pse->cpu_user_counter = entry->cpu_user_counter;
+
+                       if (entry->cpu_system_counter < pse->cpu_system_counter)
+                       {
+                               pse->cpu_system = entry->cpu_system_counter
+                                       + (ULONG_MAX - pse->cpu_system_counter);
+                       }
+                       else
+                       {
+                               pse->cpu_system = entry->cpu_system_counter - pse->cpu_system_counter;
+                       }
+                       pse->cpu_system_counter = entry->cpu_system_counter;
+               }
+
+               ps->cpu_user_counter   += pse->cpu_user;
+               ps->cpu_system_counter += pse->cpu_system;
+       }
+}
+
+/* remove old entries from instances of processes in list_head_g */
+static void ps_list_reset (void)
+{
+       procstat_t *ps;
+       procstat_entry_t *pse;
+       procstat_entry_t *pse_prev;
+
+       for (ps = list_head_g; ps != NULL; ps = ps->next)
+       {
+               ps->num_proc    = 0;
+               ps->num_lwp     = 0;
+               ps->vmem_size   = 0;
+               ps->vmem_rss    = 0;
+               ps->vmem_data   = 0;
+               ps->vmem_code   = 0;
+               ps->stack_size  = 0;
+               ps->io_rchar = -1;
+               ps->io_wchar = -1;
+               ps->io_syscr = -1;
+               ps->io_syscw = -1;
+
+               pse_prev = NULL;
+               pse = ps->instances;
+               while (pse != NULL)
+               {
+                       if (pse->age > 10)
+                       {
+                               DEBUG ("Removing this procstat entry cause it's too old: "
+                                               "id = %lu; name = %s;",
+                                               pse->id, ps->name);
+
+                               if (pse_prev == NULL)
+                               {
+                                       ps->instances = pse->next;
+                                       free (pse);
+                                       pse = ps->instances;
+                               }
+                               else
+                               {
+                                       pse_prev->next = pse->next;
+                                       free (pse);
+                                       pse = pse_prev->next;
+                               }
+                       }
+                       else
+                       {
+                               pse->age++;
+                               pse_prev = pse;
+                               pse = pse->next;
+                       }
+               } /* while (pse != NULL) */
+       } /* for (ps = list_head_g; ps != NULL; ps = ps->next) */
+}
+
+/* put all pre-defined 'Process' names from config to list_head_g tree */
+static int ps_config (oconfig_item_t *ci)
+{
+       int i;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (strcasecmp (c->key, "Process") == 0)
+               {
+                       if ((c->values_num != 1)
+                                       || (OCONFIG_TYPE_STRING != c->values[0].type)) {
+                               ERROR ("processes plugin: `Process' expects exactly "
+                                               "one string argument (got %i).",
+                                               c->values_num);
+                               continue;
+                       }
+
+                       if (c->children_num != 0) {
+                               WARNING ("processes plugin: the `Process' config option "
+                                               "does not expect any child elements -- ignoring "
+                                               "content (%i elements) of the <Process '%s'> block.",
+                                               c->children_num, c->values[0].value.string);
+                       }
+
+                       ps_list_register (c->values[0].value.string, NULL);
+               }
+               else if (strcasecmp (c->key, "ProcessMatch") == 0)
+               {
+                       if ((c->values_num != 2)
+                                       || (OCONFIG_TYPE_STRING != c->values[0].type)
+                                       || (OCONFIG_TYPE_STRING != c->values[1].type))
+                       {
+                               ERROR ("processes plugin: `ProcessMatch' needs exactly "
+                                               "two string arguments (got %i).",
+                                               c->values_num);
+                               continue;
+                       }
+
+                       if (c->children_num != 0) {
+                               WARNING ("processes plugin: the `ProcessMatch' config option "
+                                               "does not expect any child elements -- ignoring "
+                                               "content (%i elements) of the <ProcessMatch '%s' '%s'> "
+                                               "block.", c->children_num, c->values[0].value.string,
+                                               c->values[1].value.string);
+                       }
+
+                       ps_list_register (c->values[0].value.string,
+                                       c->values[1].value.string);
+               }
+               else
+               {
+                       ERROR ("processes plugin: The `%s' configuration option is not "
+                                       "understood and will be ignored.", c->key);
+                       continue;
+               }
+       }
+
+       return (0);
+}
+
+static int ps_init (void)
+{
+#if HAVE_THREAD_INFO
+       kern_return_t status;
+
+       port_host_self = mach_host_self ();
+       port_task_self = mach_task_self ();
+
+       if (pset_list != NULL)
+       {
+               vm_deallocate (port_task_self,
+                               (vm_address_t) pset_list,
+                               pset_list_len * sizeof (processor_set_t));
+               pset_list = NULL;
+               pset_list_len = 0;
+       }
+
+       if ((status = host_processor_sets (port_host_self,
+                                       &pset_list,
+                                       &pset_list_len)) != KERN_SUCCESS)
+       {
+               ERROR ("host_processor_sets failed: %s\n",
+                               mach_error_string (status));
+               pset_list = NULL;
+               pset_list_len = 0;
+               return (-1);
+       }
+/* #endif HAVE_THREAD_INFO */
+
+#elif KERNEL_LINUX
+       pagesize_g = sysconf(_SC_PAGESIZE);
+       DEBUG ("pagesize_g = %li; CONFIG_HZ = %i;",
+                       pagesize_g, CONFIG_HZ);
+/* #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) */
+
+#elif HAVE_PROCINFO_H
+       pagesize = getpagesize();
+#endif /* HAVE_PROCINFO_H */
+
+       return (0);
+} /* int ps_init */
+
+/* submit global state (e.g.: qty of zombies, running, etc..) */
+static void ps_submit_state (const char *state, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "ps_state", sizeof (vl.type));
+       sstrncpy (vl.type_instance, state, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+/* submit info about specific process (e.g.: memory taken, cpu usage, etc..) */
+static void ps_submit_proc_list (procstat_t *ps)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "processes", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
+
+       sstrncpy (vl.type, "ps_vm", sizeof (vl.type));
+       vl.values[0].gauge = ps->vmem_size;
+       vl.values_len = 1;
+       plugin_dispatch_values (&vl);
+
+       sstrncpy (vl.type, "ps_rss", sizeof (vl.type));
+       vl.values[0].gauge = ps->vmem_rss;
+       vl.values_len = 1;
+       plugin_dispatch_values (&vl);
+
+       sstrncpy (vl.type, "ps_data", sizeof (vl.type));
+       vl.values[0].gauge = ps->vmem_data;
+       vl.values_len = 1;
+       plugin_dispatch_values (&vl);
+
+       sstrncpy (vl.type, "ps_code", sizeof (vl.type));
+       vl.values[0].gauge = ps->vmem_code;
+       vl.values_len = 1;
+       plugin_dispatch_values (&vl);
+
+       sstrncpy (vl.type, "ps_stacksize", sizeof (vl.type));
+       vl.values[0].gauge = ps->stack_size;
+       vl.values_len = 1;
+       plugin_dispatch_values (&vl);
+
+       sstrncpy (vl.type, "ps_cputime", sizeof (vl.type));
+       vl.values[0].derive = ps->cpu_user_counter;
+       vl.values[1].derive = ps->cpu_system_counter;
+       vl.values_len = 2;
+       plugin_dispatch_values (&vl);
+
+       sstrncpy (vl.type, "ps_count", sizeof (vl.type));
+       vl.values[0].gauge = ps->num_proc;
+       vl.values[1].gauge = ps->num_lwp;
+       vl.values_len = 2;
+       plugin_dispatch_values (&vl);
+
+       sstrncpy (vl.type, "ps_pagefaults", sizeof (vl.type));
+       vl.values[0].derive = ps->vmem_minflt_counter;
+       vl.values[1].derive = ps->vmem_majflt_counter;
+       vl.values_len = 2;
+       plugin_dispatch_values (&vl);
+
+       if ( (ps->io_rchar != -1) && (ps->io_wchar != -1) )
+       {
+               sstrncpy (vl.type, "ps_disk_octets", sizeof (vl.type));
+               vl.values[0].derive = ps->io_rchar;
+               vl.values[1].derive = ps->io_wchar;
+               vl.values_len = 2;
+               plugin_dispatch_values (&vl);
+       }
+
+       if ( (ps->io_syscr != -1) && (ps->io_syscw != -1) )
+       {
+               sstrncpy (vl.type, "ps_disk_ops", sizeof (vl.type));
+               vl.values[0].derive = ps->io_syscr;
+               vl.values[1].derive = ps->io_syscw;
+               vl.values_len = 2;
+               plugin_dispatch_values (&vl);
+       }
+
+       DEBUG ("name = %s; num_proc = %lu; num_lwp = %lu; "
+                       "vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
+                       "vmem_code = %lu; "
+                       "vmem_minflt_counter = %"PRIi64"; vmem_majflt_counter = %"PRIi64"; "
+                       "cpu_user_counter = %"PRIi64"; cpu_system_counter = %"PRIi64"; "
+                       "io_rchar = %"PRIi64"; io_wchar = %"PRIi64"; "
+                       "io_syscr = %"PRIi64"; io_syscw = %"PRIi64";",
+                       ps->name, ps->num_proc, ps->num_lwp,
+                       ps->vmem_size, ps->vmem_rss,
+                       ps->vmem_data, ps->vmem_code,
+                       ps->vmem_minflt_counter, ps->vmem_majflt_counter,
+                       ps->cpu_user_counter, ps->cpu_system_counter,
+                       ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw);
+} /* void ps_submit_proc_list */
+
+#if KERNEL_LINUX || KERNEL_SOLARIS
+static void ps_submit_fork_rate (derive_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy(vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy(vl.plugin, "processes", sizeof (vl.plugin));
+       sstrncpy(vl.plugin_instance, "", sizeof (vl.plugin_instance));
+       sstrncpy(vl.type, "fork_rate", sizeof (vl.type));
+       sstrncpy(vl.type_instance, "", sizeof (vl.type_instance));
+
+       plugin_dispatch_values(&vl);
+}
+#endif /* KERNEL_LINUX || KERNEL_SOLARIS*/
+
+/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
+#if KERNEL_LINUX
+static int ps_read_tasks (int pid)
+{
+       char           dirname[64];
+       DIR           *dh;
+       struct dirent *ent;
+       int count = 0;
+
+       ssnprintf (dirname, sizeof (dirname), "/proc/%i/task", pid);
+
+       if ((dh = opendir (dirname)) == NULL)
+       {
+               DEBUG ("Failed to open directory `%s'", dirname);
+               return (-1);
+       }
+
+       while ((ent = readdir (dh)) != NULL)
+       {
+               if (!isdigit ((int) ent->d_name[0]))
+                       continue;
+               else
+                       count++;
+       }
+       closedir (dh);
+
+       return ((count >= 1) ? count : 1);
+} /* int *ps_read_tasks */
+
+/* Read advanced virtual memory data from /proc/pid/status */
+static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
+{
+       FILE *fh;
+       char buffer[1024];
+       char filename[64];
+       unsigned long long lib = 0;
+       unsigned long long exe = 0;
+       unsigned long long data = 0;
+       char *fields[8];
+       int numfields;
+
+       ssnprintf (filename, sizeof (filename), "/proc/%i/status", pid);
+       if ((fh = fopen (filename, "r")) == NULL)
+               return (NULL);
+
+       while (fgets (buffer, sizeof(buffer), fh) != NULL)
+       {
+               long long tmp;
+               char *endptr;
+
+               if (strncmp (buffer, "Vm", 2) != 0)
+                       continue;
+
+               numfields = strsplit (buffer, fields,
+                               STATIC_ARRAY_SIZE (fields));
+
+               if (numfields < 2)
+                       continue;
+
+               errno = 0;
+               endptr = NULL;
+               tmp = strtoll (fields[1], &endptr, /* base = */ 10);
+               if ((errno == 0) && (endptr != fields[1]))
+               {
+                       if (strncmp (buffer, "VmData", 6) == 0)
+                       {
+                               data = tmp;
+                       }
+                       else if (strncmp (buffer, "VmLib", 5) == 0)
+                       {
+                               lib = tmp;
+                       }
+                       else if  (strncmp(buffer, "VmExe", 5) == 0)
+                       {
+                               exe = tmp;
+                       }
+               }
+       } /* while (fgets) */
+
+       if (fclose (fh))
+       {
+               char errbuf[1024];
+               WARNING ("processes: fclose: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+
+       ps->vmem_data = data * 1024;
+       ps->vmem_code = (exe + lib) * 1024;
+
+       return (ps);
+} /* procstat_t *ps_read_vmem */
+
+static procstat_t *ps_read_io (int pid, procstat_t *ps)
+{
+       FILE *fh;
+       char buffer[1024];
+       char filename[64];
+
+       char *fields[8];
+       int numfields;
+
+       ssnprintf (filename, sizeof (filename), "/proc/%i/io", pid);
+       if ((fh = fopen (filename, "r")) == NULL)
+               return (NULL);
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               derive_t *val = NULL;
+               long long tmp;
+               char *endptr;
+
+               if (strncasecmp (buffer, "rchar:", 6) == 0)
+                       val = &(ps->io_rchar);
+               else if (strncasecmp (buffer, "wchar:", 6) == 0)
+                       val = &(ps->io_wchar);
+               else if (strncasecmp (buffer, "syscr:", 6) == 0)
+                       val = &(ps->io_syscr);
+               else if (strncasecmp (buffer, "syscw:", 6) == 0)
+                       val = &(ps->io_syscw);
+               else
+                       continue;
+
+               numfields = strsplit (buffer, fields,
+                               STATIC_ARRAY_SIZE (fields));
+
+               if (numfields < 2)
+                       continue;
+
+               errno = 0;
+               endptr = NULL;
+               tmp = strtoll (fields[1], &endptr, /* base = */ 10);
+               if ((errno != 0) || (endptr == fields[1]))
+                       *val = -1;
+               else
+                       *val = (derive_t) tmp;
+       } /* while (fgets) */
+
+       if (fclose (fh))
+       {
+               char errbuf[1024];
+               WARNING ("processes: fclose: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+
+       return (ps);
+} /* procstat_t *ps_read_io */
+
+int ps_read_process (int pid, procstat_t *ps, char *state)
+{
+       char  filename[64];
+       char  buffer[1024];
+
+       char *fields[64];
+       char  fields_len;
+
+       int   buffer_len;
+
+       char *buffer_ptr;
+       size_t name_start_pos;
+       size_t name_end_pos;
+       size_t name_len;
+
+       derive_t cpu_user_counter;
+       derive_t cpu_system_counter;
+       long long unsigned vmem_size;
+       long long unsigned vmem_rss;
+       long long unsigned stack_size;
+
+       memset (ps, 0, sizeof (procstat_t));
+
+       ssnprintf (filename, sizeof (filename), "/proc/%i/stat", pid);
+
+       buffer_len = read_file_contents (filename,
+                       buffer, sizeof(buffer) - 1);
+       if (buffer_len <= 0)
+               return (-1);
+       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
+        * else, use these to determine the process name. We don't use
+        * strchr(3) and strrchr(3) to avoid pointer arithmetic which would
+        * otherwise be required to determine name_len. */
+       name_start_pos = 0;
+       while ((buffer[name_start_pos] != '(')
+                       && (name_start_pos < buffer_len))
+               name_start_pos++;
+
+       name_end_pos = buffer_len;
+       while ((buffer[name_end_pos] != ')')
+                       && (name_end_pos > 0))
+               name_end_pos--;
+
+       /* Either '(' or ')' is not found or they are in the wrong order.
+        * Anyway, something weird that shouldn't happen ever. */
+       if (name_start_pos >= name_end_pos)
+       {
+               ERROR ("processes plugin: name_start_pos = %zu >= name_end_pos = %zu",
+                               name_start_pos, name_end_pos);
+               return (-1);
+       }
+
+       name_len = (name_end_pos - name_start_pos) - 1;
+       if (name_len >= sizeof (ps->name))
+               name_len = sizeof (ps->name) - 1;
+
+       sstrncpy (ps->name, &buffer[name_start_pos + 1], name_len + 1);
+
+       if ((buffer_len - name_end_pos) < 2)
+               return (-1);
+       buffer_ptr = &buffer[name_end_pos + 2];
+
+       fields_len = strsplit (buffer_ptr, fields, STATIC_ARRAY_SIZE (fields));
+       if (fields_len < 22)
+       {
+               DEBUG ("processes plugin: ps_read_process (pid = %i):"
+                               " `%s' has only %i fields..",
+                               (int) pid, filename, fields_len);
+               return (-1);
+       }
+
+       *state = fields[0][0];
+
+       if (*state == 'Z')
+       {
+               ps->num_lwp  = 0;
+               ps->num_proc = 0;
+       }
+       else
+       {
+               if ( (ps->num_lwp = ps_read_tasks (pid)) == -1 )
+               {
+                       /* returns -1 => kernel 2.4 */
+                       ps->num_lwp = 1;
+               }
+               ps->num_proc = 1;
+       }
+
+       /* Leave the rest at zero if this is only a zombi */
+       if (ps->num_proc == 0)
+       {
+               DEBUG ("processes plugin: This is only a zombi: pid = %i; "
+                               "name = %s;", pid, ps->name);
+               return (0);
+       }
+
+       cpu_user_counter   = atoll (fields[11]);
+       cpu_system_counter = atoll (fields[12]);
+       vmem_size          = atoll (fields[20]);
+       vmem_rss           = atoll (fields[21]);
+       ps->vmem_minflt_counter = atol (fields[7]);
+       ps->vmem_majflt_counter = atol (fields[9]);
+
+       {
+               unsigned long long stack_start = atoll (fields[25]);
+               unsigned long long stack_ptr   = atoll (fields[26]);
+
+               stack_size = (stack_start > stack_ptr)
+                       ? stack_start - stack_ptr
+                       : stack_ptr - stack_start;
+       }
+
+       /* Convert jiffies to useconds */
+       cpu_user_counter   = cpu_user_counter   * 1000000 / CONFIG_HZ;
+       cpu_system_counter = cpu_system_counter * 1000000 / CONFIG_HZ;
+       vmem_rss = vmem_rss * pagesize_g;
+
+       if ( (ps_read_vmem(pid, ps)) == NULL)
+       {
+               /* No VMem data */
+               ps->vmem_data = -1;
+               ps->vmem_code = -1;
+               DEBUG("ps_read_process: did not get vmem data for pid %i",pid);
+       }
+
+       ps->cpu_user_counter = cpu_user_counter;
+       ps->cpu_system_counter = cpu_system_counter;
+       ps->vmem_size = (unsigned long) vmem_size;
+       ps->vmem_rss = (unsigned long) vmem_rss;
+       ps->stack_size = (unsigned long) stack_size;
+
+       if ( (ps_read_io (pid, ps)) == NULL)
+       {
+               /* no io data */
+               ps->io_rchar = -1;
+               ps->io_wchar = -1;
+               ps->io_syscr = -1;
+               ps->io_syscw = -1;
+
+               DEBUG("ps_read_process: not get io data for pid %i",pid);
+       }
+
+       /* success */
+       return (0);
+} /* int ps_read_process (...) */
+
+static char *ps_get_cmdline (pid_t pid, char *name, char *buf, size_t buf_len)
+{
+       char  *buf_ptr;
+       size_t len;
+
+       char file[PATH_MAX];
+       int  fd;
+
+       size_t n;
+
+       if ((pid < 1) || (NULL == buf) || (buf_len < 2))
+               return NULL;
+
+       ssnprintf (file, sizeof (file), "/proc/%u/cmdline",
+                       (unsigned int) pid);
+
+       errno = 0;
+       fd = open (file, O_RDONLY);
+       if (fd < 0) {
+               char errbuf[4096];
+               /* ENOENT means the process exited while we were handling it.
+                * Don't complain about this, it only fills the logs. */
+               if (errno != ENOENT)
+                       WARNING ("processes plugin: Failed to open `%s': %s.", file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return NULL;
+       }
+
+       buf_ptr = buf;
+       len     = buf_len;
+
+       n = 0;
+
+       while (42) {
+               ssize_t status;
+
+               status = read (fd, (void *)buf_ptr, len);
+
+               if (status < 0) {
+                       char errbuf[1024];
+
+                       if ((EAGAIN == errno) || (EINTR == errno))
+                               continue;
+
+                       WARNING ("processes plugin: Failed to read from `%s': %s.", file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (fd);
+                       return NULL;
+               }
+
+               n += status;
+
+               if (status == 0)
+                       break;
+
+               buf_ptr += status;
+               len     -= status;
+
+               if (len <= 0)
+                       break;
+       }
+
+       close (fd);
+
+       if (0 == n) {
+               /* cmdline not available; e.g. kernel thread, zombie */
+               if (NULL == name)
+                       return NULL;
+
+               ssnprintf (buf, buf_len, "[%s]", name);
+               return buf;
+       }
+
+       assert (n <= buf_len);
+
+       if (n == buf_len)
+               --n;
+       buf[n] = '\0';
+
+       --n;
+       /* remove trailing whitespace */
+       while ((n > 0) && (isspace (buf[n]) || ('\0' == buf[n]))) {
+               buf[n] = '\0';
+               --n;
+       }
+
+       /* arguments are separated by '\0' in /proc/<pid>/cmdline */
+       while (n > 0) {
+               if ('\0' == buf[n])
+                       buf[n] = ' ';
+               --n;
+       }
+       return buf;
+} /* char *ps_get_cmdline (...) */
+
+static int read_fork_rate ()
+{
+       FILE *proc_stat;
+       char buffer[1024];
+       value_t value;
+       _Bool value_valid = 0;
+
+       proc_stat = fopen ("/proc/stat", "r");
+       if (proc_stat == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("processes plugin: fopen (/proc/stat) failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buffer, sizeof (buffer), proc_stat) != NULL)
+       {
+               int status;
+               char *fields[3];
+               int fields_num;
+
+               fields_num = strsplit (buffer, fields,
+                               STATIC_ARRAY_SIZE (fields));
+               if (fields_num != 2)
+                       continue;
+
+               if (strcmp ("processes", fields[0]) != 0)
+                       continue;
+
+               status = parse_value (fields[1], &value, DS_TYPE_DERIVE);
+               if (status == 0)
+                       value_valid = 1;
+
+               break;
+       }
+       fclose(proc_stat);
+
+       if (!value_valid)
+               return (-1);
+
+       ps_submit_fork_rate (value.derive);
+       return (0);
+}
+#endif /*KERNEL_LINUX */
+
+#if KERNEL_SOLARIS
+static const char *ps_get_cmdline (long pid, /* {{{ */
+               char *buffer, size_t buffer_size)
+{
+       char path[PATH_MAX];
+       psinfo_t info;
+       int status;
+
+       snprintf(path, sizeof (path), "/proc/%li/psinfo", pid);
+
+       status = read_file_contents (path, (void *) &info, sizeof (info));
+       if (status != sizeof (info))
+       {
+               ERROR ("processes plugin: Unexpected return value "
+                               "while reading \"%s\": "
+                               "Returned %i but expected %zu.",
+                               path, status, buffer_size);
+               return (NULL);
+       }
+
+       info.pr_psargs[sizeof (info.pr_psargs) - 1] = 0;
+       sstrncpy (buffer, info.pr_psargs, buffer_size);
+
+       return (buffer);
+} /* }}} int ps_get_cmdline */
+
+/*
+ * Reads process information on the Solaris OS. The information comes mainly from
+ * /proc/PID/status, /proc/PID/psinfo and /proc/PID/usage
+ * The values for input and ouput chars are calculated "by hand"
+ * Added a few "solaris" specific process states as well
+ */
+static int ps_read_process(long pid, procstat_t *ps, char *state)
+{
+       char filename[64];
+       char f_psinfo[64], f_usage[64];
+       char *buffer;
+
+       pstatus_t *myStatus;
+       psinfo_t *myInfo;
+       prusage_t *myUsage;
+
+       snprintf(filename, sizeof (filename), "/proc/%li/status", pid);
+       snprintf(f_psinfo, sizeof (f_psinfo), "/proc/%li/psinfo", pid);
+       snprintf(f_usage, sizeof (f_usage), "/proc/%li/usage", pid);
+
+
+       buffer = malloc(sizeof (pstatus_t));
+       memset(buffer, 0, sizeof (pstatus_t));
+       read_file_contents(filename, buffer, sizeof (pstatus_t));
+       myStatus = (pstatus_t *) buffer;
+
+       buffer = malloc(sizeof (psinfo_t));
+       memset(buffer, 0, sizeof(psinfo_t));
+       read_file_contents(f_psinfo, buffer, sizeof (psinfo_t));
+       myInfo = (psinfo_t *) buffer;
+
+       buffer = malloc(sizeof (prusage_t));
+       memset(buffer, 0, sizeof(prusage_t));
+       read_file_contents(f_usage, buffer, sizeof (prusage_t));
+       myUsage = (prusage_t *) buffer;
+
+       sstrncpy(ps->name, myInfo->pr_fname, sizeof (myInfo->pr_fname));
+       ps->num_lwp = myStatus->pr_nlwp;
+       if (myInfo->pr_wstat != 0) {
+               ps->num_proc = 0;
+               ps->num_lwp = 0;
+               *state = (char) 'Z';
+               return (0);
+       } else {
+               ps->num_proc = 1;
+               ps->num_lwp = myInfo->pr_nlwp;
+       }
+
+       /*
+        * Convert system time and user time from nanoseconds to microseconds
+        * for compatibility with the linux module
+        */
+       ps->cpu_system_counter = myStatus -> pr_stime.tv_nsec / 1000;
+       ps->cpu_user_counter = myStatus -> pr_utime.tv_nsec / 1000;
+
+       /*
+        * Convert rssize from KB to bytes to be consistent w/ the linux module
+        */
+       ps->vmem_rss = myInfo->pr_rssize * 1024;
+       ps->vmem_size = myInfo->pr_size * 1024;
+       ps->vmem_minflt_counter = myUsage->pr_minf;
+       ps->vmem_majflt_counter = myUsage->pr_majf;
+
+       /*
+        * TODO: Data and code segment calculations for Solaris
+        */
+
+       ps->vmem_data = -1;
+       ps->vmem_code = -1;
+       ps->stack_size = myStatus->pr_stksize;
+
+       /*
+        * Calculating input/ouput chars
+        * Formula used is total chars / total blocks => chars/block
+        * then convert input/output blocks to chars
+        */
+       ulong_t tot_chars = myUsage->pr_ioch;
+       ulong_t tot_blocks = myUsage->pr_inblk + myUsage->pr_oublk;
+       ulong_t chars_per_block = 1;
+       if (tot_blocks != 0)
+               chars_per_block = tot_chars / tot_blocks;
+       ps->io_rchar = myUsage->pr_inblk * chars_per_block;
+       ps->io_wchar = myUsage->pr_oublk * chars_per_block;
+       ps->io_syscr = myUsage->pr_sysc;
+       ps->io_syscw = myUsage->pr_sysc;
+
+
+       /*
+        * TODO: Find way of setting BLOCKED and PAGING status
+        */
+
+       *state = (char) 'R';
+       if (myStatus->pr_flags & PR_ASLEEP)
+               *state = (char) 'S';
+       else if (myStatus->pr_flags & PR_STOPPED)
+               *state = (char) 'T';
+       else if (myStatus->pr_flags & PR_DETACH)
+               *state = (char) 'E';
+       else if (myStatus->pr_flags & PR_DAEMON)
+               *state = (char) 'A';
+       else if (myStatus->pr_flags & PR_ISSYS)
+               *state = (char) 'Y';
+       else if (myStatus->pr_flags & PR_ORPHAN)
+               *state = (char) 'O';
+
+       sfree(myStatus);
+       sfree(myInfo);
+       sfree(myUsage);
+
+       return (0);
+}
+
+/*
+ * Reads the number of threads created since the last reboot. On Solaris these
+ * are retrieved from kstat (module cpu, name sys, class misc, stat nthreads).
+ * The result is the sum for all the threads created on each cpu
+ */
+static int read_fork_rate()
+{
+       extern kstat_ctl_t *kc;
+       kstat_t *ksp_chain = NULL;
+       derive_t result = 0;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (ksp_chain = kc->kc_chain;
+                       ksp_chain != NULL;
+                       ksp_chain = ksp_chain->ks_next)
+       {
+               if ((strcmp (ksp_chain->ks_module, "cpu") == 0)
+                               && (strcmp (ksp_chain->ks_name, "sys") == 0)
+                               && (strcmp (ksp_chain->ks_class, "misc") == 0))
+               {
+                       long long tmp;
+
+                       kstat_read (kc, ksp_chain, NULL);
+
+                       tmp = get_kstat_value(ksp_chain, "nthreads");
+                       if (tmp != -1LL)
+                               result += tmp;
+               }
+       }
+
+       ps_submit_fork_rate (result);
+       return (0);
+}
+#endif /* KERNEL_SOLARIS */
+
+#if HAVE_THREAD_INFO
+static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_len)
+{
+       int mib[4];
+
+       struct kinfo_proc kp;
+       size_t            kp_size;
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROC;
+       mib[2] = KERN_PROC_PID;
+
+       if (pid_for_task (t, pid) != KERN_SUCCESS)
+               return (-1);
+       mib[3] = *pid;
+
+       kp_size = sizeof (kp);
+       if (sysctl (mib, 4, &kp, &kp_size, NULL, 0) != 0)
+               return (-1);
+
+       if (name_max_len > (MAXCOMLEN + 1))
+               name_max_len = MAXCOMLEN + 1;
+
+       strncpy (name, kp.kp_proc.p_comm, name_max_len - 1);
+       name[name_max_len - 1] = '\0';
+
+       DEBUG ("pid = %i; name = %s;", *pid, name);
+
+       /* We don't do the special handling for `p_comm == "LaunchCFMApp"' as
+        * `top' does it, because it is a lot of work and only used when
+        * debugging. -octo */
+
+       return (0);
+}
+#endif /* HAVE_THREAD_INFO */
+/* ------- end of additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
+
+/* do actual readings from kernel */
+static int ps_read (void)
+{
+#if HAVE_THREAD_INFO
+       kern_return_t            status;
+
+       int                      pset;
+       processor_set_t          port_pset_priv;
+
+       int                      task;
+       task_array_t             task_list;
+       mach_msg_type_number_t   task_list_len;
+
+       int                      task_pid;
+       char                     task_name[MAXCOMLEN + 1];
+
+       int                      thread;
+       thread_act_array_t       thread_list;
+       mach_msg_type_number_t   thread_list_len;
+       thread_basic_info_data_t thread_data;
+       mach_msg_type_number_t   thread_data_len;
+
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int blocked  = 0;
+
+       procstat_t *ps;
+       procstat_entry_t pse;
+
+       ps_list_reset ();
+
+       /*
+        * The Mach-concept is a little different from the traditional UNIX
+        * concept: All the work is done in threads. Threads are contained in
+        * `tasks'. Therefore, `task status' doesn't make much sense, since
+        * it's actually a `thread status'.
+        * Tasks are assigned to sets of processors, so that's where you go to
+        * get a list.
+        */
+       for (pset = 0; pset < pset_list_len; pset++)
+       {
+               if ((status = host_processor_set_priv (port_host_self,
+                                               pset_list[pset],
+                                               &port_pset_priv)) != KERN_SUCCESS)
+               {
+                       ERROR ("host_processor_set_priv failed: %s\n",
+                                       mach_error_string (status));
+                       continue;
+               }
+
+               if ((status = processor_set_tasks (port_pset_priv,
+                                               &task_list,
+                                               &task_list_len)) != KERN_SUCCESS)
+               {
+                       ERROR ("processor_set_tasks failed: %s\n",
+                                       mach_error_string (status));
+                       mach_port_deallocate (port_task_self, port_pset_priv);
+                       continue;
+               }
+
+               for (task = 0; task < task_list_len; task++)
+               {
+                       ps = NULL;
+                       if (mach_get_task_name (task_list[task],
+                                               &task_pid,
+                                               task_name, PROCSTAT_NAME_LEN) == 0)
+                       {
+                               /* search for at least one match */
+                               for (ps = list_head_g; ps != NULL; ps = ps->next)
+                                       /* FIXME: cmdline should be here instead of NULL */
+                                       if (ps_list_match (task_name, NULL, ps) == 1)
+                                               break;
+                       }
+
+                       /* Collect more detailed statistics for this process */
+                       if (ps != NULL)
+                       {
+                               task_basic_info_data_t        task_basic_info;
+                               mach_msg_type_number_t        task_basic_info_len;
+                               task_events_info_data_t       task_events_info;
+                               mach_msg_type_number_t        task_events_info_len;
+                               task_absolutetime_info_data_t task_absolutetime_info;
+                               mach_msg_type_number_t        task_absolutetime_info_len;
+
+                               memset (&pse, '\0', sizeof (pse));
+                               pse.id = task_pid;
+
+                               task_basic_info_len = TASK_BASIC_INFO_COUNT;
+                               status = task_info (task_list[task],
+                                               TASK_BASIC_INFO,
+                                               (task_info_t) &task_basic_info,
+                                               &task_basic_info_len);
+                               if (status != KERN_SUCCESS)
+                               {
+                                       ERROR ("task_info failed: %s",
+                                                       mach_error_string (status));
+                                       continue; /* with next thread_list */
+                               }
+
+                               task_events_info_len = TASK_EVENTS_INFO_COUNT;
+                               status = task_info (task_list[task],
+                                               TASK_EVENTS_INFO,
+                                               (task_info_t) &task_events_info,
+                                               &task_events_info_len);
+                               if (status != KERN_SUCCESS)
+                               {
+                                       ERROR ("task_info failed: %s",
+                                                       mach_error_string (status));
+                                       continue; /* with next thread_list */
+                               }
+
+                               task_absolutetime_info_len = TASK_ABSOLUTETIME_INFO_COUNT;
+                               status = task_info (task_list[task],
+                                               TASK_ABSOLUTETIME_INFO,
+                                               (task_info_t) &task_absolutetime_info,
+                                               &task_absolutetime_info_len);
+                               if (status != KERN_SUCCESS)
+                               {
+                                       ERROR ("task_info failed: %s",
+                                                       mach_error_string (status));
+                                       continue; /* with next thread_list */
+                               }
+
+                               pse.num_proc++;
+                               pse.vmem_size = task_basic_info.virtual_size;
+                               pse.vmem_rss = task_basic_info.resident_size;
+                               /* Does not seem to be easily exposed */
+                               pse.vmem_data = 0;
+                               pse.vmem_code = 0;
+
+                               pse.vmem_minflt_counter = task_events_info.cow_faults;
+                               pse.vmem_majflt_counter = task_events_info.faults;
+
+                               pse.cpu_user_counter = task_absolutetime_info.total_user;
+                               pse.cpu_system_counter = task_absolutetime_info.total_system;
+                       }
+
+                       status = task_threads (task_list[task], &thread_list,
+                                       &thread_list_len);
+                       if (status != KERN_SUCCESS)
+                       {
+                               /* Apple's `top' treats this case a zombie. It
+                                * makes sense to some extend: A `zombie'
+                                * thread is nonsense, since the task/process
+                                * is dead. */
+                               zombies++;
+                               DEBUG ("task_threads failed: %s",
+                                               mach_error_string (status));
+                               if (task_list[task] != port_task_self)
+                                       mach_port_deallocate (port_task_self,
+                                                       task_list[task]);
+                               continue; /* with next task_list */
+                       }
+
+                       for (thread = 0; thread < thread_list_len; thread++)
+                       {
+                               thread_data_len = THREAD_BASIC_INFO_COUNT;
+                               status = thread_info (thread_list[thread],
+                                               THREAD_BASIC_INFO,
+                                               (thread_info_t) &thread_data,
+                                               &thread_data_len);
+                               if (status != KERN_SUCCESS)
+                               {
+                                       ERROR ("thread_info failed: %s",
+                                                       mach_error_string (status));
+                                       if (task_list[task] != port_task_self)
+                                               mach_port_deallocate (port_task_self,
+                                                               thread_list[thread]);
+                                       continue; /* with next thread_list */
+                               }
+
+                               if (ps != NULL)
+                                       pse.num_lwp++;
+
+                               switch (thread_data.run_state)
+                               {
+                                       case TH_STATE_RUNNING:
+                                               running++;
+                                               break;
+                                       case TH_STATE_STOPPED:
+                                       /* What exactly is `halted'? */
+                                       case TH_STATE_HALTED:
+                                               stopped++;
+                                               break;
+                                       case TH_STATE_WAITING:
+                                               sleeping++;
+                                               break;
+                                       case TH_STATE_UNINTERRUPTIBLE:
+                                               blocked++;
+                                               break;
+                                       /* There is no `zombie' case here,
+                                        * since there are no zombie-threads.
+                                        * There's only zombie tasks, which are
+                                        * handled above. */
+                                       default:
+                                               WARNING ("Unknown thread status: %i",
+                                                               thread_data.run_state);
+                                               break;
+                               } /* switch (thread_data.run_state) */
+
+                               if (task_list[task] != port_task_self)
+                               {
+                                       status = mach_port_deallocate (port_task_self,
+                                                       thread_list[thread]);
+                                       if (status != KERN_SUCCESS)
+                                               ERROR ("mach_port_deallocate failed: %s",
+                                                               mach_error_string (status));
+                               }
+                       } /* for (thread_list) */
+
+                       if ((status = vm_deallocate (port_task_self,
+                                                       (vm_address_t) thread_list,
+                                                       thread_list_len * sizeof (thread_act_t)))
+                                       != KERN_SUCCESS)
+                       {
+                               ERROR ("vm_deallocate failed: %s",
+                                               mach_error_string (status));
+                       }
+                       thread_list = NULL;
+                       thread_list_len = 0;
+
+                       /* Only deallocate the task port, if it isn't our own.
+                        * Don't know what would happen in that case, but this
+                        * is what Apple's top does.. ;) */
+                       if (task_list[task] != port_task_self)
+                       {
+                               status = mach_port_deallocate (port_task_self,
+                                               task_list[task]);
+                               if (status != KERN_SUCCESS)
+                                       ERROR ("mach_port_deallocate failed: %s",
+                                                       mach_error_string (status));
+                       }
+
+                       if (ps != NULL)
+                               /* FIXME: cmdline should be here instead of NULL */
+                               ps_list_add (task_name, NULL, &pse);
+               } /* for (task_list) */
+
+               if ((status = vm_deallocate (port_task_self,
+                               (vm_address_t) task_list,
+                               task_list_len * sizeof (task_t))) != KERN_SUCCESS)
+               {
+                       ERROR ("vm_deallocate failed: %s",
+                                       mach_error_string (status));
+               }
+               task_list = NULL;
+               task_list_len = 0;
+
+               if ((status = mach_port_deallocate (port_task_self, port_pset_priv))
+                               != KERN_SUCCESS)
+               {
+                       ERROR ("mach_port_deallocate failed: %s",
+                                       mach_error_string (status));
+               }
+       } /* for (pset_list) */
+
+       ps_submit_state ("running", running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies", zombies);
+       ps_submit_state ("stopped", stopped);
+       ps_submit_state ("blocked", blocked);
+
+       for (ps = list_head_g; ps != NULL; ps = ps->next)
+               ps_submit_proc_list (ps);
+/* #endif HAVE_THREAD_INFO */
+
+#elif KERNEL_LINUX
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int paging   = 0;
+       int blocked  = 0;
+
+       struct dirent *ent;
+       DIR           *proc;
+       int            pid;
+
+       char cmdline[CMDLINE_BUFFER_SIZE];
+
+       int        status;
+       procstat_t ps;
+       procstat_entry_t pse;
+       char       state;
+
+       procstat_t *ps_ptr;
+
+       running = sleeping = zombies = stopped = paging = blocked = 0;
+       ps_list_reset ();
+
+       if ((proc = opendir ("/proc")) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("Cannot open `/proc': %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while ((ent = readdir (proc)) != NULL)
+       {
+               if (!isdigit (ent->d_name[0]))
+                       continue;
+
+               if ((pid = atoi (ent->d_name)) < 1)
+                       continue;
+
+               status = ps_read_process (pid, &ps, &state);
+               if (status != 0)
+               {
+                       DEBUG ("ps_read_process failed: %i", status);
+                       continue;
+               }
+
+               pse.id       = pid;
+               pse.age      = 0;
+
+               pse.num_proc   = ps.num_proc;
+               pse.num_lwp    = ps.num_lwp;
+               pse.vmem_size  = ps.vmem_size;
+               pse.vmem_rss   = ps.vmem_rss;
+               pse.vmem_data  = ps.vmem_data;
+               pse.vmem_code  = ps.vmem_code;
+               pse.stack_size = ps.stack_size;
+
+               pse.vmem_minflt = 0;
+               pse.vmem_minflt_counter = ps.vmem_minflt_counter;
+               pse.vmem_majflt = 0;
+               pse.vmem_majflt_counter = ps.vmem_majflt_counter;
+
+               pse.cpu_user = 0;
+               pse.cpu_user_counter = ps.cpu_user_counter;
+               pse.cpu_system = 0;
+               pse.cpu_system_counter = ps.cpu_system_counter;
+
+               pse.io_rchar = ps.io_rchar;
+               pse.io_wchar = ps.io_wchar;
+               pse.io_syscr = ps.io_syscr;
+               pse.io_syscw = ps.io_syscw;
+
+               switch (state)
+               {
+                       case 'R': running++;  break;
+                       case 'S': sleeping++; break;
+                       case 'D': blocked++;  break;
+                       case 'Z': zombies++;  break;
+                       case 'T': stopped++;  break;
+                       case 'W': paging++;   break;
+               }
+
+               ps_list_add (ps.name,
+                               ps_get_cmdline (pid, ps.name, cmdline, sizeof (cmdline)),
+                               &pse);
+       }
+
+       closedir (proc);
+
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("paging",   paging);
+       ps_submit_state ("blocked",  blocked);
+
+       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+               ps_submit_proc_list (ps_ptr);
+
+       read_fork_rate();
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int blocked  = 0;
+       int idle     = 0;
+       int wait     = 0;
+
+       kvm_t *kd;
+       char errbuf[_POSIX2_LINE_MAX];
+       struct kinfo_proc *procs;          /* array of processes */
+       struct kinfo_proc *proc_ptr = NULL;
+       int count;                         /* returns number of processes */
+       int i;
+
+       procstat_t *ps_ptr;
+       procstat_entry_t pse;
+
+       ps_list_reset ();
+
+       /* Open the kvm interface, get a descriptor */
+       kd = kvm_openfiles (NULL, "/dev/null", NULL, 0, errbuf);
+       if (kd == NULL)
+       {
+               ERROR ("processes plugin: Cannot open kvm interface: %s",
+                               errbuf);
+               return (0);
+       }
+
+       /* Get the list of processes. */
+       procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count);
+       if (procs == NULL)
+       {
+               ERROR ("processes plugin: Cannot get kvm processes list: %s",
+                               kvm_geterr(kd));
+               kvm_close (kd);
+               return (0);
+       }
+
+       /* Iterate through the processes in kinfo_proc */
+       for (i = 0; i < count; i++)
+       {
+               /* Create only one process list entry per _process_, i.e.
+                * filter out threads (duplicate PID entries). */
+               if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid))
+               {
+                       char cmdline[CMDLINE_BUFFER_SIZE] = "";
+                       _Bool have_cmdline = 0;
+
+                       proc_ptr = &(procs[i]);
+                       /* Don't probe system processes and processes without arguments */
+                       if (((procs[i].ki_flag & P_SYSTEM) == 0)
+                                       && (procs[i].ki_args != NULL))
+                       {
+                               char **argv;
+                               int argc;
+                               int status;
+
+                               /* retrieve the arguments */
+                               argv = kvm_getargv (kd, proc_ptr, /* nchr = */ 0);
+                               argc = 0;
+                               if ((argv != NULL) && (argv[0] != NULL))
+                               {
+                                       while (argv[argc] != NULL)
+                                               argc++;
+
+                                       status = strjoin (cmdline, sizeof (cmdline), argv, argc, " ");
+                                       if (status < 0)
+                                               WARNING ("processes plugin: Command line did not fit into buffer.");
+                                       else
+                                               have_cmdline = 1;
+                               }
+                       } /* if (process has argument list) */
+
+                       pse.id       = procs[i].ki_pid;
+                       pse.age      = 0;
+
+                       pse.num_proc = 1;
+                       pse.num_lwp  = procs[i].ki_numthreads;
+
+                       pse.vmem_size = procs[i].ki_size;
+                       pse.vmem_rss = procs[i].ki_rssize * pagesize;
+                       pse.vmem_data = procs[i].ki_dsize * pagesize;
+                       pse.vmem_code = procs[i].ki_tsize * pagesize;
+                       pse.stack_size = procs[i].ki_ssize * pagesize;
+                       pse.vmem_minflt = 0;
+                       pse.vmem_minflt_counter = procs[i].ki_rusage.ru_minflt;
+                       pse.vmem_majflt = 0;
+                       pse.vmem_majflt_counter = procs[i].ki_rusage.ru_majflt;
+
+                       pse.cpu_user = 0;
+                       pse.cpu_system = 0;
+                       pse.cpu_user_counter = 0;
+                       pse.cpu_system_counter = 0;
+                       /*
+                        * The u-area might be swapped out, and we can't get
+                        * at it because we have a crashdump and no swap.
+                        * If it's here fill in these fields, otherwise, just
+                        * leave them 0.
+                        */
+                       if (procs[i].ki_flag & P_INMEM)
+                       {
+                               pse.cpu_user_counter = procs[i].ki_rusage.ru_utime.tv_usec
+                                       + (1000000lu * procs[i].ki_rusage.ru_utime.tv_sec);
+                               pse.cpu_system_counter = procs[i].ki_rusage.ru_stime.tv_usec
+                                       + (1000000lu * procs[i].ki_rusage.ru_stime.tv_sec);
+                       }
+
+                       /* no I/O data */
+                       pse.io_rchar = -1;
+                       pse.io_wchar = -1;
+                       pse.io_syscr = -1;
+                       pse.io_syscw = -1;
+
+                       ps_list_add (procs[i].ki_comm, have_cmdline ? cmdline : NULL, &pse);
+               } /* if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid)) */
+
+               switch (procs[i].ki_stat)
+               {
+                       case SSTOP:     stopped++;      break;
+                       case SSLEEP:    sleeping++;     break;
+                       case SRUN:      running++;      break;
+                       case SIDL:      idle++;         break;
+                       case SWAIT:     wait++;         break;
+                       case SLOCK:     blocked++;      break;
+                       case SZOMB:     zombies++;      break;
+               }
+       }
+
+       kvm_close(kd);
+
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("blocked",  blocked);
+       ps_submit_state ("idle",     idle);
+       ps_submit_state ("wait",     wait);
+
+       for (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 */
+
+#elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int onproc   = 0;
+       int idle     = 0;
+       int dead     = 0;
+
+       kvm_t *kd;
+       char errbuf[1024];
+       struct kinfo_proc *procs;          /* array of processes */
+       struct kinfo_proc *proc_ptr = NULL;
+       int count;                         /* returns number of processes */
+       int i;
+
+       procstat_t *ps_ptr;
+       procstat_entry_t pse;
+
+       ps_list_reset ();
+
+       /* Open the kvm interface, get a descriptor */
+       kd = kvm_open (NULL, NULL, NULL, 0, errbuf);
+       if (kd == NULL)
+       {
+               ERROR ("processes plugin: Cannot open kvm interface: %s",
+                               errbuf);
+               return (0);
+       }
+
+       /* Get the list of processes. */
+       procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count);
+       if (procs == NULL)
+       {
+               ERROR ("processes plugin: Cannot get kvm processes list: %s",
+                               kvm_geterr(kd));
+               kvm_close (kd);
+               return (0);
+       }
+
+       /* Iterate through the processes in kinfo_proc */
+       for (i = 0; i < count; i++)
+       {
+               /* Create only one process list entry per _process_, i.e.
+                * filter out threads (duplicate PID entries). */
+               if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid))
+               {
+                       char cmdline[CMDLINE_BUFFER_SIZE] = "";
+                       _Bool have_cmdline = 0;
+
+                       proc_ptr = &(procs[i]);
+                       /* Don't probe zombie processes  */
+                       if (!P_ZOMBIE(proc_ptr))
+                       {
+                               char **argv;
+                               int argc;
+                               int status;
+
+                               /* retrieve the arguments */
+                               argv = kvm_getargv (kd, proc_ptr, /* nchr = */ 0);
+                               argc = 0;
+                               if ((argv != NULL) && (argv[0] != NULL))
+                               {
+                                       while (argv[argc] != NULL)
+                                               argc++;
+
+                                       status = strjoin (cmdline, sizeof (cmdline), argv, argc, " ");
+                                       if (status < 0)
+                                               WARNING ("processes plugin: Command line did not fit into buffer.");
+                                       else
+                                               have_cmdline = 1;
+                               }
+                       } /* if (process has argument list) */
+
+                       pse.id       = procs[i].p_pid;
+                       pse.age      = 0;
+
+                       pse.num_proc = 1;
+                       pse.num_lwp  = 1; /* XXX: accumulate p_tid values for a single p_pid ? */
+
+                       pse.vmem_rss = procs[i].p_vm_rssize * pagesize;
+                       pse.vmem_data = procs[i].p_vm_dsize * pagesize;
+                       pse.vmem_code = procs[i].p_vm_tsize * pagesize;
+                       pse.stack_size = procs[i].p_vm_ssize * pagesize;
+                       pse.vmem_size = pse.stack_size + pse.vmem_code + pse.vmem_data;
+                       pse.vmem_minflt = 0;
+                       pse.vmem_minflt_counter = procs[i].p_uru_minflt;
+                       pse.vmem_majflt = 0;
+                       pse.vmem_majflt_counter = procs[i].p_uru_majflt;
+
+                       pse.cpu_user = 0;
+                       pse.cpu_system = 0;
+                       pse.cpu_user_counter = procs[i].p_uutime_usec +
+                                               (1000000lu * procs[i].p_uutime_sec);
+                       pse.cpu_system_counter = procs[i].p_ustime_usec +
+                                               (1000000lu * procs[i].p_ustime_sec);
+
+                       /* no I/O data */
+                       pse.io_rchar = -1;
+                       pse.io_wchar = -1;
+                       pse.io_syscr = -1;
+                       pse.io_syscw = -1;
+
+                       ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
+               } /* if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid)) */
+
+               switch (procs[i].p_stat)
+               {
+                       case SSTOP:     stopped++;      break;
+                       case SSLEEP:    sleeping++;     break;
+                       case SRUN:      running++;      break;
+                       case SIDL:      idle++;         break;
+                       case SONPROC:   onproc++;       break;
+                       case SDEAD:     dead++;         break;
+                       case SZOMB:     zombies++;      break;
+               }
+       }
+
+       kvm_close(kd);
+
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("onproc",   onproc);
+       ps_submit_state ("idle",     idle);
+       ps_submit_state ("dead",     dead);
+
+       for (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 */
+
+#elif HAVE_PROCINFO_H
+       /* AIX */
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int paging   = 0;
+       int blocked  = 0;
+
+       pid_t pindex = 0;
+       int nprocs;
+
+       procstat_t *ps;
+       procstat_entry_t pse;
+
+       ps_list_reset ();
+       while ((nprocs = getprocs64 (procentry, sizeof(struct procentry64),
+                                       /* fdsinfo = */ NULL, sizeof(struct fdsinfo64),
+                                       &pindex, MAXPROCENTRY)) > 0)
+       {
+               int i;
+
+               for (i = 0; i < nprocs; i++)
+               {
+                       tid64_t thindex;
+                       int nthreads;
+                       char arglist[MAXARGLN+1];
+                       char *cargs;
+                       char *cmdline;
+
+                       if (procentry[i].pi_state == SNONE) continue;
+                       /* if (procentry[i].pi_state == SZOMB)  FIXME */
+
+                       cmdline = procentry[i].pi_comm;
+                       cargs = procentry[i].pi_comm;
+                       if ( procentry[i].pi_flags & SKPROC )
+                       {
+                               if (procentry[i].pi_pid == 0)
+                                       cmdline = "swapper";
+                               cargs = cmdline;
+                       }
+                       else
+                       {
+                               if (getargs(&procentry[i], sizeof(struct procentry64), arglist, MAXARGLN) >= 0)
+                               {
+                                       int n;
+
+                                       n = -1;
+                                       while (++n < MAXARGLN)
+                                       {
+                                               if (arglist[n] == '\0')
+                                               {
+                                                       if (arglist[n+1] == '\0')
+                                                               break;
+                                                       arglist[n] = ' ';
+                                               }
+                                       }
+                                       cargs = arglist;
+                               }
+                       }
+
+                       pse.id       = procentry[i].pi_pid;
+                       pse.age      = 0;
+                       pse.num_lwp  = procentry[i].pi_thcount;
+                       pse.num_proc = 1;
+
+                       thindex=0;
+                       while ((nthreads = getthrds64(procentry[i].pi_pid,
+                                                       thrdentry, sizeof(struct thrdentry64),
+                                                       &thindex, MAXTHRDENTRY)) > 0)
+                       {
+                               int j;
+
+                               for (j=0; j< nthreads; j++)
+                               {
+                                       switch (thrdentry[j].ti_state)
+                                       {
+                                               /* case TSNONE: break; */
+                                               case TSIDL:     blocked++;      break; /* FIXME is really blocked */
+                                               case TSRUN:     running++;      break;
+                                               case TSSLEEP:   sleeping++;     break;
+                                               case TSSWAP:    paging++;       break;
+                                               case TSSTOP:    stopped++;      break;
+                                               case TSZOMB:    zombies++;      break;
+                                       }
+                               }
+                               if (nthreads < MAXTHRDENTRY)
+                                       break;
+                       }
+
+                       pse.cpu_user = 0;
+                       /* tv_usec is nanosec ??? */
+                       pse.cpu_user_counter = procentry[i].pi_ru.ru_utime.tv_sec * 1000000 +
+                               procentry[i].pi_ru.ru_utime.tv_usec / 1000;
+
+                       pse.cpu_system = 0;
+                       /* tv_usec is nanosec ??? */
+                       pse.cpu_system_counter = procentry[i].pi_ru.ru_stime.tv_sec * 1000000 +
+                               procentry[i].pi_ru.ru_stime.tv_usec / 1000;
+
+                       pse.vmem_minflt = 0;
+                       pse.vmem_minflt_counter = procentry[i].pi_minflt;
+                       pse.vmem_majflt = 0;
+                       pse.vmem_majflt_counter = procentry[i].pi_majflt;
+
+                       pse.vmem_size = procentry[i].pi_tsize + procentry[i].pi_dvm * pagesize;
+                       pse.vmem_rss = (procentry[i].pi_drss + procentry[i].pi_trss) * pagesize;
+                       /* Not supported */
+                       pse.vmem_data = 0;
+                       pse.vmem_code = 0;
+                       pse.stack_size =  0;
+
+                       pse.io_rchar = -1;
+                       pse.io_wchar = -1;
+                       pse.io_syscr = -1;
+                       pse.io_syscw = -1;
+
+                       ps_list_add (cmdline, cargs, &pse);
+               } /* for (i = 0 .. nprocs) */
+
+               if (nprocs < MAXPROCENTRY)
+                       break;
+       } /* while (getprocs64() > 0) */
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("paging",   paging);
+       ps_submit_state ("blocked",  blocked);
+
+       for (ps = list_head_g; ps != NULL; ps = ps->next)
+               ps_submit_proc_list (ps);
+/* #endif HAVE_PROCINFO_H */
+
+#elif KERNEL_SOLARIS
+       /*
+        * The Solaris section adds a few more process states and removes some
+        * process states compared to linux. Most notably there is no "PAGING"
+        * and "BLOCKED" state for a process.  The rest is similar to the linux
+        * code.
+        */
+       int running = 0;
+       int sleeping = 0;
+       int zombies = 0;
+       int stopped = 0;
+       int detached = 0;
+       int daemon = 0;
+       int system = 0;
+       int orphan = 0;
+
+       struct dirent *ent;
+       DIR *proc;
+
+       int status;
+       procstat_t *ps_ptr;
+       char state;
+
+       char cmdline[PRARGSZ];
+
+       ps_list_reset ();
+
+       proc = opendir ("/proc");
+       if (proc == NULL)
+               return (-1);
+
+       while ((ent = readdir(proc)) != NULL)
+       {
+               long pid;
+               struct procstat ps;
+               procstat_entry_t pse;
+               char *endptr;
+
+               if (!isdigit ((int) ent->d_name[0]))
+                       continue;
+
+               pid = strtol (ent->d_name, &endptr, 10);
+               if (*endptr != 0) /* value didn't completely parse as a number */
+                       continue;
+
+               status = ps_read_process (pid, &ps, &state);
+               if (status != 0)
+               {
+                       DEBUG("ps_read_process failed: %i", status);
+                       continue;
+               }
+
+               pse.id = pid;
+               pse.age = 0;
+
+               pse.num_proc   = ps.num_proc;
+               pse.num_lwp    = ps.num_lwp;
+               pse.vmem_size  = ps.vmem_size;
+               pse.vmem_rss   = ps.vmem_rss;
+               pse.vmem_data  = ps.vmem_data;
+               pse.vmem_code  = ps.vmem_code;
+               pse.stack_size = ps.stack_size;
+
+               pse.vmem_minflt = 0;
+               pse.vmem_minflt_counter = ps.vmem_minflt_counter;
+               pse.vmem_majflt = 0;
+               pse.vmem_majflt_counter = ps.vmem_majflt_counter;
+
+               pse.cpu_user = 0;
+               pse.cpu_user_counter = ps.cpu_user_counter;
+               pse.cpu_system = 0;
+               pse.cpu_system_counter = ps.cpu_system_counter;
+
+               pse.io_rchar = ps.io_rchar;
+               pse.io_wchar = ps.io_wchar;
+               pse.io_syscr = ps.io_syscr;
+               pse.io_syscw = ps.io_syscw;
+
+               switch (state)
+               {
+                       case 'R': running++;  break;
+                       case 'S': sleeping++; break;
+                       case 'E': detached++; break;
+                       case 'Z': zombies++;  break;
+                       case 'T': stopped++;  break;
+                       case 'A': daemon++;   break;
+                       case 'Y': system++;   break;
+                       case 'O': orphan++;   break;
+               }
+
+
+               ps_list_add (ps.name,
+                               ps_get_cmdline (pid, cmdline, sizeof (cmdline)),
+                               &pse);
+       } /* while(readdir) */
+       closedir (proc);
+
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("detached", detached);
+       ps_submit_state ("daemon",   daemon);
+       ps_submit_state ("system",   system);
+       ps_submit_state ("orphan",   orphan);
+
+       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+               ps_submit_proc_list (ps_ptr);
+
+       read_fork_rate();
+#endif /* KERNEL_SOLARIS */
+
+       return (0);
+} /* int ps_read */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("processes", ps_config);
+       plugin_register_init ("processes", ps_init);
+       plugin_register_read ("processes", ps_read);
+} /* void module_register */
diff --git a/src/protocols.c b/src/protocols.c
new file mode 100644 (file)
index 0000000..1a39aad
--- /dev/null
@@ -0,0 +1,247 @@
+/**
+ * collectd - src/protocols.c
+ * Copyright (C) 2009,2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+#define SNMP_FILE "/proc/net/snmp"
+#define NETSTAT_FILE "/proc/net/netstat"
+
+/*
+ * Global variables
+ */
+static const char *config_keys[] =
+{
+  "Value",
+  "IgnoreSelected",
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *values_list = NULL;
+
+/* 
+ * Functions
+ */
+static void submit (const char *protocol_name,
+    const char *str_key, const char *str_value)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  int status;
+
+  status = parse_value (str_value, values, DS_TYPE_DERIVE);
+  if (status != 0)
+  {
+    ERROR ("protocols plugin: Parsing string as integer failed: %s",
+        str_value);
+    return;
+  }
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "protocols", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, protocol_name, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, "protocol_counter", sizeof (vl.type));
+  sstrncpy (vl.type_instance, str_key, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void submit */
+
+static int read_file (const char *path)
+{
+  FILE *fh;
+  char key_buffer[4096];
+  char value_buffer[4096];
+  char *key_ptr;
+  char *value_ptr;
+  char *key_fields[256];
+  char *value_fields[256];
+  int key_fields_num;
+  int value_fields_num;
+  int status;
+  int i;
+
+  fh = fopen (path, "r");
+  if (fh == NULL)
+  {
+    ERROR ("protocols plugin: fopen (%s) failed: %s.",
+        path, sstrerror (errno, key_buffer, sizeof (key_buffer)));
+    return (-1);
+  }
+
+  status = -1;
+  while (42)
+  {
+    clearerr (fh);
+    key_ptr = fgets (key_buffer, sizeof (key_buffer), fh);
+    if (key_ptr == NULL)
+    {
+      if (feof (fh) != 0)
+      {
+        status = 0;
+        break;
+      }
+      else if (ferror (fh) != 0)
+      {
+        ERROR ("protocols plugin: Reading from %s failed.", path);
+        break;
+      }
+      else
+      {
+        ERROR ("protocols plugin: fgets failed for an unknown reason.");
+        break;
+      }
+    } /* if (key_ptr == NULL) */
+
+    value_ptr = fgets (value_buffer, sizeof (value_buffer), fh);
+    if (value_ptr == NULL)
+    {
+      ERROR ("protocols plugin: read_file (%s): Could not read values line.",
+          path);
+      break;
+    }
+
+    key_ptr = strchr (key_buffer, ':');
+    if (key_ptr == NULL)
+    {
+      ERROR ("protocols plugin: Could not find protocol name in keys line.");
+      break;
+    }
+    *key_ptr = 0;
+    key_ptr++;
+
+    value_ptr = strchr (value_buffer, ':');
+    if (value_ptr == NULL)
+    {
+      ERROR ("protocols plugin: Could not find protocol name "
+          "in values line.");
+      break;
+    }
+    *value_ptr = 0;
+    value_ptr++;
+
+    if (strcmp (key_buffer, value_buffer) != 0)
+    {
+      ERROR ("protocols plugin: Protocol names in keys and values lines "
+          "don't match: `%s' vs. `%s'.",
+          key_buffer, value_buffer);
+      break;
+    }
+
+
+    key_fields_num = strsplit (key_ptr,
+        key_fields, STATIC_ARRAY_SIZE (key_fields));
+    value_fields_num = strsplit (value_ptr,
+        value_fields, STATIC_ARRAY_SIZE (value_fields));
+
+    if (key_fields_num != value_fields_num)
+    {
+      ERROR ("protocols plugin: Number of fields in keys and values lines "
+          "don't match: %i vs %i.",
+          key_fields_num, value_fields_num);
+      break;
+    }
+
+    for (i = 0; i < key_fields_num; i++)
+    {
+      if (values_list != NULL)
+      {
+        char match_name[2 * DATA_MAX_NAME_LEN];
+
+        ssnprintf (match_name, sizeof (match_name), "%s:%s",
+            key_buffer, key_fields[i]);
+
+        if (ignorelist_match (values_list, match_name))
+          continue;
+      } /* if (values_list != NULL) */
+
+      submit (key_buffer, key_fields[i], value_fields[i]);
+    } /* for (i = 0; i < key_fields_num; i++) */
+  } /* while (42) */
+
+  fclose (fh);
+
+  return (status);
+} /* int read_file */
+
+static int protocols_read (void)
+{
+  int status;
+  int success = 0;
+
+  status = read_file (SNMP_FILE);
+  if (status == 0)
+    success++;
+
+  status = read_file (NETSTAT_FILE);
+  if (status == 0)
+    success++;
+
+  if (success == 0)
+    return (-1);
+
+  return (0);
+} /* int protocols_read */
+
+static int protocols_config (const char *key, const char *value)
+{
+  if (values_list == NULL)
+    values_list = ignorelist_create (/* invert = */ 1);
+
+  if (strcasecmp (key, "Value") == 0)
+  {
+    ignorelist_add (values_list, value);
+  }
+  else if (strcasecmp (key, "IgnoreSelected") == 0)
+  {
+    int invert = 1;
+    if (IS_TRUE (value))
+      invert = 0;
+    ignorelist_set_invert (values_list, invert);
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int protocols_config */
+
+void module_register (void)
+{
+  plugin_register_config ("protocols", protocols_config,
+      config_keys, config_keys_num);
+  plugin_register_read ("protocols", protocols_read);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/pyconfig.c b/src/pyconfig.c
new file mode 100644 (file)
index 0000000..b5c01aa
--- /dev/null
@@ -0,0 +1,217 @@
+/**
+ * collectd - src/pyconfig.c
+ * Copyright (C) 2009  Sven Trenkel
+ *
+ * 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:
+ *   Sven Trenkel <collectd at semidefinite.de>  
+ **/
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "collectd.h"
+#include "common.h"
+
+#include "cpython.h"
+
+static char config_doc[] = "This represents a piece of collectd's config file.\n"
+               "It is passed to scripts with config callbacks (see \"register_config\")\n"
+               "and is of little use if created somewhere else.\n"
+               "\n"
+               "It has no methods beyond the bare minimum and only exists for its\n"
+               "data members";
+
+static char parent_doc[] = "This represents the parent of this node. On the root node\n"
+               "of the config tree it will be None.\n";
+
+static char key_doc[] = "This is the keyword of this item, ie the first word of any\n"
+               "given line in the config file. It will always be a string.\n";
+
+static char values_doc[] = "This is a tuple (which might be empty) of all value, ie words\n"
+               "following the keyword in any given line in the config file.\n"
+               "\n"
+               "Every item in this tuple will be either a string or a float or a bool,\n"
+               "depending on the contents of the configuration file.\n";
+
+static char children_doc[] = "This is a tuple of child nodes. For most nodes this will be\n"
+               "empty. If this node represents a block instead of a single line of the config\n"
+               "file it will contain all nodes in this block.\n";
+
+static PyObject *Config_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+       Config *self;
+       
+       self = (Config *) type->tp_alloc(type, 0);
+       if (self == NULL)
+               return NULL;
+       
+       self->parent = NULL;
+       self->key = NULL;
+       self->values = NULL;
+       self->children = NULL;
+       return (PyObject *) self;
+}
+
+static int Config_init(PyObject *s, PyObject *args, PyObject *kwds) {
+       PyObject *key = NULL, *parent = NULL, *values = NULL, *children = NULL, *tmp;
+       Config *self = (Config *) s;
+       static char *kwlist[] = {"key", "parent", "values", "children", NULL};
+       
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist,
+                       &key, &parent, &values, &children))
+               return -1;
+       
+       if (!IS_BYTES_OR_UNICODE(key)) {
+               PyErr_SetString(PyExc_TypeError, "argument 1 must be str");
+               Py_XDECREF(parent);
+               Py_XDECREF(values);
+               Py_XDECREF(children);
+               return -1;
+       }
+       if (values == NULL) {
+               values = PyTuple_New(0);
+               PyErr_Clear();
+       }
+       if (children == NULL) {
+               children = PyTuple_New(0);
+               PyErr_Clear();
+       }
+       tmp = self->key;
+       Py_INCREF(key);
+       self->key = key;
+       Py_XDECREF(tmp);
+       if (parent != NULL) {
+               tmp = self->parent;
+               Py_INCREF(parent);
+               self->parent = parent;
+               Py_XDECREF(tmp);
+       }
+       if (values != NULL) {
+               tmp = self->values;
+               Py_INCREF(values);
+               self->values = values;
+               Py_XDECREF(tmp);
+       }
+       if (children != NULL) {
+               tmp = self->children;
+               Py_INCREF(children);
+               self->children = children;
+               Py_XDECREF(tmp);
+       }
+       return 0;
+}
+
+static PyObject *Config_repr(PyObject *s) {
+       Config *self = (Config *) s;
+       PyObject *ret = NULL;
+       static PyObject *node_prefix = NULL, *root_prefix = NULL, *ending = NULL;
+       
+       /* This is ok because we have the GIL, so this is thread-save by default. */
+       if (node_prefix == NULL)
+               node_prefix = cpy_string_to_unicode_or_bytes("<collectd.Config node ");
+       if (root_prefix == NULL)
+               root_prefix = cpy_string_to_unicode_or_bytes("<collectd.Config root node ");
+       if (ending == NULL)
+               ending = cpy_string_to_unicode_or_bytes(">");
+       if (node_prefix == NULL || root_prefix == NULL || ending == NULL)
+               return NULL;
+       
+       ret = PyObject_Str(self->key);
+       CPY_SUBSTITUTE(PyObject_Repr, ret, ret);
+       if (self->parent == NULL || self->parent == Py_None)
+               CPY_STRCAT(&ret, root_prefix);
+       else
+               CPY_STRCAT(&ret, node_prefix);
+       CPY_STRCAT(&ret, ending);
+       
+       return ret;
+}
+
+static int Config_traverse(PyObject *self, visitproc visit, void *arg) {
+       Config *c = (Config *) self;
+       Py_VISIT(c->parent);
+       Py_VISIT(c->key);
+       Py_VISIT(c->values);
+       Py_VISIT(c->children);
+       return 0;}
+
+static int Config_clear(PyObject *self) {
+       Config *c = (Config *) self;
+       Py_CLEAR(c->parent);
+       Py_CLEAR(c->key);
+       Py_CLEAR(c->values);
+       Py_CLEAR(c->children);
+       return 0;
+}
+
+static void Config_dealloc(PyObject *self) {
+       Config_clear(self);
+       self->ob_type->tp_free(self);
+}
+
+static PyMemberDef Config_members[] = {
+       {"parent", T_OBJECT, offsetof(Config, parent), 0, parent_doc},
+       {"key", T_OBJECT_EX, offsetof(Config, key), 0, key_doc},
+       {"values", T_OBJECT_EX, offsetof(Config, values), 0, values_doc},
+       {"children", T_OBJECT_EX, offsetof(Config, children), 0, children_doc},
+       {NULL}
+};
+
+PyTypeObject ConfigType = {
+       CPY_INIT_TYPE
+       "collectd.Config",         /* tp_name */
+       sizeof(Config),            /* tp_basicsize */
+       0,                         /* Will be filled in later */
+       Config_dealloc,            /* tp_dealloc */
+       0,                         /* tp_print */
+       0,                         /* tp_getattr */
+       0,                         /* tp_setattr */
+       0,                         /* tp_compare */
+       Config_repr,               /* tp_repr */
+       0,                         /* tp_as_number */
+       0,                         /* tp_as_sequence */
+       0,                         /* tp_as_mapping */
+       0,                         /* tp_hash */
+       0,                         /* tp_call */
+       0,                         /* tp_str */
+       0,                         /* tp_getattro */
+       0,                         /* tp_setattro */
+       0,                         /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+       config_doc,                /* tp_doc */
+       Config_traverse,           /* tp_traverse */
+       Config_clear,              /* tp_clear */
+       0,                         /* tp_richcompare */
+       0,                         /* tp_weaklistoffset */
+       0,                         /* tp_iter */
+       0,                         /* tp_iternext */
+       0,                         /* tp_methods */
+       Config_members,            /* tp_members */
+       0,                         /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       Config_init,               /* tp_init */
+       0,                         /* tp_alloc */
+       Config_new                 /* tp_new */
+};
+
diff --git a/src/python.c b/src/python.c
new file mode 100644 (file)
index 0000000..8b378a2
--- /dev/null
@@ -0,0 +1,1222 @@
+/**
+ * collectd - src/python.c
+ * Copyright (C) 2009  Sven Trenkel
+ *
+ * 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:
+ *   Sven Trenkel <collectd at semidefinite.de>  
+ **/
+
+#include <Python.h>
+#include <structmember.h>
+
+#include <signal.h>
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+#include "collectd.h"
+#include "common.h"
+
+#include "cpython.h"
+
+typedef struct cpy_callback_s {
+       char *name;
+       PyObject *callback;
+       PyObject *data;
+       struct cpy_callback_s *next;
+} cpy_callback_t;
+
+static char log_doc[] = "This function sends a string to all logging plugins.";
+
+static char get_ds_doc[] = "get_dataset(name) -> definition\n"
+               "\n"
+               "Returns the definition of a dataset specified by name.\n"
+               "\n"
+               "'name' is a string specifying the dataset to query.\n"
+               "'definition' is a list of 4-tuples. Every tuple represents a \n"
+               "    data source within the data set and its 4 values are the \n"
+               "    name, type, min and max value.\n"
+               "    'name' is a string.\n"
+               "    'type' is a string that is equal to either DS_TYPE_COUNTER,\n"
+               "        DS_TYPE_GAUGE, DS_TYPE_DERIVE or DS_TYPE_ABSOLUTE.\n"
+               "    'min' and 'max' are either a float or None.";
+
+static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
+               "\n"
+               "Flushes the cache of another plugin.";
+
+static char unregister_doc[] = "Unregisters a callback. This function needs exactly one parameter either\n"
+               "the function to unregister or the callback identifier to unregister.";
+
+static char reg_log_doc[] = "register_log(callback[, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function for log messages.\n"
+               "\n"
+               "'callback' is a callable object that will be called every time something\n"
+               "    is logged.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function every time it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called with two or three parameters:\n"
+               "severity: An integer that should be compared to the LOG_ constants.\n"
+               "message: The text to be logged.\n"
+               "data: The optional data parameter passed to the register function.\n"
+               "    If the parameter was omitted it will be omitted here, too.";
+
+static char reg_init_doc[] = "register_init(callback[, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function that will be executed once after the config.\n"
+               "file has been read, all plugins heve been loaded and the collectd has\n"
+               "forked into the background.\n"
+               "\n"
+               "'callback' is a callable object that will be executed.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function when it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called without parameters, except for\n"
+               "data if it was supplied.";
+
+static char reg_config_doc[] = "register_config(callback[, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function for config file entries.\n"
+               "'callback' is a callable object that will be called for every config block.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function every time it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called with one or two parameters:\n"
+               "config: A Config object.\n"
+               "data: The optional data parameter passed to the register function.\n"
+               "    If the parameter was omitted it will be omitted here, too.";
+
+static char reg_read_doc[] = "register_read(callback[, interval][, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function for reading data. It will just be called\n"
+               "in a fixed interval to signal that it's time to dispatch new values.\n"
+               "'callback' is a callable object that will be called every time something\n"
+               "    is logged.\n"
+               "'interval' is the number of seconds between between calls to the callback\n"
+               "    function. Full float precision is supported here.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function every time it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called without parameters, except for\n"
+               "data if it was supplied.";
+
+static char reg_write_doc[] = "register_write(callback[, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function to receive values dispatched by other plugins.\n"
+               "'callback' is a callable object that will be called every time a value\n"
+               "    is dispatched.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function every time it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called with one or two parameters:\n"
+               "values: A Values object which is a copy of the dispatched values.\n"
+               "data: The optional data parameter passed to the register function.\n"
+               "    If the parameter was omitted it will be omitted here, too.";
+
+static char reg_notification_doc[] = "register_notification(callback[, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function for notifications.\n"
+               "'callback' is a callable object that will be called every time a notification\n"
+               "    is dispatched.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function every time it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called with one or two parameters:\n"
+               "notification: A copy of the notification that was dispatched.\n"
+               "data: The optional data parameter passed to the register function.\n"
+               "    If the parameter was omitted it will be omitted here, too.";
+
+static char reg_flush_doc[] = "register_flush(callback[, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function for flush messages.\n"
+               "'callback' is a callable object that will be called every time a plugin\n"
+               "    requests a flush for either this or all plugins.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function every time it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called with two or three parameters:\n"
+               "timeout: Indicates that only data older than 'timeout' seconds is to\n"
+               "    be flushed.\n"
+               "id: Specifies which values are to be flushed.\n"
+               "data: The optional data parameter passed to the register function.\n"
+               "    If the parameter was omitted it will be omitted here, too.";
+
+static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) -> identifier\n"
+               "\n"
+               "Register a callback function for collectd shutdown.\n"
+               "'callback' is a callable object that will be called once collectd is\n"
+               "    shutting down.\n"
+               "'data' is an optional object that will be passed back to the callback\n"
+               "    function if it is called.\n"
+               "'name' is an optional identifier for this callback. The default name\n"
+               "    is 'python.<module>'.\n"
+               "    Every callback needs a unique identifier, so if you want to\n"
+               "    register this callback multiple time from the same module you need\n"
+               "    to specify a name here.\n"
+               "'identifier' is the full identifier assigned to this callback.\n"
+               "\n"
+               "The callback function will be called with no parameters except for\n"
+               "    data if it was supplied.";
+
+
+static int do_interactive = 0;
+
+/* This is our global thread state. Python saves some stuff in thread-local
+ * storage. So if we allow the interpreter to run in the background
+ * (the scriptwriters might have created some threads from python), we have
+ * to save the state so we can resume it later after shutdown. */
+
+static PyThreadState *state;
+
+static PyObject *sys_path, *cpy_format_exception;
+
+static cpy_callback_t *cpy_config_callbacks;
+static cpy_callback_t *cpy_init_callbacks;
+static cpy_callback_t *cpy_shutdown_callbacks;
+
+static void cpy_destroy_user_data(void *data) {
+       cpy_callback_t *c = data;
+       free(c->name);
+       Py_DECREF(c->callback);
+       Py_XDECREF(c->data);
+       free(c);
+}
+
+/* You must hold the GIL to call this function!
+ * But if you managed to extract the callback parameter then you probably already do. */
+
+static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
+       const char *module = NULL;
+       PyObject *mod = NULL;
+       
+       if (name != NULL) {
+               snprintf(buf, size, "python.%s", name);
+               return;
+       }
+       
+       mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
+       if (mod != NULL)
+               module = cpy_unicode_or_bytes_to_string(&mod);
+       
+       if (module != NULL) {
+               snprintf(buf, size, "python.%s", module);
+               Py_XDECREF(mod);
+               PyErr_Clear();
+               return;
+       }
+       Py_XDECREF(mod);
+       
+       snprintf(buf, size, "python.%p", callback);
+       PyErr_Clear();
+}
+
+void cpy_log_exception(const char *context) {
+       int l = 0, i;
+       const char *typename = NULL, *message = NULL;
+       PyObject *type, *value, *traceback, *tn, *m, *list;
+       
+       PyErr_Fetch(&type, &value, &traceback);
+       PyErr_NormalizeException(&type, &value, &traceback);
+       if (type == NULL) return;
+       tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
+       m = PyObject_Str(value); /* New reference. */
+       if (tn != NULL)
+               typename = cpy_unicode_or_bytes_to_string(&tn);
+       if (m != NULL)
+               message = cpy_unicode_or_bytes_to_string(&m);
+       if (typename == NULL)
+               typename = "NamelessException";
+       if (message == NULL)
+               message = "N/A";
+       Py_BEGIN_ALLOW_THREADS
+       ERROR("Unhandled python exception in %s: %s: %s", context, typename, message);
+       Py_END_ALLOW_THREADS
+       Py_XDECREF(tn);
+       Py_XDECREF(m);
+       if (!cpy_format_exception || !traceback) {
+               PyErr_Clear();
+               Py_DECREF(type);
+               Py_XDECREF(value);
+               Py_XDECREF(traceback);
+               return;
+       }
+       list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. */
+       if (list)
+               l = PyObject_Length(list);
+       for (i = 0; i < l; ++i) {
+               char *s;
+               PyObject *line;
+               
+               line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
+               Py_INCREF(line);
+               s = strdup(cpy_unicode_or_bytes_to_string(&line));
+               Py_DECREF(line);
+               if (s[strlen(s) - 1] == '\n')
+                       s[strlen(s) - 1] = 0;
+               Py_BEGIN_ALLOW_THREADS
+               ERROR("%s", s);
+               Py_END_ALLOW_THREADS
+               free(s);
+       }
+       Py_XDECREF(list);
+       PyErr_Clear();
+       Py_DECREF(type);
+       Py_XDECREF(value);
+       Py_XDECREF(traceback);
+}
+
+static int cpy_read_callback(user_data_t *data) {
+       cpy_callback_t *c = data->data;
+       PyObject *ret;
+
+       CPY_LOCK_THREADS
+               ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
+               if (ret == NULL) {
+                       cpy_log_exception("read callback");
+               } else {
+                       Py_DECREF(ret);
+               }
+       CPY_RELEASE_THREADS
+       if (ret == NULL)
+               return 1;
+       return 0;
+}
+
+static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
+       int i;
+       cpy_callback_t *c = data->data;
+       PyObject *ret, *list, *temp, *dict = NULL;
+       Values *v;
+
+       CPY_LOCK_THREADS
+               list = PyList_New(value_list->values_len); /* New reference. */
+               if (list == NULL) {
+                       cpy_log_exception("write callback");
+                       CPY_RETURN_FROM_THREADS 0;
+               }
+               for (i = 0; i < value_list->values_len; ++i) {
+                       if (ds->ds[i].type == DS_TYPE_COUNTER) {
+                               if ((long) value_list->values[i].counter == value_list->values[i].counter)
+                                       PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
+                               else
+                                       PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
+                       } else if (ds->ds[i].type == DS_TYPE_GAUGE) {
+                               PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
+                       } else if (ds->ds[i].type == DS_TYPE_DERIVE) {
+                               if ((long) value_list->values[i].derive == value_list->values[i].derive)
+                                       PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
+                               else
+                                       PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
+                       } else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
+                               if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
+                                       PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
+                               else
+                                       PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
+                       } else {
+                               Py_BEGIN_ALLOW_THREADS
+                               ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
+                               Py_END_ALLOW_THREADS
+                               Py_DECREF(list);
+                               CPY_RETURN_FROM_THREADS 0;
+                       }
+                       if (PyErr_Occurred() != NULL) {
+                               cpy_log_exception("value building for write callback");
+                               Py_DECREF(list);
+                               CPY_RETURN_FROM_THREADS 0;
+                       }
+               }
+               dict = PyDict_New();  /* New reference. */
+               if (value_list->meta) {
+                       int i, num;
+                       char **table;
+                       meta_data_t *meta = value_list->meta;
+
+                       num = meta_data_toc(meta, &table);
+                       for (i = 0; i < num; ++i) {
+                               int type;
+                               char *string;
+                               int64_t si;
+                               uint64_t ui;
+                               double d;
+                               _Bool b;
+                               
+                               type = meta_data_type(meta, table[i]);
+                               if (type == MD_TYPE_STRING) {
+                                       if (meta_data_get_string(meta, table[i], &string))
+                                               continue;
+                                       temp = cpy_string_to_unicode_or_bytes(string);  /* New reference. */
+                                       free(string);
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_SIGNED_INT) {
+                                       if (meta_data_get_signed_int(meta, table[i], &si))
+                                               continue;
+                                       temp = PyObject_CallFunctionObjArgs((void *) &SignedType, PyLong_FromLongLong(si), (void *) 0);  /* New reference. */
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_UNSIGNED_INT) {
+                                       if (meta_data_get_unsigned_int(meta, table[i], &ui))
+                                               continue;
+                                       temp = PyObject_CallFunctionObjArgs((void *) &UnsignedType, PyLong_FromUnsignedLongLong(ui), (void *) 0);  /* New reference. */
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_DOUBLE) {
+                                       if (meta_data_get_double(meta, table[i], &d))
+                                               continue;
+                                       temp = PyFloat_FromDouble(d);  /* New reference. */
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_BOOLEAN) {
+                                       if (meta_data_get_boolean(meta, table[i], &b))
+                                               continue;
+                                       if (b)
+                                               PyDict_SetItemString(dict, table[i], Py_True);
+                                       else
+                                               PyDict_SetItemString(dict, table[i], Py_False);
+                               }
+                               free(table[i]);
+                       }
+                       free(table);
+               }
+               v = (Values *) Values_New(); /* New reference. */
+               sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
+               sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
+               sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance));
+               sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
+               sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance));
+               v->data.time = CDTIME_T_TO_DOUBLE(value_list->time);
+               v->interval = CDTIME_T_TO_DOUBLE(value_list->interval);
+               Py_CLEAR(v->values);
+               v->values = list;
+               Py_CLEAR(v->meta);
+               v->meta = dict;  /* Steals a reference. */
+               ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
+               Py_XDECREF(v);
+               if (ret == NULL) {
+                       cpy_log_exception("write callback");
+               } else {
+                       Py_DECREF(ret);
+               }
+       CPY_RELEASE_THREADS
+       return 0;
+}
+
+static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
+       cpy_callback_t *c = data->data;
+       PyObject *ret, *notify;
+       Notification *n;
+
+       CPY_LOCK_THREADS
+               notify = Notification_New(); /* New reference. */
+               n = (Notification *) notify;
+               sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
+               sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
+               sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance));
+               sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
+               sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance));
+               n->data.time = CDTIME_T_TO_DOUBLE(notification->time);
+               sstrncpy(n->message, notification->message, sizeof(n->message));
+               n->severity = notification->severity;
+               ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
+               Py_XDECREF(notify);
+               if (ret == NULL) {
+                       cpy_log_exception("notification callback");
+               } else {
+                       Py_DECREF(ret);
+               }
+       CPY_RELEASE_THREADS
+       return 0;
+}
+
+static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
+       cpy_callback_t * c = data->data;
+       PyObject *ret, *text;
+
+       CPY_LOCK_THREADS
+       text = cpy_string_to_unicode_or_bytes(message);  /* New reference. */
+       if (c->data == NULL)
+               ret = PyObject_CallFunction(c->callback, "iN", severity, text); /* New reference. Steals a reference from "text". */
+       else
+               ret = PyObject_CallFunction(c->callback, "iNO", severity, text, c->data); /* New reference. Steals a reference from "text". */
+
+       if (ret == NULL) {
+               /* FIXME */
+               /* Do we really want to trigger a log callback because a log callback failed?
+                * Probably not. */
+               PyErr_Print();
+               /* In case someone wanted to be clever, replaced stderr and failed at that. */
+               PyErr_Clear();
+       } else {
+               Py_DECREF(ret);
+       }
+       CPY_RELEASE_THREADS
+}
+
+static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
+       cpy_callback_t * c = data->data;
+       PyObject *ret, *text;
+
+       CPY_LOCK_THREADS
+       text = cpy_string_to_unicode_or_bytes(id);
+       if (c->data == NULL)
+               ret = PyObject_CallFunction(c->callback, "iN", timeout, text); /* New reference. */
+       else
+               ret = PyObject_CallFunction(c->callback, "iNO", timeout, text, c->data); /* New reference. */
+
+       if (ret == NULL) {
+               cpy_log_exception("flush callback");
+       } else {
+               Py_DECREF(ret);
+       }
+       CPY_RELEASE_THREADS
+}
+
+static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
+       char buf[512];
+       cpy_callback_t *c;
+       char *name = NULL;
+       PyObject *callback = NULL, *data = NULL, *mod = NULL;
+       static char *kwlist[] = {"callback", "data", "name", NULL};
+       
+       if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
+       if (PyCallable_Check(callback) == 0) {
+               PyMem_Free(name);
+               PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
+               return NULL;
+       }
+       cpy_build_name(buf, sizeof(buf), callback, name);
+
+       Py_INCREF(callback);
+       Py_XINCREF(data);
+       c = malloc(sizeof(*c));
+       c->name = strdup(buf);
+       c->callback = callback;
+       c->data = data;
+       c->next = *list_head;
+       *list_head = c;
+       Py_XDECREF(mod);
+       PyMem_Free(name);
+       return cpy_string_to_unicode_or_bytes(buf);
+}
+
+static PyObject *float_or_none(float number) {
+       if (isnan(number)) {
+               Py_RETURN_NONE;
+       }
+       return PyFloat_FromDouble(number);
+}
+
+static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
+       int i;
+       char *name;
+       const data_set_t *ds;
+       PyObject *list, *tuple;
+
+       if (PyArg_ParseTuple(args, "et", NULL, &name) == 0) return NULL;
+       ds = plugin_get_ds(name);
+       PyMem_Free(name);
+       if (ds == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
+               return NULL;
+       }
+       list = PyList_New(ds->ds_num); /* New reference. */
+       for (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, 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);
+       }
+       return list;
+}
+
+static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
+       int timeout = -1;
+       char *plugin = NULL, *identifier = NULL;
+       static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
+       
+       if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       plugin_flush(plugin, timeout, identifier);
+       Py_END_ALLOW_THREADS
+       PyMem_Free(plugin);
+       PyMem_Free(identifier);
+       Py_RETURN_NONE;
+}
+
+static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
+       return cpy_register_generic(&cpy_config_callbacks, args, kwds);
+}
+
+static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
+       return cpy_register_generic(&cpy_init_callbacks, args, kwds);
+}
+
+typedef int reg_function_t(const char *name, void *callback, void *data);
+
+static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
+       char buf[512];
+       reg_function_t *register_function = (reg_function_t *) reg;
+       cpy_callback_t *c = NULL;
+       user_data_t *user_data = NULL;
+       char *name = NULL;
+       PyObject *callback = NULL, *data = NULL;
+       static char *kwlist[] = {"callback", "data", "name", NULL};
+       
+       if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
+       if (PyCallable_Check(callback) == 0) {
+               PyMem_Free(name);
+               PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
+               return NULL;
+       }
+       cpy_build_name(buf, sizeof(buf), callback, name);
+       PyMem_Free(name);
+       
+       Py_INCREF(callback);
+       Py_XINCREF(data);
+       c = malloc(sizeof(*c));
+       c->name = strdup(buf);
+       c->callback = callback;
+       c->data = data;
+       c->next = NULL;
+       user_data = malloc(sizeof(*user_data));
+       user_data->free_func = cpy_destroy_user_data;
+       user_data->data = c;
+       register_function(buf, handler, user_data);
+       return cpy_string_to_unicode_or_bytes(buf);
+}
+
+static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
+       char buf[512];
+       cpy_callback_t *c = NULL;
+       user_data_t *user_data = NULL;
+       double interval = 0;
+       char *name = NULL;
+       PyObject *callback = NULL, *data = NULL;
+       struct timespec ts;
+       static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
+       
+       if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
+       if (PyCallable_Check(callback) == 0) {
+               PyMem_Free(name);
+               PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
+               return NULL;
+       }
+       cpy_build_name(buf, sizeof(buf), callback, name);
+       PyMem_Free(name);
+       
+       Py_INCREF(callback);
+       Py_XINCREF(data);
+       c = malloc(sizeof(*c));
+       c->name = strdup(buf);
+       c->callback = callback;
+       c->data = data;
+       c->next = NULL;
+       user_data = malloc(sizeof(*user_data));
+       user_data->free_func = cpy_destroy_user_data;
+       user_data->data = c;
+       ts.tv_sec = interval;
+       ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
+       plugin_register_complex_read(/* group = */ NULL, buf,
+                       cpy_read_callback, &ts, user_data);
+       return cpy_string_to_unicode_or_bytes(buf);
+}
+
+static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
+       return cpy_register_generic_userdata((void *) plugin_register_log,
+                       (void *) cpy_log_callback, args, kwds);
+}
+
+static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
+       return cpy_register_generic_userdata((void *) plugin_register_write,
+                       (void *) cpy_write_callback, args, kwds);
+}
+
+static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
+       return cpy_register_generic_userdata((void *) plugin_register_notification,
+                       (void *) cpy_notification_callback, args, kwds);
+}
+
+static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
+       return cpy_register_generic_userdata((void *) plugin_register_flush,
+                       (void *) cpy_flush_callback, args, kwds);
+}
+
+static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
+       return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
+}
+
+static PyObject *cpy_error(PyObject *self, PyObject *args) {
+       char *text;
+       if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       plugin_log(LOG_ERR, "%s", text);
+       Py_END_ALLOW_THREADS
+       PyMem_Free(text);
+       Py_RETURN_NONE;
+}
+
+static PyObject *cpy_warning(PyObject *self, PyObject *args) {
+       char *text;
+       if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       plugin_log(LOG_WARNING, "%s", text);
+       Py_END_ALLOW_THREADS
+       PyMem_Free(text);
+       Py_RETURN_NONE;
+}
+
+static PyObject *cpy_notice(PyObject *self, PyObject *args) {
+       char *text;
+       if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       plugin_log(LOG_NOTICE, "%s", text);
+       Py_END_ALLOW_THREADS
+       PyMem_Free(text);
+       Py_RETURN_NONE;
+}
+
+static PyObject *cpy_info(PyObject *self, PyObject *args) {
+       char *text;
+       if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       plugin_log(LOG_INFO, "%s", text);
+       Py_END_ALLOW_THREADS
+       PyMem_Free(text);
+       Py_RETURN_NONE;
+}
+
+static PyObject *cpy_debug(PyObject *self, PyObject *args) {
+#ifdef COLLECT_DEBUG
+       char *text;
+       if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
+       Py_BEGIN_ALLOW_THREADS
+       plugin_log(LOG_DEBUG, "%s", text);
+       Py_END_ALLOW_THREADS
+       PyMem_Free(text);
+#endif
+       Py_RETURN_NONE;
+}
+
+static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
+       char buf[512];
+       const char *name;
+       cpy_callback_t *prev = NULL, *tmp;
+
+       Py_INCREF(arg);
+       name = cpy_unicode_or_bytes_to_string(&arg);
+       if (name == NULL) {
+               PyErr_Clear();
+               if (!PyCallable_Check(arg)) {
+                       PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
+                       Py_DECREF(arg);
+                       return NULL;
+               }
+               cpy_build_name(buf, sizeof(buf), arg, NULL);
+               name = buf;
+       }
+       for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
+               if (strcmp(name, tmp->name) == 0)
+                       break;
+       
+       Py_DECREF(arg);
+       if (tmp == NULL) {
+               PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
+               return NULL;
+       }
+       /* Yes, this is actually save. To call this function the caller has to
+        * hold the GIL. Well, save as long as there is only one GIL anyway ... */
+       if (prev == NULL)
+               *list_head = tmp->next;
+       else
+               prev->next = tmp->next;
+       cpy_destroy_user_data(tmp);
+       Py_RETURN_NONE;
+}
+
+typedef int cpy_unregister_function_t(const char *name);
+
+static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
+       char buf[512];
+       const char *name;
+
+       Py_INCREF(arg);
+       name = cpy_unicode_or_bytes_to_string(&arg);
+       if (name == NULL) {
+               PyErr_Clear();
+               if (!PyCallable_Check(arg)) {
+                       PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
+                       Py_DECREF(arg);
+                       return NULL;
+               }
+               cpy_build_name(buf, sizeof(buf), arg, NULL);
+               name = buf;
+       }
+       if (unreg(name) == 0) {
+               Py_DECREF(arg);
+               Py_RETURN_NONE;
+       }
+       PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
+       Py_DECREF(arg);
+       return NULL;
+}
+
+static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
+}
+
+static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
+}
+
+static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
+}
+
+static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
+}
+
+static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
+}
+
+static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
+}
+
+static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
+}
+
+static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
+       return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
+}
+
+static PyMethodDef cpy_methods[] = {
+       {"debug", cpy_debug, METH_VARARGS, log_doc},
+       {"info", cpy_info, METH_VARARGS, log_doc},
+       {"notice", cpy_notice, METH_VARARGS, log_doc},
+       {"warning", cpy_warning, METH_VARARGS, log_doc},
+       {"error", cpy_error, METH_VARARGS, log_doc},
+       {"get_dataset", (PyCFunction) cpy_get_dataset, METH_VARARGS, get_ds_doc},
+       {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
+       {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
+       {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
+       {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
+       {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
+       {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
+       {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
+       {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
+       {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
+       {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
+       {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
+       {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
+       {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
+       {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
+       {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
+       {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
+       {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
+       {0, 0, 0, 0}
+};
+
+static int cpy_shutdown(void) {
+       cpy_callback_t *c;
+       PyObject *ret;
+       
+       /* This can happen if the module was loaded but not configured. */
+       if (state != NULL)
+               PyEval_RestoreThread(state);
+
+       for (c = cpy_shutdown_callbacks; c; c = c->next) {
+               ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
+               if (ret == NULL)
+                       cpy_log_exception("shutdown callback");
+               else
+                       Py_DECREF(ret);
+       }
+       PyErr_Print();
+       Py_Finalize();
+       return 0;
+}
+
+static void cpy_int_handler(int sig) {
+       return;
+}
+
+static void *cpy_interactive(void *data) {
+       sigset_t sigset;
+       struct sigaction sig_int_action, old;
+       
+       /* Signal handler in a plugin? Bad stuff, but the best way to
+        * handle it I guess. In an interactive session people will
+        * press Ctrl+C at some time, which will generate a SIGINT.
+        * This will cause collectd to shutdown, thus killing the
+        * interactive interpreter, and leaving the terminal in a
+        * mess. Chances are, this isn't what the user wanted to do.
+        * 
+        * So this is the plan:
+        * 1. Block SIGINT in the main thread.
+        * 2. Install our own signal handler that does nothing.
+        * 3. Unblock SIGINT in the interactive thread.
+        *
+        * This will make sure that SIGINT won't kill collectd but
+        * still interrupt syscalls like sleep and pause.
+        * It does not raise a KeyboardInterrupt exception because so
+        * far nobody managed to figure out how to do that. */
+       memset (&sig_int_action, '\0', sizeof (sig_int_action));
+       sig_int_action.sa_handler = cpy_int_handler;
+       sigaction (SIGINT, &sig_int_action, &old);
+       
+       sigemptyset(&sigset);
+       sigaddset(&sigset, SIGINT);
+       pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
+       PyEval_AcquireThread(state);
+       if (PyImport_ImportModule("readline") == NULL) {
+               /* This interactive session will suck. */
+               cpy_log_exception("interactive session init");
+       }
+       PyRun_InteractiveLoop(stdin, "<stdin>");
+       PyErr_Print();
+       PyEval_ReleaseThread(state);
+       NOTICE("python: Interactive interpreter exited, stopping collectd ...");
+       /* Restore the original collectd SIGINT handler and raise SIGINT.
+        * The main thread still has SIGINT blocked and there's nothing we
+        * can do about that so this thread will handle it. But that's not
+        * important, except that it won't interrupt the main loop and so
+        * it might take a few seconds before collectd really shuts down. */
+       sigaction (SIGINT, &old, NULL);
+       raise(SIGINT);
+       pause();
+       return NULL;
+}
+
+static int cpy_init(void) {
+       cpy_callback_t *c;
+       PyObject *ret;
+       static pthread_t thread;
+       sigset_t sigset;
+       
+       if (!Py_IsInitialized()) {
+               WARNING("python: Plugin loaded but not configured.");
+               plugin_unregister_shutdown("python");
+               return 0;
+       }
+       PyEval_InitThreads();
+       /* Now it's finally OK to use python threads. */
+       for (c = cpy_init_callbacks; c; c = c->next) {
+               ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
+               if (ret == NULL)
+                       cpy_log_exception("init callback");
+               else
+                       Py_DECREF(ret);
+       }
+       sigemptyset(&sigset);
+       sigaddset(&sigset, SIGINT);
+       pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+       state = PyEval_SaveThread();
+       if (do_interactive) {
+               if (plugin_thread_create(&thread, NULL, cpy_interactive, NULL)) {
+                       ERROR("python: Error creating thread for interactive interpreter.");
+               }
+       }
+
+       return 0;
+}
+
+static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
+       int i;
+       PyObject *item, *values, *children, *tmp;
+       
+       if (parent == NULL)
+               parent = Py_None;
+       
+       values = PyTuple_New(ci->values_num); /* New reference. */
+       for (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));
+               } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
+                       PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
+               } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
+                       PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
+               }
+       }
+       
+       tmp = cpy_string_to_unicode_or_bytes(ci->key);
+       item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
+       if (item == NULL)
+               return NULL;
+       children = PyTuple_New(ci->children_num); /* New reference. */
+       for (i = 0; i < ci->children_num; ++i) {
+               PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
+       }
+       tmp = ((Config *) item)->children;
+       ((Config *) item)->children = children;
+       Py_XDECREF(tmp);
+       return item;
+}
+
+#ifdef IS_PY3K
+static struct PyModuleDef collectdmodule = {
+       PyModuleDef_HEAD_INIT,
+       "collectd",   /* name of module */
+       "The python interface to collectd", /* module documentation, may be NULL */
+       -1,
+       cpy_methods
+};
+
+PyMODINIT_FUNC PyInit_collectd(void) {
+       return PyModule_Create(&collectdmodule);
+}
+#endif
+
+static int cpy_init_python() {
+       PyObject *sys;
+       PyObject *module;
+
+#ifdef IS_PY3K
+       wchar_t *argv = L"";
+       /* Add a builtin module, before Py_Initialize */
+       PyImport_AppendInittab("collectd", PyInit_collectd);
+#else
+       char *argv = "";
+#endif
+       
+       Py_Initialize();
+       
+       PyType_Ready(&ConfigType);
+       PyType_Ready(&PluginDataType);
+       ValuesType.tp_base = &PluginDataType;
+       PyType_Ready(&ValuesType);
+       NotificationType.tp_base = &PluginDataType;
+       PyType_Ready(&NotificationType);
+       SignedType.tp_base = &PyLong_Type;
+       PyType_Ready(&SignedType);
+       UnsignedType.tp_base = &PyLong_Type;
+       PyType_Ready(&UnsignedType);
+       sys = PyImport_ImportModule("sys"); /* New reference. */
+       if (sys == NULL) {
+               cpy_log_exception("python initialization");
+               return 1;
+       }
+       sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
+       Py_DECREF(sys);
+       if (sys_path == NULL) {
+               cpy_log_exception("python initialization");
+               return 1;
+       }
+       PySys_SetArgv(1, &argv);
+       PyList_SetSlice(sys_path, 0, 1, NULL);
+
+#ifdef IS_PY3K
+       module = PyImport_ImportModule("collectd");
+#else
+       module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
+#endif
+       PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
+       PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
+       PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
+       PyModule_AddObject(module, "Signed", (void *) &SignedType); /* Steals a reference. */
+       PyModule_AddObject(module, "Unsigned", (void *) &UnsignedType); /* Steals a reference. */
+       PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
+       PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
+       PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
+       PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
+       PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
+       PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
+       PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
+       PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
+       PyModule_AddStringConstant(module, "DS_TYPE_COUNTER", DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
+       PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
+       PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
+       PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
+       return 0;
+}
+
+static int cpy_config(oconfig_item_t *ci) {
+       int i;
+       PyObject *tb;
+
+       /* Ok in theory we shouldn't do initialization at this point
+        * but we have to. In order to give python scripts a chance
+        * to register a config callback we need to be able to execute
+        * python code during the config callback so we have to start
+        * the interpreter here. */
+       /* Do *not* use the python "thread" module at this point! */
+
+       if (!Py_IsInitialized() && cpy_init_python()) return 1;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *item = ci->children + i;
+               
+               if (strcasecmp(item->key, "Interactive") == 0) {
+                       if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+                               continue;
+                       do_interactive = item->values[0].value.boolean;
+               } else if (strcasecmp(item->key, "Encoding") == 0) {
+                       if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
+                               continue;
+#ifdef IS_PY3K
+                       NOTICE("python: \"Encoding\" was used in the config file but Python3 was used, which does not support changing encodings. Ignoring this.");
+#else
+                       /* Why is this even necessary? And undocumented? */
+                       if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
+                               cpy_log_exception("setting default encoding");
+#endif
+               } else if (strcasecmp(item->key, "LogTraces") == 0) {
+                       if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+                               continue;
+                       if (!item->values[0].value.boolean) {
+                               Py_XDECREF(cpy_format_exception);
+                               cpy_format_exception = NULL;
+                               continue;
+                       }
+                       if (cpy_format_exception)
+                               continue;
+                       tb = PyImport_ImportModule("traceback"); /* New reference. */
+                       if (tb == NULL) {
+                               cpy_log_exception("python initialization");
+                               continue;
+                       }
+                       cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
+                       Py_DECREF(tb);
+                       if (cpy_format_exception == NULL)
+                               cpy_log_exception("python initialization");
+               } else if (strcasecmp(item->key, "ModulePath") == 0) {
+                       char *dir = NULL;
+                       PyObject *dir_object;
+                       
+                       if (cf_util_get_string(item, &dir) != 0) 
+                               continue;
+                       dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
+                       if (dir_object == NULL) {
+                               ERROR("python plugin: Unable to convert \"%s\" to "
+                                     "a python object.", dir);
+                               free(dir);
+                               cpy_log_exception("python initialization");
+                               continue;
+                       }
+                       if (PyList_Insert(sys_path, 0, dir_object) != 0) {
+                               ERROR("python plugin: Unable to prepend \"%s\" to "
+                                     "python module path.", dir);
+                               cpy_log_exception("python initialization");
+                       }
+                       Py_DECREF(dir_object);
+                       free(dir);
+               } else if (strcasecmp(item->key, "Import") == 0) {
+                       char *module_name = NULL;
+                       PyObject *module;
+                       
+                       if (cf_util_get_string(item, &module_name) != 0) 
+                               continue;
+                       module = PyImport_ImportModule(module_name); /* New reference. */
+                       if (module == NULL) {
+                               ERROR("python plugin: Error importing module \"%s\".", module_name);
+                               cpy_log_exception("importing module");
+                       }
+                       free(module_name);
+                       Py_XDECREF(module);
+               } else if (strcasecmp(item->key, "Module") == 0) {
+                       char *name = NULL;
+                       cpy_callback_t *c;
+                       PyObject *ret;
+                       
+                       if (cf_util_get_string(item, &name) != 0)
+                               continue;
+                       for (c = cpy_config_callbacks; c; c = c->next) {
+                               if (strcasecmp(c->name + 7, name) == 0)
+                                       break;
+                       }
+                       if (c == NULL) {
+                               WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
+                                       "but the plugin isn't loaded or didn't register "
+                                       "a configuration callback.", name);
+                               free(name);
+                               continue;
+                       }
+                       free(name);
+                       if (c->data == NULL)
+                               ret = PyObject_CallFunction(c->callback, "N",
+                                       cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
+                       else
+                               ret = PyObject_CallFunction(c->callback, "NO",
+                                       cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
+                       if (ret == NULL)
+                               cpy_log_exception("loading module");
+                       else
+                               Py_DECREF(ret);
+               } else {
+                       WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
+               }
+       }
+       return 0;
+}
+
+void module_register(void) {
+       plugin_register_complex_config("python", cpy_config);
+       plugin_register_init("python", cpy_init);
+       plugin_register_shutdown("python", cpy_shutdown);
+}
diff --git a/src/pyvalues.c b/src/pyvalues.c
new file mode 100644 (file)
index 0000000..78e6cf9
--- /dev/null
@@ -0,0 +1,1100 @@
+/**
+ * collectd - src/pyvalues.c
+ * Copyright (C) 2009  Sven Trenkel
+ *
+ * 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:
+ *   Sven Trenkel <collectd at semidefinite.de>  
+ **/
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "collectd.h"
+#include "common.h"
+
+#include "cpython.h"
+
+#define FreeAll() do {\
+       PyMem_Free(type);\
+       PyMem_Free(plugin_instance);\
+       PyMem_Free(type_instance);\
+       PyMem_Free(plugin);\
+       PyMem_Free(host);\
+} while(0)
+
+static PyObject *cpy_common_repr(PyObject *s) {
+       PyObject *ret, *tmp;
+       static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL, *l_plugin_instance = NULL;
+       static PyObject *l_host = NULL, *l_time = NULL;
+       PluginData *self = (PluginData *) s;
+       
+       if (l_type == NULL)
+               l_type = cpy_string_to_unicode_or_bytes("(type=");
+       if (l_type_instance == NULL)
+               l_type_instance = cpy_string_to_unicode_or_bytes(",type_instance=");
+       if (l_plugin == NULL)
+               l_plugin = cpy_string_to_unicode_or_bytes(",plugin=");
+       if (l_plugin_instance == NULL)
+               l_plugin_instance = cpy_string_to_unicode_or_bytes(",plugin_instance=");
+       if (l_host == NULL)
+               l_host = cpy_string_to_unicode_or_bytes(",host=");
+       if (l_time == NULL)
+               l_time = cpy_string_to_unicode_or_bytes(",time=");
+       
+       if (!l_type || !l_type_instance || !l_plugin || !l_plugin_instance || !l_host || !l_time)
+               return NULL;
+       
+       ret = cpy_string_to_unicode_or_bytes(s->ob_type->tp_name);
+
+       CPY_STRCAT(&ret, l_type);
+       tmp = cpy_string_to_unicode_or_bytes(self->type);
+       CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+       CPY_STRCAT_AND_DEL(&ret, tmp);
+
+       if (self->type_instance[0] != 0) {
+               CPY_STRCAT(&ret, l_type_instance);
+               tmp = cpy_string_to_unicode_or_bytes(self->type_instance);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+
+       if (self->plugin[0] != 0) {
+               CPY_STRCAT(&ret, l_plugin);
+               tmp = cpy_string_to_unicode_or_bytes(self->plugin);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+
+       if (self->plugin_instance[0] != 0) {
+               CPY_STRCAT(&ret, l_plugin_instance);
+               tmp = cpy_string_to_unicode_or_bytes(self->plugin_instance);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+
+       if (self->host[0] != 0) {
+               CPY_STRCAT(&ret, l_host);
+               tmp = cpy_string_to_unicode_or_bytes(self->host);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+
+       if (self->time != 0) {
+               CPY_STRCAT(&ret, l_time);
+               tmp = PyFloat_FromDouble(self->time);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+       return ret;
+}
+
+static char time_doc[] = "This is the Unix timestap of the time this value was read.\n"
+               "For dispatching values this can be set to 0 which means \"now\".\n"
+               "This means the time the value is actually dispatched, not the time\n"
+               "it was set to 0.";
+
+static char host_doc[] = "The hostname of the host this value was read from.\n"
+               "For dispatching this can be set to an empty string which means\n"
+               "the local hostname as defined in the collectd.conf.";
+
+static char type_doc[] = "The type of this value. This type has to be defined\n"
+               "in your types.db. Attempting to set it to any other value will\n"
+               "raise a TypeError exception.\n"
+               "Assigning a type is mandetory, calling dispatch without doing\n"
+               "so will raise a RuntimeError exception.";
+
+static char type_instance_doc[] = "";
+
+static char plugin_doc[] = "The name of the plugin that read the data. Setting this\n"
+               "member to an empty string will insert \"python\" upon dispatching.";
+
+static char plugin_instance_doc[] = "";
+
+static char PluginData_doc[] = "This is an internal class that is the base for Values\n"
+               "and Notification. It is pretty useless by itself and was therefore not\n"
+               "exported to the collectd module.";
+
+static PyObject *PluginData_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+       PluginData *self;
+       
+       self = (PluginData *) type->tp_alloc(type, 0);
+       if (self == NULL)
+               return NULL;
+       
+       self->time = 0;
+       self->host[0] = 0;
+       self->plugin[0] = 0;
+       self->plugin_instance[0] = 0;
+       self->type[0] = 0;
+       self->type_instance[0] = 0;
+       return (PyObject *) self;
+}
+
+static int PluginData_init(PyObject *s, PyObject *args, PyObject *kwds) {
+       PluginData *self = (PluginData *) s;
+       double time = 0;
+       char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
+       static char *kwlist[] = {"type", "plugin_instance", "type_instance",
+                       "plugin", "host", "time", NULL};
+       
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetd", kwlist, NULL, &type,
+                       NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time))
+               return -1;
+       
+       if (type && plugin_get_ds(type) == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
+               FreeAll();
+               return -1;
+       }
+
+       sstrncpy(self->host, host ? host : "", sizeof(self->host));
+       sstrncpy(self->plugin, plugin ? plugin : "", sizeof(self->plugin));
+       sstrncpy(self->plugin_instance, plugin_instance ? plugin_instance : "", sizeof(self->plugin_instance));
+       sstrncpy(self->type, type ? type : "", sizeof(self->type));
+       sstrncpy(self->type_instance, type_instance ? type_instance : "", sizeof(self->type_instance));
+       self->time = time;
+
+       FreeAll();
+
+       return 0;
+}
+
+static PyObject *PluginData_repr(PyObject *s) {
+       PyObject *ret;
+       static PyObject *l_closing = NULL;
+       
+       if (l_closing == NULL)
+               l_closing = cpy_string_to_unicode_or_bytes(")");
+       
+       if (l_closing == NULL)
+               return NULL;
+       
+       ret = cpy_common_repr(s);
+       CPY_STRCAT(&ret, l_closing);
+       return ret;
+}
+
+static PyMemberDef PluginData_members[] = {
+       {"time", T_DOUBLE, offsetof(PluginData, time), 0, time_doc},
+       {NULL}
+};
+
+static PyObject *PluginData_getstring(PyObject *self, void *data) {
+       const char *value = ((char *) self) + (intptr_t) data;
+       
+       return cpy_string_to_unicode_or_bytes(value);
+}
+
+static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
+       char *old;
+       const char *new;
+       
+       if (value == NULL) {
+               PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
+               return -1;
+       }
+       Py_INCREF(value);
+       new = cpy_unicode_or_bytes_to_string(&value);
+       if (new == NULL) {
+               Py_DECREF(value);
+               return -1;
+       }
+       old = ((char *) self) + (intptr_t) data;
+       sstrncpy(old, new, DATA_MAX_NAME_LEN);
+       Py_DECREF(value);
+       return 0;
+}
+
+static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
+       char *old;
+       const char *new;
+       
+       if (value == NULL) {
+               PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
+               return -1;
+       }
+       Py_INCREF(value);
+       new = cpy_unicode_or_bytes_to_string(&value);
+       if (new == NULL) {
+               Py_DECREF(value);
+               return -1;
+       }
+
+       if (plugin_get_ds(new) == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", new);
+               Py_DECREF(value);
+               return -1;
+       }
+
+       old = ((char *) self) + (intptr_t) data;
+       sstrncpy(old, new, DATA_MAX_NAME_LEN);
+       Py_DECREF(value);
+       return 0;
+}
+
+static PyGetSetDef PluginData_getseters[] = {
+       {"host", PluginData_getstring, PluginData_setstring, host_doc, (void *) offsetof(PluginData, host)},
+       {"plugin", PluginData_getstring, PluginData_setstring, plugin_doc, (void *) offsetof(PluginData, plugin)},
+       {"plugin_instance", PluginData_getstring, PluginData_setstring, plugin_instance_doc, (void *) offsetof(PluginData, plugin_instance)},
+       {"type_instance", PluginData_getstring, PluginData_setstring, type_instance_doc, (void *) offsetof(PluginData, type_instance)},
+       {"type", PluginData_getstring, PluginData_settype, type_doc, (void *) offsetof(PluginData, type)},
+       {NULL}
+};
+
+PyTypeObject PluginDataType = {
+       CPY_INIT_TYPE
+       "collectd.PluginData",     /* tp_name */
+       sizeof(PluginData),        /* tp_basicsize */
+       0,                         /* Will be filled in later */
+       0,                         /* tp_dealloc */
+       0,                         /* tp_print */
+       0,                         /* tp_getattr */
+       0,                         /* tp_setattr */
+       0,                         /* tp_compare */
+       PluginData_repr,           /* tp_repr */
+       0,                         /* tp_as_number */
+       0,                         /* tp_as_sequence */
+       0,                         /* tp_as_mapping */
+       0,                         /* tp_hash */
+       0,                         /* tp_call */
+       0,                         /* tp_str */
+       0,                         /* tp_getattro */
+       0,                         /* tp_setattro */
+       0,                         /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE /*| Py_TPFLAGS_HAVE_GC*/, /*tp_flags*/
+       PluginData_doc,            /* tp_doc */
+       0,                         /* tp_traverse */
+       0,                         /* tp_clear */
+       0,                         /* tp_richcompare */
+       0,                         /* tp_weaklistoffset */
+       0,                         /* tp_iter */
+       0,                         /* tp_iternext */
+       0,                         /* tp_methods */
+       PluginData_members,        /* tp_members */
+       PluginData_getseters,      /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       PluginData_init,           /* tp_init */
+       0,                         /* tp_alloc */
+       PluginData_new             /* tp_new */
+};
+
+static char interval_doc[] = "The interval is the timespan in seconds between two submits for\n"
+               "the same data source. This value has to be a positive integer, so you can't\n"
+               "submit more than one value per second. If this member is set to a\n"
+               "non-positive value, the default value as specified in the config file will\n"
+               "be used (default: 10).\n"
+               "\n"
+               "If you submit values more often than the specified interval, the average\n"
+               "will be used. If you submit less values, your graphs will have gaps.";
+
+static char values_doc[] = "These are the actual values that get dispatched to collectd.\n"
+               "It has to be a sequence (a tuple or list) of numbers.\n"
+               "The size of the sequence and the type of its content depend on the type\n"
+               "member your types.db file. For more information on this read the types.db\n"
+               "man page.\n"
+               "\n"
+               "If the sequence does not have the correct size upon dispatch a RuntimeError\n"
+               "exception will be raised. If the content of the sequence is not a number,\n"
+               "a TypeError exception will be raised.";
+
+static char meta_doc[] = "These are the meta data for this Value object.\n"
+               "It has to be a dictionary of numbers, strings or bools. All keys must be\n"
+               "strings. int and long objects will be dispatched as signed integers unless\n"
+               "they are between 2**63 and 2**64-1, which will result in a unsigned integer.\n"
+               "You can force one of these storage classes by using the classes\n"
+               "collectd.Signed and collectd.Unsigned. A meta object received by a write\n"
+               "callback will always contain Signed or Unsigned objects.";
+
+static char dispatch_doc[] = "dispatch([type][, values][, plugin_instance][, type_instance]"
+               "[, plugin][, host][, time][, interval]) -> None.  Dispatch a value list.\n"
+               "\n"
+               "Dispatch this instance to the collectd process. The object has members\n"
+               "for each of the possible arguments for this method. For a detailed explanation\n"
+               "of these parameters see the member of the same same.\n"
+               "\n"
+               "If you do not submit a parameter the value saved in its member will be submitted.\n"
+               "If you do provide a parameter it will be used instead, without altering the member.";
+
+static char write_doc[] = "write([destination][, type][, values][, plugin_instance][, type_instance]"
+               "[, plugin][, host][, time][, interval]) -> None.  Dispatch a value list.\n"
+               "\n"
+               "Write this instance to a single plugin or all plugins if 'destination' is obmitted.\n"
+               "This will bypass the main collectd process and all filtering and caching.\n"
+               "Other than that it works similar to 'dispatch'. In most cases 'dispatch' should be\n"
+               "used instead of 'write'.\n";
+
+static char Values_doc[] = "A Values object used for dispatching values to collectd and receiving values from write callbacks.";
+
+static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+       Values *self;
+       
+       self = (Values *) PluginData_new(type, args, kwds);
+       if (self == NULL)
+               return NULL;
+       
+       self->values = PyList_New(0);
+       self->meta = PyDict_New();
+       self->interval = 0;
+       return (PyObject *) self;
+}
+
+static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
+       Values *self = (Values *) s;
+       double interval = 0, time = 0;
+       PyObject *values = NULL, *meta = NULL, *tmp;
+       char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
+       static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
+                       "plugin", "host", "time", "interval", "meta", NULL};
+       
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
+                       NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
+                       NULL, &plugin, NULL, &host, &time, &interval, &meta))
+               return -1;
+       
+       if (type && plugin_get_ds(type) == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
+               FreeAll();
+               return -1;
+       }
+
+       sstrncpy(self->data.host, host ? host : "", sizeof(self->data.host));
+       sstrncpy(self->data.plugin, plugin ? plugin : "", sizeof(self->data.plugin));
+       sstrncpy(self->data.plugin_instance, plugin_instance ? plugin_instance : "", sizeof(self->data.plugin_instance));
+       sstrncpy(self->data.type, type ? type : "", sizeof(self->data.type));
+       sstrncpy(self->data.type_instance, type_instance ? type_instance : "", sizeof(self->data.type_instance));
+       self->data.time = time;
+
+       FreeAll();
+
+       if (values == NULL) {
+               values = PyList_New(0);
+               PyErr_Clear();
+       } else {
+               Py_INCREF(values);
+       }
+       
+       if (meta == NULL) {
+               meta = PyDict_New();
+               PyErr_Clear();
+       } else {
+               Py_INCREF(meta);
+       }
+       
+       tmp = self->values;
+       self->values = values;
+       Py_XDECREF(tmp);
+       
+       tmp = self->meta;
+       self->meta = meta;
+       Py_XDECREF(tmp);
+
+       self->interval = interval;
+       return 0;
+}
+
+static meta_data_t *cpy_build_meta(PyObject *meta) {
+       int i, s;
+       meta_data_t *m = NULL;
+       PyObject *l;
+       
+       if ((meta == NULL) || (meta == Py_None))
+               return NULL;
+
+       l = PyDict_Items(meta); /* New reference. */
+       if (!l) {
+               cpy_log_exception("building meta data");
+               return NULL;
+       }
+       s = PyList_Size(l);
+       if (s <= 0) {
+               Py_XDECREF(l);
+               return NULL;
+       }
+
+       m = meta_data_create();
+       for (i = 0; i < s; ++i) {
+               const char *string, *keystring;
+               PyObject *key, *value, *item, *tmp;
+               
+               item = PyList_GET_ITEM(l, i);
+               key = PyTuple_GET_ITEM(item, 0);
+               Py_INCREF(key);
+               keystring = cpy_unicode_or_bytes_to_string(&key);
+               if (!keystring) {
+                       PyErr_Clear();
+                       Py_XDECREF(key);
+                       continue;
+               }
+               value = PyTuple_GET_ITEM(item, 1);
+               Py_INCREF(value);
+               if (value == Py_True) {
+                       meta_data_add_boolean(m, keystring, 1);
+               } else if (value == Py_False) {
+                       meta_data_add_boolean(m, keystring, 0);
+               } else if (PyFloat_Check(value)) {
+                       meta_data_add_double(m, keystring, PyFloat_AsDouble(value));
+               } else if (PyObject_TypeCheck(value, &SignedType)) {
+                       long long int lli;
+                       lli = PyLong_AsLongLong(value);
+                       if (!PyErr_Occurred() && (lli == (int64_t) lli))
+                               meta_data_add_signed_int(m, keystring, lli);
+               } else if (PyObject_TypeCheck(value, &UnsignedType)) {
+                       long long unsigned llu;
+                       llu = PyLong_AsUnsignedLongLong(value);
+                       if (!PyErr_Occurred() && (llu == (uint64_t) llu))
+                               meta_data_add_unsigned_int(m, keystring, llu);
+               } else if (PyNumber_Check(value)) {
+                       long long int lli;
+                       long long unsigned llu;
+                       tmp = PyNumber_Long(value);
+                       lli = PyLong_AsLongLong(tmp);
+                       if (!PyErr_Occurred() && (lli == (int64_t) lli)) {
+                               meta_data_add_signed_int(m, keystring, lli);
+                       } else {
+                               PyErr_Clear();
+                               llu = PyLong_AsUnsignedLongLong(tmp);
+                               if (!PyErr_Occurred() && (llu == (uint64_t) llu))
+                                       meta_data_add_unsigned_int(m, keystring, llu);
+                       }
+                       Py_XDECREF(tmp);
+               } else {
+                       string = cpy_unicode_or_bytes_to_string(&value);
+                       if (string) {
+                               meta_data_add_string(m, keystring, string);
+                       } else {
+                               PyErr_Clear();
+                               tmp = PyObject_Str(value);
+                               string = cpy_unicode_or_bytes_to_string(&tmp);
+                               if (string)
+                                       meta_data_add_string(m, keystring, string);
+                               Py_XDECREF(tmp);
+                       }
+               }
+               if (PyErr_Occurred())
+                       cpy_log_exception("building meta data");
+               Py_XDECREF(value);
+               Py_DECREF(key);
+       }
+       Py_XDECREF(l);
+       return m;
+}
+
+static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
+       int i, ret;
+       const data_set_t *ds;
+       int size;
+       value_t *value;
+       value_list_t value_list = VALUE_LIST_INIT;
+       PyObject *values = self->values, *meta = self->meta;
+       double time = self->data.time, interval = self->interval;
+       char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
+       
+       static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
+                       "plugin", "host", "time", "interval", "meta", NULL};
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
+                       NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
+                       NULL, &plugin, NULL, &host, &time, &interval, &meta))
+               return NULL;
+
+       sstrncpy(value_list.host, host ? host : self->data.host, sizeof(value_list.host));
+       sstrncpy(value_list.plugin, plugin ? plugin : self->data.plugin, sizeof(value_list.plugin));
+       sstrncpy(value_list.plugin_instance, plugin_instance ? plugin_instance : self->data.plugin_instance, sizeof(value_list.plugin_instance));
+       sstrncpy(value_list.type, type ? type : self->data.type, sizeof(value_list.type));
+       sstrncpy(value_list.type_instance, type_instance ? type_instance : self->data.type_instance, sizeof(value_list.type_instance));
+       FreeAll();
+       if (value_list.type[0] == 0) {
+               PyErr_SetString(PyExc_RuntimeError, "type not set");
+               FreeAll();
+               return NULL;
+       }
+       ds = plugin_get_ds(value_list.type);
+       if (ds == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", value_list.type);
+               return NULL;
+       }
+       if (values == NULL || (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
+               PyErr_Format(PyExc_TypeError, "values must be list or tuple");
+               return NULL;
+       }
+       if (meta != NULL && meta != Py_None && !PyDict_Check(meta)) {
+               PyErr_Format(PyExc_TypeError, "meta must be a dict");
+               return NULL;
+       }
+       size = (int) PySequence_Length(values);
+       if (size != ds->ds_num) {
+               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+               return NULL;
+       }
+       value = malloc(size * sizeof(*value));
+       for (i = 0; i < size; ++i) {
+               PyObject *item, *num;
+               item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
+               if (ds->ds->type == DS_TYPE_COUNTER) {
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].counter = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
+               } else if (ds->ds->type == DS_TYPE_GAUGE) {
+                       num = PyNumber_Float(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].gauge = PyFloat_AsDouble(num);
+                               Py_XDECREF(num);
+                       }
+               } else if (ds->ds->type == DS_TYPE_DERIVE) {
+                       /* This might overflow without raising an exception.
+                        * Not much we can do about it */
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].derive = PyLong_AsLongLong(num);
+                               Py_XDECREF(num);
+                       }
+               } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
+                       /* This might overflow without raising an exception.
+                        * Not much we can do about it */
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].absolute = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
+               } else {
+                       free(value);
+                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, value_list.type);
+                       return NULL;
+               }
+               if (PyErr_Occurred() != NULL) {
+                       free(value);
+                       return NULL;
+               }
+       }
+       value_list.values = value;
+       value_list.meta = cpy_build_meta(meta);
+       value_list.values_len = size;
+       value_list.time = DOUBLE_TO_CDTIME_T(time);
+       value_list.interval = DOUBLE_TO_CDTIME_T(interval);
+       if (value_list.host[0] == 0)
+               sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
+       if (value_list.plugin[0] == 0)
+               sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
+       Py_BEGIN_ALLOW_THREADS;
+       ret = plugin_dispatch_values(&value_list);
+       Py_END_ALLOW_THREADS;
+       meta_data_destroy(value_list.meta);
+       free(value);
+       if (ret != 0) {
+               PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
+               return NULL;
+       }
+       Py_RETURN_NONE;
+}
+
+static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
+       int i, ret;
+       const data_set_t *ds;
+       int size;
+       value_t *value;
+       value_list_t value_list = VALUE_LIST_INIT;
+       PyObject *values = self->values, *meta = self->meta;
+       double time = self->data.time, interval = self->interval;
+       char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL, *dest = NULL;
+       
+       static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
+                       "plugin", "host", "time", "interval", "meta", NULL};
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|etOetetetetdiO", kwlist, NULL, &dest,
+                       NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
+                       NULL, &plugin, NULL, &host, &time, &interval, &meta))
+               return NULL;
+
+       sstrncpy(value_list.host, host ? host : self->data.host, sizeof(value_list.host));
+       sstrncpy(value_list.plugin, plugin ? plugin : self->data.plugin, sizeof(value_list.plugin));
+       sstrncpy(value_list.plugin_instance, plugin_instance ? plugin_instance : self->data.plugin_instance, sizeof(value_list.plugin_instance));
+       sstrncpy(value_list.type, type ? type : self->data.type, sizeof(value_list.type));
+       sstrncpy(value_list.type_instance, type_instance ? type_instance : self->data.type_instance, sizeof(value_list.type_instance));
+       FreeAll();
+       if (value_list.type[0] == 0) {
+               PyErr_SetString(PyExc_RuntimeError, "type not set");
+               return NULL;
+       }
+       ds = plugin_get_ds(value_list.type);
+       if (ds == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", value_list.type);
+               return NULL;
+       }
+       if (values == NULL || (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
+               PyErr_Format(PyExc_TypeError, "values must be list or tuple");
+               return NULL;
+       }
+       size = (int) PySequence_Length(values);
+       if (size != ds->ds_num) {
+               PyErr_Format(PyExc_RuntimeError, "type %s needs %d values, got %i", value_list.type, ds->ds_num, size);
+               return NULL;
+       }
+       value = malloc(size * sizeof(*value));
+       for (i = 0; i < size; ++i) {
+               PyObject *item, *num;
+               item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
+               if (ds->ds->type == DS_TYPE_COUNTER) {
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].counter = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
+               } else if (ds->ds->type == DS_TYPE_GAUGE) {
+                       num = PyNumber_Float(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].gauge = PyFloat_AsDouble(num);
+                               Py_XDECREF(num);
+                       }
+               } else if (ds->ds->type == DS_TYPE_DERIVE) {
+                       /* This might overflow without raising an exception.
+                        * Not much we can do about it */
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].derive = PyLong_AsLongLong(num);
+                               Py_XDECREF(num);
+                       }
+               } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
+                       /* This might overflow without raising an exception.
+                        * Not much we can do about it */
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
+                               value[i].absolute = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
+               } else {
+                       free(value);
+                       PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, value_list.type);
+                       return NULL;
+               }
+               if (PyErr_Occurred() != NULL) {
+                       free(value);
+                       return NULL;
+               }
+       }
+       value_list.values = value;
+       value_list.values_len = size;
+       value_list.time = DOUBLE_TO_CDTIME_T(time);
+       value_list.interval = DOUBLE_TO_CDTIME_T(interval);
+       value_list.meta = cpy_build_meta(meta);;
+       if (value_list.host[0] == 0)
+               sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
+       if (value_list.plugin[0] == 0)
+               sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
+       Py_BEGIN_ALLOW_THREADS;
+       ret = plugin_write(dest, NULL, &value_list);
+       Py_END_ALLOW_THREADS;
+       meta_data_destroy(value_list.meta);
+       free(value);
+       if (ret != 0) {
+               PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
+               return NULL;
+       }
+       Py_RETURN_NONE;
+}
+
+static PyObject *Values_repr(PyObject *s) {
+       PyObject *ret, *tmp;
+       static PyObject *l_interval = NULL, *l_values = NULL, *l_meta = NULL, *l_closing = NULL;
+       Values *self = (Values *) s;
+       
+       if (l_interval == NULL)
+               l_interval = cpy_string_to_unicode_or_bytes(",interval=");
+       if (l_values == NULL)
+               l_values = cpy_string_to_unicode_or_bytes(",values=");
+       if (l_meta == NULL)
+               l_meta = cpy_string_to_unicode_or_bytes(",meta=");
+       if (l_closing == NULL)
+               l_closing = cpy_string_to_unicode_or_bytes(")");
+       
+       if (l_interval == NULL || l_values == NULL || l_meta == NULL || l_closing == NULL)
+               return NULL;
+       
+       ret = cpy_common_repr(s);
+       if (self->interval != 0) {
+               CPY_STRCAT(&ret, l_interval);
+               tmp = PyFloat_FromDouble(self->interval);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+       if (self->values && (!PyList_Check(self->values) || PySequence_Length(self->values) > 0)) {
+               CPY_STRCAT(&ret, l_values);
+               tmp = PyObject_Repr(self->values);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+       if (self->meta && (!PyDict_Check(self->meta) || PyDict_Size(self->meta) > 0)) {
+               CPY_STRCAT(&ret, l_meta);
+               tmp = PyObject_Repr(self->meta);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+       CPY_STRCAT(&ret, l_closing);
+       return ret;
+}
+
+static int Values_traverse(PyObject *self, visitproc visit, void *arg) {
+       Values *v = (Values *) self;
+       Py_VISIT(v->values);
+       Py_VISIT(v->meta);
+       return 0;
+}
+
+static int Values_clear(PyObject *self) {
+       Values *v = (Values *) self;
+       Py_CLEAR(v->values);
+       Py_CLEAR(v->meta);
+       return 0;
+}
+
+static void Values_dealloc(PyObject *self) {
+       Values_clear(self);
+       self->ob_type->tp_free(self);
+}
+
+static PyMemberDef Values_members[] = {
+       {"interval", T_DOUBLE, offsetof(Values, interval), 0, interval_doc},
+       {"values", T_OBJECT_EX, offsetof(Values, values), 0, values_doc},
+       {"meta", T_OBJECT_EX, offsetof(Values, meta), 0, meta_doc},
+       {NULL}
+};
+
+static PyMethodDef Values_methods[] = {
+       {"dispatch", (PyCFunction) Values_dispatch, METH_VARARGS | METH_KEYWORDS, dispatch_doc},
+       {"write", (PyCFunction) Values_write, METH_VARARGS | METH_KEYWORDS, write_doc},
+       {NULL}
+};
+
+PyTypeObject ValuesType = {
+       CPY_INIT_TYPE
+       "collectd.Values",         /* tp_name */
+       sizeof(Values),            /* tp_basicsize */
+       0,                         /* Will be filled in later */
+       Values_dealloc,            /* tp_dealloc */
+       0,                         /* tp_print */
+       0,                         /* tp_getattr */
+       0,                         /* tp_setattr */
+       0,                         /* tp_compare */
+       Values_repr,               /* tp_repr */
+       0,                         /* tp_as_number */
+       0,                         /* tp_as_sequence */
+       0,                         /* tp_as_mapping */
+       0,                         /* tp_hash */
+       0,                         /* tp_call */
+       0,                         /* tp_str */
+       0,                         /* tp_getattro */
+       0,                         /* tp_setattro */
+       0,                         /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+       Values_doc,                /* tp_doc */
+       Values_traverse,           /* tp_traverse */
+       Values_clear,              /* tp_clear */
+       0,                         /* tp_richcompare */
+       0,                         /* tp_weaklistoffset */
+       0,                         /* tp_iter */
+       0,                         /* tp_iternext */
+       Values_methods,            /* tp_methods */
+       Values_members,            /* tp_members */
+       0,                         /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       Values_init,               /* tp_init */
+       0,                         /* tp_alloc */
+       Values_new                 /* tp_new */
+};
+
+static char severity_doc[] = "The severity of this notification. Assign or compare to\n"
+               "NOTIF_FAILURE, NOTIF_WARNING or NOTIF_OKAY.";
+
+static char message_doc[] = "Some kind of description what's going on and why this Notification was generated.";
+
+static char Notification_doc[] = "The Notification class is a wrapper around the collectd notification.\n"
+               "It can be used to notify other plugins about bad stuff happening. It works\n"
+               "similar to Values but has a severity and a message instead of interval\n"
+               "and time.\n"
+               "Notifications can be dispatched at any time and can be received with register_notification.";
+
+static int Notification_init(PyObject *s, PyObject *args, PyObject *kwds) {
+       Notification *self = (Notification *) s;
+       int severity = 0;
+       double time = 0;
+       char *message = NULL;
+       char *type = NULL, *plugin_instance = NULL, *type_instance = NULL, *plugin = NULL, *host = NULL;
+       static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
+                       "plugin", "host", "time", "severity", NULL};
+       
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
+                       NULL, &type, NULL, &message, NULL, &plugin_instance, NULL, &type_instance,
+                       NULL, &plugin, NULL, &host, &time, &severity))
+               return -1;
+       
+       if (type && plugin_get_ds(type) == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
+               FreeAll();
+               PyMem_Free(message);
+               return -1;
+       }
+
+       sstrncpy(self->data.host, host ? host : "", sizeof(self->data.host));
+       sstrncpy(self->data.plugin, plugin ? plugin : "", sizeof(self->data.plugin));
+       sstrncpy(self->data.plugin_instance, plugin_instance ? plugin_instance : "", sizeof(self->data.plugin_instance));
+       sstrncpy(self->data.type, type ? type : "", sizeof(self->data.type));
+       sstrncpy(self->data.type_instance, type_instance ? type_instance : "", sizeof(self->data.type_instance));
+       sstrncpy(self->message, message ? message : "", sizeof(self->message));
+       self->data.time = time;
+       self->severity = severity;
+
+       FreeAll();
+       PyMem_Free(message);
+       return 0;
+}
+
+static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObject *kwds) {
+       int ret;
+       const data_set_t *ds;
+       notification_t notification;
+       double t = self->data.time;
+       int severity = self->severity;
+       char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL, *type_instance = NULL;
+       char *message = NULL;
+       
+       static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
+                       "plugin", "host", "time", "severity", NULL};
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
+                       NULL, &type, NULL, &message, NULL, &plugin_instance, NULL, &type_instance,
+                       NULL, &plugin, NULL, &host, &t, &severity))
+               return NULL;
+
+       notification.time = DOUBLE_TO_CDTIME_T(t);
+       notification.severity = severity;
+       sstrncpy(notification.message, message ? message : self->message, sizeof(notification.message));
+       sstrncpy(notification.host, host ? host : self->data.host, sizeof(notification.host));
+       sstrncpy(notification.plugin, plugin ? plugin : self->data.plugin, sizeof(notification.plugin));
+       sstrncpy(notification.plugin_instance, plugin_instance ? plugin_instance : self->data.plugin_instance, sizeof(notification.plugin_instance));
+       sstrncpy(notification.type, type ? type : self->data.type, sizeof(notification.type));
+       sstrncpy(notification.type_instance, type_instance ? type_instance : self->data.type_instance, sizeof(notification.type_instance));
+       notification.meta = NULL;
+       FreeAll();
+       PyMem_Free(message);
+
+       if (notification.type[0] == 0) {
+               PyErr_SetString(PyExc_RuntimeError, "type not set");
+               return NULL;
+       }
+       ds = plugin_get_ds(notification.type);
+       if (ds == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", notification.type);
+               return NULL;
+       }
+
+       if (notification.time == 0)
+               notification.time = cdtime();
+       if (notification.host[0] == 0)
+               sstrncpy(notification.host, hostname_g, sizeof(notification.host));
+       if (notification.plugin[0] == 0)
+               sstrncpy(notification.plugin, "python", sizeof(notification.plugin));
+       Py_BEGIN_ALLOW_THREADS;
+       ret = plugin_dispatch_notification(&notification);
+       Py_END_ALLOW_THREADS;
+       if (ret != 0) {
+               PyErr_SetString(PyExc_RuntimeError, "error dispatching notification, read the logs");
+               return NULL;
+       }
+       Py_RETURN_NONE;
+}
+
+static PyObject *Notification_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+       Notification *self;
+       
+       self = (Notification *) PluginData_new(type, args, kwds);
+       if (self == NULL)
+               return NULL;
+       
+       self->message[0] = 0;
+       self->severity = 0;
+       return (PyObject *) self;
+}
+
+static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
+       char *old;
+       const char *new;
+       
+       if (value == NULL) {
+               PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
+               return -1;
+       }
+       Py_INCREF(value);
+       new = cpy_unicode_or_bytes_to_string(&value);
+       if (new == NULL) {
+               Py_DECREF(value);
+               return -1;
+       }
+       old = ((char *) self) + (intptr_t) data;
+       sstrncpy(old, new, NOTIF_MAX_MSG_LEN);
+       Py_DECREF(value);
+       return 0;
+}
+
+static PyObject *Notification_repr(PyObject *s) {
+       PyObject *ret, *tmp;
+       static PyObject *l_severity = NULL, *l_message = NULL, *l_closing = NULL;
+       Notification *self = (Notification *) s;
+       
+       if (l_severity == NULL)
+               l_severity = cpy_string_to_unicode_or_bytes(",severity=");
+       if (l_message == NULL)
+               l_message = cpy_string_to_unicode_or_bytes(",message=");
+       if (l_closing == NULL)
+               l_closing = cpy_string_to_unicode_or_bytes(")");
+       
+       if (l_severity == NULL || l_message == NULL || l_closing == NULL)
+               return NULL;
+       
+       ret = cpy_common_repr(s);
+       if (self->severity != 0) {
+               CPY_STRCAT(&ret, l_severity);
+               tmp = PyInt_FromLong(self->severity);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+       if (self->message[0] != 0) {
+               CPY_STRCAT(&ret, l_message);
+               tmp = cpy_string_to_unicode_or_bytes(self->message);
+               CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
+       CPY_STRCAT(&ret, l_closing);
+       return ret;
+}
+
+static PyMethodDef Notification_methods[] = {
+       {"dispatch", (PyCFunction) Notification_dispatch, METH_VARARGS | METH_KEYWORDS, dispatch_doc},
+       {NULL}
+};
+
+static PyMemberDef Notification_members[] = {
+       {"severity", T_INT, offsetof(Notification, severity), 0, severity_doc},
+       {NULL}
+};
+
+static PyGetSetDef Notification_getseters[] = {
+       {"message", PluginData_getstring, Notification_setstring, message_doc, (void *) offsetof(Notification, message)},
+       {NULL}
+};
+
+PyTypeObject NotificationType = {
+       CPY_INIT_TYPE
+       "collectd.Notification",   /* tp_name */
+       sizeof(Notification),      /* tp_basicsize */
+       0,                         /* Will be filled in later */
+       0,                         /* tp_dealloc */
+       0,                         /* tp_print */
+       0,                         /* tp_getattr */
+       0,                         /* tp_setattr */
+       0,                         /* tp_compare */
+       Notification_repr,         /* tp_repr */
+       0,                         /* tp_as_number */
+       0,                         /* tp_as_sequence */
+       0,                         /* tp_as_mapping */
+       0,                         /* tp_hash */
+       0,                         /* tp_call */
+       0,                         /* tp_str */
+       0,                         /* tp_getattro */
+       0,                         /* tp_setattro */
+       0,                         /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+       Notification_doc,          /* tp_doc */
+       0,                         /* tp_traverse */
+       0,                         /* tp_clear */
+       0,                         /* tp_richcompare */
+       0,                         /* tp_weaklistoffset */
+       0,                         /* tp_iter */
+       0,                         /* tp_iternext */
+       Notification_methods,      /* tp_methods */
+       Notification_members,      /* tp_members */
+       Notification_getseters,    /* tp_getset */
+       0,                         /* tp_base */
+       0,                         /* tp_dict */
+       0,                         /* tp_descr_get */
+       0,                         /* tp_descr_set */
+       0,                         /* tp_dictoffset */
+       Notification_init,         /* tp_init */
+       0,                         /* tp_alloc */
+       Notification_new           /* tp_new */
+};
+
+static char Signed_doc[] = "This is a long by another name. Use it in meta data dicts\n"
+               "to choose the way it is stored in the meta data.";
+
+PyTypeObject SignedType = {
+       CPY_INIT_TYPE
+       "collectd.Signed",         /* tp_name */
+       sizeof(Signed),            /* tp_basicsize */
+       0,                         /* Will be filled in later */
+       0,                         /* tp_dealloc */
+       0,                         /* tp_print */
+       0,                         /* tp_getattr */
+       0,                         /* tp_setattr */
+       0,                         /* tp_compare */
+       0,                         /* tp_repr */
+       0,                         /* tp_as_number */
+       0,                         /* tp_as_sequence */
+       0,                         /* tp_as_mapping */
+       0,                         /* tp_hash */
+       0,                         /* tp_call */
+       0,                         /* tp_str */
+       0,                         /* tp_getattro */
+       0,                         /* tp_setattro */
+       0,                         /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+       Signed_doc                 /* tp_doc */
+};
+
+static char Unsigned_doc[] = "This is a long by another name. Use it in meta data dicts\n"
+               "to choose the way it is stored in the meta data.";
+
+PyTypeObject UnsignedType = {
+       CPY_INIT_TYPE
+       "collectd.Unsigned",       /* tp_name */
+       sizeof(Unsigned),          /* tp_basicsize */
+       0,                         /* Will be filled in later */
+       0,                         /* tp_dealloc */
+       0,                         /* tp_print */
+       0,                         /* tp_getattr */
+       0,                         /* tp_setattr */
+       0,                         /* tp_compare */
+       0,                         /* tp_repr */
+       0,                         /* tp_as_number */
+       0,                         /* tp_as_sequence */
+       0,                         /* tp_as_mapping */
+       0,                         /* tp_hash */
+       0,                         /* tp_call */
+       0,                         /* tp_str */
+       0,                         /* tp_getattro */
+       0,                         /* tp_setattro */
+       0,                         /* tp_as_buffer */
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+       Unsigned_doc               /* tp_doc */
+};
diff --git a/src/redis.c b/src/redis.c
new file mode 100644 (file)
index 0000000..7864ead
--- /dev/null
@@ -0,0 +1,459 @@
+/**
+ * collectd - src/redis.c, based on src/memcached.c
+ * Copyright (C) 2010       Andrés J. Díaz <ajdiaz@connectical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Andrés J. Díaz <ajdiaz@connectical.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <hiredis/hiredis.h>
+
+#ifndef HOST_NAME_MAX
+# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
+#endif
+
+#define REDIS_DEF_HOST   "localhost"
+#define REDIS_DEF_PASSWD ""
+#define REDIS_DEF_PORT    6379
+#define REDIS_DEF_TIMEOUT 2000
+#define MAX_REDIS_NODE_NAME 64
+#define MAX_REDIS_PASSWD_LENGTH 512
+#define MAX_REDIS_VAL_SIZE 256
+#define MAX_REDIS_QUERY 2048
+
+/* Redis plugin configuration example:
+ *
+ * <Plugin redis>
+ *   <Node "mynode">
+ *     Host "localhost"
+ *     Port "6379"
+ *     Timeout 2
+ *     Password "foobar"
+ *   </Node>
+ * </Plugin>
+ */
+
+struct redis_query_s;
+typedef struct redis_query_s redis_query_t;
+struct redis_query_s
+{
+    char query[MAX_REDIS_QUERY];
+    char type[DATA_MAX_NAME_LEN];
+    char instance[DATA_MAX_NAME_LEN];
+    redis_query_t *next;
+};
+
+struct redis_node_s;
+typedef struct redis_node_s redis_node_t;
+struct redis_node_s
+{
+  char name[MAX_REDIS_NODE_NAME];
+  char host[HOST_NAME_MAX];
+  char passwd[MAX_REDIS_PASSWD_LENGTH];
+  int port;
+  struct timeval timeout;
+  redis_query_t *queries;
+
+  redis_node_t *next;
+};
+
+static redis_node_t *nodes_head = NULL;
+
+static int redis_node_add (const redis_node_t *rn) /* {{{ */
+{
+  redis_node_t *rn_copy;
+  redis_node_t *rn_ptr;
+
+  /* Check for duplicates first */
+  for (rn_ptr = nodes_head; rn_ptr != NULL; rn_ptr = rn_ptr->next)
+    if (strcmp (rn->name, rn_ptr->name) == 0)
+      break;
+
+  if (rn_ptr != NULL)
+  {
+    ERROR ("redis plugin: A node with the name `%s' already exists.",
+        rn->name);
+    return (-1);
+  }
+
+  rn_copy = malloc (sizeof (*rn_copy));
+  if (rn_copy == NULL)
+  {
+    ERROR ("redis plugin: malloc failed adding redis_node to the tree.");
+    return (-1);
+  }
+
+  memcpy (rn_copy, rn, sizeof (*rn_copy));
+  rn_copy->next = NULL;
+
+  DEBUG ("redis plugin: Adding node \"%s\".", rn->name);
+
+  if (nodes_head == NULL)
+    nodes_head = rn_copy;
+  else
+  {
+    rn_ptr = nodes_head;
+    while (rn_ptr->next != NULL)
+      rn_ptr = rn_ptr->next;
+    rn_ptr->next = rn_copy;
+  }
+
+  return (0);
+} /* }}} */
+
+static redis_query_t *redis_config_query (oconfig_item_t *ci) /* {{{ */
+{
+    redis_query_t *rq;
+    int status;
+    int i;
+
+    rq = calloc(1, sizeof(*rq));
+    if (rq == NULL) {
+        ERROR("redis plugin: calloca failed adding redis_query.");
+        return NULL;
+    }
+    status = cf_util_get_string_buffer(ci, rq->query, sizeof(rq->query));
+    if (status != 0)
+        goto err;
+
+    /*
+     * Default to a gauge type.
+     */
+    (void)strncpy(rq->type, "gauge", sizeof(rq->type));
+    (void)strncpy(rq->instance, rq->query, sizeof(rq->instance));
+    replace_special(rq->instance, sizeof(rq->instance));
+
+    for (i = 0; i < ci->children_num; i++) {
+        oconfig_item_t *option = ci->children + i;
+
+        if (strcasecmp("Type", option->key) == 0) {
+            status = cf_util_get_string_buffer(option, rq->type, sizeof(rq->type));
+        } else if (strcasecmp("Instance", option->key) == 0) {
+            status = cf_util_get_string_buffer(option, rq->instance, sizeof(rq->instance));
+        } else {
+            WARNING("redis plugin: unknown configuration option: %s", option->key);
+            status = -1;
+        }
+        if (status != 0)
+            goto err;
+    }
+    return rq;
+ err:
+    free(rq);
+    return NULL;
+} /* }}} */
+
+static int redis_config_node (oconfig_item_t *ci) /* {{{ */
+{
+  redis_node_t rn;
+  redis_query_t *rq;
+  int i;
+  int status;
+  int timeout;
+
+  memset (&rn, 0, sizeof (rn));
+  sstrncpy (rn.host, REDIS_DEF_HOST, sizeof (rn.host));
+  rn.port = REDIS_DEF_PORT;
+  rn.timeout.tv_usec = REDIS_DEF_TIMEOUT;
+  rn.queries = NULL;
+
+  status = cf_util_get_string_buffer (ci, rn.name, sizeof (rn.name));
+  if (status != 0)
+    return (status);
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if (strcasecmp ("Host", option->key) == 0)
+      status = cf_util_get_string_buffer (option, rn.host, sizeof (rn.host));
+    else if (strcasecmp ("Port", option->key) == 0)
+    {
+      status = cf_util_get_port_number (option);
+      if (status > 0)
+      {
+        rn.port = status;
+        status = 0;
+      }
+    }
+    else if (strcasecmp ("Query", option->key) == 0)
+    {
+      rq = redis_config_query(option);
+      if (rq == NULL) {
+          status =1;
+      } else {
+          rq->next = rn.queries;
+          rn.queries = rq;
+      }
+    }
+    else if (strcasecmp ("Timeout", option->key) == 0)
+    {
+      status = cf_util_get_int (option, &timeout);
+      if (status == 0) rn.timeout.tv_usec = timeout;
+    }
+    else if (strcasecmp ("Password", option->key) == 0)
+      status = cf_util_get_string_buffer (option, rn.passwd, sizeof (rn.passwd));
+    else
+      WARNING ("redis plugin: Option `%s' not allowed inside a `Node' "
+          "block. I'll ignore this option.", option->key);
+
+    if (status != 0)
+      break;
+  }
+
+  if (status != 0)
+    return (status);
+
+  return (redis_node_add (&rn));
+} /* }}} int redis_config_node */
+
+static int redis_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if (strcasecmp ("Node", option->key) == 0)
+      redis_config_node (option);
+    else
+      WARNING ("redis plugin: Option `%s' not allowed in redis"
+          " configuration. It will be ignored.", option->key);
+  }
+
+  if (nodes_head == NULL)
+  {
+    ERROR ("redis plugin: No valid node configuration could be found.");
+    return (ENOENT);
+  }
+
+  return (0);
+} /* }}} */
+
+  __attribute__ ((nonnull(2)))
+static void redis_submit (char *plugin_instance,
+    const char *type, const char *type_instance,
+    value_t value) /* {{{ */
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  values[0] = value;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "redis", sizeof (vl.plugin));
+  if (plugin_instance != NULL)
+    sstrncpy (vl.plugin_instance, plugin_instance,
+        sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance,
+        sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* }}} */
+
+static int redis_init (void) /* {{{ */
+{
+  redis_node_t rn = {
+    .name = "default",
+    .host = REDIS_DEF_HOST,
+    .port = REDIS_DEF_PORT,
+    .timeout.tv_sec = 0,
+    .timeout.tv_usec = REDIS_DEF_TIMEOUT,
+    .next = NULL
+};
+
+  if (nodes_head == NULL)
+    redis_node_add (&rn);
+
+  return (0);
+} /* }}} int redis_init */
+
+int redis_handle_info (char *node, char const *info_line, char const *type, char const *type_instance, char const *field_name, int ds_type) /* {{{ */
+{
+  char *str = strstr (info_line, field_name);
+  static char buf[MAX_REDIS_VAL_SIZE];
+  value_t val;
+  if (str)
+  {
+    int i;
+
+    str += strlen (field_name) + 1; /* also skip the ':' */
+    for(i=0;(*str && (isdigit(*str) || *str == '.'));i++,str++)
+      buf[i] = *str;
+    buf[i] ='\0';
+
+    if(parse_value (buf, &val, ds_type) == -1)
+    {
+      WARNING ("redis plugin: Unable to parse field `%s'.", field_name);
+      return (-1);
+    }
+
+    redis_submit (node, type, type_instance, val);
+    return (0);
+  }
+  return (-1);
+
+} /* }}} int redis_handle_info */
+
+int redis_handle_query (redisContext *rh, redis_node_t *rn, redis_query_t *rq) /* {{{ */
+{
+    redisReply *rr;
+    const data_set_t *ds;
+    value_t val;
+
+    ds = plugin_get_ds (rq->type);
+    if (!ds) {
+        ERROR ("redis plugin: DataSet `%s' not defined.", rq->type);
+        return (-1);
+    }
+
+    if (ds->ds_num != 1) {
+        ERROR ("redis plugin: DS `%s' has too many types.", rq->type);
+        return (-1);
+    }
+
+    if ((rr = redisCommand(rh, rq->query)) == NULL) {
+        WARNING("redis plugin: unable to carry out query `%s'.", rq->query);
+        return (-1);
+    }
+
+    switch (rr->type) {
+    case REDIS_REPLY_INTEGER:
+        switch (ds->ds[0].type) {
+        case DS_TYPE_COUNTER:
+            val.counter = (counter_t)rr->integer;
+            break;
+        case DS_TYPE_GAUGE:
+            val.gauge = (gauge_t)rr->integer;
+            break;
+        case DS_TYPE_DERIVE:
+            val.gauge = (derive_t)rr->integer;
+            break;
+        case DS_TYPE_ABSOLUTE:
+            val.gauge = (absolute_t)rr->integer;
+            break;
+        }
+        break;
+    case REDIS_REPLY_STRING:
+        if (parse_value (rr->str, &val, ds->ds[0].type) == -1) {
+            WARNING("redis plugin: Unable to parse field `%s'.", rq->type);
+            freeReplyObject (rr);
+            return (-1);
+        }
+        break;
+    default:
+        WARNING("redis plugin: Cannot coerce redis type.");
+        freeReplyObject(rr);
+        return (-1);
+    }
+
+    redis_submit(rn->name, rq->type, (strlen(rq->instance) >0)?rq->instance:NULL, val);
+    freeReplyObject (rr);
+    return 0;
+} /* }}} int redis_handle_info */
+
+static int redis_read (void) /* {{{ */
+{
+  redis_node_t *rn;
+  redis_query_t *rq;
+
+  for (rn = nodes_head; rn != NULL; rn = rn->next)
+  {
+    redisContext *rh;
+    redisReply   *rr;
+
+    DEBUG ("redis plugin: querying info from node `%s' (%s:%d).", rn->name, rn->host, rn->port);
+
+    rh = redisConnectWithTimeout ((char *)rn->host, rn->port, rn->timeout);
+    if (rh == NULL)
+    {
+      ERROR ("redis plugin: unable to connect to node `%s' (%s:%d).", rn->name, rn->host, rn->port);
+      continue;
+    }
+
+    if (strlen (rn->passwd) > 0)
+    {
+      DEBUG ("redis plugin: authenticanting node `%s' passwd(%s).", rn->name, rn->passwd);
+      rr = redisCommand (rh, "AUTH %s", rn->passwd);
+
+      if (rr == NULL || rr->type != REDIS_REPLY_STATUS)
+      {
+        WARNING ("redis plugin: unable to authenticate on node `%s'.", rn->name);
+        if (rr != NULL)
+          freeReplyObject (rr);
+
+        redisFree (rh);
+        continue;
+      }
+    }
+
+    if ((rr = redisCommand(rh, "INFO")) == NULL)
+    {
+      WARNING ("redis plugin: unable to connect to node `%s'.", rn->name);
+      redisFree (rh);
+      continue;
+    }
+
+    redis_handle_info (rn->name, rr->str, "uptime", NULL, "uptime_in_seconds", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "current_connections", "clients", "connected_clients", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "blocked_clients", NULL, "blocked_clients", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "memory", NULL, "used_memory", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "memory_lua", NULL, "used_memory_lua", DS_TYPE_GAUGE);
+    /* changes_since_last_save: Deprecated in redis version 2.6 and above */
+    redis_handle_info (rn->name, rr->str, "volatile_changes", NULL, "changes_since_last_save", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "total_connections", NULL, "total_connections_received", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "total_operations", NULL, "total_commands_processed", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "expired_keys", NULL, "expired_keys", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "pubsub", "channels", "pubsub_channels", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "pubsub", "patterns", "pubsub_patterns", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "current_connections", "slaves", "connected_slaves", DS_TYPE_GAUGE);
+
+    freeReplyObject (rr);
+
+    for (rq = rn->queries; rq != NULL; rq = rq->next)
+        redis_handle_query(rh, rn, rq);
+
+    redisFree (rh);
+  }
+
+  return 0;
+}
+/* }}} */
+
+void module_register (void) /* {{{ */
+{
+  plugin_register_complex_config ("redis", redis_config);
+  plugin_register_init ("redis", redis_init);
+  plugin_register_read ("redis", redis_read);
+  /* TODO: plugin_register_write: one redis list per value id with
+   * X elements */
+}
+/* }}} */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/riemann.proto b/src/riemann.proto
new file mode 100644 (file)
index 0000000..3e946a3
--- /dev/null
@@ -0,0 +1,45 @@
+option java_package = "com.aphyr.riemann";
+option java_outer_classname = "Proto";
+
+message State {
+  optional int64 time = 1;
+  optional string state = 2;
+  optional string service = 3;
+  optional string host = 4;
+  optional string description = 5;
+  optional bool once = 6;
+  repeated string tags = 7;
+  optional float ttl = 8;
+}
+
+message Event {
+  optional int64 time = 1;
+  optional string state = 2;
+  optional string service = 3;
+  optional string host = 4;
+  optional string description = 5;
+  repeated string tags = 7;
+  optional float ttl = 8;
+  repeated Attribute attributes = 9;
+
+  optional sint64 metric_sint64 = 13;
+  optional double metric_d = 14;
+  optional float metric_f = 15;
+}
+
+message Query {
+  optional string string = 1;
+}
+
+message Msg {
+  optional bool ok = 2;
+  optional string error = 3;
+  repeated State states = 4;
+  optional Query query = 5;
+  repeated Event events = 6;
+}
+
+message Attribute {
+  required string key = 1;
+  optional string value = 2;
+}
diff --git a/src/routeros.c b/src/routeros.c
new file mode 100644 (file)
index 0000000..4ca9d5b
--- /dev/null
@@ -0,0 +1,449 @@
+/**
+ * collectd - src/routeros.c
+ * Copyright (C) 2009,2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <routeros_api.h>
+
+struct cr_data_s
+{
+  ros_connection_t *connection;
+
+  char *node;
+  char *service;
+  char *username;
+  char *password;
+
+  _Bool collect_interface;
+  _Bool collect_regtable;
+  _Bool collect_cpu_load;
+  _Bool collect_memory;
+  _Bool collect_df;
+  _Bool collect_disk;
+};
+typedef struct cr_data_s cr_data_t;
+
+static void cr_submit_io (cr_data_t *rd, const char *type, /* {{{ */
+    const char *type_instance, derive_t rx, derive_t tx)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, rd->node, sizeof (vl.host));
+       sstrncpy (vl.plugin, "routeros", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* }}} void cr_submit_io */
+
+static void submit_interface (cr_data_t *rd, /* {{{ */
+    const ros_interface_t *i)
+{
+  if (i == NULL)
+    return;
+
+  if (!i->running)
+  {
+    submit_interface (rd, i->next);
+    return;
+  }
+
+  cr_submit_io (rd, "if_packets", i->name,
+      (derive_t) i->rx_packets, (derive_t) i->tx_packets);
+  cr_submit_io (rd, "if_octets", i->name,
+      (derive_t) i->rx_bytes, (derive_t) i->tx_bytes);
+  cr_submit_io (rd, "if_errors", i->name,
+      (derive_t) i->rx_errors, (derive_t) i->tx_errors);
+  cr_submit_io (rd, "if_dropped", i->name,
+      (derive_t) i->rx_drops, (derive_t) i->tx_drops);
+
+  submit_interface (rd, i->next);
+} /* }}} void submit_interface */
+
+static int handle_interface (__attribute__((unused)) ros_connection_t *c, /* {{{ */
+    const ros_interface_t *i, void *user_data)
+{
+  if ((i == NULL) || (user_data == NULL))
+    return (EINVAL);
+
+  submit_interface (user_data, i);
+  return (0);
+} /* }}} int handle_interface */
+
+static void cr_submit_gauge (cr_data_t *rd, const char *type, /* {{{ */
+    const char *type_instance, gauge_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, rd->node, sizeof (vl.host));
+       sstrncpy (vl.plugin, "routeros", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* }}} void cr_submit_gauge */
+
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0)
+static void cr_submit_counter (cr_data_t *rd, const char *type, /* {{{ */
+    const char *type_instance, derive_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = value;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, rd->node, sizeof (vl.host));
+       sstrncpy (vl.plugin, "routeros", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* }}} void cr_submit_gauge */
+#endif
+
+static void submit_regtable (cr_data_t *rd, /* {{{ */
+    const ros_registration_table_t *r)
+{
+  char type_instance[DATA_MAX_NAME_LEN];
+
+  if (r == NULL)
+    return;
+
+  /*** RX ***/
+  ssnprintf (type_instance, sizeof (type_instance), "%s-%s-rx",
+      r->interface, r->radio_name);
+  cr_submit_gauge (rd, "bitrate", type_instance,
+      (gauge_t) (1000000.0 * r->rx_rate));
+  cr_submit_gauge (rd, "signal_power", type_instance,
+      (gauge_t) r->rx_signal_strength);
+  cr_submit_gauge (rd, "signal_quality", type_instance,
+      (gauge_t) r->rx_ccq);
+
+  /*** TX ***/
+  ssnprintf (type_instance, sizeof (type_instance), "%s-%s-tx",
+      r->interface, r->radio_name);
+  cr_submit_gauge (rd, "bitrate", type_instance,
+      (gauge_t) (1000000.0 * r->tx_rate));
+  cr_submit_gauge (rd, "signal_power", type_instance,
+      (gauge_t) r->tx_signal_strength);
+  cr_submit_gauge (rd, "signal_quality", type_instance,
+      (gauge_t) r->tx_ccq);
+
+  /*** RX / TX ***/
+  ssnprintf (type_instance, sizeof (type_instance), "%s-%s",
+      r->interface, r->radio_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);
+
+  submit_regtable (rd, r->next);
+} /* }}} void submit_regtable */
+
+static int handle_regtable (__attribute__((unused)) ros_connection_t *c, /* {{{ */
+    const ros_registration_table_t *r, void *user_data)
+{
+  if ((r == NULL) || (user_data == NULL))
+    return (EINVAL);
+
+  submit_regtable (user_data, r);
+  return (0);
+} /* }}} int handle_regtable */
+
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0)
+static int handle_system_resource (__attribute__((unused)) ros_connection_t *c, /* {{{ */
+        const ros_system_resource_t *r,
+       __attribute__((unused)) void *user_data)
+{
+  cr_data_t *rd;
+
+  if ((r == NULL) || (user_data == NULL))
+    return (EINVAL);
+  rd = user_data;
+
+  if (rd->collect_cpu_load)
+    cr_submit_gauge (rd, "gauge", "cpu_load", (gauge_t) r->cpu_load);
+
+  if (rd->collect_memory)
+  {
+    cr_submit_gauge (rd, "memory", "used",
+       (gauge_t) (r->total_memory - r->free_memory));
+    cr_submit_gauge (rd, "memory", "free", (gauge_t) r->free_memory);
+  }
+
+  if (rd->collect_df)
+  {
+    cr_submit_gauge (rd, "df_complex", "used",
+       (gauge_t) (r->total_memory - r->free_memory));
+    cr_submit_gauge (rd, "df_complex", "free", (gauge_t) r->free_memory);
+  }
+
+  if (rd->collect_disk)
+  {
+    cr_submit_counter (rd, "counter", "secors_written", (derive_t) r->write_sect_total);
+    cr_submit_gauge (rd, "gauge", "bad_blocks", (gauge_t) r->bad_blocks);
+  }
+
+  return (0);
+} /* }}} int handle_system_resource */
+#endif
+
+static int cr_read (user_data_t *user_data) /* {{{ */
+{
+  int status;
+  cr_data_t *rd;
+
+  if (user_data == NULL)
+    return (EINVAL);
+
+  rd = user_data->data;
+  if (rd == NULL)
+    return (EINVAL);
+
+  if (rd->connection == NULL)
+  {
+    rd->connection = ros_connect (rd->node, rd->service,
+       rd->username, rd->password);
+    if (rd->connection == NULL)
+    {
+      char errbuf[128];
+      ERROR ("routeros plugin: ros_connect failed: %s",
+         sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (-1);
+    }
+  }
+  assert (rd->connection != NULL);
+
+  if (rd->collect_interface)
+  {
+    status = ros_interface (rd->connection, handle_interface,
+       /* user data = */ rd);
+    if (status != 0)
+    {
+      char errbuf[128];
+      ERROR ("routeros plugin: ros_interface failed: %s",
+         sstrerror (status, errbuf, sizeof (errbuf)));
+      ros_disconnect (rd->connection);
+      rd->connection = NULL;
+      return (-1);
+    }
+  }
+
+  if (rd->collect_regtable)
+  {
+    status = ros_registration_table (rd->connection, handle_regtable,
+       /* user data = */ rd);
+    if (status != 0)
+    {
+      char errbuf[128];
+      ERROR ("routeros plugin: ros_registration_table failed: %s",
+         sstrerror (status, errbuf, sizeof (errbuf)));
+      ros_disconnect (rd->connection);
+      rd->connection = NULL;
+      return (-1);
+    }
+  }
+
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0)
+  if (rd->collect_cpu_load
+      || rd->collect_memory
+      || rd->collect_df
+      || rd->collect_disk)
+  {
+    status = ros_system_resource (rd->connection, handle_system_resource,
+       /* user data = */ rd);
+    if (status != 0)
+    {
+      char errbuf[128];
+      ERROR ("routeros plugin: ros_system_resource failed: %s",
+         sstrerror (status, errbuf, sizeof (errbuf)));
+      ros_disconnect (rd->connection);
+      rd->connection = NULL;
+      return (-1);
+    }
+  }
+#endif
+
+  return (0);
+} /* }}} int cr_read */
+
+static void cr_free_data (cr_data_t *ptr) /* {{{ */
+{
+  if (ptr == NULL)
+    return;
+
+  ros_disconnect (ptr->connection);
+  ptr->connection = NULL;
+
+  sfree (ptr->node);
+  sfree (ptr->service);
+  sfree (ptr->username);
+  sfree (ptr->password);
+
+  sfree (ptr);
+} /* }}} void cr_free_data */
+
+static int cr_config_router (oconfig_item_t *ci) /* {{{ */
+{
+  cr_data_t *router_data;
+  char read_name[128];
+  user_data_t user_data;
+  int status;
+  int i;
+
+  router_data = malloc (sizeof (*router_data));
+  if (router_data == NULL)
+    return (-1);
+  memset (router_data, 0, sizeof (router_data));
+  router_data->connection = NULL;
+  router_data->node = NULL;
+  router_data->service = NULL;
+  router_data->username = NULL;
+  router_data->password = NULL;
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &router_data->node);
+    else if (strcasecmp ("Port", child->key) == 0)
+      status = cf_util_get_service (child, &router_data->service);
+    else if (strcasecmp ("User", child->key) == 0)
+      status = cf_util_get_string (child, &router_data->username);
+    else if (strcasecmp ("Password", child->key) == 0)
+      status = cf_util_get_string (child, &router_data->password);
+    else if (strcasecmp ("CollectInterface", child->key) == 0)
+      cf_util_get_boolean (child, &router_data->collect_interface);
+    else if (strcasecmp ("CollectRegistrationTable", child->key) == 0)
+      cf_util_get_boolean (child, &router_data->collect_regtable);
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0)
+    else if (strcasecmp ("CollectCPULoad", child->key) == 0)
+      cf_util_get_boolean (child, &router_data->collect_cpu_load);
+    else if (strcasecmp ("CollectMemory", child->key) == 0)
+      cf_util_get_boolean (child, &router_data->collect_memory);
+    else if (strcasecmp ("CollectDF", child->key) == 0)
+      cf_util_get_boolean (child, &router_data->collect_df);
+    else if (strcasecmp ("CollectDisk", child->key) == 0)
+      cf_util_get_boolean (child, &router_data->collect_disk);
+#endif
+    else
+    {
+      WARNING ("routeros plugin: Unknown config option `%s'.", child->key);
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if (status == 0)
+  {
+    if (router_data->node == NULL)
+    {
+      ERROR ("routeros plugin: No `Host' option within a `Router' block. "
+         "Where should I connect to?");
+      status = -1;
+    }
+
+    if (router_data->password == NULL)
+    {
+      ERROR ("routeros plugin: No `Password' option within a `Router' block. "
+         "How should I authenticate?");
+      status = -1;
+    }
+
+    if (!router_data->collect_interface
+       && !router_data->collect_regtable)
+    {
+      ERROR ("routeros plugin: No `Collect*' option within a `Router' block. "
+         "What statistics should I collect?");
+      status = -1;
+    }
+  }
+
+  if ((status == 0) && (router_data->username == NULL))
+  {
+    router_data->username = sstrdup ("admin");
+    if (router_data->username == NULL)
+    {
+      ERROR ("routeros plugin: sstrdup failed.");
+      status = -1;
+    }
+  }
+
+  ssnprintf (read_name, sizeof (read_name), "routeros/%s", router_data->node);
+  user_data.data = router_data;
+  user_data.free_func = (void *) cr_free_data;
+  if (status == 0)
+    status = plugin_register_complex_read (/* group = */ NULL, read_name,
+       cr_read, /* interval = */ NULL, &user_data);
+
+  if (status != 0)
+    cr_free_data (router_data);
+
+  return (status);
+} /* }}} int cr_config_router */
+
+static int cr_config (oconfig_item_t *ci)
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Router", child->key) == 0)
+      cr_config_router (child);
+    else
+    {
+      WARNING ("routeros plugin: Unknown config option `%s'.", child->key);
+    }
+  }
+
+  return (0);
+} /* }}} int cr_config */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("routeros", cr_config);
+} /* void module_register */
+
+/* vim: set sw=2 noet fdm=marker : */
diff --git a/src/rrdcached.c b/src/rrdcached.c
new file mode 100644 (file)
index 0000000..645032c
--- /dev/null
@@ -0,0 +1,543 @@
+/**
+ * collectd - src/rrdcached.c
+ * Copyright (C) 2008-2013  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_rrdcreate.h"
+
+#undef HAVE_CONFIG_H
+#include <rrd.h>
+#include <rrd_client.h>
+
+/*
+ * Private variables
+ */
+static char *datadir = NULL;
+static char *daemon_address = NULL;
+static _Bool config_create_files = 1;
+static _Bool config_collect_stats = 1;
+static rrdcreate_config_t rrdcreate_config =
+{
+       /* stepsize = */ 0,
+       /* heartbeat = */ 0,
+       /* rrarows = */ 1200,
+       /* xff = */ 0.1,
+
+       /* timespans = */ NULL,
+       /* timespans_num = */ 0,
+
+       /* consolidation_functions = */ NULL,
+       /* consolidation_functions_num = */ 0,
+
+       /* async = */ 0
+};
+
+/*
+ * Prototypes.
+ */
+static int rc_write (const data_set_t *ds, const value_list_t *vl,
+    user_data_t __attribute__((unused)) *user_data);
+static int rc_flush (__attribute__((unused)) cdtime_t timeout,
+    const char *identifier, __attribute__((unused)) user_data_t *ud);
+
+static int value_list_to_string (char *buffer, int buffer_len,
+    const data_set_t *ds, const value_list_t *vl)
+{
+  int offset;
+  int status;
+  int i;
+  time_t t;
+
+  assert (0 == strcmp (ds->type, vl->type));
+
+  memset (buffer, '\0', buffer_len);
+
+  t = CDTIME_T_TO_TIME_T (vl->time);
+  status = ssnprintf (buffer, buffer_len, "%lu", (unsigned long) t);
+  if ((status < 1) || (status >= buffer_len))
+    return (-1);
+  offset = status;
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if ((ds->ds[i].type != DS_TYPE_COUNTER)
+        && (ds->ds[i].type != DS_TYPE_GAUGE)
+       && (ds->ds[i].type != DS_TYPE_DERIVE)
+       && (ds->ds[i].type != DS_TYPE_ABSOLUTE))
+      return (-1);
+
+    if (ds->ds[i].type == DS_TYPE_COUNTER)
+    {
+      status = ssnprintf (buffer + offset, buffer_len - offset,
+          ":%llu", vl->values[i].counter);
+    }
+    else if (ds->ds[i].type == DS_TYPE_GAUGE) 
+    {
+      status = ssnprintf (buffer + offset, buffer_len - offset,
+          ":%f", vl->values[i].gauge);
+    }
+    else if (ds->ds[i].type == DS_TYPE_DERIVE) {
+      status = ssnprintf (buffer + offset, buffer_len - offset,
+         ":%"PRIi64, vl->values[i].derive);
+    }
+    else /* if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ {
+      status = ssnprintf (buffer + offset, buffer_len - offset,
+         ":%"PRIu64, vl->values[i].absolute);
+    }
+
+    if ((status < 1) || (status >= (buffer_len - offset)))
+      return (-1);
+
+    offset += status;
+  } /* for ds->ds_num */
+
+  return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, size_t buffer_size,
+    value_list_t const *vl)
+{
+  char const suffix[] = ".rrd";
+  int status;
+  size_t len;
+
+  if (datadir != NULL)
+  {
+    size_t datadir_len = strlen (datadir) + 1;
+
+    if (datadir_len >= buffer_size)
+      return (ENOMEM);
+
+    sstrncpy (buffer, datadir, buffer_size);
+    buffer[datadir_len - 1] = '/';
+    buffer[datadir_len] = 0;
+
+    buffer += datadir_len;
+    buffer_size -= datadir_len;
+  }
+
+  status = FORMAT_VL (buffer, buffer_size, vl);
+  if (status != 0)
+    return (status);
+
+  len = strlen (buffer);
+  assert (len < buffer_size);
+  buffer += len;
+  buffer_size -= len;
+
+  if (buffer_size <= sizeof (suffix))
+    return (ENOMEM);
+
+  memcpy (buffer, suffix, sizeof (suffix));
+  return (0);
+} /* int value_list_to_filename */
+
+static int rc_config_get_int_positive (oconfig_item_t const *ci, int *ret)
+{
+  int status;
+  int tmp = 0;
+
+  status = cf_util_get_int (ci, &tmp);
+  if (status != 0)
+    return (status);
+  if (tmp < 0)
+    return (EINVAL);
+
+  *ret = tmp;
+  return (0);
+} /* int rc_config_get_int_positive */
+
+static int rc_config_get_xff (oconfig_item_t const *ci, double *ret)
+{
+  double value;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    ERROR ("rrdcached plugin: The \"%s\" needs exactly one numeric argument "
+        "in the range [0.0, 1.0)", ci->key);
+    return (EINVAL);
+  }
+
+  value = ci->values[0].value.number;
+  if ((value >= 0.0) && (value < 1.0))
+  {
+    *ret = value;
+    return (0);
+  }
+
+  ERROR ("rrdcached plugin: The \"%s\" needs exactly one numeric argument "
+      "in the range [0.0, 1.0)", ci->key);
+  return (EINVAL);
+} /* int rc_config_get_xff */
+
+static int rc_config_add_timespan (int timespan)
+{
+  int *tmp;
+
+  if (timespan <= 0)
+    return (EINVAL);
+
+  tmp = realloc (rrdcreate_config.timespans,
+      sizeof (*rrdcreate_config.timespans)
+      * (rrdcreate_config.timespans_num + 1));
+  if (tmp == NULL)
+    return (ENOMEM);
+  rrdcreate_config.timespans = tmp;
+
+  rrdcreate_config.timespans[rrdcreate_config.timespans_num] = timespan;
+  rrdcreate_config.timespans_num++;
+
+  return (0);
+} /* int rc_config_add_timespan */
+
+static int rc_config (oconfig_item_t *ci)
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t const *child = ci->children + i;
+    const char *key = child->key;
+    int status = 0;
+
+    if (strcasecmp ("DataDir", key) == 0)
+    {
+      status = cf_util_get_string (child, &datadir);
+      if (status == 0)
+      {
+        int len = strlen (datadir);
+
+        while ((len > 0) && (datadir[len - 1] == '/'))
+        {
+          len--;
+          datadir[len] = 0;
+        }
+
+        if (len <= 0)
+          sfree (datadir);
+      }
+    }
+    else if (strcasecmp ("DaemonAddress", key) == 0)
+      status = cf_util_get_string (child, &daemon_address);
+    else if (strcasecmp ("CreateFiles", key) == 0)
+      status = cf_util_get_boolean (child, &config_create_files);
+    else if (strcasecmp ("CreateFilesAsync", key) == 0)
+      status = cf_util_get_boolean (child, &rrdcreate_config.async);
+    else if (strcasecmp ("CollectStatistics", key) == 0)
+      status = cf_util_get_boolean (child, &config_collect_stats);
+    else if (strcasecmp ("StepSize", key) == 0)
+    {
+      int tmp = -1;
+
+      status = rc_config_get_int_positive (child, &tmp);
+      if (status == 0)
+        rrdcreate_config.stepsize = (unsigned long) tmp;
+    }
+    else if (strcasecmp ("HeartBeat", key) == 0)
+      status = rc_config_get_int_positive (child, &rrdcreate_config.heartbeat);
+    else if (strcasecmp ("RRARows", key) == 0)
+      status = rc_config_get_int_positive (child, &rrdcreate_config.rrarows);
+    else if (strcasecmp ("RRATimespan", key) == 0)
+    {
+      int tmp = -1;
+      status = rc_config_get_int_positive (child, &tmp);
+      if (status == 0)
+        status = rc_config_add_timespan (tmp);
+    }
+    else if (strcasecmp ("XFF", key) == 0)
+      status = rc_config_get_xff (child, &rrdcreate_config.xff);
+    else
+    {
+      WARNING ("rrdcached plugin: Ignoring invalid option %s.", key);
+      continue;
+    }
+
+    if (status != 0)
+      WARNING ("rrdcached plugin: Handling the \"%s\" option failed.", key);
+  }
+
+  if (daemon_address != NULL)
+  {
+    plugin_register_write ("rrdcached", rc_write, /* user_data = */ NULL);
+    plugin_register_flush ("rrdcached", rc_flush, /* user_data = */ NULL);
+  }
+  return (0);
+} /* int rc_config */
+
+static int rc_read (void)
+{
+  int status;
+  rrdc_stats_t *head;
+  rrdc_stats_t *ptr;
+
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  if (daemon_address == NULL)
+    return (-1);
+
+  if (!config_collect_stats)
+    return (-1);
+
+  vl.values = values;
+  vl.values_len = 1;
+
+  if ((strncmp ("unix:", daemon_address, strlen ("unix:")) == 0)
+      || (daemon_address[0] == '/'))
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  else
+    sstrncpy (vl.host, daemon_address, sizeof (vl.host));
+  sstrncpy (vl.plugin, "rrdcached", sizeof (vl.plugin));
+
+  status = rrdc_connect (daemon_address);
+  if (status != 0)
+  {
+    ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.",
+        daemon_address, status);
+    return (-1);
+  }
+
+  head = NULL;
+  status = rrdc_stats_get (&head);
+  if (status != 0)
+  {
+    ERROR ("rrdcached plugin: rrdc_stats_get failed with status %i.", status);
+    return (-1);
+  }
+
+  for (ptr = head; ptr != NULL; ptr = ptr->next)
+  {
+    if (ptr->type == RRDC_STATS_TYPE_GAUGE)
+      values[0].gauge = (gauge_t) ptr->value.gauge;
+    else if (ptr->type == RRDC_STATS_TYPE_COUNTER)
+      values[0].counter = (counter_t) ptr->value.counter;
+    else
+      continue;
+
+    if (strcasecmp ("QueueLength", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "queue_length", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("UpdatesWritten", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "operations", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "write-updates", sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("DataSetsWritten", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "operations", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "write-data_sets",
+          sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("TreeNodesNumber", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "gauge", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "tree_nodes", sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("TreeDepth", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "gauge", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "tree_depth", sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("FlushesReceived", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "operations", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "receive-flush", sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("JournalBytes", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "counter", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "journal-bytes", sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("JournalRotate", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "counter", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "journal-rotates", sizeof (vl.type_instance));
+    }
+    else if (strcasecmp ("UpdatesReceived", ptr->name) == 0)
+    {
+      sstrncpy (vl.type, "operations", sizeof (vl.type));
+      sstrncpy (vl.type_instance, "receive-update", sizeof (vl.type_instance));
+    }
+    else
+    {
+      DEBUG ("rrdcached plugin: rc_read: Unknown statistic `%s'.", ptr->name);
+      continue;
+    }
+
+    plugin_dispatch_values (&vl);
+  } /* for (ptr = head; ptr != NULL; ptr = ptr->next) */
+
+  rrdc_stats_free (head);
+
+  return (0);
+} /* int rc_read */
+
+static int rc_init (void)
+{
+  if (config_collect_stats)
+    plugin_register_read ("rrdcached", rc_read);
+
+  return (0);
+} /* int rc_init */
+
+static int rc_write (const data_set_t *ds, const value_list_t *vl,
+    user_data_t __attribute__((unused)) *user_data)
+{
+  char filename[PATH_MAX];
+  char values[512];
+  char *values_array[2];
+  int status;
+
+  if (daemon_address == NULL)
+  {
+    ERROR ("rrdcached plugin: daemon_address == NULL.");
+    plugin_unregister_write ("rrdcached");
+    return (-1);
+  }
+
+  if (strcmp (ds->type, vl->type) != 0)
+  {
+    ERROR ("rrdcached plugin: DS type does not match value list type");
+    return (-1);
+  }
+
+  if (value_list_to_filename (filename, sizeof (filename), vl) != 0)
+  {
+    ERROR ("rrdcached plugin: value_list_to_filename failed.");
+    return (-1);
+  }
+
+  if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+  {
+    ERROR ("rrdcached plugin: value_list_to_string failed.");
+    return (-1);
+  }
+
+  values_array[0] = values;
+  values_array[1] = NULL;
+
+  if (config_create_files)
+  {
+    struct stat statbuf;
+
+    status = stat (filename, &statbuf);
+    if (status != 0)
+    {
+      if (errno != ENOENT)
+      {
+        char errbuf[1024];
+        ERROR ("rrdcached plugin: stat (%s) failed: %s",
+            filename, sstrerror (errno, errbuf, sizeof (errbuf)));
+        return (-1);
+      }
+
+      status = cu_rrd_create_file (filename, ds, vl, &rrdcreate_config);
+      if (status != 0)
+      {
+        ERROR ("rrdcached plugin: cu_rrd_create_file (%s) failed.",
+            filename);
+        return (-1);
+      }
+      else if (rrdcreate_config.async)
+        return (0);
+    }
+  }
+
+  status = rrdc_connect (daemon_address);
+  if (status != 0)
+  {
+    ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.",
+        daemon_address, status);
+    return (-1);
+  }
+
+  status = rrdc_update (filename, /* values_num = */ 1, (void *) values_array);
+  if (status != 0)
+  {
+    ERROR ("rrdcached plugin: rrdc_update (%s, [%s], 1) failed with "
+        "status %i.",
+        filename, values_array[0], status);
+    return (-1);
+  }
+
+  return (0);
+} /* int rc_write */
+
+static int rc_flush (__attribute__((unused)) cdtime_t timeout, /* {{{ */
+    const char *identifier,
+    __attribute__((unused)) user_data_t *ud)
+{
+  char filename[PATH_MAX + 1];
+  int status;
+
+  if (identifier == NULL)
+    return (EINVAL);
+
+  if (datadir != NULL)
+    ssnprintf (filename, sizeof (filename), "%s/%s.rrd", datadir, identifier);
+  else
+    ssnprintf (filename, sizeof (filename), "%s.rrd", identifier);
+
+  status = rrdc_connect (daemon_address);
+  if (status != 0)
+  {
+    ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.",
+        daemon_address, status);
+    return (-1);
+  }
+
+  status = rrdc_flush (filename);
+  if (status != 0)
+  {
+    ERROR ("rrdcached plugin: rrdc_flush (%s) failed with status %i.",
+        filename, status);
+    return (-1);
+  }
+  DEBUG ("rrdcached plugin: rrdc_flush (%s): Success.", filename);
+
+  return (0);
+} /* }}} int rc_flush */
+
+static int rc_shutdown (void)
+{
+  rrdc_disconnect ();
+  return (0);
+} /* int rc_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("rrdcached", rc_config);
+  plugin_register_init ("rrdcached", rc_init);
+  plugin_register_shutdown ("rrdcached", rc_shutdown);
+} /* void module_register */
+
+/*
+ * vim: set sw=2 sts=2 et :
+ */
diff --git a/src/rrdtool.c b/src/rrdtool.c
new file mode 100644 (file)
index 0000000..bebf468
--- /dev/null
@@ -0,0 +1,1248 @@
+/**
+ * collectd - src/rrdtool.c
+ * Copyright (C) 2006-2013  Florian octo Forster
+ * Copyright (C) 2008-2008  Sebastian Harl
+ * Copyright (C) 2009       Mariusz Gronczewski
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Mariusz Gronczewski <xani666 at gmail.com>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_avltree.h"
+#include "utils_random.h"
+#include "utils_rrdcreate.h"
+
+#include <rrd.h>
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+/*
+ * Private types
+ */
+struct rrd_cache_s
+{
+       int      values_num;
+       char   **values;
+       cdtime_t first_value;
+       cdtime_t last_value;
+       int64_t  random_variation;
+       enum
+       {
+               FLAG_NONE   = 0x00,
+               FLAG_QUEUED = 0x01,
+               FLAG_FLUSHQ = 0x02
+       } flags;
+};
+typedef struct rrd_cache_s rrd_cache_t;
+
+enum rrd_queue_dir_e
+{
+  QUEUE_INSERT_FRONT,
+  QUEUE_INSERT_BACK
+};
+typedef enum rrd_queue_dir_e rrd_queue_dir_t;
+
+struct rrd_queue_s
+{
+       char *filename;
+       struct rrd_queue_s *next;
+};
+typedef struct rrd_queue_s rrd_queue_t;
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+       "CacheTimeout",
+       "CacheFlush",
+       "CreateFilesAsync",
+       "DataDir",
+       "StepSize",
+       "HeartBeat",
+       "RRARows",
+       "RRATimespan",
+       "XFF",
+       "WritesPerSecond",
+       "RandomTimeout"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+/* If datadir is zero, the daemon's basedir is used. If stepsize or heartbeat
+ * is zero a default, depending on the `interval' member of the value list is
+ * being used. */
+static char *datadir   = NULL;
+static double write_rate = 0.0;
+static rrdcreate_config_t rrdcreate_config =
+{
+       /* stepsize = */ 0,
+       /* heartbeat = */ 0,
+       /* rrarows = */ 1200,
+       /* xff = */ 0.1,
+
+       /* timespans = */ NULL,
+       /* timespans_num = */ 0,
+
+       /* consolidation_functions = */ NULL,
+       /* consolidation_functions_num = */ 0,
+
+       /* async = */ 0
+};
+
+/* XXX: If you need to lock both, cache_lock and queue_lock, at the same time,
+ * ALWAYS lock `cache_lock' first! */
+static cdtime_t    cache_timeout = 0;
+static cdtime_t    cache_flush_timeout = 0;
+static cdtime_t    random_timeout = TIME_T_TO_CDTIME_T (1);
+static cdtime_t    cache_flush_last;
+static c_avl_tree_t *cache = NULL;
+static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static rrd_queue_t    *queue_head = NULL;
+static rrd_queue_t    *queue_tail = NULL;
+static rrd_queue_t    *flushq_head = NULL;
+static rrd_queue_t    *flushq_tail = NULL;
+static pthread_t       queue_thread;
+static int             queue_thread_running = 1;
+static pthread_mutex_t queue_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t  queue_cond = PTHREAD_COND_INITIALIZER;
+
+#if !HAVE_THREADSAFE_LIBRRD
+static pthread_mutex_t librrd_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static int do_shutdown = 0;
+
+#if HAVE_THREADSAFE_LIBRRD
+static int srrd_update (char *filename, char *template,
+               int argc, const char **argv)
+{
+       int status;
+
+       optind = 0; /* bug in librrd? */
+       rrd_clear_error ();
+
+       status = rrd_update_r (filename, template, argc, (void *) argv);
+
+       if (status != 0)
+       {
+               WARNING ("rrdtool plugin: rrd_update_r (%s) failed: %s",
+                               filename, rrd_get_error ());
+       }
+
+       return (status);
+} /* int srrd_update */
+/* #endif HAVE_THREADSAFE_LIBRRD */
+
+#else /* !HAVE_THREADSAFE_LIBRRD */
+static int srrd_update (char *filename, char *template,
+               int argc, const char **argv)
+{
+       int status;
+
+       int new_argc;
+       char **new_argv;
+
+       assert (template == NULL);
+
+       new_argc = 2 + argc;
+       new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+       if (new_argv == NULL)
+       {
+               ERROR ("rrdtool plugin: malloc failed.");
+               return (-1);
+       }
+
+       new_argv[0] = "update";
+       new_argv[1] = filename;
+
+       memcpy (new_argv + 2, argv, argc * sizeof (char *));
+       new_argv[new_argc] = NULL;
+
+       pthread_mutex_lock (&librrd_lock);
+       optind = 0; /* bug in librrd? */
+       rrd_clear_error ();
+
+       status = rrd_update (new_argc, new_argv);
+       pthread_mutex_unlock (&librrd_lock);
+
+       if (status != 0)
+       {
+               WARNING ("rrdtool plugin: rrd_update_r failed: %s: %s",
+                               filename, rrd_get_error ());
+       }
+
+       sfree (new_argv);
+
+       return (status);
+} /* int srrd_update */
+#endif /* !HAVE_THREADSAFE_LIBRRD */
+
+static int value_list_to_string_multiple (char *buffer, int buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       int offset;
+       int status;
+       time_t tt;
+       int i;
+
+       memset (buffer, '\0', buffer_len);
+
+       tt = CDTIME_T_TO_TIME_T (vl->time);
+       status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) tt);
+       if ((status < 1) || (status >= buffer_len))
+               return (-1);
+       offset = status;
+
+       for (i = 0; i < ds->ds_num; i++)
+       {
+               if ((ds->ds[i].type != DS_TYPE_COUNTER)
+                               && (ds->ds[i].type != DS_TYPE_GAUGE)
+                               && (ds->ds[i].type != DS_TYPE_DERIVE)
+                               && (ds->ds[i].type != DS_TYPE_ABSOLUTE))
+                       return (-1);
+
+               if (ds->ds[i].type == DS_TYPE_COUNTER)
+                       status = ssnprintf (buffer + offset, buffer_len - offset,
+                                       ":%llu", vl->values[i].counter);
+               else if (ds->ds[i].type == DS_TYPE_GAUGE)
+                       status = ssnprintf (buffer + offset, buffer_len - offset,
+                                       ":"GAUGE_FORMAT, vl->values[i].gauge);
+               else if (ds->ds[i].type == DS_TYPE_DERIVE)
+                       status = ssnprintf (buffer + offset, buffer_len - offset,
+                                       ":%"PRIi64, vl->values[i].derive);
+               else /*if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */
+                       status = ssnprintf (buffer + offset, buffer_len - offset,
+                                       ":%"PRIu64, vl->values[i].absolute);
+
+               if ((status < 1) || (status >= (buffer_len - offset)))
+                       return (-1);
+
+               offset += status;
+       } /* for ds->ds_num */
+
+       return (0);
+} /* int value_list_to_string_multiple */
+
+static int value_list_to_string (char *buffer, int buffer_len,
+               const data_set_t *ds, const value_list_t *vl)
+{
+       int status;
+       time_t tt;
+
+       if (ds->ds_num != 1)
+               return (value_list_to_string_multiple (buffer, buffer_len,
+                                       ds, vl));
+
+       tt = CDTIME_T_TO_TIME_T (vl->time);
+       switch (ds->ds[0].type)
+       {
+               case DS_TYPE_DERIVE:
+                       status = ssnprintf (buffer, buffer_len, "%u:%"PRIi64,
+                               (unsigned) tt, vl->values[0].derive);
+                       break;
+               case DS_TYPE_GAUGE:
+                       status = ssnprintf (buffer, buffer_len, "%u:"GAUGE_FORMAT,
+                               (unsigned) tt, vl->values[0].gauge);
+                       break;
+               case DS_TYPE_COUNTER:
+                       status = ssnprintf (buffer, buffer_len, "%u:%llu",
+                               (unsigned) tt, vl->values[0].counter);
+                       break;
+               case DS_TYPE_ABSOLUTE:
+                       status = ssnprintf (buffer, buffer_len, "%u:%"PRIu64,
+                               (unsigned) tt, vl->values[0].absolute);
+                       break;
+               default:
+                       return (EINVAL);
+       }
+
+       if ((status < 1) || (status >= buffer_len))
+               return (ENOMEM);
+
+       return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, size_t buffer_size,
+               value_list_t const *vl)
+{
+       char const suffix[] = ".rrd";
+       int status;
+       size_t len;
+
+       if (datadir != NULL)
+       {
+               size_t datadir_len = strlen (datadir) + 1;
+
+               if (datadir_len >= buffer_size)
+                       return (ENOMEM);
+
+               sstrncpy (buffer, datadir, buffer_size);
+               buffer[datadir_len - 1] = '/';
+               buffer[datadir_len] = 0;
+
+               buffer += datadir_len;
+               buffer_size -= datadir_len;
+       }
+
+       status = FORMAT_VL (buffer, buffer_size, vl);
+       if (status != 0)
+               return (status);
+
+       len = strlen (buffer);
+       assert (len < buffer_size);
+       buffer += len;
+       buffer_size -= len;
+
+       if (buffer_size <= sizeof (suffix))
+               return (ENOMEM);
+
+       memcpy (buffer, suffix, sizeof (suffix));
+       return (0);
+} /* int value_list_to_filename */
+
+static void *rrd_queue_thread (void __attribute__((unused)) *data)
+{
+        struct timeval tv_next_update;
+        struct timeval tv_now;
+
+        gettimeofday (&tv_next_update, /* timezone = */ NULL);
+
+       while (42)
+       {
+               rrd_queue_t *queue_entry;
+               rrd_cache_t *cache_entry;
+               char **values;
+               int    values_num;
+               int    status;
+               int    i;
+
+               values = NULL;
+               values_num = 0;
+
+                pthread_mutex_lock (&queue_lock);
+                /* Wait for values to arrive */
+                while (42)
+                {
+                  struct timespec ts_wait;
+
+                  while ((flushq_head == NULL) && (queue_head == NULL)
+                      && (do_shutdown == 0))
+                    pthread_cond_wait (&queue_cond, &queue_lock);
+
+                  if ((flushq_head == NULL) && (queue_head == NULL))
+                    break;
+
+                  /* Don't delay if there's something to flush */
+                  if (flushq_head != NULL)
+                    break;
+
+                  /* Don't delay if we're shutting down */
+                  if (do_shutdown != 0)
+                    break;
+
+                  /* Don't delay if no delay was configured. */
+                  if (write_rate <= 0.0)
+                    break;
+
+                  gettimeofday (&tv_now, /* timezone = */ NULL);
+                  status = timeval_cmp (tv_next_update, tv_now, NULL);
+                  /* We're good to go */
+                  if (status <= 0)
+                    break;
+
+                  /* We're supposed to wait a bit with this update, so we'll
+                   * wait for the next addition to the queue or to the end of
+                   * the wait period - whichever comes first. */
+                  ts_wait.tv_sec = tv_next_update.tv_sec;
+                  ts_wait.tv_nsec = 1000 * tv_next_update.tv_usec;
+
+                  status = pthread_cond_timedwait (&queue_cond, &queue_lock,
+                      &ts_wait);
+                  if (status == ETIMEDOUT)
+                    break;
+                } /* while (42) */
+
+                /* XXX: If you need to lock both, cache_lock and queue_lock, at
+                 * the same time, ALWAYS lock `cache_lock' first! */
+
+                /* We're in the shutdown phase */
+                if ((flushq_head == NULL) && (queue_head == NULL))
+                {
+                  pthread_mutex_unlock (&queue_lock);
+                  break;
+                }
+
+                if (flushq_head != NULL)
+                {
+                  /* Dequeue the first flush entry */
+                  queue_entry = flushq_head;
+                  if (flushq_head == flushq_tail)
+                    flushq_head = flushq_tail = NULL;
+                  else
+                    flushq_head = flushq_head->next;
+                }
+                else /* if (queue_head != NULL) */
+                {
+                  /* Dequeue the first regular entry */
+                  queue_entry = queue_head;
+                  if (queue_head == queue_tail)
+                    queue_head = queue_tail = NULL;
+                  else
+                    queue_head = queue_head->next;
+                }
+
+               /* Unlock the queue again */
+               pthread_mutex_unlock (&queue_lock);
+
+               /* We now need the cache lock so the entry isn't updated while
+                * we make a copy of it's values */
+               pthread_mutex_lock (&cache_lock);
+
+               status = c_avl_get (cache, queue_entry->filename,
+                               (void *) &cache_entry);
+
+               if (status == 0)
+               {
+                       values = cache_entry->values;
+                       values_num = cache_entry->values_num;
+
+                       cache_entry->values = NULL;
+                       cache_entry->values_num = 0;
+                       cache_entry->flags = FLAG_NONE;
+               }
+
+               pthread_mutex_unlock (&cache_lock);
+
+               if (status != 0)
+               {
+                       sfree (queue_entry->filename);
+                       sfree (queue_entry);
+                       continue;
+               }
+
+               /* Update `tv_next_update' */
+               if (write_rate > 0.0) 
+                {
+                  gettimeofday (&tv_now, /* timezone = */ NULL);
+                  tv_next_update.tv_sec = tv_now.tv_sec;
+                  tv_next_update.tv_usec = tv_now.tv_usec
+                    + ((suseconds_t) (1000000 * write_rate));
+                  while (tv_next_update.tv_usec > 1000000)
+                  {
+                    tv_next_update.tv_sec++;
+                    tv_next_update.tv_usec -= 1000000;
+                  }
+                }
+
+               /* Write the values to the RRD-file */
+               srrd_update (queue_entry->filename, NULL,
+                               values_num, (const char **)values);
+               DEBUG ("rrdtool plugin: queue thread: Wrote %i value%s to %s",
+                               values_num, (values_num == 1) ? "" : "s",
+                               queue_entry->filename);
+
+               for (i = 0; i < values_num; i++)
+               {
+                       sfree (values[i]);
+               }
+               sfree (values);
+               sfree (queue_entry->filename);
+               sfree (queue_entry);
+       } /* while (42) */
+
+       pthread_exit ((void *) 0);
+       return ((void *) 0);
+} /* void *rrd_queue_thread */
+
+static int rrd_queue_enqueue (const char *filename,
+    rrd_queue_t **head, rrd_queue_t **tail)
+{
+  rrd_queue_t *queue_entry;
+
+  queue_entry = (rrd_queue_t *) malloc (sizeof (rrd_queue_t));
+  if (queue_entry == NULL)
+    return (-1);
+
+  queue_entry->filename = strdup (filename);
+  if (queue_entry->filename == NULL)
+  {
+    free (queue_entry);
+    return (-1);
+  }
+
+  queue_entry->next = NULL;
+
+  pthread_mutex_lock (&queue_lock);
+
+  if (*tail == NULL)
+    *head = queue_entry;
+  else
+    (*tail)->next = queue_entry;
+  *tail = queue_entry;
+
+  pthread_cond_signal (&queue_cond);
+  pthread_mutex_unlock (&queue_lock);
+
+  return (0);
+} /* int rrd_queue_enqueue */
+
+static int rrd_queue_dequeue (const char *filename,
+    rrd_queue_t **head, rrd_queue_t **tail)
+{
+  rrd_queue_t *this;
+  rrd_queue_t *prev;
+
+  pthread_mutex_lock (&queue_lock);
+
+  prev = NULL;
+  this = *head;
+
+  while (this != NULL)
+  {
+    if (strcmp (this->filename, filename) == 0)
+      break;
+    
+    prev = this;
+    this = this->next;
+  }
+
+  if (this == NULL)
+  {
+    pthread_mutex_unlock (&queue_lock);
+    return (-1);
+  }
+
+  if (prev == NULL)
+    *head = this->next;
+  else
+    prev->next = this->next;
+
+  if (this->next == NULL)
+    *tail = prev;
+
+  pthread_mutex_unlock (&queue_lock);
+
+  sfree (this->filename);
+  sfree (this);
+
+  return (0);
+} /* int rrd_queue_dequeue */
+
+/* XXX: You must hold "cache_lock" when calling this function! */
+static void rrd_cache_flush (cdtime_t timeout)
+{
+       rrd_cache_t *rc;
+       cdtime_t     now;
+
+       char **keys = NULL;
+       int    keys_num = 0;
+
+       char *key;
+       c_avl_iterator_t *iter;
+       int i;
+
+       DEBUG ("rrdtool plugin: Flushing cache, timeout = %.3f",
+                       CDTIME_T_TO_DOUBLE (timeout));
+
+       now = cdtime ();
+       timeout = TIME_T_TO_CDTIME_T (timeout);
+
+       /* Build a list of entries to be flushed */
+       iter = c_avl_get_iterator (cache);
+       while (c_avl_iterator_next (iter, (void *) &key, (void *) &rc) == 0)
+       {
+               if (rc->flags != FLAG_NONE)
+                       continue;
+               /* timeout == 0  =>  flush everything */
+               else if ((timeout != 0)
+                               && ((now - rc->first_value) < timeout))
+                       continue;
+               else if (rc->values_num > 0)
+               {
+                       int status;
+
+                       status = rrd_queue_enqueue (key, &queue_head,  &queue_tail);
+                       if (status == 0)
+                               rc->flags = FLAG_QUEUED;
+               }
+               else /* ancient and no values -> waste of memory */
+               {
+                       char **tmp = (char **) realloc ((void *) keys,
+                                       (keys_num + 1) * sizeof (char *));
+                       if (tmp == NULL)
+                       {
+                               char errbuf[1024];
+                               ERROR ("rrdtool plugin: "
+                                               "realloc failed: %s",
+                                               sstrerror (errno, errbuf,
+                                                       sizeof (errbuf)));
+                               c_avl_iterator_destroy (iter);
+                               sfree (keys);
+                               return;
+                       }
+                       keys = tmp;
+                       keys[keys_num] = key;
+                       keys_num++;
+               }
+       } /* while (c_avl_iterator_next) */
+       c_avl_iterator_destroy (iter);
+       
+       for (i = 0; i < keys_num; i++)
+       {
+               if (c_avl_remove (cache, keys[i], (void *) &key, (void *) &rc) != 0)
+               {
+                       DEBUG ("rrdtool plugin: c_avl_remove (%s) failed.", keys[i]);
+                       continue;
+               }
+
+               assert (rc->values == NULL);
+               assert (rc->values_num == 0);
+
+               sfree (rc);
+               sfree (key);
+               keys[i] = NULL;
+       } /* for (i = 0..keys_num) */
+
+       sfree (keys);
+
+       cache_flush_last = now;
+} /* void rrd_cache_flush */
+
+static int rrd_cache_flush_identifier (cdtime_t timeout,
+    const char *identifier)
+{
+  rrd_cache_t *rc;
+  cdtime_t now;
+  int status;
+  char key[2048];
+
+  if (identifier == NULL)
+  {
+    rrd_cache_flush (timeout);
+    return (0);
+  }
+
+  now = cdtime ();
+
+  if (datadir == NULL)
+    snprintf (key, sizeof (key), "%s.rrd",
+        identifier);
+  else
+    snprintf (key, sizeof (key), "%s/%s.rrd",
+        datadir, identifier);
+  key[sizeof (key) - 1] = 0;
+
+  status = c_avl_get (cache, key, (void *) &rc);
+  if (status != 0)
+  {
+    INFO ("rrdtool plugin: rrd_cache_flush_identifier: "
+        "c_avl_get (%s) failed. Does that file really exist?",
+        key);
+    return (status);
+  }
+
+  if (rc->flags == FLAG_FLUSHQ)
+  {
+    status = 0;
+  }
+  else if (rc->flags == FLAG_QUEUED)
+  {
+    rrd_queue_dequeue (key, &queue_head, &queue_tail);
+    status = rrd_queue_enqueue (key, &flushq_head, &flushq_tail);
+    if (status == 0)
+      rc->flags = FLAG_FLUSHQ;
+  }
+  else if ((now - rc->first_value) < timeout)
+  {
+    status = 0;
+  }
+  else if (rc->values_num > 0)
+  {
+    status = rrd_queue_enqueue (key, &flushq_head, &flushq_tail);
+    if (status == 0)
+      rc->flags = FLAG_FLUSHQ;
+  }
+
+  return (status);
+} /* int rrd_cache_flush_identifier */
+
+static int64_t rrd_get_random_variation (void)
+{
+  long min;
+  long max;
+
+  if (random_timeout <= 0)
+    return (0);
+
+  /* Assure that "cache_timeout + random_variation" is never negative. */
+  if (random_timeout > cache_timeout)
+  {
+         INFO ("rrdtool plugin: Adjusting \"RandomTimeout\" to %.3f seconds.",
+                         CDTIME_T_TO_DOUBLE (cache_timeout));
+         random_timeout = cache_timeout;
+  }
+
+  max = (long) (random_timeout / 2);
+  min = max - ((long) random_timeout);
+
+  return ((int64_t) cdrand_range (min, max));
+} /* int64_t rrd_get_random_variation */
+
+static int rrd_cache_insert (const char *filename,
+               const char *value, cdtime_t value_time)
+{
+       rrd_cache_t *rc = NULL;
+       int new_rc = 0;
+       char **values_new;
+
+       pthread_mutex_lock (&cache_lock);
+
+       /* This shouldn't happen, but it did happen at least once, so we'll be
+        * careful. */
+       if (cache == NULL)
+       {
+               pthread_mutex_unlock (&cache_lock);
+               WARNING ("rrdtool plugin: cache == NULL.");
+               return (-1);
+       }
+
+       c_avl_get (cache, filename, (void *) &rc);
+
+       if (rc == NULL)
+       {
+               rc = malloc (sizeof (*rc));
+               if (rc == NULL)
+                       return (-1);
+               rc->values_num = 0;
+               rc->values = NULL;
+               rc->first_value = 0;
+               rc->last_value = 0;
+               rc->random_variation = rrd_get_random_variation ();
+               rc->flags = FLAG_NONE;
+               new_rc = 1;
+       }
+
+       if (rc->last_value >= value_time)
+       {
+               pthread_mutex_unlock (&cache_lock);
+               DEBUG ("rrdtool plugin: (rc->last_value = %"PRIu64") "
+                               ">= (value_time = %"PRIu64")",
+                               rc->last_value, value_time);
+               return (-1);
+       }
+
+       values_new = (char **) realloc ((void *) rc->values,
+                       (rc->values_num + 1) * sizeof (char *));
+       if (values_new == NULL)
+       {
+               char errbuf[1024];
+               void *cache_key = NULL;
+
+               sstrerror (errno, errbuf, sizeof (errbuf));
+
+               c_avl_remove (cache, filename, &cache_key, NULL);
+               pthread_mutex_unlock (&cache_lock);
+
+               ERROR ("rrdtool plugin: realloc failed: %s", errbuf);
+
+               sfree (cache_key);
+               sfree (rc->values);
+               sfree (rc);
+               return (-1);
+       }
+       rc->values = values_new;
+
+       rc->values[rc->values_num] = strdup (value);
+       if (rc->values[rc->values_num] != NULL)
+               rc->values_num++;
+
+       if (rc->values_num == 1)
+               rc->first_value = value_time;
+       rc->last_value = value_time;
+
+       /* Insert if this is the first value */
+       if (new_rc == 1)
+       {
+               void *cache_key = strdup (filename);
+
+               if (cache_key == NULL)
+               {
+                       char errbuf[1024];
+                       sstrerror (errno, errbuf, sizeof (errbuf));
+
+                       pthread_mutex_unlock (&cache_lock);
+
+                       ERROR ("rrdtool plugin: strdup failed: %s", errbuf);
+
+                       sfree (rc->values[0]);
+                       sfree (rc->values);
+                       sfree (rc);
+                       return (-1);
+               }
+
+               c_avl_insert (cache, cache_key, rc);
+       }
+
+       DEBUG ("rrdtool plugin: rrd_cache_insert: file = %s; "
+                       "values_num = %i; age = %.3f;",
+                       filename, rc->values_num,
+                       CDTIME_T_TO_DOUBLE (rc->last_value - rc->first_value));
+
+       if ((rc->last_value - rc->first_value) >= (cache_timeout + rc->random_variation))
+       {
+               /* XXX: If you need to lock both, cache_lock and queue_lock, at
+                * the same time, ALWAYS lock `cache_lock' first! */
+               if (rc->flags == FLAG_NONE)
+               {
+                       int status;
+
+                       status = rrd_queue_enqueue (filename, &queue_head, &queue_tail);
+                       if (status == 0)
+                               rc->flags = FLAG_QUEUED;
+
+                        rc->random_variation = rrd_get_random_variation ();
+               }
+               else
+               {
+                       DEBUG ("rrdtool plugin: `%s' is already queued.", filename);
+               }
+       }
+
+       if ((cache_timeout > 0) &&
+                       ((cdtime () - cache_flush_last) > cache_flush_timeout))
+               rrd_cache_flush (cache_flush_timeout);
+
+       pthread_mutex_unlock (&cache_lock);
+
+       return (0);
+} /* int rrd_cache_insert */
+
+static int rrd_cache_destroy (void) /* {{{ */
+{
+  void *key = NULL;
+  void *value = NULL;
+
+  int non_empty = 0;
+
+  pthread_mutex_lock (&cache_lock);
+
+  if (cache == NULL)
+  {
+    pthread_mutex_unlock (&cache_lock);
+    return (0);
+  }
+
+  while (c_avl_pick (cache, &key, &value) == 0)
+  {
+    rrd_cache_t *rc;
+    int i;
+
+    sfree (key);
+    key = NULL;
+
+    rc = value;
+    value = NULL;
+
+    if (rc->values_num > 0)
+      non_empty++;
+
+    for (i = 0; i < rc->values_num; i++)
+      sfree (rc->values[i]);
+    sfree (rc->values);
+    sfree (rc);
+  }
+
+  c_avl_destroy (cache);
+  cache = NULL;
+
+  if (non_empty > 0)
+  {
+    INFO ("rrdtool plugin: %i cache %s had values when destroying the cache.",
+        non_empty, (non_empty == 1) ? "entry" : "entries");
+  }
+  else
+  {
+    DEBUG ("rrdtool plugin: No values have been lost "
+        "when destroying the cache.");
+  }
+
+  pthread_mutex_unlock (&cache_lock);
+  return (0);
+} /* }}} int rrd_cache_destroy */
+
+static int rrd_compare_numeric (const void *a_ptr, const void *b_ptr)
+{
+       int a = *((int *) a_ptr);
+       int b = *((int *) b_ptr);
+
+       if (a < b)
+               return (-1);
+       else if (a > b)
+               return (1);
+       else
+               return (0);
+} /* int rrd_compare_numeric */
+
+static int rrd_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       struct stat  statbuf;
+       char         filename[512];
+       char         values[512];
+       int          status;
+
+       if (do_shutdown)
+               return (0);
+
+       if (0 != strcmp (ds->type, vl->type)) {
+               ERROR ("rrdtool plugin: DS type does not match value list type");
+               return -1;
+       }
+
+       if (value_list_to_filename (filename, sizeof (filename), vl) != 0)
+               return (-1);
+
+       if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+               return (-1);
+
+       if (stat (filename, &statbuf) == -1)
+       {
+               if (errno == ENOENT)
+               {
+                       status = cu_rrd_create_file (filename,
+                                       ds, vl, &rrdcreate_config);
+                       if (status != 0)
+                               return (-1);
+                       else if (rrdcreate_config.async)
+                               return (0);
+               }
+               else
+               {
+                       char errbuf[1024];
+                       ERROR ("stat(%s) failed: %s", filename,
+                                       sstrerror (errno, errbuf,
+                                               sizeof (errbuf)));
+                       return (-1);
+               }
+       }
+       else if (!S_ISREG (statbuf.st_mode))
+       {
+               ERROR ("stat(%s): Not a regular file!",
+                               filename);
+               return (-1);
+       }
+
+       status = rrd_cache_insert (filename, values, vl->time);
+
+       return (status);
+} /* int rrd_write */
+
+static int rrd_flush (cdtime_t timeout, const char *identifier,
+               __attribute__((unused)) user_data_t *user_data)
+{
+       pthread_mutex_lock (&cache_lock);
+
+       if (cache == NULL) {
+               pthread_mutex_unlock (&cache_lock);
+               return (0);
+       }
+
+       rrd_cache_flush_identifier (timeout, identifier);
+
+       pthread_mutex_unlock (&cache_lock);
+       return (0);
+} /* int rrd_flush */
+
+static int rrd_config (const char *key, const char *value)
+{
+       if (strcasecmp ("CacheTimeout", key) == 0)
+       {
+               double tmp = atof (value);
+               if (tmp < 0)
+               {
+                       fprintf (stderr, "rrdtool: `CacheTimeout' must "
+                                       "be greater than 0.\n");
+                       ERROR ("rrdtool: `CacheTimeout' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               cache_timeout = DOUBLE_TO_CDTIME_T (tmp);
+       }
+       else if (strcasecmp ("CacheFlush", key) == 0)
+       {
+               int tmp = atoi (value);
+               if (tmp < 0)
+               {
+                       fprintf (stderr, "rrdtool: `CacheFlush' must "
+                                       "be greater than 0.\n");
+                       ERROR ("rrdtool: `CacheFlush' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               cache_flush_timeout = tmp;
+       }
+       else if (strcasecmp ("DataDir", key) == 0)
+       {
+               if (datadir != NULL)
+                       free (datadir);
+               datadir = strdup (value);
+               if (datadir != NULL)
+               {
+                       int len = strlen (datadir);
+                       while ((len > 0) && (datadir[len - 1] == '/'))
+                       {
+                               len--;
+                               datadir[len] = '\0';
+                       }
+                       if (len <= 0)
+                       {
+                               free (datadir);
+                               datadir = NULL;
+                       }
+               }
+       }
+       else if (strcasecmp ("StepSize", key) == 0)
+       {
+               unsigned long temp = strtoul (value, NULL, 0);
+               if (temp > 0)
+                       rrdcreate_config.stepsize = temp;
+       }
+       else if (strcasecmp ("HeartBeat", key) == 0)
+       {
+               int temp = atoi (value);
+               if (temp > 0)
+                       rrdcreate_config.heartbeat = temp;
+       }
+       else if (strcasecmp ("CreateFilesAsync", key) == 0)
+       {
+               if (IS_TRUE (value))
+                       rrdcreate_config.async = 1;
+               else
+                       rrdcreate_config.async = 0;
+       }
+       else if (strcasecmp ("RRARows", key) == 0)
+       {
+               int tmp = atoi (value);
+               if (tmp <= 0)
+               {
+                       fprintf (stderr, "rrdtool: `RRARows' must "
+                                       "be greater than 0.\n");
+                       ERROR ("rrdtool: `RRARows' must "
+                                       "be greater than 0.\n");
+                       return (1);
+               }
+               rrdcreate_config.rrarows = tmp;
+       }
+       else if (strcasecmp ("RRATimespan", key) == 0)
+       {
+               char *saveptr = NULL;
+               char *dummy;
+               char *ptr;
+               char *value_copy;
+               int *tmp_alloc;
+
+               value_copy = strdup (value);
+               if (value_copy == NULL)
+                       return (1);
+
+               dummy = value_copy;
+               while ((ptr = strtok_r (dummy, ", \t", &saveptr)) != NULL)
+               {
+                       dummy = NULL;
+                       
+                       tmp_alloc = realloc (rrdcreate_config.timespans,
+                                       sizeof (int) * (rrdcreate_config.timespans_num + 1));
+                       if (tmp_alloc == NULL)
+                       {
+                               fprintf (stderr, "rrdtool: realloc failed.\n");
+                               ERROR ("rrdtool: realloc failed.\n");
+                               free (value_copy);
+                               return (1);
+                       }
+                       rrdcreate_config.timespans = tmp_alloc;
+                       rrdcreate_config.timespans[rrdcreate_config.timespans_num] = atoi (ptr);
+                       if (rrdcreate_config.timespans[rrdcreate_config.timespans_num] != 0)
+                               rrdcreate_config.timespans_num++;
+               } /* while (strtok_r) */
+
+               qsort (/* base = */ rrdcreate_config.timespans,
+                               /* nmemb  = */ rrdcreate_config.timespans_num,
+                               /* size   = */ sizeof (rrdcreate_config.timespans[0]),
+                               /* compar = */ rrd_compare_numeric);
+
+               free (value_copy);
+       }
+       else if (strcasecmp ("XFF", key) == 0)
+       {
+               double tmp = atof (value);
+               if ((tmp < 0.0) || (tmp >= 1.0))
+               {
+                       fprintf (stderr, "rrdtool: `XFF' must "
+                                       "be in the range 0 to 1 (exclusive).");
+                       ERROR ("rrdtool: `XFF' must "
+                                       "be in the range 0 to 1 (exclusive).");
+                       return (1);
+               }
+               rrdcreate_config.xff = tmp;
+       }
+       else if (strcasecmp ("WritesPerSecond", key) == 0)
+       {
+               double wps = atof (value);
+
+               if (wps < 0.0)
+               {
+                       fprintf (stderr, "rrdtool: `WritesPerSecond' must be "
+                                       "greater than or equal to zero.");
+                       return (1);
+               }
+               else if (wps == 0.0)
+               {
+                       write_rate = 0.0;
+               }
+               else
+               {
+                       write_rate = 1.0 / wps;
+               }
+       }
+       else if (strcasecmp ("RandomTimeout", key) == 0)
+        {
+               double tmp;
+
+               tmp = atof (value);
+               if (tmp < 0.0)
+               {
+                       fprintf (stderr, "rrdtool: `RandomTimeout' must "
+                                       "be greater than or equal to zero.\n");
+                       ERROR ("rrdtool: `RandomTimeout' must "
+                                       "be greater then or equal to zero.");
+               }
+               else
+               {
+                       random_timeout = DOUBLE_TO_CDTIME_T (tmp);
+               }
+       }
+       else
+       {
+               return (-1);
+       }
+       return (0);
+} /* int rrd_config */
+
+static int rrd_shutdown (void)
+{
+       pthread_mutex_lock (&cache_lock);
+       rrd_cache_flush (0);
+       pthread_mutex_unlock (&cache_lock);
+
+       pthread_mutex_lock (&queue_lock);
+       do_shutdown = 1;
+       pthread_cond_signal (&queue_cond);
+       pthread_mutex_unlock (&queue_lock);
+
+       if ((queue_thread_running != 0)
+                       && ((queue_head != NULL) || (flushq_head != NULL)))
+       {
+               INFO ("rrdtool plugin: Shutting down the queue thread. "
+                               "This may take a while.");
+       }
+       else if (queue_thread_running != 0)
+       {
+               INFO ("rrdtool plugin: Shutting down the queue thread.");
+       }
+
+       /* Wait for all the values to be written to disk before returning. */
+       if (queue_thread_running != 0)
+       {
+               pthread_join (queue_thread, NULL);
+               memset (&queue_thread, 0, sizeof (queue_thread));
+               queue_thread_running = 0;
+               DEBUG ("rrdtool plugin: queue_thread exited.");
+       }
+
+       rrd_cache_destroy ();
+
+       return (0);
+} /* int rrd_shutdown */
+
+static int rrd_init (void)
+{
+       static int init_once = 0;
+       int status;
+
+       if (init_once != 0)
+               return (0);
+       init_once = 1;
+
+       if (rrdcreate_config.heartbeat <= 0)
+               rrdcreate_config.heartbeat = 2 * rrdcreate_config.stepsize;
+
+       /* Set the cache up */
+       pthread_mutex_lock (&cache_lock);
+
+       cache = c_avl_create ((int (*) (const void *, const void *)) strcmp);
+       if (cache == NULL)
+       {
+               ERROR ("rrdtool plugin: c_avl_create failed.");
+               return (-1);
+       }
+
+       cache_flush_last = cdtime ();
+       if (cache_timeout == 0)
+       {
+               cache_flush_timeout = 0;
+       }
+       else if (cache_flush_timeout < cache_timeout)
+               cache_flush_timeout = 10 * cache_timeout;
+
+       pthread_mutex_unlock (&cache_lock);
+
+       status = plugin_thread_create (&queue_thread, /* attr = */ NULL,
+                       rrd_queue_thread, /* args = */ NULL);
+       if (status != 0)
+       {
+               ERROR ("rrdtool plugin: Cannot create queue-thread.");
+               return (-1);
+       }
+       queue_thread_running = 1;
+
+       DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %lu;"
+                       " heartbeat = %i; rrarows = %i; xff = %lf;",
+                       (datadir == NULL) ? "(null)" : datadir,
+                       rrdcreate_config.stepsize,
+                       rrdcreate_config.heartbeat,
+                       rrdcreate_config.rrarows,
+                       rrdcreate_config.xff);
+
+       return (0);
+} /* int rrd_init */
+
+void module_register (void)
+{
+       plugin_register_config ("rrdtool", rrd_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("rrdtool", rrd_init);
+       plugin_register_write ("rrdtool", rrd_write, /* user_data = */ NULL);
+       plugin_register_flush ("rrdtool", rrd_flush, /* user_data = */ NULL);
+       plugin_register_shutdown ("rrdtool", rrd_shutdown);
+}
diff --git a/src/sensors.c b/src/sensors.c
new file mode 100644 (file)
index 0000000..f5b09bd
--- /dev/null
@@ -0,0 +1,600 @@
+/**
+ * collectd - src/sensors.c
+ * Copyright (C) 2005-2008  Florian octo Forster
+ * Copyright (C) 2006       Luboš Staněk
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   
+ *   Lubos Stanek <lubek at users.sourceforge.net> Wed Oct 27, 2006
+ *   - config ExtendedSensorNaming option
+ *   - precise sensor feature selection (chip-bus-address/type-feature)
+ *     with ExtendedSensorNaming
+ *   - more sensor features (finite list)
+ *   - honor sensors.conf's ignored
+ *   - config Sensor option
+ *   - config IgnoreSelected option
+ *
+ *   Henrique de Moraes Holschuh <hmh at debian.org>
+ *   - use default libsensors config file on API 0x400
+ *   - config SensorConfigFile option
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_ignorelist.h"
+
+#if defined(HAVE_SENSORS_SENSORS_H)
+# include <sensors/sensors.h>
+#endif
+
+#if !defined(SENSORS_API_VERSION)
+# define SENSORS_API_VERSION 0x000
+#endif
+
+/*
+ * The sensors library prior to version 3.0 (internal version 0x400) didn't
+ * report the type of values, only a name. The following lists are there to
+ * convert from the names to the type. They are not used with the new
+ * interface.
+ */
+#if SENSORS_API_VERSION < 0x400
+static char *sensor_type_name_map[] =
+{
+# define SENSOR_TYPE_VOLTAGE     0
+       "voltage",
+# define SENSOR_TYPE_FANSPEED    1
+       "fanspeed",
+# define SENSOR_TYPE_TEMPERATURE 2
+       "temperature",
+# define SENSOR_TYPE_POWER       3
+       "power",
+# define SENSOR_TYPE_UNKNOWN     4
+       NULL
+};
+
+struct sensors_labeltypes_s
+{
+       char *label;
+       int type;
+};
+typedef struct sensors_labeltypes_s sensors_labeltypes_t;
+
+/* finite list of known labels extracted from lm_sensors */
+static sensors_labeltypes_t known_features[] = 
+{
+       { "fan1", SENSOR_TYPE_FANSPEED },
+       { "fan2", SENSOR_TYPE_FANSPEED },
+       { "fan3", SENSOR_TYPE_FANSPEED },
+       { "fan4", SENSOR_TYPE_FANSPEED },
+       { "fan5", SENSOR_TYPE_FANSPEED },
+       { "fan6", SENSOR_TYPE_FANSPEED },
+       { "fan7", SENSOR_TYPE_FANSPEED },
+       { "AIN2", SENSOR_TYPE_VOLTAGE },
+       { "AIN1", SENSOR_TYPE_VOLTAGE },
+       { "in10", SENSOR_TYPE_VOLTAGE },
+       { "in9", SENSOR_TYPE_VOLTAGE },
+       { "in8", SENSOR_TYPE_VOLTAGE },
+       { "in7", SENSOR_TYPE_VOLTAGE },
+       { "in6", SENSOR_TYPE_VOLTAGE },
+       { "in5", SENSOR_TYPE_VOLTAGE },
+       { "in4", SENSOR_TYPE_VOLTAGE },
+       { "in3", SENSOR_TYPE_VOLTAGE },
+       { "in2", SENSOR_TYPE_VOLTAGE },
+       { "in0", SENSOR_TYPE_VOLTAGE },
+       { "CPU_Temp", SENSOR_TYPE_TEMPERATURE },
+       { "remote_temp", SENSOR_TYPE_TEMPERATURE },
+       { "temp1", SENSOR_TYPE_TEMPERATURE },
+       { "temp2", SENSOR_TYPE_TEMPERATURE },
+       { "temp3", SENSOR_TYPE_TEMPERATURE },
+       { "temp4", SENSOR_TYPE_TEMPERATURE },
+       { "temp5", SENSOR_TYPE_TEMPERATURE },
+       { "temp6", SENSOR_TYPE_TEMPERATURE },
+       { "temp7", SENSOR_TYPE_TEMPERATURE },
+       { "temp", SENSOR_TYPE_TEMPERATURE },
+       { "Vccp2", SENSOR_TYPE_VOLTAGE },
+       { "Vccp1", SENSOR_TYPE_VOLTAGE },
+       { "vdd", SENSOR_TYPE_VOLTAGE },
+       { "vid5", SENSOR_TYPE_VOLTAGE },
+       { "vid4", SENSOR_TYPE_VOLTAGE },
+       { "vid3", SENSOR_TYPE_VOLTAGE },
+       { "vid2", SENSOR_TYPE_VOLTAGE },
+       { "vid1", SENSOR_TYPE_VOLTAGE },
+       { "vid", SENSOR_TYPE_VOLTAGE },
+       { "vin4", SENSOR_TYPE_VOLTAGE },
+       { "vin3", SENSOR_TYPE_VOLTAGE },
+       { "vin2", SENSOR_TYPE_VOLTAGE },
+       { "vin1", SENSOR_TYPE_VOLTAGE },
+       { "voltbatt", SENSOR_TYPE_VOLTAGE },
+       { "volt12", SENSOR_TYPE_VOLTAGE },
+       { "volt5", SENSOR_TYPE_VOLTAGE },
+       { "vrm", SENSOR_TYPE_VOLTAGE },
+       { "5.0V", SENSOR_TYPE_VOLTAGE },
+       { "5V", SENSOR_TYPE_VOLTAGE },
+       { "3.3V", SENSOR_TYPE_VOLTAGE },
+       { "2.5V", SENSOR_TYPE_VOLTAGE },
+       { "2.0V", SENSOR_TYPE_VOLTAGE },
+       { "12V", SENSOR_TYPE_VOLTAGE },
+       { "power1", SENSOR_TYPE_POWER }
+};
+static int known_features_num = STATIC_ARRAY_SIZE (known_features);
+/* end new naming */
+#endif /* SENSORS_API_VERSION < 0x400 */
+
+static const char *config_keys[] =
+{
+       "Sensor",
+       "IgnoreSelected",
+       "SensorConfigFile"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+#if SENSORS_API_VERSION < 0x400
+typedef struct featurelist
+{
+       const sensors_chip_name    *chip;
+       const sensors_feature_data *data;
+       int                         type;
+       struct featurelist         *next;
+} featurelist_t;
+
+# ifndef SENSORS_CONF_PATH
+#  define SENSORS_CONF_PATH "/etc/sensors.conf"
+# endif
+static char *conffile = SENSORS_CONF_PATH;
+/* #endif SENSORS_API_VERSION < 0x400 */
+
+#elif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500)
+typedef struct featurelist
+{
+       const sensors_chip_name    *chip;
+       const sensors_feature      *feature;
+       const sensors_subfeature   *subfeature;
+       struct featurelist         *next;
+} featurelist_t;
+
+static char *conffile = NULL;
+/* #endif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500) */
+
+#else /* if SENSORS_API_VERSION >= 0x500 */
+# error "This version of libsensors is not supported yet. Please report this " \
+       "as bug."
+#endif
+
+featurelist_t *first_feature = NULL;
+static ignorelist_t *sensor_list;
+
+#if SENSORS_API_VERSION < 0x400
+/* full chip name logic borrowed from lm_sensors */
+static int sensors_snprintf_chip_name (char *buf, size_t buf_size,
+               const sensors_chip_name *chip)
+{
+       int status = -1;
+
+       if (chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
+       {
+               status = ssnprintf (buf, buf_size,
+                               "%s-isa-%04x",
+                               chip->prefix,
+                               chip->addr);
+       }
+       else if (chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY)
+       {
+               status = snprintf (buf, buf_size, "%s-%s-%04x",
+                               chip->prefix,
+                               chip->busname,
+                               chip->addr);
+       }
+       else
+       {
+               status = snprintf (buf, buf_size, "%s-i2c-%d-%02x",
+                               chip->prefix,
+                               chip->bus,
+                               chip->addr);
+       }
+
+       return (status);
+} /* int sensors_snprintf_chip_name */
+
+static int sensors_feature_name_to_type (const char *name)
+{
+       int i;
+
+       /* Yes, this is slow, but it's only ever done during initialization, so
+        * it's a one time cost.. */
+       for (i = 0; i < known_features_num; i++)
+               if (strcasecmp (known_features[i].label, name) == 0)
+                       return (known_features[i].type);
+
+       return (SENSOR_TYPE_UNKNOWN);
+} /* int sensors_feature_name_to_type */
+#endif
+
+static int sensors_config (const char *key, const char *value)
+{
+       if (sensor_list == NULL)
+               sensor_list = ignorelist_create (1);
+
+       /* TODO: This setting exists for compatibility with old versions of
+        * lm-sensors. Remove support for those ancient versions in the next
+        * major release. */
+       if (strcasecmp (key, "SensorConfigFile") == 0)
+       {
+               char *tmp = strdup (value);
+               if (tmp != NULL)
+               {
+                       sfree (conffile);
+                       conffile = tmp;
+               }
+       }
+       else if (strcasecmp (key, "Sensor") == 0)
+       {
+               if (ignorelist_add (sensor_list, value))
+               {
+                       ERROR ("sensors plugin: "
+                                       "Cannot add value to ignorelist.");
+                       return (1);
+               }
+       }
+       else if (strcasecmp (key, "IgnoreSelected") == 0)
+       {
+               ignorelist_set_invert (sensor_list, 1);
+               if (IS_TRUE (value))
+                       ignorelist_set_invert (sensor_list, 0);
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+}
+
+void sensors_free_features (void)
+{
+       featurelist_t *thisft;
+       featurelist_t *nextft;
+
+       if (first_feature == NULL)
+               return;
+
+       sensors_cleanup ();
+
+       for (thisft = first_feature; thisft != NULL; thisft = nextft)
+       {
+               nextft = thisft->next;
+               sfree (thisft);
+       }
+       first_feature = NULL;
+}
+
+static int sensors_load_conf (void)
+{
+       static int call_once = 0;
+
+       FILE *fh = NULL;
+       featurelist_t *last_feature = NULL;
+       
+       const sensors_chip_name *chip;
+       int chip_num;
+
+       int status;
+
+       if (call_once)
+               return 0;
+
+       call_once = 1;
+
+       if (conffile != NULL)
+       {
+               fh = fopen (conffile, "r");
+               if (fh == NULL)
+               {
+                       char errbuf[1024];
+                       ERROR ("sensors plugin: fopen(%s) failed: %s", conffile,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+       }
+
+       status = sensors_init (fh);
+       if (fh)
+               fclose (fh);
+
+       if (status != 0)
+       {
+               ERROR ("sensors plugin: Cannot initialize sensors. "
+                               "Data will not be collected.");
+               return (-1);
+       }
+
+#if SENSORS_API_VERSION < 0x400
+       chip_num = 0;
+       while ((chip = sensors_get_detected_chips (&chip_num)) != NULL)
+       {
+               int feature_num0 = 0;
+               int feature_num1 = 0;
+
+               while (42)
+               {
+                       const sensors_feature_data *feature;
+                       int feature_type;
+                       featurelist_t *fl;
+
+                       feature = sensors_get_all_features (*chip,
+                                       &feature_num0, &feature_num1);
+
+                       /* Check if all features have been read. */
+                       if (feature == NULL)
+                               break;
+
+                       /* "master features" only */
+                       if (feature->mapping != SENSORS_NO_MAPPING)
+                       {
+                               DEBUG ("sensors plugin: sensors_load_conf: "
+                                               "Ignoring subfeature `%s', "
+                                               "because (feature->mapping "
+                                               "!= SENSORS_NO_MAPPING).",
+                                               feature->name);
+                               continue;
+                       }
+
+                       /* skip ignored in sensors.conf */
+                       if (sensors_get_ignored (*chip, feature->number) == 0)
+                       {
+                               DEBUG ("sensors plugin: sensors_load_conf: "
+                                               "Ignoring subfeature `%s', "
+                                               "because "
+                                               "`sensors_get_ignored' told "
+                                               "me so.",
+                                               feature->name);
+                               continue;
+                       }
+
+                       feature_type = sensors_feature_name_to_type (
+                                       feature->name);
+                       if (feature_type == SENSOR_TYPE_UNKNOWN)
+                       {
+                               DEBUG ("sensors plugin: sensors_load_conf: "
+                                               "Ignoring subfeature `%s', "
+                                               "because its type is "
+                                               "unknown.",
+                                               feature->name);
+                               continue;
+                       }
+
+                       fl = (featurelist_t *) malloc (sizeof (featurelist_t));
+                       if (fl == NULL)
+                       {
+                               ERROR ("sensors plugin: malloc failed.");
+                               continue;
+                       }
+                       memset (fl, '\0', sizeof (featurelist_t));
+
+                       fl->chip = chip;
+                       fl->data = feature;
+                       fl->type = feature_type;
+
+                       if (first_feature == NULL)
+                               first_feature = fl;
+                       else
+                               last_feature->next = fl;
+                       last_feature = fl;
+               } /* while sensors_get_all_features */
+       } /* while sensors_get_detected_chips */
+/* #endif SENSORS_API_VERSION < 0x400 */
+
+#elif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500)
+       chip_num = 0;
+       while ((chip = sensors_get_detected_chips (NULL, &chip_num)) != NULL)
+       {
+               const sensors_feature *feature;
+               int feature_num = 0;
+
+               while ((feature = sensors_get_features (chip, &feature_num)) != NULL)
+               {
+                       const sensors_subfeature *subfeature;
+                       int subfeature_num = 0;
+
+                       /* Only handle voltage, fanspeeds and temperatures */
+                       if ((feature->type != SENSORS_FEATURE_IN)
+                                       && (feature->type != SENSORS_FEATURE_FAN)
+                                       && (feature->type != SENSORS_FEATURE_TEMP)
+                                       && (feature->type != SENSORS_FEATURE_POWER))
+                       {
+                               DEBUG ("sensors plugin: sensors_load_conf: "
+                                               "Ignoring feature `%s', "
+                                               "because its type is not "
+                                               "supported.", feature->name);
+                               continue;
+                       }
+
+                       while ((subfeature = sensors_get_all_subfeatures (chip,
+                                                       feature, &subfeature_num)) != NULL)
+                       {
+                               featurelist_t *fl;
+
+                               if ((subfeature->type != SENSORS_SUBFEATURE_IN_INPUT)
+                                               && (subfeature->type != SENSORS_SUBFEATURE_FAN_INPUT)
+                                               && (subfeature->type != SENSORS_SUBFEATURE_TEMP_INPUT)
+                                               && (subfeature->type != SENSORS_SUBFEATURE_POWER_INPUT))
+                                       continue;
+
+                               fl = (featurelist_t *) malloc (sizeof (featurelist_t));
+                               if (fl == NULL)
+                               {
+                                       ERROR ("sensors plugin: malloc failed.");
+                                       continue;
+                               }
+                               memset (fl, '\0', sizeof (featurelist_t));
+
+                               fl->chip = chip;
+                               fl->feature = feature;
+                               fl->subfeature = subfeature;
+
+                               if (first_feature == NULL)
+                                       first_feature = fl;
+                               else
+                                       last_feature->next = fl;
+                               last_feature  = fl;
+                       } /* while (subfeature) */
+               } /* while (feature) */
+       } /* while (chip) */
+#endif /* (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500) */
+
+       if (first_feature == NULL)
+       {
+               sensors_cleanup ();
+               INFO ("sensors plugin: lm_sensors reports no "
+                               "features. Data will not be collected.");
+               return (-1);
+       }
+
+       return (0);
+} /* int sensors_load_conf */
+
+static int sensors_shutdown (void)
+{
+       sensors_free_features ();
+       ignorelist_free (sensor_list);
+
+       return (0);
+} /* int sensors_shutdown */
+
+static void sensors_submit (const char *plugin_instance,
+               const char *type, const char *type_instance,
+               double val)
+{
+       char match_key[1024];
+       int status;
+
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       status = ssnprintf (match_key, sizeof (match_key), "%s/%s-%s",
+                       plugin_instance, type, type_instance);
+       if (status < 1)
+               return;
+
+       if (sensor_list != NULL)
+       {
+               DEBUG ("sensors plugin: Checking ignorelist for `%s'", match_key);
+               if (ignorelist_match (sensor_list, match_key))
+                       return;
+       }
+
+       values[0].gauge = val;
+
+       vl.values = values;
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "sensors", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void sensors_submit */
+
+static int sensors_read (void)
+{
+       featurelist_t *fl;
+
+       if (sensors_load_conf () != 0)
+               return (-1);
+
+#if SENSORS_API_VERSION < 0x400
+       for (fl = first_feature; fl != NULL; fl = fl->next)
+       {
+               double value;
+               int status;
+               char plugin_instance[DATA_MAX_NAME_LEN];
+               char type_instance[DATA_MAX_NAME_LEN];
+
+               status = sensors_get_feature (*fl->chip,
+                               fl->data->number, &value);
+               if (status < 0)
+                       continue;
+
+               status = sensors_snprintf_chip_name (plugin_instance,
+                               sizeof (plugin_instance), fl->chip);
+               if (status < 0)
+                       continue;
+
+               sstrncpy (type_instance, fl->data->name,
+                               sizeof (type_instance));
+
+               sensors_submit (plugin_instance,
+                               sensor_type_name_map[fl->type],
+                               type_instance,
+                               value);
+       } /* for fl = first_feature .. NULL */
+/* #endif SENSORS_API_VERSION < 0x400 */
+
+#elif (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500)
+       for (fl = first_feature; fl != NULL; fl = fl->next)
+       {
+               double value;
+               int status;
+               char plugin_instance[DATA_MAX_NAME_LEN];
+               char type_instance[DATA_MAX_NAME_LEN];
+               const char *type;
+
+               status = sensors_get_value (fl->chip,
+                               fl->subfeature->number, &value);
+               if (status < 0)
+                       continue;
+
+               status = sensors_snprintf_chip_name (plugin_instance,
+                               sizeof (plugin_instance), fl->chip);
+               if (status < 0)
+                       continue;
+
+               sstrncpy (type_instance, fl->feature->name,
+                               sizeof (type_instance));
+
+               if (fl->feature->type == SENSORS_FEATURE_IN)
+                       type = "voltage";
+               else if (fl->feature->type
+                               == SENSORS_FEATURE_FAN)
+                       type = "fanspeed";
+               else if (fl->feature->type
+                               == SENSORS_FEATURE_TEMP)
+                       type = "temperature";
+               else if (fl->feature->type
+                               == SENSORS_FEATURE_POWER)
+                       type = "power";
+               else
+                       continue;
+
+               sensors_submit (plugin_instance, type, type_instance, value);
+       } /* for fl = first_feature .. NULL */
+#endif /* (SENSORS_API_VERSION >= 0x400) && (SENSORS_API_VERSION < 0x500) */
+
+       return (0);
+} /* int sensors_read */
+
+void module_register (void)
+{
+       plugin_register_config ("sensors", sensors_config,
+                       config_keys, config_keys_num);
+       plugin_register_read ("sensors", sensors_read);
+       plugin_register_shutdown ("sensors", sensors_shutdown);
+} /* void module_register */
diff --git a/src/serial.c b/src/serial.c
new file mode 100644 (file)
index 0000000..4300822
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+ * collectd - src/serial.c
+ * Copyright (C) 2005,2006  David Bacher
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   David Bacher <drbacher at gmail.com>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+static void serial_submit (const char *type_instance,
+               derive_t rx, derive_t tx)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       vl.values = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "serial", sizeof (vl.plugin));
+       sstrncpy (vl.type, "serial_octets", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance,
+                       sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int serial_read (void)
+{
+       FILE *fh;
+       char buffer[1024];
+
+       derive_t rx = 0;
+       derive_t tx = 0;
+       
+       char *fields[16];
+       int i, numfields;
+       int len;
+
+       /* there are a variety of names for the serial device */
+       if ((fh = fopen ("/proc/tty/driver/serial", "r")) == NULL &&
+               (fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("serial: fopen: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               int have_rx = 0, have_tx = 0;
+
+               numfields = strsplit (buffer, fields, 16);
+
+               if (numfields < 6)
+                       continue;
+
+               /*
+                * 0: uart:16550A port:000003F8 irq:4 tx:0 rx:0
+                * 1: uart:16550A port:000002F8 irq:3 tx:0 rx:0
+                */
+               len = strlen (fields[0]) - 1;
+               if (len < 1)
+                       continue;
+               if (fields[0][len] != ':')
+                       continue;
+               fields[0][len] = '\0';
+
+               for (i = 1; i < numfields; i++)
+               {
+                       len = strlen (fields[i]);
+                       if (len < 4)
+                               continue;
+
+                       if (strncmp (fields[i], "tx:", 3) == 0)
+                       {
+                               tx = atoll (fields[i] + 3);
+                               have_tx++;
+                       }
+                       else if (strncmp (fields[i], "rx:", 3) == 0)
+                       {
+                               rx = atoll (fields[i] + 3);
+                               have_rx++;
+                       }
+               }
+
+               if ((have_rx == 0) || (have_tx == 0))
+                       continue;
+
+               serial_submit (fields[0], rx, tx);
+       }
+
+       fclose (fh);
+       return (0);
+} /* int serial_read */
+
+void module_register (void)
+{
+       plugin_register_read ("serial", serial_read);
+} /* void module_register */
diff --git a/src/sigrok.c b/src/sigrok.c
new file mode 100644 (file)
index 0000000..eecb54c
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * collectd - src/sigrok.c
+ * Copyright (C) 2013 Bert Vermeulen
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Bert Vermeulen <bert at biot.com>
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <pthread.h>
+
+#include <glib.h>
+#include <libsigrok/libsigrok.h>
+
+/* Minimum interval between dispatches coming from this plugin. The RRD
+ * plugin, at least, complains when written to with sub-second intervals.*/
+#define DEFAULT_MIN_DISPATCH_INTERVAL TIME_T_TO_CDTIME_T(0)
+
+static pthread_t sr_thread;
+static int sr_thread_running = FALSE;
+GSList *config_devices;
+static int num_devices;
+static int loglevel = SR_LOG_WARN;
+static struct sr_context *sr_ctx;
+
+struct config_device {
+       char *name;
+       char *driver;
+       char *conn;
+       char *serialcomm;
+       struct sr_dev_inst *sdi;
+       cdtime_t min_dispatch_interval;
+       cdtime_t last_dispatch;
+};
+
+
+static int sigrok_log_callback(void*cb_data __attribute__((unused)),
+               int msg_loglevel, const char *format, va_list args)
+{
+       char s[512];
+
+       if (msg_loglevel <= loglevel) {
+               vsnprintf(s, 512, format, args);
+               plugin_log(LOG_INFO, "sigrok plugin: %s", s);
+       }
+
+       return 0;
+}
+
+static int sigrok_config_device(oconfig_item_t *ci)
+{
+       struct config_device *cfdev;
+       int i;
+
+       if (!(cfdev = malloc(sizeof(struct config_device)))) {
+               ERROR("sigrok plugin: malloc() failed.");
+               return -1;
+       }
+       memset(cfdev, 0, sizeof(*cfdev));
+       if (cf_util_get_string(ci, &cfdev->name)) {
+               free(cfdev);
+               WARNING("sigrok plugin: Invalid device name.");
+               return -1;
+       }
+       cfdev->min_dispatch_interval = DEFAULT_MIN_DISPATCH_INTERVAL;
+
+       for (i = 0; i < ci->children_num; i++) {
+               oconfig_item_t *item = ci->children + i;
+               if (!strcasecmp(item->key, "driver"))
+                       cf_util_get_string(item, &cfdev->driver);
+               else if (!strcasecmp(item->key, "conn"))
+                       cf_util_get_string(item, &cfdev->conn);
+               else if (!strcasecmp(item->key, "serialcomm"))
+                       cf_util_get_string(item, &cfdev->serialcomm);
+               else if (!strcasecmp(item->key, "minimuminterval"))
+                       cf_util_get_cdtime(item, &cfdev->min_dispatch_interval);
+               else
+                       WARNING("sigrok plugin: Invalid keyword \"%s\".",
+                                       item->key);
+       }
+
+       config_devices = g_slist_append(config_devices, cfdev);
+
+       return 0;
+}
+
+static int sigrok_config(oconfig_item_t *ci)
+{
+       int i;
+
+       for (i = 0; i < ci->children_num; i++) {
+               oconfig_item_t *item = ci->children + i;
+               if (strcasecmp("LogLevel", item->key) == 0) {
+                       int status;
+                       int tmp = -1;
+
+                       status = cf_util_get_int (item, &tmp);
+                       if (status != 0)
+                               continue;
+                       else if ((tmp < 0) || (tmp > 5)) {
+                               ERROR ("sigrok plugin: The \"LogLevel\" "
+                                               "configuration option expects "
+                                               "an integer between 0 and 5 "
+                                               "(inclusive); you provided %i.",
+                                               tmp);
+                               continue;
+                       }
+                       loglevel = tmp;
+               } else if (!strcasecmp(item->key, "Device"))
+                       sigrok_config_device(item);
+               else
+                       WARNING("sigrok plugin: Invalid keyword \"%s\".",
+                                       item->key);
+       }
+
+       return 0;
+}
+
+static char *sigrok_value_type(const struct sr_datafeed_analog *analog)
+{
+       char *s;
+
+       if (analog->mq == SR_MQ_VOLTAGE)
+               s = "voltage";
+       else if (analog->mq == SR_MQ_CURRENT)
+               s = "current";
+       else if (analog->mq == SR_MQ_FREQUENCY)
+               s = "frequency";
+       else if (analog->mq == SR_MQ_POWER)
+               s = "power";
+       else if (analog->mq == SR_MQ_TEMPERATURE)
+               s = "temperature";
+       else if (analog->mq == SR_MQ_RELATIVE_HUMIDITY)
+               s = "humidity";
+       else if (analog->mq == SR_MQ_SOUND_PRESSURE_LEVEL)
+               s = "spl";
+       else
+               s = "gauge";
+
+       return s;
+}
+
+static void sigrok_feed_callback(const struct sr_dev_inst *sdi,
+               const struct sr_datafeed_packet *packet, void *cb_data)
+{
+       const struct sr_datafeed_analog *analog;
+       struct config_device *cfdev;
+       GSList *l;
+       value_t value;
+       value_list_t vl = VALUE_LIST_INIT;
+
+       /* Find this device's configuration. */
+       cfdev = NULL;
+       for (l = config_devices; l; l = l->next) {
+               cfdev = l->data;
+               if (cfdev->sdi == sdi) {
+                       /* Found it. */
+                       break;
+               }
+               cfdev = NULL;
+       }
+
+       if (!cfdev) {
+               ERROR("sigrok plugin: Received data from driver \"%s\" but "
+                               "can't find a configuration / device matching "
+                               "it.", sdi->driver->name);
+               return;
+       }
+
+       if (packet->type == SR_DF_END) {
+               /* TODO: try to restart acquisition after a delay? */
+               WARNING("sigrok plugin: acquisition for \"%s\" ended.",
+                               cfdev->name);
+               return;
+       }
+
+       if (packet->type != SR_DF_ANALOG)
+               return;
+
+       if ((cfdev->min_dispatch_interval != 0)
+                       && ((cdtime() - cfdev->last_dispatch)
+                               < cfdev->min_dispatch_interval))
+               return;
+
+       /* Ignore all but the first sample on the first probe. */
+       analog = packet->payload;
+       value.gauge = analog->data[0];
+       vl.values = &value;
+       vl.values_len = 1;
+       sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+       sstrncpy(vl.plugin, "sigrok", sizeof(vl.plugin));
+       ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance),
+                       "%s", cfdev->name);
+       sstrncpy(vl.type, sigrok_value_type(analog), sizeof(vl.type));
+
+       plugin_dispatch_values(&vl);
+       cfdev->last_dispatch = cdtime();
+}
+
+static void sigrok_free_drvopts(struct sr_config *src)
+{
+       g_variant_unref(src->data);
+       g_free(src);
+}
+
+static int sigrok_init_driver(struct config_device *cfdev,
+               struct sr_dev_driver *drv)
+{
+       struct sr_config *src;
+       GSList *devlist, *drvopts;
+       char hwident[512];
+
+       if (sr_driver_init(sr_ctx, drv) != SR_OK)
+               /* Error was logged by libsigrok. */
+               return -1;
+
+       drvopts = NULL;
+       if (cfdev->conn) {
+               if (!(src = malloc(sizeof(struct sr_config))))
+                       return -1;
+               src->key = SR_CONF_CONN;
+               src->data = g_variant_new_string(cfdev->conn);
+               drvopts = g_slist_append(drvopts, src);
+       }
+       if (cfdev->serialcomm) {
+               if (!(src = malloc(sizeof(struct sr_config))))
+                       return -1;
+               src->key = SR_CONF_SERIALCOMM;
+               src->data = g_variant_new_string(cfdev->serialcomm);
+               drvopts = g_slist_append(drvopts, src);
+       }
+       devlist = sr_driver_scan(drv, drvopts);
+       g_slist_free_full(drvopts, (GDestroyNotify)sigrok_free_drvopts);
+       if (!devlist) {
+               /* Not an error, but the user should know about it. */
+               WARNING("sigrok plugin: No device found for \"%s\".",
+                               cfdev->name);
+               return 0;
+       }
+
+       if (g_slist_length(devlist) > 1) {
+               INFO("sigrok plugin: %d sigrok devices for device entry "
+                               "\"%s\": must be 1.",
+                               g_slist_length(devlist), cfdev->name);
+               return -1;
+       }
+       cfdev->sdi = devlist->data;
+       g_slist_free(devlist);
+       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)
+               return -1;
+
+       if (sr_session_dev_add(cfdev->sdi) != SR_OK)
+               return -1;
+
+       return 1;
+}
+
+static void *sigrok_read_thread(void *arg __attribute__((unused)))
+{
+       struct sr_dev_driver *drv, **drvlist;
+       GSList *l;
+       struct config_device *cfdev;
+       int ret, i;
+
+       sr_log_callback_set(sigrok_log_callback, NULL);
+       sr_log_loglevel_set(loglevel);
+
+       if ((ret = sr_init(&sr_ctx)) != SR_OK) {
+               ERROR("sigrok plugin: Failed to initialize libsigrok: %s.",
+                               sr_strerror(ret));
+               return NULL;
+       }
+
+       if (!sr_session_new())
+               return NULL;
+
+       num_devices = 0;
+       drvlist = sr_driver_list();
+       for (l = config_devices; l; l = l->next) {
+               cfdev = l->data;
+               drv = NULL;
+               for (i = 0; drvlist[i]; i++) {
+                       if (!strcmp(drvlist[i]->name, cfdev->driver)) {
+                               drv = drvlist[i];
+                               break;
+                       }
+               }
+               if (!drv) {
+                       ERROR("sigrok plugin: Unknown driver \"%s\".",
+                                       cfdev->driver);
+                       return NULL;
+               }
+
+               if ((ret = sigrok_init_driver(cfdev, drv)) < 0)
+                       /* Error was already logged. */
+                       return NULL;
+
+               num_devices += ret;
+       }
+
+       if (num_devices > 0) {
+               /* Do this only when we're sure there's hardware to talk to. */
+               if (sr_session_datafeed_callback_add(sigrok_feed_callback, NULL)
+                               != SR_OK)
+                       return NULL;
+
+               /* Start acquisition on all devices. */
+               if (sr_session_start() != SR_OK)
+                       return NULL;
+
+               /* Main loop, runs forever. */
+               sr_session_run();
+
+               sr_session_stop();
+               sr_session_dev_remove_all();
+       }
+
+       sr_session_destroy();
+
+       sr_exit(sr_ctx);
+
+       pthread_exit(NULL);
+       sr_thread_running = FALSE;
+
+       return NULL;
+}
+
+static int sigrok_init(void)
+{
+       int status;
+
+       if (sr_thread_running) {
+               ERROR("sigrok plugin: Thread already running.");
+               return -1;
+       }
+
+       if ((status = plugin_thread_create(&sr_thread, NULL, sigrok_read_thread,
+                       NULL)) != 0) {
+               ERROR("sigrok plugin: Failed to create thread: %s.",
+                               strerror(status));
+               return -1;
+       }
+       sr_thread_running = TRUE;
+
+       return 0;
+}
+
+static int sigrok_shutdown(void)
+{
+       struct config_device *cfdev;
+       GSList *l;
+
+       if (sr_thread_running) {
+               pthread_cancel(sr_thread);
+               pthread_join(sr_thread, NULL);
+       }
+
+       for (l = config_devices; l; l = l->next) {
+               cfdev = l->data;
+               free(cfdev->name);
+               free(cfdev->driver);
+               free(cfdev->conn);
+               free(cfdev->serialcomm);
+               free(cfdev);
+       }
+       g_slist_free(config_devices);
+
+       return 0;
+}
+
+void module_register(void)
+{
+       plugin_register_complex_config("sigrok", sigrok_config);
+       plugin_register_init("sigrok", sigrok_init);
+       plugin_register_shutdown("sigrok", sigrok_shutdown);
+}
diff --git a/src/smart.c b/src/smart.c
new file mode 100644 (file)
index 0000000..3b113bd
--- /dev/null
@@ -0,0 +1,269 @@
+/**
+ * collectd - src/smart.c
+ * Copyright (C) 2014       Vincent Bernat
+ *
+ * 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:
+ *   Vincent Bernat <vbe at exoscale.ch>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#include <atasmart.h>
+#include <libudev.h>
+
+static const char *config_keys[] =
+{
+  "Disk",
+  "IgnoreSelected"
+};
+
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+static int smart_config (const char *key, const char *value)
+{
+  if (ignorelist == NULL)
+    ignorelist = ignorelist_create (/* invert = */ 1);
+  if (ignorelist == NULL)
+    return (1);
+
+  if (strcasecmp ("Disk", key) == 0)
+  {
+    ignorelist_add (ignorelist, value);
+  }
+  else if (strcasecmp ("IgnoreSelected", key) == 0)
+  {
+    int invert = 1;
+    if (IS_TRUE (value))
+      invert = 0;
+    ignorelist_set_invert (ignorelist, invert);
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int smart_config */
+
+static void smart_submit (const char *dev, char *type, char *type_inst, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedData *a,
+                                        void* userdata)
+{
+  const char *dev = userdata;
+  value_t values[4];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  if (!a->current_value_valid || !a->worst_value_valid) return;
+  values[0].gauge = a->current_value;
+  values[1].gauge = a->worst_value;
+  values[2].gauge = a->threshold_valid?a->threshold:0;
+  values[3].gauge = a->pretty_value;
+
+  vl.values = values;
+  vl.values_len = 4;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, "smart_attribute", sizeof (vl.type));
+  sstrncpy (vl.type_instance, a->name, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+
+  if (a->threshold_valid && a->current_value <= a->threshold)
+  {
+    notification_t notif = { NOTIF_WARNING,
+                             cdtime (),
+                             "",
+                             "",
+                             "smart", "",
+                             "smart_attribute",
+                             "",
+                             NULL };
+    sstrncpy (notif.host, hostname_g, sizeof (notif.host));
+    sstrncpy (notif.plugin_instance, dev, sizeof (notif.plugin_instance));
+    sstrncpy (notif.type_instance, a->name, sizeof (notif.type_instance));
+    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);
+  }
+}
+
+static void smart_handle_disk (const char *dev)
+{
+  SkDisk *d = NULL;
+  SkBool awake = FALSE;
+  SkBool available = FALSE;
+  const char *shortname;
+  const SkSmartParsedData *spd;
+  uint64_t poweron, powercycles, badsectors, temperature;
+
+  shortname = strrchr(dev, '/');
+  if (!shortname) return;
+  shortname++;
+  if (ignorelist_match (ignorelist, shortname) != 0) {
+    DEBUG ("smart plugin: ignoring %s.", dev);
+    return;
+  }
+
+  DEBUG ("smart plugin: checking SMART status of %s.",
+         dev);
+
+  if (sk_disk_open (dev, &d) < 0)
+  {
+    ERROR ("smart plugin: unable to open %s.", dev);
+    return;
+  }
+  if (sk_disk_identify_is_available (d, &available) < 0 || !available)
+  {
+    DEBUG ("smart plugin: disk %s cannot be identified.", dev);
+    goto end;
+  }
+  if (sk_disk_smart_is_available (d, &available) < 0 || !available)
+  {
+    DEBUG ("smart plugin: disk %s has no SMART support.", dev);
+    goto end;
+  }
+  if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+  {
+    DEBUG ("smart plugin: disk %s is sleeping.", dev);
+    goto end;
+  }
+  if (sk_disk_smart_read_data (d) < 0)
+  {
+    ERROR ("smart plugin: unable to get SMART data for disk %s.", dev);
+    goto end;
+  }
+  if (sk_disk_smart_parse (d, &spd) < 0)
+  {
+    ERROR ("smart plugin: unable to parse SMART data for disk %s.", dev);
+    goto end;
+  }
+
+  /* Get some specific values */
+  if (sk_disk_smart_get_power_on (d, &poweron) < 0)
+  {
+    WARNING ("smart plugin: unable to get milliseconds since power on for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_poweron", "", poweron / 1000.);
+
+  if (sk_disk_smart_get_power_cycle (d, &powercycles) < 0)
+  {
+    WARNING ("smart plugin: unable to get number of power cycles for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_powercycles", "", powercycles);
+
+  if (sk_disk_smart_get_bad (d, &badsectors) < 0)
+  {
+    WARNING ("smart plugin: unable to get number of bad sectors for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_badsectors", "", badsectors);
+
+  if (sk_disk_smart_get_temperature (d, &temperature) < 0)
+  {
+    WARNING ("smart plugin: unable to get temperature for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_temperature", "", temperature / 1000. - 273.15);
+
+  /* Grab all attributes */
+  if (sk_disk_smart_parse_attributes(d, smart_handle_disk_attribute,
+                                     (char *)shortname) < 0)
+  {
+    ERROR ("smart plugin: unable to handle SMART attributes for %s.",
+           dev);
+  }
+
+end:
+  sk_disk_free(d);
+}
+
+static int smart_read (void)
+{
+  struct udev *handle_udev;
+  struct udev_enumerate *enumerate;
+  struct udev_list_entry *devices, *dev_list_entry;
+  struct udev_device *dev;
+
+  /* Use udev to get a list of disks */
+  handle_udev = udev_new();
+  if (!handle_udev)
+  {
+    ERROR ("smart plugin: unable to initialize udev.");
+    return (-1);
+  }
+  enumerate = udev_enumerate_new (handle_udev);
+  udev_enumerate_add_match_subsystem (enumerate, "block");
+  udev_enumerate_add_match_property (enumerate, "DEVTYPE", "disk");
+  udev_enumerate_scan_devices (enumerate);
+  devices = udev_enumerate_get_list_entry (enumerate);
+  udev_list_entry_foreach (dev_list_entry, devices)
+  {
+    const char *path, *devpath;
+    path = udev_list_entry_get_name (dev_list_entry);
+    dev = udev_device_new_from_syspath (handle_udev, path);
+    devpath = udev_device_get_devnode (dev);
+
+    /* Query status with libatasmart */
+    smart_handle_disk (devpath);
+  }
+
+  udev_enumerate_unref (enumerate);
+  udev_unref (handle_udev);
+
+  return (0);
+} /* int smart_read */
+
+void module_register (void)
+{
+  plugin_register_config ("smart", smart_config,
+                          config_keys, config_keys_num);
+  plugin_register_read ("smart", smart_read);
+} /* void module_register */
diff --git a/src/snmp.c b/src/snmp.c
new file mode 100644 (file)
index 0000000..cb2bb36
--- /dev/null
@@ -0,0 +1,1865 @@
+/**
+ * collectd - src/snmp.c
+ * Copyright (C) 2007-2012  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_complain.h"
+
+#include <pthread.h>
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+#include <fnmatch.h>
+
+/*
+ * Private data structes
+ */
+struct oid_s
+{
+  oid oid[MAX_OID_LEN];
+  size_t oid_len;
+};
+typedef struct oid_s oid_t;
+
+union instance_u
+{
+  char  string[DATA_MAX_NAME_LEN];
+  oid_t oid;
+};
+typedef union instance_u instance_t;
+
+struct data_definition_s
+{
+  char *name; /* used to reference this from the `Collect' option */
+  char *type; /* used to find the data_set */
+  _Bool is_table;
+  instance_t instance;
+  char *instance_prefix;
+  oid_t *values;
+  int values_len;
+  double scale;
+  double shift;
+  struct data_definition_s *next;
+  char **ignores;
+  size_t ignores_len;
+  int invert_match;
+};
+typedef struct data_definition_s data_definition_t;
+
+struct host_definition_s
+{
+  char *name;
+  char *address;
+  int version;
+
+  /* snmpv1/2 options */
+  char *community;
+
+  /* snmpv3 security options */
+  char *username;
+  oid *auth_protocol;
+  size_t auth_protocol_len;
+  char *auth_passphrase;
+  oid *priv_protocol;
+  size_t priv_protocol_len;
+  char *priv_passphrase;
+  int security_level;
+  char *context;
+
+  void *sess_handle;
+  c_complain_t complaint;
+  cdtime_t interval;
+  data_definition_t **data_list;
+  int data_list_len;
+};
+typedef struct host_definition_s host_definition_t;
+
+/* These two types are used to cache values in `csnmp_read_table' to handle
+ * gaps in tables. */
+struct csnmp_list_instances_s
+{
+  oid_t suffix;
+  char instance[DATA_MAX_NAME_LEN];
+  struct csnmp_list_instances_s *next;
+};
+typedef struct csnmp_list_instances_s csnmp_list_instances_t;
+
+struct csnmp_table_values_s
+{
+  oid_t suffix;
+  value_t value;
+  struct csnmp_table_values_s *next;
+};
+typedef struct csnmp_table_values_s csnmp_table_values_t;
+
+/*
+ * Private variables
+ */
+static data_definition_t *data_head = NULL;
+
+/*
+ * Prototypes
+ */
+static int csnmp_read_host (user_data_t *ud);
+
+/*
+ * Private functions
+ */
+static void csnmp_oid_init (oid_t *dst, oid const *src, size_t n)
+{
+  assert (n <= STATIC_ARRAY_SIZE (dst->oid));
+  memcpy (dst->oid, src, sizeof (*src) * n);
+  dst->oid_len = n;
+}
+
+static int csnmp_oid_compare (oid_t const *left, oid_t const *right)
+{
+  return (snmp_oid_compare (left->oid, left->oid_len,
+        right->oid, right->oid_len));
+}
+
+static int csnmp_oid_suffix (oid_t *dst, oid_t const *src,
+    oid_t const *root)
+{
+  /* Make sure "src" is in "root"s subtree. */
+  if (src->oid_len <= root->oid_len)
+    return (EINVAL);
+  if (snmp_oid_ncompare (root->oid, root->oid_len,
+        src->oid, src->oid_len,
+        /* n = */ root->oid_len) != 0)
+    return (EINVAL);
+
+  memset (dst, 0, sizeof (*dst));
+  dst->oid_len = src->oid_len - root->oid_len;
+  memcpy (dst->oid, &src->oid[root->oid_len],
+      dst->oid_len * sizeof (dst->oid[0]));
+  return (0);
+}
+
+static int csnmp_oid_to_string (char *buffer, size_t buffer_size,
+    oid_t const *o)
+{
+  char oid_str[MAX_OID_LEN][16];
+  char *oid_str_ptr[MAX_OID_LEN];
+  size_t i;
+
+  for (i = 0; i < o->oid_len; i++)
+  {
+    ssnprintf (oid_str[i], sizeof (oid_str[i]), "%lu", (unsigned long) o->oid[i]);
+    oid_str_ptr[i] = oid_str[i];
+  }
+
+  return (strjoin (buffer, buffer_size,
+        oid_str_ptr, o->oid_len, /* separator = */ "."));
+}
+
+static void csnmp_host_close_session (host_definition_t *host) /* {{{ */
+{
+  if (host->sess_handle == NULL)
+    return;
+
+  snmp_sess_close (host->sess_handle);
+  host->sess_handle = NULL;
+} /* }}} void csnmp_host_close_session */
+
+static void csnmp_host_definition_destroy (void *arg) /* {{{ */
+{
+  host_definition_t *hd;
+
+  hd = arg;
+
+  if (hd == NULL)
+    return;
+
+  if (hd->name != NULL)
+  {
+    DEBUG ("snmp plugin: Destroying host definition for host `%s'.",
+        hd->name);
+  }
+
+  csnmp_host_close_session (hd);
+
+  sfree (hd->name);
+  sfree (hd->address);
+  sfree (hd->community);
+  sfree (hd->username);
+  sfree (hd->auth_passphrase);
+  sfree (hd->priv_passphrase);
+  sfree (hd->context);
+  sfree (hd->data_list);
+
+  sfree (hd);
+} /* }}} void csnmp_host_definition_destroy */
+
+/* Many functions to handle the configuration. {{{ */
+/* First there are many functions which do configuration stuff. It's a big
+ * bloated and messy, I'm afraid. */
+
+/*
+ * Callgraph for the config stuff:
+ *  csnmp_config
+ *  +-> call_snmp_init_once
+ *  +-> csnmp_config_add_data
+ *  !   +-> csnmp_config_add_data_instance
+ *  !   +-> csnmp_config_add_data_instance_prefix
+ *  !   +-> csnmp_config_add_data_values
+ *  +-> csnmp_config_add_host
+ *      +-> csnmp_config_add_host_version
+ *      +-> csnmp_config_add_host_collect
+ *      +-> csnmp_config_add_host_auth_protocol
+ *      +-> csnmp_config_add_host_priv_protocol
+ *      +-> csnmp_config_add_host_security_level
+ */
+static void call_snmp_init_once (void)
+{
+  static int have_init = 0;
+
+  if (have_init == 0)
+    init_snmp (PACKAGE_NAME);
+  have_init = 1;
+} /* void call_snmp_init_once */
+
+static int csnmp_config_add_data_instance (data_definition_t *dd, oconfig_item_t *ci)
+{
+  char buffer[DATA_MAX_NAME_LEN];
+  int status;
+
+  status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+  if (status != 0)
+    return status;
+
+  if (dd->is_table)
+  {
+    /* Instance is an OID */
+    dd->instance.oid.oid_len = MAX_OID_LEN;
+
+    if (!read_objid (buffer,
+          dd->instance.oid.oid, &dd->instance.oid.oid_len))
+    {
+      ERROR ("snmp plugin: read_objid (%s) failed.", buffer);
+      return (-1);
+    }
+  }
+  else
+  {
+    /* Instance is a simple string */
+    sstrncpy (dd->instance.string, buffer,
+        sizeof (dd->instance.string));
+  }
+
+  return (0);
+} /* int csnmp_config_add_data_instance */
+
+static int csnmp_config_add_data_instance_prefix (data_definition_t *dd,
+    oconfig_item_t *ci)
+{
+  int status;
+
+  if (!dd->is_table)
+  {
+    WARNING ("snmp plugin: data %s: InstancePrefix is ignored when `Table' "
+        "is set to `false'.", dd->name);
+    return (-1);
+  }
+
+  status = cf_util_get_string(ci, &dd->instance_prefix);
+  return status;
+} /* int csnmp_config_add_data_instance_prefix */
+
+static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *ci)
+{
+  int i;
+
+  if (ci->values_num < 1)
+  {
+    WARNING ("snmp plugin: `Values' needs at least one argument.");
+    return (-1);
+  }
+
+  for (i = 0; i < ci->values_num; i++)
+    if (ci->values[i].type != OCONFIG_TYPE_STRING)
+    {
+      WARNING ("snmp plugin: `Values' needs only string argument.");
+      return (-1);
+    }
+
+  sfree (dd->values);
+  dd->values_len = 0;
+  dd->values = (oid_t *) malloc (sizeof (oid_t) * ci->values_num);
+  if (dd->values == NULL)
+    return (-1);
+  dd->values_len = ci->values_num;
+
+  for (i = 0; i < ci->values_num; i++)
+  {
+    dd->values[i].oid_len = MAX_OID_LEN;
+
+    if (NULL == snmp_parse_oid (ci->values[i].value.string,
+          dd->values[i].oid, &dd->values[i].oid_len))
+    {
+      ERROR ("snmp plugin: snmp_parse_oid (%s) failed.",
+          ci->values[i].value.string);
+      free (dd->values);
+      dd->values = NULL;
+      dd->values_len = 0;
+      return (-1);
+    }
+  }
+
+  return (0);
+} /* int csnmp_config_add_data_instance */
+
+static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t *ci)
+{
+  int i;
+
+  if (ci->values_num < 1)
+    return (0);
+
+  for (i = 0; i < ci->values_num; i++)
+  {
+    if (ci->values[i].type != OCONFIG_TYPE_STRING)
+    {
+      WARNING ("snmp plugin: `Ignore' needs only string argument.");
+      return (-1);
+    }
+  }
+
+  dd->ignores_len = 0;
+  dd->ignores = NULL;
+
+  for (i = 0; i < ci->values_num; ++i)
+  {
+    if (strarray_add(&(dd->ignores), &(dd->ignores_len), ci->values[i].value.string) != 0)
+    {
+      ERROR("snmp plugin: Can't allocate memory");
+      strarray_free(dd->ignores, dd->ignores_len);
+      return (ENOMEM);
+    }
+  }
+  return 0;
+} /* int csnmp_config_add_data_blacklist */
+
+static int csnmp_config_add_data_blacklist_match_inverted(data_definition_t *dd, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
+  {
+    WARNING ("snmp plugin: `InvertMatch' needs exactly one boolean argument.");
+    return (-1);
+  }
+
+  dd->invert_match = ci->values[0].value.boolean ? 1 : 0;
+
+  return (0);
+} /* int csnmp_config_add_data_blacklist_match_inverted */
+
+static int csnmp_config_add_data (oconfig_item_t *ci)
+{
+  data_definition_t *dd;
+  int status = 0;
+  int i;
+
+  dd = (data_definition_t *) malloc (sizeof (data_definition_t));
+  if (dd == NULL)
+    return (-1);
+  memset (dd, '\0', sizeof (data_definition_t));
+
+  status = cf_util_get_string(ci, &dd->name);
+  if (status != 0)
+  {
+    free (dd);
+    return (-1);
+  }
+
+  dd->scale = 1.0;
+  dd->shift = 0.0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Type", option->key) == 0)
+      status = cf_util_get_string(option, &dd->type);
+    else if (strcasecmp ("Table", option->key) == 0)
+      status = cf_util_get_boolean(option, &dd->is_table);
+    else if (strcasecmp ("Instance", option->key) == 0)
+      status = csnmp_config_add_data_instance (dd, option);
+    else if (strcasecmp ("InstancePrefix", option->key) == 0)
+      status = csnmp_config_add_data_instance_prefix (dd, option);
+    else if (strcasecmp ("Values", option->key) == 0)
+      status = csnmp_config_add_data_values (dd, option);
+    else if (strcasecmp ("Shift", option->key) == 0)
+      status = cf_util_get_double(option, &dd->shift);
+    else if (strcasecmp ("Scale", option->key) == 0)
+      status = cf_util_get_double(option, &dd->scale);
+    else if (strcasecmp ("Ignore", option->key) == 0)
+      status = csnmp_config_add_data_blacklist(dd, option);
+    else if (strcasecmp ("InvertMatch", option->key) == 0)
+      status = csnmp_config_add_data_blacklist_match_inverted(dd, option);
+    else
+    {
+      WARNING ("snmp plugin: Option `%s' not allowed here.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (ci->children) */
+
+  while (status == 0)
+  {
+    if (dd->type == NULL)
+    {
+      WARNING ("snmp plugin: `Type' not given for data `%s'", dd->name);
+      status = -1;
+      break;
+    }
+    if (dd->values == NULL)
+    {
+      WARNING ("snmp plugin: No `Value' given for data `%s'", dd->name);
+      status = -1;
+      break;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+  {
+    sfree (dd->name);
+    sfree (dd->instance_prefix);
+    sfree (dd->values);
+    sfree (dd->ignores);
+    sfree (dd);
+    return (-1);
+  }
+
+  DEBUG ("snmp plugin: dd = { name = %s, type = %s, is_table = %s, values_len = %i }",
+      dd->name, dd->type, (dd->is_table != 0) ? "true" : "false", dd->values_len);
+
+  if (data_head == NULL)
+    data_head = dd;
+  else
+  {
+    data_definition_t *last;
+    last = data_head;
+    while (last->next != NULL)
+      last = last->next;
+    last->next = dd;
+  }
+
+  return (0);
+} /* int csnmp_config_add_data */
+
+static int csnmp_config_add_host_version (host_definition_t *hd, oconfig_item_t *ci)
+{
+  int version;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("snmp plugin: The `Version' config option needs exactly one number argument.");
+    return (-1);
+  }
+
+  version = (int) ci->values[0].value.number;
+  if ((version < 1) || (version > 3))
+  {
+    WARNING ("snmp plugin: `Version' must either be `1', `2', or `3'.");
+    return (-1);
+  }
+
+  hd->version = version;
+
+  return (0);
+} /* int csnmp_config_add_host_address */
+
+static int csnmp_config_add_host_collect (host_definition_t *host,
+    oconfig_item_t *ci)
+{
+  data_definition_t *data;
+  data_definition_t **data_list;
+  int data_list_len;
+  int i;
+
+  if (ci->values_num < 1)
+  {
+    WARNING ("snmp plugin: `Collect' needs at least one argument.");
+    return (-1);
+  }
+
+  for (i = 0; i < ci->values_num; i++)
+    if (ci->values[i].type != OCONFIG_TYPE_STRING)
+    {
+      WARNING ("snmp plugin: All arguments to `Collect' must be strings.");
+      return (-1);
+    }
+
+  data_list_len = host->data_list_len + ci->values_num;
+  data_list = (data_definition_t **) realloc (host->data_list,
+      sizeof (data_definition_t *) * data_list_len);
+  if (data_list == NULL)
+    return (-1);
+  host->data_list = data_list;
+
+  for (i = 0; i < ci->values_num; i++)
+  {
+    for (data = data_head; data != NULL; data = data->next)
+      if (strcasecmp (ci->values[i].value.string, data->name) == 0)
+        break;
+
+    if (data == NULL)
+    {
+      WARNING ("snmp plugin: No such data configured: `%s'",
+          ci->values[i].value.string);
+      continue;
+    }
+
+    DEBUG ("snmp plugin: Collect: host = %s, data[%i] = %s;",
+        host->name, host->data_list_len, data->name);
+
+    host->data_list[host->data_list_len] = data;
+    host->data_list_len++;
+  } /* for (values_num) */
+
+  return (0);
+} /* int csnmp_config_add_host_collect */
+
+static int csnmp_config_add_host_auth_protocol (host_definition_t *hd, oconfig_item_t *ci)
+{
+  char buffer[4];
+  int status;
+
+  status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+  if (status != 0)
+    return status;
+
+  if (strcasecmp("MD5", buffer) == 0) {
+    hd->auth_protocol = usmHMACMD5AuthProtocol;
+    hd->auth_protocol_len = sizeof(usmHMACMD5AuthProtocol)/sizeof(oid);
+  }
+  else if (strcasecmp("SHA", buffer) == 0) {
+    hd->auth_protocol = usmHMACSHA1AuthProtocol;
+    hd->auth_protocol_len = sizeof(usmHMACSHA1AuthProtocol)/sizeof(oid);
+  }
+  else
+  {
+    WARNING ("snmp plugin: The `AuthProtocol' config option must be `MD5' or `SHA'.");
+    return (-1);
+  }
+
+  DEBUG ("snmp plugin: host = %s; host->auth_protocol = %s;",
+      hd->name, hd->auth_protocol == usmHMACMD5AuthProtocol ? "MD5" : "SHA");
+
+  return (0);
+} /* int csnmp_config_add_host_auth_protocol */
+
+static int csnmp_config_add_host_priv_protocol (host_definition_t *hd, oconfig_item_t *ci)
+{
+  char buffer[4];
+  int status;
+
+  status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+  if (status != 0)
+    return status;
+
+  if (strcasecmp("AES", buffer) == 0)
+  {
+    hd->priv_protocol = usmAESPrivProtocol;
+    hd->priv_protocol_len = sizeof(usmAESPrivProtocol)/sizeof(oid);
+  }
+  else if (strcasecmp("DES", buffer) == 0) {
+    hd->priv_protocol = usmDESPrivProtocol;
+    hd->priv_protocol_len = sizeof(usmDESPrivProtocol)/sizeof(oid);
+  }
+  else
+  {
+    WARNING ("snmp plugin: The `PrivProtocol' config option must be `AES' or `DES'.");
+    return (-1);
+  }
+
+  DEBUG ("snmp plugin: host = %s; host->priv_protocol = %s;",
+      hd->name, hd->priv_protocol == usmAESPrivProtocol ? "AES" : "DES");
+
+  return (0);
+} /* int csnmp_config_add_host_priv_protocol */
+
+static int csnmp_config_add_host_security_level (host_definition_t *hd, oconfig_item_t *ci)
+{
+  char buffer[16];
+  int status;
+
+  status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+  if (status != 0)
+    return status;
+
+  if (strcasecmp("noAuthNoPriv", buffer) == 0)
+    hd->security_level = SNMP_SEC_LEVEL_NOAUTH;
+  else if (strcasecmp("authNoPriv", buffer) == 0)
+    hd->security_level = SNMP_SEC_LEVEL_AUTHNOPRIV;
+  else if (strcasecmp("authPriv", buffer) == 0)
+    hd->security_level = SNMP_SEC_LEVEL_AUTHPRIV;
+  else
+  {
+    WARNING ("snmp plugin: The `SecurityLevel' config option must be `noAuthNoPriv', `authNoPriv', or `authPriv'.");
+    return (-1);
+  }
+
+  DEBUG ("snmp plugin: host = %s; host->security_level = %d;",
+      hd->name, hd->security_level);
+
+  return (0);
+} /* int csnmp_config_add_host_security_level */
+
+static int csnmp_config_add_host (oconfig_item_t *ci)
+{
+  host_definition_t *hd;
+  int status = 0;
+  int i;
+
+  /* Registration stuff. */
+  char cb_name[DATA_MAX_NAME_LEN];
+  user_data_t cb_data;
+  struct timespec cb_interval;
+
+  hd = (host_definition_t *) malloc (sizeof (host_definition_t));
+  if (hd == NULL)
+    return (-1);
+  memset (hd, '\0', sizeof (host_definition_t));
+  hd->version = 2;
+  C_COMPLAIN_INIT (&hd->complaint);
+
+  status = cf_util_get_string(ci, &hd->name);
+  if (status != 0)
+    return status;
+
+  hd->sess_handle = NULL;
+  hd->interval = 0;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Address", option->key) == 0)
+      status = cf_util_get_string(option, &hd->address);
+    else if (strcasecmp ("Community", option->key) == 0)
+      status = cf_util_get_string(option, &hd->community);
+    else if (strcasecmp ("Version", option->key) == 0)
+      status = csnmp_config_add_host_version (hd, option);
+    else if (strcasecmp ("Collect", option->key) == 0)
+      csnmp_config_add_host_collect (hd, option);
+    else if (strcasecmp ("Interval", option->key) == 0)
+      cf_util_get_cdtime (option, &hd->interval);
+    else if (strcasecmp ("Username", option->key) == 0)
+      status = cf_util_get_string(option, &hd->username);
+    else if (strcasecmp ("AuthProtocol", option->key) == 0)
+      status = csnmp_config_add_host_auth_protocol (hd, option);
+    else if (strcasecmp ("PrivacyProtocol", option->key) == 0)
+      status = csnmp_config_add_host_priv_protocol (hd, option);
+    else if (strcasecmp ("AuthPassphrase", option->key) == 0)
+      status = cf_util_get_string(option, &hd->auth_passphrase);
+    else if (strcasecmp ("PrivacyPassphrase", option->key) == 0)
+      status = cf_util_get_string(option, &hd->priv_passphrase);
+    else if (strcasecmp ("SecurityLevel", option->key) == 0)
+      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
+    {
+      WARNING ("snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (ci->children) */
+
+  while (status == 0)
+  {
+    if (hd->address == NULL)
+    {
+      WARNING ("snmp plugin: `Address' not given for host `%s'", hd->name);
+      status = -1;
+      break;
+    }
+    if (hd->community == NULL && hd->version < 3)
+    {
+      WARNING ("snmp plugin: `Community' not given for host `%s'", hd->name);
+      status = -1;
+      break;
+    }
+    if (hd->version == 3)
+    {
+      if (hd->username == NULL)
+      {
+        WARNING ("snmp plugin: `Username' not given for host `%s'", hd->name);
+        status = -1;
+        break;
+      }
+      if (hd->security_level == 0)
+      {
+        WARNING ("snmp plugin: `SecurityLevel' not given for host `%s'", hd->name);
+        status = -1;
+        break;
+      }
+      if (hd->security_level == SNMP_SEC_LEVEL_AUTHNOPRIV || hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV)
+      {
+       if (hd->auth_protocol == NULL)
+       {
+         WARNING ("snmp plugin: `AuthProtocol' not given for host `%s'", hd->name);
+         status = -1;
+         break;
+       }
+       if (hd->auth_passphrase == NULL)
+       {
+         WARNING ("snmp plugin: `AuthPassphrase' not given for host `%s'", hd->name);
+         status = -1;
+         break;
+       }
+      }
+      if (hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV)
+      {
+       if (hd->priv_protocol == NULL)
+       {
+         WARNING ("snmp plugin: `PrivacyProtocol' not given for host `%s'", hd->name);
+         status = -1;
+         break;
+       }
+       if (hd->priv_passphrase == NULL)
+       {
+         WARNING ("snmp plugin: `PrivacyPassphrase' not given for host `%s'", hd->name);
+         status = -1;
+         break;
+       }
+      }
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+  {
+    csnmp_host_definition_destroy (hd);
+    return (-1);
+  }
+
+  DEBUG ("snmp plugin: hd = { name = %s, address = %s, community = %s, version = %i }",
+      hd->name, hd->address, hd->community, hd->version);
+
+  ssnprintf (cb_name, sizeof (cb_name), "snmp-%s", hd->name);
+
+  memset (&cb_data, 0, sizeof (cb_data));
+  cb_data.data = hd;
+  cb_data.free_func = csnmp_host_definition_destroy;
+
+  CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval);
+
+  status = plugin_register_complex_read (/* group = */ NULL, cb_name,
+      csnmp_read_host, /* interval = */ &cb_interval,
+      /* user_data = */ &cb_data);
+  if (status != 0)
+  {
+    ERROR ("snmp plugin: Registering complex read function failed.");
+    csnmp_host_definition_destroy (hd);
+    return (-1);
+  }
+
+  return (0);
+} /* int csnmp_config_add_host */
+
+static int csnmp_config (oconfig_item_t *ci)
+{
+  int i;
+
+  call_snmp_init_once ();
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+    if (strcasecmp ("Data", child->key) == 0)
+      csnmp_config_add_data (child);
+    else if (strcasecmp ("Host", child->key) == 0)
+      csnmp_config_add_host (child);
+    else
+    {
+      WARNING ("snmp plugin: Ignoring unknown config option `%s'.", child->key);
+    }
+  } /* for (ci->children) */
+
+  return (0);
+} /* int csnmp_config */
+
+/* }}} End of the config stuff. Now the interesting part begins */
+
+static void csnmp_host_open_session (host_definition_t *host)
+{
+  struct snmp_session sess;
+  int error;
+
+  if (host->sess_handle != NULL)
+    csnmp_host_close_session (host);
+
+  snmp_sess_init (&sess);
+  sess.peername = host->address;
+  switch (host->version)
+  {
+    case 1:
+      sess.version = SNMP_VERSION_1;
+      break;
+    case 3:
+      sess.version = SNMP_VERSION_3;
+      break;
+    default:
+      sess.version = SNMP_VERSION_2c;
+      break;
+  }
+
+  if (host->version == 3)
+  {
+    sess.securityName = host->username;
+    sess.securityNameLen = strlen (host->username);
+    sess.securityLevel = host->security_level;
+
+    if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV)
+    {
+      sess.securityAuthProto = host->auth_protocol;
+      sess.securityAuthProtoLen = host->auth_protocol_len;
+      sess.securityAuthKeyLen = USM_AUTH_KU_LEN;
+      error = generate_Ku (sess.securityAuthProto,
+           sess.securityAuthProtoLen,
+           (u_char *) host->auth_passphrase,
+           strlen(host->auth_passphrase),
+           sess.securityAuthKey,
+           &sess.securityAuthKeyLen);
+      if (error != SNMPERR_SUCCESS) {
+       ERROR ("snmp plugin: host %s: Error generating Ku from auth_passphrase. (Error %d)", host->name, error);
+      }
+    }
+
+    if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV)
+    {
+      sess.securityPrivProto = host->priv_protocol;
+      sess.securityPrivProtoLen = host->priv_protocol_len;
+      sess.securityPrivKeyLen = USM_PRIV_KU_LEN;
+      error = generate_Ku (sess.securityAuthProto,
+           sess.securityAuthProtoLen,
+           (u_char *) host->priv_passphrase,
+           strlen(host->priv_passphrase),
+           sess.securityPrivKey,
+           &sess.securityPrivKeyLen);
+      if (error != SNMPERR_SUCCESS) {
+       ERROR ("snmp plugin: host %s: Error generating Ku from priv_passphrase. (Error %d)", host->name, error);
+      }
+    }
+
+    if (host->context != NULL)
+    {
+      sess.contextName = host->context;
+      sess.contextNameLen = strlen (host->context);
+    }
+  }
+  else /* SNMPv1/2 "authenticates" with community string */
+  {
+    sess.community = (u_char *) host->community;
+    sess.community_len = strlen (host->community);
+  }
+
+  /* snmp_sess_open will copy the `struct snmp_session *'. */
+  host->sess_handle = snmp_sess_open (&sess);
+
+  if (host->sess_handle == NULL)
+  {
+    char *errstr = NULL;
+
+    snmp_error (&sess, NULL, NULL, &errstr);
+
+    ERROR ("snmp plugin: host %s: snmp_sess_open failed: %s",
+        host->name, (errstr == NULL) ? "Unknown problem" : errstr);
+    sfree (errstr);
+  }
+} /* void csnmp_host_open_session */
+
+/* TODO: Check if negative values wrap around. Problem: negative temperatures. */
+static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
+    double scale, double shift,
+    const char *host_name, const char *data_name)
+{
+  value_t ret;
+  uint64_t tmp_unsigned = 0;
+  int64_t tmp_signed = 0;
+  _Bool defined = 1;
+  /* Set to true when the original SNMP type appears to have been signed. */
+  _Bool prefer_signed = 0;
+
+  if ((vl->type == ASN_INTEGER)
+      || (vl->type == ASN_UINTEGER)
+      || (vl->type == ASN_COUNTER)
+#ifdef ASN_TIMETICKS
+      || (vl->type == ASN_TIMETICKS)
+#endif
+      || (vl->type == ASN_GAUGE))
+  {
+    tmp_unsigned = (uint32_t) *vl->val.integer;
+    tmp_signed = (int32_t) *vl->val.integer;
+
+    if ((vl->type == ASN_INTEGER)
+        || (vl->type == ASN_GAUGE))
+      prefer_signed = 1;
+
+    DEBUG ("snmp plugin: Parsed int32 value is %"PRIu64".", tmp_unsigned);
+  }
+  else if (vl->type == ASN_COUNTER64)
+  {
+    tmp_unsigned = (uint32_t) vl->val.counter64->high;
+    tmp_unsigned = tmp_unsigned << 32;
+    tmp_unsigned += (uint32_t) vl->val.counter64->low;
+    tmp_signed = (int64_t) tmp_unsigned;
+    DEBUG ("snmp plugin: Parsed int64 value is %"PRIu64".", tmp_unsigned);
+  }
+  else if (vl->type == ASN_OCTET_STR)
+  {
+    /* We'll handle this later.. */
+  }
+  else
+  {
+    char oid_buffer[1024];
+
+    memset (oid_buffer, 0, sizeof (oid_buffer));
+    snprint_objid (oid_buffer, sizeof (oid_buffer) - 1,
+        vl->name, vl->name_length);
+
+#ifdef ASN_NULL
+    if (vl->type == ASN_NULL)
+      INFO ("snmp plugin: OID \"%s\" is undefined (type ASN_NULL)",
+          oid_buffer);
+    else
+#endif
+      WARNING ("snmp plugin: I don't know the ASN type #%i "
+               "(OID: \"%s\", data block \"%s\", host block \"%s\")",
+          (int) vl->type, oid_buffer,
+          (data_name != NULL) ? data_name : "UNKNOWN",
+          (host_name != NULL) ? host_name : "UNKNOWN");
+
+    defined = 0;
+  }
+
+  if (vl->type == ASN_OCTET_STR)
+  {
+    int status = -1;
+
+    if (vl->val.string != NULL)
+    {
+      char string[64];
+      size_t string_length;
+
+      string_length = sizeof (string) - 1;
+      if (vl->val_len < string_length)
+        string_length = vl->val_len;
+
+      /* The strings we get from the Net-SNMP library may not be null
+       * terminated. That is why we're using `memcpy' here and not `strcpy'.
+       * `string_length' is set to `vl->val_len' which holds the length of the
+       * string.  -octo */
+      memcpy (string, vl->val.string, string_length);
+      string[string_length] = 0;
+
+      status = parse_value (string, &ret, type);
+      if (status != 0)
+      {
+        ERROR ("snmp plugin: host %s: csnmp_value_list_to_value: Parsing string as %s failed: %s",
+            (host_name != NULL) ? host_name : "UNKNOWN",
+            DS_TYPE_TO_STRING (type), string);
+      }
+    }
+
+    if (status != 0)
+    {
+      switch (type)
+      {
+        case DS_TYPE_COUNTER:
+        case DS_TYPE_DERIVE:
+        case DS_TYPE_ABSOLUTE:
+          memset (&ret, 0, sizeof (ret));
+          break;
+
+        case DS_TYPE_GAUGE:
+          ret.gauge = NAN;
+          break;
+
+        default:
+          ERROR ("snmp plugin: csnmp_value_list_to_value: Unknown "
+              "data source type: %i.", type);
+          ret.gauge = NAN;
+      }
+    }
+  } /* if (vl->type == ASN_OCTET_STR) */
+  else if (type == DS_TYPE_COUNTER)
+  {
+    ret.counter = tmp_unsigned;
+  }
+  else if (type == DS_TYPE_GAUGE)
+  {
+    if (!defined)
+      ret.gauge = NAN;
+    else if (prefer_signed)
+      ret.gauge = (scale * tmp_signed) + shift;
+    else
+      ret.gauge = (scale * tmp_unsigned) + shift;
+  }
+  else if (type == DS_TYPE_DERIVE)
+  {
+    if (prefer_signed)
+      ret.derive = (derive_t) tmp_signed;
+    else
+      ret.derive = (derive_t) tmp_unsigned;
+  }
+  else if (type == DS_TYPE_ABSOLUTE)
+  {
+    ret.absolute = (absolute_t) tmp_unsigned;
+  }
+  else
+  {
+    ERROR ("snmp plugin: csnmp_value_list_to_value: Unknown data source "
+        "type: %i.", type);
+    ret.gauge = NAN;
+  }
+
+  return (ret);
+} /* value_t csnmp_value_list_to_value */
+
+static int csnmp_strvbcopy_hexstring (char *dst, /* {{{ */
+    const struct variable_list *vb, size_t dst_size)
+{
+  char *buffer_ptr;
+  size_t buffer_free;
+  size_t i;
+
+  buffer_ptr = dst;
+  buffer_free = dst_size;
+
+  for (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]);
+
+    if (status >= buffer_free)
+    {
+      buffer_ptr += (buffer_free - 1);
+      *buffer_ptr = 0;
+      return (dst_size + (buffer_free - status));
+    }
+    else /* if (status < buffer_free) */
+    {
+      buffer_ptr += status;
+      buffer_free -= status;
+    }
+  }
+
+  return ((int) (dst_size - buffer_free));
+} /* }}} int csnmp_strvbcopy_hexstring */
+
+static int csnmp_strvbcopy (char *dst, /* {{{ */
+    const struct variable_list *vb, size_t dst_size)
+{
+  char *src;
+  size_t num_chars;
+  size_t i;
+
+  if (vb->type == ASN_OCTET_STR)
+    src = (char *) vb->val.string;
+  else if (vb->type == ASN_BIT_STR)
+    src = (char *) vb->val.bitstring;
+  else
+  {
+    dst[0] = 0;
+    return (EINVAL);
+  }
+
+  num_chars = dst_size - 1;
+  if (num_chars > vb->val_len)
+    num_chars = vb->val_len;
+
+  for (i = 0; i < num_chars; i++)
+  {
+    /* Check for control characters. */
+    if ((unsigned char)src[i] < 32)
+      return (csnmp_strvbcopy_hexstring (dst, vb, dst_size));
+    dst[i] = src[i];
+  }
+  dst[num_chars] = 0;
+
+  return ((int) vb->val_len);
+} /* }}} int csnmp_strvbcopy */
+
+static int csnmp_instance_list_add (csnmp_list_instances_t **head,
+    csnmp_list_instances_t **tail,
+    const struct snmp_pdu *res,
+    const host_definition_t *hd, const data_definition_t *dd)
+{
+  csnmp_list_instances_t *il;
+  struct variable_list *vb;
+  oid_t vb_name;
+  int status;
+  uint32_t i;
+  uint32_t is_matched;
+
+  /* Set vb on the last variable */
+  for (vb = res->variables;
+      (vb != NULL) && (vb->next_variable != NULL);
+      vb = vb->next_variable)
+    /* do nothing */;
+  if (vb == NULL)
+    return (-1);
+
+  csnmp_oid_init (&vb_name, vb->name, vb->name_length);
+
+  il = malloc (sizeof (*il));
+  if (il == NULL)
+  {
+    ERROR ("snmp plugin: malloc failed.");
+    return (-1);
+  }
+  memset (il, 0, sizeof (*il));
+  il->next = NULL;
+
+  status = csnmp_oid_suffix (&il->suffix, &vb_name, &dd->instance.oid);
+  if (status != 0)
+  {
+    sfree (il);
+    return (status);
+  }
+
+  /* Get instance name */
+  if ((vb->type == ASN_OCTET_STR) || (vb->type == ASN_BIT_STR))
+  {
+    char *ptr;
+
+    csnmp_strvbcopy (il->instance, vb, sizeof (il->instance));
+    is_matched = 0;
+    for (i = 0; i < dd->ignores_len; i++)
+    {
+      status = fnmatch(dd->ignores[i], il->instance, 0);
+      if (status == 0)
+      {
+        if (dd->invert_match == 0)
+        {
+          sfree(il);
+          return 0;
+        }
+       else
+       {
+          is_matched = 1;
+         break;
+       }
+      }
+    }
+    if (dd->invert_match != 0 && is_matched == 0)
+    {
+      sfree(il);
+      return 0;
+    }
+    for (ptr = il->instance; *ptr != '\0'; ptr++)
+    {
+      if ((*ptr > 0) && (*ptr < 32))
+        *ptr = ' ';
+      else if (*ptr == '/')
+        *ptr = '_';
+    }
+    DEBUG ("snmp plugin: il->instance = `%s';", il->instance);
+  }
+  else
+  {
+    value_t val = csnmp_value_list_to_value (vb, DS_TYPE_COUNTER,
+        /* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
+    ssnprintf (il->instance, sizeof (il->instance),
+        "%llu", val.counter);
+  }
+
+  /* TODO: Debugging output */
+
+  if (*head == NULL)
+    *head = il;
+  else
+    (*tail)->next = il;
+  *tail = il;
+
+  return (0);
+} /* int csnmp_instance_list_add */
+
+static int csnmp_dispatch_table (host_definition_t *host, data_definition_t *data,
+    csnmp_list_instances_t *instance_list,
+    csnmp_table_values_t **value_table)
+{
+  const data_set_t *ds;
+  value_list_t vl = VALUE_LIST_INIT;
+
+  csnmp_list_instances_t *instance_list_ptr;
+  csnmp_table_values_t **value_table_ptr;
+
+  int i;
+  _Bool have_more;
+  oid_t current_suffix;
+
+  ds = plugin_get_ds (data->type);
+  if (!ds)
+  {
+    ERROR ("snmp plugin: DataSet `%s' not defined.", data->type);
+    return (-1);
+  }
+  assert (ds->ds_num == data->values_len);
+
+  instance_list_ptr = instance_list;
+
+  value_table_ptr = malloc (sizeof (*value_table_ptr) * data->values_len);
+  if (value_table_ptr == NULL)
+    return (-1);
+  for (i = 0; i < data->values_len; i++)
+    value_table_ptr[i] = value_table[i];
+
+  vl.values_len = ds->ds_num;
+  vl.values = malloc (sizeof (*vl.values) * vl.values_len);
+  if (vl.values == NULL)
+  {
+    ERROR ("snmp plugin: malloc failed.");
+    sfree (value_table_ptr);
+    return (-1);
+  }
+
+  sstrncpy (vl.host, host->name, sizeof (vl.host));
+  sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
+
+  vl.interval = host->interval;
+
+  have_more = 1;
+  memset (&current_suffix, 0, sizeof (current_suffix));
+  while (have_more)
+  {
+    _Bool suffix_skipped = 0;
+
+    /* Determine next suffix to handle. */
+    if (instance_list != NULL)
+    {
+      if (instance_list_ptr == NULL)
+      {
+        have_more = 0;
+        continue;
+      }
+
+      memcpy (&current_suffix, &instance_list_ptr->suffix, sizeof (current_suffix));
+    }
+    else /* no instance configured */
+    {
+      csnmp_table_values_t *ptr = value_table_ptr[0];
+      if (ptr == NULL)
+      {
+        have_more = 0;
+        continue;
+      }
+
+      memcpy (&current_suffix, &ptr->suffix, sizeof (current_suffix));
+    }
+
+    /* Update all the value_table_ptr to point at the entry with the same
+     * trailing partial OID */
+    for (i = 0; i < data->values_len; i++)
+    {
+      while ((value_table_ptr[i] != NULL)
+          && (csnmp_oid_compare (&value_table_ptr[i]->suffix, &current_suffix) < 0))
+        value_table_ptr[i] = value_table_ptr[i]->next;
+
+      if (value_table_ptr[i] == NULL)
+      {
+        have_more = 0;
+        break;
+      }
+      else if (csnmp_oid_compare (&value_table_ptr[i]->suffix, &current_suffix) > 0)
+      {
+        /* This suffix is missing in the subtree. Indicate this with the
+         * "suffix_skipped" flag and try the next instance / suffix. */
+        suffix_skipped = 1;
+        break;
+      }
+    } /* for (i = 0; i < columns; i++) */
+
+    if (!have_more)
+      break;
+
+    /* Matching the values failed. Start from the beginning again. */
+    if (suffix_skipped)
+    {
+      if (instance_list != NULL)
+        instance_list_ptr = instance_list_ptr->next;
+      else
+        value_table_ptr[0] = value_table_ptr[0]->next;
+
+      continue;
+    }
+
+    /* if we reach this line, all value_table_ptr[i] are non-NULL and are set
+     * to the same subid. instance_list_ptr is either NULL or points to the
+     * same subid, too. */
+#if COLLECT_DEBUG
+    for (i = 1; i < data->values_len; i++)
+    {
+      assert (value_table_ptr[i] != NULL);
+      assert (csnmp_oid_compare (&value_table_ptr[i-1]->suffix,
+            &value_table_ptr[i]->suffix) == 0);
+    }
+    assert ((instance_list_ptr == NULL)
+        || (csnmp_oid_compare (&instance_list_ptr->suffix,
+            &value_table_ptr[0]->suffix) == 0));
+#endif
+
+    sstrncpy (vl.type, data->type, sizeof (vl.type));
+
+    {
+      char temp[DATA_MAX_NAME_LEN];
+
+      if (instance_list_ptr == NULL)
+        csnmp_oid_to_string (temp, sizeof (temp), &current_suffix);
+      else
+        sstrncpy (temp, instance_list_ptr->instance, sizeof (temp));
+
+      if (data->instance_prefix == NULL)
+        sstrncpy (vl.type_instance, temp, sizeof (vl.type_instance));
+      else
+        ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s%s",
+            data->instance_prefix, temp);
+    }
+
+    for (i = 0; i < data->values_len; i++)
+      vl.values[i] = value_table_ptr[i]->value;
+
+    /* If we get here `vl.type_instance' and all `vl.values' have been set */
+    plugin_dispatch_values (&vl);
+
+    if (instance_list != NULL)
+      instance_list_ptr = instance_list_ptr->next;
+    else
+      value_table_ptr[0] = value_table_ptr[0]->next;
+  } /* while (have_more) */
+
+  sfree (vl.values);
+  sfree (value_table_ptr);
+
+  return (0);
+} /* int csnmp_dispatch_table */
+
+static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
+{
+  struct snmp_pdu *req;
+  struct snmp_pdu *res;
+  struct variable_list *vb;
+
+  const data_set_t *ds;
+
+  uint32_t oid_list_len = (uint32_t) (data->values_len + 1);
+  /* Holds the last OID returned by the device. We use this in the GETNEXT
+   * request to proceed. */
+  oid_t oid_list[oid_list_len];
+  /* Set to false when an OID has left its subtree so we don't re-request it
+   * again. */
+  _Bool oid_list_todo[oid_list_len];
+
+  int status;
+  int i;
+  uint32_t j;
+
+  /* `value_list_head' and `value_list_tail' implement a linked list for each
+   * value. `instance_list_head' and `instance_list_tail' implement a linked list of
+   * instance names. This is used to jump gaps in the table. */
+  csnmp_list_instances_t *instance_list_head;
+  csnmp_list_instances_t *instance_list_tail;
+  csnmp_table_values_t **value_list_head;
+  csnmp_table_values_t **value_list_tail;
+
+  DEBUG ("snmp plugin: csnmp_read_table (host = %s, data = %s)",
+      host->name, data->name);
+
+  if (host->sess_handle == NULL)
+  {
+    DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL");
+    return (-1);
+  }
+
+  ds = plugin_get_ds (data->type);
+  if (!ds)
+  {
+    ERROR ("snmp plugin: DataSet `%s' not defined.", data->type);
+    return (-1);
+  }
+
+  if (ds->ds_num != data->values_len)
+  {
+    ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+        data->type, ds->ds_num, data->values_len);
+    return (-1);
+  }
+
+  /* We need a copy of all the OIDs, because GETNEXT will destroy them. */
+  memcpy (oid_list, data->values, data->values_len * sizeof (oid_t));
+  if (data->instance.oid.oid_len > 0)
+    memcpy (oid_list + data->values_len, &data->instance.oid, sizeof (oid_t));
+  else /* no InstanceFrom option specified. */
+    oid_list_len--;
+
+  for (j = 0; j < oid_list_len; j++)
+    oid_list_todo[j] = 1;
+
+  /* We're going to construct n linked lists, one for each "value".
+   * value_list_head will contain pointers to the heads of these linked lists,
+   * value_list_tail will contain pointers to the tail of the lists. */
+  value_list_head = calloc (data->values_len, sizeof (*value_list_head));
+  value_list_tail = calloc (data->values_len, sizeof (*value_list_tail));
+  if ((value_list_head == NULL) || (value_list_tail == NULL))
+  {
+    ERROR ("snmp plugin: csnmp_read_table: calloc failed.");
+    sfree (value_list_head);
+    sfree (value_list_tail);
+    return (-1);
+  }
+
+  instance_list_head = NULL;
+  instance_list_tail = NULL;
+
+  status = 0;
+  while (status == 0)
+  {
+    int oid_list_todo_num;
+
+    req = snmp_pdu_create (SNMP_MSG_GETNEXT);
+    if (req == NULL)
+    {
+      ERROR ("snmp plugin: snmp_pdu_create failed.");
+      status = -1;
+      break;
+    }
+
+    oid_list_todo_num = 0;
+    for (j = 0; j < oid_list_len; j++)
+    {
+      /* Do not rerequest already finished OIDs */
+      if (!oid_list_todo[j])
+        continue;
+      oid_list_todo_num++;
+      snmp_add_null_var (req, oid_list[j].oid, oid_list[j].oid_len);
+    }
+
+    if (oid_list_todo_num == 0)
+    {
+      /* The request is still empty - so we are finished */
+      DEBUG ("snmp plugin: all variables have left their subtree");
+      status = 0;
+      break;
+    }
+
+    res = NULL;
+    status = snmp_sess_synch_response (host->sess_handle, req, &res);
+    if ((status != STAT_SUCCESS) || (res == NULL))
+    {
+      char *errstr = NULL;
+
+      snmp_sess_error (host->sess_handle, NULL, NULL, &errstr);
+
+      c_complain (LOG_ERR, &host->complaint,
+          "snmp plugin: host %s: snmp_sess_synch_response failed: %s",
+          host->name, (errstr == NULL) ? "Unknown problem" : errstr);
+
+      if (res != NULL)
+        snmp_free_pdu (res);
+      res = NULL;
+
+      /* snmp_synch_response already freed our PDU */
+      req = NULL;
+      sfree (errstr);
+      csnmp_host_close_session (host);
+
+      status = -1;
+      break;
+    }
+
+    status = 0;
+    assert (res != NULL);
+    c_release (LOG_INFO, &host->complaint,
+        "snmp plugin: host %s: snmp_sess_synch_response successful.",
+        host->name);
+
+    vb = res->variables;
+    if (vb == NULL)
+    {
+      status = -1;
+      break;
+    }
+
+    for (vb = res->variables, i = 0; (vb != NULL); vb = vb->next_variable, i++)
+    {
+      /* Calculate value index from todo list */
+      while (!oid_list_todo[i] && (i < oid_list_len))
+        i++;
+
+      /* An instance is configured and the res variable we process is the
+       * instance value (last index) */
+      if ((data->instance.oid.oid_len > 0) && (i == data->values_len))
+      {
+        if ((vb->type == SNMP_ENDOFMIBVIEW)
+            || (snmp_oid_ncompare (data->instance.oid.oid,
+                data->instance.oid.oid_len,
+                vb->name, vb->name_length,
+                data->instance.oid.oid_len) != 0))
+        {
+          DEBUG ("snmp plugin: host = %s; data = %s; Instance left its subtree.",
+              host->name, data->name);
+          oid_list_todo[i] = 0;
+          continue;
+        }
+
+        /* Allocate a new `csnmp_list_instances_t', insert the instance name and
+         * add it to the list */
+        if (csnmp_instance_list_add (&instance_list_head, &instance_list_tail,
+              res, host, data) != 0)
+        {
+          ERROR ("snmp plugin: host %s: csnmp_instance_list_add failed.",
+              host->name);
+          status = -1;
+          break;
+        }
+      }
+      else /* The variable we are processing is a normal value */
+      {
+        csnmp_table_values_t *vt;
+        oid_t vb_name;
+        oid_t suffix;
+        int ret;
+
+        csnmp_oid_init (&vb_name, vb->name, vb->name_length);
+
+        /* Calculate the current suffix. This is later used to check that the
+         * suffix is increasing. This also checks if we left the subtree */
+        ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
+        if (ret != 0)
+        {
+          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+              "Value probably left its subtree.",
+              host->name, data->name, i);
+          oid_list_todo[i] = 0;
+          continue;
+        }
+
+        /* Make sure the OIDs returned by the agent are increasing. Otherwise our
+         * table matching algorithm will get confused. */
+        if ((value_list_tail[i] != NULL)
+            && (csnmp_oid_compare (&suffix, &value_list_tail[i]->suffix) <= 0))
+        {
+          DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
+              "Suffix is not increasing.",
+              host->name, data->name, i);
+          oid_list_todo[i] = 0;
+          continue;
+        }
+
+        vt = malloc (sizeof (*vt));
+        if (vt == NULL)
+        {
+          ERROR ("snmp plugin: malloc failed.");
+          status = -1;
+          break;
+        }
+        memset (vt, 0, sizeof (*vt));
+
+        vt->value = csnmp_value_list_to_value (vb, ds->ds[i].type,
+            data->scale, data->shift, host->name, data->name);
+        memcpy (&vt->suffix, &suffix, sizeof (vt->suffix));
+        vt->next = NULL;
+
+        if (value_list_tail[i] == NULL)
+          value_list_head[i] = vt;
+        else
+          value_list_tail[i]->next = vt;
+        value_list_tail[i] = vt;
+      }
+
+      /* Copy OID to oid_list[i] */
+      memcpy (oid_list[i].oid, vb->name, sizeof (oid) * vb->name_length);
+      oid_list[i].oid_len = vb->name_length;
+
+    } /* for (vb = res->variables ...) */
+
+    if (res != NULL)
+      snmp_free_pdu (res);
+    res = NULL;
+  } /* while (status == 0) */
+
+  if (res != NULL)
+    snmp_free_pdu (res);
+  res = NULL;
+
+  if (req != NULL)
+    snmp_free_pdu (req);
+  req = NULL;
+
+  if (status == 0)
+    csnmp_dispatch_table (host, data, instance_list_head, value_list_head);
+
+  /* Free all allocated variables here */
+  while (instance_list_head != NULL)
+  {
+    csnmp_list_instances_t *next = instance_list_head->next;
+    sfree (instance_list_head);
+    instance_list_head = next;
+  }
+
+  for (i = 0; i < data->values_len; i++)
+  {
+    while (value_list_head[i] != NULL)
+    {
+      csnmp_table_values_t *next = value_list_head[i]->next;
+      sfree (value_list_head[i]);
+      value_list_head[i] = next;
+    }
+  }
+
+  sfree (value_list_head);
+  sfree (value_list_tail);
+
+  return (0);
+} /* int csnmp_read_table */
+
+static int csnmp_read_value (host_definition_t *host, data_definition_t *data)
+{
+  struct snmp_pdu *req;
+  struct snmp_pdu *res;
+  struct variable_list *vb;
+
+  const data_set_t *ds;
+  value_list_t vl = VALUE_LIST_INIT;
+
+  int status;
+  int i;
+
+  DEBUG ("snmp plugin: csnmp_read_value (host = %s, data = %s)",
+      host->name, data->name);
+
+  if (host->sess_handle == NULL)
+  {
+    DEBUG ("snmp plugin: csnmp_read_table: host->sess_handle == NULL");
+    return (-1);
+  }
+
+  ds = plugin_get_ds (data->type);
+  if (!ds)
+  {
+    ERROR ("snmp plugin: DataSet `%s' not defined.", data->type);
+    return (-1);
+  }
+
+  if (ds->ds_num != data->values_len)
+  {
+    ERROR ("snmp plugin: DataSet `%s' requires %i values, but config talks about %i",
+        data->type, ds->ds_num, data->values_len);
+    return (-1);
+  }
+
+  vl.values_len = ds->ds_num;
+  vl.values = (value_t *) malloc (sizeof (value_t) * vl.values_len);
+  if (vl.values == NULL)
+    return (-1);
+  for (i = 0; i < vl.values_len; i++)
+  {
+    if (ds->ds[i].type == DS_TYPE_COUNTER)
+      vl.values[i].counter = 0;
+    else
+      vl.values[i].gauge = NAN;
+  }
+
+  sstrncpy (vl.host, host->name, sizeof (vl.host));
+  sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
+  sstrncpy (vl.type, data->type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance));
+
+  vl.interval = host->interval;
+
+  req = snmp_pdu_create (SNMP_MSG_GET);
+  if (req == NULL)
+  {
+    ERROR ("snmp plugin: snmp_pdu_create failed.");
+    sfree (vl.values);
+    return (-1);
+  }
+
+  for (i = 0; i < data->values_len; i++)
+    snmp_add_null_var (req, data->values[i].oid, data->values[i].oid_len);
+
+  res = NULL;
+  status = snmp_sess_synch_response (host->sess_handle, req, &res);
+
+  if ((status != STAT_SUCCESS) || (res == NULL))
+  {
+    char *errstr = NULL;
+
+    snmp_sess_error (host->sess_handle, NULL, NULL, &errstr);
+    ERROR ("snmp plugin: host %s: snmp_sess_synch_response failed: %s",
+        host->name, (errstr == NULL) ? "Unknown problem" : errstr);
+
+    if (res != NULL)
+      snmp_free_pdu (res);
+    res = NULL;
+
+    sfree (errstr);
+    csnmp_host_close_session (host);
+
+    return (-1);
+  }
+
+
+  for (vb = res->variables; vb != NULL; vb = vb->next_variable)
+  {
+#if COLLECT_DEBUG
+    char buffer[1024];
+    snprint_variable (buffer, sizeof (buffer),
+        vb->name, vb->name_length, vb);
+    DEBUG ("snmp plugin: Got this variable: %s", buffer);
+#endif /* COLLECT_DEBUG */
+
+    for (i = 0; i < data->values_len; i++)
+      if (snmp_oid_compare (data->values[i].oid, data->values[i].oid_len,
+            vb->name, vb->name_length) == 0)
+        vl.values[i] = csnmp_value_list_to_value (vb, ds->ds[i].type,
+            data->scale, data->shift, host->name, data->name);
+  } /* for (res->variables) */
+
+  if (res != NULL)
+    snmp_free_pdu (res);
+  res = NULL;
+
+  DEBUG ("snmp plugin: -> plugin_dispatch_values (&vl);");
+  plugin_dispatch_values (&vl);
+  sfree (vl.values);
+
+  return (0);
+} /* int csnmp_read_value */
+
+static int csnmp_read_host (user_data_t *ud)
+{
+  host_definition_t *host;
+  cdtime_t time_start;
+  cdtime_t time_end;
+  int status;
+  int success;
+  int i;
+
+  host = ud->data;
+
+  if (host->interval == 0)
+    host->interval = plugin_get_interval ();
+
+  time_start = cdtime ();
+
+  if (host->sess_handle == NULL)
+    csnmp_host_open_session (host);
+
+  if (host->sess_handle == NULL)
+    return (-1);
+
+  success = 0;
+  for (i = 0; i < host->data_list_len; i++)
+  {
+    data_definition_t *data = host->data_list[i];
+
+    if (data->is_table)
+      status = csnmp_read_table (host, data);
+    else
+      status = csnmp_read_value (host, data);
+
+    if (status == 0)
+      success++;
+  }
+
+  time_end = cdtime ();
+  if ((time_end - time_start) > host->interval)
+  {
+    WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
+        "seconds, but reading all values takes %.3f seconds.",
+        host->name,
+        CDTIME_T_TO_DOUBLE (host->interval),
+        CDTIME_T_TO_DOUBLE (time_end - time_start));
+  }
+
+  if (success == 0)
+    return (-1);
+
+  return (0);
+} /* int csnmp_read_host */
+
+static int csnmp_init (void)
+{
+  call_snmp_init_once ();
+
+  return (0);
+} /* int csnmp_init */
+
+static int csnmp_shutdown (void)
+{
+  data_definition_t *data_this;
+  data_definition_t *data_next;
+
+  /* When we get here, the read threads have been stopped and all the
+   * `host_definition_t' will be freed. */
+  DEBUG ("snmp plugin: Destroying all data definitions.");
+
+  data_this = data_head;
+  data_head = NULL;
+  while (data_this != NULL)
+  {
+    data_next = data_this->next;
+
+    sfree (data_this->name);
+    sfree (data_this->type);
+    sfree (data_this->values);
+    sfree (data_this->ignores);
+    sfree (data_this);
+
+    data_this = data_next;
+  }
+
+  return (0);
+} /* int csnmp_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("snmp", csnmp_config);
+  plugin_register_init ("snmp", csnmp_init);
+  plugin_register_shutdown ("snmp", csnmp_shutdown);
+} /* void module_register */
+
+/*
+ * vim: shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker
+ */
diff --git a/src/statsd.c b/src/statsd.c
new file mode 100644 (file)
index 0000000..0885e23
--- /dev/null
@@ -0,0 +1,934 @@
+/**
+ * collectd - src/statsd.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "utils_avltree.h"
+#include "utils_complain.h"
+#include "utils_latency.h"
+
+#include <pthread.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <poll.h>
+
+/* AIX doesn't have MSG_DONTWAIT */
+#ifndef MSG_DONTWAIT
+#  define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
+#ifndef STATSD_DEFAULT_NODE
+# define STATSD_DEFAULT_NODE NULL
+#endif
+
+#ifndef STATSD_DEFAULT_SERVICE
+# define STATSD_DEFAULT_SERVICE "8125"
+#endif
+
+enum metric_type_e
+{
+  STATSD_COUNTER,
+  STATSD_TIMER,
+  STATSD_GAUGE,
+  STATSD_SET
+};
+typedef enum metric_type_e metric_type_t;
+
+struct statsd_metric_s
+{
+  metric_type_t type;
+  double value;
+  latency_counter_t *latency;
+  c_avl_tree_t *set;
+  unsigned long updates_num;
+};
+typedef struct statsd_metric_s statsd_metric_t;
+
+static c_avl_tree_t   *metrics_tree = NULL;
+static pthread_mutex_t metrics_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_t network_thread;
+static _Bool     network_thread_running = 0;
+static _Bool     network_thread_shutdown = 0;
+
+static char *conf_node = NULL;
+static char *conf_service = NULL;
+
+static _Bool conf_delete_counters = 0;
+static _Bool conf_delete_timers   = 0;
+static _Bool conf_delete_gauges   = 0;
+static _Bool conf_delete_sets     = 0;
+
+static double *conf_timer_percentile = NULL;
+static size_t  conf_timer_percentile_num = 0;
+
+static _Bool conf_timer_lower     = 0;
+static _Bool conf_timer_upper     = 0;
+static _Bool conf_timer_sum       = 0;
+static _Bool conf_timer_count     = 0;
+
+/* Must hold metrics_lock when calling this function. */
+static statsd_metric_t *statsd_metric_lookup_unsafe (char const *name, /* {{{ */
+    metric_type_t type)
+{
+  char key[DATA_MAX_NAME_LEN + 2];
+  char *key_copy;
+  statsd_metric_t *metric;
+  int status;
+
+  switch (type)
+  {
+    case STATSD_COUNTER: key[0] = 'c'; break;
+    case STATSD_TIMER:   key[0] = 't'; break;
+    case STATSD_GAUGE:   key[0] = 'g'; break;
+    case STATSD_SET:     key[0] = 's'; break;
+    default: return (NULL);
+  }
+
+  key[1] = ':';
+  sstrncpy (&key[2], name, sizeof (key) - 2);
+
+  status = c_avl_get (metrics_tree, key, (void *) &metric);
+  if (status == 0)
+    return (metric);
+
+  key_copy = strdup (key);
+  if (key_copy == NULL)
+  {
+    ERROR ("statsd plugin: strdup failed.");
+    return (NULL);
+  }
+
+  metric = malloc (sizeof (*metric));
+  if (metric == NULL)
+  {
+    ERROR ("statsd plugin: malloc failed.");
+    sfree (key_copy);
+    return (NULL);
+  }
+  memset (metric, 0, sizeof (*metric));
+
+  metric->type = type;
+  metric->latency = NULL;
+  metric->set = NULL;
+
+  status = c_avl_insert (metrics_tree, key_copy, metric);
+  if (status != 0)
+  {
+    ERROR ("statsd plugin: c_avl_insert failed.");
+    sfree (key_copy);
+    sfree (metric);
+    return (NULL);
+  }
+
+  return (metric);
+} /* }}} statsd_metric_lookup_unsafe */
+
+static int statsd_metric_set (char const *name, double value, /* {{{ */
+    metric_type_t type)
+{
+  statsd_metric_t *metric;
+
+  pthread_mutex_lock (&metrics_lock);
+
+  metric = statsd_metric_lookup_unsafe (name, type);
+  if (metric == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    return (-1);
+  }
+
+  metric->value = value;
+  metric->updates_num++;
+
+  pthread_mutex_unlock (&metrics_lock);
+
+  return (0);
+} /* }}} int statsd_metric_set */
+
+static int statsd_metric_add (char const *name, double delta, /* {{{ */
+    metric_type_t type)
+{
+  statsd_metric_t *metric;
+
+  pthread_mutex_lock (&metrics_lock);
+
+  metric = statsd_metric_lookup_unsafe (name, type);
+  if (metric == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    return (-1);
+  }
+
+  metric->value += delta;
+  metric->updates_num++;
+
+  pthread_mutex_unlock (&metrics_lock);
+
+  return (0);
+} /* }}} int statsd_metric_add */
+
+static int statsd_parse_value (char const *str, value_t *ret_value) /* {{{ */
+{
+  char *endptr = NULL;
+
+  ret_value->gauge = (gauge_t) strtod (str, &endptr);
+  if ((str == endptr) || ((endptr != NULL) && (*endptr != 0)))
+    return (-1);
+
+  return (0);
+} /* }}} int statsd_parse_value */
+
+static int statsd_handle_counter (char const *name, /* {{{ */
+    char const *value_str,
+    char const *extra)
+{
+  value_t value;
+  value_t scale;
+  int status;
+
+  if ((extra != NULL) && (extra[0] != '@'))
+    return (-1);
+
+  scale.gauge = 1.0;
+  if (extra != NULL)
+  {
+    status = statsd_parse_value (extra + 1, &scale);
+    if (status != 0)
+      return (status);
+
+    if (!isfinite (scale.gauge) || (scale.gauge <= 0.0) || (scale.gauge > 1.0))
+      return (-1);
+  }
+
+  value.gauge = 1.0;
+  status = statsd_parse_value (value_str, &value);
+  if (status != 0)
+    return (status);
+
+  return (statsd_metric_add (name, (double) (value.gauge / scale.gauge),
+        STATSD_COUNTER));
+} /* }}} int statsd_handle_counter */
+
+static int statsd_handle_gauge (char const *name, /* {{{ */
+    char const *value_str)
+{
+  value_t value;
+  int status;
+
+  value.gauge = 0;
+  status = statsd_parse_value (value_str, &value);
+  if (status != 0)
+    return (status);
+
+  if ((value_str[0] == '+') || (value_str[0] == '-'))
+    return (statsd_metric_add (name, (double) value.gauge, STATSD_GAUGE));
+  else
+    return (statsd_metric_set (name, (double) value.gauge, STATSD_GAUGE));
+} /* }}} int statsd_handle_gauge */
+
+static int statsd_handle_timer (char const *name, /* {{{ */
+    char const *value_str,
+    char const *extra)
+{
+  statsd_metric_t *metric;
+  value_t value_ms;
+  value_t scale;
+  cdtime_t value;
+  int status;
+
+  if ((extra != NULL) && (extra[0] != '@'))
+    return (-1);
+
+  scale.gauge = 1.0;
+  if (extra != NULL)
+  {
+    status = statsd_parse_value (extra + 1, &scale);
+    if (status != 0)
+      return (status);
+
+    if (!isfinite (scale.gauge) || (scale.gauge <= 0.0) || (scale.gauge > 1.0))
+      return (-1);
+  }
+
+  value_ms.derive = 0;
+  status = statsd_parse_value (value_str, &value_ms);
+  if (status != 0)
+    return (status);
+
+  value = MS_TO_CDTIME_T (value_ms.gauge / scale.gauge);
+
+  pthread_mutex_lock (&metrics_lock);
+
+  metric = statsd_metric_lookup_unsafe (name, STATSD_TIMER);
+  if (metric == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    return (-1);
+  }
+
+  if (metric->latency == NULL)
+    metric->latency = latency_counter_create ();
+  if (metric->latency == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    return (-1);
+  }
+
+  latency_counter_add (metric->latency, value);
+  metric->updates_num++;
+
+  pthread_mutex_unlock (&metrics_lock);
+  return (0);
+} /* }}} int statsd_handle_timer */
+
+static int statsd_handle_set (char const *name, /* {{{ */
+    char const *set_key_orig)
+{
+  statsd_metric_t *metric = NULL;
+  char *set_key;
+  int status;
+
+  pthread_mutex_lock (&metrics_lock);
+
+  metric = statsd_metric_lookup_unsafe (name, STATSD_SET);
+  if (metric == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    return (-1);
+  }
+
+  /* Make sure metric->set exists. */
+  if (metric->set == NULL)
+    metric->set = c_avl_create ((void *) strcmp);
+
+  if (metric->set == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    ERROR ("statsd plugin: c_avl_create failed.");
+    return (-1);
+  }
+
+  set_key = strdup (set_key_orig);
+  if (set_key == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    ERROR ("statsd plugin: strdup failed.");
+    return (-1);
+  }
+
+  status = c_avl_insert (metric->set, set_key, /* value = */ NULL);
+  if (status < 0)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    if (status < 0)
+      ERROR ("statsd plugin: c_avl_insert (\"%s\") failed with status %i.",
+          set_key, status);
+    sfree (set_key);
+    return (-1);
+  }
+  else if (status > 0) /* key already exists */
+  {
+    sfree (set_key);
+  }
+
+  metric->updates_num++;
+
+  pthread_mutex_unlock (&metrics_lock);
+  return (0);
+} /* }}} int statsd_handle_set */
+
+static int statsd_parse_line (char *buffer) /* {{{ */
+{
+  char *name = buffer;
+  char *value;
+  char *type;
+  char *extra;
+
+  type = strchr (name, '|');
+  if (type == NULL)
+    return (-1);
+  *type = 0;
+  type++;
+
+  value = strrchr (name, ':');
+  if (value == NULL)
+    return (-1);
+  *value = 0;
+  value++;
+
+  extra = strchr (type, '|');
+  if (extra != NULL)
+  {
+    *extra = 0;
+    extra++;
+  }
+
+  if (strcmp ("c", type) == 0)
+    return (statsd_handle_counter (name, value, extra));
+  else if (strcmp ("ms", type) == 0)
+    return (statsd_handle_timer (name, value, extra));
+
+  /* extra is only valid for counters and timers */
+  if (extra != NULL)
+    return (-1);
+
+  if (strcmp ("g", type) == 0)
+    return (statsd_handle_gauge (name, value));
+  else if (strcmp ("s", type) == 0)
+    return (statsd_handle_set (name, value));
+  else
+    return (-1);
+} /* }}} void statsd_parse_line */
+
+static void statsd_parse_buffer (char *buffer) /* {{{ */
+{
+  while (buffer != NULL)
+  {
+    char orig[64];
+    char *next;
+    int status;
+
+    next = strchr (buffer, '\n');
+    if (next != NULL)
+    {
+      *next = 0;
+      next++;
+    }
+
+    if (*buffer == 0)
+    {
+      buffer = next;
+      continue;
+    }
+
+    sstrncpy (orig, buffer, sizeof (orig));
+
+    status = statsd_parse_line (buffer);
+    if (status != 0)
+      ERROR ("statsd plugin: Unable to parse line: \"%s\"", orig);
+
+    buffer = next;
+  }
+} /* }}} void statsd_parse_buffer */
+
+static void statsd_network_read (int fd) /* {{{ */
+{
+  char buffer[4096];
+  size_t buffer_size;
+  ssize_t status;
+
+  status = recv (fd, buffer, sizeof (buffer), /* flags = */ MSG_DONTWAIT);
+  if (status < 0)
+  {
+    char errbuf[1024];
+
+    if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+      return;
+
+    ERROR ("statsd plugin: recv(2) failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return;
+  }
+
+  buffer_size = (size_t) status;
+  if (buffer_size >= sizeof (buffer))
+    buffer_size = sizeof (buffer) - 1;
+  buffer[buffer_size] = 0;
+
+  statsd_parse_buffer (buffer);
+} /* }}} void statsd_network_read */
+
+static int statsd_network_init (struct pollfd **ret_fds, /* {{{ */
+    size_t *ret_fds_num)
+{
+  struct pollfd *fds = NULL;
+  size_t fds_num = 0;
+
+  struct addrinfo ai_hints;
+  struct addrinfo *ai_list = NULL;
+  struct addrinfo *ai_ptr;
+  int status;
+
+  char const *node = (conf_node != NULL) ? conf_node : STATSD_DEFAULT_NODE;
+  char const *service = (conf_service != NULL)
+    ? conf_service : STATSD_DEFAULT_SERVICE;
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags = AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_DGRAM;
+
+  status = getaddrinfo (node, service, &ai_hints, &ai_list);
+  if (status != 0)
+  {
+    ERROR ("statsd plugin: getaddrinfo (\"%s\", \"%s\") failed: %s",
+        node, service, gai_strerror (status));
+    return (status);
+  }
+
+  for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    int fd;
+    struct pollfd *tmp;
+
+    char dbg_node[NI_MAXHOST];
+    char dbg_service[NI_MAXSERV];
+
+    fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+    if (fd < 0)
+    {
+      char errbuf[1024];
+      ERROR ("statsd plugin: socket(2) failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      continue;
+    }
+
+    getnameinfo (ai_ptr->ai_addr, ai_ptr->ai_addrlen,
+        dbg_node, sizeof (dbg_node), dbg_service, sizeof (dbg_service),
+        NI_DGRAM | NI_NUMERICHOST | NI_NUMERICSERV);
+    DEBUG ("statsd plugin: Trying to bind to [%s]:%s ...", dbg_node, dbg_service);
+
+    status = bind (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    if (status != 0)
+    {
+      char errbuf[1024];
+      ERROR ("statsd plugin: bind(2) failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      close (fd);
+      continue;
+    }
+
+    tmp = realloc (fds, sizeof (*fds) * (fds_num + 1));
+    if (tmp == NULL)
+    {
+      ERROR ("statsd plugin: realloc failed.");
+      continue;
+    }
+    fds = tmp;
+    tmp = fds + fds_num;
+    fds_num++;
+
+    memset (tmp, 0, sizeof (*tmp));
+    tmp->fd = fd;
+    tmp->events = POLLIN | POLLPRI;
+  }
+
+  freeaddrinfo (ai_list);
+
+  if (fds_num == 0)
+  {
+    ERROR ("statsd plugin: Unable to create listening socket for [%s]:%s.",
+        (node != NULL) ? node : "::", service);
+    return (ENOENT);
+  }
+
+  *ret_fds = fds;
+  *ret_fds_num = fds_num;
+  return (0);
+} /* }}} int statsd_network_init */
+
+static void *statsd_network_thread (void *args) /* {{{ */
+{
+  struct pollfd *fds = NULL;
+  size_t fds_num = 0;
+  int status;
+  size_t i;
+
+  status = statsd_network_init (&fds, &fds_num);
+  if (status != 0)
+  {
+    ERROR ("statsd plugin: Unable to open listening sockets.");
+    pthread_exit ((void *) 0);
+  }
+
+  while (!network_thread_shutdown)
+  {
+    status = poll (fds, (nfds_t) fds_num, /* timeout = */ -1);
+    if (status < 0)
+    {
+      char errbuf[1024];
+
+      if ((errno == EINTR) || (errno == EAGAIN))
+        continue;
+
+      ERROR ("statsd plugin: poll(2) failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      break;
+    }
+
+    for (i = 0; i < fds_num; i++)
+    {
+      if ((fds[i].revents & (POLLIN | POLLPRI)) == 0)
+        continue;
+
+      statsd_network_read (fds[i].fd);
+      fds[i].revents = 0;
+    }
+  } /* while (!network_thread_shutdown) */
+
+  /* Clean up */
+  for (i = 0; i < fds_num; i++)
+    close (fds[i].fd);
+  sfree (fds);
+
+  return ((void *) 0);
+} /* }}} void *statsd_network_thread */
+
+static int statsd_config_timer_percentile (oconfig_item_t *ci) /* {{{ */
+{
+  double percent = NAN;
+  double *tmp;
+  int status;
+
+  status = cf_util_get_double (ci, &percent);
+  if (status != 0)
+    return (status);
+
+  if ((percent <= 0.0) || (percent >= 100))
+  {
+    ERROR ("statsd plugin: The value for \"%s\" must be between 0 and 100, "
+        "exclusively.", ci->key);
+    return (ERANGE);
+  }
+
+  tmp = realloc (conf_timer_percentile,
+      sizeof (*conf_timer_percentile) * (conf_timer_percentile_num + 1));
+  if (tmp == NULL)
+  {
+    ERROR ("statsd plugin: realloc failed.");
+    return (ENOMEM);
+  }
+  conf_timer_percentile = tmp;
+  conf_timer_percentile[conf_timer_percentile_num] = percent;
+  conf_timer_percentile_num++;
+
+  return (0);
+} /* }}} int statsd_config_timer_percentile */
+
+static int statsd_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      cf_util_get_string (child, &conf_node);
+    else if (strcasecmp ("Port", child->key) == 0)
+      cf_util_get_service (child, &conf_service);
+    else if (strcasecmp ("DeleteCounters", child->key) == 0)
+      cf_util_get_boolean (child, &conf_delete_counters);
+    else if (strcasecmp ("DeleteTimers", child->key) == 0)
+      cf_util_get_boolean (child, &conf_delete_timers);
+    else if (strcasecmp ("DeleteGauges", child->key) == 0)
+      cf_util_get_boolean (child, &conf_delete_gauges);
+    else if (strcasecmp ("DeleteSets", child->key) == 0)
+      cf_util_get_boolean (child, &conf_delete_sets);
+    else if (strcasecmp ("TimerLower", child->key) == 0)
+      cf_util_get_boolean (child, &conf_timer_lower);
+    else if (strcasecmp ("TimerUpper", child->key) == 0)
+      cf_util_get_boolean (child, &conf_timer_upper);
+    else if (strcasecmp ("TimerSum", child->key) == 0)
+      cf_util_get_boolean (child, &conf_timer_sum);
+    else if (strcasecmp ("TimerCount", child->key) == 0)
+      cf_util_get_boolean (child, &conf_timer_count);
+    else if (strcasecmp ("TimerPercentile", child->key) == 0)
+      statsd_config_timer_percentile (child);
+    else
+      ERROR ("statsd plugin: The \"%s\" config option is not valid.",
+          child->key);
+  }
+
+  return (0);
+} /* }}} int statsd_config */
+
+static int statsd_init (void) /* {{{ */
+{
+  pthread_mutex_lock (&metrics_lock);
+  if (metrics_tree == NULL)
+    metrics_tree = c_avl_create ((void *) strcmp);
+
+  if (!network_thread_running)
+  {
+    int status;
+
+    status = pthread_create (&network_thread,
+        /* attr = */ NULL,
+        statsd_network_thread,
+        /* args = */ NULL);
+    if (status != 0)
+    {
+      char errbuf[1024];
+      pthread_mutex_unlock (&metrics_lock);
+      ERROR ("statsd plugin: pthread_create failed: %s",
+          sstrerror (errno, errbuf, sizeof (errbuf)));
+      return (status);
+    }
+  }
+  network_thread_running = 1;
+
+  pthread_mutex_unlock (&metrics_lock);
+
+  return (0);
+} /* }}} int statsd_init */
+
+/* Must hold metrics_lock when calling this function. */
+static int statsd_metric_clear_set_unsafe (statsd_metric_t *metric) /* {{{ */
+{
+  void *key;
+  void *value;
+
+  if ((metric == NULL) || (metric->type != STATSD_SET))
+    return (EINVAL);
+
+  if (metric->set == NULL)
+    return (0);
+
+  while (c_avl_pick (metric->set, &key, &value) == 0)
+  {
+    sfree (key);
+    sfree (value);
+  }
+
+  return (0);
+} /* }}} int statsd_metric_clear_set_unsafe */
+
+/* Must hold metrics_lock when calling this function. */
+static int statsd_metric_submit_unsafe (char const *name, /* {{{ */
+    statsd_metric_t const *metric)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  vl.values = values;
+  vl.values_len = 1;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "statsd", sizeof (vl.plugin));
+
+  if (metric->type == STATSD_GAUGE)
+    sstrncpy (vl.type, "gauge", sizeof (vl.type));
+  else if (metric->type == STATSD_TIMER)
+    sstrncpy (vl.type, "latency", sizeof (vl.type));
+  else if (metric->type == STATSD_SET)
+    sstrncpy (vl.type, "objects", sizeof (vl.type));
+  else /* if (metric->type == STATSD_COUNTER) */
+    sstrncpy (vl.type, "derive", sizeof (vl.type));
+
+  sstrncpy (vl.type_instance, name, sizeof (vl.type_instance));
+
+  if (metric->type == STATSD_GAUGE)
+    values[0].gauge = (gauge_t) metric->value;
+  else if (metric->type == STATSD_TIMER)
+  {
+    size_t i;
+
+    if (metric->updates_num == 0)
+      return (0);
+
+    vl.time = cdtime ();
+
+    ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+        "%s-average", name);
+    values[0].gauge = CDTIME_T_TO_DOUBLE (
+        latency_counter_get_average (metric->latency));
+    plugin_dispatch_values (&vl);
+
+    if (conf_timer_lower) {
+      ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+          "%s-lower", name);
+      values[0].gauge = CDTIME_T_TO_DOUBLE (
+          latency_counter_get_min (metric->latency));
+      plugin_dispatch_values (&vl);
+    }
+
+    if (conf_timer_upper) {
+      ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+          "%s-upper", name);
+      values[0].gauge = CDTIME_T_TO_DOUBLE (
+          latency_counter_get_max (metric->latency));
+      plugin_dispatch_values (&vl);
+    }
+
+    if (conf_timer_sum) {
+      ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+          "%s-sum", name);
+      values[0].gauge = CDTIME_T_TO_DOUBLE (
+          latency_counter_get_sum (metric->latency));
+      plugin_dispatch_values (&vl);
+    }
+
+    for (i = 0; i < conf_timer_percentile_num; i++)
+    {
+      ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+          "%s-percentile-%.0f", name, conf_timer_percentile[i]);
+      values[0].gauge = CDTIME_T_TO_DOUBLE (
+          latency_counter_get_percentile (
+            metric->latency, conf_timer_percentile[i]));
+      plugin_dispatch_values (&vl);
+    }
+
+    /* Keep this at the end, since vl.type is set to "gauge" here. The
+     * vl.type's above are implicitly set to "latency". */
+    if (conf_timer_count) {
+      sstrncpy (vl.type, "gauge", sizeof (vl.type));
+      ssnprintf (vl.type_instance, sizeof (vl.type_instance),
+          "%s-count", name);
+      values[0].gauge = latency_counter_get_num (metric->latency);
+      plugin_dispatch_values (&vl);
+    }
+
+    latency_counter_reset (metric->latency);
+    return (0);
+  }
+  else if (metric->type == STATSD_SET)
+  {
+    if (metric->set == NULL)
+      values[0].gauge = 0.0;
+    else
+      values[0].gauge = (gauge_t) c_avl_size (metric->set);
+  }
+  else
+    values[0].derive = (derive_t) metric->value;
+
+  return (plugin_dispatch_values (&vl));
+} /* }}} int statsd_metric_submit_unsafe */
+
+static int statsd_read (void) /* {{{ */
+{
+  c_avl_iterator_t *iter;
+  char *name;
+  statsd_metric_t *metric;
+
+  char **to_be_deleted = NULL;
+  size_t to_be_deleted_num = 0;
+  size_t i;
+
+  pthread_mutex_lock (&metrics_lock);
+
+  if (metrics_tree == NULL)
+  {
+    pthread_mutex_unlock (&metrics_lock);
+    return (0);
+  }
+
+  iter = c_avl_get_iterator (metrics_tree);
+  while (c_avl_iterator_next (iter, (void *) &name, (void *) &metric) == 0)
+  {
+    if ((metric->updates_num == 0)
+        && ((conf_delete_counters && (metric->type == STATSD_COUNTER))
+          || (conf_delete_timers && (metric->type == STATSD_TIMER))
+          || (conf_delete_gauges && (metric->type == STATSD_GAUGE))
+          || (conf_delete_sets && (metric->type == STATSD_SET))))
+    {
+      DEBUG ("statsd plugin: Deleting metric \"%s\".", name);
+      strarray_add (&to_be_deleted, &to_be_deleted_num, name);
+      continue;
+    }
+
+    /* Names have a prefix, e.g. "c:", which determines the (statsd) type.
+     * Remove this here. */
+    statsd_metric_submit_unsafe (name + 2, metric);
+
+    /* Reset the metric. */
+    metric->updates_num = 0;
+    if (metric->type == STATSD_SET)
+      statsd_metric_clear_set_unsafe (metric);
+  }
+  c_avl_iterator_destroy (iter);
+
+  for (i = 0; i < to_be_deleted_num; i++)
+  {
+    int status;
+
+    status = c_avl_remove (metrics_tree, to_be_deleted[i],
+        (void *) &name, (void *) &metric);
+    if (status != 0)
+    {
+      ERROR ("stats plugin: c_avl_remove (\"%s\") failed with status %i.",
+          to_be_deleted[i], status);
+      continue;
+    }
+
+    sfree (name);
+    sfree (metric);
+  }
+
+  pthread_mutex_unlock (&metrics_lock);
+
+  strarray_free (to_be_deleted, to_be_deleted_num);
+
+  return (0);
+} /* }}} int statsd_read */
+
+static int statsd_shutdown (void) /* {{{ */
+{
+  void *key;
+  void *value;
+
+  pthread_mutex_lock (&metrics_lock);
+
+  if (network_thread_running)
+  {
+    network_thread_shutdown = 1;
+    pthread_kill (network_thread, SIGTERM);
+    pthread_join (network_thread, /* retval = */ NULL);
+  }
+  network_thread_running = 0;
+
+  while (c_avl_pick (metrics_tree, &key, &value) == 0)
+  {
+    sfree (key);
+    sfree (value);
+  }
+  c_avl_destroy (metrics_tree);
+  metrics_tree = NULL;
+
+  sfree (conf_node);
+  sfree (conf_service);
+
+  pthread_mutex_unlock (&metrics_lock);
+
+  return (0);
+} /* }}} int statsd_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("statsd", statsd_config);
+  plugin_register_init ("statsd", statsd_init);
+  plugin_register_read ("statsd", statsd_read);
+  plugin_register_shutdown ("statsd", statsd_shutdown);
+}
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/swap.c b/src/swap.c
new file mode 100644 (file)
index 0000000..a8276c7
--- /dev/null
@@ -0,0 +1,794 @@
+/**
+ * collectd - src/swap.c
+ * Copyright (C) 2005-2014  Florian octo Forster
+ * Copyright (C) 2009       Stefan Völkel
+ * Copyright (C) 2009       Manuel Sanmartin
+ * Copyright (C) 2010       Aurélien Reynaud
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Manuel Sanmartin
+ *   Aurélien Reynaud <collectd at wattapower.net>
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+# undef HAVE_CONFIG_H
+#endif
+/* avoid swap.h error "Cannot use swapctl in the large files compilation environment" */
+#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
+#  undef _FILE_OFFSET_BITS
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if HAVE_SYS_SWAP_H
+# include <sys/swap.h>
+#endif
+#if HAVE_VM_ANON_H
+# include <vm/anon.h>
+#endif
+#if HAVE_SYS_PARAM_H
+#  include <sys/param.h>
+#endif
+#if HAVE_SYS_SYSCTL_H
+#  include <sys/sysctl.h>
+#endif
+#if HAVE_SYS_DKSTAT_H
+#  include <sys/dkstat.h>
+#endif
+#if HAVE_KVM_H
+#  include <kvm.h>
+#endif
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif
+
+#if HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+#endif
+
+#undef  MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+#if KERNEL_LINUX
+# define SWAP_HAVE_REPORT_BY_DEVICE 1
+static derive_t pagesize;
+static _Bool report_bytes = 0;
+static _Bool report_by_device = 0;
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS
+# define SWAP_HAVE_REPORT_BY_DEVICE 1
+static derive_t pagesize;
+static _Bool report_by_device = 0;
+/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */
+
+#elif defined(VM_SWAPUSAGE)
+/* No global variables */
+/* #endif defined(VM_SWAPUSAGE) */
+
+#elif HAVE_LIBKVM_GETSWAPINFO
+static kvm_t *kvm_obj = NULL;
+int kvm_pagesize;
+/* #endif HAVE_LIBKVM_GETSWAPINFO */
+
+#elif HAVE_LIBSTATGRAB
+/* No global variables */
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif HAVE_PERFSTAT
+static int pagesize;
+/*# endif HAVE_PERFSTAT */
+
+#else
+# error "No applicable input method."
+#endif /* HAVE_LIBSTATGRAB */
+
+static _Bool values_absolute = 1;
+static _Bool values_percentage = 0;
+
+static int swap_config (oconfig_item_t *ci) /* {{{ */
+{
+       int i;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+               if (strcasecmp ("ReportBytes", child->key) == 0)
+#if KERNEL_LINUX
+                       cf_util_get_boolean (child, &report_bytes);
+#else
+                       WARNING ("swap plugin: The \"ReportBytes\" option "
+                                       "is only valid under Linux. "
+                                       "The option is going to be ignored.");
+#endif
+               else if (strcasecmp ("ReportByDevice", child->key) == 0)
+#if SWAP_HAVE_REPORT_BY_DEVICE
+                       cf_util_get_boolean (child, &report_by_device);
+#else
+                       WARNING ("swap plugin: The \"ReportByDevice\" option "
+                                       "is not supported on this platform. "
+                                       "The option is going to be ignored.");
+#endif /* SWAP_HAVE_REPORT_BY_DEVICE */
+               else if (strcasecmp ("ValuesAbsolute", child->key) == 0)
+                       cf_util_get_boolean (child, &values_absolute);
+               else if (strcasecmp ("ValuesPercentage", child->key) == 0)
+                       cf_util_get_boolean (child, &values_percentage);
+               else
+                       WARNING ("swap plugin: Unknown config option: \"%s\"",
+                                       child->key);
+       }
+
+       return (0);
+} /* }}} int swap_config */
+
+static int swap_init (void) /* {{{ */
+{
+#if KERNEL_LINUX
+       pagesize = (derive_t) sysconf (_SC_PAGESIZE);
+/* #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 */
+
+#elif defined(VM_SWAPUSAGE)
+       /* No init stuff */
+/* #endif defined(VM_SWAPUSAGE) */
+
+#elif HAVE_LIBKVM_GETSWAPINFO
+       char errbuf[_POSIX2_LINE_MAX];
+
+       if (kvm_obj != NULL)
+       {
+               kvm_close (kvm_obj);
+               kvm_obj = NULL;
+       }
+
+       kvm_pagesize = getpagesize ();
+
+       kvm_obj = kvm_openfiles (NULL, "/dev/null", NULL, O_RDONLY, errbuf);
+
+       if (kvm_obj == NULL)
+       {
+               ERROR ("swap plugin: kvm_openfiles failed, %s", errbuf);
+               return (-1);
+       }
+/* #endif HAVE_LIBKVM_GETSWAPINFO */
+
+#elif HAVE_LIBSTATGRAB
+       /* No init stuff */
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif HAVE_PERFSTAT
+       pagesize = getpagesize();
+#endif /* HAVE_PERFSTAT */
+
+       return (0);
+} /* }}} int swap_init */
+
+static void swap_submit_usage (char const *plugin_instance, /* {{{ */
+               gauge_t used, gauge_t free,
+               char const *other_name, gauge_t other_value)
+{
+       value_t v[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = v;
+       vl.values_len = STATIC_ARRAY_SIZE (v);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance,
+                               sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "swap", sizeof (vl.type));
+
+       if (values_absolute)
+               plugin_dispatch_multivalue (&vl, 0, DS_TYPE_GAUGE,
+                               "used", used, "free", free,
+                               other_name, other_value, NULL);
+       if (values_percentage)
+               plugin_dispatch_multivalue (&vl, 1, DS_TYPE_GAUGE,
+                               "used", used, "free", free,
+                               other_name, other_value, NULL);
+} /* }}} void swap_submit_usage */
+
+#if KERNEL_LINUX || HAVE_PERFSTAT
+__attribute__((nonnull(1)))
+static void swap_submit_derive (char const *type_instance, /* {{{ */
+               derive_t value)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t v[1];
+
+       v[0].derive = value;
+
+       vl.values = v;
+       vl.values_len = STATIC_ARRAY_SIZE (v);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
+       sstrncpy (vl.type, "swap_io", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* }}} void swap_submit_derive */
+#endif
+
+#if KERNEL_LINUX
+static int swap_read_separate (void) /* {{{ */
+{
+       FILE *fh;
+       char buffer[1024];
+
+       fh = fopen ("/proc/swaps", "r");
+       if (fh == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("swap plugin: fopen (/proc/swaps) failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               char *fields[8];
+               int numfields;
+               char *endptr;
+
+               char path[PATH_MAX];
+               gauge_t total;
+               gauge_t used;
+
+               numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (numfields != 5)
+                       continue;
+
+               sstrncpy (path, fields[0], sizeof (path));
+               escape_slashes (path, sizeof (path));
+
+               errno = 0;
+               endptr = NULL;
+               total = strtod (fields[2], &endptr);
+               if ((endptr == fields[2]) || (errno != 0))
+                       continue;
+
+               errno = 0;
+               endptr = NULL;
+               used = strtod (fields[3], &endptr);
+               if ((endptr == fields[3]) || (errno != 0))
+                       continue;
+
+               if (total < used)
+                       continue;
+
+               swap_submit_usage (path, used, total - used, NULL, NAN);
+       }
+
+       fclose (fh);
+
+       return (0);
+} /* }}} int swap_read_separate */
+
+static int swap_read_combined (void) /* {{{ */
+{
+       FILE *fh;
+       char buffer[1024];
+
+       gauge_t swap_used   = NAN;
+       gauge_t swap_cached = NAN;
+       gauge_t swap_free   = NAN;
+       gauge_t swap_total  = NAN;
+
+       fh = fopen ("/proc/meminfo", "r");
+       if (fh == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("swap plugin: fopen (/proc/meminfo) failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               char *fields[8];
+               int numfields;
+
+               numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+               if (numfields < 2)
+                       continue;
+
+               if (strcasecmp (fields[0], "SwapTotal:") == 0)
+                       strtogauge (fields[1], &swap_total);
+               else if (strcasecmp (fields[0], "SwapFree:") == 0)
+                       strtogauge (fields[1], &swap_free);
+               else if (strcasecmp (fields[0], "SwapCached:") == 0)
+                       strtogauge (fields[1], &swap_cached);
+       }
+
+       fclose (fh);
+
+       if (isnan (swap_total) || isnan (swap_free))
+               return (ENOENT);
+
+       /* Some systems, OpenVZ for example, don't provide SwapCached. */
+       if (isnan (swap_cached))
+               swap_used = swap_total - swap_free;
+       else
+               swap_used = swap_total - (swap_free + swap_cached);
+       assert (!isnan (swap_used));
+
+       if (swap_used < 0.0)
+               return (EINVAL);
+
+       swap_submit_usage (NULL, swap_used, swap_free,
+                       isnan (swap_cached) ? NULL : "cached", swap_cached);
+       return (0);
+} /* }}} int swap_read_combined */
+
+static int swap_read_io (void) /* {{{ */
+{
+       FILE *fh;
+       char buffer[1024];
+
+       _Bool old_kernel = 0;
+
+       uint8_t have_data = 0;
+       derive_t swap_in  = 0;
+       derive_t swap_out = 0;
+
+       fh = fopen ("/proc/vmstat", "r");
+       if (fh == NULL)
+       {
+               /* /proc/vmstat does not exist in kernels <2.6 */
+               fh = fopen ("/proc/stat", "r");
+               if (fh == NULL)
+               {
+                       char errbuf[1024];
+                       WARNING ("swap: fopen: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       return (-1);
+               }
+               else
+                       old_kernel = 1;
+       }
+
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               char *fields[8];
+               int numfields;
+
+               numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+
+               if (!old_kernel)
+               {
+                       if (numfields != 2)
+                               continue;
+
+                       if (strcasecmp ("pswpin", fields[0]) == 0)
+                       {
+                               strtoderive (fields[1], &swap_in);
+                               have_data |= 0x01;
+                       }
+                       else if (strcasecmp ("pswpout", fields[0]) == 0)
+                       {
+                               strtoderive (fields[1], &swap_out);
+                               have_data |= 0x02;
+                       }
+               }
+               else /* if (old_kernel) */
+               {
+                       if (numfields != 3)
+                               continue;
+
+                       if (strcasecmp ("page", fields[0]) == 0)
+                       {
+                               strtoderive (fields[1], &swap_in);
+                               strtoderive (fields[2], &swap_out);
+                       }
+               }
+       } /* while (fgets) */
+
+       fclose (fh);
+
+       if (have_data != 0x03)
+               return (ENOENT);
+
+       if (report_bytes)
+       {
+               swap_in = swap_in * pagesize;
+               swap_out = swap_out * pagesize;
+       }
+
+       swap_submit_derive ("in",  swap_in);
+       swap_submit_derive ("out", swap_out);
+
+       return (0);
+} /* }}} int swap_read_io */
+
+static int swap_read (void) /* {{{ */
+{
+       if (report_by_device)
+               swap_read_separate ();
+       else
+               swap_read_combined ();
+
+       swap_read_io ();
+
+       return (0);
+} /* }}} int swap_read */
+/* #endif KERNEL_LINUX */
+
+/*
+ * Under Solaris, two mechanisms can be used to read swap statistics, swapctl
+ * and kstat. The former reads physical space used on a device, the latter
+ * reports the view from the virtual memory system. It was decided that the
+ * kstat-based information should be moved to the "vmem" plugin, but nobody
+ * with enough Solaris experience was available at that time to do this. The
+ * code below is still there for your reference but it won't be activated in
+ * *this* plugin again. --octo
+ */
+#elif 0 && HAVE_LIBKSTAT
+/* kstat-based read function */
+static int swap_read_kstat (void) /* {{{ */
+{
+       gauge_t swap_alloc;
+       gauge_t swap_resv;
+       gauge_t swap_avail;
+
+       struct anoninfo ai;
+
+       if (swapctl (SC_AINFO, &ai) == -1)
+       {
+               char errbuf[1024];
+               ERROR ("swap plugin: swapctl failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       /*
+        * Calculations from:
+        * http://cvs.opensolaris.org/source/xref/on/usr/src/cmd/swap/swap.c
+        * Also see:
+        * http://www.itworld.com/Comp/2377/UIR980701perf/ (outdated?)
+        * /usr/include/vm/anon.h
+        *
+        * In short, swap -s shows: allocated + reserved = used, available
+        *
+        * However, Solaris does not allow to allocated/reserved more than the
+        * available swap (physical memory + disk swap), so the pedant may
+        * prefer: allocated + unallocated = reserved, available
+        *
+        * We map the above to: used + resv = n/a, free
+        *
+        * Does your brain hurt yet?  - Christophe Kalt
+        *
+        * Oh, and in case you wonder,
+        * swap_alloc = pagesize * ( ai.ani_max - ai.ani_free );
+        * can suffer from a 32bit overflow.
+        */
+       swap_alloc = (gauge_t) ((ai.ani_max - ai.ani_free) * pagesize);
+       swap_resv  = (gauge_t) ((ai.ani_resv + ai.ani_free - ai.ani_max) * pagesize);
+       swap_avail = (gauge_t) ((ai.ani_max - ai.ani_resv) * pagesize);
+
+       swap_submit_usage (NULL, swap_alloc, swap_avail, "reserved", swap_resv);
+       return (0);
+} /* }}} int swap_read_kstat */
+/* #endif 0 && HAVE_LIBKSTAT */
+
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS
+/* swapctl-based read function */
+static int swap_read (void) /* {{{ */
+{
+        swaptbl_t *s;
+       char *s_paths;
+        int swap_num;
+        int status;
+        int i;
+
+        gauge_t avail = 0;
+        gauge_t total = 0;
+
+        swap_num = swapctl (SC_GETNSWP, NULL);
+        if (swap_num < 0)
+        {
+                ERROR ("swap plugin: swapctl (SC_GETNSWP) failed with status %i.",
+                                swap_num);
+                return (-1);
+        }
+        else if (swap_num == 0)
+                return (0);
+
+       /* Allocate and initialize the swaptbl_t structure */
+        s = (swaptbl_t *) smalloc (swap_num * sizeof (swapent_t) + sizeof (struct swaptable));
+        if (s == NULL)
+        {
+                ERROR ("swap plugin: smalloc failed.");
+                return (-1);
+        }
+
+       /* Memory to store the path names. We only use these paths when the
+        * separate option has been configured, but it's easier to just
+        * allocate enough memory in any case. */
+       s_paths = calloc (swap_num, PATH_MAX);
+       if (s_paths == NULL)
+       {
+               ERROR ("swap plugin: malloc failed.");
+               sfree (s);
+               return (-1);
+       }
+        for (i = 0; i < swap_num; i++)
+               s->swt_ent[i].ste_path = s_paths + (i * PATH_MAX);
+        s->swt_n = swap_num;
+
+        status = swapctl (SC_LIST, s);
+        if (status < 0)
+        {
+               char errbuf[1024];
+                ERROR ("swap plugin: swapctl (SC_LIST) failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               sfree (s_paths);
+                sfree (s);
+                return (-1);
+        }
+       else if (swap_num < status)
+       {
+               /* more elements returned than requested */
+               ERROR ("swap plugin: I allocated memory for %i structure%s, "
+                               "but swapctl(2) claims to have returned %i. "
+                               "I'm confused and will give up.",
+                               swap_num, (swap_num == 1) ? "" : "s",
+                               status);
+               sfree (s_paths);
+                sfree (s);
+                return (-1);
+       }
+       else if (swap_num > status)
+               /* less elements returned than requested */
+               swap_num = status;
+
+        for (i = 0; i < swap_num; i++)
+        {
+               char path[PATH_MAX];
+               gauge_t this_total;
+               gauge_t this_avail;
+
+                if ((s->swt_ent[i].ste_flags & ST_INDEL) != 0)
+                        continue;
+
+               this_total = (gauge_t) (s->swt_ent[i].ste_pages * pagesize);
+               this_avail = (gauge_t) (s->swt_ent[i].ste_free  * pagesize);
+
+               /* Shortcut for the "combined" setting (default) */
+               if (!report_by_device)
+               {
+                       avail += this_avail;
+                       total += this_total;
+                       continue;
+               }
+
+               sstrncpy (path, s->swt_ent[i].ste_path, sizeof (path));
+               escape_slashes (path, sizeof (path));
+
+               swap_submit_usage (path, this_total - this_avail, this_avail,
+                               NULL, NAN);
+        } /* for (swap_num) */
+
+        if (total < avail)
+        {
+                ERROR ("swap plugin: Total swap space (%g) is less than free swap space (%g).",
+                                total, avail);
+               sfree (s_paths);
+                sfree (s);
+                return (-1);
+        }
+
+       /* If the "separate" option was specified (report_by_device == 1), all
+        * values have already been dispatched from within the loop. */
+       if (!report_by_device)
+               swap_submit_usage (NULL, total - avail, avail, NULL, NAN);
+
+       sfree (s_paths);
+        sfree (s);
+       return (0);
+} /* }}} int swap_read */
+/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */
+
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS
+static int swap_read (void) /* {{{ */
+{
+       struct swapent *swap_entries;
+       int swap_num;
+       int status;
+       int i;
+
+       gauge_t used  = 0;
+       gauge_t total = 0;
+
+       swap_num = swapctl (SWAP_NSWAP, NULL, 0);
+       if (swap_num < 0)
+       {
+               ERROR ("swap plugin: swapctl (SWAP_NSWAP) failed with status %i.",
+                               swap_num);
+               return (-1);
+       }
+       else if (swap_num == 0)
+               return (0);
+
+       swap_entries = calloc (swap_num, sizeof (*swap_entries));
+       if (swap_entries == NULL)
+       {
+               ERROR ("swap plugin: calloc failed.");
+               return (-1);
+       }
+
+       status = swapctl (SWAP_STATS, swap_entries, swap_num);
+       if (status != swap_num)
+       {
+               ERROR ("swap plugin: swapctl (SWAP_STATS) failed with status %i.",
+                               status);
+               sfree (swap_entries);
+               return (-1);
+       }
+
+#if defined(DEV_BSIZE) && (DEV_BSIZE > 0)
+# define C_SWAP_BLOCK_SIZE ((gauge_t) DEV_BSIZE)
+#else
+# define C_SWAP_BLOCK_SIZE 512.0
+#endif
+
+       /* TODO: Report per-device stats. The path name is available from
+        * swap_entries[i].se_path */
+       for (i = 0; i < swap_num; i++)
+       {
+               if ((swap_entries[i].se_flags & SWF_ENABLE) == 0)
+                       continue;
+
+               used  += ((gauge_t) swap_entries[i].se_inuse) * C_SWAP_BLOCK_SIZE;
+               total += ((gauge_t) swap_entries[i].se_nblks) * C_SWAP_BLOCK_SIZE;
+       }
+
+       if (total < used)
+       {
+               ERROR ("swap plugin: Total swap space (%g) is less than used swap space (%g).",
+                               total, used);
+               return (-1);
+       }
+
+       swap_submit_usage (NULL, used, total - used, NULL, NAN);
+
+       sfree (swap_entries);
+       return (0);
+} /* }}} int swap_read */
+/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
+
+#elif defined(VM_SWAPUSAGE)
+static int swap_read (void) /* {{{ */
+{
+       int              mib[3];
+       size_t           mib_len;
+       struct xsw_usage sw_usage;
+       size_t           sw_usage_len;
+
+       mib_len = 2;
+       mib[0]  = CTL_VM;
+       mib[1]  = VM_SWAPUSAGE;
+
+       sw_usage_len = sizeof (struct xsw_usage);
+
+       if (sysctl (mib, mib_len, &sw_usage, &sw_usage_len, NULL, 0) != 0)
+               return (-1);
+
+       /* The returned values are bytes. */
+       swap_submit_usage (NULL,
+                       (gauge_t) sw_usage.xsu_used, (gauge_t) sw_usage.xsu_avail,
+                       NULL, NAN);
+
+       return (0);
+} /* }}} int swap_read */
+/* #endif VM_SWAPUSAGE */
+
+#elif HAVE_LIBKVM_GETSWAPINFO
+static int swap_read (void) /* {{{ */
+{
+       struct kvm_swap data_s;
+       int             status;
+
+       gauge_t used;
+       gauge_t total;
+
+       if (kvm_obj == NULL)
+               return (-1);
+
+       /* only one structure => only get the grand total, no details */
+       status = kvm_getswapinfo (kvm_obj, &data_s, 1, 0);
+       if (status == -1)
+               return (-1);
+
+       total = (gauge_t) data_s.ksw_total;
+       used  = (gauge_t) data_s.ksw_used;
+
+       total *= (gauge_t) kvm_pagesize;
+       used  *= (gauge_t) kvm_pagesize;
+
+       swap_submit_usage (NULL, used, total - used, NULL, NAN);
+
+       return (0);
+} /* }}} int swap_read */
+/* #endif HAVE_LIBKVM_GETSWAPINFO */
+
+#elif HAVE_LIBSTATGRAB
+static int swap_read (void) /* {{{ */
+{
+       sg_swap_stats *swap;
+
+       swap = sg_get_swap_stats ();
+       if (swap == NULL)
+               return (-1);
+
+       swap_submit_usage (NULL, (gauge_t) swap->used, (gauge_t) swap->free,
+                       NULL, NAN);
+
+       return (0);
+} /* }}} int swap_read */
+/* #endif  HAVE_LIBSTATGRAB */
+
+#elif HAVE_PERFSTAT
+static int swap_read (void) /* {{{ */
+{
+       perfstat_memory_total_t pmemory;
+       int status;
+
+       gauge_t total;
+       gauge_t free;
+       gauge_t reserved;
+
+       memset (&pmemory, 0, sizeof (pmemory));
+        status = perfstat_memory_total (NULL, &pmemory, sizeof(perfstat_memory_total_t), 1);
+       if (status < 0)
+       {
+                char errbuf[1024];
+                WARNING ("swap plugin: perfstat_memory_total failed: %s",
+                        sstrerror (errno, errbuf, sizeof (errbuf)));
+                return (-1);
+        }
+
+       total    = (gauge_t) (pmemory.pgsp_total * pagesize);
+       free     = (gauge_t) (pmemory.pgsp_free * pagesize);
+       reserved = (gauge_t) (pmemory.pgsp_rsvd * pagesize);
+
+       swap_submit_usage (NULL, total - free, free, "reserved", reserved);
+       swap_submit_derive ("in",  (derive_t) pmemory.pgspins * pagesize);
+       swap_submit_derive ("out", (derive_t) pmemory.pgspouts * pagesize);
+
+       return (0);
+} /* }}} int swap_read */
+#endif /* HAVE_PERFSTAT */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("swap", swap_config);
+       plugin_register_init ("swap", swap_init);
+       plugin_register_read ("swap", swap_read);
+} /* void module_register */
+
+/* vim: set fdm=marker : */
diff --git a/src/syslog.c b/src/syslog.c
new file mode 100644 (file)
index 0000000..3f73178
--- /dev/null
@@ -0,0 +1,160 @@
+/**
+ * collectd - src/syslog.c
+ * Copyright (C) 2007       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if HAVE_SYSLOG_H
+# include <syslog.h>
+#endif
+
+#if COLLECT_DEBUG
+static int log_level = LOG_DEBUG;
+#else
+static int log_level = LOG_INFO;
+#endif /* COLLECT_DEBUG */
+static int notif_severity = 0;
+
+static const char *config_keys[] =
+{
+       "LogLevel",
+       "NotifyLevel",
+};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+
+static int sl_config (const char *key, const char *value)
+{
+       if (strcasecmp (key, "LogLevel") == 0)
+       {
+               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);
+               }
+       }
+       else if (strcasecmp (key, "NotifyLevel") == 0)
+       {
+               notif_severity = parse_notif_severity (value);
+               if (notif_severity < 0)
+                       return (1);
+       }
+
+       return (0);
+} /* int sl_config */
+
+static void sl_log (int severity, const char *msg,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       if (severity > log_level)
+               return;
+
+       syslog (severity, "%s", msg);
+} /* void sl_log */
+
+static int sl_shutdown (void)
+{
+       closelog ();
+
+       return (0);
+}
+
+static int sl_notification (const notification_t *n,
+               user_data_t __attribute__((unused)) *user_data)
+{
+       char  buf[1024] = "";
+       size_t offset = 0;
+       int log_severity;
+       char *severity_string;
+       int status;
+
+       if (n->severity > notif_severity)
+               return (0);
+
+       switch (n->severity)
+       {
+               case NOTIF_FAILURE:
+                       severity_string = "FAILURE";
+                       log_severity = LOG_ERR;
+                       break;
+               case NOTIF_WARNING:
+                       severity_string = "WARNING";
+                       log_severity = LOG_WARNING;
+                       break;
+               case NOTIF_OKAY:
+                       severity_string = "OKAY";
+                       log_severity = LOG_NOTICE;
+                       break;
+               default:
+                       severity_string = "UNKNOWN";
+                       log_severity = LOG_ERR;
+       }
+
+#define BUFFER_ADD(...) do { \
+       status = ssnprintf (&buf[offset], sizeof (buf) - offset, \
+                       __VA_ARGS__); \
+       if (status < 1) \
+               return (-1); \
+       else if (((size_t) status) >= (sizeof (buf) - offset)) \
+               return (-ENOMEM); \
+       else \
+               offset += ((size_t) status); \
+} while (0)
+
+#define BUFFER_ADD_FIELD(field) do { \
+       if (n->field[0]) \
+               BUFFER_ADD (", " #field " = %s", n->field); \
+} while (0)
+
+       BUFFER_ADD ("Notification: severity = %s", severity_string);
+       BUFFER_ADD_FIELD (host);
+       BUFFER_ADD_FIELD (plugin);
+       BUFFER_ADD_FIELD (plugin_instance);
+       BUFFER_ADD_FIELD (type);
+       BUFFER_ADD_FIELD (type_instance);
+       BUFFER_ADD_FIELD (message);
+
+#undef BUFFER_ADD_FIELD
+#undef BUFFER_ADD
+
+       buf[sizeof (buf) - 1] = '\0';
+
+       sl_log (log_severity, buf, NULL);
+
+       return (0);
+} /* int sl_notification */
+
+void module_register (void)
+{
+       openlog ("collectd", LOG_CONS | LOG_PID, LOG_DAEMON);
+
+       plugin_register_config ("syslog", sl_config, config_keys, config_keys_num);
+       plugin_register_log ("syslog", sl_log, /* user_data = */ NULL);
+       plugin_register_notification ("syslog", sl_notification, NULL);
+       plugin_register_shutdown ("syslog", sl_shutdown);
+} /* void module_register(void) */
diff --git a/src/table.c b/src/table.c
new file mode 100644 (file)
index 0000000..c6b5bad
--- /dev/null
@@ -0,0 +1,565 @@
+/**
+ * collectd - src/table.c
+ * Copyright (C) 2009       Sebastian Harl
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+/*
+ * This module provides generic means to parse and dispatch tabular data.
+ */
+
+#include "collectd.h"
+#include "common.h"
+
+#include "configfile.h"
+#include "plugin.h"
+
+#define log_err(...) ERROR ("table plugin: " __VA_ARGS__)
+#define log_warn(...) WARNING ("table plugin: " __VA_ARGS__)
+
+/*
+ * private data types
+ */
+
+typedef struct {
+       char  *type;
+       char  *instance_prefix;
+       int   *instances;
+       size_t instances_num;
+       int   *values;
+       size_t values_num;
+
+       const data_set_t *ds;
+} tbl_result_t;
+
+typedef struct {
+       char *file;
+       char *sep;
+       char *instance;
+
+       tbl_result_t *results;
+       size_t        results_num;
+
+       size_t max_colnum;
+} tbl_t;
+
+static void tbl_result_setup (tbl_result_t *res)
+{
+       res->type            = NULL;
+
+       res->instance_prefix = NULL;
+       res->instances       = NULL;
+       res->instances_num   = 0;
+
+       res->values          = NULL;
+       res->values_num      = 0;
+
+       res->ds              = NULL;
+} /* tbl_result_setup */
+
+static void tbl_result_clear (tbl_result_t *res)
+{
+       sfree (res->type);
+
+       sfree (res->instance_prefix);
+       sfree (res->instances);
+       res->instances_num = 0;
+
+       sfree (res->values);
+       res->values_num = 0;
+
+       res->ds = NULL;
+} /* tbl_result_clear */
+
+static void tbl_setup (tbl_t *tbl, char *file)
+{
+       tbl->file        = sstrdup (file);
+       tbl->sep         = NULL;
+       tbl->instance    = NULL;
+
+       tbl->results     = NULL;
+       tbl->results_num = 0;
+
+       tbl->max_colnum  = 0;
+} /* tbl_setup */
+
+static void tbl_clear (tbl_t *tbl)
+{
+       size_t i;
+
+       sfree (tbl->file);
+       sfree (tbl->sep);
+       sfree (tbl->instance);
+
+       for (i = 0; i < tbl->results_num; ++i)
+               tbl_result_clear (tbl->results + i);
+       sfree (tbl->results);
+       tbl->results_num = 0;
+
+       tbl->max_colnum  = 0;
+} /* tbl_clear */
+
+static tbl_t *tables;
+static size_t tables_num;
+
+/*
+ * configuration handling
+ */
+
+static int tbl_config_set_s (char *name, char **var, oconfig_item_t *ci)
+{
+       if ((1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("\"%s\" expects a single string argument.", name);
+               return 1;
+       }
+
+       sfree (*var);
+       *var = sstrdup (ci->values[0].value.string);
+       return 0;
+} /* tbl_config_set_separator */
+
+static int tbl_config_append_array_i (char *name, int **var, size_t *len,
+               oconfig_item_t *ci)
+{
+       int *tmp;
+
+       size_t i;
+
+       if (1 > ci->values_num) {
+               log_err ("\"%s\" expects at least one argument.", name);
+               return 1;
+       }
+
+       for (i = 0; i < ci->values_num; ++i) {
+               if (OCONFIG_TYPE_NUMBER != ci->values[i].type) {
+                       log_err ("\"%s\" expects numerical arguments only.", name);
+                       return 1;
+               }
+       }
+
+       *len += ci->values_num;
+       tmp = (int *)realloc (*var, *len * sizeof (**var));
+       if (NULL == tmp) {
+               char errbuf[1024];
+               log_err ("realloc failed: %s.",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       *var = tmp;
+
+       for (i = *len - ci->values_num; i < *len; ++i)
+               (*var)[i] = (int)ci->values[i].value.number;
+       return 0;
+} /* tbl_config_append_array_s */
+
+static int tbl_config_result (tbl_t *tbl, oconfig_item_t *ci)
+{
+       tbl_result_t *res;
+
+       int status = 0;
+       size_t i;
+
+       if (0 != ci->values_num) {
+               log_err ("<Result> does not expect any arguments.");
+               return 1;
+       }
+
+       res = (tbl_result_t *)realloc (tbl->results,
+                       (tbl->results_num + 1) * sizeof (*tbl->results));
+       if (NULL == tbl) {
+               char errbuf[1024];
+               log_err ("realloc failed: %s.",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       tbl->results = res;
+       ++tbl->results_num;
+
+       res = tbl->results + tbl->results_num - 1;
+       tbl_result_setup (res);
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (0 == strcasecmp (c->key, "Type"))
+                       tbl_config_set_s (c->key, &res->type, c);
+               else if (0 == strcasecmp (c->key, "InstancePrefix"))
+                       tbl_config_set_s (c->key, &res->instance_prefix, c);
+               else if (0 == strcasecmp (c->key, "InstancesFrom"))
+                       tbl_config_append_array_i (c->key,
+                                       &res->instances, &res->instances_num, c);
+               else if (0 == strcasecmp (c->key, "ValuesFrom"))
+                       tbl_config_append_array_i (c->key,
+                                       &res->values, &res->values_num, c);
+               else
+                       log_warn ("Ignoring unknown config key \"%s\" "
+                                       " in <Result>.", c->key);
+       }
+
+       if (NULL == res->type) {
+               log_err ("No \"Type\" option specified for <Result> "
+                               "in table \"%s\".", tbl->file);
+               status = 1;
+       }
+
+       if (NULL == res->values) {
+               log_err ("No \"ValuesFrom\" option specified for <Result> "
+                               "in table \"%s\".", tbl->file);
+               status = 1;
+       }
+
+       if (0 != status) {
+               tbl_result_clear (res);
+               --tbl->results_num;
+               return status;
+       }
+       return 0;
+} /* tbl_config_result */
+
+static int tbl_config_table (oconfig_item_t *ci)
+{
+       tbl_t *tbl;
+
+       int status = 0;
+       size_t i;
+
+       if ((1 != ci->values_num)
+                       || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
+               log_err ("<Table> expects a single string argument.");
+               return 1;
+       }
+
+       tbl = (tbl_t *)realloc (tables, (tables_num + 1) * sizeof (*tables));
+       if (NULL == tbl) {
+               char errbuf[1024];
+               log_err ("realloc failed: %s.",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       tables = tbl;
+       ++tables_num;
+
+       tbl = tables + tables_num - 1;
+       tbl_setup (tbl, ci->values[0].value.string);
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (0 == strcasecmp (c->key, "Separator"))
+                       tbl_config_set_s (c->key, &tbl->sep, c);
+               else if (0 == strcasecmp (c->key, "Instance"))
+                       tbl_config_set_s (c->key, &tbl->instance, c);
+               else if (0 == strcasecmp (c->key, "Result"))
+                       tbl_config_result (tbl, c);
+               else
+                       log_warn ("Ignoring unknown config key \"%s\" "
+                                       "in <Table %s>.", c->key, tbl->file);
+       }
+
+       if (NULL == tbl->sep) {
+               log_err ("Table \"%s\" does not specify any separator.", tbl->file);
+               status = 1;
+       }
+       strunescape (tbl->sep, strlen (tbl->sep) + 1);
+
+       if (NULL == tbl->instance) {
+               tbl->instance = sstrdup (tbl->file);
+               replace_special (tbl->instance, strlen (tbl->instance));
+       }
+
+       if (NULL == tbl->results) {
+               log_err ("Table \"%s\" does not specify any (valid) results.",
+                               tbl->file);
+               status = 1;
+       }
+
+       if (0 != status) {
+               tbl_clear (tbl);
+               --tables_num;
+               return status;
+       }
+
+       for (i = 0; i < tbl->results_num; ++i) {
+               tbl_result_t *res = tbl->results + i;
+               size_t j;
+
+               for (j = 0; j < res->instances_num; ++j)
+                       if (res->instances[j] > tbl->max_colnum)
+                               tbl->max_colnum = res->instances[j];
+
+               for (j = 0; j < res->values_num; ++j)
+                       if (res->values[j] > tbl->max_colnum)
+                               tbl->max_colnum = res->values[j];
+       }
+       return 0;
+} /* tbl_config_table */
+
+static int tbl_config (oconfig_item_t *ci)
+{
+       size_t i;
+
+       for (i = 0; i < ci->children_num; ++i) {
+               oconfig_item_t *c = ci->children + i;
+
+               if (0 == strcasecmp (c->key, "Table"))
+                       tbl_config_table (c);
+               else
+                       log_warn ("Ignoring unknown config key \"%s\".", c->key);
+       }
+       return 0;
+} /* tbl_config */
+
+/*
+ * result handling
+ */
+
+static int tbl_prepare (tbl_t *tbl)
+{
+       size_t i;
+
+       for (i = 0; i < tbl->results_num; ++i) {
+               tbl_result_t *res = tbl->results + i;
+
+               res->ds = plugin_get_ds (res->type);
+               if (NULL == res->ds) {
+                       log_err ("Unknown type \"%s\". See types.db(5) for details.",
+                                       res->type);
+                       return -1;
+               }
+
+               if (res->values_num != (size_t)res->ds->ds_num) {
+                       log_err ("Invalid type \"%s\". Expected %zu data source%s, "
+                                       "got %i.", res->type, res->values_num,
+                                       (1 == res->values_num) ? "" : "s",
+                                       res->ds->ds_num);
+                       return -1;
+               }
+       }
+       return 0;
+} /* tbl_prepare */
+
+static int tbl_finish (tbl_t *tbl)
+{
+       size_t i;
+
+       for (i = 0; i < tbl->results_num; ++i)
+               tbl->results[i].ds = NULL;
+       return 0;
+} /* tbl_finish */
+
+static int tbl_result_dispatch (tbl_t *tbl, tbl_result_t *res,
+               char **fields, size_t fields_num)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t values[res->values_num];
+
+       size_t i;
+
+       assert (NULL != res->ds);
+       assert (res->values_num == res->ds->ds_num);
+
+       for (i = 0; i < res->values_num; ++i) {
+               char *value;
+
+               assert (res->values[i] < fields_num);
+               value = fields[res->values[i]];
+
+               if (0 != parse_value (value, &values[i], res->ds->ds[i].type))
+                       return -1;
+       }
+
+       vl.values     = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "table", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, tbl->instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, res->type, sizeof (vl.type));
+
+       if (0 == res->instances_num) {
+               if (NULL != res->instance_prefix)
+                       sstrncpy (vl.type_instance, res->instance_prefix,
+                                       sizeof (vl.type_instance));
+       }
+       else {
+               char *instances[res->instances_num];
+               char  instances_str[DATA_MAX_NAME_LEN];
+
+               for (i = 0; i < res->instances_num; ++i) {
+                       assert (res->instances[i] < fields_num);
+                       instances[i] = fields[res->instances[i]];
+               }
+
+               strjoin (instances_str, sizeof (instances_str),
+                               instances, STATIC_ARRAY_SIZE (instances), "-");
+               instances_str[sizeof (instances_str) - 1] = '\0';
+
+               vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+               if (NULL == res->instance_prefix)
+                       strncpy (vl.type_instance, instances_str,
+                                       sizeof (vl.type_instance));
+               else
+                       snprintf (vl.type_instance, sizeof (vl.type_instance),
+                                       "%s-%s", res->instance_prefix, instances_str);
+
+               if ('\0' != vl.type_instance[sizeof (vl.type_instance) - 1]) {
+                       vl.type_instance[sizeof (vl.type_instance) - 1] = '\0';
+                       log_warn ("Truncated type instance: %s.", vl.type_instance);
+               }
+       }
+
+       plugin_dispatch_values (&vl);
+       return 0;
+} /* tbl_result_dispatch */
+
+static int tbl_parse_line (tbl_t *tbl, char *line, size_t len)
+{
+       char *fields[tbl->max_colnum + 1];
+       char *ptr, *saveptr;
+
+       size_t i;
+
+       i = 0;
+       ptr = line;
+       saveptr = NULL;
+       while (NULL != (fields[i] = strtok_r (ptr, tbl->sep, &saveptr))) {
+               ptr = NULL;
+               ++i;
+
+               if (i > tbl->max_colnum)
+                       break;
+       }
+
+       if (i <= tbl->max_colnum) {
+               log_err ("Not enough columns in line "
+                               "(expected at least %zu, got %zu).",
+                               tbl->max_colnum + 1, i);
+               return -1;
+       }
+
+       for (i = 0; i < tbl->results_num; ++i)
+               if (0 != tbl_result_dispatch (tbl, tbl->results + i,
+                                       fields, STATIC_ARRAY_SIZE (fields))) {
+                       log_err ("Failed to dispatch result.");
+                       continue;
+               }
+       return 0;
+} /* tbl_parse_line */
+
+static int tbl_read_table (tbl_t *tbl)
+{
+       FILE *fh;
+       char  buf[4096];
+
+       fh = fopen (tbl->file, "r");
+       if (NULL == fh) {
+               char errbuf[1024];
+               log_err ("Failed to open file \"%s\": %s.", tbl->file,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return -1;
+       }
+
+       buf[sizeof (buf) - 1] = '\0';
+       while (NULL != fgets (buf, sizeof (buf), fh)) {
+               if ('\0' != buf[sizeof (buf) - 1]) {
+                       buf[sizeof (buf) - 1] = '\0';
+                       log_err ("Table %s: Truncated line: %s", tbl->file, buf);
+               }
+
+               if (0 != tbl_parse_line (tbl, buf, sizeof (buf))) {
+                       log_err ("Table %s: Failed to parse line: %s", tbl->file, buf);
+                       continue;
+               }
+       }
+
+       if (0 != ferror (fh)) {
+               char errbuf[1024];
+               log_err ("Failed to read from file \"%s\": %s.", tbl->file,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               fclose (fh);
+               return -1;
+       }
+
+       fclose (fh);
+       return 0;
+} /* tbl_read_table */
+
+/*
+ * collectd callbacks
+ */
+
+static int tbl_read (void)
+{
+       int status = -1;
+       size_t i;
+
+       if (0 == tables_num)
+               return 0;
+
+       for (i = 0; i < tables_num; ++i) {
+               tbl_t *tbl = tables + i;
+
+               if (0 != tbl_prepare (tbl)) {
+                       log_err ("Failed to prepare and parse table \"%s\".", tbl->file);
+                       continue;
+               }
+
+               if (0 == tbl_read_table (tbl))
+                       status = 0;
+
+               tbl_finish (tbl);
+       }
+       return status;
+} /* tbl_read */
+
+static int tbl_shutdown (void)
+{
+       size_t i;
+
+       for (i = 0; i < tables_num; ++i)
+               tbl_clear (&tables[i]);
+       sfree (tables);
+       return 0;
+} /* tbl_shutdown */
+
+static int tbl_init (void)
+{
+       if (0 == tables_num)
+               return 0;
+
+       plugin_register_read ("table", tbl_read);
+       plugin_register_shutdown ("table", tbl_shutdown);
+       return 0;
+} /* tbl_init */
+
+void module_register (void)
+{
+       plugin_register_complex_config ("table", tbl_config);
+       plugin_register_init ("table", tbl_init);
+} /* module_register */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
diff --git a/src/tail.c b/src/tail.c
new file mode 100644 (file)
index 0000000..ab06338
--- /dev/null
@@ -0,0 +1,378 @@
+/**
+ * collectd - src/tail.c
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_tail_match.h"
+
+/*
+ *  <Plugin tail>
+ *    <File "/var/log/exim4/mainlog">
+ *     Instance "exim"
+ *      Interval 60
+ *     <Match>
+ *       Regex "S=([1-9][0-9]*)"
+ *       ExcludeRegex "U=root.*S="
+ *       DSType "CounterAdd"
+ *       Type "ipt_bytes"
+ *       Instance "total"
+ *     </Match>
+ *    </File>
+ *  </Plugin>
+ */
+
+struct ctail_config_match_s
+{
+  char *regex;
+  char *excluderegex;
+  int flags;
+  char *type;
+  char *type_instance;
+  cdtime_t interval;
+};
+typedef struct ctail_config_match_s ctail_config_match_t;
+
+cu_tail_match_t **tail_match_list = NULL;
+size_t tail_match_list_num = 0;
+cdtime_t tail_match_list_intervals[255];
+
+static int ctail_config_add_match_dstype (ctail_config_match_t *cm,
+    oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("tail plugin: `DSType' needs exactly one string argument.");
+    return (-1);
+  }
+
+  if (strncasecmp ("Gauge", ci->values[0].value.string, strlen ("Gauge")) == 0)
+  {
+    cm->flags = UTILS_MATCH_DS_TYPE_GAUGE;
+    if (strcasecmp ("GaugeAverage", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_GAUGE_AVERAGE;
+    else if (strcasecmp ("GaugeMin", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_GAUGE_MIN;
+    else if (strcasecmp ("GaugeMax", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_GAUGE_MAX;
+    else if (strcasecmp ("GaugeLast", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_GAUGE_LAST;
+    else if (strcasecmp ("GaugeInc", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_GAUGE_INC;
+    else if (strcasecmp ("GaugeAdd", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_GAUGE_ADD;
+    else
+      cm->flags = 0;
+  }
+  else if (strncasecmp ("Counter", ci->values[0].value.string, strlen ("Counter")) == 0)
+  {
+    cm->flags = UTILS_MATCH_DS_TYPE_COUNTER;
+    if (strcasecmp ("CounterSet", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_COUNTER_SET;
+    else if (strcasecmp ("CounterAdd", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_COUNTER_ADD;
+    else if (strcasecmp ("CounterInc", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_COUNTER_INC;
+    else
+      cm->flags = 0;
+  }
+  else if (strncasecmp ("Derive", ci->values[0].value.string, strlen ("Derive")) == 0)
+  {
+    cm->flags = UTILS_MATCH_DS_TYPE_DERIVE;
+    if (strcasecmp ("DeriveSet", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_DERIVE_SET;
+    else if (strcasecmp ("DeriveAdd", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_DERIVE_ADD;
+    else if (strcasecmp ("DeriveInc", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_DERIVE_INC;
+    else
+      cm->flags = 0;
+  }
+  else if (strncasecmp ("Absolute", ci->values[0].value.string, strlen ("Absolute")) == 0)
+  {
+    cm->flags = UTILS_MATCH_DS_TYPE_ABSOLUTE;
+    if (strcasecmp ("AbsoluteSet", ci->values[0].value.string) == 0)
+      cm->flags |= UTILS_MATCH_CF_ABSOLUTE_SET;
+    else
+      cm->flags = 0;
+  }
+  else
+  {
+    cm->flags = 0;
+  }
+
+  if (cm->flags == 0)
+  {
+    WARNING ("tail plugin: `%s' is not a valid argument to `DSType'.",
+       ci->values[0].value.string);
+    return (-1);
+  }
+
+  return (0);
+} /* int ctail_config_add_match_dstype */
+
+static int ctail_config_add_match (cu_tail_match_t *tm,
+    const char *plugin_instance, oconfig_item_t *ci, cdtime_t interval)
+{
+  ctail_config_match_t cm;
+  int status;
+  int i;
+
+  memset (&cm, '\0', sizeof (cm));
+
+  if (ci->values_num != 0)
+  {
+    WARNING ("tail plugin: Ignoring arguments for the `Match' block.");
+  }
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if (strcasecmp ("Regex", option->key) == 0)
+      status = cf_util_get_string (option, &cm.regex);
+    else if (strcasecmp ("ExcludeRegex", option->key) == 0)
+      status = cf_util_get_string (option, &cm.excluderegex);
+    else if (strcasecmp ("DSType", option->key) == 0)
+      status = ctail_config_add_match_dstype (&cm, option);
+    else if (strcasecmp ("Type", option->key) == 0)
+      status = cf_util_get_string (option, &cm.type);
+    else if (strcasecmp ("Instance", option->key) == 0)
+      status = cf_util_get_string (option, &cm.type_instance);
+    else
+    {
+      WARNING ("tail plugin: Option `%s' not allowed here.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  while (status == 0)
+  {
+    if (cm.regex == NULL)
+    {
+      WARNING ("tail plugin: `Regex' missing in `Match' block.");
+      status = -1;
+      break;
+    }
+
+    if (cm.type == NULL)
+    {
+      WARNING ("tail plugin: `Type' missing in `Match' block.");
+      status = -1;
+      break;
+    }
+
+    if (cm.flags == 0)
+    {
+      WARNING ("tail plugin: `DSType' missing in `Match' block.");
+      status = -1;
+      break;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  if (status == 0)
+  {
+    status = tail_match_add_match_simple (tm, cm.regex, cm.excluderegex,
+       cm.flags, "tail", plugin_instance, cm.type, cm.type_instance, interval);
+
+    if (status != 0)
+    {
+      ERROR ("tail plugin: tail_match_add_match_simple failed.");
+    }
+  }
+
+  sfree (cm.regex);
+  sfree (cm.excluderegex);
+  sfree (cm.type);
+  sfree (cm.type_instance);
+
+  return (status);
+} /* int ctail_config_add_match */
+
+static int ctail_config_add_file (oconfig_item_t *ci)
+{
+  cu_tail_match_t *tm;
+  cdtime_t interval = 0;
+  char *plugin_instance = NULL;
+  int num_matches = 0;
+  int status;
+  int i;
+
+  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("tail plugin: `File' needs exactly one string argument.");
+    return (-1);
+  }
+
+  tm = tail_match_create (ci->values[0].value.string);
+  if (tm == NULL)
+  {
+    ERROR ("tail plugin: tail_match_create (%s) failed.",
+       ci->values[0].value.string);
+    return (-1);
+  }
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if (strcasecmp ("Instance", option->key) == 0)
+      status = cf_util_get_string (option, &plugin_instance);
+    else if (strcasecmp ("Interval", option->key) == 0)
+      cf_util_get_cdtime (option, &interval);
+    else if (strcasecmp ("Match", option->key) == 0)
+    {
+      status = ctail_config_add_match (tm, plugin_instance, option, interval);
+      if (status == 0)
+       num_matches++;
+      /* Be mild with failed matches.. */
+      status = 0;
+    }
+    else
+    {
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  if (num_matches == 0)
+  {
+    ERROR ("tail plugin: No (valid) matches found for file `%s'.",
+       ci->values[0].value.string);
+    tail_match_destroy (tm);
+    return (-1);
+  }
+  else
+  {
+    cu_tail_match_t **temp;
+
+    temp = (cu_tail_match_t **) realloc (tail_match_list,
+       sizeof (cu_tail_match_t *) * (tail_match_list_num + 1));
+    if (temp == NULL)
+    {
+      ERROR ("tail plugin: realloc failed.");
+      tail_match_destroy (tm);
+      return (-1);
+    }
+
+    tail_match_list = temp;
+    tail_match_list[tail_match_list_num] = tm;
+    tail_match_list_intervals[tail_match_list_num] = interval;
+    tail_match_list_num++;
+  }
+
+  return (0);
+} /* int ctail_config_add_file */
+
+static int ctail_config (oconfig_item_t *ci)
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+
+    if (strcasecmp ("File", option->key) == 0)
+      ctail_config_add_file (option);
+    else
+    {
+      WARNING ("tail plugin: Option `%s' not allowed here.", option->key);
+    }
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  return (0);
+} /* int ctail_config */
+
+static int ctail_read (user_data_t *ud)
+{
+  int status;
+
+  status = tail_match_read ((cu_tail_match_t *)ud->data);
+  if (status != 0)
+  {
+    ERROR ("tail plugin: tail_match_read failed.");
+    return (-1);
+  }
+
+  return (0);
+} /* int ctail_read */
+
+static int ctail_init (void)
+{
+  struct timespec cb_interval;
+  char str[255];
+  user_data_t ud;
+  size_t i;
+
+  if (tail_match_list_num == 0)
+  {
+    WARNING ("tail plugin: File list is empty. Returning an error.");
+    return (-1);
+  }
+
+  for (i = 0; i < tail_match_list_num; i++)
+  {
+    ud.data = (void *)tail_match_list[i];
+    ssnprintf(str, sizeof(str), "tail-%zu", i);
+    CDTIME_T_TO_TIMESPEC (tail_match_list_intervals[i], &cb_interval);
+    plugin_register_complex_read (NULL, str, ctail_read, &cb_interval, &ud);
+  }
+
+  return (0);
+} /* int ctail_init */
+
+static int ctail_shutdown (void)
+{
+  size_t i;
+
+  for (i = 0; i < tail_match_list_num; i++)
+  {
+    tail_match_destroy (tail_match_list[i]);
+    tail_match_list[i] = NULL;
+  }
+  sfree (tail_match_list);
+  tail_match_list_num = 0;
+
+  return (0);
+} /* int ctail_shutdown */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("tail", ctail_config);
+  plugin_register_init ("tail", ctail_init);
+  plugin_register_shutdown ("tail", ctail_shutdown);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/tail_csv.c b/src/tail_csv.c
new file mode 100644 (file)
index 0000000..a70b665
--- /dev/null
@@ -0,0 +1,565 @@
+/**
+ * collectd - src/tail_csv.c
+ * Copyright (C) 2013 Kris Nielander
+ * Copyright (C) 2013 Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Kris Nielander <nielander at fox-it.com>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
+#include "common.h" /* auxiliary functions */
+#include "utils_tail.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct metric_definition_s {
+    char *name;
+    char *type;
+    char *instance;
+    int data_source_type;
+    int value_from;
+    struct metric_definition_s *next;
+};
+typedef struct metric_definition_s metric_definition_t;
+
+struct instance_definition_s {
+    char *instance;
+    char *path;
+    cu_tail_t *tail;
+    metric_definition_t **metric_list;
+    size_t metric_list_len;
+    cdtime_t interval;
+    int time_from;
+    struct instance_definition_s *next;
+};
+typedef struct instance_definition_s instance_definition_t;
+
+/* Private */
+static metric_definition_t *metric_head = NULL;
+
+static int tcsv_submit (instance_definition_t *id,
+        metric_definition_t *md,
+        value_t v, cdtime_t t)
+{
+    /* Registration variables */
+    value_list_t vl = VALUE_LIST_INIT;
+
+    /* Register */
+    vl.values_len = 1;
+    vl.values = &v;
+
+    sstrncpy(vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy(vl.plugin, "tail_csv", sizeof(vl.plugin));
+    if (id->instance != NULL)
+        sstrncpy(vl.plugin_instance, id->instance, sizeof(vl.plugin_instance));
+    sstrncpy(vl.type, md->type, sizeof(vl.type));
+    if (md->instance != NULL)
+        sstrncpy(vl.type_instance, md->instance, sizeof(vl.type_instance));
+
+    vl.time = t;
+    vl.interval = id->interval;
+
+    return (plugin_dispatch_values(&vl));
+}
+
+static cdtime_t parse_time (char const *tbuf)
+{
+    double t;
+    char *endptr = 0;
+
+    errno = 0;
+    t = strtod (tbuf, &endptr);
+    if ((errno != 0) || (endptr == NULL) || (endptr[0] != 0))
+        return (cdtime ());
+
+    return (DOUBLE_TO_CDTIME_T (t));
+}
+
+static int tcsv_read_metric (instance_definition_t *id,
+        metric_definition_t *md,
+        char **fields, size_t fields_num)
+{
+    value_t v;
+    cdtime_t t;
+    int status;
+
+    if (md->data_source_type == -1)
+        return (EINVAL);
+
+    if ((md->value_from >= fields_num) || (id->time_from >= fields_num))
+        return (EINVAL);
+
+    t = 0;
+    if (id->time_from >= 0)
+        t = parse_time (fields[id->time_from]);
+
+    status = parse_value (fields[md->value_from], &v, md->data_source_type);
+    if (status != 0)
+        return (status);
+
+    return (tcsv_submit (id, md, v, t));
+}
+
+static _Bool tcsv_check_index (int index, size_t fields_num, char const *name)
+{
+    if (index < 0)
+        return 1;
+    else if (((size_t) index) < fields_num)
+        return 1;
+
+    ERROR ("tail_csv plugin: Metric \"%s\": Request for index %i when "
+            "only %zu fields are available.",
+            name, index, fields_num);
+    return (0);
+}
+
+static int tcsv_read_buffer (instance_definition_t *id,
+        char *buffer, size_t buffer_size)
+{
+    char **metrics;
+    size_t metrics_num;
+
+    char *ptr;
+    size_t i;
+
+    /* Remove newlines at the end of line. */
+    while (buffer_size > 0) {
+        if ((buffer[buffer_size - 1] == '\n')
+                || (buffer[buffer_size - 1] == '\r')) {
+            buffer[buffer_size - 1] = 0;
+            buffer_size--;
+        } else {
+            break;
+        }
+    }
+
+    /* Ignore empty lines. */
+    if ((buffer_size == 0) || (buffer[0] == '#'))
+        return (0);
+
+    /* Count the number of fields. */
+    metrics_num = 1;
+    for (i = 0; i < buffer_size; i++) {
+        if (buffer[i] == ',')
+            metrics_num++;
+    }
+
+    if (metrics_num == 1) {
+        ERROR("tail_csv plugin: last line of `%s' does not contain "
+                "enough values.", id->path);
+        return (-1);
+    }
+
+    /* Create a list of all values */
+    metrics = calloc (metrics_num, sizeof (*metrics));
+    if (metrics == NULL) {
+        ERROR ("tail_csv plugin: calloc failed.");
+        return (ENOMEM);
+    }
+
+    ptr = buffer;
+    metrics[0] = ptr;
+    i = 1;
+    for (ptr = buffer; *ptr != 0; ptr++) {
+        if (*ptr != ',')
+            continue;
+
+        *ptr = 0;
+        metrics[i] = ptr + 1;
+        i++;
+    }
+    assert (i == metrics_num);
+
+    /* Register values */
+    for (i = 0; i < id->metric_list_len; ++i){
+        metric_definition_t *md = id->metric_list[i];
+
+        if (!tcsv_check_index (md->value_from, metrics_num, md->name)
+                || !tcsv_check_index (id->time_from, metrics_num, md->name))
+            continue;
+
+        tcsv_read_metric (id, md, metrics, metrics_num);
+    }
+
+    /* Free up resources */
+    sfree (metrics);
+    return (0);
+}
+
+static int tcsv_read (user_data_t *ud) {
+    instance_definition_t *id;
+    id = ud->data;
+
+    if (id->tail == NULL)
+    {
+        id->tail = cu_tail_create (id->path);
+        if (id->tail == NULL)
+        {
+            ERROR ("tail_csv plugin: cu_tail_create (\"%s\") failed.",
+                    id->path);
+            return (-1);
+        }
+    }
+
+    while (42)
+    {
+        char buffer[1024];
+        size_t buffer_len;
+        int status;
+
+        status = cu_tail_readline (id->tail, buffer, (int) sizeof (buffer));
+        if (status != 0)
+        {
+            ERROR ("tail_csv plugin: File \"%s\": cu_tail_readline failed "
+                    "with status %i.", id->path, status);
+            return (-1);
+        }
+
+        buffer_len = strlen (buffer);
+        if (buffer_len == 0)
+            break;
+
+        tcsv_read_buffer (id, buffer, buffer_len);
+    }
+
+    return (0);
+}
+
+static void tcsv_metric_definition_destroy(void *arg){
+    metric_definition_t *md;
+    metric_definition_t *next;
+
+    md = arg;
+    if (md == NULL)
+        return;
+
+    next = md->next;
+    md->next = NULL;
+
+    sfree(md->name);
+    sfree(md->type);
+    sfree(md->instance);
+    sfree(md);
+
+    tcsv_metric_definition_destroy (next);
+}
+
+static int tcsv_config_get_index(oconfig_item_t *ci, int *ret_index) {
+    int index;
+
+    if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)){
+        WARNING("tail_csv plugin: The \"%s\" config option needs exactly one "
+                "integer argument.", ci->key);
+        return (-1);
+    }
+
+    index = (int) ci->values[0].value.number;
+    if (index < 0) {
+        WARNING("tail_csv plugin: The \"%s\" config option must be positive "
+                "(or zero).", ci->key);
+        return (-1);
+    }
+
+    *ret_index = index;
+    return (0);
+}
+
+/* Parse metric  */
+static int tcsv_config_add_metric(oconfig_item_t *ci){
+    metric_definition_t *md;
+    int status = 0;
+    int i;
+
+    md = (metric_definition_t *)malloc(sizeof(*md));
+    if (md == NULL)
+        return (-1);
+    memset(md, 0, sizeof(*md));
+    md->name = NULL;
+    md->type = NULL;
+    md->instance = NULL;
+    md->data_source_type = -1;
+    md->value_from = -1;
+    md->next = NULL;
+
+    status = cf_util_get_string (ci, &md->name);
+    if (status != 0) {
+        sfree (md);
+        return (-1);
+    }
+
+    for (i = 0; i < ci->children_num; ++i){
+        oconfig_item_t *option = ci->children + i;
+        status = 0;
+
+        if (strcasecmp("Type", option->key) == 0)
+            status = cf_util_get_string(option, &md->type);
+        else if (strcasecmp("Instance", option->key) == 0)
+            status = cf_util_get_string(option, &md->instance);
+        else if (strcasecmp("ValueFrom", option->key) == 0)
+            status = tcsv_config_get_index (option, &md->value_from);
+        else {
+            WARNING("tail_csv plugin: Option `%s' not allowed here.", option->key);
+            status = -1;
+        }
+
+        if (status != 0)
+            break;
+    }
+
+    if (status != 0){
+        tcsv_metric_definition_destroy(md);
+        return (-1);
+    }
+
+    /* Verify all necessary options have been set. */
+    if (md->type == NULL) {
+        WARNING("tail_csv plugin: Option `Type' must be set.");
+        status = -1;
+    } else if (md->value_from < 0) {
+        WARNING("tail_csv plugin: Option `ValueFrom' must be set.");
+        status = -1;
+    }
+    if (status != 0) {
+        tcsv_metric_definition_destroy(md);
+        return (status);
+    }
+
+    if (metric_head == NULL)
+        metric_head = md;
+    else {
+        metric_definition_t *last;
+        last = metric_head;
+        while (last->next != NULL)
+            last = last->next;
+        last->next = md;
+    }
+
+    return (0);
+}
+
+static void tcsv_instance_definition_destroy(void *arg){
+    instance_definition_t *id;
+
+    id = arg;
+    if (id == NULL)
+        return;
+
+    if (id->tail != NULL)
+        cu_tail_destroy (id->tail);
+    id->tail = NULL;
+
+    sfree(id->instance);
+    sfree(id->path);
+    sfree(id->metric_list);
+    sfree(id);
+}
+
+static int tcsv_config_add_instance_collect(instance_definition_t *id, oconfig_item_t *ci){
+    metric_definition_t *metric;
+    int i;
+
+    if (ci->values_num < 1){
+        WARNING("tail_csv plugin: The `Collect' config option needs at least one argument.");
+        return (-1);
+    }
+
+    /* Verify string arguments */
+    for (i = 0; i < ci->values_num; ++i)
+        if (ci->values[i].type != OCONFIG_TYPE_STRING){
+            WARNING("tail_csv plugin: All arguments to `Collect' must be strings.");
+            return (-1);
+        }
+
+    id->metric_list = (metric_definition_t **)malloc(sizeof(metric_definition_t *) * ci->values_num);
+    if (id->metric_list == NULL)
+        return (-1);
+
+    for (i = 0; i < ci->values_num; ++i){
+        for (metric = metric_head; metric != NULL; metric = metric->next)
+            if (strcasecmp(ci->values[i].value.string, metric->name) == 0)
+                break;
+
+        if (metric == NULL){
+            WARNING("tail_csv plugin: `Collect' argument not found `%s'.", ci->values[i].value.string);
+            return (-1);
+        }
+
+        id->metric_list[i] = metric;
+        id->metric_list_len++;
+    }
+
+    return (0);
+}
+
+/* <File /> block */
+static int tcsv_config_add_file(oconfig_item_t *ci)
+{
+    instance_definition_t* id;
+    int status = 0;
+    int i;
+
+    /* Registration variables */
+    char cb_name[DATA_MAX_NAME_LEN];
+    user_data_t cb_data;
+    struct timespec cb_interval;
+
+    id = malloc(sizeof(*id));
+    if (id == NULL)
+        return (-1);
+    memset(id, 0, sizeof(*id));
+    id->instance = NULL;
+    id->path = NULL;
+    id->metric_list = NULL;
+    id->time_from = -1;
+    id->next = NULL;
+
+    status = cf_util_get_string (ci, &id->path);
+    if (status != 0) {
+        sfree (id);
+        return (status);
+    }
+
+    /* Use default interval. */
+    id->interval = plugin_get_interval();
+
+    for (i = 0; i < ci->children_num; ++i){
+        oconfig_item_t *option = ci->children + i;
+        status = 0;
+
+        if (strcasecmp("Instance", option->key) == 0)
+            status = cf_util_get_string(option, &id->instance);
+        else if (strcasecmp("Collect", option->key) == 0)
+            status = tcsv_config_add_instance_collect(id, option);
+        else if (strcasecmp("Interval", option->key) == 0)
+            cf_util_get_cdtime(option, &id->interval);
+        else if (strcasecmp("TimeFrom", option->key) == 0)
+            status = tcsv_config_get_index (option, &id->time_from);
+        else {
+            WARNING("tail_csv plugin: Option `%s' not allowed here.", option->key);
+            status = -1;
+        }
+
+        if (status != 0)
+            break;
+    }
+
+    if (status != 0){
+        tcsv_instance_definition_destroy(id);
+        return (-1);
+    }
+
+    /* Verify all necessary options have been set. */
+    if (id->path == NULL){
+        WARNING("tail_csv plugin: Option `Path' must be set.");
+        status = -1;
+    } else if (id->metric_list == NULL){
+        WARNING("tail_csv plugin: Option `Collect' must be set.");
+        status = -1;
+   }
+
+    if (status != 0){
+        tcsv_instance_definition_destroy(id);
+        return (-1);
+    }
+
+    ssnprintf (cb_name, sizeof (cb_name), "tail_csv/%s", id->path);
+    memset(&cb_data, 0, sizeof(cb_data));
+    cb_data.data = id;
+    cb_data.free_func = tcsv_instance_definition_destroy;
+    CDTIME_T_TO_TIMESPEC(id->interval, &cb_interval);
+    status = plugin_register_complex_read(NULL, cb_name, tcsv_read, &cb_interval, &cb_data);
+
+    if (status != 0){
+        ERROR("tail_csv plugin: Registering complex read function failed.");
+        tcsv_instance_definition_destroy(id);
+        return (-1);
+    }
+
+    return (0);
+}
+
+/* Parse blocks */
+static int tcsv_config(oconfig_item_t *ci){
+    int i;
+    for (i = 0; i < ci->children_num; ++i){
+        oconfig_item_t *child = ci->children + i;
+        if (strcasecmp("Metric", child->key) == 0)
+            tcsv_config_add_metric(child);
+        else if (strcasecmp("File", child->key) == 0)
+            tcsv_config_add_file(child);
+        else
+            WARNING("tail_csv plugin: Ignore unknown config option `%s'.", child->key);
+    }
+
+    return (0);
+} /* int tcsv_config */
+
+static int tcsv_init(void) { /* {{{ */
+    static _Bool have_init = 0;
+    metric_definition_t *md;
+
+    if (have_init)
+        return (0);
+
+    for (md = metric_head; md != NULL; md = md->next) {
+        data_set_t const *ds;
+
+        /* Retrieve the data source type from the types db. */
+        ds = plugin_get_ds(md->type);
+        if (ds == NULL)
+        {
+            ERROR ("tail_csv plugin: Failed to look up type \"%s\" for "
+                    "metric \"%s\". It may not be defined in the types.db "
+                    "file. Please read the types.db(5) manual page for more "
+                    "details.",
+                    md->type, md->name);
+            continue;
+        }
+        else if (ds->ds_num != 1)
+        {
+            ERROR ("tail_csv plugin: The type \"%s\" has %i data sources. "
+                    "Only types with a single data soure are supported.",
+                    ds->type, ds->ds_num);
+            continue;
+        }
+
+        md->data_source_type = ds->ds->type;
+    }
+
+    return (0);
+} /* }}} int tcsv_init */
+
+static int tcsv_shutdown (void) {
+    tcsv_metric_definition_destroy (metric_head);
+    metric_head = NULL;
+
+    return (0);
+}
+
+void module_register(void){
+    plugin_register_complex_config("tail_csv", tcsv_config);
+    plugin_register_init("tail_csv", tcsv_init);
+    plugin_register_shutdown("tail_csv", tcsv_shutdown);
+}
+
+/* vim: set sw=4 sts=4 et : */
diff --git a/src/tape.c b/src/tape.c
new file mode 100644 (file)
index 0000000..a8e7dc4
--- /dev/null
@@ -0,0 +1,133 @@
+/**
+ * collectd - src/tape.c
+ * Copyright (C) 2005,2006  Scott Garrett
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Scott Garrett <sgarrett at technomancer.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if !HAVE_LIBKSTAT
+# error "No applicable input method."
+#endif
+
+#define MAX_NUMTAPE 256
+extern kstat_ctl_t *kc;
+static kstat_t *ksp[MAX_NUMTAPE];
+static int numtape = 0;
+
+static int tape_init (void)
+{
+       kstat_t *ksp_chain;
+
+       numtape = 0;
+
+       if (kc == NULL)
+               return (-1);
+
+       for (numtape = 0, ksp_chain = kc->kc_chain;
+                       (numtape < MAX_NUMTAPE) && (ksp_chain != NULL);
+                       ksp_chain = ksp_chain->ks_next)
+       {
+               if (strncmp (ksp_chain->ks_class, "tape", 4) )
+                       continue;
+               if (ksp_chain->ks_type != KSTAT_TYPE_IO)
+                       continue;
+               ksp[numtape++] = ksp_chain;
+       }
+
+       return (0);
+} /* int tape_init */
+
+static void tape_submit (const char *plugin_instance,
+               const char *type,
+               derive_t read, derive_t write)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = read;
+       values[1].derive = write;
+
+       vl.values = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "tape", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void tape_submit */
+
+static int tape_read (void)
+{
+
+#if HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_NWRITES && HAVE_KSTAT_IO_T_WTIME
+# define KIO_ROCTETS reads
+# define KIO_WOCTETS writes
+# define KIO_ROPS    nreads
+# define KIO_WOPS    nwrites
+# define KIO_RTIME   rtime
+# define KIO_WTIME   wtime
+#elif HAVE_KSTAT_IO_T_NWRITTEN && HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_WTIME
+# define KIO_ROCTETS nread
+# define KIO_WOCTETS nwritten
+# define KIO_ROPS    reads
+# define KIO_WOPS    writes
+# define KIO_RTIME   rtime
+# define KIO_WTIME   wtime
+#else
+# error "kstat_io_t does not have the required members"
+#endif
+       static kstat_io_t kio;
+       int i;
+
+       if (kc == NULL)
+               return (-1);
+
+       if (numtape <= 0)
+               return (-1);
+
+       for (i = 0; i < numtape; i++)
+       {
+               if (kstat_read (kc, ksp[i], &kio) == -1)
+                       continue;
+
+               if (strncmp (ksp[i]->ks_class, "tape", 4) == 0)
+               {
+                       tape_submit (ksp[i]->ks_name, "tape_octets",
+                                       kio.KIO_ROCTETS, kio.KIO_WOCTETS);
+                       tape_submit (ksp[i]->ks_name, "tape_ops",
+                                       kio.KIO_ROPS, kio.KIO_WOPS);
+                       /* FIXME: Convert this to microseconds if necessary */
+                       tape_submit (ksp[i]->ks_name, "tape_time",
+                                       kio.KIO_RTIME, kio.KIO_WTIME);
+               }
+       }
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_init ("tape", tape_init);
+       plugin_register_read ("tape", tape_read);
+}
diff --git a/src/target_notification.c b/src/target_notification.c
new file mode 100644 (file)
index 0000000..2e5ab3b
--- /dev/null
@@ -0,0 +1,290 @@
+/**
+ * collectd - src/target_notification.c
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "filter_chain.h"
+#include "utils_cache.h"
+#include "utils_subst.h"
+
+struct tn_data_s
+{
+  int severity;
+  char *message;
+};
+typedef struct tn_data_s tn_data_t;
+
+static int tn_config_add_severity (tn_data_t *data, /* {{{ */
+    const oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("Target `notification': The `%s' option requires exactly one string "
+        "argument.", ci->key);
+    return (-1);
+  }
+
+  if ((strcasecmp ("FAILURE", ci->values[0].value.string) == 0)
+      || (strcasecmp ("CRITICAL", ci->values[0].value.string) == 0))
+    data->severity = NOTIF_FAILURE;
+  else if ((strcasecmp ("WARNING", ci->values[0].value.string) == 0)
+      || (strcasecmp ("WARN", ci->values[0].value.string) == 0))
+    data->severity = NOTIF_WARNING;
+  else if (strcasecmp ("OKAY", ci->values[0].value.string) == 0)
+    data->severity = NOTIF_OKAY;
+  else
+  {
+    WARNING ("Target `notification': Unknown severity `%s'. "
+        "Will use `FAILURE' instead.",
+        ci->values[0].value.string);
+    data->severity = NOTIF_FAILURE;
+  }
+
+  return (0);
+} /* }}} int tn_config_add_severity */
+
+static int tn_config_add_string (char **dest, /* {{{ */
+    const oconfig_item_t *ci)
+{
+  char *temp;
+
+  if (dest == NULL)
+    return (-EINVAL);
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("Target `notification': The `%s' option requires exactly one string "
+        "argument.", ci->key);
+    return (-1);
+  }
+
+  if (ci->values[0].value.string[0] == 0)
+  {
+    ERROR ("Target `notification': The `%s' option does not accept empty strings.",
+        ci->key);
+    return (-1);
+  }
+
+  temp = sstrdup (ci->values[0].value.string);
+  if (temp == NULL)
+  {
+    ERROR ("tn_config_add_string: sstrdup failed.");
+    return (-1);
+  }
+
+  free (*dest);
+  *dest = temp;
+
+  return (0);
+} /* }}} int tn_config_add_string */
+
+static int tn_destroy (void **user_data) /* {{{ */
+{
+  tn_data_t *data;
+
+  if (user_data == NULL)
+    return (-EINVAL);
+
+  data = *user_data;
+  if (data == NULL)
+    return (0);
+
+  sfree (data->message);
+  sfree (data);
+
+  return (0);
+} /* }}} int tn_destroy */
+
+static int tn_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  tn_data_t *data;
+  int status;
+  int i;
+
+  data = (tn_data_t *) malloc (sizeof (*data));
+  if (data == NULL)
+  {
+    ERROR ("tn_create: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (data, 0, sizeof (*data));
+
+  data->message = NULL;
+  data->severity = 0;
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Message", child->key) == 0)
+      status = tn_config_add_string (&data->message, child);
+    else if (strcasecmp ("Severity", child->key) == 0)
+      status = tn_config_add_severity (data, child);
+    else
+    {
+      ERROR ("Target `notification': The `%s' configuration option is not understood "
+          "and will be ignored.", child->key);
+      status = 0;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Additional sanity-checking */
+  while (status == 0)
+  {
+    if ((data->severity != NOTIF_FAILURE)
+        && (data->severity != NOTIF_WARNING)
+        && (data->severity != NOTIF_OKAY))
+    {
+      DEBUG ("Target `notification': Setting "
+          "the default severity `WARNING'.");
+      data->severity = NOTIF_WARNING;
+    }
+
+    if (data->message == NULL)
+    {
+      ERROR ("Target `notification': No `Message' option has been specified. "
+          "Without it, the `Notification' target is useless.");
+      status = -1;
+    }
+
+    break;
+  }
+
+  if (status != 0)
+  {
+    tn_destroy ((void *) data);
+    return (status);
+  }
+
+  *user_data = data;
+  return (0);
+} /* }}} int tn_create */
+
+static int tn_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
+    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+  tn_data_t *data;
+  notification_t n;
+  char temp[NOTIF_MAX_MSG_LEN];
+
+  gauge_t *rates;
+  int rates_failed;
+
+  int i;
+
+  if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
+    return (-EINVAL);
+
+  data = *user_data;
+  if (data == NULL)
+  {
+    ERROR ("Target `notification': Invoke: `data' is NULL.");
+    return (-EINVAL);
+  }
+
+  /* Initialize the structure. */
+  memset (&n, 0, sizeof (n));
+  n.severity = data->severity;
+  n.time = cdtime ();
+  sstrncpy (n.message, data->message, sizeof (n.message));
+  sstrncpy (n.host, vl->host, sizeof (n.host));
+  sstrncpy (n.plugin, vl->plugin, sizeof (n.plugin));
+  sstrncpy (n.plugin_instance, vl->plugin_instance,
+      sizeof (n.plugin_instance));
+  sstrncpy (n.type, vl->type, sizeof (n.type));
+  sstrncpy (n.type_instance, vl->type_instance,
+      sizeof (n.type_instance));
+  n.meta = NULL;
+
+#define REPLACE_FIELD(t,v) \
+  if (subst_string (temp, sizeof (temp), n.message, t, v) != NULL) \
+    sstrncpy (n.message, temp, sizeof (n.message));
+  REPLACE_FIELD ("%{host}", n.host);
+  REPLACE_FIELD ("%{plugin}", n.plugin);
+  REPLACE_FIELD ("%{plugin_instance}", n.plugin_instance);
+  REPLACE_FIELD ("%{type}", n.type);
+  REPLACE_FIELD ("%{type_instance}", n.type_instance);
+
+  rates_failed = 0;
+  rates = NULL;
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    char template[DATA_MAX_NAME_LEN];
+    char value_str[DATA_MAX_NAME_LEN];
+
+    ssnprintf (template, sizeof (template), "%%{ds:%s}", ds->ds[i].name);
+
+    if (ds->ds[i].type != DS_TYPE_GAUGE)
+    {
+      if ((rates == NULL) && (rates_failed == 0))
+      {
+        rates = uc_get_rate (ds, vl);
+        if (rates == NULL)
+          rates_failed = 1;
+      }
+    }
+
+    /* If this is a gauge value, use the current value. */
+    if (ds->ds[i].type == DS_TYPE_GAUGE)
+      ssnprintf (value_str, sizeof (value_str),
+          GAUGE_FORMAT, (double) vl->values[i].gauge);
+    /* If it's a counter, try to use the current rate. This may fail, if the
+     * value has been renamed. */
+    else if (rates != NULL)
+      ssnprintf (value_str, sizeof (value_str),
+          GAUGE_FORMAT, (double) rates[i]);
+    /* Since we don't know any better, use the string `unknown'. */
+    else
+      sstrncpy (value_str, "unknown", sizeof (value_str));
+
+    REPLACE_FIELD (template, value_str);
+  }
+  sfree (rates);
+
+  plugin_dispatch_notification (&n);
+
+  return (FC_TARGET_CONTINUE);
+} /* }}} int tn_invoke */
+
+void module_register (void)
+{
+       target_proc_t tproc;
+
+       memset (&tproc, 0, sizeof (tproc));
+       tproc.create  = tn_create;
+       tproc.destroy = tn_destroy;
+       tproc.invoke  = tn_invoke;
+       fc_register_target ("notification", tproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
+
diff --git a/src/target_replace.c b/src/target_replace.c
new file mode 100644 (file)
index 0000000..a85eced
--- /dev/null
@@ -0,0 +1,361 @@
+/**
+ * collectd - src/target_replace.c
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "filter_chain.h"
+#include "utils_subst.h"
+
+#include <regex.h>
+
+struct tr_action_s;
+typedef struct tr_action_s tr_action_t;
+struct tr_action_s
+{
+  regex_t re;
+  char *replacement;
+  int may_be_empty;
+
+  tr_action_t *next;
+};
+
+struct tr_data_s
+{
+  tr_action_t *host;
+  tr_action_t *plugin;
+  tr_action_t *plugin_instance;
+  /* tr_action_t *type; */
+  tr_action_t *type_instance;
+};
+typedef struct tr_data_s tr_data_t;
+
+static char *tr_strdup (const char *orig) /* {{{ */
+{
+  size_t sz;
+  char *dest;
+
+  if (orig == NULL)
+    return (NULL);
+
+  sz = strlen (orig) + 1;
+  dest = (char *) malloc (sz);
+  if (dest == NULL)
+    return (NULL);
+
+  memcpy (dest, orig, sz);
+
+  return (dest);
+} /* }}} char *tr_strdup */
+
+static void tr_action_destroy (tr_action_t *act) /* {{{ */
+{
+  if (act == NULL)
+    return;
+
+  regfree (&act->re);
+  sfree (act->replacement);
+
+  if (act->next != NULL)
+    tr_action_destroy (act->next);
+
+  sfree (act);
+} /* }}} void tr_action_destroy */
+
+static int tr_config_add_action (tr_action_t **dest, /* {{{ */
+    const oconfig_item_t *ci, int may_be_empty)
+{
+  tr_action_t *act;
+  int status;
+
+  if (dest == NULL)
+    return (-EINVAL);
+
+  if ((ci->values_num != 2)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || (ci->values[1].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("Target `replace': The `%s' option requires exactly two string "
+        "arguments.", ci->key);
+    return (-1);
+  }
+
+  act = (tr_action_t *) malloc (sizeof (*act));
+  if (act == NULL)
+  {
+    ERROR ("tr_config_add_action: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (act, 0, sizeof (*act));
+
+  act->replacement = NULL;
+  act->may_be_empty = may_be_empty;
+
+  status = regcomp (&act->re, ci->values[0].value.string, REG_EXTENDED);
+  if (status != 0)
+  {
+    char errbuf[1024] = "";
+
+    /* regerror assures null termination. */
+    regerror (status, &act->re, errbuf, sizeof (errbuf));
+    ERROR ("Target `replace': Compiling the regular expression `%s' "
+        "failed: %s.",
+        ci->values[0].value.string, errbuf);
+    sfree (act);
+    return (-EINVAL);
+  }
+
+  act->replacement = tr_strdup (ci->values[1].value.string);
+  if (act->replacement == NULL)
+  {
+    ERROR ("tr_config_add_action: tr_strdup failed.");
+    regfree (&act->re);
+    sfree (act);
+    return (-ENOMEM);
+  }
+
+  /* Insert action at end of list. */
+  if (*dest == NULL)
+    *dest = act;
+  else
+  {
+    tr_action_t *prev;
+
+    prev = *dest;
+    while (prev->next != NULL)
+      prev = prev->next;
+
+    prev->next = act;
+  }
+
+  return (0);
+} /* }}} int tr_config_add_action */
+
+static int tr_action_invoke (tr_action_t *act_head, /* {{{ */
+    char *buffer_in, size_t buffer_in_size, int may_be_empty)
+{
+  tr_action_t *act;
+  int status;
+  char buffer[DATA_MAX_NAME_LEN];
+  regmatch_t matches[8];
+
+  if (act_head == NULL)
+    return (-EINVAL);
+
+  sstrncpy (buffer, buffer_in, sizeof (buffer));
+  memset (matches, 0, sizeof (matches));
+
+  DEBUG ("target_replace plugin: tr_action_invoke: <- buffer = %s;", buffer);
+
+  for (act = act_head; act != NULL; act = act->next)
+  {
+    char temp[DATA_MAX_NAME_LEN];
+    char *subst_status;
+
+    status = regexec (&act->re, buffer,
+        STATIC_ARRAY_SIZE (matches), matches,
+        /* flags = */ 0);
+    if (status == REG_NOMATCH)
+      continue;
+    else if (status != 0)
+    {
+      char errbuf[1024] = "";
+
+      regerror (status, &act->re, errbuf, sizeof (errbuf));
+      ERROR ("Target `replace': Executing a regular expression failed: %s.",
+          errbuf);
+      continue;
+    }
+
+    subst_status = subst (temp, sizeof (temp), buffer,
+        matches[0].rm_so, matches[0].rm_eo, act->replacement);
+    if (subst_status == NULL)
+    {
+      ERROR ("Target `replace': subst (buffer = %s, start = %zu, end = %zu, "
+          "replacement = %s) failed.",
+          buffer, (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo,
+          act->replacement);
+      continue;
+    }
+    sstrncpy (buffer, temp, sizeof (buffer));
+
+    DEBUG ("target_replace plugin: tr_action_invoke: -- buffer = %s;", buffer);
+  } /* for (act = act_head; act != NULL; act = act->next) */
+
+  if ((may_be_empty == 0) && (buffer[0] == 0))
+  {
+    WARNING ("Target `replace': Replacement resulted in an empty string, "
+        "which is not allowed for this buffer (`host' or `plugin').");
+    return (0);
+  }
+
+  DEBUG ("target_replace plugin: tr_action_invoke: -> buffer = %s;", buffer);
+  sstrncpy (buffer_in, buffer, buffer_in_size);
+
+  return (0);
+} /* }}} int tr_action_invoke */
+
+static int tr_destroy (void **user_data) /* {{{ */
+{
+  tr_data_t *data;
+
+  if (user_data == NULL)
+    return (-EINVAL);
+
+  data = *user_data;
+  if (data == NULL)
+    return (0);
+
+  tr_action_destroy (data->host);
+  tr_action_destroy (data->plugin);
+  tr_action_destroy (data->plugin_instance);
+  /* tr_action_destroy (data->type); */
+  tr_action_destroy (data->type_instance);
+  sfree (data);
+
+  return (0);
+} /* }}} int tr_destroy */
+
+static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  tr_data_t *data;
+  int status;
+  int i;
+
+  data = (tr_data_t *) malloc (sizeof (*data));
+  if (data == NULL)
+  {
+    ERROR ("tr_create: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (data, 0, sizeof (*data));
+
+  data->host = NULL;
+  data->plugin = NULL;
+  data->plugin_instance = NULL;
+  /* data->type = NULL; */
+  data->type_instance = NULL;
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if ((strcasecmp ("Host", child->key) == 0)
+        || (strcasecmp ("Hostname", child->key) == 0))
+      status = tr_config_add_action (&data->host, child,
+          /* may be empty = */ 0);
+    else if (strcasecmp ("Plugin", child->key) == 0)
+      status = tr_config_add_action (&data->plugin, child,
+          /* may be empty = */ 0);
+    else if (strcasecmp ("PluginInstance", child->key) == 0)
+      status = tr_config_add_action (&data->plugin_instance, child,
+          /* may be empty = */ 1);
+#if 0
+    else if (strcasecmp ("Type", child->key) == 0)
+      status = tr_config_add_action (&data->type, child,
+          /* may be empty = */ 0);
+#endif
+    else if (strcasecmp ("TypeInstance", child->key) == 0)
+      status = tr_config_add_action (&data->type_instance, child,
+          /* may be empty = */ 1);
+    else
+    {
+      ERROR ("Target `replace': The `%s' configuration option is not understood "
+          "and will be ignored.", child->key);
+      status = 0;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Additional sanity-checking */
+  while (status == 0)
+  {
+    if ((data->host == NULL)
+        && (data->plugin == NULL)
+        && (data->plugin_instance == NULL)
+        /* && (data->type == NULL) */
+        && (data->type_instance == NULL))
+    {
+      ERROR ("Target `replace': You need to set at least one of `Host', "
+          "`Plugin', `PluginInstance' or `TypeInstance'.");
+      status = -1;
+    }
+
+    break;
+  }
+
+  if (status != 0)
+  {
+    tr_destroy ((void *) &data);
+    return (status);
+  }
+
+  *user_data = data;
+  return (0);
+} /* }}} int tr_create */
+
+static int tr_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
+    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+  tr_data_t *data;
+
+  if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
+    return (-EINVAL);
+
+  data = *user_data;
+  if (data == NULL)
+  {
+    ERROR ("Target `replace': Invoke: `data' is NULL.");
+    return (-EINVAL);
+  }
+
+#define HANDLE_FIELD(f,e) \
+  if (data->f != NULL) \
+    tr_action_invoke (data->f, vl->f, sizeof (vl->f), e)
+  HANDLE_FIELD (host, 0);
+  HANDLE_FIELD (plugin, 0);
+  HANDLE_FIELD (plugin_instance, 1);
+  /* HANDLE_FIELD (type); */
+  HANDLE_FIELD (type_instance, 1);
+
+  return (FC_TARGET_CONTINUE);
+} /* }}} int tr_invoke */
+
+void module_register (void)
+{
+       target_proc_t tproc;
+
+       memset (&tproc, 0, sizeof (tproc));
+       tproc.create  = tr_create;
+       tproc.destroy = tr_destroy;
+       tproc.invoke  = tr_invoke;
+       fc_register_target ("replace", tproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
+
diff --git a/src/target_scale.c b/src/target_scale.c
new file mode 100644 (file)
index 0000000..b29a02b
--- /dev/null
@@ -0,0 +1,515 @@
+/**
+ * collectd - src/target_scale.c
+ * Copyright (C) 2008-2009  Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "filter_chain.h"
+
+#include "utils_cache.h"
+
+struct ts_data_s
+{
+       double factor;
+       double offset;
+
+       char **data_sources;
+       size_t data_sources_num;
+};
+typedef struct ts_data_s ts_data_t;
+
+static int ts_invoke_counter (const data_set_t *ds, value_list_t *vl, /* {{{ */
+               ts_data_t *data, int dsrc_index)
+{
+       uint64_t curr_counter;
+       int status;
+       int failure;
+
+       /* Required meta data */
+       uint64_t prev_counter;
+       char key_prev_counter[128];
+       uint64_t int_counter;
+       char key_int_counter[128];
+       double int_fraction;
+       char key_int_fraction[128];
+
+       curr_counter = (uint64_t) vl->values[dsrc_index].counter;
+
+       ssnprintf (key_prev_counter, sizeof (key_prev_counter),
+                       "target_scale[%p,%i]:prev_counter",
+                       (void *) data, dsrc_index);
+       ssnprintf (key_int_counter, sizeof (key_int_counter),
+                       "target_scale[%p,%i]:int_counter",
+                       (void *) data, dsrc_index);
+       ssnprintf (key_int_fraction, sizeof (key_int_fraction),
+                       "target_scale[%p,%i]:int_fraction",
+                       (void *) data, dsrc_index);
+
+       prev_counter = curr_counter;
+       int_counter = 0;
+       int_fraction = 0.0;
+
+       /* Query the meta data */
+       failure = 0;
+
+       status = uc_meta_data_get_unsigned_int (vl, key_prev_counter,
+                       &prev_counter);
+       if (status != 0)
+               failure++;
+
+       status = uc_meta_data_get_unsigned_int (vl, key_int_counter, &int_counter);
+       if (status != 0)
+               failure++;
+
+       status = uc_meta_data_get_double (vl, key_int_fraction, &int_fraction);
+       if (status != 0)
+               failure++;
+
+       if (failure == 0)
+       {
+               uint64_t difference;
+               double rate;
+
+               /* Calcualte the rate */
+               if (prev_counter > curr_counter) /* => counter overflow */
+               {
+                       if (prev_counter <= 4294967295UL) /* 32 bit overflow */
+                               difference = (4294967295UL - prev_counter) + curr_counter;
+                       else /* 64 bit overflow */
+                               difference = (18446744073709551615ULL - prev_counter) + curr_counter;
+               }
+               else /* no overflow */
+               {
+                       difference = curr_counter - prev_counter;
+               }
+               rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval);
+
+               /* Modify the rate. */
+               if (!isnan (data->factor))
+                       rate *= data->factor;
+               if (!isnan (data->offset))
+                       rate += data->offset;
+
+               /* Calculate the internal counter. */
+               int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval));
+               difference = (uint64_t) int_fraction;
+               int_fraction -= ((double) difference);
+               int_counter  += difference;
+
+               assert (int_fraction >= 0.0);
+               assert (int_fraction <  1.0);
+
+               DEBUG ("Target `scale': ts_invoke_counter: %"PRIu64" -> %g -> %"PRIu64
+                               "(+%g)",
+                               curr_counter, rate, int_counter, int_fraction);
+       }
+       else /* (failure != 0) */
+       {
+               int_counter = 0;
+               int_fraction = 0.0;
+       }
+
+       vl->values[dsrc_index].counter = (counter_t) int_counter;
+
+       /* Update to the new counter value */
+       uc_meta_data_add_unsigned_int (vl, key_prev_counter, curr_counter);
+       uc_meta_data_add_unsigned_int (vl, key_int_counter, int_counter);
+       uc_meta_data_add_double (vl, key_int_fraction, int_fraction);
+
+
+       return (0);
+} /* }}} int ts_invoke_counter */
+
+static int ts_invoke_gauge (const data_set_t *ds, value_list_t *vl, /* {{{ */
+               ts_data_t *data, int dsrc_index)
+{
+       if (!isnan (data->factor))
+               vl->values[dsrc_index].gauge *= data->factor;
+       if (!isnan (data->offset))
+               vl->values[dsrc_index].gauge += data->offset;
+
+       return (0);
+} /* }}} int ts_invoke_gauge */
+
+static int ts_invoke_derive (const data_set_t *ds, value_list_t *vl, /* {{{ */
+               ts_data_t *data, int dsrc_index)
+{
+       int64_t curr_derive;
+       int status;
+       int failure;
+
+       /* Required meta data */
+       int64_t prev_derive;
+       char key_prev_derive[128];
+       int64_t int_derive;
+       char key_int_derive[128];
+       double int_fraction;
+       char key_int_fraction[128];
+
+       curr_derive = (int64_t) vl->values[dsrc_index].derive;
+
+       ssnprintf (key_prev_derive, sizeof (key_prev_derive),
+                       "target_scale[%p,%i]:prev_derive",
+                       (void *) data, dsrc_index);
+       ssnprintf (key_int_derive, sizeof (key_int_derive),
+                       "target_scale[%p,%i]:int_derive",
+                       (void *) data, dsrc_index);
+       ssnprintf (key_int_fraction, sizeof (key_int_fraction),
+                       "target_scale[%p,%i]:int_fraction",
+                       (void *) data, dsrc_index);
+
+       prev_derive = curr_derive;
+       int_derive = 0;
+       int_fraction = 0.0;
+
+       /* Query the meta data */
+       failure = 0;
+
+       status = uc_meta_data_get_signed_int (vl, key_prev_derive,
+                       &prev_derive);
+       if (status != 0)
+               failure++;
+
+       status = uc_meta_data_get_signed_int (vl, key_int_derive, &int_derive);
+       if (status != 0)
+               failure++;
+
+       status = uc_meta_data_get_double (vl, key_int_fraction, &int_fraction);
+       if (status != 0)
+               failure++;
+
+       if (failure == 0)
+       {
+               int64_t difference;
+               double rate;
+
+               /* Calcualte the rate */
+               difference = curr_derive - prev_derive;
+               rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval);
+
+               /* Modify the rate. */
+               if (!isnan (data->factor))
+                       rate *= data->factor;
+               if (!isnan (data->offset))
+                       rate += data->offset;
+
+               /* Calculate the internal derive. */
+               int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval));
+               if (int_fraction < 0.0) /* handle negative integer rounding correctly */
+                       difference = ((int64_t) int_fraction) - 1;
+               else
+                       difference = (int64_t) int_fraction;
+               int_fraction -= ((double) difference);
+               int_derive  += difference;
+
+               assert (int_fraction >= 0.0);
+               assert (int_fraction <  1.0);
+
+               DEBUG ("Target `scale': ts_invoke_derive: %"PRIu64" -> %g -> %"PRIu64
+                               "(+%g)",
+                               curr_derive, rate, int_derive, int_fraction);
+       }
+       else /* (failure != 0) */
+       {
+               int_derive = 0;
+               int_fraction = 0.0;
+       }
+
+       vl->values[dsrc_index].derive = (derive_t) int_derive;
+
+       /* Update to the new derive value */
+       uc_meta_data_add_signed_int (vl, key_prev_derive, curr_derive);
+       uc_meta_data_add_signed_int (vl, key_int_derive, int_derive);
+       uc_meta_data_add_double (vl, key_int_fraction, int_fraction);
+
+       return (0);
+} /* }}} int ts_invoke_derive */
+
+static int ts_invoke_absolute (const data_set_t *ds, value_list_t *vl, /* {{{ */
+               ts_data_t *data, int dsrc_index)
+{
+       uint64_t curr_absolute;
+       double rate;
+       int status;
+
+       /* Required meta data */
+       double int_fraction;
+       char key_int_fraction[128];
+
+       curr_absolute = (uint64_t) vl->values[dsrc_index].absolute;
+
+       ssnprintf (key_int_fraction, sizeof (key_int_fraction),
+                       "target_scale[%p,%i]:int_fraction",
+                       (void *) data, dsrc_index);
+
+       int_fraction = 0.0;
+
+       /* Query the meta data */
+       status = uc_meta_data_get_double (vl, key_int_fraction, &int_fraction);
+       if (status != 0)
+               int_fraction = 0.0;
+
+       rate = ((double) curr_absolute) / CDTIME_T_TO_DOUBLE (vl->interval);
+
+       /* Modify the rate. */
+       if (!isnan (data->factor))
+               rate *= data->factor;
+       if (!isnan (data->offset))
+               rate += data->offset;
+
+       /* Calculate the new absolute. */
+       int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval));
+       curr_absolute = (uint64_t) int_fraction;
+       int_fraction -= ((double) curr_absolute);
+
+       vl->values[dsrc_index].absolute = (absolute_t) curr_absolute;
+
+       /* Update to the new absolute value */
+       uc_meta_data_add_double (vl, key_int_fraction, int_fraction);
+
+       return (0);
+} /* }}} int ts_invoke_absolute */
+
+static int ts_config_set_double (double *ret, oconfig_item_t *ci) /* {{{ */
+{
+       if ((ci->values_num != 1)
+                       || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+       {
+               WARNING ("scale target: The `%s' config option needs "
+                               "exactly one numeric argument.", ci->key);
+               return (-1);
+       }
+
+       *ret = ci->values[0].value.number;
+       DEBUG ("ts_config_set_double: *ret = %g", *ret);
+
+       return (0);
+} /* }}} int ts_config_set_double */
+
+static int ts_config_add_data_source(ts_data_t *data, /* {{{ */
+               oconfig_item_t *ci)
+{
+       size_t new_data_sources_num;
+       char **temp;
+       int i;
+
+       /* Check number of arbuments. */
+       if (ci->values_num < 1)
+       {
+               ERROR ("`value' match: `%s' needs at least one argument.",
+                               ci->key);
+               return (-1);
+       }
+
+       /* Check type of arguments */
+       for (i = 0; i < ci->values_num; i++)
+       {
+               if (ci->values[i].type == OCONFIG_TYPE_STRING)
+                       continue;
+
+               ERROR ("`value' match: `%s' accepts only string arguments "
+                               "(argument %i is a %s).",
+                               ci->key, i + 1,
+                               (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
+                               ? "truth value" : "number");
+               return (-1);
+       }
+
+       /* Allocate space for the char pointers */
+       new_data_sources_num = data->data_sources_num + ((size_t) ci->values_num);
+       temp = (char **) realloc (data->data_sources,
+                       new_data_sources_num * sizeof (char *));
+       if (temp == NULL)
+       {
+               ERROR ("`value' match: realloc failed.");
+               return (-1);
+       }
+       data->data_sources = temp;
+
+       /* Copy the strings, allocating memory as needed.  */
+       for (i = 0; i < ci->values_num; i++)
+       {
+               size_t j;
+
+               /* If we get here, there better be memory for us to write to.  */
+               assert (data->data_sources_num < new_data_sources_num);
+
+               j = data->data_sources_num;
+               data->data_sources[j] = sstrdup (ci->values[i].value.string);
+               if (data->data_sources[j] == NULL)
+               {
+                       ERROR ("`value' match: sstrdup failed.");
+                       continue;
+               }
+               data->data_sources_num++;
+       }
+
+       return (0);
+} /* }}} int ts_config_add_data_source */
+
+static int ts_destroy (void **user_data) /* {{{ */
+{
+       ts_data_t *data;
+
+       if (user_data == NULL)
+               return (-EINVAL);
+
+       data = (ts_data_t *) *user_data;
+
+       if ((data != NULL) && (data->data_sources != NULL))
+       {
+               size_t i;
+               for (i = 0; i < data->data_sources_num; i++)
+                       sfree (data->data_sources[i]);
+               sfree (data->data_sources);
+       }
+
+       sfree (data);
+       *user_data = NULL;
+
+       return (0);
+} /* }}} int ts_destroy */
+
+static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+       ts_data_t *data;
+       int status;
+       int i;
+
+       data = (ts_data_t *) malloc (sizeof (*data));
+       if (data == NULL)
+       {
+               ERROR ("ts_create: malloc failed.");
+               return (-ENOMEM);
+       }
+       memset (data, 0, sizeof (*data));
+
+       data->factor = NAN;
+       data->offset = NAN;
+
+       status = 0;
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Factor", child->key) == 0)
+                               status = ts_config_set_double (&data->factor, child);
+               else if (strcasecmp ("Offset", child->key) == 0)
+                               status = ts_config_set_double (&data->offset, child);
+               else if (strcasecmp ("DataSource", child->key) == 0)
+                               status = ts_config_add_data_source(data, child);
+               else
+               {
+                       ERROR ("Target `scale': The `%s' configuration option is not understood "
+                                       "and will be ignored.", child->key);
+                       status = 0;
+               }
+
+               if (status != 0)
+                       break;
+       }
+
+       /* Additional sanity-checking */
+       while (status == 0)
+       {
+               if (isnan (data->factor) && isnan (data->offset))
+               {
+                       ERROR ("Target `scale': You need to at least set either the `Factor' "
+                                       "or `Offset' option!");
+                       status = -1;
+               }
+
+               break;
+       }
+
+       if (status != 0)
+       {
+               ts_destroy ((void *) &data);
+               return (status);
+       }
+
+       *user_data = data;
+       return (0);
+} /* }}} int ts_create */
+
+static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
+               notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+       ts_data_t *data;
+       int i;
+
+       if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
+               return (-EINVAL);
+
+       data = *user_data;
+       if (data == NULL)
+       {
+               ERROR ("Target `scale': Invoke: `data' is NULL.");
+               return (-EINVAL);
+       }
+
+       for (i = 0; i < ds->ds_num; i++)
+       {
+               /* If we've got a list of data sources, is it in the list? */
+               if (data->data_sources) {
+                       size_t j;
+                       for (j = 0; j < data->data_sources_num; j++)
+                               if (strcasecmp(ds->ds[i].name, data->data_sources[j]) == 0)
+                                       break;
+
+                       /* No match, ignore */
+                       if (j >= data->data_sources_num)
+                               continue;
+               }
+
+               if (ds->ds[i].type == DS_TYPE_COUNTER)
+                       ts_invoke_counter (ds, vl, data, i);
+               else if (ds->ds[i].type == DS_TYPE_GAUGE)
+                       ts_invoke_gauge (ds, vl, data, i);
+               else if (ds->ds[i].type == DS_TYPE_DERIVE)
+                       ts_invoke_derive (ds, vl, data, i);
+               else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+                       ts_invoke_absolute (ds, vl, data, i);
+               else
+                       ERROR ("Target `scale': Ignoring unknown data source type %i",
+                                       ds->ds[i].type);
+       }
+
+       return (FC_TARGET_CONTINUE);
+} /* }}} int ts_invoke */
+
+void module_register (void)
+{
+       target_proc_t tproc;
+
+       memset (&tproc, 0, sizeof (tproc));
+       tproc.create  = ts_create;
+       tproc.destroy = ts_destroy;
+       tproc.invoke  = ts_invoke;
+       fc_register_target ("scale", tproc);
+} /* module_register */
+
+/* vim: set sw=2 ts=2 tw=78 fdm=marker : */
+
diff --git a/src/target_set.c b/src/target_set.c
new file mode 100644 (file)
index 0000000..daeaf8b
--- /dev/null
@@ -0,0 +1,202 @@
+/**
+ * collectd - src/target_set.c
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "filter_chain.h"
+
+struct ts_data_s
+{
+  char *host;
+  char *plugin;
+  char *plugin_instance;
+  /* char *type; */
+  char *type_instance;
+};
+typedef struct ts_data_s ts_data_t;
+
+static int ts_config_add_string (char **dest, /* {{{ */
+    const oconfig_item_t *ci, int may_be_empty)
+{
+  char *tmp = NULL;
+  int status;
+
+  status = cf_util_get_string (ci, &tmp);
+  if (status != 0)
+    return (status);
+
+  if (!may_be_empty && (strlen (tmp) == 0))
+  {
+    ERROR ("Target `set': The `%s' option does not accept empty strings.",
+        ci->key);
+    sfree (tmp);
+    return (-1);
+  }
+
+  *dest = tmp;
+  return (0);
+} /* }}} int ts_config_add_string */
+
+static int ts_destroy (void **user_data) /* {{{ */
+{
+  ts_data_t *data;
+
+  if (user_data == NULL)
+    return (-EINVAL);
+
+  data = *user_data;
+  if (data == NULL)
+    return (0);
+
+  free (data->host);
+  free (data->plugin);
+  free (data->plugin_instance);
+  /* free (data->type); */
+  free (data->type_instance);
+  free (data);
+
+  return (0);
+} /* }}} int ts_destroy */
+
+static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  ts_data_t *data;
+  int status;
+  int i;
+
+  data = (ts_data_t *) malloc (sizeof (*data));
+  if (data == NULL)
+  {
+    ERROR ("ts_create: malloc failed.");
+    return (-ENOMEM);
+  }
+  memset (data, 0, sizeof (*data));
+
+  data->host = NULL;
+  data->plugin = NULL;
+  data->plugin_instance = NULL;
+  /* data->type = NULL; */
+  data->type_instance = NULL;
+
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if ((strcasecmp ("Host", child->key) == 0)
+        || (strcasecmp ("Hostname", child->key) == 0))
+      status = ts_config_add_string (&data->host, child,
+          /* may be empty = */ 0);
+    else if (strcasecmp ("Plugin", child->key) == 0)
+      status = ts_config_add_string (&data->plugin, child,
+          /* may be empty = */ 0);
+    else if (strcasecmp ("PluginInstance", child->key) == 0)
+      status = ts_config_add_string (&data->plugin_instance, child,
+          /* may be empty = */ 1);
+#if 0
+    else if (strcasecmp ("Type", child->key) == 0)
+      status = ts_config_add_string (&data->type, child,
+          /* may be empty = */ 0);
+#endif
+    else if (strcasecmp ("TypeInstance", child->key) == 0)
+      status = ts_config_add_string (&data->type_instance, child,
+          /* may be empty = */ 1);
+    else
+    {
+      ERROR ("Target `set': The `%s' configuration option is not understood "
+          "and will be ignored.", child->key);
+      status = 0;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Additional sanity-checking */
+  while (status == 0)
+  {
+    if ((data->host == NULL)
+        && (data->plugin == NULL)
+        && (data->plugin_instance == NULL)
+        /* && (data->type == NULL) */
+        && (data->type_instance == NULL))
+    {
+      ERROR ("Target `set': You need to set at least one of `Host', "
+          "`Plugin', `PluginInstance' or `TypeInstance'.");
+      status = -1;
+    }
+
+    break;
+  }
+
+  if (status != 0)
+  {
+    ts_destroy ((void *) &data);
+    return (status);
+  }
+
+  *user_data = data;
+  return (0);
+} /* }}} int ts_create */
+
+static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
+    notification_meta_t __attribute__((unused)) **meta, void **user_data)
+{
+  ts_data_t *data;
+
+  if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
+    return (-EINVAL);
+
+  data = *user_data;
+  if (data == NULL)
+  {
+    ERROR ("Target `set': Invoke: `data' is NULL.");
+    return (-EINVAL);
+  }
+
+#define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); }
+  SET_FIELD (host);
+  SET_FIELD (plugin);
+  SET_FIELD (plugin_instance);
+  /* SET_FIELD (type); */
+  SET_FIELD (type_instance);
+
+  return (FC_TARGET_CONTINUE);
+} /* }}} int ts_invoke */
+
+void module_register (void)
+{
+       target_proc_t tproc;
+
+       memset (&tproc, 0, sizeof (tproc));
+       tproc.create  = ts_create;
+       tproc.destroy = ts_destroy;
+       tproc.invoke  = ts_invoke;
+       fc_register_target ("set", tproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
+
diff --git a/src/target_v5upgrade.c b/src/target_v5upgrade.c
new file mode 100644 (file)
index 0000000..d85a181
--- /dev/null
@@ -0,0 +1,476 @@
+/**
+ * collectd - src/target_v5upgrade.c
+ * Copyright (C) 2008-2010  Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "filter_chain.h"
+
+static void v5_swap_instances (value_list_t *vl) /* {{{ */
+{
+  char tmp[DATA_MAX_NAME_LEN];
+
+  assert (sizeof (tmp) == sizeof (vl->plugin_instance));
+  assert (sizeof (tmp) == sizeof (vl->type_instance));
+
+  memcpy (tmp, vl->plugin_instance, sizeof (tmp));
+  memcpy (vl->plugin_instance, vl->type_instance, sizeof (tmp));
+  memcpy (vl->type_instance, tmp, sizeof (tmp));
+} /* }}} void v5_swap_instances */
+
+/*
+ * Df type
+ *
+ * By default, the "df" plugin of version 4.* uses the "df" type and puts the
+ * mount point in the type instance. Detect this behavior and convert the type
+ * to "df_complex". This can be selected in versions 4.9 and 4.10 by setting
+ * the "ReportReserved" option of the "df" plugin.
+ */
+static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_value;
+
+  /* Can't upgrade if both instances have been set. */
+  if ((vl->plugin_instance[0] != 0)
+      && (vl->type_instance[0] != 0))
+    return (FC_TARGET_CONTINUE);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = &new_value;
+  new_vl.values_len = 1;
+  new_vl.meta = NULL;
+
+  /* Move the mount point name to the plugin instance */
+  if (new_vl.plugin_instance[0] == 0)
+    v5_swap_instances (&new_vl);
+
+  /* Change the type to "df_complex" */
+  sstrncpy (new_vl.type, "df_complex", sizeof (new_vl.type));
+
+  /* Dispatch two new value lists instead of this one */
+  new_vl.values[0].gauge = vl->values[0].gauge;
+  sstrncpy (new_vl.type_instance, "used", sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].gauge = vl->values[1].gauge;
+  sstrncpy (new_vl.type_instance, "free", sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_df */
+
+/*
+ * Interface plugin
+ *
+ * 4.* stores the interface in the type instance and leaves the plugin
+ * instance empty. If this is the case, put the interface name into the plugin
+ * instance and clear the type instance.
+ */
+static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
+    return (FC_TARGET_CONTINUE);
+
+  v5_swap_instances (vl);
+  return (FC_TARGET_CONTINUE);
+} /* }}} int v5_interface */
+
+/*
+ * MySQL query cache
+ *
+ * 4.* uses the "mysql_qcache" type which mixes different types of
+ * information. In 5.* this has been broken up.
+ */
+static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_value;
+
+  if (vl->values_len != 5)
+    return (FC_TARGET_STOP);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = &new_value;
+  new_vl.values_len = 1;
+  new_vl.meta = NULL;
+
+  /* Change the type to "cache_result" */
+  sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
+
+  /* Dispatch new value lists instead of this one */
+  new_vl.values[0].derive = (derive_t) vl->values[0].counter;
+  sstrncpy (new_vl.type_instance, "qcache-hits",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].derive = (derive_t) vl->values[1].counter;
+  sstrncpy (new_vl.type_instance, "qcache-inserts",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].derive = (derive_t) vl->values[2].counter;
+  sstrncpy (new_vl.type_instance, "qcache-not_cached",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].derive = (derive_t) vl->values[3].counter;
+  sstrncpy (new_vl.type_instance, "qcache-prunes",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  /* The last data source is a gauge value, so we have to use a different type
+   * here. */
+  new_vl.values[0].gauge = vl->values[4].gauge;
+  sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
+  sstrncpy (new_vl.type_instance, "qcache",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_mysql_qcache */
+
+/*
+ * MySQL thread count
+ *
+ * 4.* uses the "mysql_threads" type which mixes different types of
+ * information. In 5.* this has been broken up.
+ */
+static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_value;
+
+  if (vl->values_len != 4)
+    return (FC_TARGET_STOP);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = &new_value;
+  new_vl.values_len = 1;
+  new_vl.meta = NULL;
+
+  /* Change the type to "threads" */
+  sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
+
+  /* Dispatch new value lists instead of this one */
+  new_vl.values[0].gauge = vl->values[0].gauge;
+  sstrncpy (new_vl.type_instance, "running",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].gauge = vl->values[1].gauge;
+  sstrncpy (new_vl.type_instance, "connected",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].gauge = vl->values[2].gauge;
+  sstrncpy (new_vl.type_instance, "cached",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  /* The last data source is a counter value, so we have to use a different
+   * type here. */
+  new_vl.values[0].derive = (derive_t) vl->values[3].counter;
+  sstrncpy (new_vl.type, "total_threads", sizeof (new_vl.type));
+  sstrncpy (new_vl.type_instance, "created",
+      sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_mysql_threads */
+
+/*
+ * ZFS ARC hit and miss counters
+ *
+ * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
+ * more generic "cache_result" type.
+ */
+static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_value;
+  _Bool is_hits;
+
+  if (vl->values_len != 4)
+    return (FC_TARGET_STOP);
+
+  if (strcmp ("hits", vl->type_instance) == 0)
+    is_hits = 1;
+  else if (strcmp ("misses", vl->type_instance) == 0)
+    is_hits = 0;
+  else
+    return (FC_TARGET_STOP);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = &new_value;
+  new_vl.values_len = 1;
+  new_vl.meta = NULL;
+
+  /* Change the type to "cache_result" */
+  sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
+
+  /* Dispatch new value lists instead of this one */
+  new_vl.values[0].derive = (derive_t) vl->values[0].counter;
+  ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
+      "demand_data-%s",
+      is_hits ? "hit" : "miss");
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].derive = (derive_t) vl->values[1].counter;
+  ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
+      "demand_metadata-%s",
+      is_hits ? "hit" : "miss");
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].derive = (derive_t) vl->values[2].counter;
+  ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
+      "prefetch_data-%s",
+      is_hits ? "hit" : "miss");
+  plugin_dispatch_values (&new_vl);
+
+  new_vl.values[0].derive = (derive_t) vl->values[3].counter;
+  ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
+      "prefetch_metadata-%s",
+      is_hits ? "hit" : "miss");
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_zfs_arc_counts */
+
+/*
+ * ZFS ARC L2 bytes
+ *
+ * "arc_l2_bytes" -> "io_octets-L2".
+ */
+static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_values[2];
+
+  if (vl->values_len != 2)
+    return (FC_TARGET_STOP);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = new_values;
+  new_vl.values_len = 2;
+  new_vl.meta = NULL;
+
+  /* Change the type/-instance to "io_octets-L2" */
+  sstrncpy (new_vl.type, "io_octets", sizeof (new_vl.type));
+  sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
+
+  /* Copy the actual values. */
+  new_vl.values[0].derive = (derive_t) vl->values[0].counter;
+  new_vl.values[1].derive = (derive_t) vl->values[1].counter;
+
+  /* Dispatch new value lists instead of this one */
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_zfs_arc_l2_bytes */
+
+/*
+ * ZFS ARC L2 cache size
+ *
+ * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
+ * instead.
+ */
+static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_value;
+
+  if (vl->values_len != 1)
+    return (FC_TARGET_STOP);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = &new_value;
+  new_vl.values_len = 1;
+  new_vl.meta = NULL;
+
+  new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
+
+  /* Change the type to "cache_size" */
+  sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
+
+  /* Adapt the type instance */
+  sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
+
+  /* Dispatch new value lists instead of this one */
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_zfs_arc_l2_size */
+
+/*
+ * ZFS ARC ratio
+ *
+ * "arc_ratio-L1" -> "cache_ratio-arc"
+ * "arc_ratio-L2" -> "cache_ratio-L2"
+ */
+static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_value;
+
+  if (vl->values_len != 1)
+    return (FC_TARGET_STOP);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = &new_value;
+  new_vl.values_len = 1;
+  new_vl.meta = NULL;
+
+  new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
+
+  /* Change the type to "cache_ratio" */
+  sstrncpy (new_vl.type, "cache_ratio", sizeof (new_vl.type));
+
+  /* Adapt the type instance */
+  if (strcmp ("L1", vl->type_instance) == 0)
+    sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
+
+  /* Dispatch new value lists instead of this one */
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_zfs_arc_ratio */
+
+/*
+ * ZFS ARC size
+ *
+ * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
+ * replaces with the "cache_size" type and static data has been removed.
+ */
+static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+  value_list_t new_vl;
+  value_t new_value;
+
+  if (vl->values_len != 4)
+    return (FC_TARGET_STOP);
+
+  /* Copy everything: Time, interval, host, ... */
+  memcpy (&new_vl, vl, sizeof (new_vl));
+
+  /* Reset data we can't simply copy */
+  new_vl.values = &new_value;
+  new_vl.values_len = 1;
+  new_vl.meta = NULL;
+
+  /* Change the type to "cache_size" */
+  sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
+
+  /* Dispatch new value lists instead of this one */
+  new_vl.values[0].derive = (derive_t) vl->values[0].counter;
+  sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
+  plugin_dispatch_values (&new_vl);
+
+  /* Abort processing */
+  return (FC_TARGET_STOP);
+} /* }}} int v5_zfs_arc_size */
+
+static int v5_destroy (void **user_data) /* {{{ */
+{
+  return (0);
+} /* }}} int v5_destroy */
+
+static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+  *user_data = NULL;
+  return (0);
+} /* }}} int v5_create */
+
+static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
+    notification_meta_t __attribute__((unused)) **meta,
+    void __attribute__((unused)) **user_data)
+{
+  if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
+    return (-EINVAL);
+
+  if (strcmp ("df", vl->type) == 0)
+    return (v5_df (ds, vl));
+  else if (strcmp ("interface", vl->plugin) == 0)
+    return (v5_interface (ds, vl));
+  else if (strcmp ("mysql_qcache", vl->type) == 0)
+    return (v5_mysql_qcache (ds, vl));
+  else if (strcmp ("mysql_threads", vl->type) == 0)
+    return (v5_mysql_threads (ds, vl));
+  else if (strcmp ("arc_counts", vl->type) == 0)
+    return (v5_zfs_arc_counts (ds, vl));
+  else if (strcmp ("arc_l2_bytes", vl->type) == 0)
+    return (v5_zfs_arc_l2_bytes (ds, vl));
+  else if (strcmp ("arc_l2_size", vl->type) == 0)
+    return (v5_zfs_arc_l2_size (ds, vl));
+  else if (strcmp ("arc_ratio", vl->type) == 0)
+    return (v5_zfs_arc_ratio (ds, vl));
+  else if (strcmp ("arc_size", vl->type) == 0)
+    return (v5_zfs_arc_size (ds, vl));
+
+  return (FC_TARGET_CONTINUE);
+} /* }}} int v5_invoke */
+
+void module_register (void)
+{
+       target_proc_t tproc;
+
+       memset (&tproc, 0, sizeof (tproc));
+       tproc.create  = v5_create;
+       tproc.destroy = v5_destroy;
+       tproc.invoke  = v5_invoke;
+       fc_register_target ("v5upgrade", tproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
+
diff --git a/src/tcpconns.c b/src/tcpconns.c
new file mode 100644 (file)
index 0000000..0236c9d
--- /dev/null
@@ -0,0 +1,1095 @@
+/**
+ * collectd - src/tcpconns.c
+ * Copyright (C) 2007,2008  Florian octo Forster
+ * Copyright (C) 2008       Michael Stapelberg
+ *
+ * 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>
+ *   Michael Stapelberg <michael+git at stapelberg.de>
+ **/
+
+/**
+ * Code within `HAVE_LIBKVM_NLIST' blocks is provided under the following
+ * license:
+ *
+ * $collectd: parts of tcpconns.c, 2008/08/08 03:48:30 Michael Stapelberg $
+ * $OpenBSD: inet.c,v 1.100 2007/06/19 05:28:30 ray Exp $
+ * $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $
+ *
+ * Copyright (c) 1983, 1988, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+#undef HAVE_SYSCTLBYNAME /* force HAVE_LIBKVM_NLIST path */
+#endif
+
+#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !HAVE_LIBKVM_NLIST && !KERNEL_AIX
+# error "No applicable input method."
+#endif
+
+#if KERNEL_LINUX
+# include <asm/types.h>
+/* sys/socket.h is necessary to compile when using netlink on older systems. */
+# include <sys/socket.h>
+# include <linux/netlink.h>
+#if HAVE_LINUX_INET_DIAG_H
+# include <linux/inet_diag.h>
+#endif
+# include <sys/socket.h>
+# include <arpa/inet.h>
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_SYSCTLBYNAME
+# include <sys/socketvar.h>
+# include <sys/sysctl.h>
+
+/* Some includes needed for compiling on FreeBSD */
+#include <sys/time.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
+# include <net/route.h>
+# include <netinet/in.h>
+# include <netinet/in_systm.h>
+# include <netinet/ip.h>
+# include <netinet/ip6.h>
+# include <netinet/in_pcb.h>
+# include <netinet/ip_var.h>
+# include <netinet/tcp.h>
+# include <netinet/tcpip.h>
+# include <netinet/tcp_seq.h>
+# include <netinet/tcp_var.h>
+/* #endif HAVE_SYSCTLBYNAME */
+
+/* This is for OpenBSD and NetBSD. */
+#elif HAVE_LIBKVM_NLIST
+# include <sys/queue.h>
+# include <sys/socket.h>
+# include <net/route.h>
+# include <netinet/in.h>
+# include <netinet/in_systm.h>
+# include <netinet/ip.h>
+# include <netinet/ip_var.h>
+# include <netinet/in_pcb.h>
+# include <netinet/tcp.h>
+# include <netinet/tcp_timer.h>
+# include <netinet/tcp_var.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+# if !defined(HAVE_BSD_NLIST_H) || !HAVE_BSD_NLIST_H
+#  include <nlist.h>
+# else /* HAVE_BSD_NLIST_H */
+#  include <bsd/nlist.h>
+# endif
+# include <kvm.h>
+/* #endif HAVE_LIBKVM_NLIST */
+
+#elif KERNEL_AIX
+# include <arpa/inet.h>
+# include <sys/socketvar.h>
+#endif /* KERNEL_AIX */
+
+#if KERNEL_LINUX
+#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
+struct nlreq {
+  struct nlmsghdr nlh;
+  struct inet_diag_req r;
+};
+#endif
+
+static const char *tcp_state[] =
+{
+  "", /* 0 */
+  "ESTABLISHED",
+  "SYN_SENT",
+  "SYN_RECV",
+  "FIN_WAIT1",
+  "FIN_WAIT2",
+  "TIME_WAIT",
+  "CLOSED",
+  "CLOSE_WAIT",
+  "LAST_ACK",
+  "LISTEN", /* 10 */
+  "CLOSING"
+};
+
+# define TCP_STATE_LISTEN 10
+# define TCP_STATE_MIN 1
+# define TCP_STATE_MAX 11
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_SYSCTLBYNAME
+static const char *tcp_state[] =
+{
+  "CLOSED",
+  "LISTEN",
+  "SYN_SENT",
+  "SYN_RECV",
+  "ESTABLISHED",
+  "CLOSE_WAIT",
+  "FIN_WAIT1",
+  "CLOSING",
+  "LAST_ACK",
+  "FIN_WAIT2",
+  "TIME_WAIT"
+};
+
+# define TCP_STATE_LISTEN 1
+# define TCP_STATE_MIN 0
+# define TCP_STATE_MAX 10
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif HAVE_LIBKVM_NLIST
+static const char *tcp_state[] =
+{
+  "CLOSED",
+  "LISTEN",
+  "SYN_SENT",
+  "SYN_RECV",
+  "ESTABLISHED",
+  "CLOSE_WAIT",
+  "FIN_WAIT1",
+  "CLOSING",
+  "LAST_ACK",
+  "FIN_WAIT2",
+  "TIME_WAIT"
+};
+
+static kvm_t *kvmd;
+static u_long      inpcbtable_off = 0;
+struct inpcbtable *inpcbtable_ptr = NULL;
+
+# define TCP_STATE_LISTEN 1
+# define TCP_STATE_MIN 1
+# define TCP_STATE_MAX 10
+/* #endif HAVE_LIBKVM_NLIST */
+
+#elif KERNEL_AIX
+static const char *tcp_state[] =
+{
+  "CLOSED",
+  "LISTEN",
+  "SYN_SENT",
+  "SYN_RECV",
+  "ESTABLISHED",
+  "CLOSE_WAIT",
+  "FIN_WAIT1",
+  "CLOSING",
+  "LAST_ACK",
+  "FIN_WAIT2",
+  "TIME_WAIT"
+};
+
+# define TCP_STATE_LISTEN 1
+# define TCP_STATE_MIN 0
+# define TCP_STATE_MAX 10
+
+struct netinfo_conn {
+  uint32_t unknow1[2];
+  uint16_t dstport;
+  uint16_t unknow2;
+  struct in6_addr dstaddr;
+  uint16_t srcport;
+  uint16_t unknow3;
+  struct in6_addr srcaddr;
+  uint32_t unknow4[36];
+  uint16_t tcp_state;
+  uint16_t unknow5[7];
+};
+
+struct netinfo_header {
+  unsigned int proto;
+  unsigned int size;
+};
+
+# define NETINFO_TCP 3
+extern int netinfo (int proto, void *data, int *size,  int n);
+#endif /* KERNEL_AIX */
+
+#define PORT_COLLECT_LOCAL  0x01
+#define PORT_COLLECT_REMOTE 0x02
+#define PORT_IS_LISTENING   0x04
+
+typedef struct port_entry_s
+{
+  uint16_t port;
+  uint16_t flags;
+  uint32_t count_local[TCP_STATE_MAX + 1];
+  uint32_t count_remote[TCP_STATE_MAX + 1];
+  struct port_entry_s *next;
+} port_entry_t;
+
+static const char *config_keys[] =
+{
+  "ListeningPorts",
+  "LocalPort",
+  "RemotePort",
+  "AllPortsSummary"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int port_collect_listening = 0;
+static int port_collect_total = 0;
+static port_entry_t *port_list_head = NULL;
+static uint32_t count_total[TCP_STATE_MAX + 1];
+
+#if KERNEL_LINUX
+#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
+/* This depends on linux inet_diag_req because if this structure is missing,
+ * sequence_number is useless and we get a compilation warning.
+ */
+static uint32_t sequence_number = 0;
+#endif
+
+enum
+{
+  SRC_DUNNO,
+  SRC_NETLINK,
+  SRC_PROC
+} linux_source = SRC_DUNNO;
+#endif
+
+static void conn_prepare_vl (value_list_t *vl, value_t *values)
+{
+  vl->values = values;
+  vl->values_len = 1;
+  sstrncpy (vl->host, hostname_g, sizeof (vl->host));
+  sstrncpy (vl->plugin, "tcpconns", sizeof (vl->plugin));
+  sstrncpy (vl->type, "tcp_connections", sizeof (vl->type));
+}
+
+static void conn_submit_port_entry (port_entry_t *pe)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  int i;
+
+  conn_prepare_vl (&vl, values);
+
+  if (((port_collect_listening != 0) && (pe->flags & PORT_IS_LISTENING))
+      || (pe->flags & PORT_COLLECT_LOCAL))
+  {
+    ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+       "%"PRIu16"-local", pe->port);
+
+    for (i = 1; i <= TCP_STATE_MAX; i++)
+    {
+      vl.values[0].gauge = pe->count_local[i];
+
+      sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
+
+      plugin_dispatch_values (&vl);
+    }
+  }
+
+  if (pe->flags & PORT_COLLECT_REMOTE)
+  {
+    ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+       "%"PRIu16"-remote", pe->port);
+
+    for (i = 1; i <= TCP_STATE_MAX; i++)
+    {
+      vl.values[0].gauge = pe->count_remote[i];
+
+      sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
+
+      plugin_dispatch_values (&vl);
+    }
+  }
+} /* void conn_submit */
+
+static void conn_submit_port_total (void)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  int i;
+
+  conn_prepare_vl (&vl, values);
+
+  sstrncpy (vl.plugin_instance, "all", sizeof (vl.plugin_instance));
+
+  for (i = 1; i <= TCP_STATE_MAX; i++)
+  {
+    vl.values[0].gauge = count_total[i];
+
+    sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
+
+    plugin_dispatch_values (&vl);
+  }
+}
+
+static void conn_submit_all (void)
+{
+  port_entry_t *pe;
+
+  if (port_collect_total)
+    conn_submit_port_total ();
+
+  for (pe = port_list_head; pe != NULL; pe = pe->next)
+    conn_submit_port_entry (pe);
+} /* void conn_submit_all */
+
+static port_entry_t *conn_get_port_entry (uint16_t port, int create)
+{
+  port_entry_t *ret;
+
+  ret = port_list_head;
+  while (ret != NULL)
+  {
+    if (ret->port == port)
+      break;
+    ret = ret->next;
+  }
+
+  if ((ret == NULL) && (create != 0))
+  {
+    ret = (port_entry_t *) malloc (sizeof (port_entry_t));
+    if (ret == NULL)
+      return (NULL);
+    memset (ret, '\0', sizeof (port_entry_t));
+
+    ret->port = port;
+    ret->next = port_list_head;
+    port_list_head = ret;
+  }
+
+  return (ret);
+} /* port_entry_t *conn_get_port_entry */
+
+/* Removes ports that were added automatically due to the `ListeningPorts'
+ * setting but which are no longer listening. */
+static void conn_reset_port_entry (void)
+{
+  port_entry_t *prev = NULL;
+  port_entry_t *pe = port_list_head;
+
+  memset (&count_total, '\0', sizeof(count_total));
+
+  while (pe != NULL)
+  {
+    /* If this entry was created while reading the files (ant not when handling
+     * the configuration) remove it now. */
+    if ((pe->flags & (PORT_COLLECT_LOCAL
+           | PORT_COLLECT_REMOTE
+           | PORT_IS_LISTENING)) == 0)
+    {
+      port_entry_t *next = pe->next;
+
+      DEBUG ("tcpconns plugin: Removing temporary entry "
+         "for listening port %"PRIu16, pe->port);
+
+      if (prev == NULL)
+       port_list_head = next;
+      else
+       prev->next = next;
+
+      sfree (pe);
+      pe = next;
+
+      continue;
+    }
+
+    memset (pe->count_local, '\0', sizeof (pe->count_local));
+    memset (pe->count_remote, '\0', sizeof (pe->count_remote));
+    pe->flags &= ~PORT_IS_LISTENING;
+
+    pe = pe->next;
+  }
+} /* void conn_reset_port_entry */
+
+static int conn_handle_ports (uint16_t port_local, uint16_t port_remote, uint8_t state)
+{
+  port_entry_t *pe = NULL;
+
+  if ((state > TCP_STATE_MAX)
+#if TCP_STATE_MIN > 0
+      || (state < TCP_STATE_MIN)
+#endif
+     )
+  {
+    NOTICE ("tcpconns plugin: Ignoring connection with "
+       "unknown state 0x%02"PRIx8".", state);
+    return (-1);
+  }
+
+  count_total[state]++;
+
+  /* Listening sockets */
+  if ((state == TCP_STATE_LISTEN) && (port_collect_listening != 0))
+  {
+    pe = conn_get_port_entry (port_local, 1 /* create */);
+    if (pe != NULL)
+      pe->flags |= PORT_IS_LISTENING;
+  }
+
+  DEBUG ("tcpconns plugin: Connection %"PRIu16" <-> %"PRIu16" (%s)",
+      port_local, port_remote, tcp_state[state]);
+
+  pe = conn_get_port_entry (port_local, 0 /* no create */);
+  if (pe != NULL)
+    pe->count_local[state]++;
+
+  pe = conn_get_port_entry (port_remote, 0 /* no create */);
+  if (pe != NULL)
+    pe->count_remote[state]++;
+
+  return (0);
+} /* int conn_handle_ports */
+
+#if KERNEL_LINUX
+/* Returns zero on success, less than zero on socket error and greater than
+ * zero on other errors. */
+static int conn_read_netlink (void)
+{
+#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
+  int fd;
+  struct sockaddr_nl nladdr;
+  struct nlreq req;
+  struct msghdr msg;
+  struct iovec iov;
+  struct inet_diag_msg *r;
+  char buf[8192];
+
+  /* If this fails, it's likely a permission problem. We'll fall back to
+   * reading this information from files below. */
+  fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG);
+  if (fd < 0)
+  {
+    ERROR ("tcpconns plugin: conn_read_netlink: socket(AF_NETLINK, SOCK_RAW, "
+       "NETLINK_INET_DIAG) failed: %s",
+       sstrerror (errno, buf, sizeof (buf)));
+    return (-1);
+  }
+
+  memset(&nladdr, 0, sizeof(nladdr));
+  nladdr.nl_family = AF_NETLINK;
+
+  memset(&req, 0, sizeof(req));
+  req.nlh.nlmsg_len = sizeof(req);
+  req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
+  /* NLM_F_ROOT: return the complete table instead of a single entry.
+   * NLM_F_MATCH: return all entries matching criteria (not implemented)
+   * NLM_F_REQUEST: must be set on all request messages */
+  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
+  req.nlh.nlmsg_pid = 0;
+  /* The sequence_number is used to track our messages. Since netlink is not
+   * reliable, we don't want to end up with a corrupt or incomplete old
+   * message in case the system is/was out of memory. */
+  req.nlh.nlmsg_seq = ++sequence_number;
+  req.r.idiag_family = AF_INET;
+  req.r.idiag_states = 0xfff;
+  req.r.idiag_ext = 0;
+
+  memset(&iov, 0, sizeof(iov));
+  iov.iov_base = &req;
+  iov.iov_len = sizeof(req);
+
+  memset(&msg, 0, sizeof(msg));
+  msg.msg_name = (void*)&nladdr;
+  msg.msg_namelen = sizeof(nladdr);
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+
+  if (sendmsg (fd, &msg, 0) < 0)
+  {
+    ERROR ("tcpconns plugin: conn_read_netlink: sendmsg(2) failed: %s",
+       sstrerror (errno, buf, sizeof (buf)));
+    close (fd);
+    return (-1);
+  }
+
+  iov.iov_base = buf;
+  iov.iov_len = sizeof(buf);
+
+  while (1)
+  {
+    int status;
+    struct nlmsghdr *h;
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_name = (void*)&nladdr;
+    msg.msg_namelen = sizeof(nladdr);
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+
+    status = recvmsg(fd, (void *) &msg, /* flags = */ 0);
+    if (status < 0)
+    {
+      if ((errno == EINTR) || (errno == EAGAIN))
+        continue;
+
+      ERROR ("tcpconns plugin: conn_read_netlink: recvmsg(2) failed: %s",
+         sstrerror (errno, buf, sizeof (buf)));
+      close (fd);
+      return (-1);
+    }
+    else if (status == 0)
+    {
+      close (fd);
+      DEBUG ("tcpconns plugin: conn_read_netlink: Unexpected zero-sized "
+         "reply from netlink socket.");
+      return (0);
+    }
+
+    h = (struct nlmsghdr*)buf;
+    while (NLMSG_OK(h, status))
+    {
+      if (h->nlmsg_seq != sequence_number)
+      {
+       h = NLMSG_NEXT(h, status);
+       continue;
+      }
+
+      if (h->nlmsg_type == NLMSG_DONE)
+      {
+       close (fd);
+       return (0);
+      }
+      else if (h->nlmsg_type == NLMSG_ERROR)
+      {
+       struct nlmsgerr *msg_error;
+
+       msg_error = NLMSG_DATA(h);
+       WARNING ("tcpconns plugin: conn_read_netlink: Received error %i.",
+           msg_error->error);
+
+       close (fd);
+       return (1);
+      }
+
+      r = NLMSG_DATA(h);
+
+      /* This code does not (need to) distinguish between IPv4 and IPv6. */
+      conn_handle_ports (ntohs(r->id.idiag_sport),
+         ntohs(r->id.idiag_dport),
+         r->idiag_state);
+
+      h = NLMSG_NEXT(h, status);
+    } /* while (NLMSG_OK) */
+  } /* while (1) */
+
+  /* Not reached because the while() loop above handles the exit condition. */
+  return (0);
+#else
+  return (1);
+#endif /* HAVE_STRUCT_LINUX_INET_DIAG_REQ */
+} /* int conn_read_netlink */
+
+static int conn_handle_line (char *buffer)
+{
+  char *fields[32];
+  int   fields_len;
+
+  char *endptr;
+
+  char *port_local_str;
+  char *port_remote_str;
+  uint16_t port_local;
+  uint16_t port_remote;
+
+  uint8_t state;
+
+  int buffer_len = strlen (buffer);
+
+  while ((buffer_len > 0) && (buffer[buffer_len - 1] < 32))
+    buffer[--buffer_len] = '\0';
+  if (buffer_len <= 0)
+    return (-1);
+
+  fields_len = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+  if (fields_len < 12)
+  {
+    DEBUG ("tcpconns plugin: Got %i fields, expected at least 12.", fields_len);
+    return (-1);
+  }
+
+  port_local_str  = strchr (fields[1], ':');
+  port_remote_str = strchr (fields[2], ':');
+
+  if ((port_local_str == NULL) || (port_remote_str == NULL))
+    return (-1);
+  port_local_str++;
+  port_remote_str++;
+  if ((*port_local_str == '\0') || (*port_remote_str == '\0'))
+    return (-1);
+
+  endptr = NULL;
+  port_local = (uint16_t) strtol (port_local_str, &endptr, 16);
+  if ((endptr == NULL) || (*endptr != '\0'))
+    return (-1);
+
+  endptr = NULL;
+  port_remote = (uint16_t) strtol (port_remote_str, &endptr, 16);
+  if ((endptr == NULL) || (*endptr != '\0'))
+    return (-1);
+
+  endptr = NULL;
+  state = (uint8_t) strtol (fields[3], &endptr, 16);
+  if ((endptr == NULL) || (*endptr != '\0'))
+    return (-1);
+
+  return (conn_handle_ports (port_local, port_remote, state));
+} /* int conn_handle_line */
+
+static int conn_read_file (const char *file)
+{
+  FILE *fh;
+  char buffer[1024];
+
+  fh = fopen (file, "r");
+  if (fh == NULL)
+    return (-1);
+
+  while (fgets (buffer, sizeof (buffer), fh) != NULL)
+  {
+    conn_handle_line (buffer);
+  } /* while (fgets) */
+
+  fclose (fh);
+
+  return (0);
+} /* int conn_read_file */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_SYSCTLBYNAME
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif HAVE_LIBKVM_NLIST
+#endif /* HAVE_LIBKVM_NLIST */
+
+static int conn_config (const char *key, const char *value)
+{
+  if (strcasecmp (key, "ListeningPorts") == 0)
+  {
+    if (IS_TRUE (value))
+      port_collect_listening = 1;
+    else
+      port_collect_listening = 0;
+  }
+  else if ((strcasecmp (key, "LocalPort") == 0)
+      || (strcasecmp (key, "RemotePort") == 0))
+  {
+      port_entry_t *pe;
+      int port = atoi (value);
+
+      if ((port < 1) || (port > 65535))
+      {
+       ERROR ("tcpconns plugin: Invalid port: %i", port);
+       return (1);
+      }
+
+      pe = conn_get_port_entry ((uint16_t) port, 1 /* create */);
+      if (pe == NULL)
+      {
+       ERROR ("tcpconns plugin: conn_get_port_entry failed.");
+       return (1);
+      }
+
+      if (strcasecmp (key, "LocalPort") == 0)
+       pe->flags |= PORT_COLLECT_LOCAL;
+      else
+       pe->flags |= PORT_COLLECT_REMOTE;
+  }
+  else if (strcasecmp (key, "AllPortsSummary") == 0)
+  {
+    if (IS_TRUE (value))
+      port_collect_total = 1;
+    else
+      port_collect_total = 0;
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int conn_config */
+
+#if KERNEL_LINUX
+static int conn_init (void)
+{
+  if (port_collect_total == 0 && port_list_head == NULL)
+    port_collect_listening = 1;
+
+  return (0);
+} /* int conn_init */
+
+static int conn_read (void)
+{
+  int status;
+
+  conn_reset_port_entry ();
+
+  if (linux_source == SRC_NETLINK)
+  {
+    status = conn_read_netlink ();
+  }
+  else if (linux_source == SRC_PROC)
+  {
+    int errors_num = 0;
+
+    if (conn_read_file ("/proc/net/tcp") != 0)
+      errors_num++;
+    if (conn_read_file ("/proc/net/tcp6") != 0)
+      errors_num++;
+
+    if (errors_num < 2)
+      status = 0;
+    else
+      status = ENOENT;
+  }
+  else /* if (linux_source == SRC_DUNNO) */
+  {
+    /* Try to use netlink for getting this data, it is _much_ faster on systems
+     * with a large amount of connections. */
+    status = conn_read_netlink ();
+    if (status == 0)
+    {
+      INFO ("tcpconns plugin: Reading from netlink succeeded. "
+         "Will use the netlink method from now on.");
+      linux_source = SRC_NETLINK;
+    }
+    else
+    {
+      INFO ("tcpconns plugin: Reading from netlink failed. "
+         "Will read from /proc from now on.");
+      linux_source = SRC_PROC;
+
+      /* return success here to avoid the "plugin failed" message. */
+      return (0);
+    }
+  }
+
+  if (status == 0)
+    conn_submit_all ();
+  else
+    return (status);
+
+  return (0);
+} /* int conn_read */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_SYSCTLBYNAME
+static int conn_read (void)
+{
+  int status;
+  char *buffer;
+  size_t buffer_len;;
+
+  struct xinpgen *in_orig;
+  struct xinpgen *in_ptr;
+
+  conn_reset_port_entry ();
+
+  buffer_len = 0;
+  status = sysctlbyname ("net.inet.tcp.pcblist", NULL, &buffer_len, 0, 0);
+  if (status < 0)
+  {
+    ERROR ("tcpconns plugin: sysctlbyname failed.");
+    return (-1);
+  }
+
+  buffer = (char *) malloc (buffer_len);
+  if (buffer == NULL)
+  {
+    ERROR ("tcpconns plugin: malloc failed.");
+    return (-1);
+  }
+
+  status = sysctlbyname ("net.inet.tcp.pcblist", buffer, &buffer_len, 0, 0);
+  if (status < 0)
+  {
+    ERROR ("tcpconns plugin: sysctlbyname failed.");
+    sfree (buffer);
+    return (-1);
+  }
+
+  if (buffer_len <= sizeof (struct xinpgen))
+  {
+    ERROR ("tcpconns plugin: (buffer_len <= sizeof (struct xinpgen))");
+    sfree (buffer);
+    return (-1);
+  }
+
+  in_orig = (struct xinpgen *) buffer;
+  for (in_ptr = (struct xinpgen *) (((char *) in_orig) + in_orig->xig_len);
+      in_ptr->xig_len > sizeof (struct xinpgen);
+      in_ptr = (struct xinpgen *) (((char *) in_ptr) + in_ptr->xig_len))
+  {
+    struct tcpcb *tp = &((struct xtcpcb *) in_ptr)->xt_tp;
+    struct inpcb *inp = &((struct xtcpcb *) in_ptr)->xt_inp;
+    struct xsocket *so = &((struct xtcpcb *) in_ptr)->xt_socket;
+
+    /* Ignore non-TCP sockets */
+    if (so->xso_protocol != IPPROTO_TCP)
+      continue;
+
+    /* Ignore PCBs which were freed during copyout. */
+    if (inp->inp_gencnt > in_orig->xig_gen)
+      continue;
+
+    if (((inp->inp_vflag & INP_IPV4) == 0)
+       && ((inp->inp_vflag & INP_IPV6) == 0))
+      continue;
+
+    conn_handle_ports (ntohs (inp->inp_lport), ntohs (inp->inp_fport),
+       tp->t_state);
+  } /* for (in_ptr) */
+
+  in_orig = NULL;
+  in_ptr = NULL;
+  sfree (buffer);
+
+  conn_submit_all ();
+
+  return (0);
+} /* int conn_read */
+/* #endif HAVE_SYSCTLBYNAME */
+
+#elif HAVE_LIBKVM_NLIST
+static int kread (u_long addr, void *buf, int size)
+{
+  int status;
+
+  status = kvm_read (kvmd, addr, buf, size);
+  if (status != size)
+  {
+    ERROR ("tcpconns plugin: kvm_read failed (got %i, expected %i): %s\n",
+       status, size, kvm_geterr (kvmd));
+    return (-1);
+  }
+  return (0);
+} /* int kread */
+
+static int conn_init (void)
+{
+  char buf[_POSIX2_LINE_MAX];
+  struct nlist nl[] =
+  {
+#define N_TCBTABLE 0
+    { "_tcbtable" },
+    { "" }
+  };
+  int status;
+
+  kvmd = kvm_openfiles (NULL, NULL, NULL, O_RDONLY, buf);
+  if (kvmd == NULL)
+  {
+    ERROR ("tcpconns plugin: kvm_openfiles failed: %s", buf);
+    return (-1);
+  }
+
+  status = kvm_nlist (kvmd, nl);
+  if (status < 0)
+  {
+    ERROR ("tcpconns plugin: kvm_nlist failed with status %i.", status);
+    return (-1);
+  }
+
+  if (nl[N_TCBTABLE].n_type == 0)
+  {
+    ERROR ("tcpconns plugin: Error looking up kernel's namelist: "
+       "N_TCBTABLE is invalid.");
+    return (-1);
+  }
+
+  inpcbtable_off = (u_long) nl[N_TCBTABLE].n_value;
+  inpcbtable_ptr = (struct inpcbtable *) nl[N_TCBTABLE].n_value;
+
+  return (0);
+} /* int conn_init */
+
+static int conn_read (void)
+{
+  struct inpcbtable table;
+#if !defined(__OpenBSD__) && (defined(__NetBSD_Version__) && __NetBSD_Version__ <= 699002700)
+  struct inpcb *head;
+#endif
+  struct inpcb *next;
+  struct inpcb inpcb;
+  struct tcpcb tcpcb;
+  int status;
+
+  conn_reset_port_entry ();
+
+  /* Read the pcbtable from the kernel */
+  status = kread (inpcbtable_off, &table, sizeof (table));
+  if (status != 0)
+    return (-1);
+
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
+  /* inpt_queue is a TAILQ on OpenBSD */
+  /* Get the first pcb */
+  next = (struct inpcb *)TAILQ_FIRST (&table.inpt_queue);
+  while (next)
+#else
+  /* Get the `head' pcb */
+  head = (struct inpcb *) &(inpcbtable_ptr->inpt_queue);
+  /* Get the first pcb */
+  next = (struct inpcb *)CIRCLEQ_FIRST (&table.inpt_queue);
+
+  while (next != head)
+#endif
+  {
+    /* Read the pcb pointed to by `next' into `inpcb' */
+    kread ((u_long) next, &inpcb, sizeof (inpcb));
+
+    /* Advance `next' */
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
+    /* inpt_queue is a TAILQ on OpenBSD */
+    next = (struct inpcb *)TAILQ_NEXT (&inpcb, inp_queue);
+#else
+    next = (struct inpcb *)CIRCLEQ_NEXT (&inpcb, inp_queue);
+#endif
+
+    /* Ignore sockets, that are not connected. */
+#ifdef __NetBSD__
+    if (inpcb.inp_af == AF_INET6)
+      continue; /* XXX see netbsd/src/usr.bin/netstat/inet6.c */
+#else
+    if (!(inpcb.inp_flags & INP_IPV6)
+       && (inet_lnaof(inpcb.inp_laddr) == INADDR_ANY))
+      continue;
+    if ((inpcb.inp_flags & INP_IPV6)
+       && IN6_IS_ADDR_UNSPECIFIED (&inpcb.inp_laddr6))
+      continue;
+#endif
+
+    kread ((u_long) inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb));
+    conn_handle_ports (ntohs(inpcb.inp_lport), ntohs(inpcb.inp_fport), tcpcb.t_state);
+  } /* while (next != head) */
+
+  conn_submit_all ();
+
+  return (0);
+}
+/* #endif HAVE_LIBKVM_NLIST */
+
+#elif KERNEL_AIX
+
+static int conn_read (void)
+{
+  int size;
+  int i;
+  int nconn;
+  void *data;
+  struct netinfo_header *header;
+  struct netinfo_conn *conn;
+
+  conn_reset_port_entry ();
+
+  size = netinfo(NETINFO_TCP, 0, 0, 0);
+  if (size < 0)
+  {
+    ERROR ("tcpconns plugin: netinfo failed return: %i", size);
+    return (-1);
+  }
+
+  if (size == 0)
+    return (0);
+
+  if ((size - sizeof (struct netinfo_header)) % sizeof (struct netinfo_conn))
+  {
+    ERROR ("tcpconns plugin: invalid buffer size");
+    return (-1);
+  }
+
+  data = malloc(size);
+  if (data == NULL)
+  {
+    ERROR ("tcpconns plugin: malloc failed");
+    return (-1);
+  }
+
+  if (netinfo(NETINFO_TCP, data, &size, 0) < 0)
+  {
+    ERROR ("tcpconns plugin: netinfo failed");
+    free(data);
+    return (-1);
+  }
+
+  header = (struct netinfo_header *)data;
+  nconn = header->size;
+  conn = (struct netinfo_conn *)(data + sizeof(struct netinfo_header));
+
+  for (i=0; i < nconn; conn++, i++)
+  {
+    conn_handle_ports (conn->srcport, conn->dstport, conn->tcp_state);
+  }
+
+  free(data);
+
+  conn_submit_all ();
+
+  return (0);
+}
+#endif /* KERNEL_AIX */
+
+void module_register (void)
+{
+       plugin_register_config ("tcpconns", conn_config,
+                       config_keys, config_keys_num);
+#if KERNEL_LINUX
+       plugin_register_init ("tcpconns", conn_init);
+#elif HAVE_SYSCTLBYNAME
+       /* no initialization */
+#elif HAVE_LIBKVM_NLIST
+       plugin_register_init ("tcpconns", conn_init);
+#elif KERNEL_AIX
+       /* no initialization */
+#endif
+       plugin_register_read ("tcpconns", conn_read);
+} /* void module_register */
+
+/*
+ * vim: set shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker :
+ */
diff --git a/src/teamspeak2.c b/src/teamspeak2.c
new file mode 100644 (file)
index 0000000..201e182
--- /dev/null
@@ -0,0 +1,851 @@
+/**
+ * collectd - src/teamspeak2.c
+ * Copyright (C) 2008  Stefan Hacker
+ * Copyright (C) 2008  Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Stefan Hacker <d0t at dbclan dot de>
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+/*
+ * Defines
+ */
+/* Default host and port */
+#define DEFAULT_HOST   "127.0.0.1"
+#define DEFAULT_PORT   "51234"
+
+/*
+ * Variables
+ */
+/* Server linked list structure */
+typedef struct vserver_list_s
+{
+       int port;
+       struct vserver_list_s *next;
+} vserver_list_t;
+static vserver_list_t *server_list = NULL;
+
+/* Host data */
+static char *config_host = NULL;
+static char *config_port = NULL;
+
+static FILE *global_read_fh = NULL;
+static FILE *global_write_fh = NULL;
+
+/* Config data */
+static const char *config_keys[] =
+{
+       "Host",
+       "Port",
+       "Server"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+/*
+ * Functions
+ */
+static int tss2_add_vserver (int vserver_port)
+{
+       /*
+        * Adds a new vserver to the linked list
+        */
+       vserver_list_t *entry;
+
+       /* Check port range */
+       if ((vserver_port <= 0) || (vserver_port > 65535))
+       {
+               ERROR ("teamspeak2 plugin: VServer port is invalid: %i",
+                               vserver_port);
+               return (-1);
+       }
+
+       /* Allocate memory */
+       entry = (vserver_list_t *) malloc (sizeof (vserver_list_t));
+       if (entry == NULL)
+       {
+               ERROR ("teamspeak2 plugin: malloc failed.");
+               return (-1);
+       }
+       memset (entry, 0, sizeof (vserver_list_t));
+
+       /* Save data */
+       entry->port = vserver_port;
+
+       /* Insert to list */
+       if(server_list == NULL) {
+               /* Add the server as the first element */
+               server_list = entry;
+       }
+       else {
+               vserver_list_t *prev;
+
+               /* Add the server to the end of the list */
+               prev = server_list;
+               while (prev->next != NULL)
+                       prev = prev->next;
+               prev->next = entry;
+       }
+
+       INFO ("teamspeak2 plugin: Registered new vserver: %i", vserver_port);
+
+       return (0);
+} /* int tss2_add_vserver */
+
+static void tss2_submit_gauge (const char *plugin_instance,
+               const char *type, const char *type_instance,
+               gauge_t value)
+{
+       /*
+        * Submits a gauge value to the collectd daemon
+        */
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values     = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin));
+
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance,
+                               sizeof (vl.plugin_instance));
+
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance,
+                               sizeof (vl.type_instance));
+       
+       plugin_dispatch_values (&vl);
+} /* void tss2_submit_gauge */
+
+static void tss2_submit_io (const char *plugin_instance, const char *type,
+               derive_t rx, derive_t tx)
+{
+       /*
+        * Submits the io rx/tx tuple to the collectd daemon
+        */
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       vl.values     = values;
+       vl.values_len = 2;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin));
+
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance,
+                               sizeof (vl.plugin_instance));
+
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void tss2_submit_gauge */
+
+static void tss2_close_socket (void)
+{
+       /*
+        * Closes all sockets
+        */
+       if (global_write_fh != NULL)
+       {
+               fputs ("quit\r\n", global_write_fh);
+       }
+
+       if (global_read_fh != NULL)
+       {
+               fclose (global_read_fh);
+               global_read_fh = NULL;
+       }
+
+       if (global_write_fh != NULL)
+       {
+               fclose (global_write_fh);
+               global_write_fh = NULL;
+       }
+} /* void tss2_close_socket */
+
+static int tss2_get_socket (FILE **ret_read_fh, FILE **ret_write_fh)
+{
+       /*
+        * Returns connected file objects or establishes the connection
+        * if it's not already present
+        */
+       struct addrinfo ai_hints;
+       struct addrinfo *ai_head;
+       struct addrinfo *ai_ptr;
+       int sd = -1;
+       int status;
+
+       /* Check if we already got opened connections */
+       if ((global_read_fh != NULL) && (global_write_fh != NULL))
+       {
+               /* If so, use them */
+               if (ret_read_fh != NULL)
+                       *ret_read_fh = global_read_fh;
+               if (ret_write_fh != NULL)
+                       *ret_write_fh = global_write_fh;
+               return (0);
+       }
+
+       /* Get all addrs for this hostname */
+       memset (&ai_hints, 0, sizeof (ai_hints));
+#ifdef AI_ADDRCONFIG
+       ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+       ai_hints.ai_family = AF_UNSPEC;
+       ai_hints.ai_socktype = SOCK_STREAM;
+
+       status = getaddrinfo ((config_host != NULL) ? config_host : DEFAULT_HOST,
+                       (config_port != NULL) ? config_port : DEFAULT_PORT,
+                       &ai_hints,
+                       &ai_head);
+       if (status != 0)
+       {
+               ERROR ("teamspeak2 plugin: getaddrinfo failed: %s",
+                               gai_strerror (status));
+               return (-1);
+       }
+
+       /* Try all given hosts until we can connect to one */
+       for (ai_ptr = ai_head; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+       {
+               /* Create socket */
+               sd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
+                               ai_ptr->ai_protocol);
+               if (sd < 0)
+               {
+                       char errbuf[1024];
+                       WARNING ("teamspeak2 plugin: socket failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       continue;
+               }
+
+               /* Try to connect */
+               status = connect (sd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       WARNING ("teamspeak2 plugin: connect failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (sd);
+                       continue;
+               }
+
+               /*
+                * Success, we can break. Don't need more than one connection
+                */
+               break;
+       } /* for (ai_ptr) */
+
+       freeaddrinfo (ai_head);
+
+       /* Check if we really got connected */
+       if (sd < 0)
+               return (-1);
+
+       /* Create file objects from sockets */
+       global_read_fh = fdopen (sd, "r");
+       if (global_read_fh == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("teamspeak2 plugin: fdopen failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (sd);
+               return (-1);
+       }
+
+       global_write_fh = fdopen (sd, "w");
+       if (global_write_fh == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("teamspeak2 plugin: fdopen failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               tss2_close_socket ();
+               return (-1);
+       }
+
+       { /* Check that the server correctly identifies itself. */
+               char buffer[4096];
+               char *buffer_ptr;
+
+               buffer_ptr = fgets (buffer, sizeof (buffer), global_read_fh);
+               if (buffer_ptr == NULL)
+               {
+                       WARNING ("teamspeak2 plugin: Unexpected EOF received "
+                                       "from remote host %s:%s.",
+                                       config_host ? config_host : DEFAULT_HOST,
+                                       config_port ? config_port : DEFAULT_PORT);
+               }
+               buffer[sizeof (buffer) - 1] = 0;
+
+               if (memcmp ("[TS]\r\n", buffer, 6) != 0)
+               {
+                       ERROR ("teamspeak2 plugin: Unexpected response when connecting "
+                                       "to server. Expected ``[TS]'', got ``%s''.",
+                                       buffer);
+                       tss2_close_socket ();
+                       return (-1);
+               }
+               DEBUG ("teamspeak2 plugin: Server send correct banner, connected!");
+       }
+
+       /* Copy the new filehandles to the given pointers */
+       if (ret_read_fh != NULL)
+               *ret_read_fh = global_read_fh;
+       if (ret_write_fh != NULL)
+               *ret_write_fh = global_write_fh;
+       return (0);
+} /* int tss2_get_socket */
+
+static int tss2_send_request (FILE *fh, const char *request)
+{
+       /*
+        * This function puts a request to the server socket
+        */
+       int status;
+
+       status = fputs (request, fh);
+       if (status < 0)
+       {
+               ERROR ("teamspeak2 plugin: fputs failed.");
+               tss2_close_socket ();
+               return (-1);
+       }
+       fflush (fh);
+
+       return (0);
+} /* int tss2_send_request */
+
+static int tss2_receive_line (FILE *fh, char *buffer, int buffer_size)
+{
+       /*
+        * Receive a single line from the given file object
+        */
+       char *temp;
+        
+       /*
+        * fgets is blocking but much easier then doing anything else
+        * TODO: Non-blocking Version would be safer
+        */
+       temp = fgets (buffer, buffer_size, fh);
+       if (temp == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("teamspeak2 plugin: fgets failed: %s",
+                               sstrerror (errno, errbuf, sizeof(errbuf)));
+               tss2_close_socket ();
+               return (-1);
+       }
+
+       buffer[buffer_size - 1] = 0;
+       return (0);
+} /* int tss2_receive_line */
+
+static int tss2_select_vserver (FILE *read_fh, FILE *write_fh, vserver_list_t *vserver)
+{
+       /*
+        * Tell the server to select the given vserver
+        */
+       char command[128];
+       char response[128];
+       int status;
+
+       /* Send request */
+       ssnprintf (command, sizeof (command), "sel %i\r\n", vserver->port);
+
+       status = tss2_send_request (write_fh, command);
+       if (status != 0)
+       {
+               ERROR ("teamspeak2 plugin: tss2_send_request (%s) failed.", command);
+               return (-1);
+       }
+
+       /* Get answer */
+       status = tss2_receive_line (read_fh, response, sizeof (response));
+       if (status != 0)
+       {
+               ERROR ("teamspeak2 plugin: tss2_receive_line failed.");
+               return (-1);
+       }
+       response[sizeof (response) - 1] = 0;
+
+       /* Check answer */
+       if ((strncasecmp ("OK", response, 2) == 0)
+                       && ((response[2] == 0)
+                               || (response[2] == '\n')
+                               || (response[2] == '\r')))
+               return (0);
+
+       ERROR ("teamspeak2 plugin: Command ``%s'' failed. "
+                       "Response received from server was: ``%s''.",
+                       command, response);
+       return (-1);
+} /* int tss2_select_vserver */
+
+static int tss2_vserver_gapl (FILE *read_fh, FILE *write_fh,
+               gauge_t *ret_value)
+{
+       /*
+        * Reads the vserver's average packet loss and submits it to collectd.
+        * Be sure to run the tss2_read_vserver function before calling this so
+        * the vserver is selected correctly.
+        */
+       gauge_t packet_loss = NAN;
+       int status;
+
+       status = tss2_send_request (write_fh, "gapl\r\n");
+       if (status != 0)
+       {
+               ERROR("teamspeak2 plugin: tss2_send_request (gapl) failed.");
+               return (-1);
+       }
+
+       while (42)
+       {
+               char buffer[4096];
+               char *value;
+               char *endptr = NULL;
+               
+               status = tss2_receive_line (read_fh, buffer, sizeof (buffer));
+               if (status != 0)
+               {
+                       /* Set to NULL just to make sure no one uses these FHs anymore. */
+                       read_fh = NULL;
+                       write_fh = NULL;
+                       ERROR ("teamspeak2 plugin: tss2_receive_line failed.");
+                       return (-1);
+               }
+               buffer[sizeof (buffer) - 1] = 0;
+               
+               if (strncmp ("average_packet_loss=", buffer,
+                                       strlen ("average_packet_loss=")) == 0)
+               {
+                       /* Got average packet loss, now interpret it */
+                       value = &buffer[20];
+                       /* Replace , with . */
+                       while (*value != 0)
+                       {
+                               if (*value == ',')
+                               {
+                                       *value = '.';
+                                       break;
+                               }
+                               value++;
+                       }
+                       
+                       value = &buffer[20];
+                       
+                       packet_loss = strtod (value, &endptr);
+                       if (value == endptr)
+                       {
+                               /* Failed */
+                               WARNING ("teamspeak2 plugin: Could not read average package "
+                                               "loss from string: %s", buffer);
+                               continue;
+                       }
+               }
+               else if (strncasecmp ("OK", buffer, 2) == 0)
+               {
+                       break;
+               }
+               else if (strncasecmp ("ERROR", buffer, 5) == 0)
+               {
+                       ERROR ("teamspeak2 plugin: Server returned an error: %s", buffer);
+                       return (-1);
+               }
+               else
+               {
+                       WARNING ("teamspeak2 plugin: Server returned unexpected string: %s",
+                                       buffer);
+               }
+       }
+       
+       *ret_value = packet_loss;
+       return (0);
+} /* int tss2_vserver_gapl */
+
+static int tss2_read_vserver (vserver_list_t *vserver)
+{
+       /*
+        * Poll information for the given vserver and submit it to collect.
+        * If vserver is NULL the global server information will be queried.
+        */
+       int status;
+
+       gauge_t users = NAN;
+       gauge_t channels = NAN;
+       gauge_t servers = NAN;
+       derive_t rx_octets = 0;
+       derive_t tx_octets = 0;
+       derive_t rx_packets = 0;
+       derive_t tx_packets = 0;
+       gauge_t packet_loss = NAN;
+       int valid = 0;
+
+       char plugin_instance[DATA_MAX_NAME_LEN];
+
+       FILE *read_fh;
+       FILE *write_fh;
+
+       /* Get the send/receive sockets */
+       status = tss2_get_socket (&read_fh, &write_fh);
+       if (status != 0)
+       {
+               ERROR ("teamspeak2 plugin: tss2_get_socket failed.");
+               return (-1);
+       }
+
+       if (vserver == NULL)
+       {
+               /* Request global information */
+               memset (plugin_instance, 0, sizeof (plugin_instance));
+
+               status = tss2_send_request (write_fh, "gi\r\n");
+       }
+       else
+       {
+               /* Request server information */
+               ssnprintf (plugin_instance, sizeof (plugin_instance), "vserver%i",
+                               vserver->port);
+
+               /* Select the server */
+               status = tss2_select_vserver (read_fh, write_fh, vserver);
+               if (status != 0)
+                       return (status);
+
+               status = tss2_send_request (write_fh, "si\r\n");
+       }
+
+       if (status != 0)
+       {
+               ERROR ("teamspeak2 plugin: tss2_send_request failed.");
+               return (-1);
+       }
+
+       /* Loop until break */
+       while (42)
+       {
+               char buffer[4096];
+               char *key;
+               char *value;
+               char *endptr = NULL;
+               
+               /* Read one line of the server's answer */
+               status = tss2_receive_line (read_fh, buffer, sizeof (buffer));
+               if (status != 0)
+               {
+                       /* Set to NULL just to make sure no one uses these FHs anymore. */
+                       read_fh = NULL;
+                       write_fh = NULL;
+                       ERROR ("teamspeak2 plugin: tss2_receive_line failed.");
+                       break;
+               }
+
+               if (strncasecmp ("ERROR", buffer, 5) == 0)
+               {
+                       ERROR ("teamspeak2 plugin: Server returned an error: %s",
+                                       buffer);
+                       break;
+               }
+               else if (strncasecmp ("OK", buffer, 2) == 0)
+               {
+                       break;
+               }
+
+               /* Split line into key and value */
+               key = strchr (buffer, '_');
+               if (key == NULL)
+               {
+                       DEBUG ("teamspeak2 plugin: Cannot parse line: %s", buffer);
+                       continue;
+               }
+               key++;
+
+               /* Evaluate assignment */
+               value = strchr (key, '=');
+               if (value == NULL)
+               {
+                       DEBUG ("teamspeak2 plugin: Cannot parse line: %s", buffer);
+                       continue;
+               }
+               *value = 0;
+               value++;
+
+               /* Check for known key and save the given value */
+               /* global info: users_online,
+                * server info: currentusers. */
+               if ((strcmp ("currentusers", key) == 0)
+                               || (strcmp ("users_online", key) == 0))
+               {
+                       users = strtod (value, &endptr);
+                       if (value != endptr)
+                               valid |= 0x01;
+               }
+               /* global info: channels,
+                * server info: currentchannels. */
+               else if ((strcmp ("currentchannels", key) == 0)
+                               || (strcmp ("channels", key) == 0))
+               {
+                       channels = strtod (value, &endptr);
+                       if (value != endptr)
+                               valid |= 0x40;
+               }
+               /* global only */
+               else if (strcmp ("servers", key) == 0)
+               {
+                       servers = strtod (value, &endptr);
+                       if (value != endptr)
+                               valid |= 0x80;
+               }
+               else if (strcmp ("bytesreceived", key) == 0)
+               {
+                       rx_octets = strtoll (value, &endptr, 0);
+                       if (value != endptr)
+                               valid |= 0x02;
+               }
+               else if (strcmp ("bytessend", key) == 0)
+               {
+                       tx_octets = strtoll (value, &endptr, 0);
+                       if (value != endptr)
+                               valid |= 0x04;
+               }
+               else if (strcmp ("packetsreceived", key) == 0)
+               {
+                       rx_packets = strtoll (value, &endptr, 0);
+                       if (value != endptr)
+                               valid |= 0x08;
+               }
+               else if (strcmp ("packetssend", key) == 0)
+               {
+                       tx_packets = strtoll (value, &endptr, 0);
+                       if (value != endptr)
+                               valid |= 0x10;
+               }
+               else if ((strncmp ("allow_codec_", key, strlen ("allow_codec_")) == 0)
+                               || (strncmp ("bwinlast", key, strlen ("bwinlast")) == 0)
+                               || (strncmp ("bwoutlast", key, strlen ("bwoutlast")) == 0)
+                               || (strncmp ("webpost_", key, strlen ("webpost_")) == 0)
+                               || (strcmp ("adminemail", key) == 0)
+                               || (strcmp ("clan_server", key) == 0)
+                               || (strcmp ("countrynumber", key) == 0)
+                               || (strcmp ("id", key) == 0)
+                               || (strcmp ("ispname", key) == 0)
+                               || (strcmp ("linkurl", key) == 0)
+                               || (strcmp ("maxusers", key) == 0)
+                               || (strcmp ("name", key) == 0)
+                               || (strcmp ("password", key) == 0)
+                               || (strcmp ("platform", key) == 0)
+                               || (strcmp ("server_platform", key) == 0)
+                               || (strcmp ("server_uptime", key) == 0)
+                               || (strcmp ("server_version", key) == 0)
+                               || (strcmp ("udpport", key) == 0)
+                               || (strcmp ("uptime", key) == 0)
+                               || (strcmp ("users_maximal", key) == 0)
+                               || (strcmp ("welcomemessage", key) == 0))
+                       /* ignore */;
+               else
+               {
+                       INFO ("teamspeak2 plugin: Unknown key-value-pair: "
+                                       "key = %s; value = %s;", key, value);
+               }
+       } /* while (42) */
+
+       /* Collect vserver packet loss rates only if the loop above did not exit
+        * with an error. */
+       if ((status == 0) && (vserver != NULL))
+       {
+               status = tss2_vserver_gapl (read_fh, write_fh, &packet_loss);
+               if (status == 0)
+               {
+                       valid |= 0x20;
+               }
+               else
+               {
+                       WARNING ("teamspeak2 plugin: Reading package loss "
+                                       "for vserver %i failed.", vserver->port);
+               }
+       }
+
+       if ((valid & 0x01) == 0x01)
+               tss2_submit_gauge (plugin_instance, "users", NULL, users);
+
+       if ((valid & 0x06) == 0x06)
+               tss2_submit_io (plugin_instance, "io_octets", rx_octets, tx_octets);
+
+       if ((valid & 0x18) == 0x18)
+               tss2_submit_io (plugin_instance, "io_packets", rx_packets, tx_packets);
+
+       if ((valid & 0x20) == 0x20)
+               tss2_submit_gauge (plugin_instance, "percent", "packet_loss", packet_loss);
+
+       if ((valid & 0x40) == 0x40)
+               tss2_submit_gauge (plugin_instance, "gauge", "channels", channels);
+
+       if ((valid & 0x80) == 0x80)
+               tss2_submit_gauge (plugin_instance, "gauge", "servers", servers);
+
+       if (valid == 0)
+               return (-1);
+       return (0);
+} /* int tss2_read_vserver */
+
+static int tss2_config (const char *key, const char *value)
+{
+       /*
+        * Interpret configuration values
+        */
+    if (strcasecmp ("Host", key) == 0)
+       {
+               char *temp;
+
+               temp = strdup (value);
+               if (temp == NULL)
+               {
+                       ERROR("teamspeak2 plugin: strdup failed.");
+                       return (1);
+               }
+               sfree (config_host);
+               config_host = temp;
+       }
+       else if (strcasecmp ("Port", key) == 0)
+       {
+               char *temp;
+
+               temp = strdup (value);
+               if (temp == NULL)
+               {
+                       ERROR("teamspeak2 plugin: strdup failed.");
+                       return (1);
+               }
+               sfree (config_port);
+               config_port = temp;
+       }
+       else if (strcasecmp ("Server", key) == 0)
+       {
+               /* Server variable found */
+               int status;
+               
+               status = tss2_add_vserver (atoi (value));
+               if (status != 0)
+                       return (1);
+       }
+       else
+       {
+               /* Unknown variable found */
+               return (-1);
+       }
+
+       return 0;
+} /* int tss2_config */
+
+static int tss2_read (void)
+{
+       /*
+        * Poll function which collects global and vserver information
+        * and submits it to collectd
+        */
+       vserver_list_t *vserver;
+       int success = 0;
+       int status;
+
+       /* Handle global server variables */
+       status = tss2_read_vserver (NULL);
+       if (status == 0)
+       {
+               success++;
+       }
+       else
+       {
+               WARNING ("teamspeak2 plugin: Reading global server variables failed.");
+       }
+
+       /* Handle vservers */
+       for (vserver = server_list; vserver != NULL; vserver = vserver->next)
+       {
+               status = tss2_read_vserver (vserver);
+               if (status == 0)
+               {
+                       success++;
+               }
+               else
+               {
+                       WARNING ("teamspeak2 plugin: Reading statistics "
+                                       "for vserver %i failed.", vserver->port);
+                       continue;
+               }
+       }
+       
+       if (success == 0)
+               return (-1);
+    return (0);
+} /* int tss2_read */
+
+static int tss2_shutdown(void)
+{
+       /*
+        * Shutdown handler
+        */
+       vserver_list_t *entry;
+
+       tss2_close_socket ();
+
+       entry = server_list;
+       server_list = NULL;
+       while (entry != NULL)
+       {
+               vserver_list_t *next;
+
+               next = entry->next;
+               sfree (entry);
+               entry = next;
+       }
+
+       /* Get rid of the configuration */
+       sfree (config_host);
+       sfree (config_port);
+       
+    return (0);
+} /* int tss2_shutdown */
+
+void module_register(void)
+{
+       /*
+        * Mandatory module_register function
+        */
+       plugin_register_config ("teamspeak2", tss2_config,
+                       config_keys, config_keys_num);
+       plugin_register_read ("teamspeak2", tss2_read);
+       plugin_register_shutdown ("teamspeak2", tss2_shutdown);
+} /* void module_register */
+
+/* vim: set sw=4 ts=4 : */
diff --git a/src/ted.c b/src/ted.c
new file mode 100644 (file)
index 0000000..bf519bb
--- /dev/null
+++ b/src/ted.c
@@ -0,0 +1,359 @@
+/**
+ * collectd - src/ted.c
+ * Copyright (C) 2009  Eric Reed
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Eric Reed <ericr at reedhome.net>
+ *
+ *  This is a collectd module for The Energy Detective: A low-cost whole
+ * house energy monitoring system. For more information on TED, see
+ * http://theenergydetective.com
+ *
+ * This module was not created by Energy, Inc. nor is it supported by
+ * them in any way. It was created using information from two sources:
+ * David Satterfield's TED module for Misterhouse, and Micah Dowty's TED
+ * Python Module.
+ *
+ * This has only tested with the model 1001 RDU, with
+ * firmware version 9.01U. The USB port is uses the very common FTDI
+ * USB-to-serial chip, so the RDU will show up as a serial device on
+ * Windows, Mac OS, or Linux.
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#if HAVE_TERMIOS_H && HAVE_SYS_IOCTL_H && HAVE_MATH_H
+# include <termios.h>
+# include <sys/ioctl.h>
+# include <math.h>
+#else
+# error "No applicable input method."
+#endif
+
+#define EXPECTED_PACKAGE_LENGTH 278
+#define ESCAPE       0x10
+#define PKT_BEGIN    0x04
+#define PKT_END      0x03
+
+#define DEFAULT_DEVICE "/dev/ttyUSB0"
+
+static char *conf_device = NULL;
+static int   conf_retries = 0;
+
+static int fd = -1;
+
+static const char *config_keys[] =
+{
+    "Device",
+    "Retries"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int ted_read_value(double *ret_power, double *ret_voltage)
+{
+    unsigned char receive_buffer[300];
+    unsigned char package_buffer[300];
+    char pkt_request[1] = {0xAA};
+    int package_buffer_pos;
+
+    fd_set input;
+    struct timeval timeout;
+
+    int end_flag;
+    int escape_flag;
+
+    int status;
+
+    assert (fd >= 0);
+
+    /* Initialize the input set*/
+    FD_ZERO (&input);
+    FD_SET (fd, &input);
+
+    /* Initialize timeout structure, set to 2 seconds */
+    memset (&timeout, 0, sizeof (timeout));
+    timeout.tv_sec = 2;
+    timeout.tv_usec = 0;
+
+    /* clear out anything in the buffer */
+    tcflush (fd, TCIFLUSH);
+
+    status = write (fd, pkt_request, sizeof(pkt_request));
+    if (status <= 0)
+    {
+        ERROR ("ted plugin: swrite failed.");
+        return (-1);
+    }
+
+    /* Loop until we find the end of the package */
+    end_flag = 0;
+    escape_flag = 0;
+    package_buffer_pos = 0;
+    while (end_flag == 0)
+    {
+        ssize_t receive_buffer_length;
+        ssize_t i;
+
+        /* check for timeout or input error*/
+        status = select (fd + 1, &input, NULL, NULL, &timeout);
+        if (status == 0) /* Timeout */
+        {
+            WARNING ("ted plugin: Timeout while waiting for file descriptor "
+                    "to become ready.");
+            return (-1);
+        }
+        else if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
+        {
+            /* Some signal or something. Start over.. */
+            continue;
+        }
+        else if (status < 0)
+        {
+            char errbuf[1024];
+            ERROR ("ted plugin: select failed: %s",
+                    sstrerror (errno, errbuf, sizeof (errbuf)));
+            return (-1);
+        }
+
+        receive_buffer_length = read (fd, receive_buffer, sizeof (receive_buffer));
+        if (receive_buffer_length < 0)
+        {
+            char errbuf[1024];
+            if ((errno == EAGAIN) || (errno == EINTR))
+                continue;
+            ERROR ("ted plugin: read(2) failed: %s",
+                    sstrerror (errno, errbuf, sizeof (errbuf)));
+            return (-1);
+        }
+        else if (receive_buffer_length == 0)
+        {
+            /* Should we close the FD in this case? */
+            WARNING ("ted plugin: Received EOF from file descriptor.");
+            return (-1);
+        }
+        else if (receive_buffer_length > sizeof (receive_buffer))
+        {
+            ERROR ("ted plugin: read(2) returned invalid value %zi.",
+                    receive_buffer_length);
+            return (-1);
+        }
+
+        /*
+         * packet filter loop
+         *
+         * Handle escape sequences in `receive_buffer' and put the
+         * result in `package_buffer'.
+         */
+        /* We need to see the begin sequence first. When we receive `ESCAPE
+         * PKT_BEGIN', we set `package_buffer_pos' to zero to signal that
+         * the beginning of the package has been found. */
+
+        escape_flag = 0;
+        for (i = 0; i < receive_buffer_length; i++)
+        {
+            /* Check if previous byte was the escape byte. */
+            if (escape_flag == 1)
+            {
+                escape_flag = 0;
+                /* escape escape = single escape */
+                if ((receive_buffer[i] == ESCAPE)
+                        && (package_buffer_pos >= 0))
+                {
+                    package_buffer[package_buffer_pos] = ESCAPE;
+                    package_buffer_pos++;
+                }
+                else if (receive_buffer[i] == PKT_BEGIN)
+                {
+                    package_buffer_pos = 0;
+                }
+                else if  (receive_buffer[i] == PKT_END)
+                {
+                    end_flag = 1;
+                    break;
+                }
+                else
+                {
+                    DEBUG ("ted plugin: Unknown escaped byte: %#x",
+                            (unsigned int) receive_buffer[i]);
+                }
+            }
+            else if (receive_buffer[i] == ESCAPE)
+            {
+                escape_flag = 1;
+            }
+            /* if we are in a package add byte to buffer
+             * otherwise throw away */
+            else if (package_buffer_pos >= 0)
+            {
+                package_buffer[package_buffer_pos] = receive_buffer[i];
+                package_buffer_pos++;
+            }
+        } /* for (i = 0; i < receive_buffer_length; i++) */
+    } /* while (end_flag == 0) */
+
+    /* Check for errors inside the loop. */
+    if ((end_flag == 0) || (package_buffer_pos != EXPECTED_PACKAGE_LENGTH))
+        return (-1);
+
+    /*
+     * Power is at positions 247 and 248 (LSB first) in [10kW].
+     * Voltage is at positions 251 and 252 (LSB first) in [.1V].
+     *
+     * Power is in 10 Watt steps
+     * Voltage is in volts
+     */
+    *ret_power = 10.0 * (double) ((((int) package_buffer[248]) * 256)
+            + ((int) package_buffer[247]));
+    *ret_voltage = 0.1 * (double) ((((int) package_buffer[252]) * 256)
+            + ((int) package_buffer[251]));
+
+    /* success */
+    return (0);
+} /* int ted_read_value */
+
+static int ted_open_device (void)
+{
+    const char *dev;
+    struct termios options;
+
+    if (fd >= 0)
+        return (0);
+
+    dev = DEFAULT_DEVICE;
+    if (conf_device != NULL)
+        dev = conf_device;
+
+    fd = open (dev, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
+    if (fd < 0)
+    {
+        ERROR ("ted plugin: Unable to open device %s.", dev);
+        return (-1);
+    }
+
+    /* Get the current options for the port... */
+    tcgetattr(fd, &options);
+    options.c_cflag = B19200 | CS8 | CSTOPB | CREAD | CLOCAL;
+    options.c_iflag = IGNBRK | IGNPAR;
+    options.c_oflag = 0;
+    options.c_lflag = 0;
+    options.c_cc[VTIME] = 20;
+    options.c_cc[VMIN]  = 250;
+
+    /* Set the new options for the port... */
+    tcflush(fd, TCIFLUSH);
+    tcsetattr(fd, TCSANOW, &options);
+
+    INFO ("ted plugin: Successfully opened %s.", dev);
+    return (0);
+} /* int ted_open_device */
+
+static void ted_submit (char *type, double value)
+{
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    values[0].gauge = value;
+
+    vl.values = values;
+    vl.values_len = 1;
+    sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+    sstrncpy (vl.plugin, "ted", sizeof (vl.plugin));
+    sstrncpy (vl.type, type, sizeof (vl.type));
+
+    plugin_dispatch_values (&vl);
+}
+
+static int ted_config (const char *key, const char *value)
+{
+    if (strcasecmp ("Device", key) == 0)
+    {
+        sfree (conf_device);
+        conf_device = sstrdup (value);
+    }
+    else if (strcasecmp ("Retries", key) == 0)
+    {
+        int tmp;
+
+        tmp = atoi (value);
+        if (tmp < 0)
+        {
+            WARNING ("ted plugin: Invalid retry count: %i", tmp);
+            return (1);
+        }
+        conf_retries = tmp;
+    }
+    else
+    {
+        ERROR ("ted plugin: Unknown config option: %s", key);
+        return (-1);
+    }
+
+    return (0);
+} /* int ted_config */
+
+static int ted_read (void)
+{
+    double power;
+    double voltage;
+    int status;
+    int i;
+
+    status = ted_open_device ();
+    if (status != 0)
+        return (-1);
+
+    power = NAN;
+    voltage = NAN;
+    for (i = 0; i <= conf_retries; i++)
+    {
+        status = ted_read_value (&power, &voltage);
+        if (status == 0)
+            break;
+    }
+
+    if (status != 0)
+        return (-1);
+
+    ted_submit ("power", power);
+    ted_submit ("voltage", voltage);
+
+    return (0);
+} /* int ted_read */
+
+static int ted_shutdown (void)
+{
+    if (fd >= 0)
+    {
+        close (fd);
+        fd = -1;
+    }
+
+    return (0);
+} /* int ted_shutdown */
+
+void module_register (void)
+{
+    plugin_register_config ("ted", ted_config,
+            config_keys, config_keys_num);
+    plugin_register_read ("ted", ted_read);
+    plugin_register_shutdown ("ted", ted_shutdown);
+} /* void module_register */
+
+/* vim: set sw=4 et : */
diff --git a/src/testing.h b/src/testing.h
new file mode 100644 (file)
index 0000000..5df1b83
--- /dev/null
@@ -0,0 +1,67 @@
+/**
+ * collectd - src/tests/macros.h
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+static int fail_count__ = 0;
+static int check_count__ = 0;
+
+#define DEF_TEST(func) static int test_##func ()
+
+#define RUN_TEST(func) do { \
+  int status; \
+  printf ("Testing %s ...\n", #func); \
+  status = test_ ## func (); \
+  printf ("%s.\n", (status == 0) ? "Success" : "FAILURE"); \
+  if (status != 0) { fail_count__++; } \
+} while (0)
+
+#define END_TEST exit ((fail_count__ == 0) ? 0 : 1);
+
+#define OK1(cond, text) do { \
+  _Bool result = (cond); \
+  printf ("%s %i - %s\n", result ? "ok" : "not ok", ++check_count__, text); \
+} while (0)
+#define OK(cond) OK1(cond, #cond)
+
+#define STREQ(expect, actual) do { \
+  if (strcmp (expect, actual) != 0) { \
+    printf ("not ok %i - %s incorrect: expected \"%s\", got \"%s\"\n", \
+        ++check_count__, #actual, expect, actual); \
+    return (-1); \
+  } \
+  printf ("ok %i - %s evaluates to \"%s\"\n", ++check_count__, #actual, expect); \
+} while (0)
+
+#define CHECK_NOT_NULL(expr) do { \
+  void *ptr_; \
+  ptr_ = (expr); \
+  OK1(ptr_ != NULL, #expr); \
+} while (0)
+
+#define CHECK_ZERO(expr) do { \
+  long status_; \
+  status_ = (long) (expr); \
+  OK1(status_ == 0L, #expr); \
+} while (0)
diff --git a/src/thermal.c b/src/thermal.c
new file mode 100644 (file)
index 0000000..27c92bc
--- /dev/null
@@ -0,0 +1,260 @@
+/**
+ * collectd - src/thermal.c
+ * Copyright (C) 2008  Michał Mirosław
+ *
+ * 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:
+ *   Michał Mirosław <mirq-linux at rere.qmqm.pl>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_ignorelist.h"
+
+#if !KERNEL_LINUX
+# error "This module is for Linux only."
+#endif
+
+static const char *config_keys[] = {
+       "Device",
+       "IgnoreSelected",
+       "ForceUseProcfs"
+};
+
+const char *const dirname_sysfs = "/sys/class/thermal";
+const char *const dirname_procfs = "/proc/acpi/thermal_zone";
+
+static _Bool force_procfs = 0;
+static ignorelist_t *device_list;
+
+enum dev_type {
+       TEMP = 0,
+       COOLING_DEV
+};
+
+static void thermal_submit (const char *plugin_instance, enum dev_type dt,
+               gauge_t value)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t v;
+
+       v.gauge = value;
+       vl.values = &v;
+
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "thermal", sizeof(vl.plugin));
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance,
+                               sizeof (vl.plugin_instance));
+       sstrncpy (vl.type,
+                       (dt == TEMP) ? "temperature" : "gauge",
+                       sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int thermal_sysfs_device_read (const char __attribute__((unused)) *dir,
+               const char *name, void __attribute__((unused)) *user_data)
+{
+       char filename[256];
+       char data[1024];
+       int len;
+       _Bool success = 0;
+
+       if (device_list && ignorelist_match (device_list, name))
+               return -1;
+
+       len = ssnprintf (filename, sizeof (filename),
+                       "%s/%s/temp", dirname_sysfs, name);
+       if ((len < 0) || ((size_t) len >= sizeof (filename)))
+               return -1;
+
+       len = (ssize_t) read_file_contents (filename, data, sizeof(data));
+       if (len > 1 && data[--len] == '\n') {
+               char *endptr = NULL;
+               double temp;
+
+               data[len] = 0;
+               errno = 0;
+               temp = strtod (data, &endptr) / 1000.0;
+
+               if (endptr == data + len && errno == 0) {
+                       thermal_submit(name, TEMP, temp);
+                       success = 1;
+               }
+       }
+
+       len = ssnprintf (filename, sizeof (filename),
+                       "%s/%s/cur_state", dirname_sysfs, name);
+       if ((len < 0) || ((size_t) len >= sizeof (filename)))
+               return -1;
+
+       len = (ssize_t) read_file_contents (filename, data, sizeof(data));
+       if (len > 1 && data[--len] == '\n') {
+               char *endptr = NULL;
+               double state;
+
+               data[len] = 0;
+               errno = 0;
+               state = strtod (data, &endptr);
+
+               if (endptr == data + len && errno == 0) {
+                       thermal_submit(name, COOLING_DEV, state);
+                       success = 1;
+               }
+       }
+
+       return (success ? 0 : -1);
+}
+
+static int thermal_procfs_device_read (const char __attribute__((unused)) *dir,
+               const char *name, void __attribute__((unused)) *user_data)
+{
+       const char str_temp[] = "temperature:";
+       char filename[256];
+       char data[1024];
+       int len;
+
+       if (device_list && ignorelist_match (device_list, name))
+               return -1;
+
+       /**
+        * rechot ~ # cat /proc/acpi/thermal_zone/THRM/temperature
+        * temperature:             55 C
+        */
+       
+       len = ssnprintf (filename, sizeof (filename),
+                       "%s/%s/temperature", dirname_procfs, name);
+       if ((len < 0) || ((size_t) len >= sizeof (filename)))
+               return -1;
+
+       len = (ssize_t) read_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;
+               double temp;
+               double factor, add;
+               
+               if (data[--len] == 'C') {
+                       add = 0;
+                       factor = 1.0;
+               } else if (data[len] == 'F') {
+                       add = -32;
+                       factor = 5.0/9.0;
+               } else if (data[len] == 'K') {
+                       add = -273.15;
+                       factor = 1.0;
+               } else
+                       return -1;
+
+               while (len > 0 && data[--len] == ' ')
+                       ;
+               data[len + 1] = 0;
+
+               while (len > 0 && data[--len] != ' ')
+                       ;
+               ++len;
+
+               errno = 0;
+               temp = (strtod (data + len, &endptr) + add) * factor;
+
+               if (endptr != data + len && errno == 0) {
+                       thermal_submit(name, TEMP, temp);
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
+static int thermal_config (const char *key, const char *value)
+{
+       if (device_list == NULL)
+               device_list = ignorelist_create (1);
+
+       if (strcasecmp (key, "Device") == 0)
+       {
+               if (ignorelist_add (device_list, value))
+               {
+                       ERROR ("thermal plugin: "
+                                       "Cannot add value to ignorelist.");
+                       return 1;
+               }
+       }
+       else if (strcasecmp (key, "IgnoreSelected") == 0)
+       {
+               ignorelist_set_invert (device_list, 1);
+               if (IS_TRUE (value))
+                       ignorelist_set_invert (device_list, 0);
+       }
+       else if (strcasecmp (key, "ForceUseProcfs") == 0)
+       {
+               force_procfs = 0;
+               if (IS_TRUE (value))
+                       force_procfs = 1;
+       }
+       else
+       {
+               return -1;
+       }
+
+       return 0;
+}
+
+static int thermal_sysfs_read (void)
+{
+       return walk_directory (dirname_sysfs, thermal_sysfs_device_read,
+                       /* user_data = */ NULL, /* include hidden */ 0);
+}
+
+static int thermal_procfs_read (void)
+{
+       return walk_directory (dirname_procfs, thermal_procfs_device_read,
+                       /* user_data = */ NULL, /* include hidden */ 0);
+}
+
+static int thermal_init (void)
+{
+       int ret = -1;
+
+       if (!force_procfs && access (dirname_sysfs, R_OK | X_OK) == 0) {
+               ret = plugin_register_read ("thermal", thermal_sysfs_read);
+       } else if (access (dirname_procfs, R_OK | X_OK) == 0) {
+               ret = plugin_register_read ("thermal", thermal_procfs_read);
+       }
+
+       return ret;
+}
+
+static int thermal_shutdown (void)
+{
+       ignorelist_free (device_list);
+
+       return 0;
+}
+
+void module_register (void)
+{
+       plugin_register_config ("thermal", thermal_config,
+                       config_keys, STATIC_ARRAY_SIZE(config_keys));
+       plugin_register_init ("thermal", thermal_init);
+       plugin_register_shutdown ("thermal", thermal_shutdown);
+}
+
diff --git a/src/threshold.c b/src/threshold.c
new file mode 100644 (file)
index 0000000..8815a00
--- /dev/null
@@ -0,0 +1,942 @@
+/**
+ * collectd - src/threshold.c
+ * Copyright (C) 2007-2010  Florian Forster
+ * Copyright (C) 2008-2009  Sebastian Harl
+ * Copyright (C) 2009       Andrés J. Díaz
+ *
+ * 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>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Andrés J. Díaz <ajdiaz at connectical.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_avltree.h"
+#include "utils_cache.h"
+#include "utils_threshold.h"
+
+#include <assert.h>
+#include <pthread.h>
+
+/*
+ * Threshold management
+ * ====================
+ * The following functions add, delete, search, etc. configured thresholds to
+ * the underlying AVL trees.
+ */
+
+/*
+ * int ut_threshold_add
+ *
+ * Adds a threshold configuration to the list of thresholds. The threshold_t
+ * structure is copied and may be destroyed after this call. Returns zero on
+ * success, non-zero otherwise.
+ */
+static int ut_threshold_add (const threshold_t *th)
+{ /* {{{ */
+  char name[6 * DATA_MAX_NAME_LEN];
+  char *name_copy;
+  threshold_t *th_copy;
+  threshold_t *th_ptr;
+  int status = 0;
+
+  if (format_name (name, sizeof (name), th->host,
+       th->plugin, th->plugin_instance,
+       th->type, th->type_instance) != 0)
+  {
+    ERROR ("ut_threshold_add: format_name failed.");
+    return (-1);
+  }
+
+  name_copy = strdup (name);
+  if (name_copy == NULL)
+  {
+    ERROR ("ut_threshold_add: strdup failed.");
+    return (-1);
+  }
+
+  th_copy = (threshold_t *) malloc (sizeof (threshold_t));
+  if (th_copy == NULL)
+  {
+    sfree (name_copy);
+    ERROR ("ut_threshold_add: malloc failed.");
+    return (-1);
+  }
+  memcpy (th_copy, th, sizeof (threshold_t));
+  th_ptr = NULL;
+
+  DEBUG ("ut_threshold_add: Adding entry `%s'", name);
+
+  pthread_mutex_lock (&threshold_lock);
+
+  th_ptr = threshold_get (th->host, th->plugin, th->plugin_instance,
+      th->type, th->type_instance);
+
+  while ((th_ptr != NULL) && (th_ptr->next != NULL))
+    th_ptr = th_ptr->next;
+
+  if (th_ptr == NULL) /* no such threshold yet */
+  {
+    status = c_avl_insert (threshold_tree, name_copy, th_copy);
+  }
+  else /* th_ptr points to the last threshold in the list */
+  {
+    th_ptr->next = th_copy;
+    /* name_copy isn't needed */
+    sfree (name_copy);
+  }
+
+  pthread_mutex_unlock (&threshold_lock);
+
+  if (status != 0)
+  {
+    ERROR ("ut_threshold_add: c_avl_insert (%s) failed.", name);
+    sfree (name_copy);
+    sfree (th_copy);
+  }
+
+  return (status);
+} /* }}} int ut_threshold_add */
+
+/*
+ * Configuration
+ * =============
+ * The following approximately two hundred functions are used to handle the
+ * configuration and fill the threshold list.
+ * {{{ */
+static int ut_config_type_datasource (threshold_t *th, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("threshold values: The `DataSource' option needs exactly one "
+       "string argument.");
+    return (-1);
+  }
+
+  sstrncpy (th->data_source, ci->values[0].value.string,
+      sizeof (th->data_source));
+
+  return (0);
+} /* int ut_config_type_datasource */
+
+static int ut_config_type_instance (threshold_t *th, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("threshold values: The `Instance' option needs exactly one "
+       "string argument.");
+    return (-1);
+  }
+
+  sstrncpy (th->type_instance, ci->values[0].value.string,
+      sizeof (th->type_instance));
+
+  return (0);
+} /* int ut_config_type_instance */
+
+static int ut_config_type_max (threshold_t *th, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("threshold values: The `%s' option needs exactly one "
+       "number argument.", ci->key);
+    return (-1);
+  }
+
+  if (strcasecmp (ci->key, "WarningMax") == 0)
+    th->warning_max = ci->values[0].value.number;
+  else
+    th->failure_max = ci->values[0].value.number;
+
+  return (0);
+} /* int ut_config_type_max */
+
+static int ut_config_type_min (threshold_t *th, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("threshold values: The `%s' option needs exactly one "
+       "number argument.", ci->key);
+    return (-1);
+  }
+
+  if (strcasecmp (ci->key, "WarningMin") == 0)
+    th->warning_min = ci->values[0].value.number;
+  else
+    th->failure_min = ci->values[0].value.number;
+
+  return (0);
+} /* int ut_config_type_min */
+
+static int ut_config_type_hits (threshold_t *th, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("threshold values: The `%s' option needs exactly one "
+      "number argument.", ci->key);
+    return (-1);
+  }
+
+  th->hits = ci->values[0].value.number;
+
+  return (0);
+} /* int ut_config_type_hits */
+
+static int ut_config_type_hysteresis (threshold_t *th, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("threshold values: The `%s' option needs exactly one "
+      "number argument.", ci->key);
+    return (-1);
+  }
+
+  th->hysteresis = ci->values[0].value.number;
+
+  return (0);
+} /* int ut_config_type_hysteresis */
+
+static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci)
+{
+  int i;
+  threshold_t th;
+  int status = 0;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("threshold values: The `Type' block needs exactly one string "
+       "argument.");
+    return (-1);
+  }
+
+  if (ci->children_num < 1)
+  {
+    WARNING ("threshold values: The `Type' block needs at least one option.");
+    return (-1);
+  }
+
+  memcpy (&th, th_orig, sizeof (th));
+  sstrncpy (th.type, ci->values[0].value.string, sizeof (th.type));
+
+  th.warning_min = NAN;
+  th.warning_max = NAN;
+  th.failure_min = NAN;
+  th.failure_max = NAN;
+  th.hits = 0;
+  th.hysteresis = 0;
+  th.flags = UT_FLAG_INTERESTING; /* interesting by default */
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Instance", option->key) == 0)
+      status = ut_config_type_instance (&th, option);
+    else if (strcasecmp ("DataSource", option->key) == 0)
+      status = ut_config_type_datasource (&th, option);
+    else if ((strcasecmp ("WarningMax", option->key) == 0)
+       || (strcasecmp ("FailureMax", option->key) == 0))
+      status = ut_config_type_max (&th, option);
+    else if ((strcasecmp ("WarningMin", option->key) == 0)
+       || (strcasecmp ("FailureMin", option->key) == 0))
+      status = ut_config_type_min (&th, option);
+    else if (strcasecmp ("Interesting", option->key) == 0)
+      status = cf_util_get_flag (option, &th.flags, UT_FLAG_INTERESTING);
+    else if (strcasecmp ("Invert", option->key) == 0)
+      status = cf_util_get_flag (option, &th.flags, UT_FLAG_INVERT);
+    else if (strcasecmp ("Persist", option->key) == 0)
+      status = cf_util_get_flag (option, &th.flags, UT_FLAG_PERSIST);
+    else if (strcasecmp ("PersistOK", option->key) == 0)
+      status = cf_util_get_flag (option, &th.flags, UT_FLAG_PERSIST_OK);
+    else if (strcasecmp ("Percentage", option->key) == 0)
+      status = cf_util_get_flag (option, &th.flags, UT_FLAG_PERCENTAGE);
+    else if (strcasecmp ("Hits", option->key) == 0)
+      status = ut_config_type_hits (&th, option);
+    else if (strcasecmp ("Hysteresis", option->key) == 0)
+      status = ut_config_type_hysteresis (&th, option);
+    else
+    {
+      WARNING ("threshold values: Option `%s' not allowed inside a `Type' "
+         "block.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if (status == 0)
+  {
+    status = ut_threshold_add (&th);
+  }
+
+  return (status);
+} /* int ut_config_type */
+
+static int ut_config_plugin_instance (threshold_t *th, oconfig_item_t *ci)
+{
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("threshold values: The `Instance' option needs exactly one "
+       "string argument.");
+    return (-1);
+  }
+
+  sstrncpy (th->plugin_instance, ci->values[0].value.string,
+      sizeof (th->plugin_instance));
+
+  return (0);
+} /* int ut_config_plugin_instance */
+
+static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci)
+{
+  int i;
+  threshold_t th;
+  int status = 0;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("threshold values: The `Plugin' block needs exactly one string "
+       "argument.");
+    return (-1);
+  }
+
+  if (ci->children_num < 1)
+  {
+    WARNING ("threshold values: The `Plugin' block needs at least one nested "
+       "block.");
+    return (-1);
+  }
+
+  memcpy (&th, th_orig, sizeof (th));
+  sstrncpy (th.plugin, ci->values[0].value.string, sizeof (th.plugin));
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Type", option->key) == 0)
+      status = ut_config_type (&th, option);
+    else if (strcasecmp ("Instance", option->key) == 0)
+      status = ut_config_plugin_instance (&th, option);
+    else
+    {
+      WARNING ("threshold values: Option `%s' not allowed inside a `Plugin' "
+         "block.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  return (status);
+} /* int ut_config_plugin */
+
+static int ut_config_host (const threshold_t *th_orig, oconfig_item_t *ci)
+{
+  int i;
+  threshold_t th;
+  int status = 0;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("threshold values: The `Host' block needs exactly one string "
+       "argument.");
+    return (-1);
+  }
+
+  if (ci->children_num < 1)
+  {
+    WARNING ("threshold values: The `Host' block needs at least one nested "
+       "block.");
+    return (-1);
+  }
+
+  memcpy (&th, th_orig, sizeof (th));
+  sstrncpy (th.host, ci->values[0].value.string, sizeof (th.host));
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Type", option->key) == 0)
+      status = ut_config_type (&th, option);
+    else if (strcasecmp ("Plugin", option->key) == 0)
+      status = ut_config_plugin (&th, option);
+    else
+    {
+      WARNING ("threshold values: Option `%s' not allowed inside a `Host' "
+         "block.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  return (status);
+} /* int ut_config_host */
+/*
+ * End of the functions used to configure threshold values.
+ */
+/* }}} */
+
+/*
+ * int ut_report_state
+ *
+ * Checks if the `state' differs from the old state and creates a notification
+ * if appropriate.
+ * Does not fail.
+ */
+static int ut_report_state (const data_set_t *ds,
+    const value_list_t *vl,
+    const threshold_t *th,
+    const gauge_t *values,
+    int ds_index,
+    int state)
+{ /* {{{ */
+  int state_old;
+  notification_t n;
+
+  char *buf;
+  size_t bufsize;
+
+  int status;
+
+  /* Check if hits matched */
+  if ( (th->hits != 0) )
+  {
+    int hits = uc_get_hits(ds,vl);
+    /* STATE_OKAY resets hits unless PERSIST_OK flag is set. Hits resets if
+     * threshold is hit. */
+    if ( ( (state == STATE_OKAY) && ((th->flags & UT_FLAG_PERSIST_OK) == 0) ) || (hits > th->hits) )
+    {
+        DEBUG("ut_report_state: reset uc_get_hits = 0");
+        uc_set_hits(ds,vl,0); /* reset hit counter and notify */
+    } else {
+      DEBUG("ut_report_state: th->hits = %d, uc_get_hits = %d",th->hits,uc_get_hits(ds,vl));
+      (void) uc_inc_hits(ds,vl,1); /* increase hit counter */
+      return (0);
+    }
+  } /* end check hits */
+
+  state_old = uc_get_state (ds, vl);
+
+  /* If the state didn't change, report if `persistent' is specified. If the
+   * state is `okay', then only report if `persist_ok` flag is set. */
+  if (state == state_old)
+  {
+    if ((th->flags & UT_FLAG_PERSIST) == 0)
+      return (0);
+    else if ( (state == STATE_OKAY) && ((th->flags & UT_FLAG_PERSIST_OK) == 0) )
+      return (0);
+  }
+
+  if (state != state_old)
+    uc_set_state (ds, vl, state);
+
+  NOTIFICATION_INIT_VL (&n, vl);
+
+  buf = n.message;
+  bufsize = sizeof (n.message);
+
+  if (state == STATE_OKAY)
+    n.severity = NOTIF_OKAY;
+  else if (state == STATE_WARNING)
+    n.severity = NOTIF_WARNING;
+  else
+    n.severity = NOTIF_FAILURE;
+
+  n.time = vl->time;
+
+  status = ssnprintf (buf, bufsize, "Host %s, plugin %s",
+      vl->host, vl->plugin);
+  buf += status;
+  bufsize -= status;
+
+  if (vl->plugin_instance[0] != '\0')
+  {
+    status = ssnprintf (buf, bufsize, " (instance %s)",
+       vl->plugin_instance);
+    buf += status;
+    bufsize -= status;
+  }
+
+  status = ssnprintf (buf, bufsize, " type %s", vl->type);
+  buf += status;
+  bufsize -= status;
+
+  if (vl->type_instance[0] != '\0')
+  {
+    status = ssnprintf (buf, bufsize, " (instance %s)",
+       vl->type_instance);
+    buf += status;
+    bufsize -= status;
+  }
+
+  plugin_notification_meta_add_string (&n, "DataSource",
+      ds->ds[ds_index].name);
+  plugin_notification_meta_add_double (&n, "CurrentValue", values[ds_index]);
+  plugin_notification_meta_add_double (&n, "WarningMin", th->warning_min);
+  plugin_notification_meta_add_double (&n, "WarningMax", th->warning_max);
+  plugin_notification_meta_add_double (&n, "FailureMin", th->failure_min);
+  plugin_notification_meta_add_double (&n, "FailureMax", th->failure_max);
+
+  /* Send an okay notification */
+  if (state == STATE_OKAY)
+  {
+    if (state_old == STATE_MISSING)
+      status = ssnprintf (buf, bufsize,
+          ": Value is no longer missing.");
+    else
+      status = ssnprintf (buf, bufsize,
+          ": All data sources are within range again. "
+          "Current value of \"%s\" is %f.",
+          ds->ds[ds_index].name, values[ds_index]);
+    buf += status;
+    bufsize -= status;
+  }
+  else
+  {
+    double min;
+    double max;
+
+    min = (state == STATE_ERROR) ? th->failure_min : th->warning_min;
+    max = (state == STATE_ERROR) ? th->failure_max : th->warning_max;
+
+    if (th->flags & UT_FLAG_INVERT)
+    {
+      if (!isnan (min) && !isnan (max))
+      {
+        status = 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
+      {
+       status = 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;
+      gauge_t sum;
+      int i;
+
+      sum = 0.0;
+      for (i = 0; i < vl->values_len; i++)
+      {
+        if (isnan (values[i]))
+          continue;
+
+        sum += values[i];
+      }
+
+      if (sum == 0.0)
+        value = NAN;
+      else
+        value = 100.0 * values[ds_index] / sum;
+
+      status = 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 */
+    {
+      status = 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);
+    }
+    buf += status;
+    bufsize -= status;
+  }
+
+  plugin_dispatch_notification (&n);
+
+  plugin_notification_meta_free (n.meta);
+  return (0);
+} /* }}} int ut_report_state */
+
+/*
+ * int ut_check_one_data_source
+ *
+ * Checks one data source against the given threshold configuration. If the
+ * `DataSource' option is set in the threshold, and the name does NOT match,
+ * `okay' is returned. If the threshold does match, its failure and warning
+ * min and max values are checked and `failure' or `warning' is returned if
+ * appropriate.
+ * Does not fail.
+ */
+static int ut_check_one_data_source (const data_set_t *ds,
+    const value_list_t __attribute__((unused)) *vl,
+    const threshold_t *th,
+    const gauge_t *values,
+    int ds_index)
+{ /* {{{ */
+  const char *ds_name;
+  int is_warning = 0;
+  int is_failure = 0;
+  int prev_state = STATE_OKAY;
+
+  /* check if this threshold applies to this data source */
+  if (ds != NULL)
+  {
+    ds_name = ds->ds[ds_index].name;
+    if ((th->data_source[0] != 0)
+       && (strcmp (ds_name, th->data_source) != 0))
+      return (STATE_OKAY);
+  }
+
+  if ((th->flags & UT_FLAG_INVERT) != 0)
+  {
+    is_warning--;
+    is_failure--;
+  }
+
+  /* XXX: This is an experimental code, not optimized, not fast, not reliable,
+   * and probably, do not work as you expect. Enjoy! :D */
+  if (th->hysteresis > 0)
+  {
+    prev_state = uc_get_state(ds,vl);
+    /* The purpose of hysteresis is elliminating flapping state when the value
+     * oscilates around the thresholds. In other words, what is important is
+     * the previous state; if the new value would trigger a transition, make
+     * sure that we artificially widen the range which is considered to apply
+     * for the previous state, and only trigger the notification if the value
+     * is outside of this expanded range.
+     *
+     * There is no hysteresis for the OKAY state.
+     * */
+    gauge_t hysteresis_for_warning = 0, hysteresis_for_failure = 0;
+    switch (prev_state)
+    {
+      case STATE_ERROR:
+        hysteresis_for_failure = th->hysteresis;
+        break;
+      case STATE_WARNING:
+        hysteresis_for_warning = th->hysteresis;
+        break;
+      case STATE_OKAY:
+        /* do nothing -- the hysteresis only applies to the non-normal states */
+        break;
+    }
+
+    if ((!isnan (th->failure_min) && (th->failure_min + hysteresis_for_failure > values[ds_index]))
+       || (!isnan (th->failure_max) && (th->failure_max - hysteresis_for_failure < values[ds_index])))
+      is_failure++;
+
+    if ((!isnan (th->warning_min) && (th->warning_min + hysteresis_for_warning > values[ds_index]))
+       || (!isnan (th->warning_max) && (th->warning_max - hysteresis_for_warning < values[ds_index])))
+      is_warning++;
+
+  }
+  else { /* no hysteresis */
+    if ((!isnan (th->failure_min) && (th->failure_min > values[ds_index]))
+       || (!isnan (th->failure_max) && (th->failure_max < values[ds_index])))
+      is_failure++;
+
+    if ((!isnan (th->warning_min) && (th->warning_min > values[ds_index]))
+       || (!isnan (th->warning_max) && (th->warning_max < values[ds_index])))
+      is_warning++;
+  }
+
+  if (is_failure != 0)
+    return (STATE_ERROR);
+
+  if (is_warning != 0)
+    return (STATE_WARNING);
+
+  return (STATE_OKAY);
+} /* }}} int ut_check_one_data_source */
+
+/*
+ * int ut_check_one_threshold
+ *
+ * Checks all data sources of a value list against the given threshold, using
+ * the ut_check_one_data_source function above. Returns the worst status,
+ * which is `okay' if nothing has failed.
+ * Returns less than zero if the data set doesn't have any data sources.
+ */
+static int ut_check_one_threshold (const data_set_t *ds,
+    const value_list_t *vl,
+    const threshold_t *th,
+    const gauge_t *values,
+    int *ret_ds_index)
+{ /* {{{ */
+  int ret = -1;
+  int ds_index = -1;
+  int i;
+  gauge_t values_copy[ds->ds_num];
+
+  memcpy (values_copy, values, sizeof (values_copy));
+
+  if ((th->flags & UT_FLAG_PERCENTAGE) != 0)
+  {
+    int num = 0;
+    gauge_t sum=0.0;
+
+    if (ds->ds_num == 1)
+    {
+      WARNING ("ut_check_one_threshold: The %s type has only one data "
+          "source, but you have configured to check this as a percentage. "
+          "That doesn't make much sense, because the percentage will always "
+          "be 100%%!", ds->type);
+    }
+
+    /* Prepare `sum' and `num'. */
+    for (i = 0; i < ds->ds_num; i++)
+      if (!isnan (values[i]))
+      {
+        num++;
+       sum += values[i];
+      }
+
+    if ((num == 0) /* All data sources are undefined. */
+        || (sum == 0.0)) /* Sum is zero, cannot calculate percentage. */
+    {
+      for (i = 0; i < ds->ds_num; i++)
+        values_copy[i] = NAN;
+    }
+    else /* We can actually calculate the percentage. */
+    {
+      for (i = 0; i < ds->ds_num; i++)
+        values_copy[i] = 100.0 * values[i] / sum;
+    }
+  } /* if (UT_FLAG_PERCENTAGE) */
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    int status;
+
+    status = ut_check_one_data_source (ds, vl, th, values_copy, i);
+    if (ret < status)
+    {
+      ret = status;
+      ds_index = i;
+    }
+  } /* for (ds->ds_num) */
+
+  if (ret_ds_index != NULL)
+    *ret_ds_index = ds_index;
+
+  return (ret);
+} /* }}} int ut_check_one_threshold */
+
+/*
+ * int ut_check_threshold
+ *
+ * Gets a list of matching thresholds and searches for the worst status by one
+ * of the thresholds. Then reports that status using the ut_report_state
+ * function above.
+ * Returns zero on success and if no threshold has been configured. Returns
+ * less than zero on failure.
+ */
+static int ut_check_threshold (const data_set_t *ds, const value_list_t *vl,
+    __attribute__((unused)) user_data_t *ud)
+{ /* {{{ */
+  threshold_t *th;
+  gauge_t *values;
+  int status;
+
+  int worst_state = -1;
+  threshold_t *worst_th = NULL;
+  int worst_ds_index = -1;
+
+  if (threshold_tree == NULL)
+    return (0);
+
+  /* Is this lock really necessary? So far, thresholds are only inserted at
+   * startup. -octo */
+  pthread_mutex_lock (&threshold_lock);
+  th = threshold_search (vl);
+  pthread_mutex_unlock (&threshold_lock);
+  if (th == NULL)
+    return (0);
+
+  DEBUG ("ut_check_threshold: Found matching threshold(s)");
+
+  values = uc_get_rate (ds, vl);
+  if (values == NULL)
+    return (0);
+
+  while (th != NULL)
+  {
+    int ds_index = -1;
+
+    status = ut_check_one_threshold (ds, vl, th, values, &ds_index);
+    if (status < 0)
+    {
+      ERROR ("ut_check_threshold: ut_check_one_threshold failed.");
+      sfree (values);
+      return (-1);
+    }
+
+    if (worst_state < status)
+    {
+      worst_state = status;
+      worst_th = th;
+      worst_ds_index = ds_index;
+    }
+
+    th = th->next;
+  } /* while (th) */
+
+  status = ut_report_state (ds, vl, worst_th, values,
+      worst_ds_index, worst_state);
+  if (status != 0)
+  {
+    ERROR ("ut_check_threshold: ut_report_state failed.");
+    sfree (values);
+    return (-1);
+  }
+
+  sfree (values);
+
+  return (0);
+} /* }}} int ut_check_threshold */
+
+/*
+ * int ut_missing
+ *
+ * This function is called whenever a value goes "missing".
+ */
+static int ut_missing (const value_list_t *vl,
+    __attribute__((unused)) user_data_t *ud)
+{ /* {{{ */
+  threshold_t *th;
+  cdtime_t missing_time;
+  char identifier[6 * DATA_MAX_NAME_LEN];
+  notification_t n;
+  cdtime_t now;
+
+  if (threshold_tree == NULL)
+    return (0);
+
+  th = threshold_search (vl);
+  /* dispatch notifications for "interesting" values only */
+  if ((th == NULL) || ((th->flags & UT_FLAG_INTERESTING) == 0))
+    return (0);
+
+  now = cdtime ();
+  missing_time = now - vl->time;
+  FORMAT_VL (identifier, sizeof (identifier), vl);
+
+  NOTIFICATION_INIT_VL (&n, vl);
+  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);
+
+  return (0);
+} /* }}} int ut_missing */
+
+int ut_config (oconfig_item_t *ci)
+{ /* {{{ */
+  int i;
+  int status = 0;
+
+  threshold_t th;
+
+  if (threshold_tree == NULL)
+  {
+    threshold_tree = c_avl_create ((void *) strcmp);
+    if (threshold_tree == NULL)
+    {
+      ERROR ("ut_config: c_avl_create failed.");
+      return (-1);
+    }
+  }
+
+  memset (&th, '\0', sizeof (th));
+  th.warning_min = NAN;
+  th.warning_max = NAN;
+  th.failure_min = NAN;
+  th.failure_max = NAN;
+
+  th.hits = 0;
+  th.hysteresis = 0;
+  th.flags = UT_FLAG_INTERESTING; /* interesting by default */
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *option = ci->children + i;
+    status = 0;
+
+    if (strcasecmp ("Type", option->key) == 0)
+      status = ut_config_type (&th, option);
+    else if (strcasecmp ("Plugin", option->key) == 0)
+      status = ut_config_plugin (&th, option);
+    else if (strcasecmp ("Host", option->key) == 0)
+      status = ut_config_host (&th, option);
+    else
+    {
+      WARNING ("threshold values: Option `%s' not allowed here.", option->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  if (c_avl_size (threshold_tree) > 0) {
+    plugin_register_missing ("threshold", ut_missing,
+        /* user data = */ NULL);
+    plugin_register_write ("threshold", ut_check_threshold,
+        /* user data = */ NULL);
+  }
+
+  return (status);
+} /* }}} int um_config */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("threshold", ut_config);
+}
+
+/* vim: set sw=2 ts=8 sts=2 tw=78 et fdm=marker : */
diff --git a/src/tokyotyrant.c b/src/tokyotyrant.c
new file mode 100644 (file)
index 0000000..7fa621b
--- /dev/null
@@ -0,0 +1,179 @@
+/**
+ * collectd - src/tokyotyrant.c
+ * Copyright (C) 2009 Paul Sadauskas
+ *
+ * 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:
+ *   Paul Sadauskas <psadauskas@gmail.com>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_cache.h"
+
+#include <tcrdb.h>
+
+#define DEFAULT_HOST "127.0.0.1"
+#define DEFAULT_PORT 1978
+
+static const char *config_keys[] =
+{
+       "Host",
+       "Port"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char *config_host = NULL;
+static char *config_port = NULL;
+
+static TCRDB *rdb = NULL;
+
+static int tt_config (const char *key, const char *value)
+{
+       if (strcasecmp ("Host", key) == 0)
+       {
+               char *temp;
+
+               temp = strdup (value);
+               if (temp == NULL)
+               {
+                       ERROR("tokyotyrant plugin: Host strdup failed.");
+                       return (1);
+               }
+               sfree (config_host);
+               config_host = temp;
+       }
+       else if (strcasecmp ("Port", key) == 0)
+       {
+               char *temp;
+
+               temp = strdup (value);
+               if (temp == NULL)
+               {
+                       ERROR("tokyotyrant plugin: Port strdup failed.");
+                       return (1);
+               }
+               sfree (config_port);
+               config_port = temp;
+       }
+       else
+       {
+               ERROR ("tokyotyrant plugin: error: unrecognized configuration key %s", key);
+               return (-1);
+       }
+
+       return (0);
+}
+
+static void printerr()
+{
+       int ecode = tcrdbecode(rdb);
+       ERROR ("tokyotyrant plugin: error: %d, %s",
+                       ecode, tcrdberrmsg(ecode));
+}
+
+static void tt_submit (gauge_t val, const char* type)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = val;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+
+       sstrncpy (vl.host, config_host, sizeof (vl.host));
+       sstrncpy (vl.plugin, "tokyotyrant", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, config_port,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void tt_open_db (void)
+{
+       char* host = NULL;
+       int   port = DEFAULT_PORT;
+
+       if (rdb != NULL)
+               return;
+
+       host = ((config_host != NULL) ? config_host : DEFAULT_HOST);
+
+       if (config_port != NULL)
+       {
+               port = service_name_to_port_number (config_port);
+               if (port <= 0)
+                       return;
+       }
+
+       rdb = tcrdbnew ();
+       if (rdb == NULL)
+               return;
+       else if (!tcrdbopen(rdb, host, port))
+       {
+               printerr ();
+               tcrdbdel (rdb);
+               rdb = NULL;
+       }
+} /* void tt_open_db */
+
+static int tt_read (void) {
+       gauge_t rnum, size;
+
+       tt_open_db ();
+       if (rdb == NULL)
+               return (-1);
+
+       rnum = tcrdbrnum(rdb);
+       tt_submit (rnum, "records");
+
+       size = tcrdbsize(rdb);
+       tt_submit (size, "file_size");
+
+       return (0);
+}
+
+static int tt_shutdown(void)
+{
+       sfree(config_host);
+       sfree(config_port);
+
+       if (rdb != NULL)
+       {
+               if (!tcrdbclose(rdb))
+               {
+                       printerr ();
+                       tcrdbdel (rdb);
+                       return (1);
+               }
+               tcrdbdel (rdb);
+               rdb = NULL;
+       }
+
+       return(0);
+}
+
+void module_register (void)
+{
+       plugin_register_config("tokyotyrant", tt_config,
+                       config_keys, config_keys_num);
+       plugin_register_read("tokyotyrant", tt_read);
+       plugin_register_shutdown("tokyotyrant", tt_shutdown);
+}
+
+/* vim: set sw=8 ts=8 tw=78 : */
diff --git a/src/turbostat.c b/src/turbostat.c
new file mode 100644 (file)
index 0000000..80650df
--- /dev/null
@@ -0,0 +1,1611 @@
+/*
+ * turbostat -- Log CPU frequency and C-state residency
+ * on modern Intel turbo-capable processors for collectd.
+ *
+ * Based on the 'turbostat' tool of the Linux kernel, found at
+ * linux/tools/power/x86/turbostat/turbostat.c:
+ * ----
+ * Copyright (c) 2013 Intel Corporation.
+ * Len Brown <len.brown@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ * ----
+ * Ported to collectd by Vincent Brillault <git@lerya.net>
+ */
+
+/*
+ * _GNU_SOURCE is required because of the following functions:
+ * - CPU_ISSET_S
+ * - CPU_ZERO_S
+ * - CPU_SET_S
+ * - CPU_FREE
+ * - CPU_ALLOC
+ * - CPU_ALLOC_SIZE
+ */
+#define _GNU_SOURCE
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_time.h"
+
+#include <asm/msr-index.h>
+#include <cpuid.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+#define PLUGIN_NAME "turbostat"
+
+/*
+ * This tool uses the Model-Specific Registers (MSRs) present on Intel processors.
+ * The general description each of these registers, depending on the architecture,
+ * can be found in the Intel® 64 and IA-32 Architectures Software Developer Manual,
+ * Volume 3 Chapter 35.
+ */
+
+/*
+ * If set, aperf_mperf_unstable disables a/mperf based stats.
+ * This includes: C0 & C1 states, frequency
+ *
+ * This value is automatically set if mperf or aperf go backward
+ */
+static _Bool aperf_mperf_unstable;
+
+/*
+ * Bitmask of the list of core C states supported by the processor.
+ * Currently supported C-states (by this plugin): 3, 6, 7
+ */
+static unsigned int do_core_cstate;
+static unsigned int config_core_cstate;
+static _Bool apply_config_core_cstate;
+
+/*
+ * Bitmask of the list of pacages C states supported by the processor.
+ * Currently supported C-states (by this plugin): 2, 3, 6, 7, 8, 9, 10
+ */
+static unsigned int do_pkg_cstate;
+static unsigned int config_pkg_cstate;
+static _Bool apply_config_pkg_cstate;
+
+/*
+ * Boolean indicating if the processor supports 'I/O System-Management Interrupt counter'
+ */
+static _Bool do_smi;
+static _Bool config_smi;
+static _Bool apply_config_smi;
+
+/*
+ * Boolean indicating if the processor supports 'Digital temperature sensor'
+ * This feature enables the monitoring of the temperature of each core
+ *
+ * This feature has two limitations:
+ *  - if MSR_IA32_TEMPERATURE_TARGET is not supported, the absolute temperature might be wrong
+ *  - Temperatures above the tcc_activation_temp are not recorded
+ */
+static _Bool do_dts;
+static _Bool config_dts;
+static _Bool apply_config_dts;
+
+/*
+ * Boolean indicating if the processor supports 'Package thermal management'
+ * This feature allows the monitoring of the temperature of each package
+ *
+ * This feature has two limitations:
+ *  - if MSR_IA32_TEMPERATURE_TARGET is not supported, the absolute temperature might be wrong
+ *  - Temperatures above the tcc_activation_temp are not recorded
+ */
+static _Bool do_ptm;
+static _Bool config_ptm;
+static _Bool apply_config_ptm;
+
+/*
+ * Thermal Control Circuit Activation Temperature as configured by the user.
+ * This override the automated detection via MSR_IA32_TEMPERATURE_TARGET
+ * and should only be used if the automated detection fails.
+ */
+static unsigned int tcc_activation_temp;
+
+static unsigned int do_rapl;
+static unsigned int config_rapl;
+static _Bool apply_config_rapl;
+static double rapl_energy_units;
+
+#define RAPL_PKG               (1 << 0)
+                                       /* 0x610 MSR_PKG_POWER_LIMIT */
+                                       /* 0x611 MSR_PKG_ENERGY_STATUS */
+#define RAPL_DRAM              (1 << 1)
+                                       /* 0x618 MSR_DRAM_POWER_LIMIT */
+                                       /* 0x619 MSR_DRAM_ENERGY_STATUS */
+                                       /* 0x61c MSR_DRAM_POWER_INFO */
+#define RAPL_CORES             (1 << 2)
+                                       /* 0x638 MSR_PP0_POWER_LIMIT */
+                                       /* 0x639 MSR_PP0_ENERGY_STATUS */
+
+#define RAPL_GFX               (1 << 3)
+                                       /* 0x640 MSR_PP1_POWER_LIMIT */
+                                       /* 0x641 MSR_PP1_ENERGY_STATUS */
+                                       /* 0x642 MSR_PP1_POLICY */
+#define        TJMAX_DEFAULT   100
+
+static cpu_set_t *cpu_present_set, *cpu_affinity_set, *cpu_saved_affinity_set;
+static size_t cpu_present_setsize, cpu_affinity_setsize, cpu_saved_affinity_setsize;
+
+static struct thread_data {
+       unsigned long long tsc;
+       unsigned long long aperf;
+       unsigned long long mperf;
+       unsigned long long c1;
+       unsigned int smi_count;
+       unsigned int cpu_id;
+       unsigned int flags;
+#define CPU_IS_FIRST_THREAD_IN_CORE    0x2
+#define CPU_IS_FIRST_CORE_IN_PACKAGE   0x4
+} *thread_delta, *thread_even, *thread_odd;
+
+static struct core_data {
+       unsigned long long c3;
+       unsigned long long c6;
+       unsigned long long c7;
+       unsigned int core_temp_c;
+       unsigned int core_id;
+} *core_delta, *core_even, *core_odd;
+
+static struct pkg_data {
+       unsigned long long pc2;
+       unsigned long long pc3;
+       unsigned long long pc6;
+       unsigned long long pc7;
+       unsigned long long pc8;
+       unsigned long long pc9;
+       unsigned long long pc10;
+       unsigned int package_id;
+       uint32_t energy_pkg;    /* MSR_PKG_ENERGY_STATUS */
+       uint32_t energy_dram;   /* MSR_DRAM_ENERGY_STATUS */
+       uint32_t energy_cores;  /* MSR_PP0_ENERGY_STATUS */
+       uint32_t energy_gfx;    /* MSR_PP1_ENERGY_STATUS */
+       unsigned int tcc_activation_temp;
+       unsigned int pkg_temp_c;
+} *package_delta, *package_even, *package_odd;
+
+#define DELTA_COUNTERS thread_delta, core_delta, package_delta
+#define ODD_COUNTERS thread_odd, core_odd, package_odd
+#define EVEN_COUNTERS thread_even, core_even, package_even
+static _Bool is_even = 1;
+
+static _Bool allocated = 0;
+static _Bool initialized = 0;
+
+#define GET_THREAD(thread_base, thread_no, core_no, pkg_no) \
+       (thread_base + \
+               (pkg_no) * topology.num_cores * topology.num_threads + \
+               (core_no) * topology.num_threads + \
+               (thread_no))
+#define GET_CORE(core_base, core_no, pkg_no) \
+       (core_base + \
+               (pkg_no) * topology.num_cores + \
+               (core_no))
+#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
+
+struct cpu_topology {
+       unsigned int package_id;
+       unsigned int core_id;
+       _Bool first_core_in_package;
+       _Bool first_thread_in_core;
+};
+
+static struct topology {
+       unsigned int max_cpu_id;
+       unsigned int num_packages;
+       unsigned int num_cores;
+       unsigned int num_threads;
+       struct cpu_topology *cpus;
+} topology;
+
+static cdtime_t time_even, time_odd, time_delta;
+
+static const char *config_keys[] =
+{
+       "CoreCstates",
+       "PackageCstates",
+       "SystemManagementInterrupt",
+       "DigitalTemperatureSensor",
+       "PackageThermalManagement",
+       "TCCActivationTemp",
+       "RunningAveragePowerLimit",
+};
+static const int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+/*****************************
+ *  MSR Manipulation helpers *
+ *****************************/
+
+/*
+ * Open a MSR device for reading
+ * Can change the scheduling affinity of the current process if multiple_read is 1
+ */
+static int __attribute__((warn_unused_result))
+open_msr(unsigned int cpu, _Bool multiple_read)
+{
+       char pathname[32];
+       int fd;
+
+       /*
+        * If we need to do multiple read, let's migrate to the CPU
+        * Otherwise, we would lose time calling functions on another CPU
+        *
+        * If we are not yet initialized (cpu_affinity_setsize = 0),
+        * we need to skip this optimisation.
+        */
+       if (multiple_read && cpu_affinity_setsize) {
+               CPU_ZERO_S(cpu_affinity_setsize, cpu_affinity_set);
+               CPU_SET_S(cpu, cpu_affinity_setsize, cpu_affinity_set);
+               if (sched_setaffinity(0, cpu_affinity_setsize, cpu_affinity_set) == -1) {
+                       ERROR("turbostat plugin: Could not migrate to CPU %d", cpu);
+                       return -1;
+               }
+       }
+
+       ssnprintf(pathname, sizeof(pathname), "/dev/cpu/%d/msr", cpu);
+       fd = open(pathname, O_RDONLY);
+       if (fd < 0) {
+               ERROR("turbostat plugin: failed to open %s", pathname);
+               return -1;
+       }
+       return fd;
+}
+
+/*
+ * Read a single MSR from an open file descriptor
+ */
+static int __attribute__((warn_unused_result))
+read_msr(int fd, off_t offset, unsigned long long *msr)
+{
+       ssize_t retval;
+
+       retval = pread(fd, msr, sizeof *msr, offset);
+
+       if (retval != sizeof *msr) {
+               ERROR("turbostat plugin: MSR offset 0x%llx read failed",
+                     (unsigned long long)offset);
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Open a MSR device for reading, read the value asked for and close it.
+ * This call will not affect the scheduling affinity of this thread.
+ */
+static ssize_t __attribute__((warn_unused_result))
+get_msr(unsigned int cpu, off_t offset, unsigned long long *msr)
+{
+       ssize_t retval;
+       int fd;
+
+       fd = open_msr(cpu, 0);
+       if (fd < 0)
+               return fd;
+       retval = read_msr(fd, offset, msr);
+       close(fd);
+       return retval;
+}
+
+
+/********************************
+ * Raw data acquisition (1 CPU) *
+ ********************************/
+
+/*
+ * Read every data avalaible for a single CPU
+ *
+ * Core data is shared for all threads in one core: extracted only for the first thread
+ * Package data is shared for all core in one package: extracted only for the first thread of the first core
+ *
+ * Side effect: migrates to the targeted CPU
+ */
+static int __attribute__((warn_unused_result))
+get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+       unsigned int cpu = t->cpu_id;
+       unsigned long long msr;
+       int msr_fd;
+       int retval = 0;
+
+       msr_fd = open_msr(cpu, 1);
+       if (msr_fd < 0)
+               return msr_fd;
+
+#define READ_MSR(msr, dst)                                             \
+do {                                                                   \
+       if (read_msr(msr_fd, msr, dst)) {                               \
+               ERROR("turbostat plugin: Unable to read " #msr);        \
+               retval = -1;                                            \
+               goto out;                                               \
+       }                                                               \
+} while (0)
+
+       READ_MSR(MSR_IA32_TSC, &t->tsc);
+
+       READ_MSR(MSR_IA32_APERF, &t->aperf);
+       READ_MSR(MSR_IA32_MPERF, &t->mperf);
+
+       if (do_smi) {
+               READ_MSR(MSR_SMI_COUNT, &msr);
+               t->smi_count = msr & 0xFFFFFFFF;
+       }
+
+       /* collect core counters only for 1st thread in core */
+       if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) {
+               retval = 0;
+               goto out;
+       }
+
+       if (do_core_cstate & (1 << 3))
+               READ_MSR(MSR_CORE_C3_RESIDENCY, &c->c3);
+       if (do_core_cstate & (1 << 6))
+               READ_MSR(MSR_CORE_C6_RESIDENCY, &c->c6);
+       if (do_core_cstate & (1 << 7))
+               READ_MSR(MSR_CORE_C7_RESIDENCY, &c->c7);
+
+       if (do_dts) {
+               READ_MSR(MSR_IA32_THERM_STATUS, &msr);
+               c->core_temp_c = p->tcc_activation_temp - ((msr >> 16) & 0x7F);
+       }
+
+       /* collect package counters only for 1st core in package */
+       if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE)) {
+               retval = 0;
+               goto out;
+       }
+
+       if (do_pkg_cstate & (1 << 2))
+               READ_MSR(MSR_PKG_C2_RESIDENCY, &p->pc2);
+       if (do_pkg_cstate & (1 << 3))
+               READ_MSR(MSR_PKG_C3_RESIDENCY, &p->pc3);
+       if (do_pkg_cstate & (1 << 6))
+               READ_MSR(MSR_PKG_C6_RESIDENCY, &p->pc6);
+       if (do_pkg_cstate & (1 << 7))
+               READ_MSR(MSR_PKG_C7_RESIDENCY, &p->pc7);
+       if (do_pkg_cstate & (1 << 8))
+               READ_MSR(MSR_PKG_C8_RESIDENCY, &p->pc8);
+       if (do_pkg_cstate & (1 << 9))
+               READ_MSR(MSR_PKG_C9_RESIDENCY, &p->pc9);
+       if (do_pkg_cstate & (1 << 10))
+               READ_MSR(MSR_PKG_C10_RESIDENCY, &p->pc10);
+
+       if (do_rapl & RAPL_PKG) {
+               READ_MSR(MSR_PKG_ENERGY_STATUS, &msr);
+               p->energy_pkg = msr & 0xFFFFFFFF;
+       }
+       if (do_rapl & RAPL_CORES) {
+               READ_MSR(MSR_PP0_ENERGY_STATUS, &msr);
+               p->energy_cores = msr & 0xFFFFFFFF;
+       }
+       if (do_rapl & RAPL_DRAM) {
+               READ_MSR(MSR_DRAM_ENERGY_STATUS, &msr);
+               p->energy_dram = msr & 0xFFFFFFFF;
+       }
+       if (do_rapl & RAPL_GFX) {
+               READ_MSR(MSR_PP1_ENERGY_STATUS, &msr);
+               p->energy_gfx = msr & 0xFFFFFFFF;
+       }
+       if (do_ptm) {
+               READ_MSR(MSR_IA32_PACKAGE_THERM_STATUS, &msr);
+               p->pkg_temp_c = p->tcc_activation_temp - ((msr >> 16) & 0x7F);
+       }
+
+out:
+       close(msr_fd);
+       return retval;
+}
+
+
+/**********************************
+ * Evaluating the changes (1 CPU) *
+ **********************************/
+
+/*
+ * Extract the evolution old->new in delta at a package level
+ * (some are not new-delta, e.g. temperature)
+ */
+static inline void
+delta_package(struct pkg_data *delta, const struct pkg_data *new, const struct pkg_data *old)
+{
+       delta->pc2 = new->pc2 - old->pc2;
+       delta->pc3 = new->pc3 - old->pc3;
+       delta->pc6 = new->pc6 - old->pc6;
+       delta->pc7 = new->pc7 - old->pc7;
+       delta->pc8 = new->pc8 - old->pc8;
+       delta->pc9 = new->pc9 - old->pc9;
+       delta->pc10 = new->pc10 - old->pc10;
+       delta->pkg_temp_c = new->pkg_temp_c;
+
+       delta->energy_pkg = new->energy_pkg - old->energy_pkg;
+       delta->energy_cores = new->energy_cores - old->energy_cores;
+       delta->energy_gfx = new->energy_gfx - old->energy_gfx;
+       delta->energy_dram = new->energy_dram - old->energy_dram;
+}
+
+/*
+ * Extract the evolution old->new in delta at a core level
+ * (some are not new-delta, e.g. temperature)
+ */
+static inline void
+delta_core(struct core_data *delta, const struct core_data *new, const struct core_data *old)
+{
+       delta->c3 = new->c3 - old->c3;
+       delta->c6 = new->c6 - old->c6;
+       delta->c7 = new->c7 - old->c7;
+       delta->core_temp_c = new->core_temp_c;
+}
+
+/*
+ * Extract the evolution old->new in delta at a package level
+ * core_delta is required for c1 estimation (tsc - c0 - all core cstates)
+ */
+static inline int __attribute__((warn_unused_result))
+delta_thread(struct thread_data *delta, const struct thread_data *new, const struct thread_data *old,
+       const struct core_data *core_delta)
+{
+       delta->tsc = new->tsc - old->tsc;
+
+       /* check for TSC < 1 Mcycles over interval */
+       if (delta->tsc < (1000 * 1000)) {
+               WARNING("turbostat plugin: Insanely slow TSC rate, TSC stops "
+                       "in idle? You can disable all c-states by booting with"
+                       " 'idle=poll' or just the deep ones with"
+                       " 'processor.max_cstate=1'");
+               return -1;
+       }
+
+       delta->c1 = new->c1 - old->c1;
+
+       if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
+               delta->aperf = new->aperf - old->aperf;
+               delta->mperf = new->mperf - old->mperf;
+       } else {
+               if (!aperf_mperf_unstable) {
+                       WARNING("turbostat plugin: APERF or MPERF went "
+                               "backwards. Frequency results do not cover "
+                               "the entire interval. Fix this by running "
+                               "Linux-2.6.30 or later.");
+
+                       aperf_mperf_unstable = 1;
+               }
+       }
+
+       /*
+        * As counter collection is not atomic,
+        * it is possible for mperf's non-halted cycles + idle states
+        * to exceed TSC's all cycles: show c1 = 0% in that case.
+        */
+       if ((delta->mperf + core_delta->c3 + core_delta->c6 + core_delta->c7) > delta->tsc)
+               delta->c1 = 0;
+       else {
+               /* normal case, derive c1 */
+               delta->c1 = delta->tsc - delta->mperf - core_delta->c3
+                       - core_delta->c6 - core_delta->c7;
+       }
+
+       if (delta->mperf == 0) {
+               WARNING("turbostat plugin: cpu%d MPERF 0!", old->cpu_id);
+               delta->mperf = 1;       /* divide by 0 protection */
+       }
+
+       if (do_smi)
+               delta->smi_count = new->smi_count - old->smi_count;
+
+       return 0;
+}
+
+/**********************************
+ * Submitting the results (1 CPU) *
+ **********************************/
+
+/*
+ * Submit one gauge value
+ */
+static void
+turbostat_submit (const char *plugin_instance,
+       const char *type, const char *type_instance,
+       gauge_t value)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+       value_t v;
+
+       v.gauge = value;
+       vl.values = &v;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, PLUGIN_NAME, sizeof (vl.plugin));
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+/*
+ * Submit every data for a single CPU
+ *
+ * Core data is shared for all threads in one core: submitted only for the first thread
+ * Package data is shared for all core in one package: submitted only for the first thread of the first core
+ */
+static int
+submit_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+       char name[DATA_MAX_NAME_LEN];
+       double interval_float;
+
+       interval_float = CDTIME_T_TO_DOUBLE(time_delta);
+
+       ssnprintf(name, sizeof(name), "cpu%02d", t->cpu_id);
+
+       if (!aperf_mperf_unstable)
+               turbostat_submit(name, "percent", "c0", 100.0 * t->mperf/t->tsc);
+       if (!aperf_mperf_unstable)
+               turbostat_submit(name, "percent", "c1", 100.0 * t->c1/t->tsc);
+
+       turbostat_submit(name, "frequency", "average", 1.0 / 1000000 * t->aperf / interval_float);
+
+       if ((!aperf_mperf_unstable) || (!(t->aperf > t->tsc || t->mperf > t->tsc)))
+               turbostat_submit(name, "frequency", "busy", 1.0 * t->tsc / 1000000 * t->aperf / t->mperf / interval_float);
+
+       /* Sanity check (should stay stable) */
+       turbostat_submit(name, "gauge", "TSC", 1.0 * t->tsc / 1000000 / interval_float);
+
+       /* SMI */
+       if (do_smi)
+               turbostat_submit(name, "count", NULL, t->smi_count);
+
+       /* submit per-core data only for 1st thread in core */
+       if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
+               goto done;
+
+       ssnprintf(name, sizeof(name), "core%02d", c->core_id);
+
+       if (do_core_cstate & (1 << 3))
+               turbostat_submit(name, "percent", "c3", 100.0 * c->c3/t->tsc);
+       if (do_core_cstate & (1 << 6))
+               turbostat_submit(name, "percent", "c6", 100.0 * c->c6/t->tsc);
+       if (do_core_cstate & (1 << 7))
+               turbostat_submit(name, "percent", "c7", 100.0 * c->c7/t->tsc);
+
+       if (do_dts)
+               turbostat_submit(name, "temperature", NULL, c->core_temp_c);
+
+       /* submit per-package data only for 1st core in package */
+       if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
+               goto done;
+
+       ssnprintf(name, sizeof(name), "pkg%02d", p->package_id);
+
+       if (do_ptm)
+               turbostat_submit(name, "temperature", NULL, p->pkg_temp_c);
+
+       if (do_pkg_cstate & (1 << 2))
+               turbostat_submit(name, "percent", "pc2", 100.0 * p->pc2/t->tsc);
+       if (do_pkg_cstate & (1 << 3))
+               turbostat_submit(name, "percent", "pc3", 100.0 * p->pc3/t->tsc);
+       if (do_pkg_cstate & (1 << 6))
+               turbostat_submit(name, "percent", "pc6", 100.0 * p->pc6/t->tsc);
+       if (do_pkg_cstate & (1 << 7))
+               turbostat_submit(name, "percent", "pc7", 100.0 * p->pc7/t->tsc);
+       if (do_pkg_cstate & (1 << 8))
+               turbostat_submit(name, "percent", "pc8", 100.0 * p->pc8/t->tsc);
+       if (do_pkg_cstate & (1 << 9))
+               turbostat_submit(name, "percent", "pc9", 100.0 * p->pc9/t->tsc);
+       if (do_pkg_cstate & (1 << 10))
+               turbostat_submit(name, "percent", "pc10", 100.0 * p->pc10/t->tsc);
+
+       if (do_rapl) {
+               if (do_rapl & RAPL_PKG)
+                       turbostat_submit(name, "power", "pkg", p->energy_pkg * rapl_energy_units / interval_float);
+               if (do_rapl & RAPL_CORES)
+                       turbostat_submit(name, "power", "cores", p->energy_cores * rapl_energy_units / interval_float);
+               if (do_rapl & RAPL_GFX)
+                       turbostat_submit(name, "power", "GFX", p->energy_gfx * rapl_energy_units / interval_float);
+               if (do_rapl & RAPL_DRAM)
+                       turbostat_submit(name, "power", "DRAM", p->energy_dram * rapl_energy_units / interval_float);
+       }
+done:
+       return 0;
+}
+
+
+/**********************************
+ * Looping function over all CPUs *
+ **********************************/
+
+/*
+ * Check if a given cpu id is in our compiled list of existing CPUs
+ */
+static int
+cpu_is_not_present(unsigned int cpu)
+{
+       return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);
+}
+
+/*
+ * Loop on all CPUs in topological order
+ *
+ * Skip non-present cpus
+ * Return the error code at the first error or 0
+ */
+static int __attribute__((warn_unused_result))
+for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_data *),
+       struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
+{
+       int retval;
+       unsigned int pkg_no, core_no, thread_no;
+
+       for (pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
+               for (core_no = 0; core_no < topology.num_cores; ++core_no) {
+                       for (thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
+                               struct thread_data *t;
+                               struct core_data *c;
+                               struct pkg_data *p;
+
+                               t = GET_THREAD(thread_base, thread_no, core_no, pkg_no);
+
+                               if (cpu_is_not_present(t->cpu_id))
+                                       continue;
+
+                               c = GET_CORE(core_base, core_no, pkg_no);
+                               p = GET_PKG(pkg_base, pkg_no);
+
+                               retval = func(t, c, p);
+                               if (retval)
+                                       return retval;
+                       }
+               }
+       }
+       return 0;
+}
+
+/*
+ * Dedicated loop: Extract every data evolution for all CPU
+ *
+ * Skip non-present cpus
+ * Return the error code at the first error or 0
+ *
+ * Core data is shared for all threads in one core: extracted only for the first thread
+ * Package data is shared for all core in one package: extracted only for the first thread of the first core
+ */
+static int __attribute__((warn_unused_result))
+for_all_cpus_delta(const struct thread_data *thread_new_base, const struct core_data *core_new_base, const struct pkg_data *pkg_new_base,
+                  const struct thread_data *thread_old_base, const struct core_data *core_old_base, const struct pkg_data *pkg_old_base)
+{
+       int retval;
+       unsigned int pkg_no, core_no, thread_no;
+
+       for (pkg_no = 0; pkg_no < topology.num_packages; ++pkg_no) {
+               for (core_no = 0; core_no < topology.num_cores; ++core_no) {
+                       for (thread_no = 0; thread_no < topology.num_threads; ++thread_no) {
+                               struct thread_data *t_delta;
+                               const struct thread_data *t_old, *t_new;
+                               struct core_data *c_delta;
+
+                               /* Get correct pointers for threads */
+                               t_delta = GET_THREAD(thread_delta, thread_no, core_no, pkg_no);
+                               t_new = GET_THREAD(thread_new_base, thread_no, core_no, pkg_no);
+                               t_old = GET_THREAD(thread_old_base, thread_no, core_no, pkg_no);
+
+                               /* Skip threads that disappeared */
+                               if (cpu_is_not_present(t_delta->cpu_id))
+                                       continue;
+
+                               /* c_delta is always required for delta_thread */
+                               c_delta = GET_CORE(core_delta, core_no, pkg_no);
+
+                               /* calculate core delta only for 1st thread in core */
+                               if (t_new->flags & CPU_IS_FIRST_THREAD_IN_CORE) {
+                                       const struct core_data *c_old, *c_new;
+
+                                       c_new = GET_CORE(core_new_base, core_no, pkg_no);
+                                       c_old = GET_CORE(core_old_base, core_no, pkg_no);
+
+                                       delta_core(c_delta, c_new, c_old);
+                               }
+
+                               /* Always calculate thread delta */
+                               retval = delta_thread(t_delta, t_new, t_old, c_delta);
+                               if (retval)
+                                       return retval;
+
+                               /* calculate package delta only for 1st core in package */
+                               if (t_new->flags & CPU_IS_FIRST_CORE_IN_PACKAGE) {
+                                       struct pkg_data *p_delta;
+                                       const struct pkg_data *p_old, *p_new;
+
+                                       p_delta = GET_PKG(package_delta, pkg_no);
+                                       p_new = GET_PKG(pkg_new_base, pkg_no);
+                                       p_old = GET_PKG(pkg_old_base, pkg_no);
+
+                                       delta_package(p_delta, p_new, p_old);
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+
+/***************
+ * CPU Probing *
+ ***************/
+
+/*
+ * MSR_IA32_TEMPERATURE_TARGET indicates the temperature where
+ * the Thermal Control Circuit (TCC) activates.
+ * This is usually equal to tjMax.
+ *
+ * Older processors do not have this MSR, so there we guess,
+ * but also allow conficuration over-ride with "TCCActivationTemp".
+ *
+ * Several MSR temperature values are in units of degrees-C
+ * below this value, including the Digital Thermal Sensor (DTS),
+ * Package Thermal Management Sensor (PTM), and thermal event thresholds.
+ */
+static int __attribute__((warn_unused_result))
+set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+       unsigned long long msr;
+       unsigned int target_c_local;
+
+       /* tcc_activation_temp is used only for dts or ptm */
+       if (!(do_dts || do_ptm))
+               return 0;
+
+       /* this is a per-package concept */
+       if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE) || !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
+               return 0;
+
+       if (tcc_activation_temp != 0) {
+               p->tcc_activation_temp = tcc_activation_temp;
+               return 0;
+       }
+
+       if (get_msr(t->cpu_id, MSR_IA32_TEMPERATURE_TARGET, &msr))
+               goto guess;
+
+       target_c_local = (msr >> 16) & 0xFF;
+
+       if (!target_c_local)
+               goto guess;
+
+       p->tcc_activation_temp = target_c_local;
+
+       return 0;
+
+guess:
+       p->tcc_activation_temp = TJMAX_DEFAULT;
+       WARNING("turbostat plugin: cpu%d: Guessing tjMax %d C,"
+               " Please use TCCActivationTemp to specify it.",
+               t->cpu_id, p->tcc_activation_temp);
+
+       return 0;
+}
+
+/*
+ * Identify the functionality of the CPU
+ */
+static int __attribute__((warn_unused_result))
+probe_cpu()
+{
+       unsigned int eax, ebx, ecx, edx, max_level;
+       unsigned int fms, family, model;
+
+       /* CPUID(0):
+        * - EAX: Maximum Input Value for Basic CPUID Information
+        * - EBX: "Genu" (0x756e6547)
+        * - EDX: "ineI" (0x49656e69)
+        * - ECX: "ntel" (0x6c65746e)
+        */
+       max_level = ebx = ecx = edx = 0;
+       __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
+       if (ebx != 0x756e6547 && edx != 0x49656e69 && ecx != 0x6c65746e) {
+               ERROR("turbostat plugin: Unsupported CPU (not Intel)");
+               return -1;
+       }
+
+       /* CPUID(1):
+        * - EAX: Version Information: Type, Family, Model, and Stepping ID
+        *  + 4-7:   Model ID
+        *  + 8-11:  Family ID
+        *  + 12-13: Processor type
+        *  + 16-19: Extended Model ID
+        *  + 20-27: Extended Family ID
+        * - EDX: Feature Information:
+        *  + 5: Support for MSR read/write operations
+        */
+       fms = ebx = ecx = edx = 0;
+       __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+       family = (fms >> 8) & 0xf;
+       model = (fms >> 4) & 0xf;
+       if (family == 0xf)
+               family += (fms >> 20) & 0xf;
+       if (family == 6 || family == 0xf)
+               model += ((fms >> 16) & 0xf) << 4;
+       if (!(edx & (1 << 5))) {
+               ERROR("turbostat plugin: Unsupported CPU (no MSR support)");
+               return -1;
+       }
+
+       /*
+        * CPUID(6):
+        * - EAX:
+        *  + 0: Digital temperature sensor is supported if set
+        *  + 6: Package thermal management is supported if set
+        * - ECX:
+        *  + 0: Hardware Coordination Feedback Capability (Presence of IA32_MPERF and IA32_APERF).
+        *  + 3: The processor supports performance-energy bias preference if set.
+        *       It also implies the presence of a new architectural MSR called IA32_ENERGY_PERF_BIAS
+        *
+        * This check is valid for both Intel and AMD
+        */
+       eax = ebx = ecx = edx = 0;
+       __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+       do_dts = eax & (1 << 0);
+       do_ptm = eax & (1 << 6);
+       if (!(ecx & (1 << 0))) {
+               ERROR("turbostat plugin: Unsupported CPU (No APERF)");
+               return -1;
+       }
+
+       /*
+        * Enable or disable C states depending on the model and family
+        */
+       if (family == 6) {
+               switch (model) {
+               /* Atom (partial) */
+               case 0x27:
+                       do_smi = 0;
+                       do_core_cstate = 0;
+                       do_pkg_cstate = (1 << 2) | (1 << 4) | (1 << 6);
+                       break;
+               /* Silvermont */
+               case 0x37: /* BYT */
+               case 0x4D: /* AVN */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 1) | (1 << 6);
+                       do_pkg_cstate = (1 << 6);
+                       break;
+               /* Nehalem */
+               case 0x1A: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
+               case 0x1E: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
+               case 0x1F: /* Core i7 and i5 Processor - Nehalem */
+               case 0x2E: /* Nehalem-EX Xeon - Beckton */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6);
+                       do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       break;
+               /* Westmere */
+               case 0x25: /* Westmere Client - Clarkdale, Arrandale */
+               case 0x2C: /* Westmere EP - Gulftown */
+               case 0x2F: /* Westmere-EX Xeon - Eagleton */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6);
+                       do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       break;
+               /* Sandy Bridge */
+               case 0x2A: /* SNB */
+               case 0x2D: /* SNB Xeon */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
+                       break;
+               /* Ivy Bridge */
+               case 0x3A: /* IVB */
+               case 0x3E: /* IVB Xeon */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
+                       break;
+               /* Haswell Bridge */
+               case 0x3C: /* HSW */
+               case 0x3F: /* HSW */
+               case 0x46: /* HSW */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
+                       break;
+               case 0x45: /* HSW */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10);
+                       break;
+               /* Broadwel */
+               case 0x4F: /* BDW */
+               case 0x56: /* BDX-DE */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
+                       break;
+               case 0x3D: /* BDW */
+                       do_smi = 1;
+                       do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
+                       do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10);
+                       break;
+               default:
+                       do_smi = 0;
+                       do_core_cstate = 0;
+                       do_pkg_cstate = 0;
+                       break;
+               }
+               switch (model) {
+               case 0x2A: /* SNB */
+               case 0x3A: /* IVB */
+               case 0x3C: /* HSW */
+               case 0x45: /* HSW */
+               case 0x46: /* HSW */
+               case 0x3D: /* BDW */
+                       do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;
+                       break;
+               case 0x3F: /* HSX */
+               case 0x4F: /* BDX */
+               case 0x56: /* BDX-DE */
+                       do_rapl = RAPL_PKG | RAPL_DRAM ;
+                       break;
+               case 0x2D: /* SNB Xeon */
+               case 0x3E: /* IVB Xeon */
+                       do_rapl = RAPL_PKG | RAPL_CORES | RAPL_DRAM;
+                       break;
+               case 0x37: /* BYT */
+               case 0x4D: /* AVN */
+                       do_rapl = RAPL_PKG | RAPL_CORES;
+                       break;
+               default:
+                       do_rapl = 0;
+               }
+       } else {
+               ERROR("turbostat plugin: Unsupported CPU (family: %#x, "
+                     "model: %#x)", family, model);
+               return -1;
+       }
+
+       /* Override detected values with configuration */
+       if (apply_config_core_cstate)
+               do_core_cstate = config_core_cstate;
+       if (apply_config_pkg_cstate)
+               do_pkg_cstate = config_pkg_cstate;
+       if (apply_config_smi)
+               do_smi = config_smi;
+       if (apply_config_dts)
+               do_dts = config_dts;
+       if (apply_config_ptm)
+               do_ptm = config_ptm;
+       if (apply_config_rapl)
+               do_rapl = config_rapl;
+
+       if (do_rapl) {
+               unsigned long long msr;
+               if (get_msr(0, MSR_RAPL_POWER_UNIT, &msr))
+                       return 0;
+
+               if (model == 0x37)
+                       rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;
+               else
+                       rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
+       }
+
+       return 0;
+}
+
+
+/********************
+ * Topology Probing *
+ ********************/
+
+/*
+ * Read a single int from a file.
+ */
+static int __attribute__ ((format(printf,1,2)))
+parse_int_file(const char *fmt, ...)
+{
+       va_list args;
+       char path[PATH_MAX];
+       FILE *filep;
+       int len, value;
+
+       va_start(args, fmt);
+       len = vsnprintf(path, sizeof(path), fmt, args);
+       va_end(args);
+       if (len < 0 || len >= PATH_MAX) {
+               ERROR("turbostat plugin: path truncated: '%s'", path);
+               return -1;
+       }
+
+       filep = fopen(path, "r");
+       if (!filep) {
+               ERROR("turbostat plugin: Failed to open '%s'", path);
+               return -1;
+       }
+       if (fscanf(filep, "%d", &value) != 1) {
+               ERROR("turbostat plugin: Failed to parse number from '%s'", path);
+               return -1;
+       }
+       fclose(filep);
+       return value;
+}
+
+static int
+get_threads_on_core(unsigned int cpu)
+{
+       char path[80];
+       FILE *filep;
+       int sib1, sib2;
+       int matches;
+       char character;
+
+       ssnprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu);
+       filep = fopen(path, "r");
+       if (!filep) {
+               ERROR("turbostat plugin: Failed to open '%s'", path);
+               return -1;
+       }
+       /*
+        * file format:
+        * if a pair of number with a character between: 2 siblings (eg. 1-2, or 1,4)
+        * otherwinse 1 sibling (self).
+        */
+       matches = fscanf(filep, "%d%c%d\n", &sib1, &character, &sib2);
+
+       fclose(filep);
+
+       if (matches == 3)
+               return 2;
+       else
+               return 1;
+}
+
+/*
+ * run func(cpu) on every cpu in /proc/stat
+ * return max_cpu number
+ */
+static int __attribute__((warn_unused_result))
+for_all_proc_cpus(int (func)(unsigned int))
+{
+       FILE *fp;
+       unsigned int cpu_num;
+       int retval;
+
+       fp = fopen("/proc/stat", "r");
+       if (!fp) {
+               ERROR("turbostat plugin: Failed to open /proc/stat");
+               return -1;
+       }
+
+       retval = fscanf(fp, "cpu %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n");
+       if (retval != 0) {
+               ERROR("turbostat plugin: Failed to parse /proc/stat");
+               fclose(fp);
+               return -1;
+       }
+
+       while (1) {
+               retval = fscanf(fp, "cpu%u %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d\n", &cpu_num);
+               if (retval != 1)
+                       break;
+
+               retval = func(cpu_num);
+               if (retval) {
+                       fclose(fp);
+                       return(retval);
+               }
+       }
+       fclose(fp);
+       return 0;
+}
+
+/*
+ * Update the stored topology.max_cpu_id
+ */
+static int
+update_max_cpu_id(unsigned int cpu)
+{
+       if (topology.max_cpu_id < cpu)
+               topology.max_cpu_id = cpu;
+       return 0;
+}
+
+static int
+mark_cpu_present(unsigned int cpu)
+{
+       CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);
+       return 0;
+}
+
+static int __attribute__((warn_unused_result))
+allocate_cpu_set(cpu_set_t ** set, size_t * size) {
+       *set = CPU_ALLOC(topology.max_cpu_id  + 1);
+       if (*set == NULL) {
+               ERROR("turbostat plugin: Unable to allocate CPU state");
+               return -1;
+       }
+       *size = CPU_ALLOC_SIZE(topology.max_cpu_id  + 1);
+       CPU_ZERO_S(*size, *set);
+       return 0;
+}
+
+/*
+ * Build a local representation of the cpu distribution
+ */
+static int __attribute__((warn_unused_result))
+topology_probe()
+{
+       unsigned int i;
+       int ret;
+       unsigned int max_package_id, max_core_id, max_threads;
+       max_package_id = max_core_id = max_threads = 0;
+
+       /* Clean topology */
+       free(topology.cpus);
+       memset(&topology, 0, sizeof(topology));
+
+       ret = for_all_proc_cpus(update_max_cpu_id);
+       if (ret != 0)
+               goto err;
+
+       topology.cpus = calloc(1, (topology.max_cpu_id  + 1) * sizeof(struct cpu_topology));
+       if (topology.cpus == NULL) {
+               ERROR("turbostat plugin: Unable to allocate memory for CPU topology");
+               return -1;
+       }
+
+       ret = allocate_cpu_set(&cpu_present_set, &cpu_present_setsize);
+       if (ret != 0)
+               goto err;
+       ret = allocate_cpu_set(&cpu_affinity_set, &cpu_affinity_setsize);
+       if (ret != 0)
+               goto err;
+       ret = allocate_cpu_set(&cpu_saved_affinity_set, &cpu_saved_affinity_setsize);
+       if (ret != 0)
+               goto err;
+
+       ret = for_all_proc_cpus(mark_cpu_present);
+       if (ret != 0)
+               goto err;
+
+       /*
+        * For online cpus
+        * find max_core_id, max_package_id
+        */
+       for (i = 0; i <= topology.max_cpu_id; ++i) {
+               unsigned int num_threads;
+               struct cpu_topology *cpu = &topology.cpus[i];
+
+               if (cpu_is_not_present(i)) {
+                       WARNING("turbostat plugin: cpu%d NOT PRESENT", i);
+                       continue;
+               }
+
+               ret = parse_int_file("/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
+               if (ret < 0)
+                       goto err;
+               else
+                       cpu->package_id = (unsigned int) ret;
+               if (cpu->package_id > max_package_id)
+                       max_package_id = cpu->package_id;
+
+               ret = parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_id", i);
+               if (ret < 0)
+                       goto err;
+               else
+                       cpu->core_id = (unsigned int) ret;
+               if (cpu->core_id > max_core_id)
+                       max_core_id = cpu->core_id;
+               ret = parse_int_file("/sys/devices/system/cpu/cpu%d/topology/core_siblings_list", i);
+               if (ret < 0)
+                       goto err;
+               else if ((unsigned int) ret == i)
+                       cpu->first_core_in_package = 1;
+
+               ret = get_threads_on_core(i);
+               if (ret < 0)
+                       goto err;
+               else
+                       num_threads = (unsigned int) ret;
+               if (num_threads > max_threads)
+                       max_threads = num_threads;
+               ret = parse_int_file("/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
+               if (ret < 0)
+                       goto err;
+               else if ((unsigned int) ret == i)
+                       cpu->first_thread_in_core = 1;
+
+               DEBUG("turbostat plugin: cpu %d pkg %d core %d\n",
+                       i, cpu->package_id, cpu->core_id);
+       }
+       /* Num is max + 1 (need to count 0) */
+       topology.num_packages = max_package_id + 1;
+       topology.num_cores = max_core_id + 1;
+       topology.num_threads = max_threads;
+
+       return 0;
+err:
+       free(topology.cpus);
+       return ret;
+}
+
+
+/************************
+ * Main alloc/init/free *
+ ************************/
+
+static int
+allocate_counters(struct thread_data **threads, struct core_data **cores, struct pkg_data **packages)
+{
+       unsigned int i;
+       unsigned int total_threads, total_cores;
+
+       total_threads = topology.num_threads * topology.num_cores * topology.num_packages;
+       *threads = calloc(total_threads, sizeof(struct thread_data));
+       if (*threads == NULL)
+               goto err;
+
+       for (i = 0; i < total_threads; ++i)
+               (*threads)[i].cpu_id = topology.max_cpu_id + 1;
+
+       total_cores = topology.num_cores * topology.num_packages;
+       *cores = calloc(total_cores, sizeof(struct core_data));
+       if (*cores == NULL)
+               goto err_clean_threads;
+
+       *packages = calloc(topology.num_packages, sizeof(struct pkg_data));
+       if (*packages == NULL)
+               goto err_clean_cores;
+
+       return 0;
+
+err_clean_cores:
+       free(*cores);
+err_clean_threads:
+       free(*threads);
+err:
+       ERROR("turbostat plugin: Failled to allocate memory for counters");
+       return -1;
+}
+
+static void
+init_counter(struct thread_data *thread_base, struct core_data *core_base,
+       struct pkg_data *pkg_base, unsigned int cpu_id)
+{
+       struct thread_data *t;
+       struct core_data *c;
+       struct pkg_data *p;
+       struct cpu_topology *cpu = &topology.cpus[cpu_id];
+
+       t = GET_THREAD(thread_base, !(cpu->first_thread_in_core), cpu->core_id, cpu->package_id);
+       c = GET_CORE(core_base, cpu->core_id, cpu->package_id);
+       p = GET_PKG(pkg_base, cpu->package_id);
+
+       t->cpu_id = cpu_id;
+       if (cpu->first_thread_in_core)
+               t->flags |= CPU_IS_FIRST_THREAD_IN_CORE;
+       if (cpu->first_core_in_package)
+               t->flags |= CPU_IS_FIRST_CORE_IN_PACKAGE;
+
+       c->core_id = cpu->core_id;
+       p->package_id = cpu->package_id;
+}
+
+static void
+initialize_counters(void)
+{
+       unsigned int cpu_id;
+
+       for (cpu_id = 0; cpu_id <= topology.max_cpu_id; ++cpu_id) {
+               if (cpu_is_not_present(cpu_id))
+                       continue;
+               init_counter(EVEN_COUNTERS, cpu_id);
+               init_counter(ODD_COUNTERS, cpu_id);
+               init_counter(DELTA_COUNTERS, cpu_id);
+       }
+}
+
+
+
+static void
+free_all_buffers(void)
+{
+       allocated = 0;
+       initialized = 0;
+
+       CPU_FREE(cpu_present_set);
+       cpu_present_set = NULL;
+       cpu_present_set = 0;
+
+       CPU_FREE(cpu_affinity_set);
+       cpu_affinity_set = NULL;
+       cpu_affinity_setsize = 0;
+
+       CPU_FREE(cpu_saved_affinity_set);
+       cpu_saved_affinity_set = NULL;
+       cpu_saved_affinity_setsize = 0;
+
+       free(thread_even);
+       free(core_even);
+       free(package_even);
+
+       thread_even = NULL;
+       core_even = NULL;
+       package_even = NULL;
+
+       free(thread_odd);
+       free(core_odd);
+       free(package_odd);
+
+       thread_odd = NULL;
+       core_odd = NULL;
+       package_odd = NULL;
+
+       free(thread_delta);
+       free(core_delta);
+       free(package_delta);
+
+       thread_delta = NULL;
+       core_delta = NULL;
+       package_delta = NULL;
+}
+
+
+/**********************
+ * Collectd functions *
+ **********************/
+
+#define DO_OR_GOTO_ERR(something) \
+do {                             \
+       ret = (something);        \
+       if (ret < 0)              \
+               goto err;         \
+} while (0)
+
+static int setup_all_buffers(void)
+{
+       int ret;
+
+       DO_OR_GOTO_ERR(topology_probe());
+       DO_OR_GOTO_ERR(allocate_counters(&thread_even, &core_even, &package_even));
+       DO_OR_GOTO_ERR(allocate_counters(&thread_odd, &core_odd, &package_odd));
+       DO_OR_GOTO_ERR(allocate_counters(&thread_delta, &core_delta, &package_delta));
+       initialize_counters();
+       DO_OR_GOTO_ERR(for_all_cpus(set_temperature_target, EVEN_COUNTERS));
+       DO_OR_GOTO_ERR(for_all_cpus(set_temperature_target, ODD_COUNTERS));
+
+       allocated = 1;
+       return 0;
+err:
+       free_all_buffers();
+       return ret;
+}
+
+static int
+turbostat_read(void)
+{
+       int ret;
+
+       if (!allocated) {
+               if ((ret = setup_all_buffers()) < 0)
+                       return ret;
+       }
+
+       if (for_all_proc_cpus(cpu_is_not_present)) {
+               free_all_buffers();
+               if ((ret = setup_all_buffers()) < 0)
+                       return ret;
+               if (for_all_proc_cpus(cpu_is_not_present)) {
+                       ERROR("turbostat plugin: CPU appeared just after "
+                             "initialization");
+                       return -1;
+               }
+       }
+
+       /* Saving the scheduling affinity, as it will be modified by get_counters */
+       if (sched_getaffinity(0, cpu_saved_affinity_setsize, cpu_saved_affinity_set) != 0) {
+               ERROR("turbostat plugin: Unable to save the CPU affinity");
+               return -1;
+       }
+
+       if (!initialized) {
+               if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0)
+                       goto out;
+               time_even = cdtime();
+               is_even = 1;
+               initialized = 1;
+               ret = 0;
+               goto out;
+       }
+
+       if (is_even) {
+               if ((ret = for_all_cpus(get_counters, ODD_COUNTERS)) < 0)
+                       goto out;
+               time_odd = cdtime();
+               is_even = 0;
+               time_delta = time_odd - time_even;
+               if ((ret = for_all_cpus_delta(ODD_COUNTERS, EVEN_COUNTERS)) < 0)
+                       goto out;
+               if ((ret = for_all_cpus(submit_counters, DELTA_COUNTERS)) < 0)
+                       goto out;
+       } else {
+               if ((ret = for_all_cpus(get_counters, EVEN_COUNTERS)) < 0)
+                       goto out;
+               time_even = cdtime();
+               is_even = 1;
+               time_delta = time_even - time_odd;
+               if ((ret = for_all_cpus_delta(EVEN_COUNTERS, ODD_COUNTERS)) < 0)
+                       goto out;
+               if ((ret = for_all_cpus(submit_counters, DELTA_COUNTERS)) < 0)
+                       goto out;
+       }
+       ret = 0;
+out:
+       /*
+        * Let's restore the affinity
+        * This might fail if the number of CPU changed, but we can't do anything in that case..
+        */
+       (void)sched_setaffinity(0, cpu_saved_affinity_setsize, cpu_saved_affinity_set);
+       return ret;
+}
+
+static int
+check_permissions(void)
+{
+#ifdef HAVE_SYS_CAPABILITY_H
+       struct __user_cap_header_struct cap_header_data;
+       cap_user_header_t cap_header = &cap_header_data;
+       struct __user_cap_data_struct cap_data_data;
+       cap_user_data_t cap_data = &cap_data_data;
+       int ret = 0;
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+       if (getuid() == 0) {
+               /* We have everything we need */
+               return 0;
+#ifndef HAVE_SYS_CAPABILITY_H
+       } else {
+               ERROR("turbostat plugin: Initialization failed: this plugin "
+                     "requires collectd to run as root");
+               return -1;
+       }
+#else /* HAVE_SYS_CAPABILITY_H */
+       }
+
+       /* check for CAP_SYS_RAWIO */
+       cap_header->pid = getpid();
+       cap_header->version = _LINUX_CAPABILITY_VERSION;
+       if (capget(cap_header, cap_data) < 0) {
+               ERROR("turbostat plugin: capget failed");
+               return -1;
+       }
+
+       if ((cap_data->effective & (1 << CAP_SYS_RAWIO)) == 0) {
+               WARNING("turbostat plugin: Collectd doesn't have the "
+                       "CAP_SYS_RAWIO capability. If you don't want to run "
+                       "collectd as root, try running \"setcap "
+                       "cap_sys_rawio=ep\" on collectd binary");
+               ret = -1;
+       }
+
+       if (euidaccess("/dev/cpu/0/msr", R_OK)) {
+               WARNING("turbostat plugin: Collectd cannot open"
+                       "/dev/cpu/0/msr. If you don't want to run collectd as "
+                       "root, you need to change the ownership (chown) and "
+                       "permissions on /dev/cpu/*/msr to allow such access");
+               ret = -1;
+       }
+
+       if (ret != 0)
+               ERROR("turbostat plugin: Initialization failed: this plugin "
+                     "requires collectd to either to run as root or give "
+                     "collectd a special capability (CAP_SYS_RAWIO) and read "
+                      "access to /dev/cpu/*/msr (see previous warnings)");
+       return ret;
+#endif /* HAVE_SYS_CAPABILITY_H */
+}
+
+static int
+turbostat_init(void)
+{
+       struct stat sb;
+       int ret;
+
+       if (stat("/dev/cpu/0/msr", &sb)) {
+               ERROR("turbostat plugin: Initialization failed: /dev/cpu/0/msr"
+                     " does not exist while the CPU supports MSR. You may be "
+                     "missing the corresponding kernel module, please try '# "
+                     "modprobe msr'");
+               return -1;
+       }
+
+       DO_OR_GOTO_ERR(check_permissions());
+
+       DO_OR_GOTO_ERR(probe_cpu());
+
+       DO_OR_GOTO_ERR(setup_all_buffers());
+
+       plugin_register_read(PLUGIN_NAME, turbostat_read);
+
+       return 0;
+err:
+       free_all_buffers();
+       return ret;
+}
+
+static int
+turbostat_config(const char *key, const char *value)
+{
+       long unsigned int tmp_val;
+       char *end;
+
+       if (strcasecmp("CoreCstates", key) == 0) {
+               tmp_val = strtoul(value, &end, 0);
+               if (*end != '\0' || tmp_val > UINT_MAX) {
+                       ERROR("turbostat plugin: Invalid CoreCstates '%s'",
+                             value);
+                       return -1;
+               }
+               config_core_cstate = (unsigned int) tmp_val;
+               apply_config_core_cstate = 1;
+       } else if (strcasecmp("PackageCstates", key) == 0) {
+               tmp_val = strtoul(value, &end, 0);
+               if (*end != '\0' || tmp_val > UINT_MAX) {
+                       ERROR("turbostat plugin: Invalid PackageCstates '%s'",
+                             value);
+                       return -1;
+               }
+               config_pkg_cstate = (unsigned int) tmp_val;
+               apply_config_pkg_cstate = 1;
+       } else if (strcasecmp("SystemManagementInterrupt", key) == 0) {
+               config_smi = IS_TRUE(value);
+               apply_config_smi = 1;
+       } else if (strcasecmp("DigitalTemperatureSensor", key) == 0) {
+               config_dts = IS_TRUE(value);
+               apply_config_dts = 1;
+       } else if (strcasecmp("PackageThermalManagement", key) == 0) {
+               config_ptm = IS_TRUE(value);
+               apply_config_ptm = 1;
+       } else if (strcasecmp("RunningAveragePowerLimit", key) == 0) {
+               tmp_val = strtoul(value, &end, 0);
+               if (*end != '\0' || tmp_val > UINT_MAX) {
+                       ERROR("turbostat plugin: Invalid RunningAveragePowerLimit '%s'",
+                             value);
+                       return -1;
+               }
+               config_rapl = (unsigned int) tmp_val;
+               apply_config_rapl = 1;
+       } else if (strcasecmp("TCCActivationTemp", key) == 0) {
+               tmp_val = strtoul(value, &end, 0);
+               if (*end != '\0' || tmp_val > UINT_MAX) {
+                       ERROR("turbostat plugin: Invalid TCCActivationTemp '%s'",
+                             value);
+                       return -1;
+               }
+               tcc_activation_temp = (unsigned int) tmp_val;
+       } else {
+               ERROR("turbostat plugin: Invalid configuration option '%s'",
+                     key);
+               return -1;
+       }
+       return 0;
+}
+
+void module_register(void)
+{
+       plugin_register_init(PLUGIN_NAME, turbostat_init);
+       plugin_register_config(PLUGIN_NAME, turbostat_config, config_keys, config_keys_num);
+}
diff --git a/src/types.db b/src/types.db
new file mode 100644 (file)
index 0000000..38fb546
--- /dev/null
@@ -0,0 +1,241 @@
+absolute               value:ABSOLUTE:0:U
+apache_bytes           value:DERIVE:0:U
+apache_connections     value:GAUGE:0:65535
+apache_idle_workers    value:GAUGE:0:65535
+apache_requests                value:DERIVE:0:U
+apache_scoreboard      value:GAUGE:0:65535
+ath_nodes              value:GAUGE:0:65535
+ath_stat               value:DERIVE:0:U
+backends               value:GAUGE:0:65535
+bitrate                        value:GAUGE:0:4294967295
+blocked_clients value:GAUGE:0:U
+bytes                  value:GAUGE:0:U
+cache_eviction         value:DERIVE:0:U
+cache_operation                value:DERIVE:0:U
+cache_ratio            value:GAUGE:0:100
+cache_result           value:DERIVE:0:U
+cache_size             value:GAUGE:0:U
+ceph_bytes             value:GAUGE:U:U
+ceph_latency   value:GAUGE:U:U
+ceph_rate                      value:DERIVE:0:U
+changes_since_last_save   value:GAUGE:0:U
+charge                 value:GAUGE:0:U
+compression_ratio      value:GAUGE:0:2
+compression            uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
+connections            value:DERIVE:0:U
+conntrack              value:GAUGE:0:4294967295
+contextswitch          value:DERIVE:0:U
+count                  value:GAUGE:0:U
+counter                        value:COUNTER:U:U
+cpufreq                        value:GAUGE:0:U
+cpu                    value:DERIVE:0:U
+current_connections    value:GAUGE:0:U
+current_sessions       value:GAUGE:0:U
+current                        value:GAUGE:U:U
+delay                  value:GAUGE:-1000000:1000000
+derive                 value:DERIVE:0:U
+df_complex             value:GAUGE:0:U
+df_inodes              value:GAUGE:0:U
+df                     used:GAUGE:0:1125899906842623, free:GAUGE:0:1125899906842623
+disk_latency           read:GAUGE:0:U, write:GAUGE:0:U
+disk_merged            read:DERIVE:0:U, write:DERIVE:0:U
+disk_octets            read:DERIVE:0:U, write:DERIVE:0:U
+disk_ops_complex       value:DERIVE:0:U
+disk_ops               read:DERIVE:0:U, write:DERIVE:0:U
+disk_time              read:DERIVE:0:U, write:DERIVE:0:U
+disk_io_time           io_time:DERIVE:0:U, weighted_io_time:DERIVE:0:U
+dns_answer             value:DERIVE:0:U
+dns_notify             value:DERIVE:0:U
+dns_octets             queries:DERIVE:0:U, responses:DERIVE:0:U
+dns_opcode             value:DERIVE:0:U
+dns_qtype_cached       value:GAUGE:0:4294967295
+dns_qtype              value:DERIVE:0:U
+dns_query              value:DERIVE:0:U
+dns_question           value:DERIVE:0:U
+dns_rcode              value:DERIVE:0:U
+dns_reject             value:DERIVE:0:U
+dns_request            value:DERIVE:0:U
+dns_resolver           value:DERIVE:0:U
+dns_response           value:DERIVE:0:U
+dns_transfer           value:DERIVE:0:U
+dns_update             value:DERIVE:0:U
+dns_zops               value:DERIVE:0:U
+drbd_resource  value:DERIVE:0:U
+duration               seconds:GAUGE:0:U
+email_check            value:GAUGE:0:U
+email_count            value:GAUGE:0:U
+email_size             value:GAUGE:0:U
+entropy                        value:GAUGE:0:4294967295
+expired_keys    value:GAUGE:0:U
+fanspeed               value:GAUGE:0:U
+file_handles           value:GAUGE:0:U
+file_size              value:GAUGE:0:U
+files                  value:GAUGE:0:U
+flow                   value:GAUGE:0:U
+fork_rate              value:DERIVE:0:U
+frequency_offset       value:GAUGE:-1000000:1000000
+frequency              value:GAUGE:0:U
+fscache_stat           value:DERIVE:0:U
+gauge                  value:GAUGE:U:U
+hash_collisions                value:DERIVE:0:U
+http_request_methods   value:DERIVE:0:U
+http_requests          value:DERIVE:0:U
+http_response_codes    value:DERIVE:0:U
+humidity               value:GAUGE:0:100
+if_collisions          value:DERIVE:0:U
+if_dropped             rx:DERIVE:0:U, tx:DERIVE:0:U
+if_errors              rx:DERIVE:0:U, tx:DERIVE:0:U
+if_multicast           value:DERIVE:0:U
+if_octets              rx:DERIVE:0:U, tx:DERIVE:0:U
+if_packets             rx:DERIVE:0:U, tx:DERIVE:0:U
+if_rx_errors           value:DERIVE:0:U
+if_rx_octets           value:DERIVE:0:U
+if_tx_errors           value:DERIVE:0:U
+if_tx_octets           value:DERIVE:0:U
+invocations            value:DERIVE:0:U
+io_octets              rx:DERIVE:0:U, tx:DERIVE:0:U
+io_packets             rx:DERIVE:0:U, tx:DERIVE:0:U
+ipt_bytes              value:DERIVE:0:U
+ipt_packets            value:DERIVE:0:U
+irq                    value:DERIVE:0:U
+latency                        value:GAUGE:0:U
+links                  value:GAUGE:0:U
+load                   shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000
+md_disks               value:GAUGE:0:U
+memcached_command      value:DERIVE:0:U
+memcached_connections  value:GAUGE:0:U
+memcached_items                value:GAUGE:0:U
+memcached_octets       rx:DERIVE:0:U, tx:DERIVE:0:U
+memcached_ops          value:DERIVE:0:U
+memory                 value:GAUGE:0:281474976710656
+memory_lua             value:GAUGE:0:281474976710656
+multimeter             value:GAUGE:U:U
+mutex_operations       value:DERIVE:0:U
+mysql_commands         value:DERIVE:0:U
+mysql_handler          value:DERIVE:0:U
+mysql_locks            value:DERIVE:0:U
+mysql_log_position     value:DERIVE:0:U
+mysql_octets           rx:DERIVE:0:U, tx:DERIVE:0:U
+mysql_bpool_pages      value:GAUGE:0:U
+mysql_bpool_bytes      value:GAUGE:0:U
+mysql_bpool_counters   value:DERIVE:0:U
+mysql_innodb_data      value:DERIVE:0:U
+mysql_innodb_dblwr     value:DERIVE:0:U
+mysql_innodb_log       value:DERIVE:0:U
+mysql_innodb_pages     value:DERIVE:0:U
+mysql_innodb_row_lock  value:DERIVE:0:U
+mysql_innodb_rows      value:DERIVE:0:U
+mysql_select           value:DERIVE:0:U
+mysql_sort             value:DERIVE:0:U
+nfs_procedure          value:DERIVE:0:U
+nginx_connections      value:GAUGE:0:U
+nginx_requests         value:DERIVE:0:U
+node_octets            rx:DERIVE:0:U, tx:DERIVE:0:U
+node_rssi              value:GAUGE:0:255
+node_stat              value:DERIVE:0:U
+node_tx_rate           value:GAUGE:0:127
+objects                        value:GAUGE:0:U
+operations             value:DERIVE:0:U
+packets                        value:DERIVE:0:U
+pending_operations     value:GAUGE:0:U
+percent                        value:GAUGE:0:100.1
+percent_bytes          value:GAUGE:0:100.1
+percent_inodes         value:GAUGE:0:100.1
+pf_counters            value:DERIVE:0:U
+pf_limits              value:DERIVE:0:U
+pf_source              value:DERIVE:0:U
+pf_states              value:GAUGE:0:U
+pf_state               value:DERIVE:0:U
+pg_blks                        value:DERIVE:0:U
+pg_db_size             value:GAUGE:0:U
+pg_n_tup_c             value:DERIVE:0:U
+pg_n_tup_g             value:GAUGE:0:U
+pg_numbackends         value:GAUGE:0:U
+pg_scan                        value:DERIVE:0:U
+pg_xact                        value:DERIVE:0:U
+ping_droprate          value:GAUGE:0:100
+ping_stddev            value:GAUGE:0:65535
+ping                   value:GAUGE:0:65535
+players                        value:GAUGE:0:1000000
+power                  value:GAUGE:0:U
+pressure                       value:GAUGE:0:U
+protocol_counter       value:DERIVE:0:U
+ps_code                        value:GAUGE:0:9223372036854775807
+ps_count               processes:GAUGE:0:1000000, threads:GAUGE:0:1000000
+ps_cputime             user:DERIVE:0:U, syst:DERIVE:0:U
+ps_data                        value:GAUGE:0:9223372036854775807
+ps_disk_octets         read:DERIVE:0:U, write:DERIVE:0:U
+ps_disk_ops            read:DERIVE:0:U, write:DERIVE:0:U
+ps_pagefaults          minflt:DERIVE:0:U, majflt:DERIVE:0:U
+ps_rss                 value:GAUGE:0:9223372036854775807
+ps_stacksize           value:GAUGE:0:9223372036854775807
+ps_state               value:GAUGE:0:65535
+ps_vm                  value:GAUGE:0:9223372036854775807
+pubsub        value:GAUGE:0:U
+queue_length           value:GAUGE:0:U
+records                        value:GAUGE:0:U
+requests               value:GAUGE:0:U
+response_time          value:GAUGE:0:U
+response_code          value:GAUGE:0:U
+route_etx              value:GAUGE:0:U
+route_metric           value:GAUGE:0:U
+routes                 value:GAUGE:0:U
+segments               value:GAUGE:0:65535
+serial_octets          rx:DERIVE:0:U, tx:DERIVE:0:U
+signal_noise           value:GAUGE:U:0
+signal_power           value:GAUGE:U:0
+signal_quality         value:GAUGE:0:U
+smart_poweron          value:GAUGE:0:U
+smart_powercycles      value:GAUGE:0:U
+smart_badsectors       value:GAUGE:0:U
+smart_temperature      value:GAUGE:-300:300
+smart_attribute         current:GAUGE:0:255, worst:GAUGE:0:255, threshold:GAUGE:0:255, pretty:GAUGE:0:U
+snr                    value:GAUGE:0:U
+spam_check             value:GAUGE:0:U
+spam_score             value:GAUGE:U:U
+spl                    value:GAUGE:U:U
+swap_io                        value:DERIVE:0:U
+swap                   value:GAUGE:0:1099511627776
+tcp_connections                value:GAUGE:0:4294967295
+temperature            value:GAUGE:U:U
+threads                        value:GAUGE:0:U
+time_dispersion                value:GAUGE:-1000000:1000000
+timeleft               value:GAUGE:0:U
+time_offset            value:GAUGE:-1000000:1000000
+total_bytes            value:DERIVE:0:U
+total_connections      value:DERIVE:0:U
+total_objects          value:DERIVE:0:U
+total_operations       value:DERIVE:0:U
+total_requests         value:DERIVE:0:U
+total_sessions         value:DERIVE:0:U
+total_threads          value:DERIVE:0:U
+total_time_in_ms       value:DERIVE:0:U
+total_values           value:DERIVE:0:U
+uptime                 value:GAUGE:0:4294967295
+users                  value:GAUGE:0:65535
+vcl                    value:GAUGE:0:65535
+vcpu                   value:GAUGE:0:U
+virt_cpu_total         value:DERIVE:0:U
+virt_vcpu              value:DERIVE:0:U
+vmpage_action          value:DERIVE:0:U
+vmpage_faults          minflt:DERIVE:0:U, majflt:DERIVE:0:U
+vmpage_io              in:DERIVE:0:U, out:DERIVE:0:U
+vmpage_number          value:GAUGE:0:4294967295
+volatile_changes       value:GAUGE:0:U
+voltage_threshold      value:GAUGE:U:U, threshold:GAUGE:U:U
+voltage                        value:GAUGE:U:U
+vs_memory              value:GAUGE:0:9223372036854775807
+vs_processes           value:GAUGE:0:65535
+vs_threads             value:GAUGE:0:65535
+
+#
+# Legacy types
+# (required for the v5 upgrade target)
+#
+arc_counts             demand_data:COUNTER:0:U, demand_metadata:COUNTER:0:U, prefetch_data:COUNTER:0:U, prefetch_metadata:COUNTER:0:U
+arc_l2_bytes           read:COUNTER:0:U, write:COUNTER:0:U
+arc_l2_size            value:GAUGE:0:U
+arc_ratio              value:GAUGE:0:U
+arc_size               current:GAUGE:0:U, target:GAUGE:0:U, minlimit:GAUGE:0:U, maxlimit:GAUGE:0:U
+mysql_qcache           hits:COUNTER:0:U, inserts:COUNTER:0:U, not_cached:COUNTER:0:U, lowmem_prunes:COUNTER:0:U, queries_in_cache:GAUGE:0:U
+mysql_threads          running:GAUGE:0:U, connected:GAUGE:0:U, cached:GAUGE:0:U, created:COUNTER:0:U
diff --git a/src/types.db.5 b/src/types.db.5
new file mode 100644 (file)
index 0000000..2fd07d5
--- /dev/null
@@ -0,0 +1,200 @@
+.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "TYPES.DB 5"
+.TH TYPES.DB 5 "2015-03-10" "5.4.1.805.g42e4d6c" "collectd"
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+types.db \- Data\-set specifications for the system statistics collection daemon
+collectd
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.Vb 3
+\&  bitrate    value:GAUGE:0:4294967295
+\&  counter    value:COUNTER:U:U
+\&  if_octets  rx:COUNTER:0:4294967295, tx:COUNTER:0:4294967295
+.Ve
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The types.db file contains one line for each data-set specification. Each line
+consists of two fields delimited by spaces and/or horizontal tabs. The first
+field defines the name of the data-set, while the second field defines a list
+of data-source specifications, delimited by spaces and, optionally, a comma
+(\*(L",\*(R") right after each list-entry.
+.PP
+The format of the data-source specification has been inspired by RRDtool's
+data-source specification. Each data-source is defined by a quadruple made up
+of the data-source name, type, minimal and maximal values, delimited by colons
+(\*(L":\*(R"): \fIds-name\fR:\fIds-type\fR:\fImin\fR:\fImax\fR. \fIds-type\fR may be either
+\&\fB\s-1ABSOLUTE\s0\fR, \fB\s-1COUNTER\s0\fR, \fB\s-1DERIVE\s0\fR, or \fB\s-1GAUGE\s0\fR. \fImin\fR and \fImax\fR define the
+range of valid values for
+data stored for this data-source. If \fBU\fR is specified for either the min or
+max value, it will be set to unknown, meaning that no range checks will
+happen. See \fIrrdcreate\fR\|(1) for more details.
+.SH "FILES"
+.IX Header "FILES"
+The location of the types.db file is defined by the \fBTypesDB\fR configuration
+option (see \fIcollectd.conf\fR\|(5)). It defaults to collectd's shared data
+directory, i.\ e. \fI\fIprefix\fI/share/collectd/\fR.
+.SH "CUSTOM TYPES"
+.IX Header "CUSTOM TYPES"
+If you want to specify custom types, you should do so by specifying a custom
+file in addition to the default one (see \s-1FILES\s0) above. You can do that by
+having multiple \fBTypesDB\fR statements in your configuration file or by
+specifying more than one file in one line.
+.PP
+For example:
+.PP
+.Vb 2
+\& TypesDB "/opt/collectd/share/collectd/types.db"
+\& TypesDB "/opt/collectd/etc/types.db.custom"
+.Ve
+.PP
+\&\fBNote\fR: Make sure to make this file available on all systems if you're
+sending values over the network.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fIcollectd\fR\|(1),
+\&\fIcollectd.conf\fR\|(5),
+\&\fIrrdcreate\fR\|(1)
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+\&\fBcollectd\fR has been written by Florian Forster
+<octo\ at\ collectd.org>.
+.PP
+This manpage has been written by Sebastian Harl
+<sh\ at\ tokkee.org>.
diff --git a/src/types.db.pod b/src/types.db.pod
new file mode 100644 (file)
index 0000000..f0af60e
--- /dev/null
@@ -0,0 +1,68 @@
+=encoding UTF-8
+
+=head1 NAME
+
+types.db - Data-set specifications for the system statistics collection daemon
+B<collectd>
+
+=head1 SYNOPSIS
+
+  bitrate    value:GAUGE:0:4294967295
+  counter    value:COUNTER:U:U
+  if_octets  rx:COUNTER:0:4294967295, tx:COUNTER:0:4294967295
+
+=head1 DESCRIPTION
+
+The types.db file contains one line for each data-set specification. Each line
+consists of two fields delimited by spaces and/or horizontal tabs. The first
+field defines the name of the data-set, while the second field defines a list
+of data-source specifications, delimited by spaces and, optionally, a comma
+(",") right after each list-entry.
+
+The format of the data-source specification has been inspired by RRDtool's
+data-source specification. Each data-source is defined by a quadruple made up
+of the data-source name, type, minimal and maximal values, delimited by colons
+(":"): I<ds-name>:I<ds-type>:I<min>:I<max>. I<ds-type> may be either
+B<ABSOLUTE>, B<COUNTER>, B<DERIVE>, or B<GAUGE>. I<min> and I<max> define the
+range of valid values for
+data stored for this data-source. If B<U> is specified for either the min or
+max value, it will be set to unknown, meaning that no range checks will
+happen. See L<rrdcreate(1)> for more details.
+
+=head1 FILES
+
+The location of the types.db file is defined by the B<TypesDB> configuration
+option (see L<collectd.conf(5)>). It defaults to collectd's shared data
+directory, i.E<nbsp>e. F<I<prefix>/share/collectd/>.
+
+=head1 CUSTOM TYPES
+
+If you want to specify custom types, you should do so by specifying a custom
+file in addition to the default one (see L<FILES>) above. You can do that by
+having multiple B<TypesDB> statements in your configuration file or by
+specifying more than one file in one line.
+
+For example:
+
+ TypesDB "/opt/collectd/share/collectd/types.db"
+ TypesDB "/opt/collectd/etc/types.db.custom"
+
+B<Note>: Make sure to make this file available on all systems if you're
+sending values over the network.
+
+=head1 SEE ALSO
+
+L<collectd(1)>,
+L<collectd.conf(5)>,
+L<rrdcreate(1)>
+
+=head1 AUTHOR
+
+B<collectd> has been written by Florian Forster
+E<lt>octoE<nbsp>atE<nbsp>collectd.orgE<gt>.
+
+This manpage has been written by Sebastian Harl
+E<lt>shE<nbsp>atE<nbsp>tokkee.orgE<gt>.
+
+=cut
+
diff --git a/src/unixsock.c b/src/unixsock.c
new file mode 100644 (file)
index 0000000..664c018
--- /dev/null
@@ -0,0 +1,497 @@
+/**
+ * collectd - src/unixsock.c
+ * Copyright (C) 2007,2008  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include "utils_cmd_flush.h"
+#include "utils_cmd_getval.h"
+#include "utils_cmd_getthreshold.h"
+#include "utils_cmd_listval.h"
+#include "utils_cmd_putval.h"
+#include "utils_cmd_putnotif.h"
+
+/* Folks without pthread will need to disable this plugin. */
+#include <pthread.h>
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <grp.h>
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
+#endif
+
+#define US_DEFAULT_PATH LOCALSTATEDIR"/run/"PACKAGE_NAME"-unixsock"
+
+/*
+ * Private variables
+ */
+/* valid configuration file keys */
+static const char *config_keys[] =
+{
+       "SocketFile",
+       "SocketGroup",
+       "SocketPerms",
+       "DeleteSocket"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int loop = 0;
+
+/* socket configuration */
+static int   sock_fd    = -1;
+static char *sock_file  = NULL;
+static char *sock_group = NULL;
+static int   sock_perms = S_IRWXU | S_IRWXG;
+static _Bool delete_socket = 0;
+
+static pthread_t listen_thread = (pthread_t) 0;
+
+/*
+ * Functions
+ */
+static int us_open_socket (void)
+{
+       struct sockaddr_un sa;
+       int status;
+
+       sock_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+       if (sock_fd < 0)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: socket failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       memset (&sa, '\0', sizeof (sa));
+       sa.sun_family = AF_UNIX;
+       sstrncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+                       sizeof (sa.sun_path));
+
+       DEBUG ("unixsock plugin: socket path = %s", sa.sun_path);
+
+       if (delete_socket)
+       {
+               errno = 0;
+               status = unlink (sa.sun_path);
+               if ((status != 0) && (errno != ENOENT))
+               {
+                       char errbuf[1024];
+                       WARNING ("unixsock plugin: Deleting socket file \"%s\" failed: %s",
+                                       sa.sun_path,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+               else if (status == 0)
+               {
+                       INFO ("unixsock plugin: Successfully deleted socket file \"%s\".",
+                                       sa.sun_path);
+               }
+       }
+
+       status = bind (sock_fd, (struct sockaddr *) &sa, sizeof (sa));
+       if (status != 0)
+       {
+               char errbuf[1024];
+               sstrerror (errno, errbuf, sizeof (errbuf));
+               ERROR ("unixsock plugin: bind failed: %s", errbuf);
+               close (sock_fd);
+               sock_fd = -1;
+               return (-1);
+       }
+
+       chmod (sa.sun_path, sock_perms);
+
+       status = listen (sock_fd, 8);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: listen failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (sock_fd);
+               sock_fd = -1;
+               return (-1);
+       }
+
+       do
+       {
+               char *grpname;
+               struct group *g;
+               struct group sg;
+               char grbuf[2048];
+
+               grpname = (sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME;
+               g = NULL;
+
+               status = getgrnam_r (grpname, &sg, grbuf, sizeof (grbuf), &g);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       WARNING ("unixsock plugin: getgrnam_r (%s) failed: %s", grpname,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       break;
+               }
+               if (g == NULL)
+               {
+                       WARNING ("unixsock plugin: No such group: `%s'",
+                                       grpname);
+                       break;
+               }
+
+               if (chown ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+                                       (uid_t) -1, g->gr_gid) != 0)
+               {
+                       char errbuf[1024];
+                       WARNING ("unixsock plugin: chown (%s, -1, %i) failed: %s",
+                                       (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+                                       (int) g->gr_gid,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+       } while (0);
+
+       return (0);
+} /* int us_open_socket */
+
+static void *us_handle_client (void *arg)
+{
+       int fdin;
+       int fdout;
+       FILE *fhin, *fhout;
+
+       fdin = *((int *) arg);
+       free (arg);
+       arg = NULL;
+
+       DEBUG ("unixsock plugin: us_handle_client: Reading from fd #%i", fdin);
+
+       fdout = dup (fdin);
+       if (fdout < 0)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: dup failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (fdin);
+               pthread_exit ((void *) 1);
+       }
+
+       fhin  = fdopen (fdin, "r");
+       if (fhin == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: fdopen failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (fdin);
+               close (fdout);
+               pthread_exit ((void *) 1);
+               return ((void *) 1);
+       }
+
+       fhout = fdopen (fdout, "w");
+       if (fhout == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: fdopen failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               fclose (fhin); /* this closes fdin as well */
+               close (fdout);
+               pthread_exit ((void *) 1);
+               return ((void *) 1);
+       }
+
+       /* change output buffer to line buffered mode */
+       if (setvbuf (fhout, NULL, _IOLBF, 0) != 0)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: setvbuf failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               fclose (fhin);
+               fclose (fhout);
+               pthread_exit ((void *) 1);
+               return ((void *) 0);
+       }
+
+       while (42)
+       {
+               char buffer[1024];
+               char buffer_copy[1024];
+               char *fields[128];
+               int   fields_num;
+               int   len;
+
+               errno = 0;
+               if (fgets (buffer, sizeof (buffer), fhin) == NULL)
+               {
+                       if ((errno == EINTR) || (errno == EAGAIN))
+                               continue;
+
+                       if (errno != 0)
+                       {
+                               char errbuf[1024];
+                               WARNING ("unixsock plugin: failed to read from socket #%i: %s",
+                                               fileno (fhin),
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                       }
+                       break;
+               }
+
+               len = strlen (buffer);
+               while ((len > 0)
+                               && ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r')))
+                       buffer[--len] = '\0';
+
+               if (len == 0)
+                       continue;
+
+               sstrncpy (buffer_copy, buffer, sizeof (buffer_copy));
+
+               fields_num = strsplit (buffer_copy, fields,
+                               sizeof (fields) / sizeof (fields[0]));
+               if (fields_num < 1)
+               {
+                       fprintf (fhout, "-1 Internal error\n");
+                       fclose (fhin);
+                       fclose (fhout);
+                       pthread_exit ((void *) 1);
+                       return ((void *) 1);
+               }
+
+               if (strcasecmp (fields[0], "getval") == 0)
+               {
+                       handle_getval (fhout, buffer);
+               }
+               else if (strcasecmp (fields[0], "getthreshold") == 0)
+               {
+                       handle_getthreshold (fhout, buffer);
+               }
+               else if (strcasecmp (fields[0], "putval") == 0)
+               {
+                       handle_putval (fhout, buffer);
+               }
+               else if (strcasecmp (fields[0], "listval") == 0)
+               {
+                       handle_listval (fhout, buffer);
+               }
+               else if (strcasecmp (fields[0], "putnotif") == 0)
+               {
+                       handle_putnotif (fhout, buffer);
+               }
+               else if (strcasecmp (fields[0], "flush") == 0)
+               {
+                       handle_flush (fhout, buffer);
+               }
+               else
+               {
+                       if (fprintf (fhout, "-1 Unknown command: %s\n", fields[0]) < 0)
+                       {
+                               char errbuf[1024];
+                               WARNING ("unixsock plugin: failed to write to socket #%i: %s",
+                                               fileno (fhout),
+                                               sstrerror (errno, errbuf, sizeof (errbuf)));
+                               break;
+                       }
+               }
+       } /* while (fgets) */
+
+       DEBUG ("unixsock plugin: us_handle_client: Exiting..");
+       fclose (fhin);
+       fclose (fhout);
+
+       pthread_exit ((void *) 0);
+       return ((void *) 0);
+} /* void *us_handle_client */
+
+static void *us_server_thread (void __attribute__((unused)) *arg)
+{
+       int  status;
+       int *remote_fd;
+       pthread_t th;
+       pthread_attr_t th_attr;
+
+       pthread_attr_init (&th_attr);
+       pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
+
+       if (us_open_socket () != 0)
+               pthread_exit ((void *) 1);
+
+       while (loop != 0)
+       {
+               DEBUG ("unixsock plugin: Calling accept..");
+               status = accept (sock_fd, NULL, NULL);
+               if (status < 0)
+               {
+                       char errbuf[1024];
+
+                       if (errno == EINTR)
+                               continue;
+
+                       ERROR ("unixsock plugin: accept failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (sock_fd);
+                       sock_fd = -1;
+                       pthread_attr_destroy (&th_attr);
+                       pthread_exit ((void *) 1);
+               }
+
+               remote_fd = (int *) malloc (sizeof (int));
+               if (remote_fd == NULL)
+               {
+                       char errbuf[1024];
+                       WARNING ("unixsock plugin: malloc failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (status);
+                       continue;
+               }
+               *remote_fd = status;
+
+               DEBUG ("Spawning child to handle connection on fd #%i", *remote_fd);
+
+               status = plugin_thread_create (&th, &th_attr,
+                               us_handle_client, (void *) remote_fd);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       WARNING ("unixsock plugin: pthread_create failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (*remote_fd);
+                       free (remote_fd);
+                       continue;
+               }
+       } /* while (loop) */
+
+       close (sock_fd);
+       sock_fd = -1;
+       pthread_attr_destroy (&th_attr);
+
+       status = unlink ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               NOTICE ("unixsock plugin: unlink (%s) failed: %s",
+                               (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
+
+       return ((void *) 0);
+} /* void *us_server_thread */
+
+static int us_config (const char *key, const char *val)
+{
+       if (strcasecmp (key, "SocketFile") == 0)
+       {
+               char *new_sock_file = strdup (val);
+               if (new_sock_file == NULL)
+                       return (1);
+
+               sfree (sock_file);
+               sock_file = new_sock_file;
+       }
+       else if (strcasecmp (key, "SocketGroup") == 0)
+       {
+               char *new_sock_group = strdup (val);
+               if (new_sock_group == NULL)
+                       return (1);
+
+               sfree (sock_group);
+               sock_group = new_sock_group;
+       }
+       else if (strcasecmp (key, "SocketPerms") == 0)
+       {
+               sock_perms = (int) strtol (val, NULL, 8);
+       }
+       else if (strcasecmp (key, "DeleteSocket") == 0)
+       {
+               if (IS_TRUE (val))
+                       delete_socket = 1;
+               else
+                       delete_socket = 0;
+       }
+       else
+       {
+               return (-1);
+       }
+
+       return (0);
+} /* int us_config */
+
+static int us_init (void)
+{
+       static int have_init = 0;
+
+       int status;
+
+       /* Initialize only once. */
+       if (have_init != 0)
+               return (0);
+       have_init = 1;
+
+       loop = 1;
+
+       status = plugin_thread_create (&listen_thread, NULL,
+                       us_server_thread, NULL);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: pthread_create failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       return (0);
+} /* int us_init */
+
+static int us_shutdown (void)
+{
+       void *ret;
+
+       loop = 0;
+
+       if (listen_thread != (pthread_t) 0)
+       {
+               pthread_kill (listen_thread, SIGTERM);
+               pthread_join (listen_thread, &ret);
+               listen_thread = (pthread_t) 0;
+       }
+
+       plugin_unregister_init ("unixsock");
+       plugin_unregister_shutdown ("unixsock");
+
+       return (0);
+} /* int us_shutdown */
+
+void module_register (void)
+{
+       plugin_register_config ("unixsock", us_config,
+                       config_keys, config_keys_num);
+       plugin_register_init ("unixsock", us_init);
+       plugin_register_shutdown ("unixsock", us_shutdown);
+} /* void module_register (void) */
+
+/* vim: set sw=4 ts=4 sts=4 tw=78 : */
diff --git a/src/uptime.c b/src/uptime.c
new file mode 100644 (file)
index 0000000..345128d
--- /dev/null
@@ -0,0 +1,258 @@
+/**
+ * collectd - src/uptime.c
+ * Copyright (C) 2009  Marco Chiappero
+ *
+ * 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:
+ *   Marco Chiappero <marco at absence.it>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if KERNEL_LINUX
+# define STAT_FILE "/proc/stat"
+/* Using /proc filesystem to retrieve the boot time, Linux only. */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+/* Using kstats chain to retrieve the boot time on Solaris / OpenSolaris systems */
+/* #endif HAVE_LIBKSTAT */
+
+#elif HAVE_SYS_SYSCTL_H
+# include <sys/sysctl.h>
+/* Using sysctl interface to retrieve the boot time on *BSD / Darwin / OS X systems */
+/* #endif HAVE_SYS_SYSCTL_H */
+
+#elif HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+/* Using perfstat_cpu_total to retrive the boot time in AIX */
+/* #endif HAVE_PERFSTAT */
+
+#else
+# error "No applicable input method."
+#endif
+
+/*
+ * Global variables
+ */
+/* boottime always used, no OS distinction */
+static time_t boottime;
+
+#if HAVE_LIBKSTAT
+extern kstat_ctl_t *kc;
+#endif /* #endif HAVE_LIBKSTAT */
+
+static void uptime_submit (gauge_t uptime)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = uptime;
+
+       vl.values = values;
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "uptime", sizeof (vl.plugin));
+       sstrncpy (vl.type, "uptime", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static int uptime_init (void) /* {{{ */
+{
+       /*
+        * On most unix systems the uptime is calculated by looking at the boot
+        * time (stored in unix time, since epoch) and the current one. We are
+        * going to do the same, reading the boot time value while executing
+        * the uptime_init function (there is no need to read, every time the
+        * plugin_read is called, a value that won't change). However, since
+        * uptime_init is run only once, if the function fails in retrieving
+        * the boot time, the plugin is unregistered and there is no chance to
+        * try again later. Nevertheless, this is very unlikely to happen.
+        */
+
+#if KERNEL_LINUX
+       unsigned long starttime;
+       char buffer[1024];
+       int ret;
+       FILE *fh;
+
+       ret = 0;
+
+       fh = fopen (STAT_FILE, "r");
+
+       if (fh == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("uptime plugin: Cannot open "STAT_FILE": %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (fgets (buffer, 1024, fh) != NULL)
+       {
+               /* look for the btime string and read the value */
+               ret = sscanf (buffer, "btime %lu", &starttime);
+               /* avoid further loops if btime has been found and read
+                * correctly (hopefully) */
+               if (ret == 1)
+                       break;
+       }
+
+       fclose (fh);
+
+       /* loop done, check if no value has been found/read */
+       if (ret != 1)
+       {
+               ERROR ("uptime plugin: No value read from "STAT_FILE"");
+               return (-1);
+       }
+
+       boottime = (time_t) starttime;
+
+       if (boottime == 0)
+       {
+               ERROR ("uptime plugin: btime read from "STAT_FILE", "
+                               "but `boottime' is zero!");
+               return (-1);
+       }
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
+       kstat_t *ksp;
+       kstat_named_t *knp;
+
+       ksp = NULL;
+       knp = NULL;
+
+       /* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
+       if (kc == NULL)
+       {
+               ERROR ("uptime plugin: kstat chain control structure not available.");
+               return (-1);
+       }
+
+       ksp = kstat_lookup (kc, "unix", 0, "system_misc");
+       if (ksp == NULL)
+       {
+               ERROR ("uptime plugin: Cannot find unix:0:system_misc kstat.");
+               return (-1);
+       }
+
+       if (kstat_read (kc, ksp, NULL) < 0)
+       {
+               ERROR ("uptime plugin: kstat_read failed.");
+               return (-1);
+       }
+
+       knp = (kstat_named_t *) kstat_data_lookup (ksp, "boot_time");
+       if (knp == NULL)
+       {
+               ERROR ("uptime plugin: kstat_data_lookup (boot_time) failed.");
+               return (-1);
+       }
+
+       boottime = (time_t) knp->value.ui32;
+
+       if (boottime == 0)
+       {
+               ERROR ("uptime plugin: kstat_data_lookup returned success, "
+                       "but `boottime' is zero!");
+               return (-1);
+       }
+/* #endif HAVE_LIBKSTAT */
+
+# elif HAVE_SYS_SYSCTL_H
+       struct timeval boottv;
+       size_t boottv_len;
+       int status;
+
+       int mib[2];
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_BOOTTIME;
+
+       boottv_len = sizeof (boottv);
+       memset (&boottv, 0, boottv_len);
+
+       status = sysctl (mib, STATIC_ARRAY_SIZE (mib), &boottv, &boottv_len,
+                       /* new_value = */ NULL, /* new_length = */ 0);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("uptime plugin: No value read from sysctl interface: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       boottime = boottv.tv_sec;
+
+       if (boottime == 0)
+       {
+               ERROR ("uptime plugin: sysctl(3) returned success, "
+                               "but `boottime' is zero!");
+               return (-1);
+       }
+/* #endif HAVE_SYS_SYSCTL_H */
+
+#elif HAVE_PERFSTAT
+       int status;
+       perfstat_cpu_total_t cputotal;
+       int hertz;
+
+       status = perfstat_cpu_total(NULL, &cputotal,
+               sizeof(perfstat_cpu_total_t), 1);
+       if (status < 0)
+       {
+               char errbuf[1024];
+               ERROR ("uptime plugin: perfstat_cpu_total: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       hertz = sysconf(_SC_CLK_TCK);
+       if (hertz <= 0)
+               hertz = HZ;
+
+       boottime = time(NULL) - cputotal.lbolt / hertz;
+#endif /* HAVE_PERFSTAT */
+
+       return (0);
+} /* }}} int uptime_init */
+
+static int uptime_read (void)
+{
+       gauge_t uptime;
+       time_t elapsed;
+
+       /* calculate the amount of time elapsed since boot, AKA uptime */
+       elapsed = time (NULL) - boottime;
+
+       uptime = (gauge_t) elapsed;
+
+       uptime_submit (uptime);
+
+       return (0);
+}
+
+void module_register (void)
+{
+       plugin_register_init ("uptime", uptime_init);
+       plugin_register_read ("uptime", uptime_read);
+} /* void module_register */
diff --git a/src/users.c b/src/users.c
new file mode 100644 (file)
index 0000000..10f34ee
--- /dev/null
@@ -0,0 +1,132 @@
+/**
+ * collectd - src/users.c
+ * Copyright (C) 2005-2007  Sebastian Harl
+ * Copyright (C) 2005       Niki W. Waibel
+ * Copyright (C) 2005-2007  Florian octo Forster
+ * Copyright (C) 2008       Oleg King 
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Niki W. Waibel <niki.waibel at newlogic.com>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Oleg King <king2 at kaluga.ru>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if HAVE_STATGRAB_H
+# include <statgrab.h>
+#endif /* HAVE_STATGRAB_H */
+
+#if HAVE_UTMPX_H
+# include <utmpx.h>
+/* #endif HAVE_UTMPX_H */
+
+#elif HAVE_UTMP_H
+# include <utmp.h>
+/* #endif HAVE_UTMP_H */
+
+#else
+# error "No applicable input method."
+#endif
+
+static void users_submit (gauge_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "users", sizeof (vl.plugin));
+       sstrncpy (vl.type, "users", sizeof (vl.plugin));
+
+       plugin_dispatch_values (&vl);
+} /* void users_submit */
+
+static int users_read (void)
+{
+#if HAVE_GETUTXENT
+       unsigned int users = 0;
+       struct utmpx *entry = NULL;
+
+       /* according to the *utent(3) man page none of the functions sets errno
+          in case of an error, so we cannot do any error-checking here */
+       setutxent();
+
+       while (NULL != (entry = getutxent())) {
+               if (USER_PROCESS == entry->ut_type) {
+                       ++users;
+               }
+       }
+       endutxent();
+
+       users_submit (users);
+/* #endif HAVE_GETUTXENT */
+       
+#elif HAVE_GETUTENT
+       unsigned int users = 0;
+       struct utmp *entry = NULL;
+
+       /* according to the *utent(3) man page none of the functions sets errno
+          in case of an error, so we cannot do any error-checking here */
+       setutent();
+
+       while (NULL != (entry = getutent())) {
+               if (USER_PROCESS == entry->ut_type) {
+                       ++users;
+               }
+       }
+       endutent();
+
+       users_submit (users);
+/* #endif HAVE_GETUTENT */
+
+#elif HAVE_LIBSTATGRAB
+       sg_user_stats *us;
+
+# if HAVE_LIBSTATGRAB_0_90
+       size_t num_entries;
+       us = sg_get_user_stats (&num_entries);
+# else
+       us = sg_get_user_stats ();
+# endif
+       if (us == NULL)
+               return (-1);   
+
+       users_submit ((gauge_t)
+# if HAVE_LIBSTATGRAB_0_90
+                     num_entries);
+# else
+                     us->num_entries);
+# endif
+/* #endif HAVE_LIBSTATGRAB */
+
+#else
+# error "No applicable input method."
+#endif
+
+       return (0);
+} /* int users_read */
+
+void module_register (void)
+{
+       plugin_register_read ("users", users_read);
+} /* void module_register(void) */
diff --git a/src/utils_cmd_flush.c b/src/utils_cmd_flush.c
new file mode 100644 (file)
index 0000000..089ab70
--- /dev/null
@@ -0,0 +1,189 @@
+/**
+ * collectd - src/utils_cmd_flush.c
+ * Copyright (C) 2008       Sebastian Harl
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Sebastian "tokkee" Harl <sh at tokkee.org>
+ *   Florian "octo" Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_parse_option.h"
+
+#define print_to_socket(fh, ...) \
+       do { \
+               if (fprintf (fh, __VA_ARGS__) < 0) { \
+                       char errbuf[1024]; \
+                       WARNING ("handle_flush: failed to write to socket #%i: %s", \
+                                       fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+                       return -1; \
+               } \
+               fflush(fh); \
+       } while (0)
+
+static int add_to_array (char ***array, int *array_num, char *value)
+{
+       char **temp;
+
+       temp = (char **) realloc (*array, sizeof (char *) * (*array_num + 1));
+       if (temp == NULL)
+               return (-1);
+
+       *array = temp;
+       (*array)[*array_num] = value;
+       (*array_num)++;
+
+       return (0);
+} /* int add_to_array */
+
+int handle_flush (FILE *fh, char *buffer)
+{
+       int success = 0;
+       int error   = 0;
+
+       double timeout = 0.0;
+       char **plugins = NULL;
+       int plugins_num = 0;
+       char **identifiers = NULL;
+       int identifiers_num = 0;
+
+       int i;
+
+       if ((fh == NULL) || (buffer == NULL))
+               return (-1);
+
+       DEBUG ("utils_cmd_flush: handle_flush (fh = %p, buffer = %s);",
+                       (void *) fh, buffer);
+
+       if (strncasecmp ("FLUSH", buffer, strlen ("FLUSH")) != 0)
+       {
+               print_to_socket (fh, "-1 Cannot parse command.\n");
+               return (-1);
+       }
+       buffer += strlen ("FLUSH");
+
+       while (*buffer != 0)
+       {
+               char *opt_key;
+               char *opt_value;
+               int status;
+
+               opt_key = NULL;
+               opt_value = NULL;
+               status = parse_option (&buffer, &opt_key, &opt_value);
+               if (status != 0)
+               {
+                       print_to_socket (fh, "-1 Parsing options failed.\n");
+                       sfree (plugins);
+                       sfree (identifiers);
+                       return (-1);
+               }
+
+               if (strcasecmp ("plugin", opt_key) == 0)
+               {
+                       add_to_array (&plugins, &plugins_num, opt_value);
+               }
+               else if (strcasecmp ("identifier", opt_key) == 0)
+               {
+                       add_to_array (&identifiers, &identifiers_num, opt_value);
+               }
+               else if (strcasecmp ("timeout", opt_key) == 0)
+               {
+                       char *endptr;
+                       
+                       errno = 0;
+                       endptr = NULL;
+                       timeout = strtod (opt_value, &endptr);
+
+                       if ((endptr == opt_value) || (errno != 0) || (!isfinite (timeout)))
+                       {
+                               print_to_socket (fh, "-1 Invalid value for option `timeout': "
+                                               "%s\n", opt_value);
+                               sfree (plugins);
+                               sfree (identifiers);
+                               return (-1);
+                       }
+                       else if (timeout < 0.0)
+                       {
+                               timeout = 0.0;
+                       }
+               }
+               else
+               {
+                       print_to_socket (fh, "-1 Cannot parse option %s\n", opt_key);
+                       sfree (plugins);
+                       sfree (identifiers);
+                       return (-1);
+               }
+       } /* while (*buffer != 0) */
+
+       /* Add NULL entries for `any plugin' and/or `any value' if nothing was
+        * specified. */
+       if (plugins_num == 0)
+               add_to_array (&plugins, &plugins_num, NULL);
+
+       if (identifiers_num == 0)
+               add_to_array (&identifiers, &identifiers_num, NULL);
+
+       for (i = 0; i < plugins_num; i++)
+       {
+               char *plugin;
+               int j;
+
+               plugin = plugins[i];
+
+               for (j = 0; j < identifiers_num; j++)
+               {
+                       char *identifier;
+                       int status;
+
+                       identifier = identifiers[j];
+                       status = plugin_flush (plugin,
+                                       DOUBLE_TO_CDTIME_T (timeout),
+                                       identifier);
+                       if (status == 0)
+                               success++;
+                       else
+                               error++;
+               }
+       }
+
+       if ((success + error) > 0)
+       {
+               print_to_socket (fh, "0 Done: %i successful, %i errors\n",
+                               success, error);
+       }
+       else
+       {
+               plugin_flush (NULL, DOUBLE_TO_CDTIME_T (timeout), NULL);
+               print_to_socket (fh, "0 Done\n");
+       }
+
+       sfree (plugins);
+       sfree (identifiers);
+       return (0);
+} /* int handle_flush */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/utils_cmd_flush.h b/src/utils_cmd_flush.h
new file mode 100644 (file)
index 0000000..f43b257
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * collectd - src/utils_cmd_flush.h
+ * Copyright (C) 2008       Sebastian Harl
+ *
+ * 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:
+ *   Sebastian "tokkee" Harl <sh at tokkee.org>
+ **/
+
+#ifndef UTILS_CMD_FLUSH_H
+#define UTILS_CMD_FLUSH_H 1
+
+#include <stdio.h>
+
+int handle_flush (FILE *fh, char *buffer);
+
+#endif /* UTILS_CMD_FLUSH_H */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
+
diff --git a/src/utils_cmd_getthreshold.c b/src/utils_cmd_getthreshold.c
new file mode 100644 (file)
index 0000000..80babe3
--- /dev/null
@@ -0,0 +1,184 @@
+/**
+ * collectd - src/utils_cmd_getthreshold.c
+ * Copyright (C) 2008,2009  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_avltree.h"
+#include "utils_threshold.h"
+#include "utils_parse_option.h" /* for `parse_string' */
+#include "utils_cmd_getthreshold.h"
+
+#define print_to_socket(fh, ...) \
+  if (fprintf (fh, __VA_ARGS__) < 0) { \
+    char errbuf[1024]; \
+    WARNING ("handle_getthreshold: failed to write to socket #%i: %s", \
+        fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+    return -1; \
+  }
+
+int handle_getthreshold (FILE *fh, char *buffer)
+{
+  char *command;
+  char *identifier;
+  char *identifier_copy;
+
+  char *host;
+  char *plugin;
+  char *plugin_instance;
+  char *type;
+  char *type_instance;
+
+  value_list_t vl;
+  threshold_t threshold;
+
+  int   status;
+  size_t i;
+
+  if ((fh == NULL) || (buffer == NULL))
+    return (-1);
+
+  DEBUG ("utils_cmd_getthreshold: handle_getthreshold (fh = %p, buffer = %s);",
+      (void *) fh, buffer);
+
+  command = NULL;
+  status = parse_string (&buffer, &command);
+  if (status != 0)
+  {
+    print_to_socket (fh, "-1 Cannot parse command.\n");
+    return (-1);
+  }
+  assert (command != NULL);
+
+  if (strcasecmp ("GETTHRESHOLD", command) != 0)
+  {
+    print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+    return (-1);
+  }
+
+  identifier = NULL;
+  status = parse_string (&buffer, &identifier);
+  if (status != 0)
+  {
+    print_to_socket (fh, "-1 Cannot parse identifier.\n");
+    return (-1);
+  }
+  assert (identifier != NULL);
+
+  if (*buffer != 0)
+  {
+    print_to_socket (fh, "-1 Garbage after end of command: %s\n", buffer);
+    return (-1);
+  }
+
+  /* parse_identifier() modifies its first argument,
+   * returning pointers into it */
+  identifier_copy = sstrdup (identifier);
+
+  status = parse_identifier (identifier_copy, &host,
+      &plugin, &plugin_instance,
+      &type, &type_instance);
+  if (status != 0)
+  {
+    DEBUG ("handle_getthreshold: Cannot parse identifier `%s'.", identifier);
+    print_to_socket (fh, "-1 Cannot parse identifier `%s'.\n", identifier);
+    sfree (identifier_copy);
+    return (-1);
+  }
+
+  memset (&vl, 0, sizeof (vl));
+  sstrncpy (vl.host, host, sizeof (vl.host));
+  sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
+  if (plugin_instance != NULL)
+    sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+  sfree (identifier_copy);
+
+  memset (&threshold, 0, sizeof (threshold));
+  status = ut_search_threshold (&vl, &threshold);
+  if (status == ENOENT)
+  {
+    print_to_socket (fh, "-1 No threshold found for identifier %s\n",
+        identifier);
+    return (0);
+  }
+  else if (status != 0)
+  {
+    print_to_socket (fh, "-1 Error while looking up threshold: %i\n",
+        status);
+    return (-1);
+  }
+
+  /* Lets count the number of lines we'll return. */
+  i = 0;
+  if (threshold.host[0] != 0)            i++;
+  if (threshold.plugin[0] != 0)          i++;
+  if (threshold.plugin_instance[0] != 0) i++;
+  if (threshold.type[0] != 0)            i++;
+  if (threshold.type_instance[0] != 0)   i++;
+  if (threshold.data_source[0] != 0)     i++;
+  if (!isnan (threshold.warning_min))    i++;
+  if (!isnan (threshold.warning_max))    i++;
+  if (!isnan (threshold.failure_min))    i++;
+  if (!isnan (threshold.failure_max))    i++;
+  if (threshold.hysteresis > 0.0)        i++;
+  if (threshold.hits > 1)                i++;
+
+  /* Print the response */
+  print_to_socket (fh, "%zu Threshold found\n", i);
+
+  if (threshold.host[0] != 0)
+    print_to_socket (fh, "Host: %s\n", threshold.host)
+  if (threshold.plugin[0] != 0)
+    print_to_socket (fh, "Plugin: %s\n", threshold.plugin)
+  if (threshold.plugin_instance[0] != 0)
+    print_to_socket (fh, "Plugin Instance: %s\n", threshold.plugin_instance)
+  if (threshold.type[0] != 0)
+    print_to_socket (fh, "Type: %s\n", threshold.type)
+  if (threshold.type_instance[0] != 0)
+    print_to_socket (fh, "Type Instance: %s\n", threshold.type_instance)
+  if (threshold.data_source[0] != 0)
+    print_to_socket (fh, "Data Source: %s\n", threshold.data_source)
+  if (!isnan (threshold.warning_min))
+    print_to_socket (fh, "Warning Min: %g\n", threshold.warning_min)
+  if (!isnan (threshold.warning_max))
+    print_to_socket (fh, "Warning Max: %g\n", threshold.warning_max)
+  if (!isnan (threshold.failure_min))
+    print_to_socket (fh, "Failure Min: %g\n", threshold.failure_min)
+  if (!isnan (threshold.failure_max))
+    print_to_socket (fh, "Failure Max: %g\n", threshold.failure_max)
+  if (threshold.hysteresis > 0.0)
+    print_to_socket (fh, "Hysteresis: %g\n", threshold.hysteresis)
+  if (threshold.hits > 1)
+    print_to_socket (fh, "Hits: %i\n", threshold.hits)
+
+  return (0);
+} /* int handle_getthreshold */
+
+/* vim: set sw=2 sts=2 ts=8 et : */
diff --git a/src/utils_cmd_getthreshold.h b/src/utils_cmd_getthreshold.h
new file mode 100644 (file)
index 0000000..8d581c8
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * collectd - src/utils_cmd_getthreshold.h
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_CMD_GETTHRESHOLD_H
+#define UTILS_CMD_GETTHRESHOLD_H 1
+
+#include <stdio.h>
+
+int handle_getthreshold (FILE *fh, char *buffer);
+
+#endif /* UTILS_CMD_GETTHRESHOLD_H */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/utils_cmd_getval.c b/src/utils_cmd_getval.c
new file mode 100644 (file)
index 0000000..196b45e
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * collectd - src/utils_cmd_getval.c
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_cache.h"
+#include "utils_parse_option.h"
+
+#define print_to_socket(fh, ...) \
+  do { \
+    if (fprintf (fh, __VA_ARGS__) < 0) { \
+      char errbuf[1024]; \
+      WARNING ("handle_getval: failed to write to socket #%i: %s", \
+          fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+      return -1; \
+    } \
+    fflush(fh); \
+  } while (0)
+
+int handle_getval (FILE *fh, char *buffer)
+{
+  char *command;
+  char *identifier;
+  char *identifier_copy;
+
+  char *hostname;
+  char *plugin;
+  char *plugin_instance;
+  char *type;
+  char *type_instance;
+  gauge_t *values;
+  size_t values_num;
+
+  const data_set_t *ds;
+
+  int   status;
+  size_t i;
+
+  if ((fh == NULL) || (buffer == NULL))
+    return (-1);
+
+  DEBUG ("utils_cmd_getval: handle_getval (fh = %p, buffer = %s);",
+      (void *) fh, buffer);
+
+  command = NULL;
+  status = parse_string (&buffer, &command);
+  if (status != 0)
+  {
+    print_to_socket (fh, "-1 Cannot parse command.\n");
+    return (-1);
+  }
+  assert (command != NULL);
+
+  if (strcasecmp ("GETVAL", command) != 0)
+  {
+    print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+    return (-1);
+  }
+
+  identifier = NULL;
+  status = parse_string (&buffer, &identifier);
+  if (status != 0)
+  {
+    print_to_socket (fh, "-1 Cannot parse identifier.\n");
+    return (-1);
+  }
+  assert (identifier != NULL);
+
+  if (*buffer != 0)
+  {
+    print_to_socket (fh, "-1 Garbage after end of command: %s\n", buffer);
+    return (-1);
+  }
+
+  /* parse_identifier() modifies its first argument,
+   * returning pointers into it */
+  identifier_copy = sstrdup (identifier);
+
+  status = parse_identifier (identifier_copy, &hostname,
+      &plugin, &plugin_instance,
+      &type, &type_instance);
+  if (status != 0)
+  {
+    DEBUG ("handle_getval: Cannot parse identifier `%s'.", identifier);
+    print_to_socket (fh, "-1 Cannot parse identifier `%s'.\n", identifier);
+    sfree (identifier_copy);
+    return (-1);
+  }
+
+  ds = plugin_get_ds (type);
+  if (ds == NULL)
+  {
+    DEBUG ("handle_getval: plugin_get_ds (%s) == NULL;", type);
+    print_to_socket (fh, "-1 Type `%s' is unknown.\n", type);
+    sfree (identifier_copy);
+    return (-1);
+  }
+
+  values = NULL;
+  values_num = 0;
+  status = uc_get_rate_by_name (identifier, &values, &values_num);
+  if (status != 0)
+  {
+    print_to_socket (fh, "-1 No such value\n");
+    sfree (identifier_copy);
+    return (-1);
+  }
+
+  if ((size_t) ds->ds_num != values_num)
+  {
+    ERROR ("ds[%s]->ds_num = %i, "
+       "but uc_get_rate_by_name returned %u values.",
+       ds->type, ds->ds_num, (unsigned int) values_num);
+    print_to_socket (fh, "-1 Error reading value from cache.\n");
+    sfree (values);
+    sfree (identifier_copy);
+    return (-1);
+  }
+
+  print_to_socket (fh, "%u Value%s found\n", (unsigned int) values_num,
+      (values_num == 1) ? "" : "s");
+  for (i = 0; i < values_num; i++)
+  {
+    print_to_socket (fh, "%s=", ds->ds[i].name);
+    if (isnan (values[i]))
+    {
+      print_to_socket (fh, "NaN\n");
+    }
+    else
+    {
+      print_to_socket (fh, "%12e\n", values[i]);
+    }
+  }
+
+  sfree (values);
+  sfree (identifier_copy);
+
+  return (0);
+} /* int handle_getval */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/utils_cmd_getval.h b/src/utils_cmd_getval.h
new file mode 100644 (file)
index 0000000..5e12f69
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * collectd - src/utils_cmd_getval.h
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_CMD_GETVAL_H
+#define UTILS_CMD_GETVAL_H 1
+
+#include <stdio.h>
+
+int handle_getval (FILE *fh, char *buffer);
+
+#endif /* UTILS_CMD_GETVAL_H */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/utils_cmd_listval.c b/src/utils_cmd_listval.c
new file mode 100644 (file)
index 0000000..b698388
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * collectd - src/utils_cmd_listval.c
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_cmd_listval.h"
+#include "utils_cache.h"
+#include "utils_parse_option.h"
+
+#define free_everything_and_return(status) do { \
+    size_t j; \
+    for (j = 0; j < number; j++) { \
+      sfree(names[j]); \
+      names[j] = NULL; \
+    } \
+    sfree(names); \
+    sfree(times); \
+    return (status); \
+  } while (0)
+
+#define print_to_socket(fh, ...) \
+  do { \
+    if (fprintf (fh, __VA_ARGS__) < 0) { \
+      char errbuf[1024]; \
+      WARNING ("handle_listval: failed to write to socket #%i: %s", \
+          fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+      free_everything_and_return (-1); \
+    } \
+    fflush(fh); \
+  } while (0)
+
+int handle_listval (FILE *fh, char *buffer)
+{
+  char *command;
+  char **names = NULL;
+  cdtime_t *times = NULL;
+  size_t number = 0;
+  size_t i;
+  int status;
+
+  DEBUG ("utils_cmd_listval: handle_listval (fh = %p, buffer = %s);",
+      (void *) fh, buffer);
+
+  command = NULL;
+  status = parse_string (&buffer, &command);
+  if (status != 0)
+  {
+    print_to_socket (fh, "-1 Cannot parse command.\n");
+    free_everything_and_return (-1);
+  }
+  assert (command != NULL);
+
+  if (strcasecmp ("LISTVAL", command) != 0)
+  {
+    print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+    free_everything_and_return (-1);
+  }
+
+  if (*buffer != 0)
+  {
+    print_to_socket (fh, "-1 Garbage after end of command: %s\n", buffer);
+    free_everything_and_return (-1);
+  }
+
+  status = uc_get_names (&names, &times, &number);
+  if (status != 0)
+  {
+    DEBUG ("command listval: uc_get_names failed with status %i", status);
+    print_to_socket (fh, "-1 uc_get_names failed.\n");
+    free_everything_and_return (-1);
+  }
+
+  print_to_socket (fh, "%i Value%s found\n",
+      (int) number, (number == 1) ? "" : "s");
+  for (i = 0; i < number; i++)
+    print_to_socket (fh, "%.3f %s\n", CDTIME_T_TO_DOUBLE (times[i]),
+               names[i]);
+
+  free_everything_and_return (0);
+} /* int handle_listval */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/utils_cmd_listval.h b/src/utils_cmd_listval.h
new file mode 100644 (file)
index 0000000..fc125bc
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * collectd - src/utils_cmd_listval.h
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_CMD_LISTVAL_H
+#define UTILS_CMD_LISTVAL_H 1
+
+#include <stdio.h>
+
+int handle_listval (FILE *fh, char *buffer);
+
+#endif /* UTILS_CMD_LISTVAL_H */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/utils_cmd_putnotif.c b/src/utils_cmd_putnotif.c
new file mode 100644 (file)
index 0000000..530d153
--- /dev/null
@@ -0,0 +1,196 @@
+/**
+ * collectd - src/utils_cmd_putnotif.c
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_parse_option.h"
+
+#define print_to_socket(fh, ...) \
+  do { \
+    if (fprintf (fh, __VA_ARGS__) < 0) { \
+      char errbuf[1024]; \
+      WARNING ("handle_putnotif: failed to write to socket #%i: %s", \
+          fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+      return -1; \
+    } \
+    fflush(fh); \
+  } while (0)
+
+static int set_option_severity (notification_t *n, const char *value)
+{
+  if (strcasecmp (value, "Failure") == 0)
+    n->severity = NOTIF_FAILURE;
+  else if (strcasecmp (value, "Warning") == 0)
+    n->severity = NOTIF_WARNING;
+  else if (strcasecmp (value, "Okay") == 0)
+    n->severity = NOTIF_OKAY;
+  else
+    return (-1);
+
+  return (0);
+} /* int set_option_severity */
+
+static int set_option_time (notification_t *n, const char *value)
+{
+  char *endptr = NULL;
+  double tmp;
+
+  errno = 0;
+  tmp = strtod (value, &endptr);
+  if ((errno != 0)         /* Overflow */
+      || (endptr == value) /* Invalid string */
+      || (endptr == NULL)  /* This should not happen */
+      || (*endptr != 0))   /* Trailing chars */
+    return (-1);
+
+  n->time = DOUBLE_TO_CDTIME_T (tmp);
+
+  return (0);
+} /* int set_option_time */
+
+static int set_option (notification_t *n, const char *option, const char *value)
+{
+  if ((n == NULL) || (option == NULL) || (value == NULL))
+    return (-1);
+
+  DEBUG ("utils_cmd_putnotif: set_option (option = %s, value = %s);",
+      option, value);
+
+  /* Add a meta option in the form: <type>:<key> */
+  if (option[0] != '\0' && option[1] == ':') {
+    /* Refuse empty key */
+    if (option[2] == '\0')
+      return (1);
+
+    if (option[0] == 's')
+      return plugin_notification_meta_add_string (n, option + 2, value);
+    else
+      return (1);
+  }
+
+  if (strcasecmp ("severity", option) == 0)
+    return (set_option_severity (n, value));
+  else if (strcasecmp ("time", option) == 0)
+    return (set_option_time (n, value));
+  else if (strcasecmp ("message", option) == 0)
+    sstrncpy (n->message, value, sizeof (n->message));
+  else if (strcasecmp ("host", option) == 0)
+    sstrncpy (n->host, value, sizeof (n->host));
+  else if (strcasecmp ("plugin", option) == 0)
+    sstrncpy (n->plugin, value, sizeof (n->plugin));
+  else if (strcasecmp ("plugin_instance", option) == 0)
+    sstrncpy (n->plugin_instance, value, sizeof (n->plugin_instance));
+  else if (strcasecmp ("type", option) == 0)
+    sstrncpy (n->type, value, sizeof (n->type));
+  else if (strcasecmp ("type_instance", option) == 0)
+    sstrncpy (n->type_instance, value, sizeof (n->type_instance));
+  else
+    return (1);
+
+  return (0);
+} /* int set_option */
+
+int handle_putnotif (FILE *fh, char *buffer)
+{
+  char *command;
+  notification_t n;
+  int status;
+
+  if ((fh == NULL) || (buffer == NULL))
+    return (-1);
+
+  DEBUG ("utils_cmd_putnotif: handle_putnotif (fh = %p, buffer = %s);",
+      (void *) fh, buffer);
+
+  command = NULL;
+  status = parse_string (&buffer, &command);
+  if (status != 0)
+  {
+    print_to_socket (fh, "-1 Cannot parse command.\n");
+    return (-1);
+  }
+  assert (command != NULL);
+
+  if (strcasecmp ("PUTNOTIF", command) != 0)
+  {
+    print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+    return (-1);
+  }
+
+  memset (&n, '\0', sizeof (n));
+
+  status = 0;
+  while (*buffer != 0)
+  {
+    char *key;
+    char *value;
+
+    status = parse_option (&buffer, &key, &value);
+    if (status != 0)
+    {
+      print_to_socket (fh, "-1 Malformed option.\n");
+      break;
+    }
+
+    status = set_option (&n, key, value);
+    if (status != 0)
+    {
+      print_to_socket (fh, "-1 Error parsing option `%s'\n", key);
+      break;
+    }
+  } /* for (i) */
+
+  /* Check for required fields and complain if anything is missing. */
+  if ((status == 0) && (n.severity == 0))
+  {
+    print_to_socket (fh, "-1 Option `severity' missing.\n");
+    status = -1;
+  }
+  if ((status == 0) && (n.time == 0))
+  {
+    print_to_socket (fh, "-1 Option `time' missing.\n");
+    status = -1;
+  }
+  if ((status == 0) && (strlen (n.message) == 0))
+  {
+    print_to_socket (fh, "-1 No message or message of length 0 given.\n");
+    status = -1;
+  }
+
+  /* If status is still zero the notification is fine and we can finally
+   * dispatch it. */
+  if (status == 0)
+  {
+    plugin_dispatch_notification (&n);
+    print_to_socket (fh, "0 Success\n");
+  }
+
+  return (0);
+} /* int handle_putnotif */
+
+/* vim: set shiftwidth=2 softtabstop=2 tabstop=8 : */
diff --git a/src/utils_cmd_putnotif.h b/src/utils_cmd_putnotif.h
new file mode 100644 (file)
index 0000000..9d699ec
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * collectd - src/utils_cmd_putnotif.h
+ * Copyright (C) 2008       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_CMD_PUTNOTIF_H
+#define UTILS_CMD_PUTNOTIF_H 1
+
+#include <stdio.h>
+
+int handle_putnotif (FILE *fh, char *buffer);
+
+/* vim: set shiftwidth=2 softtabstop=2 tabstop=8 : */
+
+#endif /* UTILS_CMD_PUTNOTIF_H */
diff --git a/src/utils_cmd_putval.c b/src/utils_cmd_putval.c
new file mode 100644 (file)
index 0000000..c717f0b
--- /dev/null
@@ -0,0 +1,265 @@
+/**
+ * collectd - src/utils_cmd_putval.c
+ * Copyright (C) 2007-2009  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include "utils_parse_option.h"
+
+#define print_to_socket(fh, ...) \
+    do { \
+        if (fprintf (fh, __VA_ARGS__) < 0) { \
+            char errbuf[1024]; \
+            WARNING ("handle_putval: failed to write to socket #%i: %s", \
+                    fileno (fh), sstrerror (errno, errbuf, sizeof (errbuf))); \
+            return -1; \
+        } \
+        fflush(fh); \
+    } while (0)
+
+static int dispatch_values (const data_set_t *ds, value_list_t *vl,
+               FILE *fh, char *buffer)
+{
+       int status;
+
+       status = parse_values (buffer, vl, ds);
+       if (status != 0)
+       {
+               print_to_socket (fh, "-1 Parsing the values string failed.\n");
+               return (-1);
+       }
+
+       plugin_dispatch_values (vl);
+       return (0);
+} /* int dispatch_values */
+
+static int set_option (value_list_t *vl, const char *key, const char *value)
+{
+       if ((vl == NULL) || (key == NULL) || (value == NULL))
+               return (-1);
+
+       if (strcasecmp ("interval", key) == 0)
+       {
+               double tmp;
+               char *endptr;
+
+               endptr = NULL;
+               errno = 0;
+               tmp = strtod (value, &endptr);
+
+               if ((errno == 0) && (endptr != NULL)
+                               && (endptr != value) && (tmp > 0.0))
+                       vl->interval = DOUBLE_TO_CDTIME_T (tmp);
+       }
+       else
+               return (1);
+
+       return (0);
+} /* int parse_option */
+
+int handle_putval (FILE *fh, char *buffer)
+{
+       char *command;
+       char *identifier;
+       char *hostname;
+       char *plugin;
+       char *plugin_instance;
+       char *type;
+       char *type_instance;
+       int   status;
+       int   values_submitted;
+
+       char *identifier_copy;
+
+       const data_set_t *ds;
+       value_list_t vl = VALUE_LIST_INIT;
+
+       DEBUG ("utils_cmd_putval: handle_putval (fh = %p, buffer = %s);",
+                       (void *) fh, buffer);
+
+       command = NULL;
+       status = parse_string (&buffer, &command);
+       if (status != 0)
+       {
+               print_to_socket (fh, "-1 Cannot parse command.\n");
+               return (-1);
+       }
+       assert (command != NULL);
+
+       if (strcasecmp ("PUTVAL", command) != 0)
+       {
+               print_to_socket (fh, "-1 Unexpected command: `%s'.\n", command);
+               return (-1);
+       }
+
+       identifier = NULL;
+       status = parse_string (&buffer, &identifier);
+       if (status != 0)
+       {
+               print_to_socket (fh, "-1 Cannot parse identifier.\n");
+               return (-1);
+       }
+       assert (identifier != NULL);
+
+       /* parse_identifier() modifies its first argument,
+        * returning pointers into it */
+       identifier_copy = sstrdup (identifier);
+
+       status = parse_identifier (identifier_copy, &hostname,
+                       &plugin, &plugin_instance,
+                       &type, &type_instance);
+       if (status != 0)
+       {
+               DEBUG ("handle_putval: Cannot parse identifier `%s'.",
+                               identifier);
+               print_to_socket (fh, "-1 Cannot parse identifier `%s'.\n",
+                               identifier);
+               sfree (identifier_copy);
+               return (-1);
+       }
+
+       if ((strlen (hostname) >= sizeof (vl.host))
+                       || (strlen (plugin) >= sizeof (vl.plugin))
+                       || ((plugin_instance != NULL)
+                               && (strlen (plugin_instance) >= sizeof (vl.plugin_instance)))
+                       || ((type_instance != NULL)
+                               && (strlen (type_instance) >= sizeof (vl.type_instance))))
+       {
+               print_to_socket (fh, "-1 Identifier too long.\n");
+               sfree (identifier_copy);
+               return (-1);
+       }
+
+       sstrncpy (vl.host, hostname, sizeof (vl.host));
+       sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (plugin_instance != NULL)
+               sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       ds = plugin_get_ds (type);
+       if (ds == NULL) {
+               print_to_socket (fh, "-1 Type `%s' isn't defined.\n", type);
+               sfree (identifier_copy);
+               return (-1);
+       }
+
+       /* Free identifier_copy */
+       hostname = NULL;
+       plugin = NULL; plugin_instance = NULL;
+       type = NULL;   type_instance = NULL;
+       sfree (identifier_copy);
+
+       vl.values_len = ds->ds_num;
+       vl.values = (value_t *) malloc (vl.values_len * sizeof (value_t));
+       if (vl.values == NULL)
+       {
+               print_to_socket (fh, "-1 malloc failed.\n");
+               return (-1);
+       }
+
+       /* All the remaining fields are part of the optionlist. */
+       values_submitted = 0;
+       while (*buffer != 0)
+       {
+               char *string = NULL;
+               char *value  = NULL;
+
+               status = parse_option (&buffer, &string, &value);
+               if (status < 0)
+               {
+                       /* parse_option failed, buffer has been modified.
+                        * => we need to abort */
+                       print_to_socket (fh, "-1 Misformatted option.\n");
+                       return (-1);
+               }
+               else if (status == 0)
+               {
+                       assert (string != NULL);
+                       assert (value != NULL);
+                       set_option (&vl, string, value);
+                       continue;
+               }
+               /* else: parse_option but buffer has not been modified. This is
+                * the default if no `=' is found.. */
+
+               status = parse_string (&buffer, &string);
+               if (status != 0)
+               {
+                       print_to_socket (fh, "-1 Misformatted value.\n");
+                       return (-1);
+               }
+               assert (string != NULL);
+
+               status = dispatch_values (ds, &vl, fh, string);
+               if (status != 0)
+               {
+                       /* An error has already been printed. */
+                       return (-1);
+               }
+               values_submitted++;
+       } /* while (*buffer != 0) */
+       /* Done parsing the options. */
+
+       print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
+                       values_submitted,
+                       (values_submitted == 1) ? "value has" : "values have");
+
+       sfree (vl.values); 
+
+       return (0);
+} /* int handle_putval */
+
+int create_putval (char *ret, size_t ret_len, /* {{{ */
+       const data_set_t *ds, const value_list_t *vl)
+{
+       char buffer_ident[6 * DATA_MAX_NAME_LEN];
+       char buffer_values[1024];
+       int status;
+
+       status = FORMAT_VL (buffer_ident, sizeof (buffer_ident), vl);
+       if (status != 0)
+               return (status);
+       escape_string (buffer_ident, sizeof (buffer_ident));
+
+       status = format_values (buffer_values, sizeof (buffer_values),
+                       ds, vl, /* store rates = */ 0);
+       if (status != 0)
+               return (status);
+       escape_string (buffer_values, sizeof (buffer_values));
+
+       ssnprintf (ret, ret_len,
+                       "PUTVAL %s interval=%.3f %s",
+                       buffer_ident,
+                       (vl->interval > 0)
+                       ? CDTIME_T_TO_DOUBLE (vl->interval)
+                       : CDTIME_T_TO_DOUBLE (plugin_get_interval ()),
+                       buffer_values);
+
+       return (0);
+} /* }}} int create_putval */
diff --git a/src/utils_cmd_putval.h b/src/utils_cmd_putval.h
new file mode 100644 (file)
index 0000000..795409e
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * collectd - src/utils_cmd_putval.h
+ * Copyright (C) 2007       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_CMD_PUTVAL_H
+#define UTILS_CMD_PUTVAL_H 1
+
+#include <stdio.h>
+
+#include "plugin.h"
+
+int handle_putval (FILE *fh, char *buffer);
+
+int create_putval (char *ret, size_t ret_len,
+               const data_set_t *ds, const value_list_t *vl);
+
+#endif /* UTILS_CMD_PUTVAL_H */
diff --git a/src/utils_crc32.c b/src/utils_crc32.c
new file mode 100644 (file)
index 0000000..4c6d694
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
+ *  code or tables extracted from it, as desired without restriction.
+ *
+ *  First, the polynomial itself and its table of feedback terms.  The
+ *  polynomial is
+ *  X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ *
+ *  Note that we take it "backwards" and put the highest-order term in
+ *  the lowest-order bit.  The X^32 term is "implied"; the LSB is the
+ *  X^31 term, etc.  The X^0 term (usually shown as "+1") results in
+ *  the MSB being 1
+ *
+ *  Note that the usual hardware shift register implementation, which
+ *  is what we're using (we're merely optimizing it by doing eight-bit
+ *  chunks at a time) shifts bits into the lowest-order term.  In our
+ *  implementation, that means shifting towards the right.  Why do we
+ *  do it this way?  Because the calculated CRC must be transmitted in
+ *  order from highest-order term to lowest-order term.  UARTs transmit
+ *  characters in order from LSB to MSB.  By storing the CRC this way
+ *  we hand it to the UART in the order low-byte to high-byte; the UART
+ *  sends each low-bit to hight-bit; and the result is transmission bit
+ *  by bit from highest- to lowest-order term without requiring any bit
+ *  shuffling on our part.  Reception works similarly
+ *
+ *  The feedback terms table consists of 256, 32-bit entries.  Notes
+ *
+ *      The table can be generated at runtime if desired; code to do so
+ *      is shown later.  It might not be obvious, but the feedback
+ *      terms simply represent the results of eight shift/xor opera
+ *      tions for all combinations of data and CRC register values
+ *
+ *      The values must be right-shifted by eight bits by the "updcrc
+ *      logic; the shift must be unsigned (bring in zeroes).  On some
+ *      hardware you could probably optimize the shift in assembler by
+ *      using byte-swap instructions
+ *      polynomial $edb88320
+ */
+
+#include <sys/types.h>
+
+u_int32_t               crc32_buffer(const u_char *, size_t);
+static unsigned int     crc32_tab[] = {
+       0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+       0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+       0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+       0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+       0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+       0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+       0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+       0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+       0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+       0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+       0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+       0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+       0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+       0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+       0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+       0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+       0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+       0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+       0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+       0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+       0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+       0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+       0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+       0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+       0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+       0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+       0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+       0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+       0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+       0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+       0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+       0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+       0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+       0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+       0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+       0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+       0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+       0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+       0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+       0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+       0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+       0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+       0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+       0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+       0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+       0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+       0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+       0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+       0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+       0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+       0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+       0x2d02ef8dL
+};
+
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+u_int32_t
+crc32_buffer(const u_char *s, size_t len)
+{
+    size_t      i;
+    u_int32_t   ret;
+
+    ret = 0;
+    for (i = 0;  i < len;  i++)
+        ret = crc32_tab[(ret ^ s[i]) & 0xff] ^ (ret >> 8);
+    return ret;
+}
diff --git a/src/utils_crc32.h b/src/utils_crc32.h
new file mode 100644 (file)
index 0000000..822a62b
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+ * collectd - src/utils_crc32.h
+ * Copyright (C) 2014       Pierre-Yves Ritschard
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ */
+
+#ifndef UTILS_CRC32_H
+#define UTILS_CRC32_H 1
+
+u_int32_t               crc32_buffer(const u_char *, size_t);
+
+#endif
diff --git a/src/utils_db_query.c b/src/utils_db_query.c
new file mode 100644 (file)
index 0000000..893d590
--- /dev/null
@@ -0,0 +1,1135 @@
+/**
+ * collectd - src/utils_db_query.c
+ * Copyright (C) 2008,2009  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_db_query.h"
+
+/*
+ * Data types
+ */
+struct udb_result_s; /* {{{ */
+typedef struct udb_result_s udb_result_t;
+struct udb_result_s
+{
+  char    *type;
+  char    *instance_prefix;
+  char   **instances;
+  size_t   instances_num;
+  char   **values;
+  size_t   values_num;
+  char   **metadata;
+  size_t   metadata_num;
+
+  udb_result_t *next;
+}; /* }}} */
+
+struct udb_query_s /* {{{ */
+{
+  char *name;
+  char *statement;
+  void *user_data;
+
+  unsigned int min_version;
+  unsigned int max_version;
+
+  udb_result_t *results;
+}; /* }}} */
+
+struct udb_result_preparation_area_s /* {{{ */
+{
+  const   data_set_t *ds;
+  size_t *instances_pos;
+  size_t *values_pos;
+  size_t *metadata_pos;
+  char  **instances_buffer;
+  char  **values_buffer;
+  char  **metadata_buffer;
+
+  struct udb_result_preparation_area_s *next;
+}; /* }}} */
+typedef struct udb_result_preparation_area_s udb_result_preparation_area_t;
+
+struct udb_query_preparation_area_s /* {{{ */
+{
+  size_t column_num;
+  char *host;
+  char *plugin;
+  char *db_name;
+
+  cdtime_t interval;
+
+  udb_result_preparation_area_t *result_prep_areas;
+}; /* }}} */
+
+/*
+ * Config Private functions
+ */
+static int udb_config_set_string (char **ret_string, /* {{{ */
+    oconfig_item_t *ci)
+{
+  char *string;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("db query utils: The `%s' config option "
+        "needs exactly one string argument.", ci->key);
+    return (-1);
+  }
+
+  string = strdup (ci->values[0].value.string);
+  if (string == NULL)
+  {
+    ERROR ("db query utils: strdup failed.");
+    return (-1);
+  }
+
+  if (*ret_string != NULL)
+    free (*ret_string);
+  *ret_string = string;
+
+  return (0);
+} /* }}} int udb_config_set_string */
+
+static int udb_config_add_string (char ***ret_array, /* {{{ */
+    size_t *ret_array_len, oconfig_item_t *ci)
+{
+  char **array;
+  size_t array_len;
+  int i;
+
+  if (ci->values_num < 1)
+  {
+    WARNING ("db query utils: The `%s' config option "
+        "needs at least one argument.", ci->key);
+    return (-1);
+  }
+
+  for (i = 0; i < ci->values_num; i++)
+  {
+    if (ci->values[i].type != OCONFIG_TYPE_STRING)
+    {
+      WARNING ("db query utils: Argument %i to the `%s' option "
+          "is not a string.", i + 1, ci->key);
+      return (-1);
+    }
+  }
+
+  array_len = *ret_array_len;
+  array = (char **) realloc (*ret_array,
+      sizeof (char *) * (array_len + ci->values_num));
+  if (array == NULL)
+  {
+    ERROR ("db query utils: realloc failed.");
+    return (-1);
+  }
+  *ret_array = array;
+
+  for (i = 0; i < ci->values_num; i++)
+  {
+    array[array_len] = strdup (ci->values[i].value.string);
+    if (array[array_len] == NULL)
+    {
+      ERROR ("db query utils: strdup failed.");
+      *ret_array_len = array_len;
+      return (-1);
+    }
+    array_len++;
+  }
+
+  *ret_array_len = array_len;
+  return (0);
+} /* }}} int udb_config_add_string */
+
+static int udb_config_set_uint (unsigned int *ret_value, /* {{{ */
+    oconfig_item_t *ci)
+{
+  double tmp;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+  {
+    WARNING ("db query utils: The `%s' config option "
+        "needs exactly one numeric argument.", ci->key);
+    return (-1);
+  }
+
+  tmp = ci->values[0].value.number;
+  if ((tmp < 0.0) || (tmp > ((double) UINT_MAX)))
+    return (-ERANGE);
+
+  *ret_value = (unsigned int) (tmp + .5);
+  return (0);
+} /* }}} int udb_config_set_uint */
+
+/*
+ * Result private functions
+ */
+static int udb_result_submit (udb_result_t *r, /* {{{ */
+    udb_result_preparation_area_t *r_area,
+    udb_query_t const *q, udb_query_preparation_area_t *q_area)
+{
+  value_list_t vl = VALUE_LIST_INIT;
+  size_t i;
+  int status;
+
+  assert (r != NULL);
+  assert (r_area->ds != NULL);
+  assert (((size_t) r_area->ds->ds_num) == r->values_num);
+
+  vl.values = (value_t *) calloc (r_area->ds->ds_num, sizeof (value_t));
+  if (vl.values == NULL)
+  {
+    ERROR ("db query utils: malloc failed.");
+    return (-1);
+  }
+  vl.values_len = r_area->ds->ds_num;
+
+  for (i = 0; i < r->values_num; i++)
+  {
+    char *value_str = r_area->values_buffer[i];
+
+    if (0 != parse_value (value_str, &vl.values[i], r_area->ds->ds[i].type))
+    {
+      ERROR ("db query utils: udb_result_submit: Parsing `%s' as %s failed.",
+          value_str, DS_TYPE_TO_STRING (r_area->ds->ds[i].type));
+      errno = EINVAL;
+      return (-1);
+    }
+  }
+
+  if (q_area->interval > 0)
+    vl.interval = q_area->interval;
+
+  sstrncpy (vl.host, q_area->host, sizeof (vl.host));
+  sstrncpy (vl.plugin, q_area->plugin, sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, r->type, sizeof (vl.type));
+
+  /* Set vl.type_instance {{{ */
+  if (r->instances_num <= 0)
+  {
+    if (r->instance_prefix == NULL)
+      vl.type_instance[0] = 0;
+    else
+      sstrncpy (vl.type_instance, r->instance_prefix,
+          sizeof (vl.type_instance));
+  }
+  else /* if ((r->instances_num > 0) */
+  {
+    if (r->instance_prefix == NULL)
+    {
+      strjoin (vl.type_instance, sizeof (vl.type_instance),
+          r_area->instances_buffer, r->instances_num, "-");
+    }
+    else
+    {
+      char tmp[DATA_MAX_NAME_LEN];
+
+      strjoin (tmp, sizeof (tmp), r_area->instances_buffer,
+          r->instances_num, "-");
+      tmp[sizeof (tmp) - 1] = 0;
+
+      snprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
+          r->instance_prefix, tmp);
+    }
+  }
+  vl.type_instance[sizeof (vl.type_instance) - 1] = 0;
+  /* }}} */
+
+  /* Annotate meta data. {{{ */
+  if (r->metadata_num > 0)
+  {
+    vl.meta = meta_data_create ();
+    if (vl.meta == NULL)
+    {
+      ERROR ("db query utils:: meta_data_create failed.");
+      return (-ENOMEM);
+    }
+
+    for (i = 0; i < r->metadata_num; i++)
+    {
+      status = meta_data_add_string (vl.meta, r->metadata[i],
+          r_area->metadata_buffer[i]);
+      if (status != 0)
+      {
+        ERROR ("db query utils:: meta_data_add_string failed.");
+        meta_data_destroy (vl.meta);
+        vl.meta = NULL;
+        return (status);
+      }
+    }
+  }
+  /* }}} */
+
+  plugin_dispatch_values (&vl);
+
+  if (r->metadata_num > 0)
+  {
+    meta_data_destroy (vl.meta);
+    vl.meta = NULL;
+  }
+  sfree (vl.values);
+  return (0);
+} /* }}} void udb_result_submit */
+
+static void udb_result_finish_result (udb_result_t const *r, /* {{{ */
+    udb_result_preparation_area_t *prep_area)
+{
+  if ((r == NULL) || (prep_area == NULL))
+    return;
+
+  prep_area->ds = NULL;
+  sfree (prep_area->instances_pos);
+  sfree (prep_area->values_pos);
+  sfree (prep_area->metadata_pos);
+  sfree (prep_area->instances_buffer);
+  sfree (prep_area->values_buffer);
+  sfree (prep_area->metadata_buffer);
+} /* }}} void udb_result_finish_result */
+
+static int udb_result_handle_result (udb_result_t *r, /* {{{ */
+    udb_query_preparation_area_t *q_area,
+    udb_result_preparation_area_t *r_area,
+    udb_query_t const *q, char **column_values)
+{
+  size_t i;
+
+  assert (r && q_area && r_area);
+
+  for (i = 0; i < r->instances_num; i++)
+    r_area->instances_buffer[i] = column_values[r_area->instances_pos[i]];
+
+  for (i = 0; i < r->values_num; i++)
+    r_area->values_buffer[i] = column_values[r_area->values_pos[i]];
+
+  for (i = 0; i < r->metadata_num; i++)
+    r_area->metadata_buffer[i] = column_values[r_area->metadata_pos[i]];
+
+  return udb_result_submit (r, r_area, q, q_area);
+} /* }}} int udb_result_handle_result */
+
+static int udb_result_prepare_result (udb_result_t const *r, /* {{{ */
+    udb_result_preparation_area_t *prep_area,
+    char **column_names, size_t column_num)
+{
+  size_t i;
+
+  if ((r == NULL) || (prep_area == NULL))
+    return (-EINVAL);
+
+#define BAIL_OUT(status) \
+  prep_area->ds = NULL; \
+  sfree (prep_area->instances_pos); \
+  sfree (prep_area->values_pos); \
+  sfree (prep_area->metadata_pos); \
+  sfree (prep_area->instances_buffer); \
+  sfree (prep_area->values_buffer); \
+  sfree (prep_area->metadata_buffer); \
+  return (status)
+
+  /* Make sure previous preparations are cleaned up. */
+  udb_result_finish_result (r, prep_area);
+  prep_area->instances_pos = NULL;
+  prep_area->values_pos = NULL;
+  prep_area->metadata_pos = NULL;
+
+  /* Read `ds' and check number of values {{{ */
+  prep_area->ds = plugin_get_ds (r->type);
+  if (prep_area->ds == NULL)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: Type `%s' is not "
+        "known by the daemon. See types.db(5) for details.",
+        r->type);
+    BAIL_OUT (-1);
+  }
+
+  if (((size_t) prep_area->ds->ds_num) != r->values_num)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: The type `%s' "
+        "requires exactly %i value%s, but the configuration specifies %zu.",
+        r->type,
+        prep_area->ds->ds_num, (prep_area->ds->ds_num == 1) ? "" : "s",
+        r->values_num);
+    BAIL_OUT (-1);
+  }
+  /* }}} */
+
+  /* Allocate r->instances_pos, r->values_pos, r->metadata_post,
+   * r->instances_buffer, r->values_buffer, and r->metadata_buffer {{{ */
+  if (r->instances_num > 0)
+  {
+    prep_area->instances_pos
+      = (size_t *) calloc (r->instances_num, sizeof (size_t));
+    if (prep_area->instances_pos == NULL)
+    {
+      ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+      BAIL_OUT (-ENOMEM);
+    }
+
+    prep_area->instances_buffer
+      = (char **) calloc (r->instances_num, sizeof (char *));
+    if (prep_area->instances_buffer == NULL)
+    {
+      ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+      BAIL_OUT (-ENOMEM);
+    }
+  } /* if (r->instances_num > 0) */
+
+  prep_area->values_pos
+    = (size_t *) calloc (r->values_num, sizeof (size_t));
+  if (prep_area->values_pos == NULL)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    BAIL_OUT (-ENOMEM);
+  }
+
+  prep_area->values_buffer
+    = (char **) calloc (r->values_num, sizeof (char *));
+  if (prep_area->values_buffer == NULL)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    BAIL_OUT (-ENOMEM);
+  }
+
+  prep_area->metadata_pos
+    = (size_t *) calloc (r->metadata_num, sizeof (size_t));
+  if (prep_area->metadata_pos == NULL)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    BAIL_OUT (-ENOMEM);
+  }
+
+  prep_area->metadata_buffer
+    = (char **) calloc (r->metadata_num, sizeof (char *));
+  if (prep_area->metadata_buffer == NULL)
+  {
+    ERROR ("db query utils: udb_result_prepare_result: malloc failed.");
+    BAIL_OUT (-ENOMEM);
+  }
+
+  /* }}} */
+
+  /* Determine the position of the instance columns {{{ */
+  for (i = 0; i < r->instances_num; i++)
+  {
+    size_t j;
+
+    for (j = 0; j < column_num; j++)
+    {
+      if (strcasecmp (r->instances[i], column_names[j]) == 0)
+      {
+        prep_area->instances_pos[i] = j;
+        break;
+      }
+    }
+
+    if (j >= column_num)
+    {
+      ERROR ("db query utils: udb_result_prepare_result: "
+          "Column `%s' could not be found.",
+          r->instances[i]);
+      BAIL_OUT (-ENOENT);
+    }
+  } /* }}} for (i = 0; i < r->instances_num; i++) */
+
+  /* Determine the position of the value columns {{{ */
+  for (i = 0; i < r->values_num; i++)
+  {
+    size_t j;
+
+    for (j = 0; j < column_num; j++)
+    {
+      if (strcasecmp (r->values[i], column_names[j]) == 0)
+      {
+        prep_area->values_pos[i] = j;
+        break;
+      }
+    }
+
+    if (j >= column_num)
+    {
+      ERROR ("db query utils: udb_result_prepare_result: "
+          "Column `%s' could not be found.",
+          r->values[i]);
+      BAIL_OUT (-ENOENT);
+    }
+  } /* }}} for (i = 0; i < r->values_num; i++) */
+
+  /* Determine the position of the metadata columns {{{ */
+  for (i = 0; i < r->metadata_num; i++)
+  {
+    size_t j;
+
+    for (j = 0; j < column_num; j++)
+    {
+      if (strcasecmp (r->metadata[i], column_names[j]) == 0)
+      {
+        prep_area->metadata_pos[i] = j;
+        break;
+      }
+    }
+
+    if (j >= column_num)
+    {
+      ERROR ("db query utils: udb_result_prepare_result: "
+          "Metadata column `%s' could not be found.",
+          r->values[i]);
+      BAIL_OUT (-ENOENT);
+    }
+  } /* }}} for (i = 0; i < r->metadata_num; i++) */
+
+#undef BAIL_OUT
+  return (0);
+} /* }}} int udb_result_prepare_result */
+
+static void udb_result_free (udb_result_t *r) /* {{{ */
+{
+  size_t i;
+
+  if (r == NULL)
+    return;
+
+  sfree (r->type);
+
+  for (i = 0; i < r->instances_num; i++)
+    sfree (r->instances[i]);
+  sfree (r->instances);
+
+  for (i = 0; i < r->values_num; i++)
+    sfree (r->values[i]);
+  sfree (r->values);
+
+  for (i = 0; i < r->metadata_num; i++)
+    sfree (r->metadata[i]);
+  sfree (r->metadata);
+
+  udb_result_free (r->next);
+
+  sfree (r);
+} /* }}} void udb_result_free */
+
+static int udb_result_create (const char *query_name, /* {{{ */
+    udb_result_t **r_head, oconfig_item_t *ci)
+{
+  udb_result_t *r;
+  int status;
+  int i;
+
+  if (ci->values_num != 0)
+  {
+    WARNING ("db query utils: The `Result' block doesn't accept "
+        "any arguments. Ignoring %i argument%s.",
+        ci->values_num, (ci->values_num == 1) ? "" : "s");
+  }
+
+  r = (udb_result_t *) malloc (sizeof (*r));
+  if (r == NULL)
+  {
+    ERROR ("db query utils: malloc failed.");
+    return (-1);
+  }
+  memset (r, 0, sizeof (*r));
+  r->type = NULL;
+  r->instance_prefix = NULL;
+  r->instances = NULL;
+  r->values = NULL;
+  r->metadata = NULL;
+  r->next = NULL;
+
+  /* Fill the `udb_result_t' structure.. */
+  status = 0;
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Type", child->key) == 0)
+      status = udb_config_set_string (&r->type, child);
+    else if (strcasecmp ("InstancePrefix", child->key) == 0)
+      status = udb_config_set_string (&r->instance_prefix, child);
+    else if (strcasecmp ("InstancesFrom", child->key) == 0)
+      status = udb_config_add_string (&r->instances, &r->instances_num, child);
+    else if (strcasecmp ("ValuesFrom", child->key) == 0)
+      status = udb_config_add_string (&r->values, &r->values_num, child);
+    else if (strcasecmp ("MetadataFrom", child->key) == 0)
+      status = udb_config_add_string (&r->metadata, &r->metadata_num, child);
+    else
+    {
+      WARNING ("db query utils: Query `%s': Option `%s' not allowed here.",
+          query_name, child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Check that all necessary options have been given. */
+  while (status == 0)
+  {
+    if (r->type == NULL)
+    {
+      WARNING ("db query utils: `Type' not given for "
+          "result in query `%s'", query_name);
+      status = -1;
+    }
+    if (r->values == NULL)
+    {
+      WARNING ("db query utils: `ValuesFrom' not given for "
+          "result in query `%s'", query_name);
+      status = -1;
+    }
+
+    break;
+  } /* while (status == 0) */
+
+  if (status != 0)
+  {
+    udb_result_free (r);
+    return (-1);
+  }
+
+  /* If all went well, add this result to the list of results. */
+  if (*r_head == NULL)
+  {
+    *r_head = r;
+  }
+  else
+  {
+    udb_result_t *last;
+
+    last = *r_head;
+    while (last->next != NULL)
+      last = last->next;
+
+    last->next = r;
+  }
+
+  return (0);
+} /* }}} int udb_result_create */
+
+/*
+ * Query private functions
+ */
+void udb_query_free_one (udb_query_t *q) /* {{{ */
+{
+  if (q == NULL)
+    return;
+
+  sfree (q->name);
+  sfree (q->statement);
+
+  udb_result_free (q->results);
+
+  sfree (q);
+} /* }}} void udb_query_free_one */
+
+/*
+ * Query public functions
+ */
+int udb_query_create (udb_query_t ***ret_query_list, /* {{{ */
+    size_t *ret_query_list_len, oconfig_item_t *ci,
+    udb_query_create_callback_t cb)
+{
+  udb_query_t **query_list;
+  size_t        query_list_len;
+
+  udb_query_t *q;
+  int status;
+  int i;
+
+  if ((ret_query_list == NULL) || (ret_query_list_len == NULL))
+    return (-EINVAL);
+  query_list     = *ret_query_list;
+  query_list_len = *ret_query_list_len;
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    WARNING ("db query utils: The `Query' block "
+        "needs exactly one string argument.");
+    return (-1);
+  }
+
+  q = (udb_query_t *) malloc (sizeof (*q));
+  if (q == NULL)
+  {
+    ERROR ("db query utils: malloc failed.");
+    return (-1);
+  }
+  memset (q, 0, sizeof (*q));
+  q->min_version = 0;
+  q->max_version = UINT_MAX;
+
+  status = udb_config_set_string (&q->name, ci);
+  if (status != 0)
+  {
+    sfree (q);
+    return (status);
+  }
+
+  /* Fill the `udb_query_t' structure.. */
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Statement", child->key) == 0)
+      status = udb_config_set_string (&q->statement, child);
+    else if (strcasecmp ("Result", child->key) == 0)
+      status = udb_result_create (q->name, &q->results, child);
+    else if (strcasecmp ("MinVersion", child->key) == 0)
+      status = udb_config_set_uint (&q->min_version, child);
+    else if (strcasecmp ("MaxVersion", child->key) == 0)
+      status = udb_config_set_uint (&q->max_version, child);
+
+    /* Call custom callbacks */
+    else if (cb != NULL)
+    {
+      status = (*cb) (q, child);
+      if (status != 0)
+      {
+        WARNING ("db query utils: The configuration callback failed "
+            "to handle `%s'.", child->key);
+      }
+    }
+    else
+    {
+      WARNING ("db query utils: Query `%s': Option `%s' not allowed here.",
+          q->name, child->key);
+      status = -1;
+    }
+
+    if (status != 0)
+      break;
+  }
+
+  /* Check that all necessary options have been given. */
+  if (status == 0)
+  {
+    if (q->statement == NULL)
+    {
+      WARNING ("db query utils: Query `%s': No `Statement' given.", q->name);
+      status = -1;
+    }
+    if (q->results == NULL)
+    {
+      WARNING ("db query utils: Query `%s': No (valid) `Result' block given.",
+          q->name);
+      status = -1;
+    }
+  } /* if (status == 0) */
+
+  /* If all went well, add this query to the list of queries within the
+   * database structure. */
+  if (status == 0)
+  {
+    udb_query_t **temp;
+
+    temp = (udb_query_t **) realloc (query_list,
+        sizeof (*query_list) * (query_list_len + 1));
+    if (temp == NULL)
+    {
+      ERROR ("db query utils: realloc failed");
+      status = -1;
+    }
+    else
+    {
+      query_list = temp;
+      query_list[query_list_len] = q;
+      query_list_len++;
+    }
+  }
+
+  if (status != 0)
+  {
+    udb_query_free_one (q);
+    return (-1);
+  }
+
+  *ret_query_list     = query_list;
+  *ret_query_list_len = query_list_len;
+
+  return (0);
+} /* }}} int udb_query_create */
+
+void udb_query_free (udb_query_t **query_list, size_t query_list_len) /* {{{ */
+{
+  size_t i;
+
+  if (query_list == NULL)
+    return;
+
+  for (i = 0; i < query_list_len; i++)
+    udb_query_free_one (query_list[i]);
+
+  sfree (query_list);
+} /* }}} void udb_query_free */
+
+int udb_query_pick_from_list_by_name (const char *name, /* {{{ */
+    udb_query_t **src_list, size_t src_list_len,
+    udb_query_t ***dst_list, size_t *dst_list_len)
+{
+  size_t i;
+  int num_added;
+
+  if ((name == NULL) || (src_list == NULL) || (dst_list == NULL)
+      || (dst_list_len == NULL))
+  {
+    ERROR ("db query utils: udb_query_pick_from_list_by_name: "
+        "Invalid argument.");
+    return (-EINVAL);
+  }
+
+  num_added = 0;
+  for (i = 0; i < src_list_len; i++)
+  {
+    udb_query_t **tmp_list;
+    size_t tmp_list_len;
+
+    if (strcasecmp (name, src_list[i]->name) != 0)
+      continue;
+
+    tmp_list_len = *dst_list_len;
+    tmp_list = (udb_query_t **) realloc (*dst_list, (tmp_list_len + 1)
+        * sizeof (udb_query_t *));
+    if (tmp_list == NULL)
+    {
+      ERROR ("db query utils: realloc failed.");
+      return (-ENOMEM);
+    }
+
+    tmp_list[tmp_list_len] = src_list[i];
+    tmp_list_len++;
+
+    *dst_list = tmp_list;
+    *dst_list_len = tmp_list_len;
+
+    num_added++;
+  } /* for (i = 0; i < src_list_len; i++) */
+
+  if (num_added <= 0)
+  {
+    ERROR ("db query utils: Cannot find query `%s'. Make sure the <Query> "
+        "block is above the database definition!",
+        name);
+    return (-ENOENT);
+  }
+  else
+  {
+    DEBUG ("db query utils: Added %i versions of query `%s'.",
+        num_added, name);
+  }
+
+  return (0);
+} /* }}} int udb_query_pick_from_list_by_name */
+
+int udb_query_pick_from_list (oconfig_item_t *ci, /* {{{ */
+    udb_query_t **src_list, size_t src_list_len,
+    udb_query_t ***dst_list, size_t *dst_list_len)
+{
+  const char *name;
+
+  if ((ci == NULL) || (src_list == NULL) || (dst_list == NULL)
+      || (dst_list_len == NULL))
+  {
+    ERROR ("db query utils: udb_query_pick_from_list: "
+        "Invalid argument.");
+    return (-EINVAL);
+  }
+
+  if ((ci->values_num != 1)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING))
+  {
+    ERROR ("db query utils: The `%s' config option "
+        "needs exactly one string argument.", ci->key);
+    return (-1);
+  }
+  name = ci->values[0].value.string;
+
+  return (udb_query_pick_from_list_by_name (name,
+        src_list, src_list_len,
+        dst_list, dst_list_len));
+} /* }}} int udb_query_pick_from_list */
+
+const char *udb_query_get_name (udb_query_t *q) /* {{{ */
+{
+  if (q == NULL)
+    return (NULL);
+
+  return (q->name);
+} /* }}} const char *udb_query_get_name */
+
+const char *udb_query_get_statement (udb_query_t *q) /* {{{ */
+{
+  if (q == NULL)
+    return (NULL);
+
+  return (q->statement);
+} /* }}} const char *udb_query_get_statement */
+
+void udb_query_set_user_data (udb_query_t *q, void *user_data) /* {{{ */
+{
+  if (q == NULL)
+    return;
+
+  q->user_data = user_data;
+} /* }}} void udb_query_set_user_data */
+
+void *udb_query_get_user_data (udb_query_t *q) /* {{{ */
+{
+  if (q == NULL)
+    return (NULL);
+
+  return (q->user_data);
+} /* }}} void *udb_query_get_user_data */
+
+int udb_query_check_version (udb_query_t *q, unsigned int version) /* {{{ */
+{
+  if (q == NULL)
+    return (-EINVAL);
+
+  if ((version < q->min_version) || (version > q->max_version))
+    return (0);
+
+  return (1);
+} /* }}} int udb_query_check_version */
+
+void udb_query_finish_result (udb_query_t const *q, /* {{{ */
+    udb_query_preparation_area_t *prep_area)
+{
+  udb_result_preparation_area_t *r_area;
+  udb_result_t *r;
+
+  if ((q == NULL) || (prep_area == NULL))
+    return;
+
+  prep_area->column_num = 0;
+  sfree (prep_area->host);
+  sfree (prep_area->plugin);
+  sfree (prep_area->db_name);
+
+  prep_area->interval = 0;
+
+  for (r = q->results, r_area = prep_area->result_prep_areas;
+      r != NULL; r = r->next, r_area = r_area->next)
+  {
+    /* this may happen during error conditions of the caller */
+    if (r_area == NULL)
+      break;
+    udb_result_finish_result (r, r_area);
+  }
+} /* }}} void udb_query_finish_result */
+
+int udb_query_handle_result (udb_query_t const *q, /* {{{ */
+    udb_query_preparation_area_t *prep_area, char **column_values)
+{
+  udb_result_preparation_area_t *r_area;
+  udb_result_t *r;
+  int success;
+  int status;
+
+  if ((q == NULL) || (prep_area == NULL))
+    return (-EINVAL);
+
+  if ((prep_area->column_num < 1) || (prep_area->host == NULL)
+      || (prep_area->plugin == NULL) || (prep_area->db_name == NULL))
+  {
+    ERROR ("db query utils: Query `%s': Query is not prepared; "
+        "can't handle result.", q->name);
+    return (-EINVAL);
+  }
+
+#if defined(COLLECT_DEBUG) && COLLECT_DEBUG /* {{{ */
+  do
+  {
+    size_t i;
+
+    for (i = 0; i < prep_area->column_num; i++)
+    {
+      DEBUG ("db query utils: udb_query_handle_result (%s, %s): "
+          "column[%zu] = %s;",
+          prep_area->db_name, q->name, i, column_values[i]);
+    }
+  } while (0);
+#endif /* }}} */
+
+  success = 0;
+  for (r = q->results, r_area = prep_area->result_prep_areas;
+      r != NULL; r = r->next, r_area = r_area->next)
+  {
+    status = udb_result_handle_result (r, prep_area, r_area,
+        q, column_values);
+    if (status == 0)
+      success++;
+  }
+
+  if (success == 0)
+  {
+    ERROR ("db query utils: udb_query_handle_result (%s, %s): "
+        "All results failed.", prep_area->db_name, q->name);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int udb_query_handle_result */
+
+int udb_query_prepare_result (udb_query_t const *q, /* {{{ */
+    udb_query_preparation_area_t *prep_area,
+    const char *host, const char *plugin, const char *db_name,
+    char **column_names, size_t column_num, cdtime_t interval)
+{
+  udb_result_preparation_area_t *r_area;
+  udb_result_t *r;
+  int status;
+
+  if ((q == NULL) || (prep_area == NULL))
+    return (-EINVAL);
+
+  udb_query_finish_result (q, prep_area);
+
+  prep_area->column_num = column_num;
+  prep_area->host = strdup (host);
+  prep_area->plugin = strdup (plugin);
+  prep_area->db_name = strdup (db_name);
+
+  prep_area->interval = interval;
+
+  if ((prep_area->host == NULL) || (prep_area->plugin == NULL)
+      || (prep_area->db_name == NULL))
+  {
+    ERROR ("db query utils: Query `%s': Prepare failed: Out of memory.", q->name);
+    udb_query_finish_result (q, prep_area);
+    return (-ENOMEM);
+  }
+
+#if defined(COLLECT_DEBUG) && COLLECT_DEBUG
+  do
+  {
+    size_t i;
+
+    for (i = 0; i < column_num; i++)
+    {
+      DEBUG ("db query utils: udb_query_prepare_result: "
+          "query = %s; column[%zu] = %s;",
+          q->name, i, column_names[i]);
+    }
+  } while (0);
+#endif
+
+  for (r = q->results, r_area = prep_area->result_prep_areas;
+      r != NULL; r = r->next, r_area = r_area->next)
+  {
+    if (! r_area)
+    {
+      ERROR ("db query utils: Query `%s': Invalid number of result "
+          "preparation areas.", q->name);
+      udb_query_finish_result (q, prep_area);
+      return (-EINVAL);
+    }
+
+    status = udb_result_prepare_result (r, r_area, column_names, column_num);
+    if (status != 0)
+    {
+      udb_query_finish_result (q, prep_area);
+      return (status);
+    }
+  }
+
+  return (0);
+} /* }}} int udb_query_prepare_result */
+
+udb_query_preparation_area_t *
+udb_query_allocate_preparation_area (udb_query_t *q) /* {{{ */
+{
+  udb_query_preparation_area_t   *q_area;
+  udb_result_preparation_area_t **next_r_area;
+  udb_result_t *r;
+
+  q_area = (udb_query_preparation_area_t *)malloc (sizeof (*q_area));
+  if (q_area == NULL)
+    return NULL;
+
+  memset (q_area, 0, sizeof (*q_area));
+
+  next_r_area = &q_area->result_prep_areas;
+  for (r = q->results; r != NULL; r = r->next)
+  {
+    udb_result_preparation_area_t *r_area;
+
+    r_area = (udb_result_preparation_area_t *)malloc (sizeof (*r_area));
+    if (r_area == NULL)
+    {
+      for (r_area = q_area->result_prep_areas;
+          r_area != NULL; r_area = r_area->next)
+      {
+        free (r_area);
+      }
+      free (q_area);
+      return NULL;
+    }
+
+    memset (r_area, 0, sizeof (*r_area));
+
+    *next_r_area = r_area;
+    next_r_area  = &r_area->next;
+  }
+
+  return (q_area);
+} /* }}} udb_query_preparation_area_t *udb_query_allocate_preparation_area */
+
+void
+udb_query_delete_preparation_area (udb_query_preparation_area_t *q_area) /* {{{ */
+{
+  udb_result_preparation_area_t *r_area;
+
+  if (q_area == NULL)
+    return;
+
+  r_area = q_area->result_prep_areas;
+  while (r_area != NULL)
+  {
+    udb_result_preparation_area_t *area = r_area;
+
+    r_area = r_area->next;
+
+    sfree (area->instances_pos);
+    sfree (area->values_pos);
+    sfree (area->instances_buffer);
+    sfree (area->values_buffer);
+    free (area);
+  }
+
+  sfree (q_area->host);
+  sfree (q_area->plugin);
+  sfree (q_area->db_name);
+
+  free (q_area);
+} /* }}} void udb_query_delete_preparation_area */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_db_query.h b/src/utils_db_query.h
new file mode 100644 (file)
index 0000000..08b10bd
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+ * collectd - src/utils_db_query.h
+ * Copyright (C) 2008,2009  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_DB_QUERY_H
+#define UTILS_DB_QUERY_H 1
+
+#include "configfile.h"
+
+/*
+ * Data types
+ */
+struct udb_query_s;
+typedef struct udb_query_s udb_query_t;
+
+struct udb_query_preparation_area_s;
+typedef struct udb_query_preparation_area_s udb_query_preparation_area_t;
+
+typedef int (*udb_query_create_callback_t) (udb_query_t *q,
+    oconfig_item_t *ci);
+
+/* 
+ * Public functions
+ */
+int udb_query_create (udb_query_t ***ret_query_list,
+    size_t *ret_query_list_len, oconfig_item_t *ci,
+    udb_query_create_callback_t cb);
+void udb_query_free (udb_query_t **query_list, size_t query_list_len);
+
+int udb_query_pick_from_list_by_name (const char *name,
+    udb_query_t **src_list, size_t src_list_len,
+    udb_query_t ***dst_list, size_t *dst_list_len);
+int udb_query_pick_from_list (oconfig_item_t *ci,
+    udb_query_t **src_list, size_t src_list_len,
+    udb_query_t ***dst_list, size_t *dst_list_len);
+
+const char *udb_query_get_name (udb_query_t *q);
+const char *udb_query_get_statement (udb_query_t *q);
+
+void  udb_query_set_user_data (udb_query_t *q, void *user_data);
+void *udb_query_get_user_data (udb_query_t *q);
+
+/* 
+ * udb_query_check_version
+ *
+ * Returns 0 if the query is NOT suitable for `version' and >0 if the
+ * query IS suitable.
+ */
+int udb_query_check_version (udb_query_t *q, unsigned int version);
+
+int udb_query_prepare_result (udb_query_t const *q,
+    udb_query_preparation_area_t *prep_area,
+    const char *host, const char *plugin, const char *db_name,
+    char **column_names, size_t column_num, cdtime_t interval);
+int udb_query_handle_result (udb_query_t const *q,
+    udb_query_preparation_area_t *prep_area, char **column_values);
+void udb_query_finish_result (udb_query_t const *q,
+    udb_query_preparation_area_t *prep_area);
+
+udb_query_preparation_area_t *
+udb_query_allocate_preparation_area (udb_query_t *q);
+void
+udb_query_delete_preparation_area (udb_query_preparation_area_t *q_area);
+
+#endif /* UTILS_DB_QUERY_H */
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/utils_dns.c b/src/utils_dns.c
new file mode 100644 (file)
index 0000000..eefde96
--- /dev/null
@@ -0,0 +1,1088 @@
+/*
+ * collectd - src/utils_dns.c
+ * Copyright (C) 2006       Florian octo Forster
+ * Copyright (C) 2002       The Measurement Factory, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of The Measurement Factory nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ *   The Measurement Factory, Inc. <http://www.measurement-factory.com/>
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#define _DEFAULT_SOURCE
+#define _BSD_SOURCE
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#if HAVE_NET_IF_ARP_H
+# include <net/if_arp.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_NET_PPP_DEFS_H
+# include <net/ppp_defs.h>
+#endif
+#if HAVE_NET_IF_PPP_H
+# include <net/if_ppp.h>
+#endif
+
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP6_H
+# include <netinet/ip6.h>
+#endif
+#if HAVE_NETINET_IP_COMPAT_H
+# include <netinet/ip_compat.h>
+#endif
+#if HAVE_NETINET_IF_ETHER_H
+# include <netinet/if_ether.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+#ifdef HAVE_NETINET_IP_VAR_H
+# include <netinet/ip_var.h>
+#endif
+#if HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
+
+#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>
+#endif
+
+#if HAVE_PCAP_H
+# include <pcap.h>
+#endif
+
+#define PCAP_SNAPLEN 1460
+#ifndef ETHER_HDR_LEN
+#define ETHER_ADDR_LEN 6
+#define ETHER_TYPE_LEN 2
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+#endif
+#ifndef ETHERTYPE_8021Q
+# define ETHERTYPE_8021Q 0x8100
+#endif
+#ifndef ETHERTYPE_IPV6
+# define ETHERTYPE_IPV6 0x86DD
+#endif
+
+#ifndef PPP_ADDRESS_VAL
+# define PPP_ADDRESS_VAL 0xff  /* The address byte value */
+#endif
+#ifndef PPP_CONTROL_VAL
+# define PPP_CONTROL_VAL 0x03  /* The control byte value */
+#endif
+
+#if HAVE_STRUCT_UDPHDR_UH_DPORT && HAVE_STRUCT_UDPHDR_UH_SPORT
+# define UDP_DEST uh_dport
+# define UDP_SRC  uh_sport
+#elif HAVE_STRUCT_UDPHDR_DEST && HAVE_STRUCT_UDPHDR_SOURCE
+# define UDP_DEST dest
+# define UDP_SRC  source
+#else
+# error "`struct udphdr' is unusable."
+#endif
+
+#include "utils_dns.h"
+
+/*
+ * Type definitions
+ */
+struct ip_list_s
+{
+    struct in6_addr addr;
+    void *data;
+    struct ip_list_s *next;
+};
+typedef struct ip_list_s ip_list_t;
+
+typedef int (printer)(const char *, ...);
+
+/*
+ * flags/features for non-interactive mode
+ */
+
+#ifndef T_A6
+#define T_A6 38
+#endif
+#ifndef T_SRV
+#define T_SRV 33
+#endif
+
+/*
+ * Global variables
+ */
+int qtype_counts[T_MAX];
+int opcode_counts[OP_MAX];
+int qclass_counts[C_MAX];
+
+#if HAVE_PCAP_H
+static pcap_t *pcap_obj = NULL;
+#endif
+
+static ip_list_t *IgnoreList = NULL;
+
+#if HAVE_PCAP_H
+static void (*Callback) (const rfc1035_header_t *) = NULL;
+
+static int query_count_intvl = 0;
+static int query_count_total = 0;
+# ifdef __OpenBSD__
+static struct bpf_timeval last_ts;
+# else
+static struct timeval last_ts;
+# endif /* __OpenBSD__ */
+#endif /* HAVE_PCAP_H */
+
+static int cmp_in6_addr (const struct in6_addr *a,
+       const struct in6_addr *b)
+{
+    int i;
+
+    assert (sizeof (struct in6_addr) == 16);
+
+    for (i = 0; i < 16; i++)
+       if (a->s6_addr[i] != b->s6_addr[i])
+           break;
+
+    if (i >= 16)
+       return (0);
+
+    return (a->s6_addr[i] > b->s6_addr[i] ? 1 : -1);
+} /* int cmp_addrinfo */
+
+static inline int ignore_list_match (const struct in6_addr *addr)
+{
+    ip_list_t *ptr;
+
+    for (ptr = IgnoreList; ptr != NULL; ptr = ptr->next)
+       if (cmp_in6_addr (addr, &ptr->addr) == 0)
+           return (1);
+    return (0);
+} /* int ignore_list_match */
+
+static void ignore_list_add (const struct in6_addr *addr)
+{
+    ip_list_t *new;
+
+    if (ignore_list_match (addr) != 0)
+       return;
+
+    new = malloc (sizeof (ip_list_t));
+    if (new == NULL)
+    {
+       perror ("malloc");
+       return;
+    }
+
+    memcpy (&new->addr, addr, sizeof (struct in6_addr));
+    new->next = IgnoreList;
+
+    IgnoreList = new;
+} /* void ignore_list_add */
+
+void ignore_list_add_name (const char *name)
+{
+    struct addrinfo *ai_list;
+    struct addrinfo *ai_ptr;
+    struct in6_addr  addr;
+    int status;
+
+    status = getaddrinfo (name, NULL, NULL, &ai_list);
+    if (status != 0)
+       return;
+
+    for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+    {
+       if (ai_ptr->ai_family == AF_INET)
+       {
+           memset (&addr, '\0', sizeof (addr));
+           addr.s6_addr[10] = 0xFF;
+           addr.s6_addr[11] = 0xFF;
+           memcpy (addr.s6_addr + 12, &((struct sockaddr_in *) ai_ptr->ai_addr)->sin_addr, 4);
+
+           ignore_list_add (&addr);
+       }
+       else
+       {
+           ignore_list_add (&((struct sockaddr_in6 *) ai_ptr->ai_addr)->sin6_addr);
+       }
+    } /* for */
+
+    freeaddrinfo (ai_list);
+}
+
+#if HAVE_PCAP_H
+static void in6_addr_from_buffer (struct in6_addr *ia,
+       const void *buf, size_t buf_len,
+       int family)
+{
+    memset (ia, 0, sizeof (struct in6_addr));
+    if ((AF_INET == family) && (sizeof (uint32_t) == buf_len))
+    {
+       ia->s6_addr[10] = 0xFF;
+       ia->s6_addr[11] = 0xFF;
+       memcpy (ia->s6_addr + 12, buf, buf_len);
+    }
+    else if ((AF_INET6 == family) && (sizeof (struct in6_addr) == buf_len))
+    {
+       memcpy (ia, buf, buf_len);
+    }
+} /* void in6_addr_from_buffer */
+
+void dnstop_set_pcap_obj (pcap_t *po)
+{
+       pcap_obj = po;
+}
+
+void dnstop_set_callback (void (*cb) (const rfc1035_header_t *))
+{
+       Callback = cb;
+}
+
+#define RFC1035_MAXLABELSZ 63
+static int
+rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
+)
+{
+    off_t no = 0;
+    unsigned char c;
+    size_t len;
+    static int loop_detect = 0;
+    if (loop_detect > 2)
+       return 4;               /* compression loop */
+    if (ns <= 0)
+       return 4;               /* probably compression loop */
+    do {
+       if ((*off) >= sz)
+           break;
+       c = *(buf + (*off));
+       if (c > 191) {
+           /* blasted compression */
+           int rc;
+           unsigned short s;
+           off_t ptr;
+           memcpy(&s, buf + (*off), sizeof(s));
+           s = ntohs(s);
+           (*off) += sizeof(s);
+           /* Sanity check */
+           if ((*off) >= sz)
+               return 1;       /* message too short */
+           ptr = s & 0x3FFF;
+           /* Make sure the pointer is inside this message */
+           if (ptr >= sz)
+               return 2;       /* bad compression ptr */
+           if (ptr < DNS_MSG_HDR_SZ)
+               return 2;       /* bad compression ptr */
+           loop_detect++;
+           rc = rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no);
+           loop_detect--;
+           return rc;
+       } else if (c > RFC1035_MAXLABELSZ) {
+           /*
+            * "(The 10 and 01 combinations are reserved for future use.)"
+            */
+           return 3;           /* reserved label/compression flags */
+           break;
+       } else {
+           (*off)++;
+           len = (size_t) c;
+           if (len == 0)
+               break;
+           if (len > (ns - 1))
+               len = ns - 1;
+           if ((*off) + len > sz)
+               return 4;       /* message is too short */
+           if (no + len + 1 > ns)
+               return 5;       /* qname would overflow name buffer */
+           memcpy(name + no, buf + (*off), len);
+           (*off) += len;
+           no += len;
+           *(name + (no++)) = '.';
+       }
+    } while (c > 0);
+    if (no > 0)
+       *(name + no - 1) = '\0';
+    /* make sure we didn't allow someone to overflow the name buffer */
+    assert(no <= ns);
+    return 0;
+}
+
+static int
+handle_dns(const char *buf, int len)
+{
+    rfc1035_header_t qh;
+    uint16_t us;
+    off_t offset;
+    char *t;
+    int status;
+
+    /* The DNS header is 12 bytes long */
+    if (len < DNS_MSG_HDR_SZ)
+       return 0;
+
+    memcpy(&us, buf + 0, 2);
+    qh.id = ntohs(us);
+
+    memcpy(&us, buf + 2, 2);
+    us = ntohs(us);
+    qh.qr = (us >> 15) & 0x01;
+    qh.opcode = (us >> 11) & 0x0F;
+    qh.aa = (us >> 10) & 0x01;
+    qh.tc = (us >> 9) & 0x01;
+    qh.rd = (us >> 8) & 0x01;
+    qh.ra = (us >> 7) & 0x01;
+    qh.z  = (us >> 6) & 0x01;
+    qh.ad = (us >> 5) & 0x01;
+    qh.cd = (us >> 4) & 0x01;
+    qh.rcode = us & 0x0F;
+
+    memcpy(&us, buf + 4, 2);
+    qh.qdcount = ntohs(us);
+
+    memcpy(&us, buf + 6, 2);
+    qh.ancount = ntohs(us);
+
+    memcpy(&us, buf + 8, 2);
+    qh.nscount = ntohs(us);
+
+    memcpy(&us, buf + 10, 2);
+    qh.arcount = ntohs(us);
+
+    offset = DNS_MSG_HDR_SZ;
+    memset(qh.qname, '\0', MAX_QNAME_SZ);
+    status = rfc1035NameUnpack(buf, len, &offset, qh.qname, MAX_QNAME_SZ);
+    if (status != 0)
+    {
+       INFO ("utils_dns: handle_dns: rfc1035NameUnpack failed "
+               "with status %i.", status);
+       return 0;
+    }
+    if ('\0' == qh.qname[0])
+       sstrncpy (qh.qname, ".", sizeof (qh.qname));
+    while ((t = strchr(qh.qname, '\n')))
+       *t = ' ';
+    while ((t = strchr(qh.qname, '\r')))
+       *t = ' ';
+    for (t = qh.qname; *t; t++)
+       *t = tolower((int) *t);
+
+    memcpy(&us, buf + offset, 2);
+    qh.qtype = ntohs(us);
+    memcpy(&us, buf + offset + 2, 2);
+    qh.qclass = ntohs(us);
+
+    qh.length = (uint16_t) len;
+
+    /* gather stats */
+    qtype_counts[qh.qtype]++;
+    qclass_counts[qh.qclass]++;
+    opcode_counts[qh.opcode]++;
+
+    if (Callback != NULL)
+           Callback (&qh);
+
+    return 1;
+}
+
+static int
+handle_udp(const struct udphdr *udp, int len)
+{
+    char buf[PCAP_SNAPLEN];
+    if ((ntohs (udp->UDP_DEST) != 53)
+                   && (ntohs (udp->UDP_SRC) != 53))
+       return 0;
+    memcpy(buf, udp + 1, len - sizeof(*udp));
+    if (0 == handle_dns(buf, len - sizeof(*udp)))
+       return 0;
+    return 1;
+}
+
+#if HAVE_NETINET_IP6_H
+static int
+handle_ipv6 (struct ip6_hdr *ipv6, int len)
+{
+    char buf[PCAP_SNAPLEN];
+    unsigned int offset;
+    int nexthdr;
+
+    struct in6_addr c_src_addr;
+    uint16_t payload_len;
+
+    if (0 > len)
+       return (0);
+
+    offset = sizeof (struct ip6_hdr);
+    nexthdr = ipv6->ip6_nxt;
+    c_src_addr = ipv6->ip6_src;
+    payload_len = ntohs (ipv6->ip6_plen);
+
+    if (ignore_list_match (&c_src_addr))
+           return (0);
+
+    /* Parse extension headers. This only handles the standard headers, as
+     * defined in RFC 2460, correctly. Fragments are discarded. */
+    while ((IPPROTO_ROUTING == nexthdr) /* routing header */
+           || (IPPROTO_HOPOPTS == nexthdr) /* Hop-by-Hop options. */
+           || (IPPROTO_FRAGMENT == nexthdr) /* fragmentation header. */
+           || (IPPROTO_DSTOPTS == nexthdr) /* destination options. */
+           || (IPPROTO_AH == nexthdr) /* destination options. */
+           || (IPPROTO_ESP == nexthdr)) /* encapsulating security payload. */
+    {
+       struct ip6_ext ext_hdr;
+       uint16_t ext_hdr_len;
+
+       /* Catch broken packets */
+       if ((offset + sizeof (struct ip6_ext)) > (unsigned int)len)
+           return (0);
+
+       /* Cannot handle fragments. */
+       if (IPPROTO_FRAGMENT == nexthdr)
+           return (0);
+
+       memcpy (&ext_hdr, (char *) ipv6 + offset, sizeof (struct ip6_ext));
+       nexthdr = ext_hdr.ip6e_nxt;
+       ext_hdr_len = (8 * (ntohs (ext_hdr.ip6e_len) + 1));
+
+       /* This header is longer than the packets payload.. WTF? */
+       if (ext_hdr_len > payload_len)
+           return (0);
+
+       offset += ext_hdr_len;
+       payload_len -= ext_hdr_len;
+    } /* while */
+
+    /* Catch broken and empty packets */
+    if (((offset + payload_len) > (unsigned int)len)
+           || (payload_len == 0)
+           || (payload_len > PCAP_SNAPLEN))
+       return (0);
+
+    if (IPPROTO_UDP != nexthdr)
+       return (0);
+
+    memcpy (buf, (char *) ipv6 + offset, payload_len);
+    if (handle_udp ((struct udphdr *) buf, payload_len) == 0)
+       return (0);
+
+    return (1); /* Success */
+} /* int handle_ipv6 */
+/* #endif HAVE_NETINET_IP6_H */
+
+#else /* if !HAVE_NETINET_IP6_H */
+static int
+handle_ipv6 (__attribute__((unused)) void *pkg,
+       __attribute__((unused)) int len)
+{
+    return (0);
+}
+#endif /* !HAVE_NETINET_IP6_H */
+
+static int
+handle_ip(const struct ip *ip, int len)
+{
+    char buf[PCAP_SNAPLEN];
+    int offset = ip->ip_hl << 2;
+    struct in6_addr c_src_addr;
+    struct in6_addr c_dst_addr;
+
+    if (ip->ip_v == 6)
+       return (handle_ipv6 ((void *) ip, len));
+
+    in6_addr_from_buffer (&c_src_addr, &ip->ip_src.s_addr, sizeof (ip->ip_src.s_addr), AF_INET);
+    in6_addr_from_buffer (&c_dst_addr, &ip->ip_dst.s_addr, sizeof (ip->ip_dst.s_addr), AF_INET);
+    if (ignore_list_match (&c_src_addr))
+           return (0);
+    if (IPPROTO_UDP != ip->ip_p)
+       return 0;
+    memcpy(buf, (void *) ip + offset, len - offset);
+    if (0 == handle_udp((struct udphdr *) buf, len - offset))
+       return 0;
+    return 1;
+}
+
+#if HAVE_NET_IF_PPP_H
+static int
+handle_ppp(const u_char * pkt, int len)
+{
+    char buf[PCAP_SNAPLEN];
+    unsigned short us;
+    unsigned short proto;
+    if (len < 2)
+       return 0;
+    if (*pkt == PPP_ADDRESS_VAL && *(pkt + 1) == PPP_CONTROL_VAL) {
+       pkt += 2;               /* ACFC not used */
+       len -= 2;
+    }
+    if (len < 2)
+       return 0;
+    if (*pkt % 2) {
+       proto = *pkt;           /* PFC is used */
+       pkt++;
+       len--;
+    } else {
+       memcpy(&us, pkt, sizeof(us));
+       proto = ntohs(us);
+       pkt += 2;
+       len -= 2;
+    }
+    if (ETHERTYPE_IP != proto && PPP_IP != proto)
+       return 0;
+    memcpy(buf, pkt, len);
+    return handle_ip((struct ip *) buf, len);
+}
+#endif /* HAVE_NET_IF_PPP_H */
+
+static int
+handle_null(const u_char * pkt, int len)
+{
+    unsigned int family;
+    memcpy(&family, pkt, sizeof(family));
+    if (AF_INET != family)
+       return 0;
+    return handle_ip((struct ip *) (pkt + 4), len - 4);
+}
+
+#ifdef DLT_LOOP
+static int
+handle_loop(const u_char * pkt, int len)
+{
+    unsigned int family;
+    memcpy(&family, pkt, sizeof(family));
+    if (AF_INET != ntohl(family))
+       return 0;
+    return handle_ip((struct ip *) (pkt + 4), len - 4);
+}
+
+#endif
+
+#ifdef DLT_RAW
+static int
+handle_raw(const u_char * pkt, int len)
+{
+    return handle_ip((struct ip *) pkt, len);
+}
+
+#endif
+
+static int
+handle_ether(const u_char * pkt, int len)
+{
+    char buf[PCAP_SNAPLEN];
+    struct ether_header *e = (void *) pkt;
+    unsigned short etype = ntohs(e->ether_type);
+    if (len < ETHER_HDR_LEN)
+       return 0;
+    pkt += ETHER_HDR_LEN;
+    len -= ETHER_HDR_LEN;
+    if (ETHERTYPE_8021Q == etype) {
+       etype = ntohs(*(unsigned short *) (pkt + 2));
+       pkt += 4;
+       len -= 4;
+    }
+    if ((ETHERTYPE_IP != etype)
+           && (ETHERTYPE_IPV6 != etype))
+       return 0;
+    memcpy(buf, pkt, len);
+    if (ETHERTYPE_IPV6 == etype)
+       return (handle_ipv6 ((void *) buf, len));
+    else
+       return handle_ip((struct ip *) buf, len);
+}
+
+#ifdef DLT_LINUX_SLL
+static int
+handle_linux_sll (const u_char *pkt, int len)
+{
+    struct sll_header
+    {
+       uint16_t pkt_type;
+       uint16_t dev_type;
+       uint16_t addr_len;
+       uint8_t  addr[8];
+       uint16_t proto_type;
+    } *hdr;
+    uint16_t etype;
+
+    if ((0 > len) || ((unsigned int)len < sizeof (struct sll_header)))
+       return (0);
+
+    hdr  = (struct sll_header *) pkt;
+    pkt  = (u_char *) (hdr + 1);
+    len -= sizeof (struct sll_header);
+
+    etype = ntohs (hdr->proto_type);
+
+    if ((ETHERTYPE_IP != etype)
+           && (ETHERTYPE_IPV6 != etype))
+       return 0;
+
+    if (ETHERTYPE_IPV6 == etype)
+       return (handle_ipv6 ((void *) pkt, len));
+    else
+       return handle_ip((struct ip *) pkt, len);
+}
+#endif /* DLT_LINUX_SLL */
+
+/* public function */
+void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt)
+{
+    int status;
+
+    if (hdr->caplen < ETHER_HDR_LEN)
+       return;
+
+    switch (pcap_datalink (pcap_obj))
+    {
+       case DLT_EN10MB:
+           status = handle_ether (pkt, hdr->caplen);
+           break;
+#if HAVE_NET_IF_PPP_H
+       case DLT_PPP:
+           status = handle_ppp (pkt, hdr->caplen);
+           break;
+#endif
+#ifdef DLT_LOOP
+       case DLT_LOOP:
+           status = handle_loop (pkt, hdr->caplen);
+           break;
+#endif
+#ifdef DLT_RAW
+       case DLT_RAW:
+           status = handle_raw (pkt, hdr->caplen);
+           break;
+#endif
+#ifdef DLT_LINUX_SLL
+       case DLT_LINUX_SLL:
+           status = handle_linux_sll (pkt, hdr->caplen);
+           break;
+#endif
+       case DLT_NULL:
+           status = handle_null (pkt, hdr->caplen);
+           break;
+
+       default:
+           ERROR ("handle_pcap: unsupported data link type %d",
+                   pcap_datalink(pcap_obj));
+           status = 0;
+           break;
+    } /* switch (pcap_datalink(pcap_obj)) */
+
+    if (0 == status)
+       return;
+
+    query_count_intvl++;
+    query_count_total++;
+    last_ts = hdr->ts;
+}
+#endif /* HAVE_PCAP_H */
+
+const char *qtype_str(int t)
+{
+    static char buf[32];
+    switch (t) {
+#if (defined (__NAMESER)) && (__NAMESER >= 19991001)
+           case ns_t_a:        return ("A");
+           case ns_t_ns:       return ("NS");
+           case ns_t_md:       return ("MD");
+           case ns_t_mf:       return ("MF");
+           case ns_t_cname:    return ("CNAME");
+           case ns_t_soa:      return ("SOA");
+           case ns_t_mb:       return ("MB");
+           case ns_t_mg:       return ("MG");
+           case ns_t_mr:       return ("MR");
+           case ns_t_null:     return ("NULL");
+           case ns_t_wks:      return ("WKS");
+           case ns_t_ptr:      return ("PTR");
+           case ns_t_hinfo:    return ("HINFO");
+           case ns_t_minfo:    return ("MINFO");
+           case ns_t_mx:       return ("MX");
+           case ns_t_txt:      return ("TXT");
+           case ns_t_rp:       return ("RP");
+           case ns_t_afsdb:    return ("AFSDB");
+           case ns_t_x25:      return ("X25");
+           case ns_t_isdn:     return ("ISDN");
+           case ns_t_rt:       return ("RT");
+           case ns_t_nsap:     return ("NSAP");
+           case ns_t_nsap_ptr: return ("NSAP-PTR");
+           case ns_t_sig:      return ("SIG");
+           case ns_t_key:      return ("KEY");
+           case ns_t_px:       return ("PX");
+           case ns_t_gpos:     return ("GPOS");
+           case ns_t_aaaa:     return ("AAAA");
+           case ns_t_loc:      return ("LOC");
+           case ns_t_nxt:      return ("NXT");
+           case ns_t_eid:      return ("EID");
+           case ns_t_nimloc:   return ("NIMLOC");
+           case ns_t_srv:      return ("SRV");
+           case ns_t_atma:     return ("ATMA");
+           case ns_t_naptr:    return ("NAPTR");
+           case ns_t_kx:       return ("KX");
+           case ns_t_cert:     return ("CERT");
+           case ns_t_a6:       return ("A6");
+           case ns_t_dname:    return ("DNAME");
+           case ns_t_sink:     return ("SINK");
+           case ns_t_opt:      return ("OPT");
+# if __NAMESER >= 19991006
+           case ns_t_tsig:     return ("TSIG");
+# endif
+           case ns_t_ixfr:     return ("IXFR");
+           case ns_t_axfr:     return ("AXFR");
+           case ns_t_mailb:    return ("MAILB");
+           case ns_t_maila:    return ("MAILA");
+           case ns_t_any:      return ("ANY");
+           case ns_t_zxfr:     return ("ZXFR");
+/* #endif __NAMESER >= 19991006 */
+#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:
+                   ssnprintf (buf, sizeof (buf), "#%i", t);
+                   return (buf);
+    }; /* switch (t) */
+    /* NOTREACHED */
+    return (NULL);
+}
+
+const char *opcode_str (int o)
+{
+    static char buf[30];
+    switch (o) {
+    case 0:
+       return "Query";
+       break;
+    case 1:
+       return "Iquery";
+       break;
+    case 2:
+       return "Status";
+       break;
+    case 4:
+       return "Notify";
+       break;
+    case 5:
+       return "Update";
+       break;
+    default:
+       ssnprintf(buf, sizeof (buf), "Opcode%d", o);
+       return buf;
+    }
+    /* NOTREACHED */
+}
+
+const char *rcode_str (int rcode)
+{
+       static char buf[32];
+       switch (rcode)
+       {
+#if (defined (__NAMESER)) && (__NAMESER >= 19991006)
+               case ns_r_noerror:  return ("NOERROR");
+               case ns_r_formerr:  return ("FORMERR");
+               case ns_r_servfail: return ("SERVFAIL");
+               case ns_r_nxdomain: return ("NXDOMAIN");
+               case ns_r_notimpl:  return ("NOTIMPL");
+               case ns_r_refused:  return ("REFUSED");
+               case ns_r_yxdomain: return ("YXDOMAIN");
+               case ns_r_yxrrset:  return ("YXRRSET");
+               case ns_r_nxrrset:  return ("NXRRSET");
+               case ns_r_notauth:  return ("NOTAUTH");
+               case ns_r_notzone:  return ("NOTZONE");
+               case ns_r_max:      return ("MAX");
+               case ns_r_badsig:   return ("BADSIG");
+               case ns_r_badkey:   return ("BADKEY");
+               case ns_r_badtime:  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:
+                       ssnprintf (buf, sizeof (buf), "RCode%i", rcode);
+                       return (buf);
+       }
+       /* Never reached */
+       return (NULL);
+} /* const char *rcode_str (int rcode) */
+
+#if 0
+static int
+main(int argc, char *argv[])
+{
+    char errbuf[PCAP_ERRBUF_SIZE];
+    int x;
+    struct stat sb;
+    int readfile_state = 0;
+    struct bpf_program fp;
+
+    port53 = htons(53);
+    SubReport = Sources_report;
+    ignore_addr.s_addr = 0;
+    progname = strdup(strrchr(argv[0], '/') ? strchr(argv[0], '/') + 1 : argv[0]);
+    srandom(time(NULL));
+    ResetCounters();
+
+    while ((x = getopt(argc, argv, "ab:f:i:pst")) != -1) {
+       switch (x) {
+       case 'a':
+           anon_flag = 1;
+           break;
+       case 's':
+           sld_flag = 1;
+           break;
+       case 't':
+           nld_flag = 1;
+           break;
+       case 'p':
+           promisc_flag = 0;
+           break;
+       case 'b':
+           bpf_program_str = strdup(optarg);
+           break;
+       case 'i':
+           ignore_addr.s_addr = inet_addr(optarg);
+           break;
+       case 'f':
+           set_filter(optarg);
+           break;
+       default:
+           usage();
+           break;
+       }
+    }
+    argc -= optind;
+    argv += optind;
+
+    if (argc < 1)
+       usage();
+    device = strdup(argv[0]);
+
+    if (0 == stat(device, &sb))
+       readfile_state = 1;
+    if (readfile_state) {
+       pcap_obj = pcap_open_offline(device, errbuf);
+    } else {
+       pcap_obj = pcap_open_live(device, PCAP_SNAPLEN, promisc_flag, 1000, errbuf);
+    }
+    if (NULL == pcap_obj) {
+       fprintf(stderr, "pcap_open_*: %s\n", errbuf);
+       exit(1);
+    }
+
+    if (0 == isatty(1)) {
+       if (0 == readfile_state) {
+           fprintf(stderr, "Non-interactive mode requires savefile argument\n");
+           exit(1);
+       }
+       interactive = 0;
+       print_func = printf;
+    }
+
+    memset(&fp, '\0', sizeof(fp));
+    x = pcap_compile(pcap_obj, &fp, bpf_program_str, 1, 0);
+    if (x < 0) {
+       fprintf(stderr, "pcap_compile failed\n");
+       exit(1);
+    }
+    x = pcap_setfilter(pcap_obj, &fp);
+    if (x < 0) {
+       fprintf(stderr, "pcap_setfilter failed\n");
+       exit(1);
+    }
+
+    /*
+     * non-blocking call added for Mac OS X bugfix.  Sent by Max Horn.
+     * ref http://www.tcpdump.org/lists/workers/2002/09/msg00033.html
+     */
+    x = pcap_setnonblock(pcap_obj, 1, errbuf);
+    if (x < 0) {
+       fprintf(stderr, "pcap_setnonblock failed: %s\n", errbuf);
+       exit(1);
+    }
+
+    switch (pcap_datalink(pcap_obj)) {
+    case DLT_EN10MB:
+       handle_datalink = handle_ether;
+       break;
+#if HAVE_NET_IF_PPP_H
+    case DLT_PPP:
+       handle_datalink = handle_ppp;
+       break;
+#endif
+#ifdef DLT_LOOP
+    case DLT_LOOP:
+       handle_datalink = handle_loop;
+       break;
+#endif
+#ifdef DLT_RAW
+    case DLT_RAW:
+       handle_datalink = handle_raw;
+       break;
+#endif
+    case DLT_NULL:
+       handle_datalink = handle_null;
+       break;
+    default:
+       fprintf(stderr, "unsupported data link type %d\n",
+           pcap_datalink(pcap_obj));
+       return 1;
+       break;
+    }
+    if (interactive) {
+       init_curses();
+       while (0 == Quit) {
+           if (readfile_state < 2) {
+               /*
+                * On some OSes select() might return 0 even when
+                * there are packets to process.  Thus, we always
+                * ignore its return value and just call pcap_dispatch()
+                * anyway.
+                */
+               if (0 == readfile_state)        /* interactive */
+                   pcap_select(pcap_obj, 1, 0);
+               x = pcap_dispatch(pcap_obj, 50, handle_pcap, NULL);
+           }
+           if (0 == x && 1 == readfile_state) {
+               /* block on keyboard until user quits */
+               readfile_state++;
+               nodelay(w, 0);
+           }
+           keyboard();
+           cron_pre();
+           report();
+           cron_post();
+       }
+       endwin();               /* klin, Thu Nov 28 08:56:51 2002 */
+    } else {
+       while (pcap_dispatch(pcap_obj, 50, handle_pcap, NULL))
+               (void) 0;
+       cron_pre();
+       Sources_report(); print_func("\n");
+       Destinatioreport(); print_func("\n");
+       Qtypes_report(); print_func("\n");
+       Opcodes_report(); print_func("\n");
+       Tld_report(); print_func("\n");
+       Sld_report(); print_func("\n");
+       Nld_report(); print_func("\n");
+       SldBySource_report();
+    }
+
+    pcap_close(pcap_obj);
+    return 0;
+} /* static int main(int argc, char *argv[]) */
+#endif
+/*
+ * vim:shiftwidth=4:tabstop=8:softtabstop=4
+ */
diff --git a/src/utils_dns.h b/src/utils_dns.h
new file mode 100644 (file)
index 0000000..83f0ea4
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * collectd - src/utils_dns.h
+ * Copyright (C) 2006       Florian octo Forster
+ * Copyright (C) 2002       The Measurement Factory, Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. Neither the name of The Measurement Factory nor the names of its
+ *    contributors may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ *   The Measurement Factory, Inc. <http://www.measurement-factory.com/>
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#ifndef COLLECTD_UTILS_DNS_H
+#define COLLECTD_UTILS_DNS_H 1
+
+#include "config.h"
+
+#include <arpa/nameser.h>
+#include <stdint.h>
+
+#if HAVE_PCAP_H
+# include <pcap.h>
+#endif
+
+#define DNS_MSG_HDR_SZ 12
+
+#define T_MAX 65536
+#define OP_MAX 16
+#define C_MAX 65536
+#define MAX_QNAME_SZ 512
+
+struct rfc1035_header_s {
+    uint16_t id;
+    unsigned int qr:1;
+    unsigned int opcode:4;
+    unsigned int aa:1;
+    unsigned int tc:1;
+    unsigned int rd:1;
+    unsigned int ra:1;
+    unsigned int z:1;
+    unsigned int ad:1;
+    unsigned int cd:1;
+    unsigned int rcode:4;
+    uint16_t qdcount;
+    uint16_t ancount;
+    uint16_t nscount;
+    uint16_t arcount;
+    uint16_t qtype;
+    uint16_t qclass;
+    char     qname[MAX_QNAME_SZ];
+    uint16_t length;
+};
+typedef struct rfc1035_header_s rfc1035_header_t;
+
+extern int qtype_counts[T_MAX];
+extern int opcode_counts[OP_MAX];
+extern int qclass_counts[C_MAX];
+
+#if HAVE_PCAP_H
+void dnstop_set_pcap_obj (pcap_t *po);
+#endif
+void dnstop_set_callback (void (*cb) (const rfc1035_header_t *));
+
+void ignore_list_add_name (const char *name);
+#if HAVE_PCAP_H
+void handle_pcap (u_char * udata, const struct pcap_pkthdr *hdr, const u_char * pkt);
+#endif
+
+const char *qtype_str(int t);
+const char *opcode_str(int o);
+const char *rcode_str (int r);
+
+#endif /* !COLLECTD_UTILS_DNS_H */
diff --git a/src/utils_fbhash.c b/src/utils_fbhash.c
new file mode 100644 (file)
index 0000000..70b8908
--- /dev/null
@@ -0,0 +1,276 @@
+/**
+ * collectd - src/utils_fbhash.c
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+
+#include <pthread.h>
+
+#include "utils_fbhash.h"
+#include "utils_avltree.h"
+
+struct fbhash_s
+{
+  char *filename;
+  time_t mtime;
+
+  pthread_mutex_t lock;
+  c_avl_tree_t *tree;
+};
+
+/* 
+ * Private functions
+ */
+static void fbh_free_tree (c_avl_tree_t *tree) /* {{{ */
+{
+  int status;
+
+  if (tree == NULL)
+    return;
+
+  while (42)
+  {
+    char *key = NULL;
+    char *value = NULL;
+
+    status = c_avl_pick (tree, (void *) &key, (void *) &value);
+    if (status != 0)
+      break;
+
+    free (key);
+    free (value);
+  }
+
+  c_avl_destroy (tree);
+} /* }}} void fbh_free_tree */
+
+static int fbh_read_file (fbhash_t *h) /* {{{ */
+{
+  FILE *fh;
+  char buffer[4096];
+  struct flock fl;
+  c_avl_tree_t *tree;
+  int status;
+
+  fh = fopen (h->filename, "r");
+  if (fh == NULL)
+    return (-1);
+
+  memset (&fl, 0, sizeof (fl));
+  fl.l_type = F_RDLCK;
+  fl.l_whence = SEEK_SET;
+  fl.l_start = 0;
+  fl.l_len = 0; /* == entire file */
+  /* TODO: Lock file? -> fcntl */
+
+  status = fcntl (fileno (fh), F_SETLK, &fl);
+  if (status != 0)
+  {
+    fclose (fh);
+    return (-1);
+  }
+
+  tree = c_avl_create ((void *) strcmp);
+  if (tree == NULL)
+  {
+    fclose (fh);
+    return (-1);
+  }
+
+  /* Read `fh' into `tree' */
+  while (fgets (buffer, sizeof (buffer), fh) != NULL) /* {{{ */
+  {
+    size_t len;
+    char *key;
+    char *value;
+
+    char *key_copy;
+    char *value_copy;
+
+    buffer[sizeof (buffer) - 1] = 0;
+    len = strlen (buffer);
+
+    /* Remove trailing newline characters. */
+    while ((len > 0)
+        && ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r')))
+    {
+      len--;
+      buffer[len] = 0;
+    }
+
+    /* Seek first non-space character */
+    key = buffer;
+    while ((*key != 0) && isspace ((int) *key))
+      key++;
+
+    /* Skip empty lines and comments */
+    if ((key[0] == 0) || (key[0] == '#'))
+      continue;
+
+    /* Seek first colon */
+    value = strchr (key, ':');
+    if (value == NULL)
+      continue;
+
+    /* Null-terminate `key'. */
+    *value = 0;
+    value++;
+
+    /* Skip leading whitespace */
+    while ((*value != 0) && isspace ((int) *value))
+      value++;
+
+    /* Skip lines without value */
+    if (value[0] == 0)
+      continue;
+
+    key_copy = strdup (key);
+    value_copy = strdup (value);
+
+    if ((key_copy == NULL) || (value_copy == NULL))
+    {
+      free (key_copy);
+      free (value_copy);
+      continue;
+    }
+
+    status = c_avl_insert (tree, key_copy, value_copy);
+    if (status != 0)
+    {
+      free (key_copy);
+      free (value_copy);
+      continue;
+    }
+
+    DEBUG ("utils_fbhash: fbh_read_file: key = %s; value = %s;",
+        key, value);
+  } /* }}} while (fgets) */
+
+  fclose (fh);
+
+  fbh_free_tree (h->tree);
+  h->tree = tree;
+
+  return (0);
+} /* }}} int fbh_read_file */
+
+static int fbh_check_file (fbhash_t *h) /* {{{ */
+{
+  struct stat statbuf;
+  int status;
+
+  memset (&statbuf, 0, sizeof (statbuf));
+
+  status = stat (h->filename, &statbuf);
+  if (status != 0)
+    return (-1);
+
+  if (h->mtime >= statbuf.st_mtime)
+    return (0);
+
+  status = fbh_read_file (h);
+  if (status == 0)
+    h->mtime = statbuf.st_mtime;
+
+  return (status);
+} /* }}} int fbh_check_file */
+
+/* 
+ * Public functions
+ */
+fbhash_t *fbh_create (const char *file) /* {{{ */
+{
+  fbhash_t *h;
+  int status;
+
+  if (file == NULL)
+    return (NULL);
+
+  h = malloc (sizeof (*h));
+  if (h == NULL)
+    return (NULL);
+  memset (h, 0, sizeof (*h));
+
+  h->filename = strdup (file);
+  if (h->filename == NULL)
+  {
+    free (h);
+    return (NULL);
+  }
+
+  h->mtime = 0;
+  pthread_mutex_init (&h->lock, /* attr = */ NULL);
+
+  status = fbh_check_file (h);
+  if (status != 0)
+  {
+    fbh_destroy (h);
+    return (NULL);
+  }
+
+  return (h);
+} /* }}} fbhash_t *fbh_create */
+
+void fbh_destroy (fbhash_t *h) /* {{{ */
+{
+  if (h == NULL)
+    return;
+
+  pthread_mutex_destroy (&h->lock);
+  free (h->filename);
+  fbh_free_tree (h->tree);
+} /* }}} void fbh_destroy */
+
+char *fbh_get (fbhash_t *h, const char *key) /* {{{ */
+{
+  char *value;
+  char *value_copy;
+  int status;
+
+  if ((h == NULL) || (key == NULL))
+    return (NULL);
+
+  value = NULL;
+  value_copy = NULL;
+
+  pthread_mutex_lock (&h->lock);
+
+  /* TODO: Checking this every time may be a bit much..? */
+  fbh_check_file (h);
+
+  status = c_avl_get (h->tree, key, (void *) &value);
+  if (status == 0)
+  {
+    assert (value != NULL);
+    value_copy = strdup (value);
+  }
+
+  pthread_mutex_unlock (&h->lock);
+
+  return (value_copy);
+} /* }}} char *fbh_get */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_fbhash.h b/src/utils_fbhash.h
new file mode 100644 (file)
index 0000000..d9206a0
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * collectd - src/utils_fbhash.h
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_FBHASH_H
+#define UTILS_FBHASH_H 1
+
+/*
+ * File-backed hash
+ *
+ * This module reads a file of the form
+ *   key: value
+ * into a hash, which can then be queried. The file is given to `fbh_create',
+ * the hash is queried using `fbh_get'. If the file is changed during runtime,
+ * it will automatically be re-read.
+ */
+
+struct fbhash_s;
+typedef struct fbhash_s fbhash_t;
+
+fbhash_t *fbh_create (const char *file);
+void fbh_destroy (fbhash_t *h);
+
+/* Returns the value as a newly allocated `char *'. It's the caller's
+ * responsibility to free this memory. */
+char *fbh_get (fbhash_t *h, const char *key);
+
+#endif /* UTILS_FBHASH_H */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_format_graphite.c b/src/utils_format_graphite.c
new file mode 100644 (file)
index 0000000..023f7a4
--- /dev/null
@@ -0,0 +1,258 @@
+/**
+ * collectd - src/utils_format_graphite.c
+ * Copyright (C) 2012  Thomas Meson
+ * Copyright (C) 2012  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Thomas Meson <zllak at hycik.org>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+
+#include "utils_format_graphite.h"
+#include "utils_cache.h"
+
+#define GRAPHITE_FORBIDDEN " \t\"\\:!/()\n\r"
+
+/* Utils functions to format data sets in graphite format.
+ * Largely taken from write_graphite.c as it remains the same formatting */
+
+static int gr_format_values (char *ret, size_t ret_len,
+        int ds_num, const data_set_t *ds, const value_list_t *vl,
+        gauge_t const *rates)
+{
+    size_t offset = 0;
+    int status;
+
+    assert (0 == strcmp (ds->type, vl->type));
+
+    memset (ret, 0, ret_len);
+
+#define BUFFER_ADD(...) do { \
+    status = ssnprintf (ret + offset, ret_len - offset, \
+            __VA_ARGS__); \
+    if (status < 1) \
+    { \
+        return (-1); \
+    } \
+    else if (((size_t) status) >= (ret_len - offset)) \
+    { \
+        return (-1); \
+    } \
+    else \
+    offset += ((size_t) status); \
+} while (0)
+
+    if (ds->ds[ds_num].type == DS_TYPE_GAUGE)
+        BUFFER_ADD (GAUGE_FORMAT, vl->values[ds_num].gauge);
+    else if (rates != NULL)
+        BUFFER_ADD ("%f", rates[ds_num]);
+    else if (ds->ds[ds_num].type == DS_TYPE_COUNTER)
+        BUFFER_ADD ("%llu", vl->values[ds_num].counter);
+    else if (ds->ds[ds_num].type == DS_TYPE_DERIVE)
+        BUFFER_ADD ("%"PRIi64, vl->values[ds_num].derive);
+    else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
+        BUFFER_ADD ("%"PRIu64, vl->values[ds_num].absolute);
+    else
+    {
+        ERROR ("gr_format_values plugin: Unknown data source type: %i",
+                ds->ds[ds_num].type);
+        return (-1);
+    }
+
+#undef BUFFER_ADD
+
+    return (0);
+}
+
+static void gr_copy_escape_part (char *dst, const char *src, size_t dst_len,
+    char escape_char)
+{
+    size_t i;
+
+    memset (dst, 0, dst_len);
+
+    if (src == NULL)
+        return;
+
+    for (i = 0; i < dst_len; i++)
+    {
+        if (src[i] == 0)
+        {
+            dst[i] = 0;
+            break;
+        }
+
+        if ((src[i] == '.')
+                || isspace ((int) src[i])
+                || iscntrl ((int) src[i]))
+            dst[i] = escape_char;
+        else
+            dst[i] = src[i];
+    }
+}
+
+static int gr_format_name (char *ret, int ret_len,
+        value_list_t const *vl,
+        char const *ds_name,
+        char const *prefix,
+        char const *postfix,
+        char const escape_char,
+        unsigned int flags)
+{
+    char n_host[DATA_MAX_NAME_LEN];
+    char n_plugin[DATA_MAX_NAME_LEN];
+    char n_plugin_instance[DATA_MAX_NAME_LEN];
+    char n_type[DATA_MAX_NAME_LEN];
+    char n_type_instance[DATA_MAX_NAME_LEN];
+
+    char tmp_plugin[2 * DATA_MAX_NAME_LEN + 1];
+    char tmp_type[2 * DATA_MAX_NAME_LEN + 1];
+
+    if (prefix == NULL)
+        prefix = "";
+
+    if (postfix == NULL)
+        postfix = "";
+
+    gr_copy_escape_part (n_host, vl->host,
+            sizeof (n_host), escape_char);
+    gr_copy_escape_part (n_plugin, vl->plugin,
+            sizeof (n_plugin), escape_char);
+    gr_copy_escape_part (n_plugin_instance, vl->plugin_instance,
+            sizeof (n_plugin_instance), escape_char);
+    gr_copy_escape_part (n_type, vl->type,
+            sizeof (n_type), escape_char);
+    gr_copy_escape_part (n_type_instance, vl->type_instance,
+            sizeof (n_type_instance), escape_char);
+
+    if (n_plugin_instance[0] != '\0')
+        ssnprintf (tmp_plugin, sizeof (tmp_plugin), "%s%c%s",
+            n_plugin,
+            (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+            n_plugin_instance);
+    else
+        sstrncpy (tmp_plugin, n_plugin, sizeof (tmp_plugin));
+
+    if (n_type_instance[0] != '\0')
+        ssnprintf (tmp_type, sizeof (tmp_type), "%s%c%s",
+            n_type,
+            (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+            n_type_instance);
+    else
+        sstrncpy (tmp_type, n_type, sizeof (tmp_type));
+
+    /* Assert always_append_ds -> ds_name */
+    assert (!(flags & GRAPHITE_ALWAYS_APPEND_DS) || (ds_name != NULL));
+    if (ds_name != NULL)
+        ssnprintf (ret, ret_len, "%s%s%s.%s.%s.%s",
+            prefix, n_host, postfix, tmp_plugin, tmp_type, ds_name);
+    else
+        ssnprintf (ret, ret_len, "%s%s%s.%s.%s",
+            prefix, n_host, postfix, tmp_plugin, tmp_type);
+
+    return (0);
+}
+
+static void escape_graphite_string (char *buffer, char escape_char)
+{
+       char *head;
+
+       assert (strchr(GRAPHITE_FORBIDDEN, escape_char) == NULL);
+
+       for (head = buffer + strcspn(buffer, GRAPHITE_FORBIDDEN);
+            *head != '\0';
+            head += strcspn(head, GRAPHITE_FORBIDDEN))
+               *head = escape_char;
+}
+
+int format_graphite (char *buffer, size_t buffer_size,
+    data_set_t const *ds, value_list_t const *vl,
+    char const *prefix, char const *postfix, char const escape_char,
+    unsigned int flags)
+{
+    int status = 0;
+    int i;
+    int buffer_pos = 0;
+
+    gauge_t *rates = NULL;
+    if (flags & GRAPHITE_STORE_RATES)
+      rates = uc_get_rate (ds, vl);
+
+    for (i = 0; i < ds->ds_num; i++)
+    {
+        char const *ds_name = NULL;
+        char        key[10*DATA_MAX_NAME_LEN];
+        char        values[512];
+        size_t      message_len;
+        char        message[1024];
+
+        if ((flags & GRAPHITE_ALWAYS_APPEND_DS)
+            || (ds->ds_num > 1))
+          ds_name = ds->ds[i].name;
+
+        /* Copy the identifier to `key' and escape it. */
+        status = gr_format_name (key, sizeof (key), vl, ds_name,
+                    prefix, postfix, escape_char, flags);
+        if (status != 0)
+        {
+            ERROR ("format_graphite: error with gr_format_name");
+            sfree (rates);
+            return (status);
+        }
+
+        escape_graphite_string (key, escape_char);
+        /* Convert the values to an ASCII representation and put that into
+         * `values'. */
+        status = gr_format_values (values, sizeof (values), i, ds, vl, rates);
+        if (status != 0)
+        {
+            ERROR ("format_graphite: error with gr_format_values");
+            sfree (rates);
+            return (status);
+        }
+
+        /* Compute the graphite command */
+        message_len = (size_t) ssnprintf (message, sizeof (message),
+                "%s %s %u\r\n",
+                key,
+                values,
+                (unsigned int) CDTIME_T_TO_TIME_T (vl->time));
+        if (message_len >= sizeof (message)) {
+            ERROR ("format_graphite: message buffer too small: "
+                    "Need %zu bytes.", message_len + 1);
+            sfree (rates);
+            return (-ENOMEM);
+        }
+
+        /* Append it in case we got multiple data set */
+        if ((buffer_pos + message_len) >= buffer_size)
+        {
+            ERROR ("format_graphite: target buffer too small");
+            sfree (rates);
+            return (-ENOMEM);
+        }
+        memcpy((void *) (buffer + buffer_pos), message, message_len);
+        buffer_pos += message_len;
+    }
+    sfree (rates);
+    return (status);
+} /* int format_graphite */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_format_graphite.h b/src/utils_format_graphite.h
new file mode 100644 (file)
index 0000000..398defb
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+ * collectd - src/utils_format_graphite.h
+ * Copyright (C) 2012  Thomas Meson
+ *
+ * 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:
+ *   Thomas Meson <zllak at hycik.org>
+ **/
+
+#ifndef UTILS_FORMAT_GRAPHITE_H
+#define UTILS_FORMAT_GRAPHITE_H 1
+
+#include "collectd.h"
+#include "plugin.h"
+
+#define GRAPHITE_STORE_RATES        0x01
+#define GRAPHITE_SEPARATE_INSTANCES 0x02
+#define GRAPHITE_ALWAYS_APPEND_DS   0x04
+
+int format_graphite (char *buffer,
+    size_t buffer_size, const data_set_t *ds,
+    const value_list_t *vl, const char *prefix,
+    const char *postfix, const char escape_char,
+    unsigned int flags);
+
+#endif /* UTILS_FORMAT_GRAPHITE_H */
diff --git a/src/utils_format_json.c b/src/utils_format_json.c
new file mode 100644 (file)
index 0000000..10a5343
--- /dev/null
@@ -0,0 +1,487 @@
+/**
+ * collectd - src/utils_format_json.c
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+
+#include "utils_cache.h"
+#include "utils_format_json.h"
+
+static int json_escape_string (char *buffer, size_t buffer_size, /* {{{ */
+    const char *string)
+{
+  size_t src_pos;
+  size_t dst_pos;
+
+  if ((buffer == NULL) || (string == NULL))
+    return (-EINVAL);
+
+  if (buffer_size < 3)
+    return (-ENOMEM);
+
+  dst_pos = 0;
+
+#define BUFFER_ADD(c) do { \
+  if (dst_pos >= (buffer_size - 1)) { \
+    buffer[buffer_size - 1] = 0; \
+    return (-ENOMEM); \
+  } \
+  buffer[dst_pos] = (c); \
+  dst_pos++; \
+} while (0)
+
+  /* Escape special characters */
+  BUFFER_ADD ('"');
+  for (src_pos = 0; string[src_pos] != 0; src_pos++)
+  {
+    if ((string[src_pos] == '"')
+        || (string[src_pos] == '\\'))
+    {
+      BUFFER_ADD ('\\');
+      BUFFER_ADD (string[src_pos]);
+    }
+    else if (string[src_pos] <= 0x001F)
+      BUFFER_ADD ('?');
+    else
+      BUFFER_ADD (string[src_pos]);
+  } /* for */
+  BUFFER_ADD ('"');
+  buffer[dst_pos] = 0;
+
+#undef BUFFER_ADD
+
+  return (0);
+} /* }}} int json_escape_string */
+
+static int values_to_json (char *buffer, size_t buffer_size, /* {{{ */
+                const data_set_t *ds, const value_list_t *vl, int store_rates)
+{
+  size_t offset = 0;
+  int i;
+  gauge_t *rates = NULL;
+
+  memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+  int status; \
+  status = ssnprintf (buffer + offset, buffer_size - offset, \
+      __VA_ARGS__); \
+  if (status < 1) \
+  { \
+    sfree(rates); \
+    return (-1); \
+  } \
+  else if (((size_t) status) >= (buffer_size - offset)) \
+  { \
+    sfree(rates); \
+    return (-ENOMEM); \
+  } \
+  else \
+    offset += ((size_t) status); \
+} while (0)
+
+  BUFFER_ADD ("[");
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if (i > 0)
+      BUFFER_ADD (",");
+
+    if (ds->ds[i].type == DS_TYPE_GAUGE)
+    {
+      if(isfinite (vl->values[i].gauge))
+        BUFFER_ADD (JSON_GAUGE_FORMAT, vl->values[i].gauge);
+      else
+        BUFFER_ADD ("null");
+    }
+    else if (store_rates)
+    {
+      if (rates == NULL)
+        rates = uc_get_rate (ds, vl);
+      if (rates == NULL)
+      {
+        WARNING ("utils_format_json: uc_get_rate failed.");
+        sfree(rates);
+        return (-1);
+      }
+
+      if(isfinite (rates[i]))
+        BUFFER_ADD (JSON_GAUGE_FORMAT, rates[i]);
+      else
+        BUFFER_ADD ("null");
+    }
+    else if (ds->ds[i].type == DS_TYPE_COUNTER)
+      BUFFER_ADD ("%llu", vl->values[i].counter);
+    else if (ds->ds[i].type == DS_TYPE_DERIVE)
+      BUFFER_ADD ("%"PRIi64, vl->values[i].derive);
+    else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+      BUFFER_ADD ("%"PRIu64, vl->values[i].absolute);
+    else
+    {
+      ERROR ("format_json: Unknown data source type: %i",
+          ds->ds[i].type);
+      sfree (rates);
+      return (-1);
+    }
+  } /* for ds->ds_num */
+  BUFFER_ADD ("]");
+
+#undef BUFFER_ADD
+
+  DEBUG ("format_json: values_to_json: buffer = %s;", buffer);
+  sfree(rates);
+  return (0);
+} /* }}} int values_to_json */
+
+static int dstypes_to_json (char *buffer, size_t buffer_size, /* {{{ */
+                const data_set_t *ds)
+{
+  size_t offset = 0;
+  int i;
+
+  memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+  int status; \
+  status = ssnprintf (buffer + offset, buffer_size - offset, \
+      __VA_ARGS__); \
+  if (status < 1) \
+    return (-1); \
+  else if (((size_t) status) >= (buffer_size - offset)) \
+    return (-ENOMEM); \
+  else \
+    offset += ((size_t) status); \
+} while (0)
+
+  BUFFER_ADD ("[");
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if (i > 0)
+      BUFFER_ADD (",");
+
+    BUFFER_ADD ("\"%s\"", DS_TYPE_TO_STRING (ds->ds[i].type));
+  } /* for ds->ds_num */
+  BUFFER_ADD ("]");
+
+#undef BUFFER_ADD
+
+  DEBUG ("format_json: dstypes_to_json: buffer = %s;", buffer);
+
+  return (0);
+} /* }}} int dstypes_to_json */
+
+static int dsnames_to_json (char *buffer, size_t buffer_size, /* {{{ */
+                const data_set_t *ds)
+{
+  size_t offset = 0;
+  int i;
+
+  memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+  int status; \
+  status = ssnprintf (buffer + offset, buffer_size - offset, \
+      __VA_ARGS__); \
+  if (status < 1) \
+    return (-1); \
+  else if (((size_t) status) >= (buffer_size - offset)) \
+    return (-ENOMEM); \
+  else \
+    offset += ((size_t) status); \
+} while (0)
+
+  BUFFER_ADD ("[");
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if (i > 0)
+      BUFFER_ADD (",");
+
+    BUFFER_ADD ("\"%s\"", ds->ds[i].name);
+  } /* for ds->ds_num */
+  BUFFER_ADD ("]");
+
+#undef BUFFER_ADD
+
+  DEBUG ("format_json: dsnames_to_json: buffer = %s;", buffer);
+
+  return (0);
+} /* }}} int dsnames_to_json */
+
+static int meta_data_to_json (char *buffer, size_t buffer_size, /* {{{ */
+    meta_data_t *meta)
+{
+  size_t offset = 0;
+  char **keys = NULL;
+  int keys_num;
+  int status;
+  int i;
+
+  buffer[0] = 0;
+
+  if (meta == NULL)
+    return (EINVAL);
+
+#define BUFFER_ADD(...) do { \
+  status = ssnprintf (buffer + offset, buffer_size - offset, \
+      __VA_ARGS__); \
+  if (status < 1) \
+    return (-1); \
+  else if (((size_t) status) >= (buffer_size - offset)) \
+    return (-ENOMEM); \
+  else \
+    offset += ((size_t) status); \
+} while (0)
+
+  keys_num = meta_data_toc (meta, &keys);
+  if (keys_num == 0)
+  {
+    sfree (keys);
+    return (0);
+  }
+
+  for (i = 0; i < keys_num; ++i)
+  {
+    int type;
+    char *key = keys[i];
+
+    type = meta_data_type (meta, key);
+    if (type == MD_TYPE_STRING)
+    {
+      char *value = NULL;
+      if (meta_data_get_string (meta, key, &value) == 0)
+      {
+        char temp[512] = "";
+        json_escape_string (temp, sizeof (temp), value);
+        sfree (value);
+        BUFFER_ADD (",\"%s\":%s", key, temp);
+      }
+    }
+    else if (type == MD_TYPE_SIGNED_INT)
+    {
+      int64_t value = 0;
+      if (meta_data_get_signed_int (meta, key, &value) == 0)
+        BUFFER_ADD (",\"%s\":%"PRIi64, key, value);
+    }
+    else if (type == MD_TYPE_UNSIGNED_INT)
+    {
+      uint64_t value = 0;
+      if (meta_data_get_unsigned_int (meta, key, &value) == 0)
+        BUFFER_ADD (",\"%s\":%"PRIu64, key, value);
+    }
+    else if (type == MD_TYPE_DOUBLE)
+    {
+      double value = 0.0;
+      if (meta_data_get_double (meta, key, &value) == 0)
+        BUFFER_ADD (",\"%s\":%f", key, value);
+    }
+    else if (type == MD_TYPE_BOOLEAN)
+    {
+      _Bool value = 0;
+      if (meta_data_get_boolean (meta, key, &value) == 0)
+        BUFFER_ADD (",\"%s\":%s", key, value ? "true" : "false");
+    }
+
+    free (key);
+  } /* for (keys) */
+  free (keys);
+
+  if (offset <= 0)
+    return (ENOENT);
+
+  buffer[0] = '{'; /* replace leading ',' */
+  BUFFER_ADD ("}");
+
+#undef BUFFER_ADD
+
+  return (0);
+} /* }}} int meta_data_to_json */
+
+static int value_list_to_json (char *buffer, size_t buffer_size, /* {{{ */
+                const data_set_t *ds, const value_list_t *vl, int store_rates)
+{
+  char temp[512];
+  size_t offset = 0;
+  int status;
+
+  memset (buffer, 0, buffer_size);
+
+#define BUFFER_ADD(...) do { \
+  status = ssnprintf (buffer + offset, buffer_size - offset, \
+      __VA_ARGS__); \
+  if (status < 1) \
+    return (-1); \
+  else if (((size_t) status) >= (buffer_size - offset)) \
+    return (-ENOMEM); \
+  else \
+    offset += ((size_t) status); \
+} while (0)
+
+  /* All value lists have a leading comma. The first one will be replaced with
+   * a square bracket in `format_json_finalize'. */
+  BUFFER_ADD (",{");
+
+  status = values_to_json (temp, sizeof (temp), ds, vl, store_rates);
+  if (status != 0)
+    return (status);
+  BUFFER_ADD ("\"values\":%s", temp);
+
+  status = dstypes_to_json (temp, sizeof (temp), ds);
+  if (status != 0)
+    return (status);
+  BUFFER_ADD (",\"dstypes\":%s", temp);
+
+  status = dsnames_to_json (temp, sizeof (temp), ds);
+  if (status != 0)
+    return (status);
+  BUFFER_ADD (",\"dsnames\":%s", temp);
+
+  BUFFER_ADD (",\"time\":%.3f", CDTIME_T_TO_DOUBLE (vl->time));
+  BUFFER_ADD (",\"interval\":%.3f", CDTIME_T_TO_DOUBLE (vl->interval));
+
+#define BUFFER_ADD_KEYVAL(key, value) do { \
+  status = json_escape_string (temp, sizeof (temp), (value)); \
+  if (status != 0) \
+    return (status); \
+  BUFFER_ADD (",\"%s\":%s", (key), temp); \
+} while (0)
+
+  BUFFER_ADD_KEYVAL ("host", vl->host);
+  BUFFER_ADD_KEYVAL ("plugin", vl->plugin);
+  BUFFER_ADD_KEYVAL ("plugin_instance", vl->plugin_instance);
+  BUFFER_ADD_KEYVAL ("type", vl->type);
+  BUFFER_ADD_KEYVAL ("type_instance", vl->type_instance);
+
+  if (vl->meta != NULL)
+  {
+    char meta_buffer[buffer_size];
+    memset (meta_buffer, 0, sizeof (meta_buffer));
+    status = meta_data_to_json (meta_buffer, sizeof (meta_buffer), vl->meta);
+    if (status != 0)
+      return (status);
+
+    BUFFER_ADD (",\"meta\":%s", meta_buffer);
+  } /* if (vl->meta != NULL) */
+
+  BUFFER_ADD ("}");
+
+#undef BUFFER_ADD_KEYVAL
+#undef BUFFER_ADD
+
+  DEBUG ("format_json: value_list_to_json: buffer = %s;", buffer);
+
+  return (0);
+} /* }}} int value_list_to_json */
+
+static int format_json_value_list_nocheck (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free,
+    const data_set_t *ds, const value_list_t *vl,
+    int store_rates, size_t temp_size)
+{
+  char temp[temp_size];
+  int status;
+
+  status = value_list_to_json (temp, sizeof (temp), ds, vl, store_rates);
+  if (status != 0)
+    return (status);
+  temp_size = strlen (temp);
+
+  memcpy (buffer + (*ret_buffer_fill), temp, temp_size + 1);
+  (*ret_buffer_fill) += temp_size;
+  (*ret_buffer_free) -= temp_size;
+
+  return (0);
+} /* }}} int format_json_value_list_nocheck */
+
+int format_json_initialize (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free)
+{
+  size_t buffer_fill;
+  size_t buffer_free;
+
+  if ((buffer == NULL) || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL))
+    return (-EINVAL);
+
+  buffer_fill = *ret_buffer_fill;
+  buffer_free = *ret_buffer_free;
+
+  buffer_free = buffer_fill + buffer_free;
+  buffer_fill = 0;
+
+  if (buffer_free < 3)
+    return (-ENOMEM);
+
+  memset (buffer, 0, buffer_free);
+  *ret_buffer_fill = buffer_fill;
+  *ret_buffer_free = buffer_free;
+
+  return (0);
+} /* }}} int format_json_initialize */
+
+int format_json_finalize (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free)
+{
+  size_t pos;
+
+  if ((buffer == NULL) || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL))
+    return (-EINVAL);
+
+  if (*ret_buffer_free < 2)
+    return (-ENOMEM);
+
+  /* Replace the leading comma added in `value_list_to_json' with a square
+   * bracket. */
+  if (buffer[0] != ',')
+    return (-EINVAL);
+  buffer[0] = '[';
+
+  pos = *ret_buffer_fill;
+  buffer[pos] = ']';
+  buffer[pos+1] = 0;
+
+  (*ret_buffer_fill)++;
+  (*ret_buffer_free)--;
+
+  return (0);
+} /* }}} int format_json_finalize */
+
+int format_json_value_list (char *buffer, /* {{{ */
+    size_t *ret_buffer_fill, size_t *ret_buffer_free,
+    const data_set_t *ds, const value_list_t *vl, int store_rates)
+{
+  if ((buffer == NULL)
+      || (ret_buffer_fill == NULL) || (ret_buffer_free == NULL)
+      || (ds == NULL) || (vl == NULL))
+    return (-EINVAL);
+
+  if (*ret_buffer_free < 3)
+    return (-ENOMEM);
+
+  return (format_json_value_list_nocheck (buffer,
+        ret_buffer_fill, ret_buffer_free, ds, vl,
+        store_rates, (*ret_buffer_free) - 2));
+} /* }}} int format_json_value_list */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_format_json.h b/src/utils_format_json.h
new file mode 100644 (file)
index 0000000..f1fbb6e
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * collectd - src/utils_format_json.h
+ * Copyright (C) 2009       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_FORMAT_JSON_H
+#define UTILS_FORMAT_JSON_H 1
+
+#include "collectd.h"
+#include "plugin.h"
+
+#ifndef JSON_GAUGE_FORMAT
+# define JSON_GAUGE_FORMAT GAUGE_FORMAT
+#endif
+
+int format_json_initialize (char *buffer,
+    size_t *ret_buffer_fill, size_t *ret_buffer_free);
+int format_json_value_list (char *buffer,
+    size_t *ret_buffer_fill, size_t *ret_buffer_free,
+    const data_set_t *ds, const value_list_t *vl, int store_rates);
+int format_json_finalize (char *buffer,
+    size_t *ret_buffer_fill, size_t *ret_buffer_free);
+
+#endif /* UTILS_FORMAT_JSON_H */
diff --git a/src/utils_ignorelist.c b/src/utils_ignorelist.c
new file mode 100644 (file)
index 0000000..0ad252b
--- /dev/null
@@ -0,0 +1,364 @@
+/**
+ * collectd - src/utils_ignorelist.c
+ * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
+ * Copyright (C) 2008 Florian Forster <octo at collectd.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ *   Lubos Stanek <lubek at users.sourceforge.net>
+ *   Florian Forster <octo at collectd.org>
+ **/
+/**
+ * ignorelist handles plugin's list of configured collectable
+ * entries with global ignore action
+ **/
+/**
+ * Usage:
+ * 
+ * Define plugin's global pointer variable of type ignorelist_t:
+ *   ignorelist_t *myconfig_ignore;
+ * If you know the state of the global ignore (IgnoreSelected),
+ * allocate the variable with:
+ *   myconfig_ignore = ignorelist_create (YourKnownIgnore);
+ * If you do not know the state of the global ignore,
+ * initialize the global variable and set the ignore flag later:
+ *   myconfig_ignore = ignorelist_init ();
+ * Append single entries in your cf_register'ed callback function:
+ *   ignorelist_add (myconfig_ignore, newentry);
+ * When you hit the IgnoreSelected config option,
+ * offer it to the list:
+ *   ignorelist_ignore (myconfig_ignore, instantly_got_value_of_ignore);
+ * That is all for the ignorelist initialization.
+ * Later during read and write (plugin's registered functions) get
+ * the information whether this entry would be collected or not:
+ *   if (ignorelist_match (myconfig_ignore, thisentry))
+ *     return;
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+/*
+ * private prototypes
+ */
+struct ignorelist_item_s
+{
+#if HAVE_REGEX_H
+       regex_t *rmatch;        /* regular expression entry identification */
+#endif
+       char *smatch;           /* string entry identification */
+       struct ignorelist_item_s *next;
+};
+typedef struct ignorelist_item_s ignorelist_item_t;
+
+struct ignorelist_s
+{
+       int ignore;             /* ignore entries */
+       ignorelist_item_t *head;        /* pointer to the first entry */
+};
+
+/* *** *** *** ********************************************* *** *** *** */
+/* *** *** *** *** *** ***   private functions   *** *** *** *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
+
+static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
+{
+       assert ((il != NULL) && (item != NULL));
+
+       item->next = il->head;
+       il->head = item;
+}
+
+#if HAVE_REGEX_H
+static int ignorelist_append_regex(ignorelist_t *il, const char *entry)
+{
+       int rcompile;
+       regex_t *regtemp;
+       int errsize;
+       char *regerr = NULL;
+       ignorelist_item_t *new;
+
+       /* create buffer */
+       if ((regtemp = malloc(sizeof(regex_t))) == NULL)
+       {
+               ERROR ("cannot allocate new config entry");
+               return (1);
+       }
+       memset (regtemp, '\0', sizeof(regex_t));
+
+       /* compile regex */
+       if ((rcompile = regcomp (regtemp, entry, REG_EXTENDED)) != 0)
+       {
+               /* prepare message buffer */
+               errsize = regerror(rcompile, regtemp, NULL, 0);
+               if (errsize)
+                       regerr = smalloc(errsize);
+               /* get error message */
+               if (regerror (rcompile, regtemp, regerr, errsize))
+               {
+                       fprintf (stderr, "Cannot compile regex %s: %i/%s",
+                                       entry, rcompile, regerr);
+                       ERROR ("Cannot compile regex %s: %i/%s",
+                                       entry, rcompile, regerr);
+               }
+               else
+               {
+                       fprintf (stderr, "Cannot compile regex %s: %i",
+                                       entry, rcompile);
+                       ERROR ("Cannot compile regex %s: %i",
+                                       entry, rcompile);
+               }
+
+               if (errsize)
+                       sfree (regerr);
+               regfree (regtemp);
+               return (1);
+       }
+       DEBUG("regex compiled: %s - %i", entry, rcompile);
+
+       /* create new entry */
+       if ((new = malloc(sizeof(ignorelist_item_t))) == NULL)
+       {
+               ERROR ("cannot allocate new config entry");
+               regfree (regtemp);
+               return (1);
+       }
+       memset (new, '\0', sizeof(ignorelist_item_t));
+       new->rmatch = regtemp;
+
+       /* append new entry */
+       ignorelist_append (il, new);
+
+       return (0);
+} /* int ignorelist_append_regex(ignorelist_t *il, const char *entry) */
+#endif
+
+static int ignorelist_append_string(ignorelist_t *il, const char *entry)
+{
+       ignorelist_item_t *new;
+
+       /* create new entry */
+       if ((new = malloc(sizeof(ignorelist_item_t))) == NULL )
+       {
+               ERROR ("cannot allocate new entry");
+               return (1);
+       }
+       memset (new, '\0', sizeof(ignorelist_item_t));
+       new->smatch = sstrdup(entry);
+
+       /* append new entry */
+       ignorelist_append (il, new);
+
+       return (0);
+} /* int ignorelist_append_string(ignorelist_t *il, const char *entry) */
+
+#if HAVE_REGEX_H
+/*
+ * check list for entry regex match
+ * return 1 if found
+ */
+static int ignorelist_match_regex (ignorelist_item_t *item, const char *entry)
+{
+       assert ((item != NULL) && (item->rmatch != NULL)
+                       && (entry != NULL) && (strlen (entry) > 0));
+
+       /* match regex */
+       if (regexec (item->rmatch, entry, 0, NULL, 0) == 0)
+               return (1);
+
+       return (0);
+} /* int ignorelist_match_regex (ignorelist_item_t *item, const char *entry) */
+#endif
+
+/*
+ * check list for entry string match
+ * return 1 if found
+ */
+static int ignorelist_match_string (ignorelist_item_t *item, const char *entry)
+{
+       assert ((item != NULL) && (item->smatch != NULL)
+                       && (entry != NULL) && (strlen (entry) > 0));
+
+       if (strcmp (entry, item->smatch) == 0)
+               return (1);
+
+       return (0);
+} /* int ignorelist_match_string (ignorelist_item_t *item, const char *entry) */
+
+
+/* *** *** *** ******************************************** *** *** *** */
+/* *** *** *** *** *** ***   public functions   *** *** *** *** *** *** */
+/* *** *** *** ******************************************** *** *** *** */
+
+/*
+ * create the ignorelist_t with known ignore state
+ * return pointer to ignorelist_t
+ */
+ignorelist_t *ignorelist_create (int invert)
+{
+       ignorelist_t *il;
+
+       /* smalloc exits if it failes */
+       il = (ignorelist_t *) smalloc (sizeof (ignorelist_t));
+       memset (il, '\0', sizeof (ignorelist_t));
+
+       /*
+        * ->ignore == 0  =>  collect
+        * ->ignore == 1  =>  ignore
+        */
+       il->ignore = invert ? 0 : 1;
+
+       return (il);
+} /* ignorelist_t *ignorelist_create (int ignore) */
+
+/*
+ * free memory used by ignorelist_t
+ */
+void ignorelist_free (ignorelist_t *il)
+{
+       ignorelist_item_t *this;
+       ignorelist_item_t *next;
+
+       if (il == NULL)
+               return;
+
+       for (this = il->head; this != NULL; this = next)
+       {
+               next = this->next;
+#if HAVE_REGEX_H
+               if (this->rmatch != NULL)
+               {
+                       regfree (this->rmatch);
+                       this->rmatch = NULL;
+               }
+#endif
+               if (this->smatch != NULL)
+               {
+                       sfree (this->smatch);
+                       this->smatch = NULL;
+               }
+               sfree (this);
+       }
+
+       sfree (il);
+       il = NULL;
+} /* void ignorelist_destroy (ignorelist_t *il) */
+
+/*
+ * set ignore state of the ignorelist_t
+ */
+void ignorelist_set_invert (ignorelist_t *il, int invert)
+{
+       if (il == NULL)
+       {
+               DEBUG("ignore call with ignorelist_t == NULL");
+               return;
+       }
+
+       il->ignore = invert ? 0 : 1;
+} /* void ignorelist_set_invert (ignorelist_t *il, int ignore) */
+
+/*
+ * append entry into ignorelist_t
+ * return 1 for success
+ */
+int ignorelist_add (ignorelist_t *il, const char *entry)
+{
+       int ret;
+       size_t entry_len;
+
+       if (il == NULL)
+       {
+               DEBUG ("add called with ignorelist_t == NULL");
+               return (1);
+       }
+
+       entry_len = strlen (entry);
+
+       /* append nothing */
+       if (entry_len == 0)
+       {
+               DEBUG("not appending: empty entry");
+               return (1);
+       }
+
+#if HAVE_REGEX_H
+       /* regex string is enclosed in "/.../" */
+       if ((entry_len > 2) && (entry[0] == '/') && entry[entry_len - 1] == '/')
+       {
+               char *entry_copy;
+               size_t entry_copy_size;
+
+               /* We need to copy `entry' since it's const */
+               entry_copy_size = entry_len - 1;
+               entry_copy = smalloc (entry_copy_size);
+               sstrncpy (entry_copy, entry + 1, entry_copy_size);
+
+               DEBUG("I'm about to add regex entry: %s", entry_copy);
+               ret = ignorelist_append_regex(il, entry_copy);
+               sfree (entry_copy);
+       }
+       else
+#endif
+       {
+               DEBUG("to add entry: %s", entry);
+               ret = ignorelist_append_string(il, entry);
+       }
+
+       return (ret);
+} /* int ignorelist_add (ignorelist_t *il, const char *entry) */
+
+/*
+ * check list for entry
+ * return 1 for ignored entry
+ */
+int ignorelist_match (ignorelist_t *il, const char *entry)
+{
+       ignorelist_item_t *traverse;
+
+       /* if no entries, collect all */
+       if ((il == NULL) || (il->head == NULL))
+               return (0);
+
+       if ((entry == NULL) || (strlen (entry) == 0))
+               return (0);
+
+       /* traverse list and check entries */
+       for (traverse = il->head; traverse != NULL; traverse = traverse->next)
+       {
+#if HAVE_REGEX_H
+               if (traverse->rmatch != NULL)
+               {
+                       if (ignorelist_match_regex (traverse, entry))
+                               return (il->ignore);
+               }
+               else
+#endif
+               {
+                       if (ignorelist_match_string (traverse, entry))
+                               return (il->ignore);
+               }
+       } /* for traverse */
+
+       return (1 - il->ignore);
+} /* int ignorelist_match (ignorelist_t *il, const char *entry) */
+
diff --git a/src/utils_ignorelist.h b/src/utils_ignorelist.h
new file mode 100644 (file)
index 0000000..b47b55a
--- /dev/null
@@ -0,0 +1,70 @@
+/**
+ * collectd - src/utils_ignorelist.h
+ * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ *   Lubos Stanek <lubek at users.sourceforge.net>
+ **/
+/**
+ * ignorelist handles plugin's list of configured collectable
+ * entries with global ignore action
+ **/
+
+#ifndef UTILS_IGNORELIST_H
+#define UTILS_IGNORELIST_H 1
+
+#include "collectd.h"
+
+#if HAVE_REGEX_H
+# include <regex.h>
+#endif
+
+/* public prototypes */
+
+struct ignorelist_s;
+typedef struct ignorelist_s ignorelist_t;
+
+/*
+ * create the ignorelist_t with known ignore state
+ * return pointer to ignorelist_t
+ */
+ignorelist_t *ignorelist_create (int invert);
+
+/*
+ * free memory used by ignorelist_t
+ */
+void ignorelist_free (ignorelist_t *il);
+
+/*
+ * set ignore state of the ignorelist_t
+ */
+void ignorelist_set_invert (ignorelist_t *il, int invert);
+
+/*
+ * append entry to ignorelist_t
+ * returns zero on success, non-zero upon failure.
+ */
+int ignorelist_add (ignorelist_t *il, const char *entry);
+
+/*
+ * check list for entry
+ * return 1 for ignored entry
+ */
+int ignorelist_match (ignorelist_t *il, const char *entry);
+
+#endif /* UTILS_IGNORELIST_H */
diff --git a/src/utils_latency.c b/src/utils_latency.c
new file mode 100644 (file)
index 0000000..7f60e11
--- /dev/null
@@ -0,0 +1,268 @@
+/**
+ * collectd - src/utils_latency.c
+ * Copyright (C) 2013       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <ff at octo.it>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "utils_latency.h"
+#include "common.h"
+
+#include <math.h>
+
+#ifndef HISTOGRAM_NUM_BINS
+# define HISTOGRAM_NUM_BINS 1000
+#endif
+
+static const int HISTOGRAM_DEFAULT_BIN_WIDTH = 1;
+
+struct latency_counter_s
+{
+  cdtime_t start_time;
+
+  cdtime_t sum;
+  size_t num;
+
+  cdtime_t min;
+  cdtime_t max;
+
+  int bin_width;
+  int histogram[HISTOGRAM_NUM_BINS];
+};
+
+/*
+* 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 it's 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.
+*
+*/
+void change_bin_width (latency_counter_t *lc, size_t val) /* {{{ */
+{
+  int i=0;
+  /* This function is called because the new value is above histogram's range.
+   * First find the required bin width:
+   *           requiredBinWidth = (value + 1) / numBins
+   * then get the next nearest power of 2
+   *           newBinWidth = 2^(ceil(log2(requiredBinWidth)))
+   */
+  double required_bin_width = (double)(val + 1) / HISTOGRAM_NUM_BINS;
+  double required_bin_width_logbase2 = log(required_bin_width) / log(2.0);
+  int new_bin_width = (int)(pow(2.0, ceil( required_bin_width_logbase2)));
+  int old_bin_width = lc->bin_width;
+  lc->bin_width = new_bin_width;
+
+  /*
+   * bin width has been increased, now iterate through all bins and move the
+   * old bin's count to new bin.
+   */
+  if (lc->num > 0) // if the histogram has data then iterate else skip
+  {
+      double width_change_ratio = old_bin_width / new_bin_width;
+      for (i=0; i<HISTOGRAM_NUM_BINS; i++)
+      {
+         int new_bin = (int)(i * width_change_ratio);
+         if (i == new_bin)
+             continue;
+         lc->histogram[new_bin] += lc->histogram[i];
+         lc->histogram[i] = 0;
+      }
+      DEBUG("utils_latency: change_bin_width: fixed all bins");
+  }
+
+  DEBUG("utils_latency: change_bin_width: val-[%zu], oldBinWidth-[%d], "
+          "newBinWidth-[%d], required_bin_width-[%f], "
+          "required_bin_width_logbase2-[%f]",
+          val, old_bin_width, new_bin_width, required_bin_width,
+          required_bin_width_logbase2);
+
+} /* }}} void change_bin_width */
+
+latency_counter_t *latency_counter_create () /* {{{ */
+{
+  latency_counter_t *lc;
+
+  lc = malloc (sizeof (*lc));
+  if (lc == NULL)
+    return (NULL);
+
+  latency_counter_reset (lc);
+  lc->bin_width = HISTOGRAM_DEFAULT_BIN_WIDTH;
+  return (lc);
+} /* }}} latency_counter_t *latency_counter_create */
+
+void latency_counter_destroy (latency_counter_t *lc) /* {{{ */
+{
+  sfree (lc);
+} /* }}} void latency_counter_destroy */
+
+void latency_counter_add (latency_counter_t *lc, cdtime_t latency) /* {{{ */
+{
+  size_t latency_ms;
+
+  if ((lc == NULL) || (latency == 0))
+    return;
+
+  lc->sum += latency;
+  lc->num++;
+
+  if ((lc->min == 0) && (lc->max == 0))
+    lc->min = lc->max = latency;
+  if (lc->min > latency)
+    lc->min = latency;
+  if (lc->max < latency)
+    lc->max = latency;
+
+  /* A latency of _exactly_ 1.0 ms should be stored in the buffer 0, so
+   * subtract one from the cdtime_t value so that exactly 1.0 ms get sorted
+   * accordingly. */
+  latency_ms = (size_t) CDTIME_T_TO_MS (latency - 1);
+
+  int bin = (int)(latency_ms / lc->bin_width);
+  if (bin >= HISTOGRAM_NUM_BINS)
+  {
+      change_bin_width(lc, latency_ms);
+      bin = (int)(latency_ms / lc->bin_width);
+      if (bin >= HISTOGRAM_NUM_BINS)
+      {
+          ERROR("utils_latency: latency_counter_add: Invalid bin %d", bin);
+          return;
+      }
+  }
+  lc->histogram[bin]++;
+} /* }}} void latency_counter_add */
+
+void latency_counter_reset (latency_counter_t *lc) /* {{{ */
+{
+  if (lc == NULL)
+    return;
+
+  int bin_width = lc->bin_width;
+  memset (lc, 0, sizeof (*lc));
+
+  /* preserve bin width */
+  lc->bin_width = bin_width;
+  lc->start_time = cdtime ();
+} /* }}} void latency_counter_reset */
+
+cdtime_t latency_counter_get_min (latency_counter_t *lc) /* {{{ */
+{
+  if (lc == NULL)
+    return (0);
+  return (lc->min);
+} /* }}} cdtime_t latency_counter_get_min */
+
+cdtime_t latency_counter_get_max (latency_counter_t *lc) /* {{{ */
+{
+  if (lc == NULL)
+    return (0);
+  return (lc->max);
+} /* }}} cdtime_t latency_counter_get_max */
+
+cdtime_t latency_counter_get_sum (latency_counter_t *lc) /* {{{ */
+{
+  if (lc == NULL)
+    return (0);
+  return (lc->sum);
+} /* }}} cdtime_t latency_counter_get_sum */
+
+size_t latency_counter_get_num (latency_counter_t *lc) /* {{{ */
+{
+  if (lc == NULL)
+    return (0);
+  return (lc->num);
+} /* }}} size_t latency_counter_get_num */
+
+cdtime_t latency_counter_get_average (latency_counter_t *lc) /* {{{ */
+{
+  double average;
+
+  if ((lc == NULL) || (lc->num == 0))
+    return (0);
+
+  average = CDTIME_T_TO_DOUBLE (lc->sum) / ((double) lc->num);
+  return (DOUBLE_TO_CDTIME_T (average));
+} /* }}} cdtime_t latency_counter_get_average */
+
+cdtime_t latency_counter_get_percentile (latency_counter_t *lc,
+    double percent)
+{
+  double percent_upper;
+  double percent_lower;
+  double ms_upper;
+  double ms_lower;
+  double ms_interpolated;
+  int sum;
+  size_t i;
+
+  if ((lc == NULL) || (lc->num == 0) || !((percent > 0.0) && (percent < 100.0)))
+    return (0);
+
+  /* Find index i so that at least "percent" events are within i+1 ms. */
+  percent_upper = 0.0;
+  percent_lower = 0.0;
+  sum = 0;
+  for (i = 0; i < HISTOGRAM_NUM_BINS; i++)
+  {
+    percent_lower = percent_upper;
+    sum += lc->histogram[i];
+    if (sum == 0)
+      percent_upper = 0.0;
+    else
+      percent_upper = 100.0 * ((double) sum) / ((double) lc->num);
+
+    if (percent_upper >= percent)
+      break;
+  }
+
+  if (i >= HISTOGRAM_NUM_BINS)
+    return (0);
+
+  assert (percent_upper >= percent);
+  assert (percent_lower < percent);
+
+  ms_upper = (double) ( (i + 1) * lc->bin_width );
+  ms_lower = (double) ( i * lc->bin_width );
+  if (i == 0)
+    return (MS_TO_CDTIME_T (ms_upper));
+
+  ms_interpolated = (((percent_upper - percent) * ms_lower)
+      + ((percent - percent_lower) * ms_upper))
+    / (percent_upper - percent_lower);
+
+  return (MS_TO_CDTIME_T (ms_interpolated));
+} /* }}} cdtime_t latency_counter_get_percentile */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_latency.h b/src/utils_latency.h
new file mode 100644 (file)
index 0000000..9930b72
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * collectd - src/utils_latency.h
+ * Copyright (C) 2013       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <ff at octo.it>
+ **/
+
+#include "collectd.h"
+#include "utils_time.h"
+
+struct latency_counter_s;
+typedef struct latency_counter_s latency_counter_t;
+
+latency_counter_t *latency_counter_create ();
+void latency_counter_destroy (latency_counter_t *lc);
+
+void latency_counter_add (latency_counter_t *lc, cdtime_t latency);
+void latency_counter_reset (latency_counter_t *lc);
+
+cdtime_t latency_counter_get_min (latency_counter_t *lc);
+cdtime_t latency_counter_get_max (latency_counter_t *lc);
+cdtime_t latency_counter_get_sum (latency_counter_t *lc);
+size_t   latency_counter_get_num (latency_counter_t *lc);
+cdtime_t latency_counter_get_average (latency_counter_t *lc);
+cdtime_t latency_counter_get_percentile (latency_counter_t *lc,
+    double percent);
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/utils_mount.c b/src/utils_mount.c
new file mode 100644 (file)
index 0000000..b63a81a
--- /dev/null
@@ -0,0 +1,777 @@
+/**
+ * collectd - src/utils_mount.c
+ * Copyright (C) 2005,2006  Niki W. Waibel
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Author:
+ *   Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+#include "collectd.h"
+#include "utils_mount.h"
+
+#include "common.h" /* sstrncpy() et alii */
+#include "plugin.h" /* ERROR() macro */
+
+#if HAVE_XFS_XQM_H
+# include <xfs/xqm.h>
+#define XFS_SUPER_MAGIC_STR "XFSB"
+#define XFS_SUPER_MAGIC2_STR "BSFX"
+#endif
+
+#if HAVE_GETVFSSTAT
+#  if HAVE_SYS_TYPES_H
+#    include <sys/types.h>
+#  endif
+#  if HAVE_SYS_STATVFS_H
+#    include <sys/statvfs.h>
+#  endif
+/* #endif HAVE_GETVFSSTAT */
+
+#elif HAVE_GETFSSTAT
+#  if HAVE_SYS_PARAM_H
+#    include <sys/param.h>
+#  endif
+#  if HAVE_SYS_UCRED_H
+#    include <sys/ucred.h>
+#  endif
+#  if HAVE_SYS_MOUNT_H
+#    include <sys/mount.h>
+#  endif
+#endif /* HAVE_GETFSSTAT */
+
+#if HAVE_MNTENT_H
+#  include <mntent.h>
+#endif
+#if HAVE_SYS_MNTTAB_H
+#  include <sys/mnttab.h>
+#endif
+
+#if HAVE_PATHS_H
+#  include <paths.h>
+#endif
+
+#ifdef COLLECTD_MNTTAB
+#  undef COLLECTD_MNTTAB
+#endif
+
+#if defined(_PATH_MOUNTED) /* glibc */
+#  define COLLECTD_MNTTAB _PATH_MOUNTED
+#elif defined(MNTTAB) /* Solaris */
+#  define COLLECTD_MNTTAB MNTTAB
+#elif defined(MNT_MNTTAB)
+#  define COLLECTD_MNTTAB MNT_MNTTAB
+#elif defined(MNTTABNAME)
+#  define COLLECTD_MNTTAB MNTTABNAME
+#elif defined(KMTAB)
+#  define COLLECTD_MNTTAB KMTAB
+#else
+#  define COLLECTD_MNTTAB "/etc/mnttab"
+#endif
+
+/* *** *** *** ********************************************* *** *** *** */
+/* *** *** *** *** *** ***   private functions   *** *** *** *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
+
+/* stolen from quota-3.13 (quota-tools) */
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR     "/dev"
+#define UUID   1
+#define VOL    2
+
+static struct uuidCache_s {
+       struct uuidCache_s *next;
+       char uuid[16];
+       char *label;
+       char *device;
+} *uuidCache = NULL;
+
+#define EXT2_SUPER_MAGIC 0xEF53
+struct ext2_super_block {
+       unsigned char s_dummy1[56];
+       unsigned char s_magic[2];
+       unsigned char s_dummy2[46];
+       unsigned char s_uuid[16];
+       char s_volume_name[16];
+};
+#define ext2magic(s) ((unsigned int)s.s_magic[0] \
+       + (((unsigned int)s.s_magic[1]) << 8))
+
+#if HAVE_XFS_XQM_H
+struct xfs_super_block {
+       unsigned char s_magic[4];
+       unsigned char s_dummy[28];
+       unsigned char s_uuid[16];
+       unsigned char s_dummy2[60];
+       char s_fsname[12];
+};
+#endif /* HAVE_XFS_XQM_H */
+
+#define REISER_SUPER_MAGIC "ReIsEr2Fs"
+struct reiserfs_super_block {
+       unsigned char s_dummy1[52];
+       unsigned char s_magic[10];
+       unsigned char s_dummy2[22];
+       unsigned char s_uuid[16];
+       char s_volume_name[16];
+};
+
+/* for now, only ext2 and xfs are supported */
+static int
+get_label_uuid(const char *device, char **label, char *uuid)
+{
+       /* start with ext2 and xfs tests, taken from mount_guess_fstype */
+       /* should merge these later */
+       int fd, rv = 1;
+       size_t namesize;
+       struct ext2_super_block e2sb;
+#if HAVE_XFS_XQM_H
+       struct xfs_super_block xfsb;
+#endif
+       struct reiserfs_super_block reisersb;
+
+       fd = open(device, O_RDONLY);
+       if(fd == -1) {
+               return rv;
+       }
+
+       if(lseek(fd, 1024, SEEK_SET) == 1024
+       && read(fd, (char *)&e2sb, sizeof(e2sb)) == sizeof(e2sb)
+       && ext2magic(e2sb) == EXT2_SUPER_MAGIC) {
+               memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+               namesize = sizeof(e2sb.s_volume_name);
+               *label = smalloc(namesize + 1);
+               sstrncpy(*label, e2sb.s_volume_name, namesize);
+               rv = 0;
+#if HAVE_XFS_XQM_H
+       } else if(lseek(fd, 0, SEEK_SET) == 0
+       && read(fd, (char *)&xfsb, sizeof(xfsb)) == sizeof(xfsb)
+       && (strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC_STR, 4) == 0 ||
+       strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC2_STR, 4) == 0)) {
+               memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
+               namesize = sizeof(xfsb.s_fsname);
+               *label = smalloc(namesize + 1);
+               sstrncpy(*label, xfsb.s_fsname, namesize);
+               rv = 0;
+#endif /* HAVE_XFS_XQM_H */
+       } else if(lseek(fd, 65536, SEEK_SET) == 65536
+       && read(fd, (char *)&reisersb, sizeof(reisersb)) == sizeof(reisersb)
+       && !strncmp((char *)&reisersb.s_magic, REISER_SUPER_MAGIC, 9)) {
+               memcpy(uuid, reisersb.s_uuid, sizeof(reisersb.s_uuid));
+               namesize = sizeof(reisersb.s_volume_name);
+               *label = smalloc(namesize + 1);
+               sstrncpy(*label, reisersb.s_volume_name, namesize);
+               rv = 0;
+       }
+       close(fd);
+       return rv;
+}
+
+static void
+uuidcache_addentry(char *device, char *label, char *uuid)
+{
+       struct uuidCache_s *last;
+
+       if(!uuidCache) {
+               last = uuidCache = smalloc(sizeof(*uuidCache));
+       } else {
+               for(last = uuidCache; last->next; last = last->next);
+               last->next = smalloc(sizeof(*uuidCache));
+               last = last->next;
+       }
+       last->next = NULL;
+       last->device = device;
+       last->label = label;
+       memcpy(last->uuid, uuid, sizeof(last->uuid));
+}
+
+static void
+uuidcache_init(void)
+{
+       char line[100];
+       char *s;
+       int ma, mi, sz;
+       static char ptname[100];
+       FILE *procpt;
+       char uuid[16], *label = NULL;
+       char device[110];
+       int firstPass;
+       int handleOnFirst;
+
+       if(uuidCache) {
+               return;
+       }
+
+       procpt = fopen(PROC_PARTITIONS, "r");
+       if(procpt == NULL) {
+               return;
+       }
+
+       for(firstPass = 1; firstPass >= 0; firstPass--) {
+               fseek(procpt, 0, SEEK_SET);
+               while(fgets(line, sizeof(line), procpt)) {
+                       if(sscanf(line, " %d %d %d %[^\n ]",
+                               &ma, &mi, &sz, ptname) != 4)
+                       {
+                               continue;
+                       }
+
+                       /* skip extended partitions (heuristic: size 1) */
+                       if(sz == 1) {
+                               continue;
+                       }
+
+                       /* look only at md devices on first pass */
+                       handleOnFirst = !strncmp(ptname, "md", 2);
+                       if(firstPass != handleOnFirst) {
+                               continue;
+                       }
+
+                       /* skip entire disk (minor 0, 64, ... on ide;
+                       0, 16, ... on sd) */
+                       /* heuristic: partition name ends in a digit */
+
+                       for(s = ptname; *s; s++);
+
+                       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.)
+                       */
+                               ssnprintf(device, sizeof(device), "%s/%s",
+                                       DEVLABELDIR, ptname);
+                               if(!get_label_uuid(device, &label, uuid)) {
+                                       uuidcache_addentry(sstrdup(device),
+                                               label, uuid);
+                               }
+                       }
+               }
+       }
+       fclose(procpt);
+}
+
+static unsigned char
+fromhex(char c)
+{
+       if(isdigit((int)c)) {
+               return (c - '0');
+       } else if(islower((int)c)) {
+               return (c - 'a' + 10);
+       } else {
+               return (c - 'A' + 10);
+       }
+}
+
+static char *
+get_spec_by_x(int n, const char *t)
+{
+       struct uuidCache_s *uc;
+
+       uuidcache_init();
+       uc = uuidCache;
+
+       while(uc) {
+               switch(n) {
+               case UUID:
+                       if(!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
+                               return sstrdup(uc->device);
+                       }
+                       break;
+               case VOL:
+                       if(!strcmp(t, uc->label)) {
+                               return sstrdup(uc->device);
+                       }
+                       break;
+               }
+               uc = uc->next;
+       }
+       return NULL;
+}
+
+static char *
+get_spec_by_uuid(const char *s)
+{
+       char uuid[16];
+       int i;
+
+       if(strlen(s) != 36
+       || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-') {
+               goto bad_uuid;
+       }
+
+       for(i=0; i<16; i++) {
+               if(*s == '-') {
+                       s++;
+               }
+               if(!isxdigit((int)s[0]) || !isxdigit((int)s[1])) {
+                       goto bad_uuid;
+               }
+               uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1]));
+               s += 2;
+       }
+       return get_spec_by_x(UUID, uuid);
+
+       bad_uuid:
+               DEBUG("utils_mount: Found an invalid UUID: %s", s);
+       return NULL;
+}
+
+static char *get_spec_by_volume_label(const char *s)
+{
+        return get_spec_by_x (VOL, s);
+}
+
+static char *get_device_name(const char *optstr)
+{
+       char *rc;
+
+       if (optstr == NULL)
+       {
+               return (NULL);
+       }
+       else if (strncmp (optstr, "UUID=", 5) == 0)
+       {
+               DEBUG ("utils_mount: TODO: check UUID= code!");
+               rc = get_spec_by_uuid (optstr + 5);
+       }
+       else if (strncmp (optstr, "LABEL=", 6) == 0)
+       {
+               DEBUG ("utils_mount: TODO: check LABEL= code!");
+               rc = get_spec_by_volume_label (optstr + 6);
+       }
+       else
+       {
+               rc = sstrdup (optstr);
+       }
+
+       if(!rc)
+       {
+               DEBUG ("utils_mount: Error checking device name: optstr = %s", optstr);
+       }
+       return rc;
+}
+
+/* What weird OS is this..? I can't find any info with google :/ -octo */
+#if HAVE_LISTMNTENT && 0
+static cu_mount_t *cu_mount_listmntent (void)
+{
+       cu_mount_t *last = *list;
+       struct tabmntent *p;
+       struct mntent *mnt;
+
+       struct tabmntent *mntlist;
+       if(listmntent(&mntlist, COLLECTD_MNTTAB, NULL, NULL) < 0) {
+#if COLLECT_DEBUG
+               char errbuf[1024];
+               DEBUG("utils_mount: calling listmntent() failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif /* COLLECT_DEBUG */
+       }
+
+       for(p = mntlist; p; p = p->next) {
+               char *loop = NULL, *device = NULL;
+
+               mnt = p->ment;
+               loop = cu_mount_getoptionvalue(mnt->mnt_opts, "loop=");
+               if(loop == NULL) {   /* no loop= mount */
+                       device = get_device_name(mnt->mnt_fsname);
+                       if(device == NULL) {
+                               DEBUG("utils_mount: can't get devicename for fs (%s) %s (%s)"
+                                       ": ignored", mnt->mnt_type,
+                                       mnt->mnt_dir, mnt->mnt_fsname);
+                               continue;
+                       }
+               } else {
+                       device = loop;
+               }
+               if(*list == NULL) {
+                       *list = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
+                       last = *list;
+               } else {
+                       while(last->next != NULL) { /* is last really last? */
+                               last = last->next;
+                       }
+                       last->next = (cu_mount_t *)smalloc(sizeof(cu_mount_t));
+                       last = last->next;
+               }
+               last->dir = sstrdup(mnt->mnt_dir);
+               last->spec_device = sstrdup(mnt->mnt_fsname);
+               last->device = device;
+               last->type = sstrdup(mnt->mnt_type);
+               last->options = sstrdup(mnt->mnt_opts);
+               last->next = NULL;
+       } /* for(p = mntlist; p; p = p->next) */
+
+       return(last);
+} /* cu_mount_t *cu_mount_listmntent(void) */
+/* #endif HAVE_LISTMNTENT */
+
+/* 4.4BSD and Mac OS X (getfsstat) or NetBSD (getvfsstat) */
+#elif HAVE_GETVFSSTAT || HAVE_GETFSSTAT
+static cu_mount_t *cu_mount_getfsstat (void)
+{
+#if HAVE_GETVFSSTAT
+#  define STRUCT_STATFS struct statvfs
+#  define CMD_STATFS    getvfsstat
+#  define FLAGS_STATFS  ST_NOWAIT
+/* #endif HAVE_GETVFSSTAT */
+#elif HAVE_GETFSSTAT
+#  define STRUCT_STATFS struct statfs
+#  define CMD_STATFS    getfsstat
+#  define FLAGS_STATFS  MNT_NOWAIT
+#endif /* HAVE_GETFSSTAT */
+
+       int bufsize;
+       STRUCT_STATFS *buf;
+
+       int num;
+       int i;
+
+       cu_mount_t *first = NULL;
+       cu_mount_t *last  = NULL;
+       cu_mount_t *new   = NULL;
+
+       /* Get the number of mounted file systems */
+       if ((bufsize = CMD_STATFS (NULL, 0, FLAGS_STATFS)) < 1)
+       {
+#if COLLECT_DEBUG
+               char errbuf[1024];
+               DEBUG ("utils_mount: getv?fsstat failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif /* COLLECT_DEBUG */
+               return (NULL);
+       }
+
+       if ((buf = (STRUCT_STATFS *) malloc (bufsize * sizeof (STRUCT_STATFS)))
+                       == NULL)
+               return (NULL);
+       memset (buf, '\0', bufsize * sizeof (STRUCT_STATFS));
+
+       /* The bufsize needs to be passed in bytes. Really. This is not in the
+        * manpage.. -octo */
+       if ((num = CMD_STATFS (buf, bufsize * sizeof (STRUCT_STATFS), FLAGS_STATFS)) < 1)
+       {
+#if COLLECT_DEBUG
+               char errbuf[1024];
+               DEBUG ("utils_mount: getv?fsstat failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+#endif /* COLLECT_DEBUG */
+               free (buf);
+               return (NULL);
+       }
+
+       for (i = 0; i < num; i++)
+       {
+               if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+                       break;
+               memset (new, '\0', sizeof (cu_mount_t));
+               
+               /* Copy values from `struct mnttab' */
+               new->dir         = sstrdup (buf[i].f_mntonname);
+               new->spec_device = sstrdup (buf[i].f_mntfromname);
+               new->type        = sstrdup (buf[i].f_fstypename);
+               new->options     = NULL;
+               new->device      = get_device_name (new->options);
+               new->next = NULL;
+
+               /* Append to list */
+               if (first == NULL)
+               {
+                       first = new;
+                       last  = new;
+               }
+               else
+               {
+                       last->next = new;
+                       last       = new;
+               }
+       }
+
+       free (buf);
+
+       return (first);
+}
+/* #endif HAVE_GETVFSSTAT || HAVE_GETFSSTAT */
+
+/* Solaris (SunOS 10): int getmntent(FILE *fp, struct mnttab *mp); */
+#elif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT
+static cu_mount_t *cu_mount_gen_getmntent (void)
+{
+       struct mnttab mt;
+       FILE *fp;
+
+       cu_mount_t *first = NULL;
+       cu_mount_t *last  = NULL;
+       cu_mount_t *new   = NULL;
+
+       DEBUG ("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB);
+
+       if ((fp = fopen (COLLECTD_MNTTAB, "r")) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("fopen (%s): %s", COLLECTD_MNTTAB,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (NULL);
+       }
+
+       while (getmntent (fp, &mt) == 0)
+       {
+               if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+                       break;
+               memset (new, '\0', sizeof (cu_mount_t));
+               
+               /* Copy values from `struct mnttab' */
+               new->dir         = sstrdup (mt.mnt_mountp);
+               new->spec_device = sstrdup (mt.mnt_special);
+               new->type        = sstrdup (mt.mnt_fstype);
+               new->options     = sstrdup (mt.mnt_mntopts);
+               new->device      = get_device_name (new->options);
+               new->next = NULL;
+
+               /* Append to list */
+               if (first == NULL)
+               {
+                       first = new;
+                       last  = new;
+               }
+               else
+               {
+                       last->next = new;
+                       last       = new;
+               }
+       }
+
+       fclose (fp);
+
+       return (first);
+} /* static cu_mount_t *cu_mount_gen_getmntent (void) */
+/* #endif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT */
+
+#elif HAVE_SEQ_GETMNTENT
+#warn "This version of `getmntent' hat not yet been implemented!"
+/* #endif HAVE_SEQ_GETMNTENT */
+
+#elif HAVE_ONE_GETMNTENT
+static cu_mount_t *cu_mount_getmntent (void)
+{
+       FILE *fp;
+       struct mntent *me;
+
+       cu_mount_t *first = NULL;
+       cu_mount_t *last  = NULL;
+       cu_mount_t *new   = NULL;
+
+       DEBUG ("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB);
+
+       if ((fp = setmntent (COLLECTD_MNTTAB, "r")) == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("setmntent (%s): %s", COLLECTD_MNTTAB,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (NULL);
+       }
+
+       while ((me = getmntent (fp)) != NULL)
+       {
+               if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+                       break;
+               memset (new, '\0', sizeof (cu_mount_t));
+               
+               /* Copy values from `struct mntent *' */
+               new->dir         = sstrdup (me->mnt_dir);
+               new->spec_device = sstrdup (me->mnt_fsname);
+               new->type        = sstrdup (me->mnt_type);
+               new->options     = sstrdup (me->mnt_opts);
+               new->device      = get_device_name (new->options);
+               new->next        = NULL;
+
+               DEBUG ("utils_mount: new = {dir = %s, spec_device = %s, type = %s, options = %s, device = %s}",
+                               new->dir, new->spec_device, new->type, new->options, new->device);
+
+               /* Append to list */
+               if (first == NULL)
+               {
+                       first = new;
+                       last  = new;
+               }
+               else
+               {
+                       last->next = new;
+                       last       = new;
+               }
+       }
+
+       endmntent (fp);
+
+       DEBUG ("utils_mount: return (0x%p)", (void *) first);
+
+       return (first);
+}
+#endif /* HAVE_ONE_GETMNTENT */
+
+/* *** *** *** ******************************************** *** *** *** */
+/* *** *** *** *** *** ***   public functions   *** *** *** *** *** *** */
+/* *** *** *** ******************************************** *** *** *** */
+
+cu_mount_t *cu_mount_getlist(cu_mount_t **list)
+{
+       cu_mount_t *new;
+       cu_mount_t *first = NULL;
+       cu_mount_t *last  = NULL;
+
+       if (list == NULL)
+               return (NULL);
+
+       if (*list != NULL)
+       {
+               first = *list;
+               last  =  first;
+               while (last->next != NULL)
+                       last = last->next;
+       }
+
+#if HAVE_LISTMNTENT && 0
+       new = cu_mount_listmntent ();
+#elif HAVE_GETVFSSTAT || HAVE_GETFSSTAT
+       new = cu_mount_getfsstat ();
+#elif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT
+       new = cu_mount_gen_getmntent ();
+#elif HAVE_SEQ_GETMNTENT
+# error "This version of `getmntent' hat not yet been implemented!"
+#elif HAVE_ONE_GETMNTENT
+       new = cu_mount_getmntent ();
+#else
+# error "Could not determine how to find mountpoints."
+#endif
+
+       if (first != NULL)
+       {
+               last->next = new;
+       }
+       else
+       {
+               first = new;
+               last  = new;
+               *list = first;
+       }
+
+       while ((last != NULL) && (last->next != NULL))
+               last = last->next;
+
+       return (last);
+} /* cu_mount_t *cu_mount_getlist(cu_mount_t **list) */
+
+void cu_mount_freelist (cu_mount_t *list)
+{
+       cu_mount_t *this;
+       cu_mount_t *next;
+
+       for (this = list; this != NULL; this = next)
+       {
+               next = this->next;
+
+               sfree (this->dir);
+               sfree (this->spec_device);
+               sfree (this->device);
+               sfree (this->type);
+               sfree (this->options);
+               sfree (this);
+       }
+} /* void cu_mount_freelist(cu_mount_t *list) */
+
+char *
+cu_mount_checkoption(char *line, char *keyword, int full)
+{
+       char *line2, *l2;
+       int l = strlen(keyword);
+       char *p1, *p2;
+
+       if(line == NULL || keyword == NULL) {
+               return NULL;
+       }
+       if(full != 0) {
+               full = 1;
+       }
+
+       line2 = sstrdup(line);
+       l2 = line2;
+       while(*l2 != '\0') {
+               if(*l2 == ',') {
+                       *l2 = '\0';
+               }
+               l2++;
+       }
+
+       p1 = line - 1;
+       p2 = strchr(line, ',');
+       do {
+               if(strncmp(line2+(p1-line)+1, keyword, l+full) == 0) {
+                       free(line2);
+                       return p1+1;
+               }
+               p1 = p2;
+               if(p1 != NULL) {
+                       p2 = strchr(p1+1, ',');
+               }
+       } while(p1 != NULL);
+
+       free(line2);
+       return NULL;
+} /* char *cu_mount_checkoption(char *line, char *keyword, int full) */
+
+char *
+cu_mount_getoptionvalue(char *line, char *keyword)
+{
+       char *r;
+
+       r = cu_mount_checkoption(line, keyword, 0);
+       if(r != NULL) {
+               char *p;
+               r += strlen(keyword);
+               p = strchr(r, ',');
+               if(p == NULL) {
+                       return sstrdup(r);
+               } else {
+                       char *m;
+                       if((p-r) == 1) {
+                               return NULL;
+                       }
+                       m = (char *)smalloc(p-r+1);
+                       sstrncpy(m, r, p-r+1);
+                       return m;
+               }
+       }
+       return r;
+} /* char *cu_mount_getoptionvalue(char *line, char *keyword) */
+
+int
+cu_mount_type(const char *type)
+{
+       if(strcmp(type, "ext3") == 0) return CUMT_EXT3;
+       if(strcmp(type, "ext2") == 0) return CUMT_EXT2;
+       if(strcmp(type, "ufs")  == 0) return CUMT_UFS;
+       if(strcmp(type, "vxfs") == 0) return CUMT_VXFS;
+       if(strcmp(type, "zfs")  == 0) return CUMT_ZFS;
+       return CUMT_UNKNOWN;
+} /* int cu_mount_type(const char *type) */
+
diff --git a/src/utils_mount.h b/src/utils_mount.h
new file mode 100644 (file)
index 0000000..bc0077f
--- /dev/null
@@ -0,0 +1,189 @@
+/**
+ * collectd - src/utils_mount.h
+ * Copyright (C) 2005,2006  Niki W. Waibel
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Author:
+ *   Niki W. Waibel <niki.waibel@gmx.net>
+**/
+
+/* See below for instructions how to use the public functions. */
+
+#ifndef COLLECTD_UTILS_MOUNT_H
+#define COLLECTD_UTILS_MOUNT_H 1
+
+#include <stdio.h>
+#if HAVE_FS_INFO_H
+# include <fs_info.h>
+#endif
+#if HAVE_FSHELP_H
+# include <fshelp.h>
+#endif
+#if HAVE_PATHS_H
+# include <paths.h>
+#endif
+#if HAVE_MNTENT_H
+# include <mntent.h>
+#endif
+#if HAVE_MNTTAB_H
+# include <mnttab.h>
+#endif
+#if HAVE_SYS_FSTYP_H
+# include <sys/fstyp.h>
+#endif
+#if HAVE_SYS_FS_TYPES_H
+# include <sys/fs_types.h>
+#endif
+#if HAVE_SYS_MNTENT_H
+# include <sys/mntent.h>
+#endif
+#if HAVE_SYS_MNTTAB_H
+# include <sys/mnttab.h>
+#endif
+#if HAVE_SYS_MOUNT_H
+# include <sys/mount.h>
+#endif
+#if HAVE_SYS_STATFS_H
+# include <sys/statfs.h>
+#endif
+#if HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+#if HAVE_SYS_VFSTAB_H
+# include <sys/vfstab.h>
+#endif
+
+/* Collectd Utils Mount Type */
+#define CUMT_UNKNOWN (0)
+#define CUMT_EXT2    (1)
+#define CUMT_EXT3    (2)
+#define CUMT_XFS     (3)
+#define CUMT_UFS     (4)
+#define CUMT_VXFS    (5)
+#define CUMT_ZFS     (6)
+
+typedef struct _cu_mount_t cu_mount_t;
+struct _cu_mount_t {
+       char *dir;         /* "/sys" or "/" */
+       char *spec_device; /* "LABEL=/" or "none" or "proc" or "/dev/hda1" */
+       char *device;      /* "none" or "proc" or "/dev/hda1" */
+       char *type;        /* "sysfs" or "ext3" */
+       char *options;     /* "rw,noatime,commit=600,quota,grpquota" */
+       cu_mount_t *next;
+};
+
+cu_mount_t *cu_mount_getlist(cu_mount_t **list);
+/*
+  DESCRIPTION
+       The cu_mount_getlist() function creates a list
+       of all mountpoints.
+
+       If *list is NULL, a new list is created and *list is
+       set to point to the first entry.
+
+       If *list is not NULL, the list of mountpoints is appended
+       and *list is not changed.
+
+  RETURN VALUE
+       The cu_mount_getlist() function returns a pointer to
+       the last entry of the list, or NULL if an error has
+       occured.
+
+  NOTES
+       In case of an error, *list is not modified.
+*/
+
+void cu_mount_freelist(cu_mount_t *list);
+/*
+  DESCRIPTION
+       The cu_mount_freelist() function free()s all memory
+       allocated by *list and *list itself as well.
+*/
+
+char *cu_mount_checkoption(char *line, char *keyword, int full);
+/*
+  DESCRIPTION
+       The cu_mount_checkoption() function is a replacement of
+       char *hasmntopt(const struct mntent *mnt, const char *opt).
+       In fact hasmntopt() just looks for the first occurrence of the
+       characters at opt in mnt->mnt_opts. cu_mount_checkoption()
+       checks for the *option* keyword in line, starting at the
+       first character of line or after a ','.
+
+       If full is not 0 then also the end of keyword has to match
+       either the end of line or a ',' after keyword.
+
+  RETURN VALUE
+       The cu_mount_checkoption() function returns a pointer into
+       string line if a match of keyword is found. If no match is
+       found cu_mount_checkoption() returns NULL.
+
+  NOTES
+       Do *not* try to free() the pointer which is returned! It is
+       just part of the string line.
+
+       full should be set to 0 when matching options like: rw, quota,
+       noatime. Set full to 1 when matching options like: loop=,
+       gid=, commit=.
+
+  EXAMPLES
+       If line is "rw,usrquota,grpquota", keyword is "quota", NULL
+       will be returned (independend of full).
+
+       If line is "rw,usrquota,grpquota", keyword is "usrquota",
+       a pointer to "usrquota,grpquota" is returned (independend
+       of full).
+
+       If line is "rw,loop=/dev/loop1,quota", keyword is "loop="
+       and full is 0, then a pointer to "loop=/dev/loop1,quota"
+       is returned. If full is not 0 then NULL is returned. But
+       maybe you might want to try cu_mount_getoptionvalue()...
+*/
+
+char *cu_mount_getoptionvalue(char *line, char *keyword);
+/*
+  DESCRIPTION
+       The cu_mount_getoptionvalue() function can be used to grab
+       a VALUE out of a mount option (line) like:
+               loop=VALUE
+       whereas "loop=" is the keyword.
+
+  RETURN VALUE
+       If the cu_mount_getoptionvalue() function can find the option
+       keyword in line, then memory is allocated for the value of
+       that option and a pointer to that value is returned.
+
+       If the option keyword is not found, cu_mount_getoptionvalue()
+       returns NULL;
+
+  NOTES
+       Internally it calls cu_mount_checkoption(), then it
+       allocates memory for VALUE and returns a pointer to that
+       string. So *do not forget* to free() the memory returned
+       after use!!!
+*/
+
+int cu_mount_type(const char *type);
+/*
+  DESCRIPTION
+
+  RETURN VALUE
+*/
+
+
+#endif /* !COLLECTD_UTILS_MOUNT_H */
+
diff --git a/src/utils_mount_test.c b/src/utils_mount_test.c
new file mode 100644 (file)
index 0000000..c5ffbfb
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+ * collectd - src/tests/test_utils_mount.c
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "testing.h"
+#include "collectd.h"
+#include "utils_mount.h"
+
+DEF_TEST(cu_mount_checkoption)
+{
+  char line_opts[] = "foo=one,bar=two,qux=three";
+  char *foo = strstr (line_opts, "foo");
+  char *bar = strstr (line_opts, "bar");
+  char *qux = strstr (line_opts, "qux");
+
+  char line_bool[] = "one,two,three";
+  char *one = strstr (line_bool, "one");
+  char *two = strstr (line_bool, "two");
+  char *three = strstr (line_bool, "three");
+
+  /* Normal operation */
+  OK (foo == cu_mount_checkoption (line_opts, "foo", 0));
+  OK (bar == cu_mount_checkoption (line_opts, "bar", 0));
+  OK (qux == cu_mount_checkoption (line_opts, "qux", 0));
+  OK (NULL == cu_mount_checkoption (line_opts, "unknown", 0));
+
+  OK (one == cu_mount_checkoption (line_bool, "one", 0));
+  OK (two == cu_mount_checkoption (line_bool, "two", 0));
+  OK (three == cu_mount_checkoption (line_bool, "three", 0));
+  OK (NULL == cu_mount_checkoption (line_bool, "four", 0));
+
+  /* Shorter and longer parts */
+  OK (foo == cu_mount_checkoption (line_opts, "fo", 0));
+  OK (bar == cu_mount_checkoption (line_opts, "bar=", 0));
+  OK (qux == cu_mount_checkoption (line_opts, "qux=thr", 0));
+
+  OK (one == cu_mount_checkoption (line_bool, "o", 0));
+  OK (two == cu_mount_checkoption (line_bool, "tw", 0));
+  OK (three == cu_mount_checkoption (line_bool, "thr", 0));
+
+  /* "full" flag */
+  OK (one == cu_mount_checkoption (line_bool, "one", 1));
+  OK (two == cu_mount_checkoption (line_bool, "two", 1));
+  OK (three == cu_mount_checkoption (line_bool, "three", 1));
+  OK (NULL == cu_mount_checkoption (line_bool, "four", 1));
+
+  OK (NULL == cu_mount_checkoption (line_bool, "o", 1));
+  OK (NULL == cu_mount_checkoption (line_bool, "tw", 1));
+  OK (NULL == cu_mount_checkoption (line_bool, "thr", 1));
+
+  return (0);
+}
+DEF_TEST(cu_mount_getoptionvalue)
+{
+  char line_opts[] = "foo=one,bar=two,qux=three";
+  char line_bool[] = "one,two,three";
+
+  STREQ ("one", cu_mount_getoptionvalue (line_opts, "foo="));
+  STREQ ("two", cu_mount_getoptionvalue (line_opts, "bar="));
+  STREQ ("three", cu_mount_getoptionvalue (line_opts, "qux="));
+  OK (NULL == cu_mount_getoptionvalue (line_opts, "unknown="));
+
+  STREQ ("", cu_mount_getoptionvalue (line_bool, "one"));
+  STREQ ("", cu_mount_getoptionvalue (line_bool, "two"));
+  STREQ ("", cu_mount_getoptionvalue (line_bool, "three"));
+  OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
+
+  return (0);
+}
+
+int main (void)
+{
+  RUN_TEST(cu_mount_checkoption);
+  RUN_TEST(cu_mount_getoptionvalue);
+
+  END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/utils_parse_option.c b/src/utils_parse_option.c
new file mode 100644 (file)
index 0000000..7f06f29
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ * collectd - src/utils_parse_option.c
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_parse_option.h"
+
+int parse_string (char **ret_buffer, char **ret_string)
+{
+  char *buffer;
+  char *string;
+
+  buffer = *ret_buffer;
+
+  /* Eat up leading spaces. */
+  string = buffer;
+  while (isspace ((int) *string))
+    string++;
+  if (*string == 0)
+    return (1);
+
+  /* A quoted string */
+  if (*string == '"')
+  {
+    char *dst;
+
+    string++;
+    if (*string == 0)
+      return (1);
+
+    dst = string;
+    buffer = string;
+    while ((*buffer != '"') && (*buffer != 0))
+    {
+      /* Un-escape backslashes */
+      if (*buffer == '\\')
+      {
+        buffer++;
+        /* Catch a backslash at the end of buffer */
+        if (*buffer == 0)
+          return (-1);
+      }
+      *dst = *buffer;
+      buffer++;
+      dst++;
+    }
+    /* No quote sign has been found */
+    if (*buffer == 0)
+      return (-1);
+
+    *dst = 0;
+    dst++;
+    *buffer = 0;
+    buffer++;
+
+    /* Check for trailing spaces. */
+    if ((*buffer != 0) && !isspace ((int) *buffer))
+      return (-1);
+  }
+  else /* an unquoted string */
+  {
+    buffer = string;
+    while ((*buffer != 0) && !isspace ((int) *buffer))
+      buffer++;
+    if (*buffer != 0)
+    {
+      *buffer = 0;
+      buffer++;
+    }
+  }
+  
+  /* Eat up trailing spaces */
+  while (isspace ((int) *buffer))
+    buffer++;
+
+  *ret_buffer = buffer;
+  *ret_string = string;
+
+  return (0);
+} /* int parse_string */
+
+/*
+ * parse_option
+ * ------------
+ *  Parses an ``option'' as used with the unixsock and exec commands. An
+ *  option is of the form:
+ *    name0="value"
+ *    name1="value with \"quotes\""
+ *    name2="value \\ backslash"
+ *  However, if the value does *not* contain a space character, you can skip
+ *  the quotes.
+ */
+int parse_option (char **ret_buffer, char **ret_key, char **ret_value)
+{
+  char *buffer;
+  char *key;
+  char *value;
+  int status;
+
+  buffer = *ret_buffer;
+
+  /* Eat up leading spaces */
+  key = buffer;
+  while (isspace ((int) *key))
+    key++;
+  if (*key == 0)
+    return (1);
+
+  /* Look for the equal sign */
+  buffer = key;
+  while (isalnum ((int) *buffer) || *buffer == '_' || *buffer == ':')
+    buffer++;
+  if ((*buffer != '=') || (buffer == key))
+    return (1);
+  *buffer = 0;
+  buffer++;
+  /* Empty values must be written as "" */
+  if (isspace ((int) *buffer) || (*buffer == 0))
+    return (-1);
+
+  status = parse_string (&buffer, &value);
+  if (status != 0)
+    return (-1);
+
+  /* NB: parse_string will have eaten up all trailing spaces. */
+
+  *ret_buffer = buffer;
+  *ret_key = key;
+  *ret_value = value;
+
+  return (0);
+} /* int parse_option */
+
+/* vim: set sw=2 ts=8 tw=78 et : */
diff --git a/src/utils_parse_option.h b/src/utils_parse_option.h
new file mode 100644 (file)
index 0000000..885a6a3
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * collectd - src/utils_parse_option.h
+ * Copyright (C) 2008       Florian Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_PARSE_OPTION
+#define UTILS_PARSE_OPTION 1
+
+int parse_string (char **ret_buffer, char **ret_string);
+int parse_option (char **ret_buffer, char **ret_key, char **ret_value);
+
+#endif /* UTILS_PARSE_OPTION */
+
+/* vim: set sw=2 ts=8 tw=78 et : */
diff --git a/src/utils_rrdcreate.c b/src/utils_rrdcreate.c
new file mode 100644 (file)
index 0000000..0e2d86c
--- /dev/null
@@ -0,0 +1,734 @@
+/**
+ * collectd - src/utils_rrdcreate.c
+ * Copyright (C) 2006-2013  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_rrdcreate.h"
+
+#include <pthread.h>
+#include <rrd.h>
+
+struct srrd_create_args_s
+{
+  char *filename;
+  unsigned long pdp_step;
+  time_t last_up;
+  int argc;
+  char **argv;
+};
+typedef struct srrd_create_args_s srrd_create_args_t;
+
+struct async_create_file_s;
+typedef struct async_create_file_s async_create_file_t;
+struct async_create_file_s
+{
+  char *filename;
+  async_create_file_t *next;
+};
+
+/*
+ * Private variables
+ */
+static int rra_timespans[] =
+{
+  3600,
+  86400,
+  604800,
+  2678400,
+  31622400
+};
+static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
+
+static char *rra_types[] =
+{
+  "AVERAGE",
+  "MIN",
+  "MAX"
+};
+static int rra_types_num = STATIC_ARRAY_SIZE (rra_types);
+
+#if !defined(HAVE_THREADSAFE_LIBRRD) || !HAVE_THREADSAFE_LIBRRD
+static pthread_mutex_t librrd_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static async_create_file_t *async_creation_list = NULL;
+static pthread_mutex_t async_creation_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * Private functions
+ */
+static void rra_free (int rra_num, char **rra_def) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < rra_num; i++)
+  {
+    sfree (rra_def[i]);
+  }
+  sfree (rra_def);
+} /* }}} void rra_free */
+
+static void srrd_create_args_destroy (srrd_create_args_t *args)
+{
+  if (args == NULL)
+    return;
+
+  sfree (args->filename);
+  if (args->argv != NULL)
+  {
+    int i;
+    for (i = 0; i < args->argc; i++)
+      sfree (args->argv[i]);
+    sfree (args->argv);
+  }
+  sfree (args);
+} /* void srrd_create_args_destroy */
+
+static srrd_create_args_t *srrd_create_args_create (const char *filename,
+    unsigned long pdp_step, time_t last_up,
+    int argc, const char **argv)
+{
+  srrd_create_args_t *args;
+
+  args = malloc (sizeof (*args));
+  if (args == NULL)
+  {
+    ERROR ("srrd_create_args_create: malloc failed.");
+    return (NULL);
+  }
+  memset (args, 0, sizeof (*args));
+  args->filename = NULL;
+  args->pdp_step = pdp_step;
+  args->last_up = last_up;
+  args->argv = NULL;
+
+  args->filename = strdup (filename);
+  if (args->filename == NULL)
+  {
+    ERROR ("srrd_create_args_create: strdup failed.");
+    srrd_create_args_destroy (args);
+    return (NULL);
+  }
+
+  args->argv = calloc ((size_t) (argc + 1), sizeof (*args->argv));
+  if (args->argv == NULL)
+  {
+    ERROR ("srrd_create_args_create: calloc failed.");
+    srrd_create_args_destroy (args);
+    return (NULL);
+  }
+
+  for (args->argc = 0; args->argc < argc; args->argc++)
+  {
+    args->argv[args->argc] = strdup (argv[args->argc]);
+    if (args->argv[args->argc] == NULL)
+    {
+      ERROR ("srrd_create_args_create: strdup failed.");
+      srrd_create_args_destroy (args);
+      return (NULL);
+    }
+  }
+  assert (args->argc == argc);
+  args->argv[args->argc] = NULL;
+
+  return (args);
+} /* srrd_create_args_t *srrd_create_args_create */
+
+/* * * * * * * * * *
+ * WARNING:  Magic *
+ * * * * * * * * * */
+static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */
+    const rrdcreate_config_t *cfg)
+{
+  char **rra_def;
+  int rra_num;
+
+  int *rts;
+  int  rts_num;
+
+  int rra_max;
+
+  int span;
+
+  int cdp_num;
+  int cdp_len;
+  int i, j;
+
+  char buffer[128];
+
+  /* The stepsize we use here: If it is user-set, use it. If not, use the
+   * interval of the value-list. */
+  int ss;
+
+  if (cfg->rrarows <= 0)
+  {
+    *ret = NULL;
+    return (-1);
+  }
+
+  if ((cfg->xff < 0) || (cfg->xff >= 1.0))
+  {
+    *ret = NULL;
+    return (-1);
+  }
+
+  if (cfg->stepsize > 0)
+    ss = cfg->stepsize;
+  else
+    ss = (int) CDTIME_T_TO_TIME_T (vl->interval);
+  if (ss <= 0)
+  {
+    *ret = NULL;
+    return (-1);
+  }
+
+  /* Use the configured timespans or fall back to the built-in defaults */
+  if (cfg->timespans_num != 0)
+  {
+    rts = cfg->timespans;
+    rts_num = cfg->timespans_num;
+  }
+  else
+  {
+    rts = rra_timespans;
+    rts_num = rra_timespans_num;
+  }
+
+  rra_max = rts_num * rra_types_num;
+
+  if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
+    return (-1);
+  memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
+  rra_num = 0;
+
+  cdp_len = 0;
+  for (i = 0; i < rts_num; i++)
+  {
+    span = rts[i];
+
+    if ((span / ss) < cfg->rrarows)
+      span = ss * cfg->rrarows;
+
+    if (cdp_len == 0)
+      cdp_len = 1;
+    else
+      cdp_len = (int) floor (((double) span)
+          / ((double) (cfg->rrarows * ss)));
+
+    cdp_num = (int) ceil (((double) span)
+        / ((double) (cdp_len * ss)));
+
+    for (j = 0; j < rra_types_num; j++)
+    {
+      int status;
+
+      if (rra_num >= rra_max)
+        break;
+
+      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)))
+      {
+        ERROR ("rra_get: Buffer would have been truncated.");
+        continue;
+      }
+
+      rra_def[rra_num++] = sstrdup (buffer);
+    }
+  }
+
+  *ret = rra_def;
+  return (rra_num);
+} /* }}} int rra_get */
+
+static void ds_free (int ds_num, char **ds_def) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ds_num; i++)
+    if (ds_def[i] != NULL)
+      free (ds_def[i]);
+  free (ds_def);
+} /* }}} void ds_free */
+
+static int ds_get (char ***ret, /* {{{ */
+    const data_set_t *ds, const value_list_t *vl,
+    const rrdcreate_config_t *cfg)
+{
+  char **ds_def;
+  int ds_num;
+
+  char min[32];
+  char max[32];
+  char buffer[128];
+
+  ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
+  if (ds_def == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("rrdtool plugin: malloc failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+  memset (ds_def, '\0', ds->ds_num * sizeof (char *));
+
+  for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
+  {
+    data_source_t *d = ds->ds + ds_num;
+    char *type;
+    int status;
+
+    ds_def[ds_num] = NULL;
+
+    if (d->type == DS_TYPE_COUNTER)
+      type = "COUNTER";
+    else if (d->type == DS_TYPE_GAUGE)
+      type = "GAUGE";
+    else if (d->type == DS_TYPE_DERIVE)
+      type = "DERIVE";
+    else if (d->type == DS_TYPE_ABSOLUTE)
+      type = "ABSOLUTE";
+    else
+    {
+      ERROR ("rrdtool plugin: Unknown DS type: %i",
+          d->type);
+      break;
+    }
+
+    if (isnan (d->min))
+    {
+      sstrncpy (min, "U", sizeof (min));
+    }
+    else
+      ssnprintf (min, sizeof (min), "%f", d->min);
+
+    if (isnan (d->max))
+    {
+      sstrncpy (max, "U", sizeof (max));
+    }
+    else
+      ssnprintf (max, sizeof (max), "%f", d->max);
+
+    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),
+        min, max);
+    if ((status < 1) || ((size_t) status >= sizeof (buffer)))
+      break;
+
+    ds_def[ds_num] = sstrdup (buffer);
+  } /* for ds_num = 0 .. ds->ds_num */
+
+  if (ds_num != ds->ds_num)
+  {
+    ds_free (ds_num, ds_def);
+    return (-1);
+  }
+
+  *ret = ds_def;
+  return (ds_num);
+} /* }}} int ds_get */
+
+#if HAVE_THREADSAFE_LIBRRD
+static int srrd_create (const char *filename, /* {{{ */
+    unsigned long pdp_step, time_t last_up,
+    int argc, const char **argv)
+{
+  int status;
+  char *filename_copy;
+
+  if ((filename == NULL) || (argv == NULL))
+    return (-EINVAL);
+
+  /* Some versions of librrd don't have the `const' qualifier for the first
+   * argument, so we have to copy the pointer here to avoid warnings. It sucks,
+   * but what else can we do? :(  -octo */
+  filename_copy = strdup (filename);
+  if (filename_copy == NULL)
+  {
+    ERROR ("srrd_create: strdup failed.");
+    return (-ENOMEM);
+  }
+
+  optind = 0; /* bug in librrd? */
+  rrd_clear_error ();
+
+  status = rrd_create_r (filename_copy, pdp_step, last_up,
+      argc, (void *) argv);
+
+  if (status != 0)
+  {
+    WARNING ("rrdtool plugin: rrd_create_r (%s) failed: %s",
+        filename, rrd_get_error ());
+  }
+
+  sfree (filename_copy);
+
+  return (status);
+} /* }}} int srrd_create */
+/* #endif HAVE_THREADSAFE_LIBRRD */
+
+#else /* !HAVE_THREADSAFE_LIBRRD */
+static int srrd_create (const char *filename, /* {{{ */
+    unsigned long pdp_step, time_t last_up,
+    int argc, const char **argv)
+{
+  int status;
+
+  int new_argc;
+  char **new_argv;
+
+  char pdp_step_str[16];
+  char last_up_str[16];
+
+  new_argc = 6 + argc;
+  new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
+  if (new_argv == NULL)
+  {
+    ERROR ("rrdtool plugin: malloc failed.");
+    return (-1);
+  }
+
+  if (last_up == 0)
+    last_up = time (NULL) - 10;
+
+  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;
+  new_argv[2] = "-s";
+  new_argv[3] = pdp_step_str;
+  new_argv[4] = "-b";
+  new_argv[5] = last_up_str;
+
+  memcpy (new_argv + 6, argv, argc * sizeof (char *));
+  new_argv[new_argc] = NULL;
+
+  pthread_mutex_lock (&librrd_lock);
+  optind = 0; /* bug in librrd? */
+  rrd_clear_error ();
+
+  status = rrd_create (new_argc, new_argv);
+  pthread_mutex_unlock (&librrd_lock);
+
+  if (status != 0)
+  {
+    WARNING ("rrdtool plugin: rrd_create (%s) failed: %s",
+        filename, rrd_get_error ());
+  }
+
+  sfree (new_argv);
+
+  return (status);
+} /* }}} int srrd_create */
+#endif /* !HAVE_THREADSAFE_LIBRRD */
+
+static int lock_file (char const *filename) /* {{{ */
+{
+  async_create_file_t *ptr;
+  struct stat sb;
+  int status;
+
+  pthread_mutex_lock (&async_creation_lock);
+
+  for (ptr = async_creation_list; ptr != NULL; ptr = ptr->next)
+    if (strcmp (filename, ptr->filename) == 0)
+      break;
+
+  if (ptr != NULL)
+  {
+    pthread_mutex_unlock (&async_creation_lock);
+    return (EEXIST);
+  }
+
+  status = stat (filename, &sb);
+  if ((status == 0) || (errno != ENOENT))
+  {
+    pthread_mutex_unlock (&async_creation_lock);
+    return (EEXIST);
+  }
+
+  ptr = malloc (sizeof (*ptr));
+  if (ptr == NULL)
+  {
+    pthread_mutex_unlock (&async_creation_lock);
+    return (ENOMEM);
+  }
+
+  ptr->filename = strdup (filename);
+  if (ptr->filename == NULL)
+  {
+    pthread_mutex_unlock (&async_creation_lock);
+    sfree (ptr);
+    return (ENOMEM);
+  }
+
+  ptr->next = async_creation_list;
+  async_creation_list = ptr;
+
+  pthread_mutex_unlock (&async_creation_lock);
+
+  return (0);
+} /* }}} int lock_file */
+
+static int unlock_file (char const *filename) /* {{{ */
+{
+  async_create_file_t *this;
+  async_create_file_t *prev;
+
+
+  pthread_mutex_lock (&async_creation_lock);
+
+  prev = NULL;
+  for (this = async_creation_list; this != NULL; this = this->next)
+  {
+    if (strcmp (filename, this->filename) == 0)
+      break;
+    prev = this;
+  }
+
+  if (this == NULL)
+  {
+    pthread_mutex_unlock (&async_creation_lock);
+    return (ENOENT);
+  }
+
+  if (prev == NULL)
+  {
+    assert (this == async_creation_list);
+    async_creation_list = this->next;
+  }
+  else
+  {
+    assert (this == prev->next);
+    prev->next = this->next;
+  }
+  this->next = NULL;
+
+  pthread_mutex_unlock (&async_creation_lock);
+
+  sfree (this->filename);
+  sfree (this);
+
+  return (0);
+} /* }}} int unlock_file */
+
+static void *srrd_create_thread (void *targs) /* {{{ */
+{
+  srrd_create_args_t *args = targs;
+  char tmpfile[PATH_MAX];
+  int status;
+
+  status = lock_file (args->filename);
+  if (status != 0)
+  {
+    if (status == EEXIST)
+      NOTICE ("srrd_create_thread: File \"%s\" is already being created.",
+          args->filename);
+    else
+      ERROR ("srrd_create_thread: Unable to lock file \"%s\".",
+          args->filename);
+    srrd_create_args_destroy (args);
+    return (0);
+  }
+
+  ssnprintf (tmpfile, sizeof (tmpfile), "%s.async", args->filename);
+
+  status = srrd_create (tmpfile, args->pdp_step, args->last_up,
+      args->argc, (void *) args->argv);
+  if (status != 0)
+  {
+    WARNING ("srrd_create_thread: srrd_create (%s) returned status %i.",
+        args->filename, status);
+    unlink (tmpfile);
+    unlock_file (args->filename);
+    srrd_create_args_destroy (args);
+    return (0);
+  }
+
+  status = rename (tmpfile, args->filename);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("srrd_create_thread: rename (\"%s\", \"%s\") failed: %s",
+        tmpfile, args->filename,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    unlink (tmpfile);
+    unlock_file (args->filename);
+    srrd_create_args_destroy (args);
+    return (0);
+  }
+
+  DEBUG ("srrd_create_thread: Successfully created RRD file \"%s\".",
+      args->filename);
+
+  unlock_file (args->filename);
+  srrd_create_args_destroy (args);
+
+  return (0);
+} /* }}} void *srrd_create_thread */
+
+static int srrd_create_async (const char *filename, /* {{{ */
+    unsigned long pdp_step, time_t last_up,
+    int argc, const char **argv)
+{
+  srrd_create_args_t *args;
+  pthread_t thread;
+  pthread_attr_t attr;
+  int status;
+
+  DEBUG ("srrd_create_async: Creating \"%s\" in the background.", filename);
+
+  args = srrd_create_args_create (filename, pdp_step, last_up, argc, argv);
+  if (args == NULL)
+    return (-1);
+
+  status = pthread_attr_init (&attr);
+  if (status != 0)
+  {
+    srrd_create_args_destroy (args);
+    return (-1);
+  }
+
+  status = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  if (status != 0)
+  {
+    pthread_attr_destroy (&attr);
+    srrd_create_args_destroy (args);
+    return (-1);
+  }
+
+  status = pthread_create (&thread, &attr, srrd_create_thread, args);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    ERROR ("srrd_create_async: pthread_create failed: %s",
+        sstrerror (status, errbuf, sizeof (errbuf)));
+    pthread_attr_destroy (&attr);
+    srrd_create_args_destroy (args);
+    return (status);
+  }
+
+  pthread_attr_destroy (&attr);
+  /* args is freed in srrd_create_thread(). */
+  return (0);
+} /* }}} int srrd_create_async */
+
+/*
+ * Public functions
+ */
+int cu_rrd_create_file (const char *filename, /* {{{ */
+    const data_set_t *ds, const value_list_t *vl,
+    const rrdcreate_config_t *cfg)
+{
+  char **argv;
+  int argc;
+  char **rra_def;
+  int rra_num;
+  char **ds_def;
+  int ds_num;
+  int status = 0;
+  time_t last_up;
+  unsigned long stepsize;
+
+  if (check_create_dir (filename))
+    return (-1);
+
+  if ((rra_num = rra_get (&rra_def, vl, cfg)) < 1)
+  {
+    ERROR ("cu_rrd_create_file failed: Could not calculate RRAs");
+    return (-1);
+  }
+
+  if ((ds_num = ds_get (&ds_def, ds, vl, cfg)) < 1)
+  {
+    ERROR ("cu_rrd_create_file failed: Could not calculate DSes");
+    return (-1);
+  }
+
+  argc = ds_num + rra_num;
+
+  if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("cu_rrd_create_file failed: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  memcpy (argv, ds_def, ds_num * sizeof (char *));
+  memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *));
+  argv[ds_num + rra_num] = NULL;
+
+  last_up = CDTIME_T_TO_TIME_T (vl->time);
+  if (last_up <= 0)
+    last_up = time (NULL);
+  last_up -= 1;
+
+  if (cfg->stepsize > 0)
+    stepsize = cfg->stepsize;
+  else
+    stepsize = (unsigned long) CDTIME_T_TO_TIME_T (vl->interval);
+
+  if (cfg->async)
+  {
+    status = srrd_create_async (filename, stepsize, last_up,
+        argc, (const char **) argv);
+    if (status != 0)
+      WARNING ("cu_rrd_create_file: srrd_create_async (%s) "
+          "returned status %i.",
+          filename, status);
+  }
+  else /* synchronous */
+  {
+    status = srrd_create (filename, stepsize, last_up,
+        argc, (const char **) argv);
+
+    if (status != 0)
+    {
+      WARNING ("cu_rrd_create_file: srrd_create (%s) returned status %i.",
+          filename, status);
+    }
+    else
+    {
+      DEBUG ("cu_rrd_create_file: Successfully created RRD file \"%s\".",
+          filename);
+    }
+  }
+
+  free (argv);
+  ds_free (ds_num, ds_def);
+  rra_free (rra_num, rra_def);
+
+  return (status);
+} /* }}} int cu_rrd_create_file */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
diff --git a/src/utils_rrdcreate.h b/src/utils_rrdcreate.h
new file mode 100644 (file)
index 0000000..14daadf
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * collectd - src/utils_rrdcreate.h
+ * Copyright (C) 2008-2013  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_RRDCREATE_H
+#define UTILS_RRDCREATE_H 1
+
+#include "plugin.h"
+
+#include <stddef.h>
+
+struct rrdcreate_config_s
+{
+  unsigned long stepsize;
+  int    heartbeat;
+  int    rrarows;
+  double xff;
+
+  int *timespans;
+  size_t timespans_num;
+
+  char **consolidation_functions;
+  size_t consolidation_functions_num;
+
+  _Bool async;
+};
+typedef struct rrdcreate_config_s rrdcreate_config_t;
+
+int cu_rrd_create_file (const char *filename,
+    const data_set_t *ds, const value_list_t *vl,
+    const rrdcreate_config_t *cfg);
+
+#endif /* UTILS_RRDCREATE_H */
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/utils_vl_lookup.c b/src/utils_vl_lookup.c
new file mode 100644 (file)
index 0000000..75c0206
--- /dev/null
@@ -0,0 +1,655 @@
+/**
+ * collectd - src/utils_vl_lookup.c
+ * Copyright (C) 2012       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+
+#include <pthread.h>
+#include <regex.h>
+
+#include "common.h"
+#include "utils_vl_lookup.h"
+#include "utils_avltree.h"
+
+#if BUILD_TEST
+# define sstrncpy strncpy
+# define plugin_log(s, ...) do { \
+  printf ("[severity %i] ", s); \
+  printf (__VA_ARGS__); \
+  printf ("\n"); \
+} while (0)
+#endif
+
+/*
+ * Types
+ */
+struct part_match_s
+{
+  char str[DATA_MAX_NAME_LEN];
+  regex_t regex;
+  _Bool is_regex;
+};
+typedef struct part_match_s part_match_t;
+
+struct identifier_match_s
+{
+  part_match_t host;
+  part_match_t plugin;
+  part_match_t plugin_instance;
+  part_match_t type;
+  part_match_t type_instance;
+
+  unsigned int group_by;
+};
+typedef struct identifier_match_s identifier_match_t;
+
+struct lookup_s
+{
+  c_avl_tree_t *by_type_tree;
+
+  lookup_class_callback_t cb_user_class;
+  lookup_obj_callback_t cb_user_obj;
+  lookup_free_class_callback_t cb_free_class;
+  lookup_free_obj_callback_t cb_free_obj;
+};
+
+struct user_obj_s;
+typedef struct user_obj_s user_obj_t;
+struct user_obj_s
+{
+  void *user_obj;
+  identifier_t ident;
+
+  user_obj_t *next;
+};
+
+struct user_class_s
+{
+  pthread_mutex_t lock;
+  void *user_class;
+  identifier_match_t match;
+  user_obj_t *user_obj_list; /* list of user_obj */
+};
+typedef struct user_class_s user_class_t;
+
+struct user_class_list_s;
+typedef struct user_class_list_s user_class_list_t;
+struct user_class_list_s
+{
+  user_class_t entry;
+  user_class_list_t *next;
+};
+
+struct by_type_entry_s
+{
+  c_avl_tree_t *by_plugin_tree; /* plugin -> user_class_list_t */
+  user_class_list_t *wildcard_plugin_list;
+};
+typedef struct by_type_entry_s by_type_entry_t;
+
+/*
+ * Private functions
+ */
+static _Bool lu_part_matches (part_match_t const *match, /* {{{ */
+    char const *str)
+{
+  if (match->is_regex)
+  {
+    /* Short cut popular catch-all regex. */
+    if (strcmp (".*", match->str) == 0)
+      return (1);
+
+    int status = regexec (&match->regex, str,
+        /* nmatch = */ 0, /* pmatch = */ NULL,
+        /* flags = */ 0);
+    if (status == 0)
+      return (1);
+    else
+      return (0);
+  }
+  else if (strcmp (match->str, str) == 0)
+    return (1);
+  else
+    return (0);
+} /* }}} _Bool lu_part_matches */
+
+static int lu_copy_ident_to_match_part (part_match_t *match_part, /* {{{ */
+    char const *ident_part)
+{
+  size_t len = strlen (ident_part);
+  int status;
+
+  if ((len < 3) || (ident_part[0] != '/') || (ident_part[len - 1] != '/'))
+  {
+    sstrncpy (match_part->str, ident_part, sizeof (match_part->str));
+    match_part->is_regex = 0;
+    return (0);
+  }
+
+  /* Copy string without the leading slash. */
+  sstrncpy (match_part->str, ident_part + 1, sizeof (match_part->str));
+  assert (sizeof (match_part->str) > len);
+  /* strip trailing slash */
+  match_part->str[len - 2] = 0;
+  
+  status = regcomp (&match_part->regex, match_part->str,
+      /* flags = */ REG_EXTENDED);
+  if (status != 0)
+  {
+    char errbuf[1024];
+    regerror (status, &match_part->regex, errbuf, sizeof (errbuf));
+    ERROR ("utils_vl_lookup: Compiling regular expression \"%s\" failed: %s",
+        match_part->str, errbuf);
+    return (EINVAL);
+  }
+  match_part->is_regex = 1;
+  
+  return (0);
+} /* }}} int lu_copy_ident_to_match_part */
+
+static int lu_copy_ident_to_match (identifier_match_t *match, /* {{{ */
+    identifier_t const *ident, unsigned int group_by)
+{
+  memset (match, 0, sizeof (*match));
+
+  match->group_by = group_by;
+
+#define COPY_FIELD(field) do { \
+  int status = lu_copy_ident_to_match_part (&match->field, ident->field); \
+  if (status != 0) \
+    return (status); \
+} while (0)
+
+  COPY_FIELD (host);
+  COPY_FIELD (plugin);
+  COPY_FIELD (plugin_instance);
+  COPY_FIELD (type);
+  COPY_FIELD (type_instance);
+
+#undef COPY_FIELD
+
+  return (0);
+} /* }}} int lu_copy_ident_to_match */
+
+/* user_class->lock must be held when calling this function */
+static void *lu_create_user_obj (lookup_t *obj, /* {{{ */
+    data_set_t const *ds, value_list_t const *vl,
+    user_class_t *user_class)
+{
+  user_obj_t *user_obj;
+
+  user_obj = malloc (sizeof (*user_obj));
+  if (user_obj == NULL)
+  {
+    ERROR ("utils_vl_lookup: malloc failed.");
+    return (NULL);
+  }
+  memset (user_obj, 0, sizeof (*user_obj));
+  user_obj->next = NULL;
+
+  user_obj->user_obj = obj->cb_user_class (ds, vl, user_class->user_class);
+  if (user_obj->user_obj == NULL)
+  {
+    sfree (user_obj);
+    WARNING("utils_vl_lookup: User-provided constructor failed.");
+    return (NULL);
+  }
+
+#define COPY_FIELD(field, group_mask) do { \
+  if (user_class->match.field.is_regex \
+      && ((user_class->match.group_by & group_mask) == 0)) \
+    sstrncpy (user_obj->ident.field, "/.*/", sizeof (user_obj->ident.field)); \
+  else \
+    sstrncpy (user_obj->ident.field, vl->field, sizeof (user_obj->ident.field)); \
+} while (0)
+
+  COPY_FIELD (host, LU_GROUP_BY_HOST);
+  COPY_FIELD (plugin, LU_GROUP_BY_PLUGIN);
+  COPY_FIELD (plugin_instance, LU_GROUP_BY_PLUGIN_INSTANCE);
+  COPY_FIELD (type, 0);
+  COPY_FIELD (type_instance, LU_GROUP_BY_TYPE_INSTANCE);
+
+#undef COPY_FIELD
+
+  if (user_class->user_obj_list == NULL)
+  {
+    user_class->user_obj_list = user_obj;
+  }
+  else
+  {
+    user_obj_t *last = user_class->user_obj_list;
+    while (last->next != NULL)
+      last = last->next;
+    last->next = user_obj;
+  }
+
+  return (user_obj);
+} /* }}} void *lu_create_user_obj */
+
+/* user_class->lock must be held when calling this function */
+static user_obj_t *lu_find_user_obj (user_class_t *user_class, /* {{{ */
+    value_list_t const *vl)
+{
+  user_obj_t *ptr;
+
+  for (ptr = user_class->user_obj_list;
+      ptr != NULL;
+      ptr = ptr->next)
+  {
+    if (user_class->match.host.is_regex
+        && (user_class->match.group_by & LU_GROUP_BY_HOST)
+        && (strcmp (vl->host, ptr->ident.host) != 0))
+      continue;
+    if (user_class->match.plugin.is_regex
+        && (user_class->match.group_by & LU_GROUP_BY_PLUGIN)
+        && (strcmp (vl->plugin, ptr->ident.plugin) != 0))
+      continue;
+    if (user_class->match.plugin_instance.is_regex
+        && (user_class->match.group_by & LU_GROUP_BY_PLUGIN_INSTANCE)
+        && (strcmp (vl->plugin_instance, ptr->ident.plugin_instance) != 0))
+      continue;
+    if (user_class->match.type_instance.is_regex
+        && (user_class->match.group_by & LU_GROUP_BY_TYPE_INSTANCE)
+        && (strcmp (vl->type_instance, ptr->ident.type_instance) != 0))
+      continue;
+
+    return (ptr);
+  }
+
+  return (NULL);
+} /* }}} user_obj_t *lu_find_user_obj */
+
+static int lu_handle_user_class (lookup_t *obj, /* {{{ */
+    data_set_t const *ds, value_list_t const *vl,
+    user_class_t *user_class)
+{
+  user_obj_t *user_obj;
+  int status;
+
+  assert (strcmp (vl->type, user_class->match.type.str) == 0);
+  assert (user_class->match.plugin.is_regex
+      || (strcmp (vl->plugin, user_class->match.plugin.str)) == 0);
+
+  if (!lu_part_matches (&user_class->match.type_instance, vl->type_instance)
+      || !lu_part_matches (&user_class->match.plugin_instance, vl->plugin_instance)
+      || !lu_part_matches (&user_class->match.plugin, vl->plugin)
+      || !lu_part_matches (&user_class->match.host, vl->host))
+    return (1);
+
+  pthread_mutex_lock (&user_class->lock);
+  user_obj = lu_find_user_obj (user_class, vl);
+  if (user_obj == NULL)
+  {
+    /* call lookup_class_callback_t() and insert into the list of user objects. */
+    user_obj = lu_create_user_obj (obj, ds, vl, user_class);
+    pthread_mutex_unlock (&user_class->lock);
+    if (user_obj == NULL)
+      return (-1);
+  }
+  pthread_mutex_unlock (&user_class->lock);
+
+  status = obj->cb_user_obj (ds, vl,
+      user_class->user_class, user_obj->user_obj);
+  if (status != 0)
+  {
+    ERROR ("utils_vl_lookup: The user object callback failed with status %i.",
+        status);
+    /* Returning a negative value means: abort! */
+    if (status < 0)
+      return (status);
+    else
+      return (1);
+  }
+
+  return (0);
+} /* }}} int lu_handle_user_class */
+
+static int lu_handle_user_class_list (lookup_t *obj, /* {{{ */
+    data_set_t const *ds, value_list_t const *vl,
+    user_class_list_t *user_class_list)
+{
+  user_class_list_t *ptr;
+  int retval = 0;
+  
+  for (ptr = user_class_list; ptr != NULL; ptr = ptr->next)
+  {
+    int status;
+
+    status = lu_handle_user_class (obj, ds, vl, &ptr->entry);
+    if (status < 0)
+      return (status);
+    else if (status == 0)
+      retval++;
+  }
+
+  return (retval);
+} /* }}} int lu_handle_user_class_list */
+
+static by_type_entry_t *lu_search_by_type (lookup_t *obj, /* {{{ */
+    char const *type, _Bool allocate_if_missing)
+{
+  by_type_entry_t *by_type;
+  char *type_copy;
+  int status;
+
+  status = c_avl_get (obj->by_type_tree, type, (void *) &by_type);
+  if (status == 0)
+    return (by_type);
+
+  if (!allocate_if_missing)
+    return (NULL);
+
+  type_copy = strdup (type);
+  if (type_copy == NULL)
+  {
+    ERROR ("utils_vl_lookup: strdup failed.");
+    return (NULL);
+  }
+
+  by_type = malloc (sizeof (*by_type));
+  if (by_type == NULL)
+  {
+    ERROR ("utils_vl_lookup: malloc failed.");
+    sfree (type_copy);
+    return (NULL);
+  }
+  memset (by_type, 0, sizeof (*by_type));
+  by_type->wildcard_plugin_list = NULL;
+  
+  by_type->by_plugin_tree = c_avl_create ((void *) strcmp);
+  if (by_type->by_plugin_tree == NULL)
+  {
+    ERROR ("utils_vl_lookup: c_avl_create failed.");
+    sfree (by_type);
+    sfree (type_copy);
+    return (NULL);
+  }
+
+  status = c_avl_insert (obj->by_type_tree,
+      /* key = */ type_copy, /* value = */ by_type);
+  assert (status <= 0); /* >0 => entry exists => race condition. */
+  if (status != 0)
+  {
+    ERROR ("utils_vl_lookup: c_avl_insert failed.");
+    c_avl_destroy (by_type->by_plugin_tree);
+    sfree (by_type);
+    sfree (type_copy);
+    return (NULL);
+  }
+  
+  return (by_type);
+} /* }}} by_type_entry_t *lu_search_by_type */
+
+static int lu_add_by_plugin (by_type_entry_t *by_type, /* {{{ */
+    user_class_list_t *user_class_list)
+{
+  user_class_list_t *ptr = NULL;
+  identifier_match_t const *match = &user_class_list->entry.match;
+
+  /* Lookup user_class_list from the per-plugin structure. If this is the first
+   * user_class to be added, the block returns immediately. Otherwise they will
+   * set "ptr" to non-NULL. */
+  if (match->plugin.is_regex)
+  {
+    if (by_type->wildcard_plugin_list == NULL)
+    {
+      by_type->wildcard_plugin_list = user_class_list;
+      return (0);
+    }
+
+    ptr = by_type->wildcard_plugin_list;
+  } /* if (plugin is wildcard) */
+  else /* (plugin is not wildcard) */
+  {
+    int status;
+
+    status = c_avl_get (by_type->by_plugin_tree,
+        match->plugin.str, (void *) &ptr);
+
+    if (status != 0) /* plugin not yet in tree */
+    {
+      char *plugin_copy = strdup (match->plugin.str);
+
+      if (plugin_copy == NULL)
+      {
+        ERROR ("utils_vl_lookup: strdup failed.");
+        sfree (user_class_list);
+        return (ENOMEM);
+      }
+
+      status = c_avl_insert (by_type->by_plugin_tree,
+          plugin_copy, user_class_list);
+      if (status != 0)
+      {
+        ERROR ("utils_vl_lookup: c_avl_insert(\"%s\") failed with status %i.",
+            plugin_copy, status);
+        sfree (plugin_copy);
+        sfree (user_class_list);
+        return (status);
+      }
+      else
+      {
+        return (0);
+      }
+    } /* if (plugin not yet in tree) */
+  } /* if (plugin is not wildcard) */
+
+  assert (ptr != NULL);
+
+  while (ptr->next != NULL)
+    ptr = ptr->next;
+  ptr->next = user_class_list;
+
+  return (0);
+} /* }}} int lu_add_by_plugin */
+
+static void lu_destroy_user_obj (lookup_t *obj, /* {{{ */
+    user_obj_t *user_obj)
+{
+  while (user_obj != NULL)
+  {
+    user_obj_t *next = user_obj->next;
+
+    if (obj->cb_free_obj != NULL)
+      obj->cb_free_obj (user_obj->user_obj);
+    user_obj->user_obj = NULL;
+
+    sfree (user_obj);
+    user_obj = next;
+  }
+} /* }}} void lu_destroy_user_obj */
+
+static void lu_destroy_user_class_list (lookup_t *obj, /* {{{ */
+    user_class_list_t *user_class_list)
+{
+  while (user_class_list != NULL)
+  {
+    user_class_list_t *next = user_class_list->next;
+
+    if (obj->cb_free_class != NULL)
+      obj->cb_free_class (user_class_list->entry.user_class);
+    user_class_list->entry.user_class = NULL;
+
+    lu_destroy_user_obj (obj, user_class_list->entry.user_obj_list);
+    user_class_list->entry.user_obj_list = NULL;
+    pthread_mutex_destroy (&user_class_list->entry.lock);
+
+    sfree (user_class_list);
+    user_class_list = next;
+  }
+} /* }}} void lu_destroy_user_class_list */
+
+static void lu_destroy_by_type (lookup_t *obj, /* {{{ */
+    by_type_entry_t *by_type)
+{
+  
+  while (42)
+  {
+    char *plugin = NULL;
+    user_class_list_t *user_class_list = NULL;
+    int status;
+
+    status = c_avl_pick (by_type->by_plugin_tree,
+        (void *) &plugin, (void *) &user_class_list);
+    if (status != 0)
+      break;
+
+    DEBUG ("utils_vl_lookup: lu_destroy_by_type: Destroying plugin \"%s\".",
+        plugin);
+    sfree (plugin);
+    lu_destroy_user_class_list (obj, user_class_list);
+  }
+
+  c_avl_destroy (by_type->by_plugin_tree);
+  by_type->by_plugin_tree = NULL;
+
+  lu_destroy_user_class_list (obj, by_type->wildcard_plugin_list);
+  by_type->wildcard_plugin_list = NULL;
+
+  sfree (by_type);
+} /* }}} int lu_destroy_by_type */
+
+/*
+ * Public functions
+ */
+lookup_t *lookup_create (lookup_class_callback_t cb_user_class, /* {{{ */
+    lookup_obj_callback_t cb_user_obj,
+    lookup_free_class_callback_t cb_free_class,
+    lookup_free_obj_callback_t cb_free_obj)
+{
+  lookup_t *obj = malloc (sizeof (*obj));
+  if (obj == NULL)
+  {
+    ERROR ("utils_vl_lookup: malloc failed.");
+    return (NULL);
+  }
+  memset (obj, 0, sizeof (*obj));
+
+  obj->by_type_tree = c_avl_create ((void *) strcmp);
+  if (obj->by_type_tree == NULL)
+  {
+    ERROR ("utils_vl_lookup: c_avl_create failed.");
+    sfree (obj);
+    return (NULL);
+  }
+
+  obj->cb_user_class = cb_user_class;
+  obj->cb_user_obj = cb_user_obj;
+  obj->cb_free_class = cb_free_class;
+  obj->cb_free_obj = cb_free_obj;
+
+  return (obj);
+} /* }}} lookup_t *lookup_create */
+
+void lookup_destroy (lookup_t *obj) /* {{{ */
+{
+  int status;
+
+  if (obj == NULL)
+    return;
+
+  while (42)
+  {
+    char *type = NULL;
+    by_type_entry_t *by_type = NULL;
+
+    status = c_avl_pick (obj->by_type_tree, (void *) &type, (void *) &by_type);
+    if (status != 0)
+      break;
+
+    DEBUG ("utils_vl_lookup: lookup_destroy: Destroying type \"%s\".", type);
+    sfree (type);
+    lu_destroy_by_type (obj, by_type);
+  }
+
+  c_avl_destroy (obj->by_type_tree);
+  obj->by_type_tree = NULL;
+
+  sfree (obj);
+} /* }}} void lookup_destroy */
+
+int lookup_add (lookup_t *obj, /* {{{ */
+    identifier_t const *ident, unsigned int group_by, void *user_class)
+{
+  by_type_entry_t *by_type = NULL;
+  user_class_list_t *user_class_obj;
+
+  by_type = lu_search_by_type (obj, ident->type, /* allocate = */ 1);
+  if (by_type == NULL)
+    return (-1);
+
+  user_class_obj = malloc (sizeof (*user_class_obj));
+  if (user_class_obj == NULL)
+  {
+    ERROR ("utils_vl_lookup: malloc failed.");
+    return (ENOMEM);
+  }
+  memset (user_class_obj, 0, sizeof (*user_class_obj));
+  pthread_mutex_init (&user_class_obj->entry.lock, /* attr = */ NULL);
+  user_class_obj->entry.user_class = user_class;
+  lu_copy_ident_to_match (&user_class_obj->entry.match, ident, group_by);
+  user_class_obj->entry.user_obj_list = NULL;
+  user_class_obj->next = NULL;
+
+  return (lu_add_by_plugin (by_type, user_class_obj));
+} /* }}} int lookup_add */
+
+/* returns the number of successful calls to the callback function */
+int lookup_search (lookup_t *obj, /* {{{ */
+    data_set_t const *ds, value_list_t const *vl)
+{
+  by_type_entry_t *by_type = NULL;
+  user_class_list_t *user_class_list = NULL;
+  int retval = 0;
+  int status;
+
+  if ((obj == NULL) || (ds == NULL) || (vl == NULL))
+    return (-EINVAL);
+
+  by_type = lu_search_by_type (obj, vl->type, /* allocate = */ 0);
+  if (by_type == NULL)
+    return (0);
+
+  status = c_avl_get (by_type->by_plugin_tree,
+      vl->plugin, (void *) &user_class_list);
+  if (status == 0)
+  {
+    status = lu_handle_user_class_list (obj, ds, vl, user_class_list);
+    if (status < 0)
+      return (status);
+    retval += status;
+  }
+
+  if (by_type->wildcard_plugin_list != NULL)
+  {
+    status = lu_handle_user_class_list (obj, ds, vl,
+        by_type->wildcard_plugin_list);
+    if (status < 0)
+      return (status);
+    retval += status;
+  }
+    
+  return (retval);
+} /* }}} lookup_search */
diff --git a/src/utils_vl_lookup.h b/src/utils_vl_lookup.h
new file mode 100644 (file)
index 0000000..1d01ebd
--- /dev/null
@@ -0,0 +1,89 @@
+/**
+ * collectd - src/utils_vl_lookup.h
+ * Copyright (C) 2012       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#ifndef UTILS_VL_LOOKUP_H
+#define UTILS_VL_LOOKUP_H 1
+
+#include "plugin.h"
+
+/*
+ * Types
+ */
+struct lookup_s;
+typedef struct lookup_s lookup_t;
+
+/* Given a user_class, constructs a new user_obj. */
+typedef void *(*lookup_class_callback_t) (data_set_t const *ds,
+    value_list_t const *vl, void *user_class);
+
+/* Given a user_class and a ds/vl combination, does stuff with the data.
+ * This is the main working horse of the module. */
+typedef int (*lookup_obj_callback_t) (data_set_t const *ds,
+    value_list_t const *vl,
+    void *user_class, void *user_obj);
+
+/* Used to free user_class pointers. May be NULL in which case nothing is
+ * freed. */
+typedef void (*lookup_free_class_callback_t) (void *user_class);
+
+/* Used to free user_obj pointers. May be NULL in which case nothing is
+ * freed. */
+typedef void (*lookup_free_obj_callback_t) (void *user_obj);
+
+struct identifier_s
+{
+  char host[DATA_MAX_NAME_LEN];
+  char plugin[DATA_MAX_NAME_LEN];
+  char plugin_instance[DATA_MAX_NAME_LEN];
+  char type[DATA_MAX_NAME_LEN];
+  char type_instance[DATA_MAX_NAME_LEN];
+};
+typedef struct identifier_s identifier_t;
+
+#define LU_GROUP_BY_HOST            0x01
+#define LU_GROUP_BY_PLUGIN          0x02
+#define LU_GROUP_BY_PLUGIN_INSTANCE 0x04
+/* #define LU_GROUP_BY_TYPE            0x00 */
+#define LU_GROUP_BY_TYPE_INSTANCE   0x10
+
+/*
+ * Functions
+ */
+__attribute__((nonnull(1,2)))
+lookup_t *lookup_create (lookup_class_callback_t,
+    lookup_obj_callback_t,
+    lookup_free_class_callback_t,
+    lookup_free_obj_callback_t);
+void lookup_destroy (lookup_t *obj);
+
+int lookup_add (lookup_t *obj,
+    identifier_t const *ident, unsigned int group_by, void *user_class);
+
+/* TODO(octo): Pass lookup_obj_callback_t to lookup_search()? */
+int lookup_search (lookup_t *obj,
+    data_set_t const *ds, value_list_t const *vl);
+
+#endif /* UTILS_VL_LOOKUP_H */
diff --git a/src/utils_vl_lookup_test.c b/src/utils_vl_lookup_test.c
new file mode 100644 (file)
index 0000000..6a2676a
--- /dev/null
@@ -0,0 +1,249 @@
+/**
+ * collectd - src/tests/test_utils_vl_lookup.c
+ * Copyright (C) 2012       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ **/
+
+#include "testing.h"
+#include "collectd.h"
+#include "utils_vl_lookup.h"
+
+static _Bool expect_new_obj = 0;
+static _Bool have_new_obj = 0;
+
+static identifier_t last_class_ident;
+static identifier_t last_obj_ident;
+
+static data_source_t dsrc_test = { "value", DS_TYPE_DERIVE, 0.0, NAN };
+static data_set_t const ds_test = { "test", 1, &dsrc_test };
+
+static data_source_t dsrc_unknown = { "value", DS_TYPE_DERIVE, 0.0, NAN };
+static data_set_t const ds_unknown = { "unknown", 1, &dsrc_unknown };
+
+static int lookup_obj_callback (data_set_t const *ds,
+    value_list_t const *vl,
+    void *user_class, void *user_obj)
+{
+  identifier_t *class = user_class;
+  identifier_t *obj = user_obj;
+
+  OK1(expect_new_obj == have_new_obj,
+      (expect_new_obj ? "New obj is created." : "Updating existing obj."));
+
+  memcpy (&last_class_ident, class, sizeof (last_class_ident));
+  memcpy (&last_obj_ident, obj, sizeof (last_obj_ident));
+
+  if (strcmp (obj->plugin_instance, "failure") == 0)
+    return (-1);
+
+  return (0);
+}
+
+static void *lookup_class_callback (data_set_t const *ds,
+    value_list_t const *vl, void *user_class)
+{
+  identifier_t *class = user_class;
+  identifier_t *obj;
+
+  OK(expect_new_obj);
+
+  memcpy (&last_class_ident, class, sizeof (last_class_ident));
+  
+  obj = malloc (sizeof (*obj));
+  strncpy (obj->host, vl->host, sizeof (obj->host));
+  strncpy (obj->plugin, vl->plugin, sizeof (obj->plugin));
+  strncpy (obj->plugin_instance, vl->plugin_instance, sizeof (obj->plugin_instance));
+  strncpy (obj->type, vl->type, sizeof (obj->type));
+  strncpy (obj->type_instance, vl->type_instance, sizeof (obj->type_instance));
+
+  have_new_obj = 1;
+
+  return ((void *) obj);
+}
+
+static void checked_lookup_add (lookup_t *obj, /* {{{ */
+    char const *host,
+    char const *plugin, char const *plugin_instance,
+    char const *type, char const *type_instance,
+    unsigned int group_by)
+{
+  identifier_t ident;
+  void *user_class;
+
+  memset (&ident, 0, sizeof (ident));
+  strncpy (ident.host, host, sizeof (ident.host));
+  strncpy (ident.plugin, plugin, sizeof (ident.plugin));
+  strncpy (ident.plugin_instance, plugin_instance, sizeof (ident.plugin_instance));
+  strncpy (ident.type, type, sizeof (ident.type));
+  strncpy (ident.type_instance, type_instance, sizeof (ident.type_instance));
+
+  user_class = malloc (sizeof (ident));
+  memmove (user_class, &ident, sizeof (ident));
+
+  OK(lookup_add (obj, &ident, group_by, user_class) == 0);
+} /* }}} void test_add */
+
+static int checked_lookup_search (lookup_t *obj,
+    char const *host,
+    char const *plugin, char const *plugin_instance,
+    char const *type, char const *type_instance,
+    _Bool expect_new)
+{
+  int status;
+  value_list_t vl = VALUE_LIST_STATIC;
+  data_set_t const *ds = &ds_unknown;
+
+  strncpy (vl.host, host, sizeof (vl.host));
+  strncpy (vl.plugin, plugin, sizeof (vl.plugin));
+  strncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+  strncpy (vl.type, type, sizeof (vl.type));
+  strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  if (strcmp (vl.type, "test") == 0)
+    ds = &ds_test;
+
+  expect_new_obj = expect_new;
+  have_new_obj = 0;
+
+  status = lookup_search (obj, ds, &vl);
+  return (status);
+}
+
+static lookup_t *checked_lookup_create (void)
+{
+  lookup_t *obj = lookup_create (
+      lookup_class_callback,
+      lookup_obj_callback,
+      (void *) free,
+      (void *) free);
+  OK(obj != NULL);
+  return (obj);
+}
+
+DEF_TEST(group_by_specific_host)
+{
+  lookup_t *obj = checked_lookup_create ();
+
+  checked_lookup_add (obj, "/.*/", "test", "", "test", "/.*/", LU_GROUP_BY_HOST);
+  checked_lookup_search (obj, "host0", "test", "", "test", "0",
+      /* expect new = */ 1);
+  checked_lookup_search (obj, "host0", "test", "", "test", "1",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "host1", "test", "", "test", "0",
+      /* expect new = */ 1);
+  checked_lookup_search (obj, "host1", "test", "", "test", "1",
+      /* expect new = */ 0);
+
+  lookup_destroy (obj);
+  return (0);
+}
+
+DEF_TEST(group_by_any_host)
+{
+  lookup_t *obj = checked_lookup_create ();
+
+  checked_lookup_add (obj, "/.*/", "/.*/", "/.*/", "test", "/.*/", LU_GROUP_BY_HOST);
+  checked_lookup_search (obj, "host0", "plugin0", "", "test", "0",
+      /* expect new = */ 1);
+  checked_lookup_search (obj, "host0", "plugin0", "", "test", "1",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "host0", "plugin1", "", "test", "0",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "host0", "plugin1", "", "test", "1",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "host1", "plugin0", "", "test", "0",
+      /* expect new = */ 1);
+  checked_lookup_search (obj, "host1", "plugin0", "", "test", "1",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "host1", "plugin1", "", "test", "0",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "host1", "plugin1", "", "test", "1",
+      /* expect new = */ 0);
+
+  lookup_destroy (obj);
+  return (0);
+}
+
+DEF_TEST(multiple_lookups)
+{
+  lookup_t *obj = checked_lookup_create ();
+  int status;
+
+  checked_lookup_add (obj, "/.*/", "plugin0", "", "test", "/.*/", LU_GROUP_BY_HOST);
+  checked_lookup_add (obj, "/.*/", "/.*/", "", "test", "ti0", LU_GROUP_BY_HOST);
+
+  status = checked_lookup_search (obj, "host0", "plugin1", "", "test", "",
+      /* expect new = */ 0);
+  assert (status == 0);
+  status = checked_lookup_search (obj, "host0", "plugin0", "", "test", "",
+      /* expect new = */ 1);
+  assert (status == 1);
+  status = checked_lookup_search (obj, "host0", "plugin1", "", "test", "ti0",
+      /* expect new = */ 1);
+  assert (status == 1);
+  status = checked_lookup_search (obj, "host0", "plugin0", "", "test", "ti0",
+      /* expect new = */ 0);
+  assert (status == 2);
+
+  lookup_destroy (obj);
+  return (0);
+}
+
+DEF_TEST(regex)
+{
+  lookup_t *obj = checked_lookup_create ();
+
+  checked_lookup_add (obj, "/^db[0-9]\\./", "cpu", "/.*/", "cpu", "/.*/",
+      LU_GROUP_BY_TYPE_INSTANCE);
+  checked_lookup_search (obj, "db0.example.com", "cpu", "0", "cpu", "user",
+      /* expect new = */ 1);
+  checked_lookup_search (obj, "db0.example.com", "cpu", "0", "cpu", "idle",
+      /* expect new = */ 1);
+  checked_lookup_search (obj, "db0.example.com", "cpu", "1", "cpu", "user",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "db0.example.com", "cpu", "1", "cpu", "idle",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "app0.example.com", "cpu", "0", "cpu", "user",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "app0.example.com", "cpu", "0", "cpu", "idle",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "user",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "idle",
+      /* expect new = */ 0);
+  checked_lookup_search (obj, "db1.example.com", "cpu", "0", "cpu", "system",
+      /* expect new = */ 1);
+
+  lookup_destroy (obj);
+  return (0);
+}
+
+int main (int argc, char **argv) /* {{{ */
+{
+  RUN_TEST(group_by_specific_host);
+  RUN_TEST(group_by_any_host);
+  RUN_TEST(multiple_lookups);
+  RUN_TEST(regex);
+
+  END_TEST;
+} /* }}} int main */
diff --git a/src/uuid.c b/src/uuid.c
new file mode 100644 (file)
index 0000000..2df6063
--- /dev/null
@@ -0,0 +1,269 @@
+/**
+ * collectd - src/uuid.c
+ * Copyright (C) 2007  Red Hat Inc.
+ *
+ * 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:
+ *   Dan Berrange <berrange@redhat.com>
+ *   Richard W.M. Jones <rjones@redhat.com>
+ *
+ * Derived from UUID detection code by Dan Berrange <berrange@redhat.com>
+ * http://hg.et.redhat.com/virt/daemons/spectre--devel?f=f6e3a1b06433;file=lib/uuid.c
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "configfile.h"
+#include "plugin.h"
+
+#if HAVE_LIBHAL
+#include <libhal.h>
+#endif
+
+#define UUID_RAW_LENGTH 16
+#define UUID_PRINTABLE_COMPACT_LENGTH  (UUID_RAW_LENGTH * 2)
+#define UUID_PRINTABLE_NORMAL_LENGTH  (UUID_PRINTABLE_COMPACT_LENGTH + 4)
+
+static char *uuidfile = NULL;
+
+static const char *config_keys[] = {
+    "UUIDFile"
+};
+
+static int
+looks_like_a_uuid (const char *uuid)
+{
+    int len;
+
+    if (!uuid) return 0;
+
+    len = strlen (uuid);
+
+    if (len < UUID_PRINTABLE_COMPACT_LENGTH)
+        return 0;
+
+    while (*uuid) {
+        if (!isxdigit ((int)*uuid) && *uuid != '-') return 0;
+        uuid++;
+    }
+    return 1;
+}
+
+static char *
+uuid_parse_dmidecode(FILE *file)
+{
+    char line[1024];
+
+    while (fgets (line, sizeof (line), file) != NULL)
+    {
+        char *fields[4];
+        int fields_num;
+
+        strstripnewline (line);
+
+        /* Look for a line reading:
+         *   UUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+         */
+        fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields));
+        if (fields_num != 2)
+            continue;
+
+        if (strcmp("UUID:", fields[0]) != 0)
+            continue;
+
+        if (!looks_like_a_uuid (fields[1]))
+            continue;
+
+        return strdup (fields[1]);
+    }
+    return NULL;
+}
+
+static char *
+uuid_get_from_dmidecode(void)
+{
+    FILE *dmidecode = popen("dmidecode 2>/dev/null", "r");
+    char *uuid;
+
+    if (!dmidecode) {
+        return NULL;
+    }
+    
+    uuid = uuid_parse_dmidecode(dmidecode);
+
+    pclose(dmidecode);
+    return uuid;
+}
+
+#if HAVE_LIBHAL
+
+#define UUID_PATH "/org/freedesktop/Hal/devices/computer"
+#define UUID_PROPERTY "smbios.system.uuid"
+
+static char *
+uuid_get_from_hal(void)
+{
+    LibHalContext *ctx;
+
+    DBusError error;
+    DBusConnection *con;
+
+    dbus_error_init(&error);
+
+    if (!(con = dbus_bus_get(DBUS_BUS_SYSTEM, &error)) ) {
+        goto bailout_nobus;
+    }
+
+    ctx = libhal_ctx_new();
+    libhal_ctx_set_dbus_connection(ctx, con);
+
+    if (!libhal_ctx_init(ctx, &error)) {
+        goto bailout;
+    }
+
+    if (!libhal_device_property_exists(ctx,
+                                       UUID_PATH,
+                                       UUID_PROPERTY,
+                                       &error)) {
+        goto bailout;
+    }
+
+    char *uuid  = libhal_device_get_property_string(ctx,
+                                                    UUID_PATH,
+                                                    UUID_PROPERTY,
+                                                    &error);
+    if (looks_like_a_uuid (uuid)) {
+        return uuid;
+    }
+
+ bailout:
+    {
+        DBusError ctxerror;
+        dbus_error_init(&ctxerror);
+        if (!(libhal_ctx_shutdown(ctx, &ctxerror))) {
+            dbus_error_free(&ctxerror);
+        }
+    }
+
+    libhal_ctx_free(ctx);
+    //dbus_connection_unref(con);
+
+ bailout_nobus:
+    if (dbus_error_is_set(&error)) {
+        /*printf("Error %s\n", error.name);*/
+        dbus_error_free(&error);
+    }
+    return NULL;
+}
+#endif
+
+static char *
+uuid_get_from_file(const char *path)
+{
+    FILE *file;
+    char uuid[UUID_PRINTABLE_NORMAL_LENGTH + 1] = "";
+
+    file = fopen (path, "r");
+    if (file == NULL)
+        return NULL;
+
+    if (!fgets(uuid, sizeof(uuid), file)) {
+        fclose(file);
+        return NULL;
+    }
+    fclose(file);
+    strstripnewline (uuid);
+
+    return strdup (uuid);
+}
+
+static char *
+uuid_get_local(void)
+{
+    char *uuid;
+
+    /* Check /etc/uuid / UUIDFile before any other method. */
+    if ((uuid = uuid_get_from_file(uuidfile ? uuidfile : "/etc/uuid")) != NULL){
+        return uuid;
+    }
+
+#if HAVE_LIBHAL
+    if ((uuid = uuid_get_from_hal()) != NULL) {
+        return uuid;
+    }
+#endif
+
+    if ((uuid = uuid_get_from_dmidecode()) != NULL) {
+        return uuid;
+    }
+
+    if ((uuid = uuid_get_from_file("/sys/hypervisor/uuid")) != NULL) {
+        return uuid;
+    }
+
+    return NULL;
+}
+
+static int
+uuid_config (const char *key, const char *value)
+{
+    if (strcasecmp (key, "UUIDFile") == 0) {
+        char *tmp = strdup (value);
+        if (tmp == NULL)
+            return -1;
+        sfree (uuidfile);
+        uuidfile = tmp;
+    } else {
+        return 1;
+    }
+
+    return 0;
+}
+
+static int
+uuid_init (void)
+{
+    char *uuid = uuid_get_local ();
+
+    if (uuid) {
+        sstrncpy (hostname_g, uuid, DATA_MAX_NAME_LEN);
+        sfree (uuid);
+        return 0;
+    }
+
+    WARNING ("uuid: could not read UUID using any known method");
+    return 0;
+}
+
+void module_register (void)
+{
+    plugin_register_config ("uuid", uuid_config,
+            config_keys, STATIC_ARRAY_SIZE (config_keys));
+    plugin_register_init ("uuid", uuid_init);
+}
+
+/*
+ * vim: set tabstop=4:
+ * vim: set shiftwidth=4:
+ * vim: set expandtab:
+ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff --git a/src/varnish.c b/src/varnish.c
new file mode 100644 (file)
index 0000000..8e6d95e
--- /dev/null
@@ -0,0 +1,939 @@
+/**
+ * collectd - src/varnish.c
+ * Copyright (C) 2010      Jérôme Renard
+ * Copyright (C) 2010      Marc Fournier
+ * Copyright (C) 2010-2012 Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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:
+ *   Jérôme Renard <jerome.renard at gmail.com>
+ *   Marc Fournier <marc.fournier at camptocamp.com>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#if HAVE_VARNISH_V4
+#include <varnish/vapi/vsm.h>
+#include <varnish/vapi/vsc.h>
+typedef struct VSC_C_main c_varnish_stats_t;
+#endif
+
+#if HAVE_VARNISH_V3
+#include <varnish/varnishapi.h>
+#include <varnish/vsc.h>
+typedef struct VSC_C_main c_varnish_stats_t;
+#endif
+
+#if HAVE_VARNISH_V2
+#include <varnish/varnishapi.h>
+typedef struct varnish_stats c_varnish_stats_t;
+#endif
+
+/* {{{ user_config_s */
+struct user_config_s {
+       char *instance;
+
+       _Bool collect_cache;
+       _Bool collect_connections;
+       _Bool collect_esi;
+       _Bool collect_backend;
+#ifdef HAVE_VARNISH_V3
+       _Bool collect_dirdns;
+#endif
+       _Bool collect_fetch;
+       _Bool collect_hcb;
+       _Bool collect_objects;
+#if HAVE_VARNISH_V2
+       _Bool collect_purge;
+#else
+       _Bool collect_ban;
+#endif
+       _Bool collect_session;
+       _Bool collect_shm;
+       _Bool collect_sms;
+#if HAVE_VARNISH_V2
+       _Bool collect_sm;
+       _Bool collect_sma;
+#endif
+       _Bool collect_struct;
+       _Bool collect_totals;
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+       _Bool collect_uptime;
+#endif
+       _Bool collect_vcl;
+       _Bool collect_workers;
+#if HAVE_VARNISH_V4
+       _Bool collect_vsm;
+#endif
+};
+typedef struct user_config_s user_config_t; /* }}} */
+
+static _Bool have_instance = 0;
+
+static int varnish_submit (const char *plugin_instance, /* {{{ */
+               const char *category, const char *type, const char *type_instance, value_t value)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = &value;
+       vl.values_len = 1;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+
+       sstrncpy (vl.plugin, "varnish", sizeof (vl.plugin));
+
+       if (plugin_instance == NULL)
+               plugin_instance = "default";
+
+       ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+               "%s-%s", plugin_instance, category);
+
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance,
+                               sizeof (vl.type_instance));
+
+       return (plugin_dispatch_values (&vl));
+} /* }}} int varnish_submit */
+
+static int varnish_submit_gauge (const char *plugin_instance, /* {{{ */
+               const char *category, const char *type, const char *type_instance,
+               uint64_t gauge_value)
+{
+       value_t value;
+
+       value.gauge = (gauge_t) gauge_value;
+
+       return (varnish_submit (plugin_instance, category, type, type_instance, value));
+} /* }}} int varnish_submit_gauge */
+
+static int varnish_submit_derive (const char *plugin_instance, /* {{{ */
+               const char *category, const char *type, const char *type_instance,
+               uint64_t derive_value)
+{
+       value_t value;
+
+       value.derive = (derive_t) derive_value;
+
+       return (varnish_submit (plugin_instance, category, type, type_instance, value));
+} /* }}} int varnish_submit_derive */
+
+static void varnish_monitor (const user_config_t *conf, /* {{{ */
+               const c_varnish_stats_t *stats)
+{
+       if (conf->collect_cache)
+       {
+               /* Cache hits */
+               varnish_submit_derive (conf->instance, "cache", "cache_result", "hit",     stats->cache_hit);
+               /* Cache misses */
+               varnish_submit_derive (conf->instance, "cache", "cache_result", "miss",    stats->cache_miss);
+               /* Cache hits for pass */
+               varnish_submit_derive (conf->instance, "cache", "cache_result", "hitpass", stats->cache_hitpass);
+       }
+
+       if (conf->collect_connections)
+       {
+#ifndef HAVE_VARNISH_V4
+               /* Client connections accepted */
+               varnish_submit_derive (conf->instance, "connections", "connections", "accepted", stats->client_conn);
+               /* Connection dropped, no sess */
+               varnish_submit_derive (conf->instance, "connections", "connections", "dropped" , stats->client_drop);
+#endif
+               /* Client requests received    */
+               varnish_submit_derive (conf->instance, "connections", "connections", "received", stats->client_req);
+       }
+
+#ifdef HAVE_VARNISH_V3
+       if (conf->collect_dirdns)
+       {
+               /* DNS director lookups */
+               varnish_submit_derive (conf->instance, "dirdns", "cache_operation", "lookups",    stats->dir_dns_lookups);
+               /* DNS director failed lookups */
+               varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "failed",     stats->dir_dns_failed);
+               /* DNS director cached lookups hit */
+               varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "hits",       stats->dir_dns_hit);
+               /* DNS director full dnscache */
+               varnish_submit_derive (conf->instance, "dirdns", "cache_result",    "cache_full", stats->dir_dns_cache_full);
+       }
+#endif
+
+       if (conf->collect_esi)
+       {
+               /* ESI parse errors (unlock)   */
+               varnish_submit_derive (conf->instance, "esi", "total_operations", "error",   stats->esi_errors);
+#if HAVE_VARNISH_V2
+               /* Objects ESI parsed (unlock) */
+               varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed",  stats->esi_parse);
+#else
+               /* ESI parse warnings (unlock) */
+               varnish_submit_derive (conf->instance, "esi", "total_operations", "warning", stats->esi_warnings);
+#endif
+       }
+
+       if (conf->collect_backend)
+       {
+               /* Backend conn. success       */
+               varnish_submit_derive (conf->instance, "backend", "connections", "success"      , stats->backend_conn);
+               /* Backend conn. not attempted */
+               varnish_submit_derive (conf->instance, "backend", "connections", "not-attempted", stats->backend_unhealthy);
+               /* Backend conn. too many      */
+               varnish_submit_derive (conf->instance, "backend", "connections", "too-many"     , stats->backend_busy);
+               /* Backend conn. failures      */
+               varnish_submit_derive (conf->instance, "backend", "connections", "failures"     , stats->backend_fail);
+               /* Backend conn. reuses        */
+               varnish_submit_derive (conf->instance, "backend", "connections", "reuses"       , stats->backend_reuse);
+               /* Backend conn. was closed    */
+               varnish_submit_derive (conf->instance, "backend", "connections", "was-closed"   , stats->backend_toolate);
+               /* Backend conn. recycles      */
+               varnish_submit_derive (conf->instance, "backend", "connections", "recycled"     , stats->backend_recycle);
+#if HAVE_VARNISH_V2
+               /* Backend conn. unused        */
+               varnish_submit_derive (conf->instance, "backend", "connections", "unused"       , stats->backend_unused);
+#else
+               /* Backend conn. retry         */
+               varnish_submit_derive (conf->instance, "backend", "connections", "retries"      , stats->backend_retry);
+#endif
+               /* Backend requests mades      */
+               varnish_submit_derive (conf->instance, "backend", "http_requests", "requests"   , stats->backend_req);
+               /* N backends                  */
+               varnish_submit_gauge  (conf->instance, "backend", "backends", "n_backends"      , stats->n_backend);
+       }
+
+       if (conf->collect_fetch)
+       {
+               /* Fetch head                */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "head"       , stats->fetch_head);
+               /* Fetch with length         */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "length"     , stats->fetch_length);
+               /* Fetch chunked             */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "chunked"    , stats->fetch_chunked);
+               /* Fetch EOF                 */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "eof"        , stats->fetch_eof);
+               /* Fetch bad headers         */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "bad_headers", stats->fetch_bad);
+               /* Fetch wanted close        */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "close"      , stats->fetch_close);
+               /* Fetch pre HTTP/1.1 closed */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "oldhttp"    , stats->fetch_oldhttp);
+               /* Fetch zero len            */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero"       , stats->fetch_zero);
+               /* Fetch failed              */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed"     , stats->fetch_failed);
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               /* Fetch no body (1xx)       */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_1xx", stats->fetch_1xx);
+               /* Fetch no body (204)       */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_204", stats->fetch_204);
+               /* Fetch no body (304)       */
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_304", stats->fetch_304);
+#endif
+       }
+
+       if (conf->collect_hcb)
+       {
+               /* HCB Lookups without lock */
+               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_nolock", stats->hcb_nolock);
+               /* HCB Lookups with lock    */
+               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_lock",   stats->hcb_lock);
+               /* HCB Inserts              */
+               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "insert",        stats->hcb_insert);
+       }
+
+       if (conf->collect_objects)
+       {
+               /* N expired objects             */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "expired",            stats->n_expired);
+               /* N LRU nuked objects           */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_nuked",          stats->n_lru_nuked);
+#if HAVE_VARNISH_V2
+               /* N LRU saved objects           */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_saved",          stats->n_lru_saved);
+#endif
+               /* N LRU moved objects           */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_moved",          stats->n_lru_moved);
+#if HAVE_VARNISH_V2
+               /* N objects on deathrow         */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "deathrow",           stats->n_deathrow);
+#endif
+               /* HTTP header overflows         */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "header_overflow",    stats->losthdr);
+#if HAVE_VARNISH_V4
+               /* N purged objects              */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "purged",             stats->n_obj_purged);
+#else
+               /* Objects sent with sendfile    */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_sendfile",      stats->n_objsendfile);
+               /* Objects sent with write       */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_write",         stats->n_objwrite);
+               /* Objects overflowing workspace */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "workspace_overflow", stats->n_objoverflow);
+#endif
+       }
+
+#if HAVE_VARNISH_V2
+       if (conf->collect_purge)
+       {
+               /* N total active purges      */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "total",            stats->n_purge);
+               /* N new purges added         */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "added",            stats->n_purge_add);
+               /* N old purges deleted       */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "deleted",          stats->n_purge_retire);
+               /* N objects tested           */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "objects_tested",   stats->n_purge_obj_test);
+               /* N regexps tested against   */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "regexps_tested",   stats->n_purge_re_test);
+               /* N duplicate purges removed */
+               varnish_submit_derive (conf->instance, "purge", "total_operations", "duplicate",        stats->n_purge_dups);
+       }
+#endif
+#if HAVE_VARNISH_V3
+       if (conf->collect_ban)
+       {
+               /* N total active bans      */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          stats->n_ban);
+               /* N new bans added         */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          stats->n_ban_add);
+               /* N old bans deleted       */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        stats->n_ban_retire);
+               /* N objects tested         */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "objects_tested", stats->n_ban_obj_test);
+               /* N regexps tested against */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "regexps_tested", stats->n_ban_re_test);
+               /* N duplicate bans removed */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      stats->n_ban_dups);
+       }
+#endif
+#if HAVE_VARNISH_V4
+       if (conf->collect_ban)
+       {
+               /* N total active bans      */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          stats->bans);
+               /* N new bans added         */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          stats->bans_added);
+               /* N bans using obj */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "obj",            stats->bans_obj);
+               /* N bans using req */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "req",            stats->bans_req);
+               /* N new bans completed     */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "completed",      stats->bans_completed);
+               /* N old bans deleted       */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        stats->bans_deleted);
+               /* N objects tested         */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "tested",         stats->bans_tested);
+               /* N duplicate bans removed */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      stats->bans_dups);
+       }
+#endif
+
+       if (conf->collect_session)
+       {
+               /* Session Closed     */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "closed",    stats->sess_closed);
+               /* Session Pipeline   */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "pipeline",  stats->sess_pipeline);
+               /* Session Read Ahead */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "readahead", stats->sess_readahead);
+#if HAVE_VARNISH_V4
+               /* Sessions accepted */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "accepted",  stats->sess_conn);
+               /* Sessions dropped for thread */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "dropped",   stats->sess_drop);
+               /* Sessions accept failure */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "failed",    stats->sess_fail);
+               /* Sessions pipe overflow */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "overflow",  stats->sess_pipe_overflow);
+               /* Sessions queued for thread */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "queued",    stats->sess_queued);
+#else
+               /* Session Linger     */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "linger",    stats->sess_linger);
+#endif
+               /* Session herd       */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "herd",      stats->sess_herd);
+       }
+
+       if (conf->collect_shm)
+       {
+               /* SHM records                 */
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "records"   , stats->shm_records);
+               /* SHM writes                  */
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "writes"    , stats->shm_writes);
+               /* SHM flushes due to overflow */
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "flushes"   , stats->shm_flushes);
+               /* SHM MTX contention          */
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "contention", stats->shm_cont);
+               /* SHM cycles through buffer   */
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "cycles"    , stats->shm_cycles);
+       }
+
+#if HAVE_VARNISH_V2
+       if (conf->collect_sm)
+       {
+               /* allocator requests */
+               varnish_submit_derive (conf->instance, "sm", "total_requests", "nreq",         stats->sm_nreq);
+               /* outstanding allocations */
+               varnish_submit_gauge (conf->instance,  "sm", "requests", "outstanding",        stats->sm_nobj);
+               /* bytes allocated */
+               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "allocated",      stats->sm_balloc);
+               /* bytes free */
+               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "free",           stats->sm_bfree);
+       }
+
+       if (conf->collect_sma)
+       {
+               /* SMA allocator requests */
+               varnish_submit_derive (conf->instance, "sma", "total_requests", "nreq",    stats->sma_nreq);
+               /* SMA outstanding allocations */
+               varnish_submit_gauge (conf->instance,  "sma", "requests", "outstanding",   stats->sma_nobj);
+               /* SMA outstanding bytes */
+               varnish_submit_gauge (conf->instance,  "sma", "bytes", "outstanding",      stats->sma_nbytes);
+               /* SMA bytes allocated */
+               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "allocated", stats->sma_balloc);
+               /* SMA bytes free */
+               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "free" ,     stats->sma_bfree);
+       }
+#endif
+
+       if (conf->collect_sms)
+       {
+               /* SMS allocator requests */
+               varnish_submit_derive (conf->instance, "sms", "total_requests", "allocator", stats->sms_nreq);
+               /* SMS outstanding allocations */
+               varnish_submit_gauge (conf->instance,  "sms", "requests", "outstanding",     stats->sms_nobj);
+               /* SMS outstanding bytes */
+               varnish_submit_gauge (conf->instance,  "sms", "bytes", "outstanding",        stats->sms_nbytes);
+               /* SMS bytes allocated */
+               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "allocated",   stats->sms_balloc);
+               /* SMS bytes freed */
+               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "free",        stats->sms_bfree);
+       }
+
+       if (conf->collect_struct)
+       {
+#if !HAVE_VARNISH_V4
+               /* N struct sess_mem       */
+               varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess_mem",  stats->n_sess_mem);
+               /* N struct sess           */
+               varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess",      stats->n_sess);
+#endif
+               /* N struct object         */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "object",             stats->n_object);
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               /* N unresurrected objects */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "vampireobject",      stats->n_vampireobject);
+               /* N struct objectcore     */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "objectcore",         stats->n_objectcore);
+               /* N struct waitinglist    */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "waitinglist",        stats->n_waitinglist);
+#endif
+               /* N struct objecthead     */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead",         stats->n_objecthead);
+#ifdef HAVE_VARNISH_V2
+               /* N struct smf            */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "smf",                stats->n_smf);
+               /* N small free smf         */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "smf_frag",           stats->n_smf_frag);
+               /* N large free smf         */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "smf_large",          stats->n_smf_large);
+               /* N struct vbe_conn        */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "vbe_conn",           stats->n_vbe_conn);
+#endif
+       }
+
+       if (conf->collect_totals)
+       {
+               /* Total Sessions */
+               varnish_submit_derive (conf->instance, "totals", "total_sessions", "sessions",  stats->s_sess);
+               /* Total Requests */
+               varnish_submit_derive (conf->instance, "totals", "total_requests", "requests",  stats->s_req);
+               /* Total pipe */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "pipe",    stats->s_pipe);
+               /* Total pass */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "pass",    stats->s_pass);
+               /* Total fetch */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "fetches", stats->s_fetch);
+#if HAVE_VARNISH_V4
+               /* Total synth */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "synth",       stats->s_synth);
+               /* Request header bytes */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_header",  stats->s_req_hdrbytes);
+               /* Request body byte */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_body",    stats->s_req_bodybytes);
+               /* Response header bytes */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_header", stats->s_resp_hdrbytes);
+               /* Response body byte */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_body",   stats->s_resp_bodybytes);
+               /* Pipe request header bytes */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_header", stats->s_pipe_hdrbytes);
+               /* Piped bytes from client */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_in",     stats->s_pipe_in);
+               /* Piped bytes to client */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_out",    stats->s_pipe_out);
+               /* Number of purge operations */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "purges", stats->n_purges);
+#else
+               /* Total header bytes */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "header-bytes", stats->s_hdrbytes);
+               /* Total body byte */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   stats->s_bodybytes);
+#endif
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               /* Gzip operations */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "gzip",    stats->n_gzip);
+               /* Gunzip operations */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "gunzip",  stats->n_gunzip);
+#endif
+       }
+
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+       if (conf->collect_uptime)
+       {
+               /* Client uptime */
+               varnish_submit_gauge (conf->instance, "uptime", "uptime", "client_uptime", stats->uptime);
+       }
+#endif
+
+       if (conf->collect_vcl)
+       {
+               /* N vcl total     */
+               varnish_submit_gauge (conf->instance, "vcl", "vcl", "total_vcl",     stats->n_vcl);
+               /* N vcl available */
+               varnish_submit_gauge (conf->instance, "vcl", "vcl", "avail_vcl",     stats->n_vcl_avail);
+               /* N vcl discarded */
+               varnish_submit_gauge (conf->instance, "vcl", "vcl", "discarded_vcl", stats->n_vcl_discard);
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               /* Loaded VMODs */
+               varnish_submit_gauge (conf->instance, "vcl", "objects", "vmod",      stats->vmods);
+#endif
+       }
+
+       if (conf->collect_workers)
+       {
+#ifdef HAVE_VARNISH_V4
+               /* total number of threads */
+               varnish_submit_gauge (conf->instance, "workers", "threads", "worker",             stats->threads);
+               /* threads created */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "created",     stats->threads_created);
+               /* thread creation failed */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",      stats->threads_failed);
+               /* threads hit max */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->threads_limited);
+               /* threads destroyed */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",     stats->threads_destroyed);
+               /* length of session queue */
+               varnish_submit_derive (conf->instance, "workers", "queue_length",  "threads",     stats->thread_queue_len);
+#else
+               /* worker threads */
+               varnish_submit_gauge (conf->instance, "workers", "threads", "worker",             stats->n_wrk);
+               /* worker threads created */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "created",     stats->n_wrk_create);
+               /* worker threads not created */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",      stats->n_wrk_failed);
+               /* worker threads limited */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->n_wrk_max);
+               /* dropped work requests */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",     stats->n_wrk_drop);
+#ifdef HAVE_VARNISH_V2
+               /* queued work requests */
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",     stats->n_wrk_queue);
+               /* overflowed work requests */
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", stats->n_wrk_overflow);
+#else /* HAVE_VARNISH_V3 */
+               /* queued work requests */
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       stats->n_wrk_queued);
+               /* work request queue length */
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "queue_length", stats->n_wrk_lqueue);
+#endif
+#endif
+       }
+
+#if HAVE_VARNISH_V4
+       if (conf->collect_vsm)
+       {
+               /* Free VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "free",              stats->vsm_free);
+               /* Used VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "used",              stats->vsm_used);
+               /* Cooling VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "cooling",           stats->vsm_cooling);
+               /* Overflow VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "overflow",          stats->vsm_overflow);
+               /* Total overflowed VSM space */
+               varnish_submit_derive (conf->instance, "vsm", "total_bytes", "overflowed", stats->vsm_overflowed);
+       }
+#endif
+
+} /* }}} void varnish_monitor */
+
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+static int varnish_read (user_data_t *ud) /* {{{ */
+{
+       struct VSM_data *vd;
+       const c_varnish_stats_t *stats;
+
+       user_config_t *conf;
+
+       if ((ud == NULL) || (ud->data == NULL))
+               return (EINVAL);
+
+       conf = ud->data;
+
+       vd = VSM_New();
+#if HAVE_VARNISH_V3
+       VSC_Setup(vd);
+#endif
+
+       if (conf->instance != NULL)
+       {
+               int status;
+
+               status = VSM_n_Arg (vd, conf->instance);
+               if (status < 0)
+               {
+                       ERROR ("varnish plugin: VSM_n_Arg (\"%s\") failed "
+                                       "with status %i.",
+                                       conf->instance, status);
+                       return (-1);
+               }
+       }
+
+#if HAVE_VARNISH_V3
+       if (VSC_Open (vd, /* diag = */ 1))
+#else /* if HAVE_VARNISH_V4 */
+       if (VSM_Open (vd))
+#endif
+       {
+               ERROR ("varnish plugin: Unable to load statistics.");
+
+               return (-1);
+       }
+
+#if HAVE_VARNISH_V3
+       stats = VSC_Main(vd);
+#else /* if HAVE_VARNISH_V4 */
+       stats = VSC_Main(vd, NULL);
+#endif
+
+       varnish_monitor (conf, stats);
+       VSM_Close (vd);
+
+       return (0);
+} /* }}} */
+#else /* if HAVE_VARNISH_V2 */
+static int varnish_read (user_data_t *ud) /* {{{ */
+{
+       const c_varnish_stats_t *stats;
+
+       user_config_t *conf;
+
+       if ((ud == NULL) || (ud->data == NULL))
+               return (EINVAL);
+
+       conf = ud->data;
+
+       stats = VSL_OpenStats (conf->instance);
+       if (stats == NULL)
+       {
+               ERROR ("Varnish plugin : unable to load statistics");
+
+               return (-1);
+       }
+
+       varnish_monitor (conf, stats);
+
+       return (0);
+} /* }}} */
+#endif
+
+static void varnish_config_free (void *ptr) /* {{{ */
+{
+       user_config_t *conf = ptr;
+
+       if (conf == NULL)
+               return;
+
+       sfree (conf->instance);
+       sfree (conf);
+} /* }}} */
+
+static int varnish_config_apply_default (user_config_t *conf) /* {{{ */
+{
+       if (conf == NULL)
+               return (EINVAL);
+
+       conf->collect_backend     = 1;
+       conf->collect_cache       = 1;
+       conf->collect_connections = 1;
+#ifdef HAVE_VARNISH_V3
+       conf->collect_dirdns      = 0;
+#endif
+       conf->collect_esi         = 0;
+       conf->collect_fetch       = 0;
+       conf->collect_hcb         = 0;
+       conf->collect_objects     = 0;
+#if HAVE_VARNISH_V2
+       conf->collect_purge       = 0;
+#else
+       conf->collect_ban         = 0;
+#endif
+       conf->collect_session     = 0;
+       conf->collect_shm         = 1;
+#if HAVE_VARNISH_V2
+       conf->collect_sm          = 0;
+       conf->collect_sma         = 0;
+#endif
+       conf->collect_sms         = 0;
+       conf->collect_struct      = 0;
+       conf->collect_totals      = 0;
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+       conf->collect_uptime      = 0;
+#endif
+       conf->collect_vcl         = 0;
+       conf->collect_workers     = 0;
+#if HAVE_VARNISH_V4
+       conf->collect_vsm         = 0;
+#endif
+
+       return (0);
+} /* }}} int varnish_config_apply_default */
+
+static int varnish_init (void) /* {{{ */
+{
+       user_config_t *conf;
+       user_data_t ud;
+
+       if (have_instance)
+               return (0);
+
+       conf = malloc (sizeof (*conf));
+       if (conf == NULL)
+               return (ENOMEM);
+       memset (conf, 0, sizeof (*conf));
+
+       /* Default settings: */
+       conf->instance = NULL;
+
+       varnish_config_apply_default (conf);
+
+       ud.data = conf;
+       ud.free_func = varnish_config_free;
+
+       plugin_register_complex_read (/* group = */ "varnish",
+                       /* name      = */ "varnish/localhost",
+                       /* callback  = */ varnish_read,
+                       /* interval  = */ NULL,
+                       /* user data = */ &ud);
+
+       return (0);
+} /* }}} int varnish_init */
+
+static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
+{
+       user_config_t *conf;
+       user_data_t ud;
+       char callback_name[DATA_MAX_NAME_LEN];
+       int i;
+
+       conf = malloc (sizeof (*conf));
+       if (conf == NULL)
+               return (ENOMEM);
+       memset (conf, 0, sizeof (*conf));
+       conf->instance = NULL;
+
+       varnish_config_apply_default (conf);
+
+       if (ci->values_num == 1)
+       {
+               int status;
+
+               status = cf_util_get_string (ci, &conf->instance);
+               if (status != 0)
+               {
+                       sfree (conf);
+                       return (status);
+               }
+               assert (conf->instance != NULL);
+
+               if (strcmp ("localhost", conf->instance) == 0)
+               {
+                       sfree (conf->instance);
+                       conf->instance = NULL;
+               }
+       }
+       else if (ci->values_num > 1)
+       {
+               WARNING ("Varnish plugin: \"Instance\" blocks accept only "
+                               "one argument.");
+               return (EINVAL);
+       }
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("CollectCache", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_cache);
+               else if (strcasecmp ("CollectConnections", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_connections);
+               else if (strcasecmp ("CollectESI", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_esi);
+#ifdef HAVE_VARNISH_V3
+               else if (strcasecmp ("CollectDirectorDNS", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_dirdns);
+#endif
+               else if (strcasecmp ("CollectBackend", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_backend);
+               else if (strcasecmp ("CollectFetch", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_fetch);
+               else if (strcasecmp ("CollectHCB", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_hcb);
+               else if (strcasecmp ("CollectObjects", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_objects);
+#if HAVE_VARNISH_V2
+               else if (strcasecmp ("CollectPurge", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_purge);
+#else
+               else if (strcasecmp ("CollectBan", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_ban);
+#endif
+               else if (strcasecmp ("CollectSession", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_session);
+               else if (strcasecmp ("CollectSHM", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_shm);
+               else if (strcasecmp ("CollectSMS", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_sms);
+#if HAVE_VARNISH_V2
+               else if (strcasecmp ("CollectSMA", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_sma);
+               else if (strcasecmp ("CollectSM", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_sm);
+#endif
+               else if (strcasecmp ("CollectStruct", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_struct);
+               else if (strcasecmp ("CollectTotals", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_totals);
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               else if (strcasecmp ("CollectUptime", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_uptime);
+#endif
+               else if (strcasecmp ("CollectVCL", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_vcl);
+               else if (strcasecmp ("CollectWorkers", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_workers);
+#if HAVE_VARNISH_V4
+               else if (strcasecmp ("CollectVSM", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_vsm);
+#endif
+               else
+               {
+                       WARNING ("Varnish plugin: Ignoring unknown "
+                                       "configuration option: \"%s\". Did "
+                                       "you forget to add an <Instance /> "
+                                       "block around the configuration?",
+                                       child->key);
+               }
+       }
+
+       if (!conf->collect_cache
+                       && !conf->collect_connections
+                       && !conf->collect_esi
+                       && !conf->collect_backend
+#ifdef HAVE_VARNISH_V3
+                       && !conf->collect_dirdns
+#endif
+                       && !conf->collect_fetch
+                       && !conf->collect_hcb
+                       && !conf->collect_objects
+#if HAVE_VARNISH_V2
+                       && !conf->collect_purge
+#else
+                       && !conf->collect_ban
+#endif
+                       && !conf->collect_session
+                       && !conf->collect_shm
+                       && !conf->collect_sms
+#if HAVE_VARNISH_V2
+                       && !conf->collect_sma
+                       && !conf->collect_sm
+#endif
+                       && !conf->collect_struct
+                       && !conf->collect_totals
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+                       && !conf->collect_uptime
+#endif
+                       && !conf->collect_vcl
+                       && !conf->collect_workers
+#if HAVE_VARNISH_V4
+                       && !conf->collect_vsm
+#endif
+       )
+       {
+               WARNING ("Varnish plugin: No metric has been configured for "
+                               "instance \"%s\". Disabling this instance.",
+                               (conf->instance == NULL) ? "localhost" : conf->instance);
+               return (EINVAL);
+       }
+
+       ssnprintf (callback_name, sizeof (callback_name), "varnish/%s",
+                       (conf->instance == NULL) ? "localhost" : conf->instance);
+
+       ud.data = conf;
+       ud.free_func = varnish_config_free;
+
+       plugin_register_complex_read (/* group = */ "varnish",
+                       /* name      = */ callback_name,
+                       /* callback  = */ varnish_read,
+                       /* interval  = */ NULL,
+                       /* user data = */ &ud);
+
+       have_instance = 1;
+
+       return (0);
+} /* }}} int varnish_config_instance */
+
+static int varnish_config (oconfig_item_t *ci) /* {{{ */
+{
+       int i;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Instance", child->key) == 0)
+                       varnish_config_instance (child);
+               else
+               {
+                       WARNING ("Varnish plugin: Ignoring unknown "
+                                       "configuration option: \"%s\"",
+                                       child->key);
+               }
+       }
+
+       return (0);
+} /* }}} int varnish_config */
+
+void module_register (void) /* {{{ */
+{
+       plugin_register_complex_config ("varnish", varnish_config);
+       plugin_register_init ("varnish", varnish_init);
+} /* }}} */
+
+/* vim: set sw=8 noet fdm=marker : */
diff --git a/src/virt.c b/src/virt.c
new file mode 100644 (file)
index 0000000..b6fedf5
--- /dev/null
@@ -0,0 +1,1010 @@
+/**
+ * collectd - src/virt.c
+ * Copyright (C) 2006-2008  Red Hat Inc.
+ *
+ * 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:
+ *   Richard W.M. Jones <rjones@redhat.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_ignorelist.h"
+#include "utils_complain.h"
+
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
+/* Plugin name */
+#define PLUGIN_NAME "virt"
+
+static const char *config_keys[] = {
+    "Connection",
+
+    "RefreshInterval",
+
+    "Domain",
+    "BlockDevice",
+    "InterfaceDevice",
+    "IgnoreSelected",
+
+    "HostnameFormat",
+    "InterfaceFormat",
+
+    "PluginInstanceFormat",
+
+    NULL
+};
+#define NR_CONFIG_KEYS ((sizeof config_keys / sizeof config_keys[0]) - 1)
+
+/* Connection. */
+static virConnectPtr conn = 0;
+static char *conn_string = NULL;
+static c_complain_t conn_complain = C_COMPLAIN_INIT_STATIC;
+
+/* Seconds between list refreshes, 0 disables completely. */
+static int interval = 60;
+
+/* List of domains, if specified. */
+static ignorelist_t *il_domains = NULL;
+/* List of block devices, if specified. */
+static ignorelist_t *il_block_devices = NULL;
+/* List of network interface devices, if specified. */
+static ignorelist_t *il_interface_devices = NULL;
+
+static int ignore_device_match (ignorelist_t *,
+                                const char *domname, const char *devpath);
+
+/* Actual list of domains found on last refresh. */
+static virDomainPtr *domains = NULL;
+static int nr_domains = 0;
+
+static void free_domains (void);
+static int add_domain (virDomainPtr dom);
+
+/* Actual list of block devices found on last refresh. */
+struct block_device {
+    virDomainPtr dom;           /* domain */
+    char *path;                 /* name of block device */
+};
+
+static struct block_device *block_devices = NULL;
+static int nr_block_devices = 0;
+
+static void free_block_devices (void);
+static int add_block_device (virDomainPtr dom, const char *path);
+
+/* Actual list of network interfaces found on last refresh. */
+struct interface_device {
+    virDomainPtr dom;           /* domain */
+    char *path;                 /* name of interface device */
+    char *address;              /* mac address of interface device */
+    char *number;               /* interface device number */
+};
+
+static struct interface_device *interface_devices = NULL;
+static int nr_interface_devices = 0;
+
+static void free_interface_devices (void);
+static int add_interface_device (virDomainPtr dom, const char *path, const char *address, unsigned int number);
+
+/* HostnameFormat. */
+#define HF_MAX_FIELDS 3
+
+enum hf_field {
+    hf_none = 0,
+    hf_hostname,
+    hf_name,
+    hf_uuid
+};
+
+static enum hf_field hostname_format[HF_MAX_FIELDS] =
+    { hf_name };
+
+/* PluginInstanceFormat */
+#define PLGINST_MAX_FIELDS 2
+
+enum plginst_field {
+    plginst_none = 0,
+    plginst_name,
+    plginst_uuid
+};
+
+static enum plginst_field plugin_instance_format[PLGINST_MAX_FIELDS] =
+    { plginst_name };
+
+/* InterfaceFormat. */
+enum if_field {
+    if_address,
+    if_name,
+    if_number
+};
+
+static enum if_field interface_format = if_name;
+
+/* Time that we last refreshed. */
+static time_t last_refresh = (time_t) 0;
+
+static int refresh_lists (void);
+
+/* ERROR(...) macro for virterrors. */
+#define VIRT_ERROR(conn,s) do {                 \
+        virErrorPtr err;                        \
+        err = (conn) ? virConnGetLastError ((conn)) : virGetLastError (); \
+        if (err) ERROR ("%s: %s", (s), err->message);                   \
+    } while(0)
+
+static void
+init_value_list (value_list_t *vl, virDomainPtr dom)
+{
+    int i, n;
+    const char *name;
+    char uuid[VIR_UUID_STRING_BUFLEN];
+
+    sstrncpy (vl->plugin, PLUGIN_NAME, sizeof (vl->plugin));
+
+    vl->host[0] = '\0';
+
+    /* Construct the hostname field according to HostnameFormat. */
+    for (i = 0; i < HF_MAX_FIELDS; ++i) {
+        if (hostname_format[i] == hf_none)
+            continue;
+
+        n = DATA_MAX_NAME_LEN - strlen (vl->host) - 2;
+
+        if (i > 0 && n >= 1) {
+            strncat (vl->host, ":", 1);
+            n--;
+        }
+
+        switch (hostname_format[i]) {
+        case hf_none: break;
+        case hf_hostname:
+            strncat (vl->host, hostname_g, n);
+            break;
+        case hf_name:
+            name = virDomainGetName (dom);
+            if (name)
+                strncat (vl->host, name, n);
+            break;
+        case hf_uuid:
+            if (virDomainGetUUIDString (dom, uuid) == 0)
+                strncat (vl->host, uuid, n);
+            break;
+        }
+    }
+
+    vl->host[sizeof (vl->host) - 1] = '\0';
+
+    /* Construct the plugin instance field according to PluginInstanceFormat. */
+    for (i = 0; i < PLGINST_MAX_FIELDS; ++i) {
+        if (plugin_instance_format[i] == plginst_none)
+            continue;
+
+        n = sizeof(vl->plugin_instance) - strlen (vl->plugin_instance) - 2;
+
+        if (i > 0 && n >= 1) {
+            strncat (vl->plugin_instance, ":", 1);
+            n--;
+        }
+
+        switch (plugin_instance_format[i]) {
+        case plginst_none: break;
+        case plginst_name:
+            name = virDomainGetName (dom);
+            if (name)
+                strncat (vl->plugin_instance, name, n);
+            break;
+        case plginst_uuid:
+            if (virDomainGetUUIDString (dom, uuid) == 0)
+                strncat (vl->plugin_instance, uuid, n);
+            break;
+        }
+    }
+
+    vl->plugin_instance[sizeof (vl->plugin_instance) - 1] = '\0';
+
+} /* void init_value_list */
+
+static void
+memory_submit (gauge_t memory, virDomainPtr dom)
+{
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    init_value_list (&vl, dom);
+
+    values[0].gauge = memory;
+
+    vl.values = values;
+    vl.values_len = 1;
+
+    sstrncpy (vl.type, "memory", sizeof (vl.type));
+    sstrncpy (vl.type_instance, "total", sizeof (vl.type_instance));
+
+    plugin_dispatch_values (&vl);
+}
+
+static void
+memory_stats_submit (gauge_t memory, virDomainPtr dom, int tag_index)
+{
+    static const char *tags[] = { "swap_in", "swap_out", "major_fault", "minor_fault",
+                                    "unused", "available", "actual_balloon", "rss"};
+
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    init_value_list (&vl, dom);
+
+    values[0].gauge = memory;
+
+    vl.values = values;
+    vl.values_len = 1;
+
+    sstrncpy (vl.type, "memory", sizeof (vl.type));
+    sstrncpy (vl.type_instance, tags[tag_index], sizeof (vl.type_instance));
+
+    plugin_dispatch_values (&vl);
+}
+
+static void
+cpu_submit (unsigned long long cpu_time,
+            virDomainPtr dom, const char *type)
+{
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    init_value_list (&vl, dom);
+
+    values[0].derive = cpu_time;
+
+    vl.values = values;
+    vl.values_len = 1;
+
+    sstrncpy (vl.type, type, sizeof (vl.type));
+
+    plugin_dispatch_values (&vl);
+}
+
+static void
+vcpu_submit (derive_t cpu_time,
+             virDomainPtr dom, int vcpu_nr, const char *type)
+{
+    value_t values[1];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    init_value_list (&vl, dom);
+
+    values[0].derive = cpu_time;
+    vl.values = values;
+    vl.values_len = 1;
+
+    sstrncpy (vl.type, type, sizeof (vl.type));
+    ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr);
+
+    plugin_dispatch_values (&vl);
+}
+
+static void
+submit_derive2 (const char *type, derive_t v0, derive_t v1,
+             virDomainPtr dom, const char *devname)
+{
+    value_t values[2];
+    value_list_t vl = VALUE_LIST_INIT;
+
+    init_value_list (&vl, dom);
+
+    values[0].derive = v0;
+    values[1].derive = v1;
+    vl.values = values;
+    vl.values_len = 2;
+
+    sstrncpy (vl.type, type, sizeof (vl.type));
+    sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance));
+
+    plugin_dispatch_values (&vl);
+} /* void submit_derive2 */
+
+static int
+lv_init (void)
+{
+    if (virInitialize () != 0)
+        return -1;
+
+       return 0;
+}
+
+static int
+lv_config (const char *key, const char *value)
+{
+    if (virInitialize () != 0)
+        return 1;
+
+    if (il_domains == NULL)
+        il_domains = ignorelist_create (1);
+    if (il_block_devices == NULL)
+        il_block_devices = ignorelist_create (1);
+    if (il_interface_devices == NULL)
+        il_interface_devices = ignorelist_create (1);
+
+    if (strcasecmp (key, "Connection") == 0) {
+        char *tmp = strdup (value);
+        if (tmp == NULL) {
+            ERROR (PLUGIN_NAME " plugin: Connection strdup failed.");
+            return 1;
+        }
+        sfree (conn_string);
+        conn_string = tmp;
+        return 0;
+    }
+
+    if (strcasecmp (key, "RefreshInterval") == 0) {
+        char *eptr = NULL;
+        interval = strtol (value, &eptr, 10);
+        if (eptr == NULL || *eptr != '\0') return 1;
+        return 0;
+    }
+
+    if (strcasecmp (key, "Domain") == 0) {
+        if (ignorelist_add (il_domains, value)) return 1;
+        return 0;
+    }
+    if (strcasecmp (key, "BlockDevice") == 0) {
+        if (ignorelist_add (il_block_devices, value)) return 1;
+        return 0;
+    }
+    if (strcasecmp (key, "InterfaceDevice") == 0) {
+        if (ignorelist_add (il_interface_devices, value)) return 1;
+        return 0;
+    }
+
+    if (strcasecmp (key, "IgnoreSelected") == 0) {
+        if (IS_TRUE (value))
+        {
+            ignorelist_set_invert (il_domains, 0);
+            ignorelist_set_invert (il_block_devices, 0);
+            ignorelist_set_invert (il_interface_devices, 0);
+        }
+        else
+        {
+            ignorelist_set_invert (il_domains, 1);
+            ignorelist_set_invert (il_block_devices, 1);
+            ignorelist_set_invert (il_interface_devices, 1);
+        }
+        return 0;
+    }
+
+    if (strcasecmp (key, "HostnameFormat") == 0) {
+        char *value_copy;
+        char *fields[HF_MAX_FIELDS];
+        int i, n;
+
+        value_copy = strdup (value);
+        if (value_copy == NULL) {
+            ERROR (PLUGIN_NAME " plugin: strdup failed.");
+            return -1;
+        }
+
+        n = strsplit (value_copy, fields, HF_MAX_FIELDS);
+        if (n < 1) {
+            sfree (value_copy);
+            ERROR (PLUGIN_NAME " plugin: HostnameFormat: no fields");
+            return -1;
+        }
+
+        for (i = 0; i < n; ++i) {
+            if (strcasecmp (fields[i], "hostname") == 0)
+                hostname_format[i] = hf_hostname;
+            else if (strcasecmp (fields[i], "name") == 0)
+                hostname_format[i] = hf_name;
+            else if (strcasecmp (fields[i], "uuid") == 0)
+                hostname_format[i] = hf_uuid;
+            else {
+                sfree (value_copy);
+                ERROR (PLUGIN_NAME " plugin: unknown HostnameFormat field: %s", fields[i]);
+                return -1;
+            }
+        }
+        sfree (value_copy);
+
+        for (i = n; i < HF_MAX_FIELDS; ++i)
+            hostname_format[i] = hf_none;
+
+        return 0;
+    }
+
+    if (strcasecmp (key, "PluginInstanceFormat") == 0) {
+        char *value_copy;
+        char *fields[PLGINST_MAX_FIELDS];
+        int i, n;
+
+        value_copy = strdup (value);
+        if (value_copy == NULL) {
+            ERROR (PLUGIN_NAME " plugin: strdup failed.");
+            return -1;
+        }
+
+        n = strsplit (value_copy, fields, PLGINST_MAX_FIELDS);
+        if (n < 1) {
+            sfree (value_copy);
+            ERROR (PLUGIN_NAME " plugin: PluginInstanceFormat: no fields");
+            return -1;
+        }
+
+        for (i = 0; i < n; ++i) {
+            if (strcasecmp (fields[i], "name") == 0)
+                plugin_instance_format[i] = plginst_name;
+            else if (strcasecmp (fields[i], "uuid") == 0)
+                plugin_instance_format[i] = plginst_uuid;
+            else {
+                sfree (value_copy);
+                ERROR (PLUGIN_NAME " plugin: unknown HostnameFormat field: %s", fields[i]);
+                return -1;
+            }
+        }
+        sfree (value_copy);
+
+        for (i = n; i < PLGINST_MAX_FIELDS; ++i)
+            plugin_instance_format[i] = plginst_none;
+
+        return 0;
+    }
+
+    if (strcasecmp (key, "InterfaceFormat") == 0) {
+        if (strcasecmp (value, "name") == 0)
+            interface_format = if_name;
+        else if (strcasecmp (value, "address") == 0)
+            interface_format = if_address;
+        else if (strcasecmp (value, "number") == 0)
+            interface_format = if_number;
+        else {
+            ERROR (PLUGIN_NAME " plugin: unknown InterfaceFormat: %s", value);
+            return -1;
+        }
+        return 0;
+    }
+
+    /* Unrecognised option. */
+    return -1;
+}
+
+static int
+lv_read (void)
+{
+    time_t t;
+    int i;
+
+    if (conn == NULL) {
+        /* `conn_string == NULL' is acceptable. */
+        conn = virConnectOpenReadOnly (conn_string);
+        if (conn == NULL) {
+            c_complain (LOG_ERR, &conn_complain,
+                    PLUGIN_NAME " plugin: Unable to connect: "
+                    "virConnectOpenReadOnly failed.");
+            return -1;
+        }
+    }
+    c_release (LOG_NOTICE, &conn_complain,
+            PLUGIN_NAME " plugin: Connection established.");
+
+    time (&t);
+
+    /* Need to refresh domain or device lists? */
+    if ((last_refresh == (time_t) 0) ||
+            ((interval > 0) && ((last_refresh + interval) <= t))) {
+        if (refresh_lists () != 0) {
+            if (conn != NULL)
+                virConnectClose (conn);
+            conn = NULL;
+            return -1;
+        }
+        last_refresh = t;
+    }
+
+#if 0
+    for (i = 0; i < nr_domains; ++i)
+        fprintf (stderr, "domain %s\n", virDomainGetName (domains[i]));
+    for (i = 0; i < nr_block_devices; ++i)
+        fprintf  (stderr, "block device %d %s:%s\n",
+                  i, virDomainGetName (block_devices[i].dom),
+                  block_devices[i].path);
+    for (i = 0; i < nr_interface_devices; ++i)
+        fprintf (stderr, "interface device %d %s:%s\n",
+                 i, virDomainGetName (interface_devices[i].dom),
+                 interface_devices[i].path);
+#endif
+
+    /* Get CPU usage, memory, VCPU usage for each domain. */
+    for (i = 0; i < nr_domains; ++i) {
+        virDomainInfo info;
+        virVcpuInfoPtr vinfo = NULL;
+        virDomainMemoryStatPtr minfo = NULL;
+        int status;
+        int j;
+
+        status = virDomainGetInfo (domains[i], &info);
+        if (status != 0)
+        {
+            ERROR (PLUGIN_NAME " plugin: virDomainGetInfo failed with status %i.",
+                    status);
+            continue;
+        }
+
+        if (info.state != VIR_DOMAIN_RUNNING)
+        {
+            /* only gather stats for running domains */
+            continue;
+        }
+
+        cpu_submit (info.cpuTime, domains[i], "virt_cpu_total");
+        memory_submit ((gauge_t) info.memory * 1024, domains[i]);
+
+        vinfo = malloc (info.nrVirtCpu * sizeof (vinfo[0]));
+        if (vinfo == NULL) {
+            ERROR (PLUGIN_NAME " plugin: malloc failed.");
+            continue;
+        }
+
+        status = virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu,
+                /* cpu map = */ NULL, /* cpu map length = */ 0);
+        if (status < 0)
+        {
+            ERROR (PLUGIN_NAME " plugin: virDomainGetVcpus failed with status %i.",
+                    status);
+            sfree (vinfo);
+            continue;
+        }
+
+        for (j = 0; j < info.nrVirtCpu; ++j)
+            vcpu_submit (vinfo[j].cpuTime,
+                    domains[i], vinfo[j].number, "virt_vcpu");
+
+        sfree (vinfo);
+
+        minfo = malloc (VIR_DOMAIN_MEMORY_STAT_NR * sizeof (virDomainMemoryStatStruct));
+        if (minfo == NULL) {
+            ERROR ("virt plugin: malloc failed.");
+            continue;
+        }
+
+        status =  virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
+
+        if (status < 0) {
+            ERROR ("virt plugin: virDomainMemoryStats failed with status %i.",
+                    status);
+            sfree (minfo);
+            continue;
+        }
+
+        for (j = 0; j < status; j++) {
+            memory_stats_submit ((gauge_t) minfo[j].val * 1024, domains[i], minfo[j].tag);
+        }
+
+        sfree (minfo);
+    }
+
+
+    /* Get block device stats for each domain. */
+    for (i = 0; i < nr_block_devices; ++i) {
+        struct _virDomainBlockStats stats;
+
+        if (virDomainBlockStats (block_devices[i].dom, block_devices[i].path,
+                    &stats, sizeof stats) != 0)
+            continue;
+
+        if ((stats.rd_req != -1) && (stats.wr_req != -1))
+            submit_derive2 ("disk_ops",
+                    (derive_t) stats.rd_req, (derive_t) stats.wr_req,
+                    block_devices[i].dom, block_devices[i].path);
+
+        if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1))
+            submit_derive2 ("disk_octets",
+                    (derive_t) stats.rd_bytes, (derive_t) stats.wr_bytes,
+                    block_devices[i].dom, block_devices[i].path);
+    } /* for (nr_block_devices) */
+
+    /* Get interface stats for each domain. */
+    for (i = 0; i < nr_interface_devices; ++i) {
+        struct _virDomainInterfaceStats stats;
+        char *display_name = NULL;
+
+
+        switch (interface_format) {
+            case if_address:
+                display_name = interface_devices[i].address;
+                break;
+            case if_number:
+                display_name = interface_devices[i].number;
+                break;
+            case if_name:
+            default:
+                display_name = interface_devices[i].path;
+        }
+
+        if (virDomainInterfaceStats (interface_devices[i].dom,
+                    interface_devices[i].path,
+                    &stats, sizeof stats) != 0)
+            continue;
+
+       if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1))
+           submit_derive2 ("if_octets",
+                   (derive_t) stats.rx_bytes, (derive_t) stats.tx_bytes,
+                   interface_devices[i].dom, display_name);
+
+       if ((stats.rx_packets != -1) && (stats.tx_packets != -1))
+           submit_derive2 ("if_packets",
+                   (derive_t) stats.rx_packets, (derive_t) stats.tx_packets,
+                   interface_devices[i].dom, display_name);
+
+       if ((stats.rx_errs != -1) && (stats.tx_errs != -1))
+           submit_derive2 ("if_errors",
+                   (derive_t) stats.rx_errs, (derive_t) stats.tx_errs,
+                   interface_devices[i].dom, display_name);
+
+       if ((stats.rx_drop != -1) && (stats.tx_drop != -1))
+           submit_derive2 ("if_dropped",
+                   (derive_t) stats.rx_drop, (derive_t) stats.tx_drop,
+                   interface_devices[i].dom, display_name);
+    } /* for (nr_interface_devices) */
+
+    return 0;
+}
+
+static int
+refresh_lists (void)
+{
+    int n;
+
+    n = virConnectNumOfDomains (conn);
+    if (n < 0) {
+        VIRT_ERROR (conn, "reading number of domains");
+        return -1;
+    }
+
+    if (n > 0) {
+        int i;
+        int *domids;
+
+        /* Get list of domains. */
+        domids = malloc (sizeof (int) * n);
+        if (domids == 0) {
+            ERROR (PLUGIN_NAME " plugin: malloc failed.");
+            return -1;
+        }
+
+        n = virConnectListDomains (conn, domids, n);
+        if (n < 0) {
+            VIRT_ERROR (conn, "reading list of domains");
+            sfree (domids);
+            return -1;
+        }
+
+        free_block_devices ();
+        free_interface_devices ();
+        free_domains ();
+
+        /* Fetch each domain and add it to the list, unless ignore. */
+        for (i = 0; i < n; ++i) {
+            virDomainPtr dom = NULL;
+            const char *name;
+            char *xml = NULL;
+            xmlDocPtr xml_doc = NULL;
+            xmlXPathContextPtr xpath_ctx = NULL;
+            xmlXPathObjectPtr xpath_obj = NULL;
+            int j;
+
+            dom = virDomainLookupByID (conn, domids[i]);
+            if (dom == NULL) {
+                VIRT_ERROR (conn, "virDomainLookupByID");
+                /* Could be that the domain went away -- ignore it anyway. */
+                continue;
+            }
+
+            name = virDomainGetName (dom);
+            if (name == NULL) {
+                VIRT_ERROR (conn, "virDomainGetName");
+                goto cont;
+            }
+
+            if (il_domains && ignorelist_match (il_domains, name) != 0)
+                goto cont;
+
+            if (add_domain (dom) < 0) {
+                ERROR (PLUGIN_NAME " plugin: malloc failed.");
+                goto cont;
+            }
+
+            /* Get a list of devices for this domain. */
+            xml = virDomainGetXMLDesc (dom, 0);
+            if (!xml) {
+                VIRT_ERROR (conn, "virDomainGetXMLDesc");
+                goto cont;
+            }
+
+            /* Yuck, XML.  Parse out the devices. */
+            xml_doc = xmlReadDoc ((xmlChar *) xml, NULL, NULL, XML_PARSE_NONET);
+            if (xml_doc == NULL) {
+                VIRT_ERROR (conn, "xmlReadDoc");
+                goto cont;
+            }
+
+            xpath_ctx = xmlXPathNewContext (xml_doc);
+
+            /* Block devices. */
+            xpath_obj = xmlXPathEval
+                ((xmlChar *) "/domain/devices/disk/target[@dev]",
+                 xpath_ctx);
+            if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET ||
+                xpath_obj->nodesetval == NULL)
+                goto cont;
+
+            for (j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) {
+                xmlNodePtr node;
+                char *path = NULL;
+
+                node = xpath_obj->nodesetval->nodeTab[j];
+                if (!node) continue;
+                path = (char *) xmlGetProp (node, (xmlChar *) "dev");
+                if (!path) continue;
+
+                if (il_block_devices &&
+                    ignore_device_match (il_block_devices, name, path) != 0)
+                    goto cont2;
+
+                add_block_device (dom, path);
+            cont2:
+                if (path) xmlFree (path);
+            }
+            xmlXPathFreeObject (xpath_obj);
+
+            /* Network interfaces. */
+            xpath_obj = xmlXPathEval
+                ((xmlChar *) "/domain/devices/interface[target[@dev]]",
+                 xpath_ctx);
+            if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET ||
+                xpath_obj->nodesetval == NULL)
+                goto cont;
+
+            xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval;
+
+            for (j = 0; j < xml_interfaces->nodeNr; ++j) {
+                char *path = NULL;
+                char *address = NULL;
+                xmlNodePtr xml_interface;
+
+                xml_interface = xml_interfaces->nodeTab[j];
+                if (!xml_interface) continue;
+                xmlNodePtr child = NULL;
+
+                for (child = xml_interface->children; child; child = child->next) {
+                    if (child->type != XML_ELEMENT_NODE) continue;
+
+                    if (xmlStrEqual(child->name, (const xmlChar *) "target")) {
+                        path = (char *) xmlGetProp (child, (const xmlChar *) "dev");
+                        if (!path) continue;
+                    } else if (xmlStrEqual(child->name, (const xmlChar *) "mac")) {
+                        address = (char *) xmlGetProp (child, (const xmlChar *) "address");
+                        if (!address) continue;
+                    }
+                }
+
+                if (il_interface_devices &&
+                    (ignore_device_match (il_interface_devices, name, path) != 0 ||
+                     ignore_device_match (il_interface_devices, name, address) != 0))
+                    goto cont3;
+
+                add_interface_device (dom, path, address, j+1);
+                cont3:
+                    if (path) xmlFree (path);
+                    if (address) xmlFree (address);
+            }
+
+        cont:
+            if (xpath_obj) xmlXPathFreeObject (xpath_obj);
+            if (xpath_ctx) xmlXPathFreeContext (xpath_ctx);
+            if (xml_doc) xmlFreeDoc (xml_doc);
+            sfree (xml);
+        }
+
+        sfree (domids);
+    }
+
+    return 0;
+}
+
+static void
+free_domains ()
+{
+    int i;
+
+    if (domains) {
+        for (i = 0; i < nr_domains; ++i)
+            virDomainFree (domains[i]);
+        sfree (domains);
+    }
+    domains = NULL;
+    nr_domains = 0;
+}
+
+static int
+add_domain (virDomainPtr dom)
+{
+    virDomainPtr *new_ptr;
+    int new_size = sizeof (domains[0]) * (nr_domains+1);
+
+    if (domains)
+        new_ptr = realloc (domains, new_size);
+    else
+        new_ptr = malloc (new_size);
+
+    if (new_ptr == NULL)
+        return -1;
+
+    domains = new_ptr;
+    domains[nr_domains] = dom;
+    return nr_domains++;
+}
+
+static void
+free_block_devices ()
+{
+    int i;
+
+    if (block_devices) {
+        for (i = 0; i < nr_block_devices; ++i)
+            sfree (block_devices[i].path);
+        sfree (block_devices);
+    }
+    block_devices = NULL;
+    nr_block_devices = 0;
+}
+
+static int
+add_block_device (virDomainPtr dom, const char *path)
+{
+    struct block_device *new_ptr;
+    int new_size = sizeof (block_devices[0]) * (nr_block_devices+1);
+    char *path_copy;
+
+    path_copy = strdup (path);
+    if (!path_copy)
+        return -1;
+
+    if (block_devices)
+        new_ptr = realloc (block_devices, new_size);
+    else
+        new_ptr = malloc (new_size);
+
+    if (new_ptr == NULL) {
+        sfree (path_copy);
+        return -1;
+    }
+    block_devices = new_ptr;
+    block_devices[nr_block_devices].dom = dom;
+    block_devices[nr_block_devices].path = path_copy;
+    return nr_block_devices++;
+}
+
+static void
+free_interface_devices ()
+{
+    int i;
+
+    if (interface_devices) {
+        for (i = 0; i < nr_interface_devices; ++i) {
+            sfree (interface_devices[i].path);
+            sfree (interface_devices[i].address);
+            sfree (interface_devices[i].number);
+        }
+        sfree (interface_devices);
+    }
+    interface_devices = NULL;
+    nr_interface_devices = 0;
+}
+
+static int
+add_interface_device (virDomainPtr dom, const char *path, const char *address, unsigned int number)
+{
+    struct interface_device *new_ptr;
+    int new_size = sizeof (interface_devices[0]) * (nr_interface_devices+1);
+    char *path_copy, *address_copy, number_string[15];
+
+    path_copy = strdup (path);
+    if (!path_copy) return -1;
+
+    address_copy = strdup (address);
+    if (!address_copy) {
+        sfree(path_copy);
+        return -1;
+    }
+
+    snprintf(number_string, sizeof (number_string), "interface-%u", number);
+
+    if (interface_devices)
+        new_ptr = realloc (interface_devices, new_size);
+    else
+        new_ptr = malloc (new_size);
+
+    if (new_ptr == NULL) {
+        sfree (path_copy);
+        sfree (address_copy);
+        return -1;
+    }
+    interface_devices = new_ptr;
+    interface_devices[nr_interface_devices].dom = dom;
+    interface_devices[nr_interface_devices].path = path_copy;
+    interface_devices[nr_interface_devices].address = address_copy;
+    interface_devices[nr_interface_devices].number = strdup(number_string);
+    return nr_interface_devices++;
+}
+
+static int
+ignore_device_match (ignorelist_t *il, const char *domname, const char *devpath)
+{
+    char *name;
+    int n, r;
+
+    n = sizeof (char) * (strlen (domname) + strlen (devpath) + 2);
+    name = malloc (n);
+    if (name == NULL) {
+        ERROR (PLUGIN_NAME " plugin: malloc failed.");
+        return 0;
+    }
+    ssnprintf (name, n, "%s:%s", domname, devpath);
+    r = ignorelist_match (il, name);
+    sfree (name);
+    return r;
+}
+
+static int
+lv_shutdown (void)
+{
+    free_block_devices ();
+    free_interface_devices ();
+    free_domains ();
+
+    if (conn != NULL)
+        virConnectClose (conn);
+    conn = NULL;
+
+    ignorelist_free (il_domains);
+    il_domains = NULL;
+    ignorelist_free (il_block_devices);
+    il_block_devices = NULL;
+    ignorelist_free (il_interface_devices);
+    il_interface_devices = NULL;
+
+    return 0;
+}
+
+void
+module_register (void)
+{
+    plugin_register_config (PLUGIN_NAME,
+    lv_config,
+    config_keys, NR_CONFIG_KEYS);
+    plugin_register_init (PLUGIN_NAME, lv_init);
+    plugin_register_read (PLUGIN_NAME, lv_read);
+    plugin_register_shutdown (PLUGIN_NAME, lv_shutdown);
+}
+
+/*
+ * vim: shiftwidth=4 tabstop=8 softtabstop=4 expandtab fdm=marker
+ */
diff --git a/src/vmem.c b/src/vmem.c
new file mode 100644 (file)
index 0000000..c3ccbe6
--- /dev/null
@@ -0,0 +1,287 @@
+/**
+ * collectd - src/vmem.c
+ * Copyright (C) 2008-2010  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if KERNEL_LINUX
+static const char *config_keys[] =
+{
+  "Verbose"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int verbose_output = 0;
+/* #endif KERNEL_LINUX */
+
+#else
+# error "No applicable input method."
+#endif /* HAVE_LIBSTATGRAB */
+
+static void submit (const char *plugin_instance, const char *type,
+    const char *type_instance, value_t *values, int values_len)
+{
+  value_list_t vl = VALUE_LIST_INIT;
+
+  vl.values = values;
+  vl.values_len = values_len;
+
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "vmem", sizeof (vl.plugin));
+  if (plugin_instance != NULL)
+    sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, type, sizeof (vl.type));
+  if (type_instance != NULL)
+    sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+} /* void vmem_submit */
+
+static void submit_two (const char *plugin_instance, const char *type,
+    const char *type_instance, derive_t c0, derive_t c1)
+{
+  value_t values[2];
+
+  values[0].derive = c0;
+  values[1].derive = c1;
+
+  submit (plugin_instance, type, type_instance, values, 2);
+} /* void submit_one */
+
+static void submit_one (const char *plugin_instance, const char *type,
+    const char *type_instance, value_t value)
+{
+  submit (plugin_instance, type, type_instance, &value, 1);
+} /* void submit_one */
+
+static int vmem_config (const char *key, const char *value)
+{
+  if (strcasecmp ("Verbose", key) == 0)
+  {
+    if (IS_TRUE (value))
+      verbose_output = 1;
+    else
+      verbose_output = 0;
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int vmem_config */
+
+static int vmem_read (void)
+{
+#if KERNEL_LINUX
+  derive_t pgpgin = 0;
+  derive_t pgpgout = 0;
+  int pgpgvalid = 0;
+
+  derive_t pswpin = 0;
+  derive_t pswpout = 0;
+  int pswpvalid = 0;
+
+  derive_t pgfault = 0;
+  derive_t pgmajfault = 0;
+  int pgfaultvalid = 0;
+
+  FILE *fh;
+  char buffer[1024];
+
+  fh = fopen ("/proc/vmstat", "r");
+  if (fh == NULL)
+  {
+    char errbuf[1024];
+    ERROR ("vmem plugin: fopen (/proc/vmstat) failed: %s",
+       sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  while (fgets (buffer, sizeof (buffer), fh) != NULL)
+  {
+    char *fields[4];
+    int fields_num;
+    char *key;
+    char *endptr;
+    derive_t counter;
+    gauge_t gauge;
+
+    fields_num = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
+    if (fields_num != 2)
+      continue;
+
+    key = fields[0];
+
+    endptr = NULL;
+    counter = strtoll (fields[1], &endptr, 10);
+    if (fields[1] == endptr)
+      continue;
+
+    endptr = NULL;
+    gauge = strtod (fields[1], &endptr);
+    if (fields[1] == endptr)
+      continue;
+
+    /* 
+     * Number of pages
+     *
+     * The total number of {inst} pages, e. g dirty pages.
+     */
+    if (strncmp ("nr_", key, strlen ("nr_")) == 0)
+    {
+      char *inst = key + strlen ("nr_");
+      value_t value = { .gauge = gauge };
+      submit_one (NULL, "vmpage_number", inst, value);
+    }
+
+    /* 
+     * Page in and page outs. For memory and swap.
+     */
+    else if (strcmp ("pgpgin", key) == 0)
+    {
+      pgpgin = counter;
+      pgpgvalid |= 0x01;
+    }
+    else if (strcmp ("pgpgout", key) == 0)
+    {
+      pgpgout = counter;
+      pgpgvalid |= 0x02;
+    }
+    else if (strcmp ("pswpin", key) == 0)
+    {
+      pswpin = counter;
+      pswpvalid |= 0x01;
+    }
+    else if (strcmp ("pswpout", key) == 0)
+    {
+      pswpout = counter;
+      pswpvalid |= 0x02;
+    }
+
+    /*
+     * Pagefaults
+     */
+    else if (strcmp ("pgfault", key) == 0)
+    {
+      pgfault = counter;
+      pgfaultvalid |= 0x01;
+    }
+    else if (strcmp ("pgmajfault", key) == 0)
+    {
+      pgmajfault = counter;
+      pgfaultvalid |= 0x02;
+    }
+
+    /*
+     * Skip the other statistics if verbose output is disabled.
+     */
+    else if (verbose_output == 0)
+      continue;
+
+    /*
+     * Number of page allocations, refills, steals and scans. This is collected
+     * ``per zone'', i. e. for DMA, DMA32, normal and possibly highmem.
+     */
+    else if (strncmp ("pgalloc_", key, strlen ("pgalloc_")) == 0)
+    {
+      char *inst = key + strlen ("pgalloc_");
+      value_t value  = { .derive = counter };
+      submit_one (inst, "vmpage_action", "alloc", value);
+    }
+    else if (strncmp ("pgrefill_", key, strlen ("pgrefill_")) == 0)
+    {
+      char *inst = key + strlen ("pgrefill_");
+      value_t value  = { .derive = counter };
+      submit_one (inst, "vmpage_action", "refill", value);
+    }
+    else if (strncmp ("pgsteal_", key, strlen ("pgsteal_")) == 0)
+    {
+      char *inst = key + strlen ("pgsteal_");
+      value_t value  = { .derive = counter };
+      submit_one (inst, "vmpage_action", "steal", value);
+    }
+    else if (strncmp ("pgscan_kswapd_", key, strlen ("pgscan_kswapd_")) == 0)
+    {
+      char *inst = key + strlen ("pgscan_kswapd_");
+      value_t value  = { .derive = counter };
+      submit_one (inst, "vmpage_action", "scan_kswapd", value);
+    }
+    else if (strncmp ("pgscan_direct_", key, strlen ("pgscan_direct_")) == 0)
+    {
+      char *inst = key + strlen ("pgscan_direct_");
+      value_t value  = { .derive = counter };
+      submit_one (inst, "vmpage_action", "scan_direct", value);
+    }
+
+    /*
+     * Page action
+     *
+     * number of pages moved to the active or inactive lists and freed, i. e.
+     * removed from either list.
+     */
+    else if (strcmp ("pgfree", key) == 0)
+    {
+      value_t value  = { .derive = counter };
+      submit_one (NULL, "vmpage_action", "free", value);
+    }
+    else if (strcmp ("pgactivate", key) == 0)
+    {
+      value_t value  = { .derive = counter };
+      submit_one (NULL, "vmpage_action", "activate", value);
+    }
+    else if (strcmp ("pgdeactivate", key) == 0)
+    {
+      value_t value  = { .derive = counter };
+      submit_one (NULL, "vmpage_action", "deactivate", value);
+    }
+  } /* while (fgets) */
+
+  fclose (fh);
+  fh = NULL;
+
+  if (pgfaultvalid == 0x03)
+    submit_two (NULL, "vmpage_faults", NULL, pgfault, pgmajfault);
+
+  if (pgpgvalid == 0x03)
+    submit_two (NULL, "vmpage_io", "memory", pgpgin, pgpgout);
+
+  if (pswpvalid == 0x03)
+    submit_two (NULL, "vmpage_io", "swap", pswpin, pswpout);
+#endif /* KERNEL_LINUX */
+
+  return (0);
+} /* int vmem_read */
+
+void module_register (void)
+{
+  plugin_register_config ("vmem", vmem_config,
+      config_keys, config_keys_num);
+  plugin_register_read ("vmem", vmem_read);
+} /* void module_register */
+
+/* vim: set sw=2 sts=2 ts=8 : */
diff --git a/src/vserver.c b/src/vserver.c
new file mode 100644 (file)
index 0000000..bd2e867
--- /dev/null
@@ -0,0 +1,367 @@
+/**
+ * collectd - src/vserver.c
+ * Copyright (C) 2006,2007  Sebastian Harl
+ * Copyright (C) 2007-2010  Florian octo Forster
+ *
+ * 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:
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <dirent.h>
+#include <sys/types.h>
+
+#define BUFSIZE 512
+
+#define PROCDIR "/proc/virtual"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+static int pagesize = 0;
+
+static int vserver_init (void)
+{
+       /* XXX Should we check for getpagesize () in configure?
+        * What's the right thing to do, if there is no getpagesize ()? */
+       pagesize = getpagesize ();
+
+       return (0);
+} /* static void vserver_init(void) */
+
+static void traffic_submit (const char *plugin_instance,
+               const char *type_instance, derive_t rx, derive_t tx)
+{
+       value_t values[2];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = rx;
+       values[1].derive = tx;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "if_octets", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void traffic_submit */
+
+static void load_submit (const char *plugin_instance,
+               gauge_t snum, gauge_t mnum, gauge_t lnum)
+{
+       value_t values[3];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = snum;
+       values[1].gauge = mnum;
+       values[2].gauge = lnum;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, "load", sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void submit_gauge (const char *plugin_instance, const char *type,
+               const char *type_instance, gauge_t value)
+
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* void submit_gauge */
+
+static derive_t vserver_get_sock_bytes(const char *s)
+{
+       value_t v;
+       int status;
+
+       while (s[0] != '/')
+               ++s;
+
+       /* Remove '/' */
+       ++s;
+
+       status = parse_value (s, &v, DS_TYPE_DERIVE);
+       if (status != 0)
+               return (-1);
+       return (v.derive);
+}
+
+static int vserver_read (void)
+{
+#if NAME_MAX < 1024
+# define DIRENT_BUFFER_SIZE (sizeof (struct dirent) + 1024 + 1)
+#else
+# define DIRENT_BUFFER_SIZE (sizeof (struct dirent) + NAME_MAX + 1)
+#endif
+
+       DIR                     *proc;
+       struct dirent   *dent; /* 42 */
+       char dirent_buffer[DIRENT_BUFFER_SIZE];
+
+       errno = 0;
+       proc = opendir (PROCDIR);
+       if (proc == NULL)
+       {
+               char errbuf[1024];
+               ERROR ("vserver plugin: fopen (%s): %s", PROCDIR, 
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       while (42)
+       {
+               int len;
+               char file[BUFSIZE];
+
+               FILE *fh;
+               char buffer[BUFSIZE];
+
+               struct stat statbuf;
+               char *cols[4];
+
+               int status;
+
+               status = readdir_r (proc, (struct dirent *) dirent_buffer, &dent);
+               if (status != 0)
+               {
+                       char errbuf[4096];
+                       ERROR ("vserver plugin: readdir_r failed: %s",
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+                       closedir (proc);
+                       return (-1);
+               }
+               else if (dent == NULL)
+               {
+                       /* end of directory */
+                       break;
+               }
+
+               if (dent->d_name[0] == '.')
+                       continue;
+
+               len = ssnprintf (file, sizeof (file), PROCDIR "/%s", dent->d_name);
+               if ((len < 0) || (len >= BUFSIZE))
+                       continue;
+               
+               status = stat (file, &statbuf);
+               if (status != 0)
+               {
+                       char errbuf[4096];
+                       WARNING ("vserver plugin: stat (%s) failed: %s",
+                                       file, sstrerror (errno, errbuf, sizeof (errbuf)));
+                       continue;
+               }
+               
+               if (!S_ISDIR (statbuf.st_mode))
+                       continue;
+
+               /* socket message accounting */
+               len = ssnprintf (file, sizeof (file),
+                               PROCDIR "/%s/cacct", dent->d_name);
+               if ((len < 0) || ((size_t) len >= sizeof (file)))
+                       continue;
+
+               if (NULL == (fh = fopen (file, "r")))
+               {
+                       char errbuf[1024];
+                       ERROR ("Cannot open '%s': %s", file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+
+               while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
+               {
+                       derive_t rx;
+                       derive_t tx;
+                       char *type_instance;
+
+                       if (strsplit (buffer, cols, 4) < 4)
+                               continue;
+
+                       if (0 == strcmp (cols[0], "UNIX:"))
+                               type_instance = "unix";
+                       else if (0 == strcmp (cols[0], "INET:"))
+                               type_instance = "inet";
+                       else if (0 == strcmp (cols[0], "INET6:"))
+                               type_instance = "inet6";
+                       else if (0 == strcmp (cols[0], "OTHER:"))
+                               type_instance = "other";
+                       else if (0 == strcmp (cols[0], "UNSPEC:"))
+                               type_instance = "unspec";
+                       else
+                               continue;
+
+                       rx = vserver_get_sock_bytes (cols[1]);
+                       tx = vserver_get_sock_bytes (cols[2]);
+                       /* cols[3] == errors */
+
+                       traffic_submit (dent->d_name, type_instance, rx, tx);
+               } /* while (fgets) */
+
+               if (fh != NULL)
+               {
+                       fclose (fh);
+                       fh = NULL;
+               }
+
+               /* thread information and load */
+               len = ssnprintf (file, sizeof (file),
+                               PROCDIR "/%s/cvirt", dent->d_name);
+               if ((len < 0) || ((size_t) len >= sizeof (file)))
+                       continue;
+
+               if (NULL == (fh = fopen (file, "r")))
+               {
+                       char errbuf[1024];
+                       ERROR ("Cannot open '%s': %s", file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+
+               while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
+               {
+                       int n = strsplit (buffer, cols, 4);
+
+                       if (2 == n)
+                       {
+                               char   *type_instance;
+                               gauge_t value;
+
+                               if (0 == strcmp (cols[0], "nr_threads:"))
+                                       type_instance = "total";
+                               else if (0 == strcmp (cols[0], "nr_running:"))
+                                       type_instance = "running";
+                               else if (0 == strcmp (cols[0], "nr_unintr:"))
+                                       type_instance = "uninterruptable";
+                               else if (0 == strcmp (cols[0], "nr_onhold:"))
+                                       type_instance = "onhold";
+                               else
+                                       continue;
+
+                               value = atof (cols[1]);
+                               submit_gauge (dent->d_name, "vs_threads", type_instance, value);
+                       }
+                       else if (4 == n) {
+                               if (0 == strcmp (cols[0], "loadavg:"))
+                               {
+                                       gauge_t snum = atof (cols[1]);
+                                       gauge_t mnum = atof (cols[2]);
+                                       gauge_t lnum = atof (cols[3]);
+                                       load_submit (dent->d_name, snum, mnum, lnum);
+                               }
+                       }
+               } /* while (fgets) */
+
+               if (fh != NULL)
+               {
+                       fclose (fh);
+                       fh = NULL;
+               }
+
+               /* processes and memory usage */
+               len = ssnprintf (file, sizeof (file),
+                               PROCDIR "/%s/limit", dent->d_name);
+               if ((len < 0) || ((size_t) len >= sizeof (file)))
+                       continue;
+
+               if (NULL == (fh = fopen (file, "r")))
+               {
+                       char errbuf[1024];
+                       ERROR ("Cannot open '%s': %s", file,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+
+               while ((fh != NULL) && (NULL != fgets (buffer, BUFSIZE, fh)))
+               {
+                       char *type = "vs_memory";
+                       char *type_instance;
+                       gauge_t value;
+
+                       if (strsplit (buffer, cols, 2) < 2)
+                               continue;
+
+                       if (0 == strcmp (cols[0], "PROC:"))
+                       {
+                               type = "vs_processes";
+                               type_instance = "";
+                               value = atof (cols[1]);
+                       }
+                       else
+                       {
+                               if (0 == strcmp (cols[0], "VM:"))
+                                       type_instance = "vm";
+                               else if (0 == strcmp (cols[0], "VML:"))
+                                       type_instance = "vml";
+                               else if (0 == strcmp (cols[0], "RSS:"))
+                                       type_instance = "rss";
+                               else if (0 == strcmp (cols[0], "ANON:"))
+                                       type_instance = "anon";
+                               else
+                                       continue;
+
+                               value = atof (cols[1]) * pagesize;
+                       }
+
+                       submit_gauge (dent->d_name, type, type_instance, value);
+               } /* while (fgets) */
+
+               if (fh != NULL)
+               {
+                       fclose (fh);
+                       fh = NULL;
+               }
+       } /* while (readdir) */
+
+       closedir (proc);
+
+       return (0);
+} /* int vserver_read */
+
+void module_register (void)
+{
+       plugin_register_init ("vserver", vserver_init);
+       plugin_register_read ("vserver", vserver_read);
+} /* void module_register(void) */
+
+/* vim: set ts=4 sw=4 noexpandtab : */
diff --git a/src/wireless.c b/src/wireless.c
new file mode 100644 (file)
index 0000000..f2a3cf5
--- /dev/null
@@ -0,0 +1,173 @@
+/**
+ * collectd - src/wireless.c
+ * Copyright (C) 2006,2007  Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if !KERNEL_LINUX
+# error "No applicable input method."
+#endif
+
+#define WIRELESS_PROC_FILE "/proc/net/wireless"
+
+#if 0
+static double wireless_dbm_to_watt (double dbm)
+{
+       double watt;
+
+       /*
+        * dbm = 10 * log_{10} (1000 * power / W)
+        * power = 10^(dbm/10) * W/1000 
+        */
+
+       watt = pow (10.0, (dbm / 10.0)) / 1000.0;
+
+       return (watt);
+}
+#endif
+
+static void wireless_submit (const char *plugin_instance, const char *type,
+               double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "wireless", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, plugin_instance,
+                       sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void wireless_submit */
+
+#define POWER_MIN -90.0
+#define POWER_MAX -50.0
+static double wireless_percent_to_power (double quality)
+{
+       assert ((quality >= 0.0) && (quality <= 100.0));
+
+       return ((quality * (POWER_MAX - POWER_MIN)) + POWER_MIN);
+} /* double wireless_percent_to_power */
+
+static int wireless_read (void)
+{
+#ifdef KERNEL_LINUX
+       FILE *fh;
+       char buffer[1024];
+
+       char   *device;
+       double  quality;
+       double  power;
+       double  noise;
+       
+       char *fields[8];
+       int   numfields;
+
+       int devices_found;
+       int len;
+
+       /* there are a variety of names for the wireless device */
+       if ((fh = fopen (WIRELESS_PROC_FILE, "r")) == NULL)
+       {
+               char errbuf[1024];
+               WARNING ("wireless: fopen: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       devices_found = 0;
+       while (fgets (buffer, sizeof (buffer), fh) != NULL)
+       {
+               char *endptr;
+
+               numfields = strsplit (buffer, fields, 8);
+
+               if (numfields < 5)
+                       continue;
+
+               len = strlen (fields[0]) - 1;
+               if (len < 1)
+                       continue;
+               if (fields[0][len] != ':')
+                       continue;
+               fields[0][len] = '\0';
+
+               device  = fields[0];
+
+               quality = strtod (fields[2], &endptr);
+               if (fields[2] == endptr)
+                       quality = -1.0; /* invalid */
+
+               /* power [dBm] < 0.0 */
+               power = strtod (fields[3], &endptr);
+               if (fields[3] == endptr)
+                       power = 1.0; /* invalid */
+               else if ((power >= 0.0) && (power <= 100.0))
+                       power = wireless_percent_to_power (power);
+               else if ((power > 100.0) && (power <= 256.0))
+                       power = power - 256.0;
+               else if (power > 0.0)
+                       power = 1.0; /* invalid */
+
+               /* noise [dBm] < 0.0 */
+               noise = strtod (fields[4], &endptr);
+               if (fields[4] == endptr)
+                       noise = 1.0; /* invalid */
+               else if ((noise >= 0.0) && (noise <= 100.0))
+                       noise = wireless_percent_to_power (noise);
+               else if ((noise > 100.0) && (noise <= 256.0))
+                       noise = noise - 256.0;
+               else if (noise > 0.0)
+                       noise = 1.0; /* invalid */
+
+               wireless_submit (device, "signal_quality", quality);
+               wireless_submit (device, "signal_power", power);
+               wireless_submit (device, "signal_noise", noise);
+
+               devices_found++;
+       }
+
+       fclose (fh);
+
+       /* If no wireless devices are present return an error, so the plugin
+        * code delays our read function. */
+       if (devices_found == 0)
+               return (-1);
+#endif /* KERNEL_LINUX */
+
+       return (0);
+} /* int wireless_read */
+
+void module_register (void)
+{
+       plugin_register_read ("wireless", wireless_read);
+} /* void module_register */
diff --git a/src/write_graphite.c b/src/write_graphite.c
new file mode 100644 (file)
index 0000000..41451a8
--- /dev/null
@@ -0,0 +1,615 @@
+/**
+ * collectd - src/write_graphite.c
+ * Copyright (C) 2012       Pierre-Yves Ritschard
+ * Copyright (C) 2011       Scott Sanders
+ * Copyright (C) 2009       Paul Sadauskas
+ * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2007-2013  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Doug MacEachern <dougm at hyperic.com>
+ *   Paul Sadauskas <psadauskas at gmail.com>
+ *   Scott Sanders <scott at jssjr.com>
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ *
+ * Based on the write_http plugin.
+ **/
+
+ /* write_graphite plugin configuation example
+  *
+  * <Plugin write_graphite>
+  *   <Carbon>
+  *     Host "localhost"
+  *     Port "2003"
+  *     Protocol "udp"
+  *     LogSendErrors true
+  *     Prefix "collectd"
+  *   </Carbon>
+  * </Plugin>
+  */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include "utils_cache.h"
+#include "utils_complain.h"
+#include "utils_format_graphite.h"
+
+/* Folks without pthread will need to disable this plugin. */
+#include <pthread.h>
+
+#include <sys/socket.h>
+#include <netdb.h>
+
+#ifndef WG_DEFAULT_NODE
+# define WG_DEFAULT_NODE "localhost"
+#endif
+
+#ifndef WG_DEFAULT_SERVICE
+# define WG_DEFAULT_SERVICE "2003"
+#endif
+
+#ifndef WG_DEFAULT_PROTOCOL
+# define WG_DEFAULT_PROTOCOL "tcp"
+#endif
+
+#ifndef WG_DEFAULT_LOG_SEND_ERRORS
+# define WG_DEFAULT_LOG_SEND_ERRORS 1
+#endif
+
+#ifndef WG_DEFAULT_ESCAPE
+# define WG_DEFAULT_ESCAPE '_'
+#endif
+
+/* Ethernet - (IPv6 + TCP) = 1500 - (40 + 32) = 1428 */
+#ifndef WG_SEND_BUF_SIZE
+# define WG_SEND_BUF_SIZE 1428
+#endif
+
+#ifndef WG_MIN_RECONNECT_INTERVAL
+# define WG_MIN_RECONNECT_INTERVAL TIME_T_TO_CDTIME_T (1)
+#endif
+
+/*
+ * Private variables
+ */
+struct wg_callback
+{
+    int      sock_fd;
+
+    char    *name;
+
+    char    *node;
+    char    *service;
+    char    *protocol;
+    _Bool   log_send_errors;
+    char    *prefix;
+    char    *postfix;
+    char     escape_char;
+
+    unsigned int format_flags;
+
+    char     send_buf[WG_SEND_BUF_SIZE];
+    size_t   send_buf_free;
+    size_t   send_buf_fill;
+    cdtime_t send_buf_init_time;
+
+    pthread_mutex_t send_lock;
+    c_complain_t init_complaint;
+    cdtime_t last_connect_time;
+};
+
+
+/*
+ * Functions
+ */
+static void wg_reset_buffer (struct wg_callback *cb)
+{
+    memset (cb->send_buf, 0, sizeof (cb->send_buf));
+    cb->send_buf_free = sizeof (cb->send_buf);
+    cb->send_buf_fill = 0;
+    cb->send_buf_init_time = cdtime ();
+}
+
+static int wg_send_buffer (struct wg_callback *cb)
+{
+    ssize_t status = 0;
+
+    status = swrite (cb->sock_fd, cb->send_buf, strlen (cb->send_buf));
+    if (status < 0)
+    {
+        const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
+
+        if (cb->log_send_errors)
+        {
+            char errbuf[1024];
+            ERROR ("write_graphite plugin: send to %s:%s (%s) failed with status %zi (%s)",
+                    cb->node, cb->service, protocol,
+                    status, sstrerror (errno, errbuf, sizeof (errbuf)));
+        }
+
+        close (cb->sock_fd);
+        cb->sock_fd = -1;
+
+        return (-1);
+    }
+
+    return (0);
+}
+
+/* NOTE: You must hold cb->send_lock when calling this function! */
+static int wg_flush_nolock (cdtime_t timeout, struct wg_callback *cb)
+{
+    int status;
+
+    DEBUG ("write_graphite plugin: wg_flush_nolock: timeout = %.3f; "
+            "send_buf_fill = %zu;",
+            (double)timeout,
+            cb->send_buf_fill);
+
+    /* timeout == 0  => flush unconditionally */
+    if (timeout > 0)
+    {
+        cdtime_t now;
+
+        now = cdtime ();
+        if ((cb->send_buf_init_time + timeout) > now)
+            return (0);
+    }
+
+    if (cb->send_buf_fill <= 0)
+    {
+        cb->send_buf_init_time = cdtime ();
+        return (0);
+    }
+
+    status = wg_send_buffer (cb);
+    wg_reset_buffer (cb);
+
+    return (status);
+}
+
+static int wg_callback_init (struct wg_callback *cb)
+{
+    struct addrinfo ai_hints;
+    struct addrinfo *ai_list;
+    struct addrinfo *ai_ptr;
+    cdtime_t now;
+    int status;
+
+    const char *node = cb->node ? cb->node : WG_DEFAULT_NODE;
+    const char *service = cb->service ? cb->service : WG_DEFAULT_SERVICE;
+    const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
+
+    char connerr[1024] = "";
+
+    if (cb->sock_fd > 0)
+        return (0);
+
+    /* Don't try to reconnect too often. By default, one reconnection attempt
+     * is made per second. */
+    now = cdtime ();
+    if ((now - cb->last_connect_time) < WG_MIN_RECONNECT_INTERVAL)
+        return (EAGAIN);
+    cb->last_connect_time = now;
+
+    memset (&ai_hints, 0, sizeof (ai_hints));
+#ifdef AI_ADDRCONFIG
+    ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+    ai_hints.ai_family = AF_UNSPEC;
+
+    if (0 == strcasecmp ("tcp", protocol))
+        ai_hints.ai_socktype = SOCK_STREAM;
+    else
+        ai_hints.ai_socktype = SOCK_DGRAM;
+
+    ai_list = NULL;
+
+    status = getaddrinfo (node, service, &ai_hints, &ai_list);
+    if (status != 0)
+    {
+        ERROR ("write_graphite plugin: getaddrinfo (%s, %s, %s) failed: %s",
+                node, service, protocol, gai_strerror (status));
+        return (-1);
+    }
+
+    assert (ai_list != NULL);
+    for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+    {
+        cb->sock_fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
+                ai_ptr->ai_protocol);
+        if (cb->sock_fd < 0) {
+            char errbuf[1024];
+            snprintf (connerr, sizeof (connerr), "failed to open socket: %s",
+                    sstrerror (errno, errbuf, sizeof (errbuf)));
+            continue;
+        }
+
+        status = connect (cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+        if (status != 0)
+        {
+            char errbuf[1024];
+            snprintf (connerr, sizeof (connerr), "failed to connect to remote "
+                    "host: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
+            close (cb->sock_fd);
+            cb->sock_fd = -1;
+            continue;
+        }
+
+        break;
+    }
+
+    freeaddrinfo (ai_list);
+
+    if (cb->sock_fd < 0)
+    {
+        if (connerr[0] == '\0')
+            /* this should not happen but try to get a message anyway */
+            sstrerror (errno, connerr, sizeof (connerr));
+        c_complain (LOG_ERR, &cb->init_complaint,
+                  "write_graphite plugin: Connecting to %s:%s via %s failed. "
+                  "The last error was: %s", node, service, protocol, connerr);
+        return (-1);
+    }
+    else
+    {
+        c_release (LOG_INFO, &cb->init_complaint,
+                "write_graphite plugin: Successfully connected to %s:%s via %s.",
+                node, service, protocol);
+    }
+
+    wg_reset_buffer (cb);
+
+    return (0);
+}
+
+static void wg_callback_free (void *data)
+{
+    struct wg_callback *cb;
+
+    if (data == NULL)
+        return;
+
+    cb = data;
+
+    pthread_mutex_lock (&cb->send_lock);
+
+    wg_flush_nolock (/* timeout = */ 0, cb);
+
+    if (cb->sock_fd >= 0)
+    {
+        close (cb->sock_fd);
+        cb->sock_fd = -1;
+    }
+
+    sfree(cb->name);
+    sfree(cb->node);
+    sfree(cb->protocol);
+    sfree(cb->service);
+    sfree(cb->prefix);
+    sfree(cb->postfix);
+
+    pthread_mutex_destroy (&cb->send_lock);
+
+    sfree(cb);
+}
+
+static int wg_flush (cdtime_t timeout,
+        const char *identifier __attribute__((unused)),
+        user_data_t *user_data)
+{
+    struct wg_callback *cb;
+    int status;
+
+    if (user_data == NULL)
+        return (-EINVAL);
+
+    cb = user_data->data;
+
+    pthread_mutex_lock (&cb->send_lock);
+
+    if (cb->sock_fd < 0)
+    {
+        status = wg_callback_init (cb);
+        if (status != 0)
+        {
+            /* An error message has already been printed. */
+            pthread_mutex_unlock (&cb->send_lock);
+            return (-1);
+        }
+    }
+
+    status = wg_flush_nolock (timeout, cb);
+    pthread_mutex_unlock (&cb->send_lock);
+
+    return (status);
+}
+
+static int wg_send_message (char const *message, struct wg_callback *cb)
+{
+    int status;
+    size_t message_len;
+
+    message_len = strlen (message);
+
+    pthread_mutex_lock (&cb->send_lock);
+
+    if (cb->sock_fd < 0)
+    {
+        status = wg_callback_init (cb);
+        if (status != 0)
+        {
+            /* An error message has already been printed. */
+            pthread_mutex_unlock (&cb->send_lock);
+            return (-1);
+        }
+    }
+
+    if (message_len >= cb->send_buf_free)
+    {
+        status = wg_flush_nolock (/* timeout = */ 0, cb);
+        if (status != 0)
+        {
+            pthread_mutex_unlock (&cb->send_lock);
+            return (status);
+        }
+    }
+
+    /* Assert that we have enough space for this message. */
+    assert (message_len < cb->send_buf_free);
+
+    /* `message_len + 1' because `message_len' does not include the
+     * trailing null byte. Neither does `send_buffer_fill'. */
+    memcpy (cb->send_buf + cb->send_buf_fill,
+            message, message_len + 1);
+    cb->send_buf_fill += message_len;
+    cb->send_buf_free -= message_len;
+
+    DEBUG ("write_graphite plugin: [%s]:%s (%s) buf %zu/%zu (%.1f %%) \"%s\"",
+            cb->node,
+            cb->service,
+            cb->protocol,
+            cb->send_buf_fill, sizeof (cb->send_buf),
+            100.0 * ((double) cb->send_buf_fill) / ((double) sizeof (cb->send_buf)),
+            message);
+
+    pthread_mutex_unlock (&cb->send_lock);
+
+    return (0);
+}
+
+static int wg_write_messages (const data_set_t *ds, const value_list_t *vl,
+        struct wg_callback *cb)
+{
+    char buffer[WG_SEND_BUF_SIZE];
+    int status;
+
+    if (0 != strcmp (ds->type, vl->type))
+    {
+        ERROR ("write_graphite plugin: DS type does not match "
+                "value list type");
+        return -1;
+    }
+
+    memset (buffer, 0, sizeof (buffer));
+    status = format_graphite (buffer, sizeof (buffer), ds, vl,
+            cb->prefix, cb->postfix, cb->escape_char, cb->format_flags);
+    if (status != 0) /* error message has been printed already. */
+        return (status);
+
+    /* Send the message to graphite */
+    status = wg_send_message (buffer, cb);
+    if (status != 0) /* error message has been printed already. */
+        return (status);
+
+    return (0);
+} /* int wg_write_messages */
+
+static int wg_write (const data_set_t *ds, const value_list_t *vl,
+        user_data_t *user_data)
+{
+    struct wg_callback *cb;
+    int status;
+
+    if (user_data == NULL)
+        return (EINVAL);
+
+    cb = user_data->data;
+
+    status = wg_write_messages (ds, vl, cb);
+
+    return (status);
+}
+
+static int config_set_char (char *dest,
+        oconfig_item_t *ci)
+{
+    char buffer[4];
+    int status;
+
+    memset (buffer, 0, sizeof (buffer));
+
+    status = cf_util_get_string_buffer (ci, buffer, sizeof (buffer));
+    if (status != 0)
+        return (status);
+
+    if (buffer[0] == 0)
+    {
+        ERROR ("write_graphite plugin: Cannot use an empty string for the "
+                "\"EscapeCharacter\" option.");
+        return (-1);
+    }
+
+    if (buffer[1] != 0)
+    {
+        WARNING ("write_graphite plugin: Only the first character of the "
+                "\"EscapeCharacter\" option ('%c') will be used.",
+                (int) buffer[0]);
+    }
+
+    *dest = buffer[0];
+
+    return (0);
+}
+
+static int wg_config_node (oconfig_item_t *ci)
+{
+    struct wg_callback *cb;
+    user_data_t user_data;
+    char callback_name[DATA_MAX_NAME_LEN];
+    int i;
+    int status = 0;
+
+    cb = malloc (sizeof (*cb));
+    if (cb == NULL)
+    {
+        ERROR ("write_graphite plugin: malloc failed.");
+        return (-1);
+    }
+    memset (cb, 0, sizeof (*cb));
+    cb->sock_fd = -1;
+    cb->name = NULL;
+    cb->node = NULL;
+    cb->service = NULL;
+    cb->protocol = NULL;
+    cb->log_send_errors = WG_DEFAULT_LOG_SEND_ERRORS;
+    cb->prefix = NULL;
+    cb->postfix = NULL;
+    cb->escape_char = WG_DEFAULT_ESCAPE;
+    cb->format_flags = GRAPHITE_STORE_RATES;
+
+    /* FIXME: Legacy configuration syntax. */
+    if (strcasecmp ("Carbon", ci->key) != 0)
+    {
+        status = cf_util_get_string (ci, &cb->name);
+        if (status != 0)
+        {
+            wg_callback_free (cb);
+            return (status);
+        }
+    }
+
+    pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
+    C_COMPLAIN_INIT (&cb->init_complaint);
+
+    for (i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp ("Host", child->key) == 0)
+            cf_util_get_string (child, &cb->node);
+        else if (strcasecmp ("Port", child->key) == 0)
+            cf_util_get_service (child, &cb->service);
+        else if (strcasecmp ("Protocol", child->key) == 0)
+        {
+            cf_util_get_string (child, &cb->protocol);
+
+            if (strcasecmp ("UDP", cb->protocol) != 0 &&
+                strcasecmp ("TCP", cb->protocol) != 0)
+            {
+                ERROR ("write_graphite plugin: Unknown protocol (%s)",
+                        cb->protocol);
+                status = -1;
+            }
+        }
+        else if (strcasecmp ("LogSendErrors", child->key) == 0)
+            cf_util_get_boolean (child, &cb->log_send_errors);
+        else if (strcasecmp ("Prefix", child->key) == 0)
+            cf_util_get_string (child, &cb->prefix);
+        else if (strcasecmp ("Postfix", child->key) == 0)
+            cf_util_get_string (child, &cb->postfix);
+        else if (strcasecmp ("StoreRates", child->key) == 0)
+            cf_util_get_flag (child, &cb->format_flags,
+                    GRAPHITE_STORE_RATES);
+        else if (strcasecmp ("SeparateInstances", child->key) == 0)
+            cf_util_get_flag (child, &cb->format_flags,
+                    GRAPHITE_SEPARATE_INSTANCES);
+        else if (strcasecmp ("AlwaysAppendDS", child->key) == 0)
+            cf_util_get_flag (child, &cb->format_flags,
+                    GRAPHITE_ALWAYS_APPEND_DS);
+        else if (strcasecmp ("EscapeCharacter", child->key) == 0)
+            config_set_char (&cb->escape_char, child);
+        else
+        {
+            ERROR ("write_graphite plugin: Invalid configuration "
+                        "option: %s.", child->key);
+            status = -1;
+        }
+
+        if (status != 0)
+            break;
+    }
+
+    if (status != 0)
+    {
+        wg_callback_free (cb);
+        return (status);
+    }
+
+    /* FIXME: Legacy configuration syntax. */
+    if (cb->name == NULL)
+        ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s/%s/%s",
+                cb->node != NULL ? cb->node : WG_DEFAULT_NODE,
+                cb->service != NULL ? cb->service : WG_DEFAULT_SERVICE,
+                cb->protocol != NULL ? cb->protocol : WG_DEFAULT_PROTOCOL);
+    else
+        ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
+                cb->name);
+
+    memset (&user_data, 0, sizeof (user_data));
+    user_data.data = cb;
+    user_data.free_func = wg_callback_free;
+    plugin_register_write (callback_name, wg_write, &user_data);
+
+    user_data.free_func = NULL;
+    plugin_register_flush (callback_name, wg_flush, &user_data);
+
+    return (0);
+}
+
+static int wg_config (oconfig_item_t *ci)
+{
+    int i;
+
+    for (i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp ("Node", child->key) == 0)
+            wg_config_node (child);
+        /* FIXME: Remove this legacy mode in version 6. */
+        else if (strcasecmp ("Carbon", child->key) == 0)
+            wg_config_node (child);
+        else
+        {
+            ERROR ("write_graphite plugin: Invalid configuration "
+                    "option: %s.", child->key);
+        }
+    }
+
+    return (0);
+}
+
+void module_register (void)
+{
+    plugin_register_complex_config ("write_graphite", wg_config);
+}
+
+/* vim: set sw=4 ts=4 sts=4 tw=78 et : */
diff --git a/src/write_http.c b/src/write_http.c
new file mode 100644 (file)
index 0000000..ed596bb
--- /dev/null
@@ -0,0 +1,705 @@
+/**
+ * collectd - src/write_http.c
+ * Copyright (C) 2009       Paul Sadauskas
+ * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2007-2014  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Doug MacEachern <dougm@hyperic.com>
+ *   Paul Sadauskas <psadauskas@gmail.com>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_cache.h"
+#include "utils_format_json.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
+#include <curl/curl.h>
+
+#ifndef WRITE_HTTP_DEFAULT_BUFFER_SIZE
+# define WRITE_HTTP_DEFAULT_BUFFER_SIZE 4096
+#endif
+
+/*
+ * Private variables
+ */
+struct wh_callback_s
+{
+        char *name;
+
+        char *location;
+        char *user;
+        char *pass;
+        char *credentials;
+        _Bool verify_peer;
+        _Bool verify_host;
+        char *cacert;
+        char *capath;
+        char *clientkey;
+        char *clientcert;
+        char *clientkeypass;
+        long sslversion;
+        _Bool store_rates;
+        int   low_speed_limit;
+        time_t low_speed_time;
+        int timeout;
+
+#define WH_FORMAT_COMMAND 0
+#define WH_FORMAT_JSON    1
+        int format;
+
+        CURL *curl;
+        char curl_errbuf[CURL_ERROR_SIZE];
+
+        char  *send_buffer;
+        size_t send_buffer_size;
+        size_t send_buffer_free;
+        size_t send_buffer_fill;
+        cdtime_t send_buffer_init_time;
+
+        pthread_mutex_t send_lock;
+};
+typedef struct wh_callback_s wh_callback_t;
+
+static void wh_reset_buffer (wh_callback_t *cb)  /* {{{ */
+{
+        memset (cb->send_buffer, 0, cb->send_buffer_size);
+        cb->send_buffer_free = cb->send_buffer_size;
+        cb->send_buffer_fill = 0;
+        cb->send_buffer_init_time = cdtime ();
+
+        if (cb->format == WH_FORMAT_JSON)
+        {
+                format_json_initialize (cb->send_buffer,
+                                &cb->send_buffer_fill,
+                                &cb->send_buffer_free);
+        }
+} /* }}} wh_reset_buffer */
+
+static int wh_send_buffer (wh_callback_t *cb) /* {{{ */
+{
+        int status = 0;
+
+        curl_easy_setopt (cb->curl, CURLOPT_POSTFIELDS, cb->send_buffer);
+        status = curl_easy_perform (cb->curl);
+        if (status != CURLE_OK)
+        {
+                ERROR ("write_http plugin: curl_easy_perform failed with "
+                                "status %i: %s",
+                                status, cb->curl_errbuf);
+        }
+        return (status);
+} /* }}} wh_send_buffer */
+
+static int wh_callback_init (wh_callback_t *cb) /* {{{ */
+{
+        struct curl_slist *headers;
+
+        if (cb->curl != NULL)
+                return (0);
+
+        cb->curl = curl_easy_init ();
+        if (cb->curl == NULL)
+        {
+                ERROR ("curl plugin: curl_easy_init failed.");
+                return (-1);
+        }
+
+        if (cb->low_speed_limit > 0 && cb->low_speed_time > 0)
+        {
+                curl_easy_setopt (cb->curl, CURLOPT_LOW_SPEED_LIMIT,
+                                  (long) (cb->low_speed_limit * cb->low_speed_time));
+                curl_easy_setopt (cb->curl, CURLOPT_LOW_SPEED_TIME,
+                                  (long) cb->low_speed_time);
+        }
+
+#ifdef HAVE_CURLOPT_TIMEOUT_MS
+        if (cb->timeout > 0)
+                curl_easy_setopt (cb->curl, CURLOPT_TIMEOUT_MS, (long) cb->timeout);
+#endif
+
+        curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1L);
+        curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
+
+        headers = NULL;
+        headers = curl_slist_append (headers, "Accept:  */*");
+        if (cb->format == WH_FORMAT_JSON)
+                headers = curl_slist_append (headers, "Content-Type: application/json");
+        else
+                headers = curl_slist_append (headers, "Content-Type: text/plain");
+        headers = curl_slist_append (headers, "Expect:");
+        curl_easy_setopt (cb->curl, CURLOPT_HTTPHEADER, headers);
+
+        curl_easy_setopt (cb->curl, CURLOPT_ERRORBUFFER, cb->curl_errbuf);
+        curl_easy_setopt (cb->curl, CURLOPT_URL, cb->location);
+        curl_easy_setopt (cb->curl, CURLOPT_FOLLOWLOCATION, 1L);
+        curl_easy_setopt (cb->curl, CURLOPT_MAXREDIRS, 50L);
+
+        if (cb->user != NULL)
+        {
+#ifdef HAVE_CURLOPT_USERNAME
+                curl_easy_setopt (cb->curl, CURLOPT_USERNAME, cb->user);
+                curl_easy_setopt (cb->curl, CURLOPT_PASSWORD,
+                        (cb->pass == NULL) ? "" : cb->pass);
+#else
+                size_t credentials_size;
+
+                credentials_size = strlen (cb->user) + 2;
+                if (cb->pass != NULL)
+                        credentials_size += strlen (cb->pass);
+
+                cb->credentials = (char *) malloc (credentials_size);
+                if (cb->credentials == NULL)
+                {
+                        ERROR ("curl plugin: malloc failed.");
+                        return (-1);
+                }
+
+                ssnprintf (cb->credentials, credentials_size, "%s:%s",
+                                cb->user, (cb->pass == NULL) ? "" : cb->pass);
+                curl_easy_setopt (cb->curl, CURLOPT_USERPWD, cb->credentials);
+#endif
+                curl_easy_setopt (cb->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+        }
+
+        curl_easy_setopt (cb->curl, CURLOPT_SSL_VERIFYPEER, (long) cb->verify_peer);
+        curl_easy_setopt (cb->curl, CURLOPT_SSL_VERIFYHOST,
+                        cb->verify_host ? 2L : 0L);
+        curl_easy_setopt (cb->curl, CURLOPT_SSLVERSION, cb->sslversion);
+        if (cb->cacert != NULL)
+                curl_easy_setopt (cb->curl, CURLOPT_CAINFO, cb->cacert);
+        if (cb->capath != NULL)
+                curl_easy_setopt (cb->curl, CURLOPT_CAPATH, cb->capath);
+
+        if (cb->clientkey != NULL && cb->clientcert != NULL)
+        {
+            curl_easy_setopt (cb->curl, CURLOPT_SSLKEY, cb->clientkey);
+            curl_easy_setopt (cb->curl, CURLOPT_SSLCERT, cb->clientcert);
+
+            if (cb->clientkeypass != NULL)
+                curl_easy_setopt (cb->curl, CURLOPT_SSLKEYPASSWD, cb->clientkeypass);
+        }
+
+        wh_reset_buffer (cb);
+
+        return (0);
+} /* }}} int wh_callback_init */
+
+static int wh_flush_nolock (cdtime_t timeout, wh_callback_t *cb) /* {{{ */
+{
+        int status;
+
+        DEBUG ("write_http plugin: wh_flush_nolock: timeout = %.3f; "
+                        "send_buffer_fill = %zu;",
+                        CDTIME_T_TO_DOUBLE (timeout),
+                        cb->send_buffer_fill);
+
+        /* timeout == 0  => flush unconditionally */
+        if (timeout > 0)
+        {
+                cdtime_t now;
+
+                now = cdtime ();
+                if ((cb->send_buffer_init_time + timeout) > now)
+                        return (0);
+        }
+
+        if (cb->format == WH_FORMAT_COMMAND)
+        {
+                if (cb->send_buffer_fill <= 0)
+                {
+                        cb->send_buffer_init_time = cdtime ();
+                        return (0);
+                }
+
+                status = wh_send_buffer (cb);
+                wh_reset_buffer (cb);
+        }
+        else if (cb->format == WH_FORMAT_JSON)
+        {
+                if (cb->send_buffer_fill <= 2)
+                {
+                        cb->send_buffer_init_time = cdtime ();
+                        return (0);
+                }
+
+                status = format_json_finalize (cb->send_buffer,
+                                &cb->send_buffer_fill,
+                                &cb->send_buffer_free);
+                if (status != 0)
+                {
+                        ERROR ("write_http: wh_flush_nolock: "
+                                        "format_json_finalize failed.");
+                        wh_reset_buffer (cb);
+                        return (status);
+                }
+
+                status = wh_send_buffer (cb);
+                wh_reset_buffer (cb);
+        }
+        else
+        {
+                ERROR ("write_http: wh_flush_nolock: "
+                                "Unknown format: %i",
+                                cb->format);
+                return (-1);
+        }
+
+        return (status);
+} /* }}} wh_flush_nolock */
+
+static int wh_flush (cdtime_t timeout, /* {{{ */
+                const char *identifier __attribute__((unused)),
+                user_data_t *user_data)
+{
+        wh_callback_t *cb;
+        int status;
+
+        if (user_data == NULL)
+                return (-EINVAL);
+
+        cb = user_data->data;
+
+        pthread_mutex_lock (&cb->send_lock);
+
+        if (cb->curl == NULL)
+        {
+                status = wh_callback_init (cb);
+                if (status != 0)
+                {
+                        ERROR ("write_http plugin: wh_callback_init failed.");
+                        pthread_mutex_unlock (&cb->send_lock);
+                        return (-1);
+                }
+        }
+
+        status = wh_flush_nolock (timeout, cb);
+        pthread_mutex_unlock (&cb->send_lock);
+
+        return (status);
+} /* }}} int wh_flush */
+
+static void wh_callback_free (void *data) /* {{{ */
+{
+        wh_callback_t *cb;
+
+        if (data == NULL)
+                return;
+
+        cb = data;
+
+        wh_flush_nolock (/* timeout = */ 0, cb);
+
+        if (cb->curl != NULL)
+        {
+                curl_easy_cleanup (cb->curl);
+                cb->curl = NULL;
+        }
+        sfree (cb->name);
+        sfree (cb->location);
+        sfree (cb->user);
+        sfree (cb->pass);
+        sfree (cb->credentials);
+        sfree (cb->cacert);
+        sfree (cb->capath);
+        sfree (cb->clientkey);
+        sfree (cb->clientcert);
+        sfree (cb->clientkeypass);
+        sfree (cb->send_buffer);
+
+        sfree (cb);
+} /* }}} void wh_callback_free */
+
+static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+                wh_callback_t *cb)
+{
+        char key[10*DATA_MAX_NAME_LEN];
+        char values[512];
+        char command[1024];
+        size_t command_len;
+
+        int status;
+
+        if (0 != strcmp (ds->type, vl->type)) {
+                ERROR ("write_http plugin: DS type does not match "
+                                "value list type");
+                return -1;
+        }
+
+        /* Copy the identifier to `key' and escape it. */
+        status = FORMAT_VL (key, sizeof (key), vl);
+        if (status != 0) {
+                ERROR ("write_http plugin: error with format_name");
+                return (status);
+        }
+        escape_string (key, sizeof (key));
+
+        /* Convert the values to an ASCII representation and put that into
+         * `values'. */
+        status = format_values (values, sizeof (values), ds, vl, cb->store_rates);
+        if (status != 0) {
+                ERROR ("write_http plugin: error with "
+                                "wh_value_list_to_string");
+                return (status);
+        }
+
+        command_len = (size_t) ssnprintf (command, sizeof (command),
+                        "PUTVAL %s interval=%.3f %s\r\n",
+                        key,
+                        CDTIME_T_TO_DOUBLE (vl->interval),
+                        values);
+        if (command_len >= sizeof (command)) {
+                ERROR ("write_http plugin: Command buffer too small: "
+                                "Need %zu bytes.", command_len + 1);
+                return (-1);
+        }
+
+        pthread_mutex_lock (&cb->send_lock);
+
+        if (cb->curl == NULL)
+        {
+                status = wh_callback_init (cb);
+                if (status != 0)
+                {
+                        ERROR ("write_http plugin: wh_callback_init failed.");
+                        pthread_mutex_unlock (&cb->send_lock);
+                        return (-1);
+                }
+        }
+
+        if (command_len >= cb->send_buffer_free)
+        {
+                status = wh_flush_nolock (/* timeout = */ 0, cb);
+                if (status != 0)
+                {
+                        pthread_mutex_unlock (&cb->send_lock);
+                        return (status);
+                }
+        }
+        assert (command_len < cb->send_buffer_free);
+
+        /* `command_len + 1' because `command_len' does not include the
+         * trailing null byte. Neither does `send_buffer_fill'. */
+        memcpy (cb->send_buffer + cb->send_buffer_fill,
+                        command, command_len + 1);
+        cb->send_buffer_fill += command_len;
+        cb->send_buffer_free -= command_len;
+
+        DEBUG ("write_http plugin: <%s> buffer %zu/%zu (%g%%) \"%s\"",
+                        cb->location,
+                        cb->send_buffer_fill, cb->send_buffer_size,
+                        100.0 * ((double) cb->send_buffer_fill) / ((double) cb->send_buffer_size),
+                        command);
+
+        /* Check if we have enough space for this command. */
+        pthread_mutex_unlock (&cb->send_lock);
+
+        return (0);
+} /* }}} int wh_write_command */
+
+static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+                wh_callback_t *cb)
+{
+        int status;
+
+        pthread_mutex_lock (&cb->send_lock);
+
+        if (cb->curl == NULL)
+        {
+                status = wh_callback_init (cb);
+                if (status != 0)
+                {
+                        ERROR ("write_http plugin: wh_callback_init failed.");
+                        pthread_mutex_unlock (&cb->send_lock);
+                        return (-1);
+                }
+        }
+
+        status = format_json_value_list (cb->send_buffer,
+                        &cb->send_buffer_fill,
+                        &cb->send_buffer_free,
+                        ds, vl, cb->store_rates);
+        if (status == (-ENOMEM))
+        {
+                status = wh_flush_nolock (/* timeout = */ 0, cb);
+                if (status != 0)
+                {
+                        wh_reset_buffer (cb);
+                        pthread_mutex_unlock (&cb->send_lock);
+                        return (status);
+                }
+
+                status = format_json_value_list (cb->send_buffer,
+                                &cb->send_buffer_fill,
+                                &cb->send_buffer_free,
+                                ds, vl, cb->store_rates);
+        }
+        if (status != 0)
+        {
+                pthread_mutex_unlock (&cb->send_lock);
+                return (status);
+        }
+
+        DEBUG ("write_http plugin: <%s> buffer %zu/%zu (%g%%)",
+                        cb->location,
+                        cb->send_buffer_fill, cb->send_buffer_size,
+                        100.0 * ((double) cb->send_buffer_fill) / ((double) cb->send_buffer_size));
+
+        /* Check if we have enough space for this command. */
+        pthread_mutex_unlock (&cb->send_lock);
+
+        return (0);
+} /* }}} int wh_write_json */
+
+static int wh_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */
+                user_data_t *user_data)
+{
+        wh_callback_t *cb;
+        int status;
+
+        if (user_data == NULL)
+                return (-EINVAL);
+
+        cb = user_data->data;
+
+        if (cb->format == WH_FORMAT_JSON)
+                status = wh_write_json (ds, vl, cb);
+        else
+                status = wh_write_command (ds, vl, cb);
+
+        return (status);
+} /* }}} int wh_write */
+
+static int config_set_format (wh_callback_t *cb, /* {{{ */
+                oconfig_item_t *ci)
+{
+        char *string;
+
+        if ((ci->values_num != 1)
+                        || (ci->values[0].type != OCONFIG_TYPE_STRING))
+        {
+                WARNING ("write_http plugin: The `%s' config option "
+                                "needs exactly one string argument.", ci->key);
+                return (-1);
+        }
+
+        string = ci->values[0].value.string;
+        if (strcasecmp ("Command", string) == 0)
+                cb->format = WH_FORMAT_COMMAND;
+        else if (strcasecmp ("JSON", string) == 0)
+                cb->format = WH_FORMAT_JSON;
+        else
+        {
+                ERROR ("write_http plugin: Invalid format string: %s",
+                                string);
+                return (-1);
+        }
+
+        return (0);
+} /* }}} int config_set_format */
+
+static int wh_config_node (oconfig_item_t *ci) /* {{{ */
+{
+        wh_callback_t *cb;
+        int buffer_size = 0;
+        user_data_t user_data;
+        char callback_name[DATA_MAX_NAME_LEN];
+        int i;
+
+        cb = malloc (sizeof (*cb));
+        if (cb == NULL)
+        {
+                ERROR ("write_http plugin: malloc failed.");
+                return (-1);
+        }
+        memset (cb, 0, sizeof (*cb));
+        cb->verify_peer = 1;
+        cb->verify_host = 1;
+        cb->format = WH_FORMAT_COMMAND;
+        cb->sslversion = CURL_SSLVERSION_DEFAULT;
+        cb->low_speed_limit = 0;
+        cb->timeout = 0;
+
+        pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
+
+        cf_util_get_string (ci, &cb->name);
+
+        /* FIXME: Remove this legacy mode in version 6. */
+        if (strcasecmp ("URL", ci->key) == 0)
+                cf_util_get_string (ci, &cb->location);
+
+        for (i = 0; i < ci->children_num; i++)
+        {
+                oconfig_item_t *child = ci->children + i;
+
+                if (strcasecmp ("URL", child->key) == 0)
+                        cf_util_get_string (child, &cb->location);
+                else if (strcasecmp ("User", child->key) == 0)
+                        cf_util_get_string (child, &cb->user);
+                else if (strcasecmp ("Password", child->key) == 0)
+                        cf_util_get_string (child, &cb->pass);
+                else if (strcasecmp ("VerifyPeer", child->key) == 0)
+                        cf_util_get_boolean (child, &cb->verify_peer);
+                else if (strcasecmp ("VerifyHost", child->key) == 0)
+                        cf_util_get_boolean (child, &cb->verify_host);
+                else if (strcasecmp ("CACert", child->key) == 0)
+                        cf_util_get_string (child, &cb->cacert);
+                else if (strcasecmp ("CAPath", child->key) == 0)
+                        cf_util_get_string (child, &cb->capath);
+                else if (strcasecmp ("ClientKey", child->key) == 0)
+                        cf_util_get_string (child, &cb->clientkey);
+                else if (strcasecmp ("ClientCert", child->key) == 0)
+                        cf_util_get_string (child, &cb->clientcert);
+                else if (strcasecmp ("ClientKeyPass", child->key) == 0)
+                        cf_util_get_string (child, &cb->clientkeypass);
+                else if (strcasecmp ("SSLVersion", child->key) == 0)
+                {
+                        char *value = NULL;
+
+                        cf_util_get_string (child, &value);
+
+                        if (value == NULL || strcasecmp ("default", value) == 0)
+                                cb->sslversion = CURL_SSLVERSION_DEFAULT;
+                        else if (strcasecmp ("SSLv2", value) == 0)
+                                cb->sslversion = CURL_SSLVERSION_SSLv2;
+                        else if (strcasecmp ("SSLv3", value) == 0)
+                                cb->sslversion = CURL_SSLVERSION_SSLv3;
+                        else if (strcasecmp ("TLSv1", value) == 0)
+                                cb->sslversion = CURL_SSLVERSION_TLSv1;
+#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 34)
+                        else if (strcasecmp ("TLSv1_0", value) == 0)
+                                cb->sslversion = CURL_SSLVERSION_TLSv1_0;
+                        else if (strcasecmp ("TLSv1_1", value) == 0)
+                                cb->sslversion = CURL_SSLVERSION_TLSv1_1;
+                        else if (strcasecmp ("TLSv1_2", value) == 0)
+                                cb->sslversion = CURL_SSLVERSION_TLSv1_2;
+#endif
+                        else
+                                ERROR ("write_http plugin: Invalid SSLVersion "
+                                                "option: %s.", value);
+
+                        sfree(value);
+                }
+                else if (strcasecmp ("Format", child->key) == 0)
+                        config_set_format (cb, child);
+                else if (strcasecmp ("StoreRates", child->key) == 0)
+                        cf_util_get_boolean (child, &cb->store_rates);
+                else if (strcasecmp ("BufferSize", child->key) == 0)
+                        cf_util_get_int (child, &buffer_size);
+                else if (strcasecmp ("LowSpeedLimit", child->key) == 0)
+                        cf_util_get_int (child, &cb->low_speed_limit);
+                else if (strcasecmp ("Timeout", child->key) == 0)
+                        cf_util_get_int (child, &cb->timeout);
+                else
+                {
+                        ERROR ("write_http plugin: Invalid configuration "
+                                        "option: %s.", child->key);
+                }
+        }
+
+        if (cb->location == NULL)
+        {
+                ERROR ("write_http plugin: no URL defined for instance '%s'",
+                        cb->name);
+                wh_callback_free (cb);
+                return (-1);
+        }
+
+        if (cb->low_speed_limit > 0)
+                cb->low_speed_time = CDTIME_T_TO_TIME_T(plugin_get_interval());
+
+        /* Determine send_buffer_size. */
+        cb->send_buffer_size = WRITE_HTTP_DEFAULT_BUFFER_SIZE;
+        if (buffer_size >= 1024)
+                cb->send_buffer_size = (size_t) buffer_size;
+        else if (buffer_size != 0)
+                ERROR ("write_http plugin: Ignoring invalid BufferSize setting (%d).",
+                                buffer_size);
+
+        /* Allocate the buffer. */
+        cb->send_buffer = malloc (cb->send_buffer_size);
+        if (cb->send_buffer == NULL)
+        {
+                ERROR ("write_http plugin: malloc(%zu) failed.", cb->send_buffer_size);
+                wh_callback_free (cb);
+                return (-1);
+        }
+        /* Nulls the buffer and sets ..._free and ..._fill. */
+        wh_reset_buffer (cb);
+
+        ssnprintf (callback_name, sizeof (callback_name), "write_http/%s",
+                        cb->name);
+        DEBUG ("write_http: Registering write callback '%s' with URL '%s'",
+                        callback_name, cb->location);
+
+        memset (&user_data, 0, sizeof (user_data));
+        user_data.data = cb;
+        user_data.free_func = NULL;
+        plugin_register_flush (callback_name, wh_flush, &user_data);
+
+        user_data.free_func = wh_callback_free;
+        plugin_register_write (callback_name, wh_write, &user_data);
+
+        return (0);
+} /* }}} int wh_config_node */
+
+static int wh_config (oconfig_item_t *ci) /* {{{ */
+{
+        int i;
+
+        for (i = 0; i < ci->children_num; i++)
+        {
+                oconfig_item_t *child = ci->children + i;
+
+                if (strcasecmp ("Node", child->key) == 0)
+                        wh_config_node (child);
+                /* FIXME: Remove this legacy mode in version 6. */
+                else if (strcasecmp ("URL", child->key) == 0) {
+                        WARNING ("write_http plugin: Legacy <URL> block found. "
+                                "Please use <Node> instead.");
+                        wh_config_node (child);
+                }
+                else
+                {
+                        ERROR ("write_http plugin: Invalid configuration "
+                                        "option: %s.", child->key);
+                }
+        }
+
+        return (0);
+} /* }}} int wh_config */
+
+static int wh_init (void) /* {{{ */
+{
+        /* Call this while collectd is still single-threaded to avoid
+         * initialization issues in libgcrypt. */
+        curl_global_init (CURL_GLOBAL_SSL);
+        return (0);
+} /* }}} int wh_init */
+
+void module_register (void) /* {{{ */
+{
+        plugin_register_complex_config ("write_http", wh_config);
+        plugin_register_init ("write_http", wh_init);
+} /* }}} void module_register */
+
+/* vim: set fdm=marker sw=8 ts=8 tw=78 et : */
diff --git a/src/write_kafka.c b/src/write_kafka.c
new file mode 100644 (file)
index 0000000..b6e8961
--- /dev/null
@@ -0,0 +1,487 @@
+/**
+ * collectd - src/write_kafka.c
+ * Copyright (C) 2014       Pierre-Yves Ritschard
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "utils_cache.h"
+#include "utils_cmd_putval.h"
+#include "utils_format_graphite.h"
+#include "utils_format_json.h"
+#include "utils_crc32.h"
+
+#include <sys/types.h>
+#include <librdkafka/rdkafka.h>
+#include <pthread.h>
+#include <zlib.h>
+#include <errno.h>
+
+struct kafka_topic_context {
+#define KAFKA_FORMAT_JSON        0
+#define KAFKA_FORMAT_COMMAND     1
+#define KAFKA_FORMAT_GRAPHITE    2
+    u_int8_t                     format;
+    unsigned int                 graphite_flags;
+    _Bool                        store_rates;
+    rd_kafka_topic_conf_t       *conf;
+    rd_kafka_topic_t            *topic;
+    rd_kafka_conf_t             *kafka_conf;
+    rd_kafka_t                  *kafka;
+    int                          has_key;
+    u_int32_t                    key;
+    char                        *prefix;
+    char                        *postfix;
+    char                         escape_char;
+    char                        *topic_name;
+    pthread_mutex_t            lock;
+};
+
+static int kafka_handle(struct kafka_topic_context *);
+static int kafka_write(const data_set_t *, const value_list_t *, user_data_t *);
+static int32_t kafka_partition(const rd_kafka_topic_t *, const void *, size_t,
+                               int32_t, void *, void *);
+
+#if defined HAVE_LIBRDKAFKA_LOGGER || defined HAVE_LIBRDKAFKA_LOG_CB
+static void kafka_log(const rd_kafka_t *, int, const char *, const char *);
+
+static void kafka_log(const rd_kafka_t *rkt, int level,
+                      const char *fac, const char *msg)
+{
+    plugin_log(level, "%s", msg);
+}
+#endif
+
+static int32_t kafka_partition(const rd_kafka_topic_t *rkt,
+                               const void *keydata, size_t keylen,
+                               int32_t partition_cnt, void *p, void *m)
+{
+    u_int32_t key = *((u_int32_t *)keydata );
+    u_int32_t target = key % partition_cnt;
+    int32_t   i = partition_cnt;
+
+    while (--i > 0 && !rd_kafka_topic_partition_available(rkt, target)) {
+        target = (target + 1) % partition_cnt;
+    }
+    return target;
+}
+
+static int kafka_handle(struct kafka_topic_context *ctx) /* {{{ */
+{
+    char                         errbuf[1024];
+    rd_kafka_conf_t             *conf;
+    rd_kafka_topic_conf_t       *topic_conf;
+
+    if (ctx->kafka != NULL && ctx->topic != NULL)
+        return(0);
+
+    if (ctx->kafka == NULL) {
+        if ((conf = rd_kafka_conf_dup(ctx->kafka_conf)) == NULL) {
+            ERROR("write_kafka plugin: cannot duplicate kafka config");
+            return(1);
+        }
+
+        if ((ctx->kafka = rd_kafka_new(RD_KAFKA_PRODUCER, conf,
+                                    errbuf, sizeof(errbuf))) == NULL) {
+               ERROR("write_kafka plugin: cannot create kafka handle.");
+               return 1;
+        }
+
+       rd_kafka_conf_destroy(ctx->kafka_conf);
+       ctx->kafka_conf = NULL;
+
+       INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
+
+#ifdef HAVE_LIBRDKAFKA_LOGGER
+       rd_kafka_set_logger(ctx->kafka, kafka_log);
+#endif
+    }
+
+    if (ctx->topic == NULL ) {
+       if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
+            ERROR("write_kafka plugin: cannot duplicate kafka topic config");
+            return 1;
+       }
+
+       if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
+                                                       topic_conf)) == NULL) {
+               ERROR("write_kafka plugin: cannot create topic : %s\n", 
+                       rd_kafka_err2str(rd_kafka_errno2err(errno)));
+               return errno;
+       }
+
+       rd_kafka_topic_conf_destroy(ctx->conf);
+       ctx->conf = NULL;
+
+       INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
+    }
+
+    return(0);
+
+} /* }}} int kafka_handle */
+
+static int kafka_write(const data_set_t *ds, /* {{{ */
+             const value_list_t *vl,
+             user_data_t *ud)
+{
+       int                      status = 0;
+    u_int32_t    key;
+    char         buffer[8192];
+    size_t bfree = sizeof(buffer);
+    size_t bfill = 0;
+    size_t blen = 0;
+       struct kafka_topic_context      *ctx = ud->data;
+
+    if ((ds == NULL) || (vl == NULL) || (ctx == NULL))
+        return EINVAL;
+
+    pthread_mutex_lock (&ctx->lock);
+    status = kafka_handle(ctx);
+    pthread_mutex_unlock (&ctx->lock);
+    if( status != 0 )
+        return status;
+
+    bzero(buffer, sizeof(buffer));
+
+    switch (ctx->format) {
+    case KAFKA_FORMAT_COMMAND:
+        status = create_putval(buffer, sizeof(buffer), ds, vl);
+        if (status != 0) {
+            ERROR("write_kafka plugin: create_putval failed with status %i.",
+                  status);
+            return status;
+        }
+        blen = strlen(buffer);
+        break;
+    case KAFKA_FORMAT_JSON:
+
+        format_json_initialize(buffer, &bfill, &bfree);
+        format_json_value_list(buffer, &bfill, &bfree, ds, vl,
+                               ctx->store_rates);
+        format_json_finalize(buffer, &bfill, &bfree);
+        blen = strlen(buffer);
+        break;
+    case KAFKA_FORMAT_GRAPHITE:
+        status = format_graphite(buffer, sizeof(buffer), ds, vl,
+                                 ctx->prefix, ctx->postfix, ctx->escape_char,
+                                 ctx->graphite_flags);
+        if (status != 0) {
+            ERROR("write_kafka plugin: format_graphite failed with status %i.",
+                  status);
+            return status;
+        }
+        blen = strlen(buffer);
+        break;
+    default:
+        ERROR("write_kafka plugin: invalid format %i.", ctx->format);
+        return -1;
+    }
+
+    /*
+     * We partition our stream by metric name
+     */
+    if (ctx->has_key)
+        key = ctx->key;
+    else
+        key = rand();
+
+    rd_kafka_produce(ctx->topic, RD_KAFKA_PARTITION_UA,
+                     RD_KAFKA_MSG_F_COPY, buffer, blen,
+                     &key, sizeof(key), NULL);
+
+       return status;
+} /* }}} int kafka_write */
+
+static void kafka_topic_context_free(void *p) /* {{{ */
+{
+       struct kafka_topic_context *ctx = p;
+
+       if (ctx == NULL)
+               return;
+
+    if (ctx->topic_name != NULL)
+        sfree(ctx->topic_name);
+    if (ctx->topic != NULL)
+        rd_kafka_topic_destroy(ctx->topic);
+    if (ctx->conf != NULL)
+        rd_kafka_topic_conf_destroy(ctx->conf);
+    if (ctx->kafka_conf != NULL)
+        rd_kafka_conf_destroy(ctx->kafka_conf);
+    if (ctx->kafka != NULL)
+        rd_kafka_destroy(ctx->kafka);
+
+    sfree(ctx);
+} /* }}} void kafka_topic_context_free */
+
+static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{ */
+{
+    int                          status;
+    int                          i;
+    struct kafka_topic_context  *tctx;
+    char                        *key = NULL;
+    char                        *val;
+    char                         callback_name[DATA_MAX_NAME_LEN];
+    char                         errbuf[1024];
+    user_data_t                  ud;
+       oconfig_item_t              *child;
+    rd_kafka_conf_res_t          ret;
+
+       if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
+               ERROR ("write_kafka plugin: calloc failed.");
+        return;
+       }
+
+    tctx->escape_char = '.';
+    tctx->store_rates = 1;
+    tctx->format = KAFKA_FORMAT_JSON;
+
+    if ((tctx->kafka_conf = rd_kafka_conf_dup(conf)) == NULL) {
+        sfree(tctx);
+        ERROR("write_kafka plugin: cannot allocate memory for kafka config");
+        return;
+    }
+
+#ifdef HAVE_LIBRDKAFKA_LOG_CB
+    rd_kafka_conf_set_log_cb(tctx->kafka_conf, kafka_log);
+#endif
+
+    if ((tctx->conf = rd_kafka_topic_conf_new()) == NULL) {
+        rd_kafka_conf_destroy(tctx->kafka_conf);
+        sfree(tctx);
+        ERROR ("write_kafka plugin: cannot create topic configuration.");
+        return;
+    }
+
+    if (ci->values_num != 1) {
+        WARNING("kafka topic name needed.");
+        goto errout;
+    }
+
+    if (ci->values[0].type != OCONFIG_TYPE_STRING) {
+        WARNING("kafka topic needs a string argument.");
+        goto errout;
+    }
+
+    if ((tctx->topic_name = strdup(ci->values[0].value.string)) == NULL) {
+        ERROR("write_kafka plugin: cannot copy topic name.");
+        goto errout;
+    }
+
+       for (i = 0; i < ci->children_num; i++) {
+               /*
+                * The code here could be simplified but makes room
+                * for easy adding of new options later on.
+                */
+               child = &ci->children[i];
+               status = 0;
+
+               if (strcasecmp ("Property", child->key) == 0) {
+                       if (child->values_num != 2) {
+                               WARNING("kafka properties need both a key and a value.");
+                goto errout;
+                       }
+                       if (child->values[0].type != OCONFIG_TYPE_STRING ||
+                           child->values[1].type != OCONFIG_TYPE_STRING) {
+                               WARNING("kafka properties needs string arguments.");
+                goto errout;
+                       }
+            key = child->values[0].value.string;
+            val = child->values[1].value.string;
+            ret = rd_kafka_topic_conf_set(tctx->conf,key, val,
+                                          errbuf, sizeof(errbuf));
+            if (ret != RD_KAFKA_CONF_OK) {
+                               WARNING("cannot set kafka topic property %s to %s: %s.",
+                        key, val, errbuf);
+                goto errout;
+                       }
+
+        } else if (strcasecmp ("Key", child->key) == 0)  {
+            char *tmp_buf = NULL;
+            status = cf_util_get_string(child, &tmp_buf);
+            if (status != 0) {
+                WARNING("write_kafka plugin: invalid key supplied");
+                break;
+            }
+
+            if (strcasecmp(tmp_buf, "Random") != 0) {
+                tctx->has_key = 1;
+                tctx->key = crc32_buffer((u_char *)tmp_buf, strlen(tmp_buf));
+            }
+            sfree(tmp_buf);
+
+        } else if (strcasecmp ("Format", child->key) == 0) {
+            status = cf_util_get_string(child, &key);
+            if (status != 0)
+                goto errout;
+
+            assert(key != NULL);
+
+            if (strcasecmp(key, "Command") == 0) {
+                tctx->format = KAFKA_FORMAT_COMMAND;
+
+            } else if (strcasecmp(key, "Graphite") == 0) {
+                tctx->format = KAFKA_FORMAT_GRAPHITE;
+
+            } else if (strcasecmp(key, "Json") == 0) {
+                tctx->format = KAFKA_FORMAT_JSON;
+
+            } else {
+                WARNING ("write_kafka plugin: Invalid format string: %s",
+                         key);
+            }
+
+            sfree(key);
+
+        } else if (strcasecmp ("StoreRates", child->key) == 0) {
+            status = cf_util_get_boolean (child, &tctx->store_rates);
+            (void) cf_util_get_flag (child, &tctx->graphite_flags,
+                                     GRAPHITE_STORE_RATES);
+
+        } else if (strcasecmp ("GraphiteSeparateInstances", child->key) == 0) {
+            status = cf_util_get_flag (child, &tctx->graphite_flags,
+                                       GRAPHITE_SEPARATE_INSTANCES);
+
+        } else if (strcasecmp ("GraphiteAlwaysAppendDS", child->key) == 0) {
+            status = cf_util_get_flag (child, &tctx->graphite_flags,
+                                       GRAPHITE_ALWAYS_APPEND_DS);
+
+        } else if (strcasecmp ("GraphitePrefix", child->key) == 0) {
+            status = cf_util_get_string (child, &tctx->prefix);
+        } else if (strcasecmp ("GraphitePostfix", child->key) == 0) {
+            status = cf_util_get_string (child, &tctx->postfix);
+        } else if (strcasecmp ("GraphiteEscapeChar", child->key) == 0) {
+            char *tmp_buff = NULL;
+            status = cf_util_get_string (child, &tmp_buff);
+            if (strlen (tmp_buff) > 1)
+                WARNING ("write_kafka plugin: The option \"GraphiteEscapeChar\" handles "
+                        "only one character. Others will be ignored.");
+            tctx->escape_char = tmp_buff[0];
+            sfree (tmp_buff);
+        } else {
+            WARNING ("write_kafka plugin: Invalid directive: %s.", child->key);
+        }
+
+        if (status != 0)
+            break;
+    }
+
+    rd_kafka_topic_conf_set_partitioner_cb(tctx->conf, kafka_partition);
+    rd_kafka_topic_conf_set_opaque(tctx->conf, tctx);
+
+    ssnprintf(callback_name, sizeof(callback_name),
+              "write_kafka/%s", tctx->topic_name);
+
+    ud.data = tctx;
+    ud.free_func = kafka_topic_context_free;
+
+       status = plugin_register_write (callback_name, kafka_write, &ud);
+       if (status != 0) {
+               WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
+                               "failed with status %i.",
+                               callback_name, status);
+        goto errout;
+    }
+
+    pthread_mutex_init (&tctx->lock, /* attr = */ NULL);
+
+    return;
+ errout:
+    if (tctx->topic_name != NULL)
+        free(tctx->topic_name);
+    if (tctx->conf != NULL)
+        rd_kafka_topic_conf_destroy(tctx->conf);
+    if (tctx->kafka_conf != NULL)
+               rd_kafka_conf_destroy(tctx->kafka_conf);
+    sfree(tctx);
+} /* }}} int kafka_config_topic */
+
+static int kafka_config(oconfig_item_t *ci) /* {{{ */
+{
+       int                          i;
+       oconfig_item_t              *child;
+    rd_kafka_conf_t             *conf;
+    rd_kafka_conf_res_t          ret;
+    char                         errbuf[1024];
+
+    if ((conf = rd_kafka_conf_new()) == NULL) {
+        WARNING("cannot allocate kafka configuration.");
+        return -1;
+    }
+       for (i = 0; i < ci->children_num; i++)  {
+               child = &ci->children[i];
+
+               if (strcasecmp("Topic", child->key) == 0) {
+                       kafka_config_topic (conf, child);
+               } else if (strcasecmp(child->key, "Property") == 0) {
+                       char *key = NULL;
+                       char *val = NULL;
+
+                       if (child->values_num != 2) {
+                               WARNING("kafka properties need both a key and a value.");
+                goto errout;
+                       }
+                       if (child->values[0].type != OCONFIG_TYPE_STRING ||
+                           child->values[1].type != OCONFIG_TYPE_STRING) {
+                               WARNING("kafka properties needs string arguments.");
+                goto errout;
+                       }
+                       if ((key = strdup(child->values[0].value.string)) == NULL) {
+                               WARNING("cannot allocate memory for attribute key.");
+                goto errout;
+                       }
+                       if ((val = strdup(child->values[1].value.string)) == NULL) {
+                               WARNING("cannot allocate memory for attribute value.");
+                goto errout;
+                       }
+            ret = rd_kafka_conf_set(conf, key, val, errbuf, sizeof(errbuf));
+            if (ret != RD_KAFKA_CONF_OK) {
+                WARNING("cannot set kafka property %s to %s: %s",
+                        key, val, errbuf);
+                goto errout;
+            }
+                       sfree(key);
+                       sfree(val);
+               } else {
+                       WARNING ("write_kafka plugin: Ignoring unknown "
+                                "configuration option \"%s\" at top level.",
+                                child->key);
+               }
+       }
+    if (conf != NULL)
+        rd_kafka_conf_destroy(conf);
+       return (0);
+ errout:
+    if (conf != NULL)
+        rd_kafka_conf_destroy(conf);
+    return -1;
+} /* }}} int kafka_config */
+
+void module_register(void)
+{
+       plugin_register_complex_config ("write_kafka", kafka_config);
+}
+
+/* vim: set sw=8 sts=8 ts=8 noet : */
diff --git a/src/write_log.c b/src/write_log.c
new file mode 100644 (file)
index 0000000..e37aae9
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * collectd - src/write_log.c
+ * Copyright (C) 2015       Pierre-Yves Ritschard
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ *
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include "utils_format_graphite.h"
+
+/* Folks without pthread will need to disable this plugin. */
+#include <pthread.h>
+
+#include <sys/socket.h>
+#include <netdb.h>
+
+#define WL_BUF_SIZE 8192
+
+static int wl_write_messages (const data_set_t *ds, const value_list_t *vl)
+{
+    char buffer[WL_BUF_SIZE];
+    int status;
+
+    if (0 != strcmp (ds->type, vl->type))
+    {
+        ERROR ("write_log plugin: DS type does not match "
+                "value list type");
+        return -1;
+    }
+
+    memset (buffer, 0, sizeof (buffer));
+    status = format_graphite (buffer, sizeof (buffer), ds, vl,
+                              NULL, NULL, '_', 0);
+    if (status != 0) /* error message has been printed already. */
+        return (status);
+
+    INFO ("write_log values:\n%s", buffer);
+
+    return (0);
+} /* int wl_write_messages */
+
+static int wl_write (const data_set_t *ds, const value_list_t *vl,
+        user_data_t *user_data)
+{
+    int status;
+
+    status = wl_write_messages (ds, vl);
+
+    return (status);
+}
+
+void module_register (void)
+{
+    plugin_register_write ("write_log", wl_write, NULL);
+}
+
+/* vim: set sw=4 ts=4 sts=4 tw=78 et : */
diff --git a/src/write_mongodb.c b/src/write_mongodb.c
new file mode 100644 (file)
index 0000000..24151ce
--- /dev/null
@@ -0,0 +1,384 @@
+/**
+ * collectd - src/write_mongodb.c
+ * Copyright (C) 2010-2013  Florian Forster
+ * Copyright (C) 2010       Akkarit Sangpetch
+ * Copyright (C) 2012       Chris Lundquist
+ *
+ * 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:
+ *   Florian Forster <octo at collectd.org>
+ *   Akkarit Sangpetch <asangpet at andrew.cmu.edu>
+ *   Chris Lundquist <clundquist at bluebox.net>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "utils_cache.h"
+
+#include <pthread.h>
+
+#if HAVE_STDINT_H
+# define MONGO_HAVE_STDINT 1
+#else
+# define MONGO_USE_LONG_LONG_INT 1
+#endif
+#include <mongo.h>
+
+#if (MONGO_MAJOR == 0) && (MONGO_MINOR < 8)
+# define bson_alloc()    bson_create()
+# define bson_dealloc(b) bson_dispose(b)
+#endif
+
+struct wm_node_s
+{
+  char name[DATA_MAX_NAME_LEN];
+
+  char *host;
+  int port;
+  int timeout;
+
+  /* Authentication information */
+  char *db;
+  char *user;
+  char *passwd;
+
+  _Bool store_rates;
+
+  mongo conn[1];
+  pthread_mutex_t lock;
+};
+typedef struct wm_node_s wm_node_t;
+
+/*
+ * Functions
+ */
+static bson *wm_create_bson (const data_set_t *ds, /* {{{ */
+    const value_list_t *vl,
+    _Bool store_rates)
+{
+  bson *ret;
+  gauge_t *rates;
+  int i;
+
+  ret = bson_alloc (); /* matched by bson_dealloc() */
+  if (ret == NULL)
+  {
+    ERROR ("write_mongodb plugin: bson_create failed.");
+    return (NULL);
+  }
+
+  if (store_rates)
+  {
+    rates = uc_get_rate (ds, vl);
+    if (rates == NULL)
+    {
+      ERROR ("write_mongodb plugin: uc_get_rate() failed.");
+      return (NULL);
+    }
+  }
+  else
+  {
+    rates = NULL;
+  }
+
+  bson_init (ret); /* matched by bson_destroy() */
+  bson_append_date (ret, "time", (bson_date_t) CDTIME_T_TO_MS (vl->time));
+  bson_append_string (ret, "host", vl->host);
+  bson_append_string (ret, "plugin", vl->plugin);
+  bson_append_string (ret, "plugin_instance", vl->plugin_instance);
+  bson_append_string (ret, "type", vl->type);
+  bson_append_string (ret, "type_instance", vl->type_instance);
+
+  bson_append_start_array (ret, "values"); /* {{{ */
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    char key[16];
+
+    ssnprintf (key, sizeof (key), "%i", i);
+
+    if (ds->ds[i].type == DS_TYPE_GAUGE)
+      bson_append_double(ret, key, vl->values[i].gauge);
+    else if (store_rates)
+      bson_append_double(ret, key, (double) rates[i]);
+    else if (ds->ds[i].type == DS_TYPE_COUNTER)
+      bson_append_long(ret, key, vl->values[i].counter);
+    else if (ds->ds[i].type == DS_TYPE_DERIVE)
+      bson_append_long(ret, key, vl->values[i].derive);
+    else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+      bson_append_long(ret, key, vl->values[i].absolute);
+    else
+      assert (23 == 42);
+  }
+  bson_append_finish_array (ret); /* }}} values */
+
+  bson_append_start_array (ret, "dstypes"); /* {{{ */
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    char key[16];
+
+    ssnprintf (key, sizeof (key), "%i", i);
+
+    if (store_rates)
+      bson_append_string (ret, key, "gauge");
+    else
+      bson_append_string (ret, key, DS_TYPE_TO_STRING (ds->ds[i].type));
+  }
+  bson_append_finish_array (ret); /* }}} dstypes */
+
+  bson_append_start_array (ret, "dsnames"); /* {{{ */
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    char key[16];
+
+    ssnprintf (key, sizeof (key), "%i", i);
+    bson_append_string (ret, key, ds->ds[i].name);
+  }
+  bson_append_finish_array (ret); /* }}} dsnames */
+
+  bson_finish (ret);
+
+  sfree (rates);
+  return (ret);
+} /* }}} bson *wm_create_bson */
+
+static int wm_write (const data_set_t *ds, /* {{{ */
+    const value_list_t *vl,
+    user_data_t *ud)
+{
+  wm_node_t *node = ud->data;
+  char collection_name[512];
+  bson *bson_record;
+  int status;
+
+  ssnprintf (collection_name, sizeof (collection_name), "collectd.%s",
+      vl->plugin);
+
+  bson_record = wm_create_bson (ds, vl, node->store_rates);
+  if (bson_record == NULL)
+    return (ENOMEM);
+
+  pthread_mutex_lock (&node->lock);
+
+  if (!mongo_is_connected (node->conn))
+  {
+    INFO ("write_mongodb plugin: Connecting to [%s]:%i",
+        (node->host != NULL) ? node->host : "localhost",
+        (node->port != 0) ? node->port : MONGO_DEFAULT_PORT);
+    status = mongo_connect (node->conn, node->host, node->port);
+    if (status != MONGO_OK) {
+      ERROR ("write_mongodb plugin: Connecting to [%s]:%i failed.",
+          (node->host != NULL) ? node->host : "localhost",
+          (node->port != 0) ? node->port : MONGO_DEFAULT_PORT);
+      mongo_destroy (node->conn);
+      pthread_mutex_unlock (&node->lock);
+      return (-1);
+    }
+
+    if ((node->db != NULL) && (node->user != NULL) && (node->passwd != NULL))
+    {
+      status = mongo_cmd_authenticate (node->conn,
+          node->db, node->user, node->passwd);
+      if (status != MONGO_OK)
+      {
+        ERROR ("write_mongodb plugin: Authenticating to [%s]%i for database "
+            "\"%s\" as user \"%s\" failed.",
+          (node->host != NULL) ? node->host : "localhost",
+          (node->port != 0) ? node->port : MONGO_DEFAULT_PORT,
+          node->db, node->user);
+        mongo_destroy (node->conn);
+        pthread_mutex_unlock (&node->lock);
+        return (-1);
+      }
+    }
+
+    if (node->timeout > 0) {
+      status = mongo_set_op_timeout (node->conn, node->timeout);
+      if (status != MONGO_OK) {
+        WARNING ("write_mongodb plugin: mongo_set_op_timeout(%i) failed: %s",
+            node->timeout, node->conn->errstr);
+      }
+    }
+  }
+
+  /* Assert if the connection has been established */
+  assert (mongo_is_connected (node->conn));
+
+  #if MONGO_MINOR >= 6
+    /* There was an API change in 0.6.0 as linked below */
+    /* https://github.com/mongodb/mongo-c-driver/blob/master/HISTORY.md */
+    status = mongo_insert (node->conn, collection_name, bson_record, NULL);
+  #else
+    status = mongo_insert (node->conn, collection_name, bson_record);
+  #endif
+
+  if (status != MONGO_OK)
+  {
+    ERROR ( "write_mongodb plugin: error inserting record: %d", node->conn->err);
+    if (node->conn->err != MONGO_BSON_INVALID)
+      ERROR ("write_mongodb plugin: %s", node->conn->errstr);
+    else
+      ERROR ("write_mongodb plugin: Invalid BSON structure, error = %#x",
+          (unsigned int) bson_record->err);
+
+    /* Disconnect except on data errors. */
+    if ((node->conn->err != MONGO_BSON_INVALID)
+        && (node->conn->err != MONGO_BSON_NOT_FINISHED))
+      mongo_destroy (node->conn);
+  }
+
+  pthread_mutex_unlock (&node->lock);
+
+  /* free our resource as not to leak memory */
+  bson_destroy (bson_record); /* matches bson_init() */
+  bson_dealloc (bson_record); /* matches bson_alloc() */
+
+  return (0);
+} /* }}} int wm_write */
+
+static void wm_config_free (void *ptr) /* {{{ */
+{
+  wm_node_t *node = ptr;
+
+  if (node == NULL)
+    return;
+
+  if (mongo_is_connected (node->conn))
+    mongo_destroy (node->conn);
+
+  sfree (node->host);
+  sfree (node);
+} /* }}} void wm_config_free */
+
+static int wm_config_node (oconfig_item_t *ci) /* {{{ */
+{
+  wm_node_t *node;
+  int status;
+  int i;
+
+  node = malloc (sizeof (*node));
+  if (node == NULL)
+    return (ENOMEM);
+  memset (node, 0, sizeof (*node));
+  mongo_init (node->conn);
+  node->host = NULL;
+  node->store_rates = 1;
+  pthread_mutex_init (&node->lock, /* attr = */ NULL);
+
+  status = cf_util_get_string_buffer (ci, node->name, sizeof (node->name));
+
+  if (status != 0)
+  {
+    sfree (node);
+    return (status);
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &node->host);
+    else if (strcasecmp ("Port", child->key) == 0)
+    {
+      status = cf_util_get_port_number (child);
+      if (status > 0)
+      {
+        node->port = status;
+        status = 0;
+      }
+    }
+    else if (strcasecmp ("Timeout", child->key) == 0)
+      status = cf_util_get_int (child, &node->timeout);
+    else if (strcasecmp ("StoreRates", child->key) == 0)
+      status = cf_util_get_boolean (child, &node->store_rates);
+    else if (strcasecmp ("Database", child->key) == 0)
+      status = cf_util_get_string (child, &node->db);
+    else if (strcasecmp ("User", child->key) == 0)
+      status = cf_util_get_string (child, &node->user);
+    else if (strcasecmp ("Password", child->key) == 0)
+      status = cf_util_get_string (child, &node->passwd);
+    else
+      WARNING ("write_mongodb plugin: Ignoring unknown config option \"%s\".",
+          child->key);
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  if ((node->db != NULL) || (node->user != NULL) || (node->passwd != NULL))
+  {
+    if ((node->db == NULL) || (node->user == NULL) || (node->passwd == NULL))
+    {
+      WARNING ("write_mongodb plugin: Authentication requires the "
+          "\"Database\", \"User\" and \"Password\" options to be specified, "
+          "but at last one of them is missing. Authentication will NOT be "
+          "used.");
+      sfree (node->db);
+      sfree (node->user);
+      sfree (node->passwd);
+    }
+  }
+
+  if (status == 0)
+  {
+    char cb_name[DATA_MAX_NAME_LEN];
+    user_data_t ud;
+
+    ssnprintf (cb_name, sizeof (cb_name), "write_mongodb/%s", node->name);
+
+    ud.data = node;
+    ud.free_func = wm_config_free;
+
+    status = plugin_register_write (cb_name, wm_write, &ud);
+    INFO ("write_mongodb plugin: registered write plugin %s %d",cb_name,status);
+  }
+
+  if (status != 0)
+    wm_config_free (node);
+
+  return (status);
+} /* }}} int wm_config_node */
+
+static int wm_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Node", child->key) == 0)
+      wm_config_node (child);
+    else
+      WARNING ("write_mongodb plugin: Ignoring unknown "
+          "configuration option \"%s\" at top level.", child->key);
+  }
+
+  return (0);
+} /* }}} int wm_config */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("write_mongodb", wm_config);
+}
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
diff --git a/src/write_redis.c b/src/write_redis.c
new file mode 100644 (file)
index 0000000..22e30ab
--- /dev/null
@@ -0,0 +1,257 @@
+/**
+ * collectd - src/write_redis.c
+ * Copyright (C) 2010       Florian Forster
+ *
+ * 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:
+ *   Florian Forster <ff at octo.it>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+
+#include <pthread.h>
+#include <sys/time.h>
+#include <hiredis/hiredis.h>
+
+struct wr_node_s
+{
+  char name[DATA_MAX_NAME_LEN];
+
+  char *host;
+  int port;
+  struct timeval timeout;
+
+  redisContext *conn;
+  pthread_mutex_t lock;
+};
+typedef struct wr_node_s wr_node_t;
+
+/*
+ * Functions
+ */
+static int wr_write (const data_set_t *ds, /* {{{ */
+    const value_list_t *vl,
+    user_data_t *ud)
+{
+  wr_node_t *node = ud->data;
+  char ident[512];
+  char key[512];
+  char value[512];
+  char time[24];
+  size_t value_size;
+  char *value_ptr;
+  int status;
+  redisReply   *rr;
+  int i;
+
+  status = FORMAT_VL (ident, sizeof (ident), vl);
+  if (status != 0)
+    return (status);
+  ssnprintf (key, sizeof (key), "collectd/%s", ident);
+  ssnprintf (time, sizeof (time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
+
+  memset (value, 0, sizeof (value));
+  value_size = sizeof (value);
+  value_ptr = &value[0];
+
+#define APPEND(...) do {                                             \
+  status = snprintf (value_ptr, value_size, __VA_ARGS__);            \
+  if (((size_t) status) > value_size)                                \
+  {                                                                  \
+    value_ptr += value_size;                                         \
+    value_size = 0;                                                  \
+  }                                                                  \
+  else                                                               \
+  {                                                                  \
+    value_ptr += status;                                             \
+    value_size -= status;                                            \
+  }                                                                  \
+} while (0)
+
+  APPEND ("%s:", time);
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if (ds->ds[i].type == DS_TYPE_COUNTER)
+      APPEND ("%llu", vl->values[i].counter);
+    else if (ds->ds[i].type == DS_TYPE_GAUGE)
+      APPEND (GAUGE_FORMAT, vl->values[i].gauge);
+    else if (ds->ds[i].type == DS_TYPE_DERIVE)
+      APPEND ("%"PRIi64, vl->values[i].derive);
+    else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+      APPEND ("%"PRIu64, vl->values[i].absolute);
+    else
+      assert (23 == 42);
+  }
+
+#undef APPEND
+
+  pthread_mutex_lock (&node->lock);
+
+  if (node->conn == NULL)
+  {
+    node->conn = redisConnectWithTimeout ((char *)node->host, node->port, node->timeout);
+    if (node->conn == NULL)
+    {
+      ERROR ("write_redis plugin: Connecting to host \"%s\" (port %i) failed: Unkown reason",
+          (node->host != NULL) ? node->host : "localhost",
+          (node->port != 0) ? node->port : 6379);
+      pthread_mutex_unlock (&node->lock);
+      return (-1);
+    }
+    else if (node->conn->err)
+    {
+      ERROR ("write_redis plugin: Connecting to host \"%s\" (port %i) failed: %s",
+          (node->host != NULL) ? node->host : "localhost",
+          (node->port != 0) ? node->port : 6379,
+          node->conn->errstr);
+      pthread_mutex_unlock (&node->lock);
+      return (-1);
+    }
+  }
+
+  rr = redisCommand (node->conn, "ZADD %s %s %s", key, time, value);
+  if (rr==NULL)
+    WARNING("ZADD command error. key:%s message:%s", key, node->conn->errstr);
+
+  rr = redisCommand (node->conn, "SADD collectd/values %s", ident);
+  if (rr==NULL)
+    WARNING("SADD command error. ident:%s message:%s", ident, node->conn->errstr);
+
+  pthread_mutex_unlock (&node->lock);
+
+  return (0);
+} /* }}} int wr_write */
+
+static void wr_config_free (void *ptr) /* {{{ */
+{
+  wr_node_t *node = ptr;
+
+  if (node == NULL)
+    return;
+
+  if (node->conn != NULL)
+  {
+    redisFree (node->conn);
+    node->conn = NULL;
+  }
+
+  sfree (node->host);
+  sfree (node);
+} /* }}} void wr_config_free */
+
+static int wr_config_node (oconfig_item_t *ci) /* {{{ */
+{
+  wr_node_t *node;
+  int timeout;
+  int status;
+  int i;
+
+  node = malloc (sizeof (*node));
+  if (node == NULL)
+    return (ENOMEM);
+  memset (node, 0, sizeof (*node));
+  node->host = NULL;
+  node->port = 0;
+  node->timeout.tv_sec = 0;
+  node->timeout.tv_usec = 1000;
+  node->conn = NULL;
+  pthread_mutex_init (&node->lock, /* attr = */ NULL);
+
+  status = cf_util_get_string_buffer (ci, node->name, sizeof (node->name));
+  if (status != 0)
+  {
+    sfree (node);
+    return (status);
+  }
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Host", child->key) == 0)
+      status = cf_util_get_string (child, &node->host);
+    else if (strcasecmp ("Port", child->key) == 0)
+    {
+      status = cf_util_get_port_number (child);
+      if (status > 0)
+      {
+        node->port = status;
+        status = 0;
+      }
+    }
+    else if (strcasecmp ("Timeout", child->key) == 0) {
+      status = cf_util_get_int (child, &timeout);
+      if (status == 0) node->timeout.tv_usec = timeout;
+    }
+    else
+      WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
+          child->key);
+
+    if (status != 0)
+      break;
+  } /* for (i = 0; i < ci->children_num; i++) */
+
+  if (status == 0)
+  {
+    char cb_name[DATA_MAX_NAME_LEN];
+    user_data_t ud;
+
+    ssnprintf (cb_name, sizeof (cb_name), "write_redis/%s", node->name);
+
+    ud.data = node;
+    ud.free_func = wr_config_free;
+
+    status = plugin_register_write (cb_name, wr_write, &ud);
+  }
+
+  if (status != 0)
+    wr_config_free (node);
+
+  return (status);
+} /* }}} int wr_config_node */
+
+static int wr_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Node", child->key) == 0)
+      wr_config_node (child);
+    else
+      WARNING ("write_redis plugin: Ignoring unknown "
+          "configuration option \"%s\" at top level.", child->key);
+  }
+
+  return (0);
+} /* }}} int wr_config */
+
+void module_register (void)
+{
+  plugin_register_complex_config ("write_redis", wr_config);
+}
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
diff --git a/src/write_riemann.c b/src/write_riemann.c
new file mode 100644 (file)
index 0000000..a09c723
--- /dev/null
@@ -0,0 +1,1084 @@
+/**
+ * collectd - src/write_riemann.c
+ * Copyright (C) 2012,2013  Pierre-Yves Ritschard
+ * Copyright (C) 2013       Florian octo Forster
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ *   Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "utils_cache.h"
+#include "riemann.pb-c.h"
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netdb.h>
+#include <inttypes.h>
+#include <pthread.h>
+
+#define RIEMANN_HOST           "localhost"
+#define RIEMANN_PORT           "5555"
+#define RIEMANN_TTL_FACTOR      2.0
+#define RIEMANN_BATCH_MAX      8192
+
+int write_riemann_threshold_check(const data_set_t *, const value_list_t *, int *);
+
+struct riemann_host {
+       char                    *name;
+       char                    *event_service_prefix;
+#define F_CONNECT       0x01
+       uint8_t                  flags;
+       pthread_mutex_t  lock;
+    _Bool            batch_mode;
+       _Bool            notifications;
+       _Bool            check_thresholds;
+       _Bool                    store_rates;
+       _Bool                    always_append_ds;
+       char                    *node;
+       char                    *service;
+       _Bool                    use_tcp;
+       int                          s;
+       double                   ttl_factor;
+    Msg             *batch_msg;
+    cdtime_t         batch_init;
+    int              batch_max;
+       int                          reference_count;
+};
+
+static char    **riemann_tags;
+static size_t    riemann_tags_num;
+static char    **riemann_attrs;
+static size_t     riemann_attrs_num;
+
+static void riemann_event_protobuf_free (Event *event) /* {{{ */
+{
+       size_t i;
+
+       if (event == NULL)
+               return;
+
+       sfree (event->state);
+       sfree (event->service);
+       sfree (event->host);
+       sfree (event->description);
+
+       strarray_free (event->tags, event->n_tags);
+       event->tags = NULL;
+       event->n_tags = 0;
+
+       for (i = 0; i < event->n_attributes; i++)
+       {
+               sfree (event->attributes[i]->key);
+               sfree (event->attributes[i]->value);
+               sfree (event->attributes[i]);
+       }
+       sfree (event->attributes);
+       event->n_attributes = 0;
+
+       sfree (event);
+} /* }}} void riemann_event_protobuf_free */
+
+static void riemann_msg_protobuf_free(Msg *msg) /* {{{ */
+{
+       size_t i;
+
+       if (msg == NULL)
+               return;
+
+       for (i = 0; i < msg->n_events; i++)
+       {
+               riemann_event_protobuf_free (msg->events[i]);
+               msg->events[i] = NULL;
+       }
+
+       sfree (msg->events);
+       msg->n_events = 0;
+
+       sfree (msg);
+} /* }}} void riemann_msg_protobuf_free */
+
+/* host->lock must be held when calling this function. */
+static int riemann_connect(struct riemann_host *host) /* {{{ */
+{
+       int                      e;
+       struct addrinfo         *ai, *res, hints;
+       char const              *node;
+       char const              *service;
+
+       if (host->flags & F_CONNECT)
+               return 0;
+
+       memset(&hints, 0, sizeof(hints));
+       memset(&service, 0, sizeof(service));
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = host->use_tcp ? SOCK_STREAM : SOCK_DGRAM;
+#ifdef AI_ADDRCONFIG
+       hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+
+       node = (host->node != NULL) ? host->node : RIEMANN_HOST;
+       service = (host->service != NULL) ? host->service : RIEMANN_PORT;
+
+       if ((e = getaddrinfo(node, service, &hints, &res)) != 0) {
+               ERROR ("write_riemann plugin: Unable to resolve host \"%s\": %s",
+                       node, gai_strerror(e));
+               return -1;
+       }
+
+       host->s = -1;
+       for (ai = res; ai != NULL; ai = ai->ai_next) {
+               if ((host->s = socket(ai->ai_family,
+                                     ai->ai_socktype,
+                                     ai->ai_protocol)) == -1) {
+                       continue;
+               }
+
+               if (connect(host->s, ai->ai_addr, ai->ai_addrlen) != 0) {
+                       close(host->s);
+                       host->s = -1;
+                       continue;
+               }
+
+               host->flags |= F_CONNECT;
+               DEBUG("write_riemann plugin: got a successful connection for: %s:%s",
+                               node, service);
+               break;
+       }
+
+       freeaddrinfo(res);
+
+       if (host->s < 0) {
+               WARNING("write_riemann plugin: Unable to connect to Riemann at %s:%s",
+                               node, service);
+               return -1;
+       }
+       return 0;
+} /* }}} int riemann_connect */
+
+/* host->lock must be held when calling this function. */
+static int riemann_disconnect (struct riemann_host *host) /* {{{ */
+{
+       if ((host->flags & F_CONNECT) == 0)
+               return (0);
+
+       close (host->s);
+       host->s = -1;
+       host->flags &= ~F_CONNECT;
+
+       return (0);
+} /* }}} int riemann_disconnect */
+
+static int riemann_send_msg (struct riemann_host *host, const Msg *msg) /* {{{ */
+{
+       int status = 0;
+       u_char *buffer = NULL;
+       size_t  buffer_len;
+
+       status = riemann_connect (host);
+       if (status != 0)
+               return status;
+
+       buffer_len = msg__get_packed_size(msg);
+
+       if (host->use_tcp)
+               buffer_len += 4;
+
+       buffer = malloc (buffer_len);
+       if (buffer == NULL) {
+               ERROR ("write_riemann plugin: malloc failed.");
+               return ENOMEM;
+       }
+       memset (buffer, 0, buffer_len);
+
+       if (host->use_tcp)
+       {
+               uint32_t length = htonl ((uint32_t) (buffer_len - 4));
+               memcpy (buffer, &length, 4);
+               msg__pack(msg, buffer + 4);
+       }
+       else
+       {
+               msg__pack(msg, buffer);
+       }
+
+       status = (int) swrite (host->s, buffer, buffer_len);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("write_riemann plugin: Sending to Riemann at %s:%s failed: %s",
+                               (host->node != NULL) ? host->node : RIEMANN_HOST,
+                               (host->service != NULL) ? host->service : RIEMANN_PORT,
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               sfree (buffer);
+               return -1;
+       }
+
+       sfree (buffer);
+       return 0;
+} /* }}} int riemann_send_msg */
+
+static int riemann_recv_ack(struct riemann_host *host) /* {{{ */
+{
+       int status = 0;
+       Msg *msg = NULL;
+       uint32_t header;
+
+       status = (int) sread (host->s, &header, 4);
+
+       if (status != 0)
+               return -1;
+
+       size_t size = ntohl(header);
+
+       // Buffer on the stack since acknowledges are typically small.
+       u_char buffer[size];
+       memset (buffer, 0, size);
+
+       status = (int) sread (host->s, buffer, size);
+
+       if (status != 0)
+               return status;
+
+       msg = msg__unpack (NULL, size, buffer);
+
+       if (msg == NULL)
+               return -1;
+
+       if (!msg->ok)
+       {
+               ERROR ("write_riemann plugin: Sending to Riemann at %s:%s acknowledgement message reported error: %s",
+                               (host->node != NULL) ? host->node : RIEMANN_HOST,
+                               (host->service != NULL) ? host->service : RIEMANN_PORT,
+                               msg->error);
+
+               msg__free_unpacked(msg, NULL);
+               return -1;
+       }
+
+       msg__free_unpacked (msg, NULL);
+       return 0;
+} /* }}} int riemann_recv_ack */
+
+/**
+ * Function to send messages (Msg) to riemann.
+ *
+ * Acquires the host lock, disconnects on errors.
+ */
+static int riemann_send(struct riemann_host *host, Msg const *msg) /* {{{ */
+{
+       int status = 0;
+       pthread_mutex_lock (&host->lock);
+
+       status = riemann_send_msg(host, msg);
+       if (status != 0) {
+               riemann_disconnect (host);
+               pthread_mutex_unlock (&host->lock);
+               return status;
+       }
+
+       /*
+        * For TCP we need to receive message acknowledgemenent.
+        */
+       if (host->use_tcp)
+       {
+               status = riemann_recv_ack(host);
+
+               if (status != 0)
+               {
+                       riemann_disconnect (host);
+                       pthread_mutex_unlock (&host->lock);
+                       return status;
+               }
+       }
+
+       pthread_mutex_unlock (&host->lock);
+       return 0;
+} /* }}} int riemann_send */
+
+static int riemann_event_add_tag (Event *event, char const *tag) /* {{{ */
+{
+       return (strarray_add (&event->tags, &event->n_tags, tag));
+} /* }}} int riemann_event_add_tag */
+
+static int riemann_event_add_attribute(Event *event, /* {{{ */
+               char const *key, char const *value)
+{
+       Attribute **new_attributes;
+       Attribute *a;
+
+       new_attributes = realloc (event->attributes,
+                       sizeof (*event->attributes) * (event->n_attributes + 1));
+       if (new_attributes == NULL)
+       {
+               ERROR ("write_riemann plugin: realloc failed.");
+               return (ENOMEM);
+       }
+       event->attributes = new_attributes;
+
+       a = malloc (sizeof (*a));
+       if (a == NULL)
+       {
+               ERROR ("write_riemann plugin: malloc failed.");
+               return (ENOMEM);
+       }
+       attribute__init (a);
+
+       a->key = strdup (key);
+       if (value != NULL)
+               a->value = strdup (value);
+
+       event->attributes[event->n_attributes] = a;
+       event->n_attributes++;
+
+       return (0);
+} /* }}} int riemann_event_add_attribute */
+
+static Msg *riemann_notification_to_protobuf(struct riemann_host *host, /* {{{ */
+               notification_t const *n)
+{
+       Msg *msg;
+       Event *event;
+       char service_buffer[6 * DATA_MAX_NAME_LEN];
+       char const *severity;
+       notification_meta_t *meta;
+       int i;
+
+       msg = malloc (sizeof (*msg));
+       if (msg == NULL)
+       {
+               ERROR ("write_riemann plugin: malloc failed.");
+               return (NULL);
+       }
+       memset (msg, 0, sizeof (*msg));
+       msg__init (msg);
+
+       msg->events = malloc (sizeof (*msg->events));
+       if (msg->events == NULL)
+       {
+               ERROR ("write_riemann plugin: malloc failed.");
+               sfree (msg);
+               return (NULL);
+       }
+
+       event = malloc (sizeof (*event));
+       if (event == NULL)
+       {
+               ERROR ("write_riemann plugin: malloc failed.");
+               sfree (msg->events);
+               sfree (msg);
+               return (NULL);
+       }
+       memset (event, 0, sizeof (*event));
+       event__init (event);
+
+       msg->events[0] = event;
+       msg->n_events = 1;
+
+       event->host = strdup (n->host);
+       event->time = CDTIME_T_TO_TIME_T (n->time);
+       event->has_time = 1;
+
+       switch (n->severity)
+       {
+               case NOTIF_OKAY:        severity = "ok"; break;
+               case NOTIF_WARNING:     severity = "warning"; break;
+               case NOTIF_FAILURE:     severity = "critical"; break;
+               default:                severity = "unknown";
+       }
+       event->state = strdup (severity);
+
+       riemann_event_add_tag (event, "notification");
+       if (n->host[0] != 0)
+               riemann_event_add_attribute (event, "host", n->host);
+       if (n->plugin[0] != 0)
+               riemann_event_add_attribute (event, "plugin", n->plugin);
+       if (n->plugin_instance[0] != 0)
+               riemann_event_add_attribute (event, "plugin_instance",
+                               n->plugin_instance);
+
+       if (n->type[0] != 0)
+               riemann_event_add_attribute (event, "type", n->type);
+       if (n->type_instance[0] != 0)
+               riemann_event_add_attribute (event, "type_instance",
+                               n->type_instance);
+
+       for (i = 0; i < riemann_attrs_num; i += 2)
+               riemann_event_add_attribute(event,
+                                           riemann_attrs[i],
+                                           riemann_attrs[i +1]);
+
+       for (i = 0; i < riemann_tags_num; i++)
+               riemann_event_add_tag (event, riemann_tags[i]);
+
+       format_name (service_buffer, sizeof (service_buffer),
+                       /* host = */ "", n->plugin, n->plugin_instance,
+                       n->type, n->type_instance);
+       event->service = strdup (&service_buffer[1]);
+
+       if (n->message[0] != 0)
+               riemann_event_add_attribute (event, "description", n->message);
+
+       /* Pull in values from threshold and add extra attributes */
+       for (meta = n->meta; meta != NULL; meta = meta->next)
+       {
+               if (strcasecmp ("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE)
+               {
+                       event->metric_d = meta->nm_value.nm_double;
+                       event->has_metric_d = 1;
+                       continue;
+               }
+
+               if (meta->type == NM_TYPE_STRING) {
+                       riemann_event_add_attribute (event, meta->name, meta->nm_value.nm_string);
+                       continue;
+               }
+       }
+
+       DEBUG ("write_riemann plugin: Successfully created protobuf for notification: "
+                       "host = \"%s\", service = \"%s\", state = \"%s\"",
+                       event->host, event->service, event->state);
+       return (msg);
+} /* }}} Msg *riemann_notification_to_protobuf */
+
+static Event *riemann_value_to_protobuf(struct riemann_host const *host, /* {{{ */
+               data_set_t const *ds,
+               value_list_t const *vl, size_t index,
+                                        gauge_t const *rates,
+                                        int status)
+{
+       Event *event;
+       char name_buffer[5 * DATA_MAX_NAME_LEN];
+       char service_buffer[6 * DATA_MAX_NAME_LEN];
+       double ttl;
+       int i;
+
+       event = malloc (sizeof (*event));
+       if (event == NULL)
+       {
+               ERROR ("write_riemann plugin: malloc failed.");
+               return (NULL);
+       }
+       memset (event, 0, sizeof (*event));
+       event__init (event);
+
+       event->host = strdup (vl->host);
+       event->time = CDTIME_T_TO_TIME_T (vl->time);
+       event->has_time = 1;
+
+       if (host->check_thresholds) {
+               switch (status) {
+                       case STATE_OKAY:
+                               event->state = strdup("ok");
+                               break;
+                       case STATE_ERROR:
+                               event->state = strdup("critical");
+                               break;
+                       case STATE_WARNING:
+                               event->state = strdup("warning");
+                               break;
+                       case STATE_MISSING:
+                               event->state = strdup("unknown");
+                               break;
+               }
+       }
+
+       ttl = CDTIME_T_TO_DOUBLE (vl->interval) * host->ttl_factor;
+       event->ttl = (float) ttl;
+       event->has_ttl = 1;
+
+       riemann_event_add_attribute (event, "plugin", vl->plugin);
+       if (vl->plugin_instance[0] != 0)
+               riemann_event_add_attribute (event, "plugin_instance",
+                               vl->plugin_instance);
+
+       riemann_event_add_attribute (event, "type", vl->type);
+       if (vl->type_instance[0] != 0)
+               riemann_event_add_attribute (event, "type_instance",
+                               vl->type_instance);
+
+       if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL))
+       {
+               char ds_type[DATA_MAX_NAME_LEN];
+
+               ssnprintf (ds_type, sizeof (ds_type), "%s:rate",
+                               DS_TYPE_TO_STRING(ds->ds[index].type));
+               riemann_event_add_attribute (event, "ds_type", ds_type);
+       }
+       else
+       {
+               riemann_event_add_attribute (event, "ds_type",
+                               DS_TYPE_TO_STRING(ds->ds[index].type));
+       }
+       riemann_event_add_attribute (event, "ds_name", ds->ds[index].name);
+       {
+               char ds_index[DATA_MAX_NAME_LEN];
+
+               ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
+               riemann_event_add_attribute (event, "ds_index", ds_index);
+       }
+
+       for (i = 0; i < riemann_attrs_num; i += 2)
+               riemann_event_add_attribute(event,
+                                           riemann_attrs[i],
+                                           riemann_attrs[i +1]);
+
+       for (i = 0; i < riemann_tags_num; i++)
+               riemann_event_add_tag (event, riemann_tags[i]);
+
+       if (ds->ds[index].type == DS_TYPE_GAUGE)
+       {
+               event->has_metric_d = 1;
+               event->metric_d = (double) vl->values[index].gauge;
+       }
+       else if (rates != NULL)
+       {
+               event->has_metric_d = 1;
+               event->metric_d = (double) rates[index];
+       }
+       else
+       {
+               event->has_metric_sint64 = 1;
+               if (ds->ds[index].type == DS_TYPE_DERIVE)
+                       event->metric_sint64 = (int64_t) vl->values[index].derive;
+               else if (ds->ds[index].type == DS_TYPE_ABSOLUTE)
+                       event->metric_sint64 = (int64_t) vl->values[index].absolute;
+               else
+                       event->metric_sint64 = (int64_t) vl->values[index].counter;
+       }
+
+       format_name (name_buffer, sizeof (name_buffer),
+                       /* host = */ "", vl->plugin, vl->plugin_instance,
+                       vl->type, vl->type_instance);
+       if (host->always_append_ds || (ds->ds_num > 1))
+       {
+               if (host->event_service_prefix == NULL)
+                       ssnprintf (service_buffer, sizeof (service_buffer), "%s/%s",
+                                       &name_buffer[1], ds->ds[index].name);
+               else
+                       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
+                       ssnprintf (service_buffer, sizeof (service_buffer), "%s%s",
+                                       host->event_service_prefix, &name_buffer[1]);
+       }
+
+       event->service = strdup (service_buffer);
+
+       DEBUG ("write_riemann plugin: Successfully created protobuf for metric: "
+                       "host = \"%s\", service = \"%s\"",
+                       event->host, event->service);
+       return (event);
+} /* }}} Event *riemann_value_to_protobuf */
+
+static Msg *riemann_value_list_to_protobuf (struct riemann_host const *host, /* {{{ */
+                                           data_set_t const *ds,
+                                           value_list_t const *vl,
+                                           int *statuses)
+{
+       Msg *msg;
+       size_t i;
+       gauge_t *rates = NULL;
+
+       /* Initialize the Msg structure. */
+       msg = malloc (sizeof (*msg));
+       if (msg == NULL)
+       {
+               ERROR ("write_riemann plugin: malloc failed.");
+               return (NULL);
+       }
+       memset (msg, 0, sizeof (*msg));
+       msg__init (msg);
+
+       /* Set up events. First, the list of pointers. */
+       msg->n_events = (size_t) vl->values_len;
+       msg->events = calloc (msg->n_events, sizeof (*msg->events));
+       if (msg->events == NULL)
+       {
+               ERROR ("write_riemann plugin: calloc failed.");
+               riemann_msg_protobuf_free (msg);
+               return (NULL);
+       }
+
+       if (host->store_rates)
+       {
+               rates = uc_get_rate (ds, vl);
+               if (rates == NULL)
+               {
+                       ERROR ("write_riemann plugin: uc_get_rate failed.");
+                       riemann_msg_protobuf_free (msg);
+                       return (NULL);
+               }
+       }
+
+       for (i = 0; i < msg->n_events; i++)
+       {
+               msg->events[i] = riemann_value_to_protobuf (host, ds, vl,
+                                                           (int) i, rates, statuses[i]);
+               if (msg->events[i] == NULL)
+               {
+                       riemann_msg_protobuf_free (msg);
+                       sfree (rates);
+                       return (NULL);
+               }
+       }
+
+       sfree (rates);
+       return (msg);
+} /* }}} Msg *riemann_value_list_to_protobuf */
+
+
+/*
+ * Always call while holding host->lock !
+ */
+static int riemann_batch_flush_nolock (cdtime_t timeout,
+                                       struct riemann_host *host)
+{
+    cdtime_t    now;
+    int         status = 0;
+
+    if (timeout > 0) {
+        now = cdtime ();
+        if ((host->batch_init + timeout) > now)
+            return status;
+    }
+    riemann_send_msg(host, host->batch_msg);
+    riemann_msg_protobuf_free(host->batch_msg);
+
+       if (host->use_tcp && ((status = riemann_recv_ack(host)) != 0))
+        riemann_disconnect (host);
+
+    host->batch_init = cdtime();
+    host->batch_msg = NULL;
+    return status;
+}
+
+static int riemann_batch_flush (cdtime_t timeout,
+        const char *identifier __attribute__((unused)),
+        user_data_t *user_data)
+{
+    struct riemann_host *host;
+    int status;
+
+    if (user_data == NULL)
+        return (-EINVAL);
+
+    host = user_data->data;
+    pthread_mutex_lock (&host->lock);
+    status = riemann_batch_flush_nolock (timeout, host);
+    if (status != 0)
+        ERROR ("write_riemann plugin: riemann_send failed with status %i",
+               status);
+
+    pthread_mutex_unlock(&host->lock);
+    return status;
+}
+
+static int riemann_batch_add_value_list (struct riemann_host *host, /* {{{ */
+                                         data_set_t const *ds,
+                                         value_list_t const *vl,
+                                         int *statuses)
+{
+       size_t i;
+    Event **events;
+    Msg *msg;
+    size_t len;
+    int ret;
+
+    msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+    if (msg == NULL)
+        return -1;
+
+    pthread_mutex_lock(&host->lock);
+
+    if (host->batch_msg == NULL) {
+        host->batch_msg = msg;
+    } else {
+        len = msg->n_events + host->batch_msg->n_events;
+        events = realloc(host->batch_msg->events,
+                         (len * sizeof(*host->batch_msg->events)));
+        if (events == NULL) {
+            pthread_mutex_unlock(&host->lock);
+            ERROR ("write_riemann plugin: out of memory");
+            riemann_msg_protobuf_free (msg);
+            return -1;
+        }
+        host->batch_msg->events = events;
+
+        for (i = host->batch_msg->n_events; i < len; i++)
+            host->batch_msg->events[i] = msg->events[i - host->batch_msg->n_events];
+
+        host->batch_msg->n_events = len;
+        sfree (msg->events);
+        msg->n_events = 0;
+        sfree (msg);
+    }
+
+       len = msg__get_packed_size(host->batch_msg);
+    ret = 0;
+    if (len >= host->batch_max) {
+        ret = riemann_batch_flush_nolock(0, host);
+    }
+
+    pthread_mutex_unlock(&host->lock);
+    return ret;
+} /* }}} Msg *riemann_batch_add_value_list */
+
+static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{ */
+{
+       int                      status;
+       struct riemann_host     *host = ud->data;
+       Msg                     *msg;
+
+       if (!host->notifications)
+               return 0;
+
+    /*
+     * Never batch for notifications, send them ASAP
+     */
+       msg = riemann_notification_to_protobuf (host, n);
+       if (msg == NULL)
+               return (-1);
+
+       status = riemann_send (host, msg);
+       if (status != 0)
+               ERROR ("write_riemann plugin: riemann_send failed with status %i",
+                               status);
+
+       riemann_msg_protobuf_free (msg);
+       return (status);
+} /* }}} int riemann_notification */
+
+static int riemann_write(const data_set_t *ds, /* {{{ */
+             const value_list_t *vl,
+             user_data_t *ud)
+{
+       int                      status = 0;
+       int                      statuses[vl->values_len];
+       struct riemann_host     *host = ud->data;
+       Msg                     *msg;
+
+       if (host->check_thresholds)
+               write_riemann_threshold_check(ds, vl, statuses);
+
+    if (host->use_tcp == 1 && host->batch_mode) {
+
+        riemann_batch_add_value_list (host, ds, vl, statuses);
+
+
+    } else {
+
+        msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+        if (msg == NULL)
+            return (-1);
+
+        status = riemann_send (host, msg);
+        if (status != 0)
+            ERROR ("write_riemann plugin: riemann_send failed with status %i",
+                   status);
+
+        riemann_msg_protobuf_free (msg);
+    }
+       return status;
+} /* }}} int riemann_write */
+
+static void riemann_free(void *p) /* {{{ */
+{
+       struct riemann_host     *host = p;
+
+       if (host == NULL)
+               return;
+
+       pthread_mutex_lock (&host->lock);
+
+       host->reference_count--;
+       if (host->reference_count > 0)
+       {
+               pthread_mutex_unlock (&host->lock);
+               return;
+       }
+
+       riemann_disconnect (host);
+
+       sfree(host->service);
+       pthread_mutex_destroy (&host->lock);
+       sfree(host);
+} /* }}} void riemann_free */
+
+static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
+{
+       struct riemann_host     *host = NULL;
+       int                      status = 0;
+       int                      i;
+       oconfig_item_t          *child;
+       char                     callback_name[DATA_MAX_NAME_LEN];
+       user_data_t              ud;
+
+       if ((host = calloc(1, sizeof (*host))) == NULL) {
+               ERROR ("write_riemann plugin: calloc failed.");
+               return ENOMEM;
+       }
+       pthread_mutex_init (&host->lock, NULL);
+       host->reference_count = 1;
+       host->node = NULL;
+       host->service = NULL;
+       host->notifications = 1;
+       host->check_thresholds = 0;
+       host->store_rates = 1;
+       host->always_append_ds = 0;
+       host->use_tcp = 1;
+       host->batch_mode = 1;
+       host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */
+       host->batch_init = cdtime();
+       host->ttl_factor = RIEMANN_TTL_FACTOR;
+
+       status = cf_util_get_string (ci, &host->name);
+       if (status != 0) {
+               WARNING("write_riemann plugin: Required host name is missing.");
+               riemann_free (host);
+               return -1;
+       }
+
+       for (i = 0; i < ci->children_num; i++) {
+               /*
+                * The code here could be simplified but makes room
+                * for easy adding of new options later on.
+                */
+               child = &ci->children[i];
+               status = 0;
+
+               if (strcasecmp ("Host", child->key) == 0) {
+                       status = cf_util_get_string (child, &host->node);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp ("Notifications", child->key) == 0) {
+                       status = cf_util_get_boolean(child, &host->notifications);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp ("EventServicePrefix", child->key) == 0) {
+                       status = cf_util_get_string (child, &host->event_service_prefix);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp ("CheckThresholds", child->key) == 0) {
+                       status = cf_util_get_boolean(child, &host->check_thresholds);
+                       if (status != 0)
+                               break;
+        } else if (strcasecmp ("Batch", child->key) == 0) {
+            status = cf_util_get_boolean(child, &host->batch_mode);
+            if (status != 0)
+                break;
+        } else if (strcasecmp("BatchMaxSize", child->key) == 0) {
+            status = cf_util_get_int(child, &host->batch_max);
+            if (status != 0)
+                break;
+               } else if (strcasecmp ("Port", child->key) == 0) {
+                       status = cf_util_get_service (child, &host->service);
+                       if (status != 0) {
+                               ERROR ("write_riemann plugin: Invalid argument "
+                                               "configured for the \"Port\" "
+                                               "option.");
+                               break;
+                       }
+               } else if (strcasecmp ("Protocol", child->key) == 0) {
+                       char tmp[16];
+                       status = cf_util_get_string_buffer (child,
+                                       tmp, sizeof (tmp));
+                       if (status != 0)
+                       {
+                               ERROR ("write_riemann plugin: cf_util_get_"
+                                               "string_buffer failed with "
+                                               "status %i.", status);
+                               break;
+                       }
+
+                       if (strcasecmp ("UDP", tmp) == 0)
+                               host->use_tcp = 0;
+                       else if (strcasecmp ("TCP", tmp) == 0)
+                               host->use_tcp = 1;
+                       else
+                               WARNING ("write_riemann plugin: The value "
+                                               "\"%s\" is not valid for the "
+                                               "\"Protocol\" option. Use "
+                                               "either \"UDP\" or \"TCP\".",
+                                               tmp);
+               } else if (strcasecmp ("StoreRates", child->key) == 0) {
+                       status = cf_util_get_boolean (child, &host->store_rates);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp ("AlwaysAppendDS", child->key) == 0) {
+                       status = cf_util_get_boolean (child,
+                                       &host->always_append_ds);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp ("TTLFactor", child->key) == 0) {
+                       double tmp = NAN;
+                       status = cf_util_get_double (child, &tmp);
+                       if (status != 0)
+                               break;
+                       if (tmp >= 2.0) {
+                               host->ttl_factor = tmp;
+                       } else if (tmp >= 1.0) {
+                               NOTICE ("write_riemann plugin: The configured "
+                                               "TTLFactor is very small "
+                                               "(%.1f). A value of 2.0 or "
+                                               "greater is recommended.",
+                                               tmp);
+                               host->ttl_factor = tmp;
+                       } else if (tmp > 0.0) {
+                               WARNING ("write_riemann plugin: The configured "
+                                               "TTLFactor is too small to be "
+                                               "useful (%.1f). I'll use it "
+                                               "since the user knows best, "
+                                               "but under protest.",
+                                               tmp);
+                               host->ttl_factor = tmp;
+                       } else { /* zero, negative and NAN */
+                               ERROR ("write_riemann plugin: The configured "
+                                               "TTLFactor is invalid (%.1f).",
+                                               tmp);
+                       }
+               } else {
+                       WARNING("write_riemann plugin: ignoring unknown config "
+                               "option: \"%s\"", child->key);
+               }
+       }
+       if (status != 0) {
+               riemann_free (host);
+               return status;
+       }
+
+       ssnprintf (callback_name, sizeof (callback_name), "write_riemann/%s",
+                       host->name);
+       ud.data = host;
+       ud.free_func = riemann_free;
+
+       pthread_mutex_lock (&host->lock);
+
+       status = plugin_register_write (callback_name, riemann_write, &ud);
+
+    if (host->use_tcp == 1 && host->batch_mode) {
+        ud.free_func = NULL;
+        plugin_register_flush(callback_name, riemann_batch_flush, &ud);
+    }
+       if (status != 0)
+               WARNING ("write_riemann plugin: plugin_register_write (\"%s\") "
+                               "failed with status %i.",
+                               callback_name, status);
+       else /* success */
+               host->reference_count++;
+
+       status = plugin_register_notification (callback_name,
+                       riemann_notification, &ud);
+       if (status != 0)
+               WARNING ("write_riemann plugin: plugin_register_notification (\"%s\") "
+                               "failed with status %i.",
+                               callback_name, status);
+       else /* success */
+               host->reference_count++;
+
+       if (host->reference_count <= 1)
+       {
+               /* Both callbacks failed => free memory.
+                * We need to unlock here, because riemann_free() will lock.
+                * This is not a race condition, because we're the only one
+                * holding a reference. */
+               pthread_mutex_unlock (&host->lock);
+               riemann_free (host);
+               return (-1);
+       }
+
+       host->reference_count--;
+       pthread_mutex_unlock (&host->lock);
+
+       return status;
+} /* }}} int riemann_config_node */
+
+static int riemann_config(oconfig_item_t *ci) /* {{{ */
+{
+       int              i;
+       oconfig_item_t  *child;
+       int              status;
+
+       for (i = 0; i < ci->children_num; i++)  {
+               child = &ci->children[i];
+
+               if (strcasecmp("Node", child->key) == 0) {
+                       riemann_config_node (child);
+               } else if (strcasecmp(child->key, "attribute") == 0) {
+                       char *key = NULL;
+                       char *val = NULL;
+
+                       if (child->values_num != 2) {
+                               WARNING("riemann attributes need both a key and a value.");
+                               return (-1);
+                       }
+                       if (child->values[0].type != OCONFIG_TYPE_STRING ||
+                           child->values[1].type != OCONFIG_TYPE_STRING) {
+                               WARNING("riemann attribute needs string arguments.");
+                               return (-1);
+                       }
+                       if ((key = strdup(child->values[0].value.string)) == NULL) {
+                               WARNING("cannot allocate memory for attribute key.");
+                               return (-1);
+                       }
+                       if ((val = strdup(child->values[1].value.string)) == NULL) {
+                               WARNING("cannot allocate memory for attribute value.");
+                               return (-1);
+                       }
+                       strarray_add(&riemann_attrs, &riemann_attrs_num, key);
+                       strarray_add(&riemann_attrs, &riemann_attrs_num, val);
+                       DEBUG("write_riemann: got attr: %s => %s", key, val);
+                       sfree(key);
+                       sfree(val);
+               } else if (strcasecmp(child->key, "tag") == 0) {
+                       char *tmp = NULL;
+                       status = cf_util_get_string(child, &tmp);
+                       if (status != 0)
+                               continue;
+
+                       strarray_add (&riemann_tags, &riemann_tags_num, tmp);
+                       DEBUG("write_riemann plugin: Got tag: %s", tmp);
+                       sfree (tmp);
+               } else {
+                       WARNING ("write_riemann plugin: Ignoring unknown "
+                                "configuration option \"%s\" at top level.",
+                                child->key);
+               }
+       }
+       return (0);
+} /* }}} int riemann_config */
+
+void module_register(void)
+{
+       plugin_register_complex_config ("write_riemann", riemann_config);
+}
+
+/* vim: set sw=8 sts=8 ts=8 noet : */
diff --git a/src/write_riemann_threshold.c b/src/write_riemann_threshold.c
new file mode 100644 (file)
index 0000000..6d5af03
--- /dev/null
@@ -0,0 +1,242 @@
+/**
+ * collectd - src/threshold.c
+ * Copyright (C) 2007-2010  Florian Forster
+ * Copyright (C) 2008-2009  Sebastian Harl
+ * Copyright (C) 2009       Andrés J. Díaz
+ * Copyright (C) 2014       Pierre-Yves Ritschard
+ *
+ * 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:
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ *   Florian octo Forster <octo at collectd.org>
+ *   Sebastian Harl <sh at tokkee.org>
+ *   Andrés J. Díaz <ajdiaz at connectical.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_avltree.h"
+#include "utils_cache.h"
+#include "utils_threshold.h"
+
+#include <assert.h>
+#include <ltdl.h>
+#include <pthread.h>
+
+/*
+ * Threshold management
+ * ====================
+ * The following functions add, delete, etc. configured thresholds to
+ * the underlying AVL trees.
+ */
+
+/*
+ * int ut_check_one_data_source
+ *
+ * Checks one data source against the given threshold configuration. If the
+ * `DataSource' option is set in the threshold, and the name does NOT match,
+ * `okay' is returned. If the threshold does match, its failure and warning
+ * min and max values are checked and `failure' or `warning' is returned if
+ * appropriate.
+ * Does not fail.
+ */
+static int ut_check_one_data_source (const data_set_t *ds,
+    const value_list_t __attribute__((unused)) *vl,
+    const threshold_t *th,
+    const gauge_t *values,
+    int ds_index)
+{ /* {{{ */
+  const char *ds_name;
+  int is_warning = 0;
+  int is_failure = 0;
+  int prev_state = STATE_OKAY;
+
+  /* check if this threshold applies to this data source */
+  if (ds != NULL)
+  {
+    ds_name = ds->ds[ds_index].name;
+    if ((th->data_source[0] != 0)
+       && (strcmp (ds_name, th->data_source) != 0))
+      return (STATE_OKAY);
+  }
+
+  if ((th->flags & UT_FLAG_INVERT) != 0)
+  {
+    is_warning--;
+    is_failure--;
+  }
+
+  /* XXX: This is an experimental code, not optimized, not fast, not reliable,
+   * and probably, do not work as you expect. Enjoy! :D */
+  if ( (th->hysteresis > 0) && ((prev_state = uc_get_state(ds,vl)) != STATE_OKAY) )
+  {
+    switch(prev_state)
+    {
+      case STATE_ERROR:
+       if ( (!isnan (th->failure_min) && ((th->failure_min + th->hysteresis) < values[ds_index])) ||
+            (!isnan (th->failure_max) && ((th->failure_max - th->hysteresis) > values[ds_index])) )
+         return (STATE_OKAY);
+       else
+         is_failure++;
+      case STATE_WARNING:
+       if ( (!isnan (th->warning_min) && ((th->warning_min + th->hysteresis) < values[ds_index])) ||
+            (!isnan (th->warning_max) && ((th->warning_max - th->hysteresis) > values[ds_index])) )
+         return (STATE_OKAY);
+       else
+         is_warning++;
+     }
+  }
+  else { /* no hysteresis */
+    if ((!isnan (th->failure_min) && (th->failure_min > values[ds_index]))
+       || (!isnan (th->failure_max) && (th->failure_max < values[ds_index])))
+      is_failure++;
+
+    if ((!isnan (th->warning_min) && (th->warning_min > values[ds_index]))
+       || (!isnan (th->warning_max) && (th->warning_max < values[ds_index])))
+      is_warning++;
+ }
+
+  if (is_failure != 0)
+    return (STATE_ERROR);
+
+  if (is_warning != 0)
+    return (STATE_WARNING);
+
+  return (STATE_OKAY);
+} /* }}} int ut_check_one_data_source */
+
+/*
+ * int ut_check_one_threshold
+ *
+ * Checks all data sources of a value list against the given threshold, using
+ * the ut_check_one_data_source function above. Returns the worst status,
+ * which is `okay' if nothing has failed.
+ * Returns less than zero if the data set doesn't have any data sources.
+ */
+static int ut_check_one_threshold (const data_set_t *ds,
+    const value_list_t *vl,
+    const threshold_t *th,
+    const gauge_t *values,
+    int *statuses)
+{ /* {{{ */
+  int ret = -1;
+  int i;
+  int status;
+  gauge_t values_copy[ds->ds_num];
+
+  memcpy (values_copy, values, sizeof (values_copy));
+
+  if ((th->flags & UT_FLAG_PERCENTAGE) != 0)
+  {
+    int num = 0;
+    gauge_t sum=0.0;
+
+    if (ds->ds_num == 1)
+    {
+      WARNING ("ut_check_one_threshold: The %s type has only one data "
+          "source, but you have configured to check this as a percentage. "
+          "That doesn't make much sense, because the percentage will always "
+          "be 100%%!", ds->type);
+    }
+
+    /* Prepare `sum' and `num'. */
+    for (i = 0; i < ds->ds_num; i++)
+      if (!isnan (values[i]))
+      {
+        num++;
+       sum += values[i];
+      }
+
+    if ((num == 0) /* All data sources are undefined. */
+        || (sum == 0.0)) /* Sum is zero, cannot calculate percentage. */
+    {
+      for (i = 0; i < ds->ds_num; i++)
+        values_copy[i] = NAN;
+    }
+    else /* We can actually calculate the percentage. */
+    {
+      for (i = 0; i < ds->ds_num; i++)
+        values_copy[i] = 100.0 * values[i] / sum;
+    }
+  } /* if (UT_FLAG_PERCENTAGE) */
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    status = ut_check_one_data_source (ds, vl, th, values_copy, i);
+    if (status != -1) {
+           ret = 0;
+           if (statuses[i] < status)
+                   statuses[i] = status;
+    }
+  } /* for (ds->ds_num) */
+
+  return (ret);
+} /* }}} int ut_check_one_threshold */
+
+/*
+ * int ut_check_threshold
+ *
+ * Gets a list of matching thresholds and searches for the worst status by one
+ * of the thresholds. Then reports that status using the ut_report_state
+ * function above.
+ * Returns zero on success and if no threshold has been configured. Returns
+ * less than zero on failure.
+ */
+int write_riemann_threshold_check (const data_set_t *ds, const value_list_t *vl,
+                                  int *statuses)
+{ /* {{{ */
+  threshold_t *th;
+  gauge_t *values;
+  int status;
+
+  memset(statuses, 0, vl->values_len * sizeof(*statuses));
+  if (threshold_tree == NULL)
+         return 0;
+
+  /* Is this lock really necessary? So far, thresholds are only inserted at
+   * startup. -octo */
+  pthread_mutex_lock (&threshold_lock);
+  th = threshold_search (vl);
+  pthread_mutex_unlock (&threshold_lock);
+  if (th == NULL)
+         return (0);
+
+  DEBUG ("ut_check_threshold: Found matching threshold(s)");
+
+  values = uc_get_rate (ds, vl);
+  if (values == NULL)
+         return (0);
+
+  while (th != NULL)
+  {
+    status = ut_check_one_threshold (ds, vl, th, values, statuses);
+    if (status < 0)
+    {
+      ERROR ("ut_check_threshold: ut_check_one_threshold failed.");
+      sfree (values);
+      return (-1);
+    }
+
+    th = th->next;
+  } /* while (th) */
+
+  sfree (values);
+
+  return (0);
+} /* }}} int ut_check_threshold */
+
+
+/* vim: set sw=2 ts=8 sts=2 tw=78 et fdm=marker : */
diff --git a/src/write_sensu.c b/src/write_sensu.c
new file mode 100644 (file)
index 0000000..7a3e4f4
--- /dev/null
@@ -0,0 +1,1240 @@
+/**
+ * collectd - src/write_sensu.c
+ * Copyright (C) 2015 Fabrice A. Marie
+ *
+ * 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:
+ *   Fabrice A. Marie <fabrice at kibinlabs.com>
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+#include "utils_cache.h"
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netdb.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stddef.h>
+
+#include <stdlib.h>
+#ifndef HAVE_ASPRINTF
+/*
+ * Uses asprintf() portable implementation from
+ * https://github.com/littlstar/asprintf.c/blob/master/
+ * copyright (c) 2014 joseph werle <joseph.werle@gmail.com> under MIT license.
+ */
+#include <stdio.h>
+#include <stdarg.h>
+
+int vasprintf(char **str, const char *fmt, va_list args) {
+       int size = 0;
+       va_list tmpa;
+       // copy
+       va_copy(tmpa, args);
+       // apply variadic arguments to
+       // sprintf with format to get size
+       size = vsnprintf(NULL, size, fmt, tmpa);
+       // toss args
+       va_end(tmpa);
+       // return -1 to be compliant if
+       // size is less than 0
+       if (size < 0) { return -1; }
+       // alloc with size plus 1 for `\0'
+       *str = (char *) malloc(size + 1);
+       // return -1 to be compliant
+       // if pointer is `NULL'
+       if (NULL == *str) { return -1; }
+       // format string with original
+       // variadic arguments and set new size
+       size = vsprintf(*str, fmt, args);
+       return size;
+}
+
+int asprintf(char **str, const char *fmt, ...) {
+       int size = 0;
+       va_list args;
+       // init variadic argumens
+       va_start(args, fmt);
+       // format and get size
+       size = vasprintf(str, fmt, args);
+       // toss args
+       va_end(args);
+       return size;
+}
+
+#endif
+
+#define SENSU_HOST             "localhost"
+#define SENSU_PORT             "3030"
+
+struct str_list {
+       int nb_strs;
+       char **strs;
+};
+
+struct sensu_host {
+       char                    *name;
+       char                    *event_service_prefix;
+       struct str_list metric_handlers;
+       struct str_list notification_handlers;
+#define F_READY      0x01
+       uint8_t                  flags;
+       pthread_mutex_t  lock;
+       _Bool            notifications;
+       _Bool            metrics;
+       _Bool                    store_rates;
+       _Bool                    always_append_ds;
+       char                    *separator;
+       char                    *node;
+       char                    *service;
+       int              s;
+       struct addrinfo *res;
+       int                          reference_count;
+};
+
+static char    *sensu_tags;
+static char    **sensu_attrs;
+static size_t sensu_attrs_num;
+
+static int add_str_to_list(struct str_list *strs,
+               const char *str_to_add) /* {{{ */
+{
+       char **old_strs_ptr = strs->strs;
+       char *newstr = strdup(str_to_add);
+       if (newstr == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return -1;
+       }
+       strs->strs = realloc(strs->strs, sizeof(char *) *(strs->nb_strs + 1));
+       if (strs->strs == NULL) {
+               strs->strs = old_strs_ptr;
+               free(newstr);
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return -1;
+       }
+       strs->strs[strs->nb_strs] = newstr;
+       strs->nb_strs++;
+       return 0;
+}
+/* }}} int add_str_to_list */
+
+static void free_str_list(struct str_list *strs) /* {{{ */
+{
+       int i;
+       for (i=0; i<strs->nb_strs; i++)
+               free(strs->strs[i]);
+       free(strs->strs);
+}
+/* }}} void free_str_list */
+
+static int sensu_connect(struct sensu_host *host) /* {{{ */
+{
+       int                      e;
+       struct addrinfo         *ai, hints;
+       char const              *node;
+       char const              *service;
+
+       // Resolve the target if we haven't done already
+       if (!(host->flags & F_READY)) {
+               memset(&hints, 0, sizeof(hints));
+               memset(&service, 0, sizeof(service));
+               host->res = NULL;
+               hints.ai_family = AF_INET;
+               hints.ai_socktype = SOCK_STREAM;
+#ifdef AI_ADDRCONFIG
+               hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+
+               node = (host->node != NULL) ? host->node : SENSU_HOST;
+               service = (host->service != NULL) ? host->service : SENSU_PORT;
+
+               if ((e = getaddrinfo(node, service, &hints, &(host->res))) != 0) {
+                       ERROR("write_sensu plugin: Unable to resolve host \"%s\": %s",
+                                       node, gai_strerror(e));
+                       return -1;
+               }
+               DEBUG("write_sensu plugin: successfully resolved host/port: %s/%s",
+                               node, service);
+               host->flags |= F_READY;
+       }
+
+       struct linger so_linger;
+       host->s = -1;
+       for (ai = host->res; ai != NULL; ai = ai->ai_next) {
+               // create the socket
+               if ((host->s = socket(ai->ai_family,
+                                     ai->ai_socktype,
+                                     ai->ai_protocol)) == -1) {
+                       continue;
+               }
+
+               // Set very low close() lingering
+               so_linger.l_onoff = 1;
+               so_linger.l_linger = 3;
+               if (setsockopt(host->s, SOL_SOCKET, SO_LINGER, &so_linger, sizeof so_linger) != 0)
+                       WARNING("write_sensu plugin: failed to set socket close() lingering");
+
+               // connect the socket
+               if (connect(host->s, ai->ai_addr, ai->ai_addrlen) != 0) {
+                       close(host->s);
+                       host->s = -1;
+                       continue;
+               }
+               DEBUG("write_sensu plugin: connected");
+               break;
+       }
+
+       if (host->s < 0) {
+               WARNING("write_sensu plugin: Unable to connect to sensu client");
+               return -1;
+       }
+       return 0;
+} /* }}} int sensu_connect */
+
+static void sensu_close_socket(struct sensu_host *host) /* {{{ */
+{
+       if (host->s != -1)
+               close(host->s);
+       host->s = -1;
+
+} /* }}} void sensu_close_socket */
+
+static char *build_json_str_list(const char *tag, struct str_list const *list) /* {{{ */
+{
+       int res;
+       char *ret_str;
+       char *temp_str;
+       int i;
+       if (list->nb_strs == 0) {
+               ret_str = malloc(sizeof(char));
+               if (ret_str == NULL) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str[0] = '\0';
+       }
+
+       res = asprintf(&temp_str, "\"%s\": [\"%s\"", tag, list->strs[0]);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       for (i=1; i<list->nb_strs; i++) {
+               res = asprintf(&ret_str, "%s, \"%s\"", temp_str, list->strs[i]);
+               free(temp_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               temp_str = ret_str;
+       }
+       res = asprintf(&ret_str, "%s]", temp_str);
+       free(temp_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+
+       return ret_str;
+} /* }}} char *build_json_str_list*/
+
+int sensu_format_name2(char *ret, int ret_len,
+               const char *hostname,
+               const char *plugin, const char *plugin_instance,
+               const char *type, const char *type_instance,
+               const char *separator)
+{
+       char *buffer;
+       size_t buffer_size;
+
+       buffer = ret;
+       buffer_size = (size_t) ret_len;
+
+#define APPEND(str) do {          \
+       size_t l = strlen (str);        \
+       if (l >= buffer_size)           \
+               return (ENOBUFS);             \
+       memcpy (buffer, (str), l);      \
+       buffer += l; buffer_size -= l;  \
+} while (0)
+
+       assert (plugin != NULL);
+       assert (type != NULL);
+
+       APPEND (hostname);
+       APPEND (separator);
+       APPEND (plugin);
+       if ((plugin_instance != NULL) && (plugin_instance[0] != 0))
+       {
+               APPEND ("-");
+               APPEND (plugin_instance);
+       }
+       APPEND (separator);
+       APPEND (type);
+       if ((type_instance != NULL) && (type_instance[0] != 0))
+       {
+               APPEND ("-");
+               APPEND (type_instance);
+       }
+       assert (buffer_size > 0);
+       buffer[0] = 0;
+
+#undef APPEND
+       return (0);
+} /* int sensu_format_name2 */
+
+static void in_place_replace_sensu_name_reserved(char *orig_name) /* {{{ */
+{
+       int i;
+       int len=strlen(orig_name);
+       for (i=0; i<len; i++) {
+               // some plugins like ipmi generate special characters in metric name
+               switch(orig_name[i]) {
+                       case '(': orig_name[i] = '_'; break;
+                       case ')': orig_name[i] = '_'; break;
+                       case ' ': orig_name[i] = '_'; break;
+                       case '"': orig_name[i] = '_'; break;
+                       case '\'': orig_name[i] = '_'; break;
+                       case '+': orig_name[i] = '_'; break;
+               }
+       }
+} /* }}} char *replace_sensu_name_reserved */
+
+static char *sensu_value_to_json(struct sensu_host const *host, /* {{{ */
+               data_set_t const *ds,
+               value_list_t const *vl, size_t index,
+               gauge_t const *rates,
+               int status)
+{
+       char name_buffer[5 * DATA_MAX_NAME_LEN];
+       char service_buffer[6 * DATA_MAX_NAME_LEN];
+       int i;
+       char *ret_str;
+       char *temp_str;
+       char *value_str;
+       int res;
+       // First part of the JSON string
+       const char *part1 = "{\"name\": \"collectd\", \"type\": \"metric\"";
+
+       char *handlers_str = build_json_str_list("handlers", &(host->metric_handlers));
+       if (handlers_str == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+
+       // incorporate the handlers
+       if (strlen(handlers_str) == 0) {
+               free(handlers_str);
+               ret_str = strdup(part1);
+               if (ret_str == NULL) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+       }
+       else {
+               res = asprintf(&ret_str, "%s, %s", part1, handlers_str);
+               free(handlers_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+       }
+
+       // incorporate the plugin name information
+       res = asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, vl->plugin);
+       free(ret_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       // incorporate the plugin type
+       res = asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, vl->type);
+       free(ret_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       // incorporate the plugin instance if any
+       if (vl->plugin_instance[0] != 0) {
+               res = asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, vl->plugin_instance);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate the plugin type instance if any
+       if (vl->type_instance[0] != 0) {
+               res = asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, vl->type_instance);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate the data source type
+       if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
+               char ds_type[DATA_MAX_NAME_LEN];
+               ssnprintf (ds_type, sizeof (ds_type), "%s:rate", DS_TYPE_TO_STRING(ds->ds[index].type));
+               res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, ds_type);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       } else {
+               res = asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"", ret_str, DS_TYPE_TO_STRING(ds->ds[index].type));
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate the data source name
+       res = asprintf(&temp_str, "%s, \"collectd_data_source_name\": \"%s\"", ret_str, ds->ds[index].name);
+       free(ret_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       // incorporate the data source index
+       {
+               char ds_index[DATA_MAX_NAME_LEN];
+               ssnprintf (ds_index, sizeof (ds_index), "%zu", index);
+               res = asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s", ret_str, ds_index);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // add key value attributes from config if any
+       for (i = 0; i < sensu_attrs_num; i += 2) {
+               res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate sensu tags from config if any
+       if (strlen(sensu_tags) != 0) {
+               res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // calculate the value and set to a string
+       if (ds->ds[index].type == DS_TYPE_GAUGE) {
+               res = asprintf(&value_str, GAUGE_FORMAT, vl->values[index].gauge);
+               if (res == -1) {
+                       free(ret_str);
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+       } else if (rates != NULL) {
+               res = asprintf(&value_str, GAUGE_FORMAT, rates[index]);
+               if (res == -1) {
+                       free(ret_str);
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+       } else {
+               if (ds->ds[index].type == DS_TYPE_DERIVE) {
+                       res = asprintf(&value_str, "%"PRIi64, vl->values[index].derive);
+                       if (res == -1) {
+                               free(ret_str);
+                               ERROR("write_sensu plugin: Unable to alloc memory");
+                               return NULL;
+                       }
+               }
+               else if (ds->ds[index].type == DS_TYPE_ABSOLUTE) {
+                       res = asprintf(&value_str, "%"PRIu64, vl->values[index].absolute);
+                       if (res == -1) {
+                               free(ret_str);
+                               ERROR("write_sensu plugin: Unable to alloc memory");
+                               return NULL;
+                       }
+               }
+               else {
+                       res = asprintf(&value_str, "%llu", vl->values[index].counter);
+                       if (res == -1) {
+                               free(ret_str);
+                               ERROR("write_sensu plugin: Unable to alloc memory");
+                               return NULL;
+                       }
+               }
+       }
+
+       // Generate the full service name
+       sensu_format_name2(name_buffer, sizeof(name_buffer),
+               vl->host, vl->plugin, vl->plugin_instance,
+               vl->type, vl->type_instance, host->separator);
+       if (host->always_append_ds || (ds->ds_num > 1)) {
+               if (host->event_service_prefix == NULL)
+                       ssnprintf(service_buffer, sizeof(service_buffer), "%s.%s",
+                                       name_buffer, ds->ds[index].name);
+               else
+                       ssnprintf(service_buffer, sizeof(service_buffer), "%s%s.%s",
+                                       host->event_service_prefix, name_buffer, ds->ds[index].name);
+       } else {
+               if (host->event_service_prefix == NULL)
+                       sstrncpy(service_buffer, name_buffer, sizeof(service_buffer));
+               else
+                       ssnprintf(service_buffer, sizeof(service_buffer), "%s%s",
+                                       host->event_service_prefix, name_buffer);
+       }
+
+       // Replace collectd sensor name reserved characters so that time series DB is happy
+       in_place_replace_sensu_name_reserved(service_buffer);
+
+       // finalize the buffer by setting the output and closing curly bracket
+       res = asprintf(&temp_str, "%s, \"output\": \"%s %s %ld\"}\n", ret_str, service_buffer, value_str, CDTIME_T_TO_TIME_T(vl->time));
+       free(ret_str);
+       free(value_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       DEBUG("write_sensu plugin: Successfully created json for metric: "
+                       "host = \"%s\", service = \"%s\"",
+                       vl->host, service_buffer);
+       return ret_str;
+} /* }}} char *sensu_value_to_json */
+
+/*
+ * Uses replace_str2() implementation from
+ * http://creativeandcritical.net/str-replace-c/
+ * copyright (c) Laird Shaw, under public domain.
+ */
+char *replace_str(const char *str, const char *old, /* {{{ */
+               const char *new)
+{
+       char *ret, *r;
+       const char *p, *q;
+       size_t oldlen = strlen(old);
+       size_t count = strlen(new);
+       size_t retlen = count;
+       size_t newlen = count;
+       int samesize = (oldlen == newlen);
+
+       if (!samesize) {
+               for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen)
+                       count++;
+               /* This is undefined if p - str > PTRDIFF_MAX */
+               retlen = p - str + strlen(p) + count * (newlen - oldlen);
+       } else
+               retlen = strlen(str);
+
+       ret = malloc(retlen + 1);
+       if (ret == NULL)
+               return NULL;
+       // added to original: not optimized, but keeps valgrind happy.
+       memset(ret, 0, retlen + 1);
+
+       r = ret;
+       p = str;
+       while (1) {
+               /* If the old and new strings are different lengths - in other
+                * words we have already iterated through with strstr above,
+                * and thus we know how many times we need to call it - then we
+                * can avoid the final (potentially lengthy) call to strstr,
+                * which we already know is going to return NULL, by
+                * decrementing and checking count.
+                */
+               if (!samesize && !count--)
+                       break;
+               /* Otherwise i.e. when the old and new strings are the same
+                * length, and we don't know how many times to call strstr,
+                * we must check for a NULL return here (we check it in any
+                * event, to avoid further conditions, and because there's
+                * no harm done with the check even when the old and new
+                * strings are different lengths).
+                */
+               if ((q = strstr(p, old)) == NULL)
+                       break;
+               /* This is undefined if q - p > PTRDIFF_MAX */
+               ptrdiff_t l = q - p;
+               memcpy(r, p, l);
+               r += l;
+               memcpy(r, new, newlen);
+               r += newlen;
+               p = q + oldlen;
+       }
+       strncpy(r, p, strlen(p));
+
+       return ret;
+} /* }}} char *replace_str */
+
+static char *replace_json_reserved(const char *message) /* {{{ */
+{
+       char *msg = replace_str(message, "\\", "\\\\");
+       if (msg == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       char *tmp = replace_str(msg, "\"", "\\\"");
+       free(msg);
+       if (tmp == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       msg = replace_str(tmp, "\n", "\\\n");
+       free(tmp);
+       if (msg == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       return msg;
+} /* }}} char *replace_json_reserved */
+
+static char *sensu_notification_to_json(struct sensu_host *host, /* {{{ */
+               notification_t const *n)
+{
+       char service_buffer[6 * DATA_MAX_NAME_LEN];
+       char const *severity;
+       notification_meta_t *meta;
+       char *ret_str;
+       char *temp_str;
+       int status;
+       int i;
+       int res;
+       // add the severity/status
+       switch (n->severity) {
+               case NOTIF_OKAY:
+                       severity = "OK";
+                       status = 0;
+                       break;
+               case NOTIF_WARNING:
+                       severity = "WARNING";
+                       status = 1;
+                       break;
+               case NOTIF_FAILURE:
+                       severity = "CRITICAL";
+                       status = 2;
+                       break;
+               default:
+                       severity = "UNKNOWN";
+                       status = 3;
+       }
+       res = asprintf(&temp_str, "{\"status\": %d", status);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       // incorporate the timestamp
+       res = asprintf(&temp_str, "%s, \"timestamp\": %ld", ret_str, CDTIME_T_TO_TIME_T(n->time));
+       free(ret_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       char *handlers_str = build_json_str_list("handlers", &(host->notification_handlers));
+       if (handlers_str == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       // incorporate the handlers
+       if (strlen(handlers_str) != 0) {
+               res = asprintf(&temp_str, "%s, %s", ret_str, handlers_str);
+               free(ret_str);
+               free(handlers_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       } else {
+               free(handlers_str);
+       }
+
+       // incorporate the plugin name information if any
+       if (n->plugin[0] != 0) {
+               res = asprintf(&temp_str, "%s, \"collectd_plugin\": \"%s\"", ret_str, n->plugin);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate the plugin type if any
+       if (n->type[0] != 0) {
+               res = asprintf(&temp_str, "%s, \"collectd_plugin_type\": \"%s\"", ret_str, n->type);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate the plugin instance if any
+       if (n->plugin_instance[0] != 0) {
+               res = asprintf(&temp_str, "%s, \"collectd_plugin_instance\": \"%s\"", ret_str, n->plugin_instance);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate the plugin type instance if any
+       if (n->type_instance[0] != 0) {
+               res = asprintf(&temp_str, "%s, \"collectd_plugin_type_instance\": \"%s\"", ret_str, n->type_instance);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // add key value attributes from config if any
+       for (i = 0; i < sensu_attrs_num; i += 2) {
+               res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, sensu_attrs[i], sensu_attrs[i+1]);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate sensu tags from config if any
+       if (strlen(sensu_tags) != 0) {
+               res = asprintf(&temp_str, "%s, %s", ret_str, sensu_tags);
+               free(ret_str);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // incorporate the service name
+       sensu_format_name2(service_buffer, sizeof(service_buffer),
+                               /* host */ "", n->plugin, n->plugin_instance,
+                               n->type, n->type_instance, host->separator);
+       // replace sensu event name chars that are considered illegal
+       in_place_replace_sensu_name_reserved(service_buffer);
+       res = asprintf(&temp_str, "%s, \"name\": \"%s\"", ret_str, &service_buffer[1]);
+       free(ret_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       // incorporate the check output
+       if (n->message[0] != 0) {
+               char *msg = replace_json_reserved(n->message);
+               if (msg == NULL) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               res = asprintf(&temp_str, "%s, \"output\": \"%s - %s\"", ret_str, severity, msg);
+               free(ret_str);
+               free(msg);
+               if (res == -1) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return NULL;
+               }
+               ret_str = temp_str;
+       }
+
+       // Pull in values from threshold and add extra attributes
+       for (meta = n->meta; meta != NULL; meta = meta->next) {
+               if (strcasecmp("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE) {
+                       res = asprintf(&temp_str, "%s, \"current_value\": \"%.8f\"", ret_str, meta->nm_value.nm_double);
+                       free(ret_str);
+                       if (res == -1) {
+                               ERROR("write_sensu plugin: Unable to alloc memory");
+                               return NULL;
+                       }
+                       ret_str = temp_str;
+               }
+               if (meta->type == NM_TYPE_STRING) {
+                       res = asprintf(&temp_str, "%s, \"%s\": \"%s\"", ret_str, meta->name, meta->nm_value.nm_string);
+                       free(ret_str);
+                       if (res == -1) {
+                               ERROR("write_sensu plugin: Unable to alloc memory");
+                               return NULL;
+                       }
+                       ret_str = temp_str;
+               }
+       }
+
+       // close the curly bracket
+       res = asprintf(&temp_str, "%s}\n", ret_str);
+       free(ret_str);
+       if (res == -1) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return NULL;
+       }
+       ret_str = temp_str;
+
+       DEBUG("write_sensu plugin: Successfully created JSON for notification: "
+                               "host = \"%s\", service = \"%s\", state = \"%s\"",
+                               n->host, service_buffer, severity);
+       return ret_str;
+} /* }}} char *sensu_notification_to_json */
+
+static int sensu_send_msg(struct sensu_host *host, const char *msg) /* {{{ */
+{
+       int status = 0;
+       size_t  buffer_len;
+
+       status = sensu_connect(host);
+       if (status != 0)
+               return status;
+
+       buffer_len = strlen(msg);
+
+       status = (int) swrite(host->s, msg, buffer_len);
+       sensu_close_socket(host);
+
+       if (status != 0) {
+               char errbuf[1024];
+               ERROR("write_sensu plugin: Sending to Sensu at %s:%s failed: %s",
+                               (host->node != NULL) ? host->node : SENSU_HOST,
+                               (host->service != NULL) ? host->service : SENSU_PORT,
+                               sstrerror(errno, errbuf, sizeof(errbuf)));
+               return -1;
+       }
+
+       return 0;
+} /* }}} int sensu_send_msg */
+
+
+static int sensu_send(struct sensu_host *host, char const *msg) /* {{{ */
+{
+       int status = 0;
+
+       status = sensu_send_msg(host, msg);
+       if (status != 0) {
+               host->flags &= ~F_READY;
+               if (host->res != NULL) {
+                       freeaddrinfo(host->res);
+                       host->res = NULL;
+               }
+               return status;
+       }
+
+       return 0;
+} /* }}} int sensu_send */
+
+
+static int sensu_write(const data_set_t *ds, /* {{{ */
+             const value_list_t *vl,
+             user_data_t *ud)
+{
+       int status = 0;
+       int statuses[vl->values_len];
+       struct sensu_host       *host = ud->data;
+       gauge_t *rates = NULL;
+       int i;
+       char *msg;
+
+       pthread_mutex_lock(&host->lock);
+       memset(statuses, 0, vl->values_len * sizeof(*statuses));
+
+       if (host->store_rates) {
+               rates = uc_get_rate(ds, vl);
+               if (rates == NULL) {
+                       ERROR("write_sensu plugin: uc_get_rate failed.");
+                       pthread_mutex_unlock(&host->lock);
+                       return -1;
+               }
+       }
+       for (i = 0; i < (size_t) vl->values_len; i++) {
+               msg = sensu_value_to_json(host, ds, vl, (int) i, rates, statuses[i]);
+               if (msg == NULL) {
+                       sfree(rates);
+                       pthread_mutex_unlock(&host->lock);
+                       return -1;
+               }
+               status = sensu_send(host, msg);
+               free(msg);
+               if (status != 0) {
+                       ERROR("write_sensu plugin: sensu_send failed with status %i", status);
+                       pthread_mutex_unlock(&host->lock);
+                       sfree(rates);
+                       return status;
+               }
+       }
+       sfree(rates);
+       pthread_mutex_unlock(&host->lock);
+       return status;
+} /* }}} int sensu_write */
+
+static int sensu_notification(const notification_t *n, user_data_t *ud) /* {{{ */
+{
+       int     status;
+       struct sensu_host *host = ud->data;
+       char *msg;
+
+       pthread_mutex_lock(&host->lock);
+
+       msg = sensu_notification_to_json(host, n);
+       if (msg == NULL) {
+               pthread_mutex_unlock(&host->lock);
+               return -1;
+       }
+
+       status = sensu_send(host, msg);
+       free(msg);
+       if (status != 0)
+               ERROR("write_sensu plugin: sensu_send failed with status %i", status);
+       pthread_mutex_unlock(&host->lock);
+
+       return status;
+} /* }}} int sensu_notification */
+
+static void sensu_free(void *p) /* {{{ */
+{
+       struct sensu_host *host = p;
+
+       if (host == NULL)
+               return;
+
+       pthread_mutex_lock(&host->lock);
+
+       host->reference_count--;
+       if (host->reference_count > 0) {
+               pthread_mutex_unlock(&host->lock);
+               return;
+       }
+
+       sensu_close_socket(host);
+       if (host->res != NULL) {
+               freeaddrinfo(host->res);
+               host->res = NULL;
+       }
+       sfree(host->service);
+       sfree(host->event_service_prefix);
+       sfree(host->name);
+       sfree(host->node);
+       sfree(host->separator);
+       free_str_list(&(host->metric_handlers));
+       free_str_list(&(host->notification_handlers));
+       pthread_mutex_destroy(&host->lock);
+       sfree(host);
+} /* }}} void sensu_free */
+
+
+static int sensu_config_node(oconfig_item_t *ci) /* {{{ */
+{
+       struct sensu_host       *host = NULL;
+       int                                     status = 0;
+       int                                     i;
+       oconfig_item_t          *child;
+       char                            callback_name[DATA_MAX_NAME_LEN];
+       user_data_t                     ud;
+
+       if ((host = calloc(1, sizeof(*host))) == NULL) {
+               ERROR("write_sensu plugin: calloc failed.");
+               return ENOMEM;
+       }
+       pthread_mutex_init(&host->lock, NULL);
+       host->reference_count = 1;
+       host->node = NULL;
+       host->service = NULL;
+       host->notifications = 0;
+       host->metrics = 0;
+       host->store_rates = 1;
+       host->always_append_ds = 0;
+       host->metric_handlers.nb_strs = 0;
+       host->metric_handlers.strs = NULL;
+       host->notification_handlers.nb_strs = 0;
+       host->notification_handlers.strs = NULL;
+       host->separator = strdup("/");
+       if (host->separator == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               sensu_free(host);
+               return -1;
+       }
+
+       status = cf_util_get_string(ci, &host->name);
+       if (status != 0) {
+               WARNING("write_sensu plugin: Required host name is missing.");
+               sensu_free(host);
+               return -1;
+       }
+
+       for (i = 0; i < ci->children_num; i++) {
+               child = &ci->children[i];
+               status = 0;
+
+               if (strcasecmp("Host", child->key) == 0) {
+                       status = cf_util_get_string(child, &host->node);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp("Notifications", child->key) == 0) {
+                       status = cf_util_get_boolean(child, &host->notifications);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp("Metrics", child->key) == 0) {
+                                       status = cf_util_get_boolean(child, &host->metrics);
+                                       if (status != 0)
+                                               break;
+               } else if (strcasecmp("EventServicePrefix", child->key) == 0) {
+                       status = cf_util_get_string(child, &host->event_service_prefix);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp("Separator", child->key) == 0) {
+                               status = cf_util_get_string(child, &host->separator);
+                               if (status != 0)
+                                       break;
+               } else if (strcasecmp("MetricHandler", child->key) == 0) {
+                       char *temp_str = NULL;
+                       status = cf_util_get_string(child, &temp_str);
+                       if (status != 0)
+                               break;
+                       status = add_str_to_list(&(host->metric_handlers), temp_str);
+                       free(temp_str);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp("NotificationHandler", child->key) == 0) {
+                       char *temp_str = NULL;
+                       status = cf_util_get_string(child, &temp_str);
+                       if (status != 0)
+                               break;
+                       status = add_str_to_list(&(host->notification_handlers), temp_str);
+                       free(temp_str);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp("Port", child->key) == 0) {
+                       status = cf_util_get_service(child, &host->service);
+                       if (status != 0) {
+                               ERROR("write_sensu plugin: Invalid argument "
+                                               "configured for the \"Port\" "
+                                               "option.");
+                               break;
+                       }
+               } else if (strcasecmp("StoreRates", child->key) == 0) {
+                       status = cf_util_get_boolean(child, &host->store_rates);
+                       if (status != 0)
+                               break;
+               } else if (strcasecmp("AlwaysAppendDS", child->key) == 0) {
+                       status = cf_util_get_boolean(child,
+                                       &host->always_append_ds);
+                       if (status != 0)
+                               break;
+               } else {
+                       WARNING("write_sensu plugin: ignoring unknown config "
+                               "option: \"%s\"", child->key);
+               }
+       }
+       if (status != 0) {
+               sensu_free(host);
+               return status;
+       }
+
+       if (host->metrics && (host->metric_handlers.nb_strs == 0)) {
+                       sensu_free(host);
+                       WARNING("write_sensu plugin: metrics enabled but no MetricHandler defined. Giving up.");
+                       return -1;
+               }
+
+       if (host->notifications && (host->notification_handlers.nb_strs == 0)) {
+               sensu_free(host);
+               WARNING("write_sensu plugin: notifications enabled but no NotificationHandler defined. Giving up.");
+               return -1;
+       }
+
+       if ((host->notification_handlers.nb_strs > 0) && (host->notifications == 0)) {
+               WARNING("write_sensu plugin: NotificationHandler given so forcing notifications to be enabled");
+               host->notifications = 1;
+       }
+
+       if ((host->metric_handlers.nb_strs > 0) && (host->metrics == 0)) {
+               WARNING("write_sensu plugin: MetricHandler given so forcing metrics to be enabled");
+               host->metrics = 1;
+       }
+
+       if (!(host->notifications || host->metrics)) {
+               WARNING("write_sensu plugin: neither metrics nor notifications enabled. Giving up.");
+               sensu_free(host);
+               return -1;
+       }
+
+       ssnprintf(callback_name, sizeof(callback_name), "write_sensu/%s", host->name);
+       ud.data = host;
+       ud.free_func = sensu_free;
+
+       pthread_mutex_lock(&host->lock);
+
+       if (host->metrics) {
+               status = plugin_register_write(callback_name, sensu_write, &ud);
+               if (status != 0)
+                       WARNING("write_sensu plugin: plugin_register_write (\"%s\") "
+                                       "failed with status %i.",
+                                       callback_name, status);
+               else /* success */
+                       host->reference_count++;
+       }
+
+       if (host->notifications) {
+               status = plugin_register_notification(callback_name, sensu_notification, &ud);
+               if (status != 0)
+                       WARNING("write_sensu plugin: plugin_register_notification (\"%s\") "
+                                       "failed with status %i.",
+                                       callback_name, status);
+               else
+                       host->reference_count++;
+       }
+
+       if (host->reference_count <= 1) {
+               /* Both callbacks failed => free memory.
+                * We need to unlock here, because sensu_free() will lock.
+                * This is not a race condition, because we're the only one
+                * holding a reference. */
+               pthread_mutex_unlock(&host->lock);
+               sensu_free(host);
+               return -1;
+       }
+
+       host->reference_count--;
+       pthread_mutex_unlock(&host->lock);
+
+       return status;
+} /* }}} int sensu_config_node */
+
+static int sensu_config(oconfig_item_t *ci) /* {{{ */
+{
+       int              i;
+       oconfig_item_t  *child;
+       int              status;
+       struct str_list sensu_tags_arr;
+
+       sensu_tags_arr.nb_strs = 0;
+       sensu_tags_arr.strs = NULL;
+       sensu_tags = malloc(sizeof(char));
+       if (sensu_tags == NULL) {
+               ERROR("write_sensu plugin: Unable to alloc memory");
+               return -1;
+       }
+       sensu_tags[0] = '\0';
+
+       for (i = 0; i < ci->children_num; i++)  {
+               child = &ci->children[i];
+
+               if (strcasecmp("Node", child->key) == 0) {
+                       sensu_config_node(child);
+               } else if (strcasecmp(child->key, "attribute") == 0) {
+                       char *key = NULL;
+                       char *val = NULL;
+
+                       if (child->values_num != 2) {
+                               WARNING("sensu attributes need both a key and a value.");
+                               free(sensu_tags);
+                               return -1;
+                       }
+                       if (child->values[0].type != OCONFIG_TYPE_STRING ||
+                           child->values[1].type != OCONFIG_TYPE_STRING) {
+                               WARNING("sensu attribute needs string arguments.");
+                               free(sensu_tags);
+                               return -1;
+                       }
+                       if ((key = strdup(child->values[0].value.string)) == NULL) {
+                               ERROR("write_sensu plugin: Unable to alloc memory");
+                               free(sensu_tags);
+                               return -1;
+                       }
+                       if ((val = strdup(child->values[1].value.string)) == NULL) {
+                               free(sensu_tags);
+                               free(key);
+                               ERROR("write_sensu plugin: Unable to alloc memory");
+                               return -1;
+                       }
+                       strarray_add(&sensu_attrs, &sensu_attrs_num, key);
+                       strarray_add(&sensu_attrs, &sensu_attrs_num, val);
+                       DEBUG("write_sensu: got attr: %s => %s", key, val);
+                       sfree(key);
+                       sfree(val);
+               } else if (strcasecmp(child->key, "tag") == 0) {
+                       char *tmp = NULL;
+                       status = cf_util_get_string(child, &tmp);
+                       if (status != 0)
+                               continue;
+
+                       status = add_str_to_list(&sensu_tags_arr, tmp);
+                       sfree(tmp);
+                       if (status != 0)
+                               continue;
+                       DEBUG("write_sensu plugin: Got tag: %s", tmp);
+               } else {
+                       WARNING("write_sensu plugin: Ignoring unknown "
+                                "configuration option \"%s\" at top level.",
+                                child->key);
+               }
+       }
+       if (sensu_tags_arr.nb_strs > 0) {
+               free(sensu_tags);
+               sensu_tags = build_json_str_list("tags", &sensu_tags_arr);
+               free_str_list(&sensu_tags_arr);
+               if (sensu_tags == NULL) {
+                       ERROR("write_sensu plugin: Unable to alloc memory");
+                       return -1;
+               }
+       }
+       return 0;
+} /* }}} int sensu_config */
+
+void module_register(void)
+{
+       plugin_register_complex_config("write_sensu", sensu_config);
+}
+
+/* vim: set sw=8 sts=8 ts=8 noet : */
diff --git a/src/write_tsdb.c b/src/write_tsdb.c
new file mode 100644 (file)
index 0000000..27ea473
--- /dev/null
@@ -0,0 +1,657 @@
+/**
+ * collectd - src/write_tsdb.c
+ * Copyright (C) 2012       Pierre-Yves Ritschard
+ * Copyright (C) 2011       Scott Sanders
+ * Copyright (C) 2009       Paul Sadauskas
+ * Copyright (C) 2009       Doug MacEachern
+ * Copyright (C) 2007-2012  Florian octo Forster
+ * Copyright (C) 2013-2014  Limelight Networks, Inc.
+ * 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
+ *
+ * Based on the write_graphite plugin. Authors:
+ *   Florian octo Forster <octo at collectd.org>
+ *   Doug MacEachern <dougm at hyperic.com>
+ *   Paul Sadauskas <psadauskas at gmail.com>
+ *   Scott Sanders <scott at jssjr.com>
+ *   Pierre-Yves Ritschard <pyr at spootnik.org>
+ * write_tsdb Authors:
+ *   Brett Hawn <bhawn at llnw.com>
+ *   Kevin Bowling <kbowling@llnw.com>
+ **/
+
+/* write_tsdb plugin configuation example
+ *
+ * <Plugin write_tsdb>
+ *   <Node>
+ *     Host "localhost"
+ *     Port "4242"
+ *     HostTags "status=production deviceclass=www"
+ *   </Node>
+ * </Plugin>
+ */
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include "utils_cache.h"
+
+#include <pthread.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#ifndef WT_DEFAULT_NODE
+# define WT_DEFAULT_NODE "localhost"
+#endif
+
+#ifndef WT_DEFAULT_SERVICE
+# define WT_DEFAULT_SERVICE "4242"
+#endif
+
+#ifndef WT_DEFAULT_ESCAPE
+# define WT_DEFAULT_ESCAPE '.'
+#endif
+
+/* Ethernet - (IPv6 + TCP) = 1500 - (40 + 32) = 1428 */
+#ifndef WT_SEND_BUF_SIZE
+# define WT_SEND_BUF_SIZE 1428
+#endif
+
+/*
+ * Private variables
+ */
+struct wt_callback
+{
+    int      sock_fd;
+
+    char     *node;
+    char     *service;
+    char     *host_tags;
+
+    _Bool    store_rates;
+    _Bool    always_append_ds;
+
+    char     send_buf[WT_SEND_BUF_SIZE];
+    size_t   send_buf_free;
+    size_t   send_buf_fill;
+    cdtime_t send_buf_init_time;
+
+    pthread_mutex_t send_lock;
+};
+
+
+/*
+ * Functions
+ */
+static void wt_reset_buffer(struct wt_callback *cb)
+{
+    memset(cb->send_buf, 0, sizeof(cb->send_buf));
+    cb->send_buf_free = sizeof(cb->send_buf);
+    cb->send_buf_fill = 0;
+    cb->send_buf_init_time = cdtime();
+}
+
+static int wt_send_buffer(struct wt_callback *cb)
+{
+    ssize_t status = 0;
+
+    status = swrite(cb->sock_fd, cb->send_buf, strlen(cb->send_buf));
+    if (status < 0)
+    {
+        char errbuf[1024];
+        ERROR("write_tsdb plugin: send failed with status %zi (%s)",
+              status, sstrerror (errno, errbuf, sizeof (errbuf)));
+
+        close (cb->sock_fd);
+        cb->sock_fd = -1;
+
+        return -1;
+    }
+
+    return 0;
+}
+
+/* NOTE: You must hold cb->send_lock when calling this function! */
+static int wt_flush_nolock(cdtime_t timeout, struct wt_callback *cb)
+{
+    int status;
+
+    DEBUG("write_tsdb plugin: wt_flush_nolock: timeout = %.3f; "
+          "send_buf_fill = %zu;",
+          (double)timeout,
+          cb->send_buf_fill);
+
+    /* timeout == 0  => flush unconditionally */
+    if (timeout > 0)
+    {
+        cdtime_t now;
+
+        now = cdtime();
+        if ((cb->send_buf_init_time + timeout) > now)
+            return 0;
+    }
+
+    if (cb->send_buf_fill <= 0)
+    {
+        cb->send_buf_init_time = cdtime();
+        return 0;
+    }
+
+    status = wt_send_buffer(cb);
+    wt_reset_buffer(cb);
+
+    return status;
+}
+
+static int wt_callback_init(struct wt_callback *cb)
+{
+    struct addrinfo ai_hints;
+    struct addrinfo *ai_list;
+    struct addrinfo *ai_ptr;
+    int status;
+
+    const char *node = cb->node ? cb->node : WT_DEFAULT_NODE;
+    const char *service = cb->service ? cb->service : WT_DEFAULT_SERVICE;
+
+    if (cb->sock_fd > 0)
+        return 0;
+
+    memset(&ai_hints, 0, sizeof(ai_hints));
+#ifdef AI_ADDRCONFIG
+    ai_hints.ai_flags    |= AI_ADDRCONFIG;
+#endif
+    ai_hints.ai_family   = AF_UNSPEC;
+    ai_hints.ai_socktype = SOCK_STREAM;
+
+    ai_list = NULL;
+
+    status = getaddrinfo(node, service, &ai_hints, &ai_list);
+    if (status != 0)
+    {
+        ERROR("write_tsdb plugin: getaddrinfo (%s, %s) failed: %s",
+              node, service, gai_strerror (status));
+        return -1;
+    }
+
+    assert (ai_list != NULL);
+    for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+    {
+        cb->sock_fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype,
+                             ai_ptr->ai_protocol);
+        if (cb->sock_fd < 0)
+            continue;
+
+        status = connect(cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+        if (status != 0)
+        {
+            close(cb->sock_fd);
+            cb->sock_fd = -1;
+            continue;
+        }
+
+        break;
+    }
+
+    freeaddrinfo(ai_list);
+
+    if (cb->sock_fd < 0)
+    {
+        char errbuf[1024];
+        ERROR("write_tsdb plugin: Connecting to %s:%s failed. "
+              "The last error was: %s", node, service,
+              sstrerror (errno, errbuf, sizeof(errbuf)));
+        close(cb->sock_fd);
+        return -1;
+    }
+
+    wt_reset_buffer(cb);
+
+    return 0;
+}
+
+static void wt_callback_free(void *data)
+{
+    struct wt_callback *cb;
+
+    if (data == NULL)
+        return;
+
+    cb = data;
+
+    pthread_mutex_lock(&cb->send_lock);
+
+    wt_flush_nolock(0, cb);
+
+    close(cb->sock_fd);
+    cb->sock_fd = -1;
+
+    sfree(cb->node);
+    sfree(cb->service);
+    sfree(cb->host_tags);
+
+    pthread_mutex_destroy(&cb->send_lock);
+
+    sfree(cb);
+}
+
+static int wt_flush(cdtime_t timeout,
+                    const char *identifier __attribute__((unused)),
+                    user_data_t *user_data)
+{
+    struct wt_callback *cb;
+    int status;
+
+    if (user_data == NULL)
+        return -EINVAL;
+
+    cb = user_data->data;
+
+    pthread_mutex_lock(&cb->send_lock);
+
+    if (cb->sock_fd < 0)
+    {
+        status = wt_callback_init(cb);
+        if (status != 0)
+        {
+            ERROR("write_tsdb plugin: wt_callback_init failed.");
+            pthread_mutex_unlock(&cb->send_lock);
+            return -1;
+        }
+    }
+
+    status = wt_flush_nolock(timeout, cb);
+    pthread_mutex_unlock(&cb->send_lock);
+
+    return status;
+}
+
+static int wt_format_values(char *ret, size_t ret_len,
+                            int ds_num, const data_set_t *ds,
+                            const value_list_t *vl,
+                            _Bool store_rates)
+{
+    size_t offset = 0;
+    int status;
+    gauge_t *rates = NULL;
+
+    assert(0 == strcmp (ds->type, vl->type));
+
+    memset(ret, 0, ret_len);
+
+#define BUFFER_ADD(...) do { \
+        status = ssnprintf (ret + offset, ret_len - offset, \
+                            __VA_ARGS__); \
+        if (status < 1) \
+        { \
+            sfree(rates); \
+            return -1; \
+        } \
+        else if (((size_t) status) >= (ret_len - offset)) \
+        { \
+            sfree(rates); \
+            return -1; \
+        } \
+        else \
+            offset += ((size_t) status); \
+} while (0)
+
+    if (ds->ds[ds_num].type == DS_TYPE_GAUGE)
+        BUFFER_ADD(GAUGE_FORMAT, vl->values[ds_num].gauge);
+    else if (store_rates)
+    {
+        if (rates == NULL)
+            rates = uc_get_rate (ds, vl);
+        if (rates == NULL)
+        {
+            WARNING("format_values: "
+                    "uc_get_rate failed.");
+            return -1;
+        }
+        BUFFER_ADD(GAUGE_FORMAT, rates[ds_num]);
+    }
+    else if (ds->ds[ds_num].type == DS_TYPE_COUNTER)
+        BUFFER_ADD("%llu", vl->values[ds_num].counter);
+    else if (ds->ds[ds_num].type == DS_TYPE_DERIVE)
+        BUFFER_ADD("%" PRIi64, vl->values[ds_num].derive);
+    else if (ds->ds[ds_num].type == DS_TYPE_ABSOLUTE)
+        BUFFER_ADD("%" PRIu64, vl->values[ds_num].absolute);
+    else
+    {
+        ERROR("format_values plugin: Unknown data source type: %i",
+              ds->ds[ds_num].type);
+        sfree(rates);
+        return -1;
+    }
+
+#undef BUFFER_ADD
+
+    sfree(rates);
+    return 0;
+}
+
+static int wt_format_name(char *ret, int ret_len,
+                          const value_list_t *vl,
+                          const struct wt_callback *cb,
+                          const char *ds_name)
+{
+    int status;
+    char *temp = NULL;
+    char *prefix = "";
+    const char *meta_prefix = "tsdb_prefix";
+
+    if (vl->meta) {
+        status = meta_data_get_string(vl->meta, meta_prefix, &temp);
+        if (status == -ENOENT) {
+            /* defaults to empty string */
+        } else if (status < 0) {
+            sfree(temp);
+            return status;
+        } else {
+            prefix = temp;
+        }
+    }
+
+    if (ds_name != NULL) {
+        if (vl->plugin_instance[0] == '\0') {
+            if (vl->type_instance[0] == '\0') {
+                ssnprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin,
+                        vl->type, ds_name);
+            } else {
+                ssnprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin,
+                        vl->type, vl->type_instance, ds_name);
+            }
+        } else { /* vl->plugin_instance != "" */
+            if (vl->type_instance[0] == '\0') {
+                ssnprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin,
+                        vl->plugin_instance, vl->type, ds_name);
+            } else {
+                ssnprintf(ret, ret_len, "%s%s.%s.%s.%s.%s", prefix,
+                        vl->plugin, vl->plugin_instance, vl->type,
+                        vl->type_instance, ds_name);
+            }
+        }
+    } else { /* ds_name == NULL */
+        if (vl->plugin_instance[0] == '\0') {
+            if (vl->type_instance[0] == '\0') {
+                ssnprintf(ret, ret_len, "%s%s.%s", prefix, vl->plugin,
+                        vl->type);
+            } else {
+                ssnprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin,
+                        vl->type_instance, vl->type);
+            }
+        } else { /* vl->plugin_instance != "" */
+            if (vl->type_instance[0] == '\0') {
+                ssnprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin,
+                        vl->plugin_instance, vl->type);
+            } else {
+                ssnprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin,
+                        vl->plugin_instance, vl->type, vl->type_instance);
+            }
+        }
+    }
+
+    sfree(temp);
+    return 0;
+}
+
+static int wt_send_message (const char* key, const char* value,
+                            cdtime_t time, struct wt_callback *cb,
+                            const char* host, meta_data_t *md)
+{
+    int status;
+    int message_len;
+    char *temp = NULL;
+    char *tags = "";
+    char message[1024];
+    char *host_tags = cb->host_tags ? cb->host_tags : "";
+    const char *meta_tsdb = "tsdb_tags";
+
+    /* skip if value is NaN */
+    if (value[0] == 'n')
+        return 0;
+
+    if (md) {
+        status = meta_data_get_string(md, meta_tsdb, &temp);
+        if (status == -ENOENT) {
+            /* defaults to empty string */
+        } else if (status < 0) {
+            ERROR("write_tsdb plugin: tags metadata get failure");
+            sfree(temp);
+            pthread_mutex_unlock(&cb->send_lock);
+            return status;
+        } else {
+            tags = temp;
+        }
+    }
+
+    message_len = ssnprintf (message,
+                             sizeof(message),
+                             "put %s %.0f %s fqdn=%s %s %s\r\n",
+                             key,
+                             CDTIME_T_TO_DOUBLE(time),
+                             value,
+                             host,
+                             tags,
+                             host_tags);
+
+    sfree(temp);
+
+    if (message_len >= sizeof(message)) {
+        ERROR("write_tsdb plugin: message buffer too small: "
+              "Need %d bytes.", message_len + 1);
+        return -1;
+    }
+
+    pthread_mutex_lock(&cb->send_lock);
+
+    if (cb->sock_fd < 0)
+    {
+        status = wt_callback_init(cb);
+        if (status != 0)
+        {
+            ERROR("write_tsdb plugin: wt_callback_init failed.");
+            pthread_mutex_unlock(&cb->send_lock);
+            return -1;
+        }
+    }
+
+    if (message_len >= cb->send_buf_free)
+    {
+        status = wt_flush_nolock(0, cb);
+        if (status != 0)
+        {
+            pthread_mutex_unlock(&cb->send_lock);
+            return status;
+        }
+    }
+
+    /* Assert that we have enough space for this message. */
+    assert(message_len < cb->send_buf_free);
+
+    /* `message_len + 1' because `message_len' does not include the
+     * trailing null byte. Neither does `send_buffer_fill'. */
+    memcpy(cb->send_buf + cb->send_buf_fill,
+            message, message_len + 1);
+    cb->send_buf_fill += message_len;
+    cb->send_buf_free -= message_len;
+
+    DEBUG("write_tsdb plugin: [%s]:%s buf %zu/%zu (%.1f %%) \"%s\"",
+          cb->node,
+          cb->service,
+          cb->send_buf_fill, sizeof(cb->send_buf),
+          100.0 * ((double) cb->send_buf_fill) /
+          ((double) sizeof(cb->send_buf)),
+          message);
+
+    pthread_mutex_unlock(&cb->send_lock);
+
+    return 0;
+}
+
+static int wt_write_messages(const data_set_t *ds, const value_list_t *vl,
+                             struct wt_callback *cb)
+{
+    char key[10*DATA_MAX_NAME_LEN];
+    char values[512];
+
+    int status, i;
+
+    if (0 != strcmp(ds->type, vl->type))
+    {
+        ERROR("write_tsdb plugin: DS type does not match "
+              "value list type");
+        return -1;
+    }
+
+    for (i = 0; i < ds->ds_num; i++)
+    {
+        const char *ds_name = NULL;
+
+        if (cb->always_append_ds || (ds->ds_num > 1))
+            ds_name = ds->ds[i].name;
+
+        /* Copy the identifier to 'key' and escape it. */
+        status = wt_format_name(key, sizeof(key), vl, cb, ds_name);
+        if (status != 0)
+        {
+            ERROR("write_tsdb plugin: error with format_name");
+            return status;
+        }
+
+        escape_string(key, sizeof(key));
+        /* Convert the values to an ASCII representation and put that into
+         * 'values'. */
+        status = wt_format_values(values, sizeof(values), i, ds, vl,
+                                  cb->store_rates);
+        if (status != 0)
+        {
+            ERROR("write_tsdb plugin: error with "
+                  "wt_format_values");
+            return status;
+        }
+
+        /* Send the message to tsdb */
+        status = wt_send_message(key, values, vl->time, cb, vl->host, vl->meta);
+        if (status != 0)
+        {
+            ERROR("write_tsdb plugin: error with "
+                  "wt_send_message");
+            return status;
+        }
+    }
+
+    return 0;
+}
+
+static int wt_write(const data_set_t *ds, const value_list_t *vl,
+                    user_data_t *user_data)
+{
+    struct wt_callback *cb;
+    int status;
+
+    if (user_data == NULL)
+        return EINVAL;
+
+    cb = user_data->data;
+
+    status = wt_write_messages(ds, vl, cb);
+
+    return status;
+}
+
+static int wt_config_tsd(oconfig_item_t *ci)
+{
+    struct wt_callback *cb;
+    user_data_t user_data;
+    char callback_name[DATA_MAX_NAME_LEN];
+    int i;
+
+    cb = malloc(sizeof(*cb));
+    if (cb == NULL)
+    {
+        ERROR("write_tsdb plugin: malloc failed.");
+        return -1;
+    }
+    memset(cb, 0, sizeof(*cb));
+    cb->sock_fd = -1;
+    cb->node = NULL;
+    cb->service = NULL;
+    cb->host_tags = NULL;
+    cb->store_rates = 0;
+
+    pthread_mutex_init (&cb->send_lock, NULL);
+
+    for (i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp("Host", child->key) == 0)
+            cf_util_get_string(child, &cb->node);
+        else if (strcasecmp("Port", child->key) == 0)
+            cf_util_get_service(child, &cb->service);
+        else if (strcasecmp("HostTags", child->key) == 0)
+            cf_util_get_string(child, &cb->host_tags);
+        else if (strcasecmp("StoreRates", child->key) == 0)
+            cf_util_get_boolean(child, &cb->store_rates);
+        else if (strcasecmp("AlwaysAppendDS", child->key) == 0)
+            cf_util_get_boolean(child, &cb->always_append_ds);
+        else
+        {
+            ERROR("write_tsdb plugin: Invalid configuration "
+                  "option: %s.", child->key);
+        }
+    }
+
+    ssnprintf(callback_name, sizeof(callback_name), "write_tsdb/%s/%s",
+              cb->node != NULL ? cb->node : WT_DEFAULT_NODE,
+              cb->service != NULL ? cb->service : WT_DEFAULT_SERVICE);
+
+    memset(&user_data, 0, sizeof(user_data));
+    user_data.data = cb;
+    user_data.free_func = wt_callback_free;
+    plugin_register_write(callback_name, wt_write, &user_data);
+
+    user_data.free_func = NULL;
+    plugin_register_flush(callback_name, wt_flush, &user_data);
+
+    return 0;
+}
+
+static int wt_config(oconfig_item_t *ci)
+{
+    int i;
+
+    for (i = 0; i < ci->children_num; i++)
+    {
+        oconfig_item_t *child = ci->children + i;
+
+        if (strcasecmp("Node", child->key) == 0)
+            wt_config_tsd(child);
+        else
+        {
+            ERROR("write_tsdb plugin: Invalid configuration "
+                  "option: %s.", child->key);
+        }
+    }
+
+    return 0;
+}
+
+void module_register(void)
+{
+    plugin_register_complex_config("write_tsdb", wt_config);
+}
+
+/* vim: set sw=4 ts=4 sts=4 tw=78 et : */
diff --git a/src/xmms.c b/src/xmms.c
new file mode 100644 (file)
index 0000000..a423bb6
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+ * collectd - src/xmms.c
+ * Copyright (C) 2007       Florian octo Forster
+ *
+ * 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:
+ *   Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+
+#include <xmms/xmmsctrl.h>
+
+static gint xmms_session;
+
+static void cxmms_submit (const char *type, gauge_t value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "xmms", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void cxmms_submit */
+
+int cxmms_read (void)
+{
+  gint rate;
+  gint freq;
+  gint nch;
+
+  if (!xmms_remote_is_running (xmms_session))
+    return (0);
+
+  xmms_remote_get_info (xmms_session, &rate, &freq, &nch);
+
+  if ((freq == 0) || (nch == 0))
+    return (-1);
+
+  cxmms_submit ("bitrate", rate);
+  cxmms_submit ("frequency", freq);
+
+  return (0);
+} /* int read */
+
+void module_register (void)
+{
+  plugin_register_read ("xmms", cxmms_read);
+} /* void module_register */
+
+/*
+ * vim: shiftwidth=2:softtabstop=2:textwidth=78
+ */
diff --git a/src/zfs_arc.c b/src/zfs_arc.c
new file mode 100644 (file)
index 0000000..f0d2323
--- /dev/null
@@ -0,0 +1,338 @@
+/**
+ * collectd - src/zfs_arc.c
+ * Copyright (C) 2009  Anthony Dewhurst
+ * Copyright (C) 2012  Aurelien Rougemont
+ * Copyright (C) 2013  Xin Li
+ * Copyright (C) 2014  Marc Fournier
+ * Copyright (C) 2014  Wilfried Goesgens
+ *
+ * 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:
+ *   Anthony Dewhurst <dewhurst at gmail>
+ *   Aurelien Rougemont <beorn at gandi.net>
+ *   Xin Li <delphij at FreeBSD.org>
+ *   Marc Fournier <marc.fournier at camptocamp.com>
+ *   Wilfried Goesgens <dothebart at citadel.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+/*
+ * Global variables
+ */
+
+#if defined(KERNEL_LINUX)
+#include "utils_llist.h"
+#define ZOL_ARCSTATS_FILE "/proc/spl/kstat/zfs/arcstats"
+
+typedef        llist_t kstat_t;
+
+static long long get_zfs_value(kstat_t *zfs_stats  __attribute__((unused)),
+               char *name)
+{
+       llentry_t *e;
+
+       e = llist_search (zfs_stats, name);
+       if (e == NULL)
+       {
+               ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", name);
+               return (-1);
+       }
+
+       return (*(long long int*)e->value);
+}
+
+#elif !defined(__FreeBSD__) // Solaris
+extern kstat_ctl_t *kc;
+
+static long long get_zfs_value(kstat_t *ksp, char *name)
+{
+
+       return (get_kstat_value(ksp, name));
+}
+#else // FreeBSD
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+const char zfs_arcstat[] = "kstat.zfs.misc.arcstats.";
+
+#if !defined(kstat_t)
+typedef void kstat_t;
+#endif
+
+static long long get_zfs_value(kstat_t *dummy __attribute__((unused)),
+               char const *name)
+{
+       char buffer[256];
+       long long value;
+       size_t valuelen = sizeof(value);
+       int rv;
+
+       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)
+               return (value);
+
+       return (-1);
+}
+#endif
+
+static void za_submit (const char* type, const char* type_instance, value_t* values, int values_len)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values = values;
+       vl.values_len = values_len;
+
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "zfs_arc", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void za_submit_gauge (const char* type, const char* type_instance, gauge_t value)
+{
+       value_t vv;
+
+       vv.gauge = value;
+       za_submit (type, type_instance, &vv, 1);
+}
+
+static int za_read_derive (kstat_t *ksp, const char *kstat_value,
+    const char *type, const char *type_instance)
+{
+  long long tmp;
+  value_t v;
+
+  tmp = get_zfs_value (ksp, (char *)kstat_value);
+  if (tmp == -1LL)
+  {
+    WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
+    return (-1);
+  }
+
+  v.derive = (derive_t) tmp;
+  za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1);
+  return (0);
+}
+
+static int za_read_gauge (kstat_t *ksp, const char *kstat_value,
+    const char *type, const char *type_instance)
+{
+  long long tmp;
+  value_t v;
+
+  tmp = get_zfs_value (ksp, (char *)kstat_value);
+  if (tmp == -1LL)
+  {
+    WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
+    return (-1);
+  }
+
+  v.gauge = (gauge_t) tmp;
+  za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1);
+  return (0);
+}
+
+static void za_submit_ratio (const char* type_instance, gauge_t hits, gauge_t misses)
+{
+       gauge_t ratio = NAN;
+
+       if (!isfinite (hits) || (hits < 0.0))
+               hits = 0.0;
+       if (!isfinite (misses) || (misses < 0.0))
+               misses = 0.0;
+
+       if ((hits != 0.0) || (misses != 0.0))
+               ratio = hits / (hits + misses);
+
+       za_submit_gauge ("cache_ratio", type_instance, ratio);
+}
+
+static int za_read (void)
+{
+       gauge_t  arc_hits, arc_misses, l2_hits, l2_misses;
+       value_t  l2_io[2];
+       kstat_t  *ksp   = NULL;
+
+#if KERNEL_LINUX
+       long long int *llvalues = NULL;
+       char file_contents[1024 * 10];
+       char *fields[3];
+       int numfields;
+       ssize_t len;
+
+       ksp = llist_create ();
+       if (ksp == NULL)
+       {
+               ERROR ("zfs_arc plugin: `llist_create' failed.");
+               return (-1);
+       }
+
+       len = read_file_contents (ZOL_ARCSTATS_FILE, file_contents, sizeof(file_contents));
+       if (len > 1)
+       {
+
+               int i=0;
+               char *pnl = file_contents;
+               char *pnnl;
+
+               file_contents[len] = '\0';
+
+               while (pnl != NULL)
+               {
+                       pnl = strchr(pnl, '\n');
+                       i++;
+                       if (pnl && (*pnl != '\0'))
+                               pnl++;
+               }
+
+               if (i > 0)
+               {
+                       llentry_t *e;
+                       llvalues = malloc(sizeof(long long int) * i);
+                       int j = 0;
+
+                       pnl = file_contents;
+                       while (pnl != NULL)
+                       {
+                               pnnl = strchr(pnl, '\n');
+                               if (pnnl != NULL)
+                                       *pnnl = '\0';
+
+                               numfields = strsplit (pnl, fields, 4);
+                               if (numfields == 3)
+                               {
+                                       llvalues[j] = atoll (fields[2]);
+
+                                       e = llentry_create (fields[0], &llvalues[j]);
+                                       if (e == NULL)
+                                       {
+                                               ERROR ("zfs_arc plugin: `llentry_create' failed.");
+                                       }
+                                       else
+                                       {
+                                               llist_append (ksp, e);
+                                       }
+                                       j++;
+                               }
+                               pnl = pnnl;
+                               if (pnl != NULL)
+                                       pnl ++;
+                       }
+               }
+       }
+
+#elif !defined(__FreeBSD__) // Solaris
+       get_kstat (&ksp, "zfs", 0, "arcstats");
+       if (ksp == NULL)
+       {
+               ERROR ("zfs_arc plugin: Cannot find zfs:0:arcstats kstat.");
+               return (-1);
+       }
+#endif
+
+       /* Sizes */
+       za_read_gauge (ksp, "size",    "cache_size", "arc");
+
+       /* 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.
+        */
+       static int l2_size_avail = 1;
+       if (l2_size_avail && za_read_gauge (ksp, "l2_size", "cache_size", "L2") != 0)
+               l2_size_avail = 0;
+
+       /* Operations */
+       za_read_derive (ksp, "deleted",  "cache_operation", "deleted");
+#if __FreeBSD__
+       za_read_derive (ksp, "allocated","cache_operation", "allocated");
+       za_read_derive (ksp, "stolen",   "cache_operation", "stolen");
+#endif
+
+       /* Issue indicators */
+       za_read_derive (ksp, "mutex_miss", "mutex_operations", "miss");
+       za_read_derive (ksp, "hash_collisions", "hash_collisions", "");
+
+       /* Evictions */
+       za_read_derive (ksp, "evict_l2_cached",     "cache_eviction", "cached");
+       za_read_derive (ksp, "evict_l2_eligible",   "cache_eviction", "eligible");
+       za_read_derive (ksp, "evict_l2_ineligible", "cache_eviction", "ineligible");
+
+       /* Hits / misses */
+       za_read_derive (ksp, "demand_data_hits",         "cache_result", "demand_data-hit");
+       za_read_derive (ksp, "demand_metadata_hits",     "cache_result", "demand_metadata-hit");
+       za_read_derive (ksp, "prefetch_data_hits",       "cache_result", "prefetch_data-hit");
+       za_read_derive (ksp, "prefetch_metadata_hits",   "cache_result", "prefetch_metadata-hit");
+       za_read_derive (ksp, "demand_data_misses",       "cache_result", "demand_data-miss");
+       za_read_derive (ksp, "demand_metadata_misses",   "cache_result", "demand_metadata-miss");
+       za_read_derive (ksp, "prefetch_data_misses",     "cache_result", "prefetch_data-miss");
+       za_read_derive (ksp, "prefetch_metadata_misses", "cache_result", "prefetch_metadata-miss");
+
+       /* Ratios */
+       arc_hits   = (gauge_t) get_zfs_value(ksp, "hits");
+       arc_misses = (gauge_t) get_zfs_value(ksp, "misses");
+       l2_hits    = (gauge_t) get_zfs_value(ksp, "l2_hits");
+       l2_misses  = (gauge_t) get_zfs_value(ksp, "l2_misses");
+
+       za_submit_ratio ("arc", arc_hits, arc_misses);
+       za_submit_ratio ("L2", l2_hits, l2_misses);
+
+       /* I/O */
+       l2_io[0].derive = get_zfs_value(ksp, "l2_read_bytes");
+       l2_io[1].derive = get_zfs_value(ksp, "l2_write_bytes");
+
+       za_submit ("io_octets", "L2", l2_io, /* num values = */ 2);
+
+#if defined(KERNEL_LINUX)
+       if (llvalues != NULL)
+       {
+               free(llvalues);
+       }
+       if (ksp != NULL)
+       {
+               llist_destroy (ksp);
+       }
+#endif
+
+       return (0);
+} /* int za_read */
+
+static int za_init (void) /* {{{ */
+{
+#if !defined(__FreeBSD__) && !defined(KERNEL_LINUX) // Solaris
+       /* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */
+       if (kc == NULL)
+       {
+               ERROR ("zfs_arc plugin: kstat chain control structure not available.");
+               return (-1);
+       }
+#endif
+
+       return (0);
+} /* }}} int za_init */
+
+void module_register (void)
+{
+       plugin_register_init ("zfs_arc", za_init);
+       plugin_register_read ("zfs_arc", za_read);
+} /* void module_register */
+
+/* vmi: set sw=8 noexpandtab fdm=marker : */
diff --git a/src/zookeeper.c b/src/zookeeper.c
new file mode 100644 (file)
index 0000000..63ee6c9
--- /dev/null
@@ -0,0 +1,322 @@
+/**
+ * collectd - src/zookeeper.c
+ * Copyright (C) 2014       Google, Inc.
+ *
+ * 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:
+ *   Jeremy Katz <jeremy at katzbox.net>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#define ZOOKEEPER_DEF_HOST "127.0.0.1"
+#define ZOOKEEPER_DEF_PORT "2181"
+
+static char *zk_host = NULL;
+static char *zk_port = NULL;
+
+static const char *config_keys[] =
+{
+       "Host",
+       "Port"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int zookeeper_config(const char *key, const char *value)
+{
+       if (strncmp(key, "Host", strlen("Host")) == 0)
+       {
+               sfree (zk_host);
+               zk_host = strdup (value);
+       }
+       else if (strncmp(key, "Port", strlen("Port")) == 0)
+       {
+               sfree (zk_port);
+               zk_port = strdup (value);
+       }
+       else
+       {
+               return -1;
+       }
+       return 0;
+}
+
+static void zookeeper_submit_gauge (const char * type, const char * type_inst, gauge_t val)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = val;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "zookeeper", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_inst != NULL)
+               sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* zookeeper_submit_gauge */
+
+static void zookeeper_submit_derive (const char * type, const char * type_inst, derive_t val)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].derive = val;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "zookeeper", sizeof (vl.plugin));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_inst != NULL)
+               sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* zookeeper_submit_derive */
+
+static int zookeeper_connect (void)
+{
+       int sk = -1;
+       int status;
+       struct addrinfo ai_hints;
+       struct addrinfo *ai;
+       struct addrinfo *ai_list;
+       char *host;
+       char *port;
+
+       memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
+       ai_hints.ai_family   = AF_UNSPEC;
+       ai_hints.ai_socktype = SOCK_STREAM;
+
+       host = (zk_host != NULL) ? zk_host : ZOOKEEPER_DEF_HOST;
+       port = (zk_port != NULL) ? zk_port : ZOOKEEPER_DEF_PORT;
+       status = getaddrinfo (host, port, &ai_hints, &ai_list);
+       if (status != 0)
+       {
+               char errbuf[1024];
+               INFO ("getaddrinfo failed: %s",
+                         (status == EAI_SYSTEM)
+                         ? sstrerror (errno, errbuf, sizeof (errbuf))
+                         : gai_strerror (status));
+               return (-1);
+       }
+
+       for (ai = ai_list; ai != NULL; ai = ai->ai_next)
+       {
+               sk = socket (ai->ai_family, SOCK_STREAM, 0);
+               if (sk < 0)
+               {
+                       char errbuf[1024];
+                       WARNING ("zookeeper: socket(2) failed: %s",
+                                        sstrerror (errno, errbuf, sizeof(errbuf)));
+                       continue;
+               }
+               status = (int) connect (sk, ai->ai_addr, ai->ai_addrlen);
+               if (status != 0)
+               {
+                       char errbuf[1024];
+                       close (sk);
+                       sk = -1;
+                       WARNING ("zookeeper: connect(2) failed: %s",
+                                        sstrerror (errno, errbuf, sizeof(errbuf)));
+                       continue;
+               }
+
+               /* connected */
+               break;
+       }
+
+       freeaddrinfo(ai_list);
+       return (sk);
+} /* int zookeeper_connect */
+
+static int zookeeper_query (char *buffer, size_t buffer_size)
+{
+       int sk = -1;
+       int status;
+       size_t buffer_fill;
+
+       sk = zookeeper_connect();
+       if (sk < 0)
+       {
+               ERROR ("zookeeper: Could not connect to daemon");
+               return (-1);
+       }
+
+       status = (int) swrite (sk, "mntr\r\n", strlen("mntr\r\n"));
+       if (status != 0)
+       {
+               char errbuf[1024];
+               ERROR ("zookeeper: write(2) failed: %s",
+                          sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (sk);
+               return (-1);
+       }
+
+       memset (buffer, 0, buffer_size);
+       buffer_fill = 0;
+
+       while ((status = (int) recv (sk, buffer + buffer_fill,
+          buffer_size - buffer_fill, /* flags = */ 0)) != 0)
+       {
+               if (status < 0)
+               {
+                       char errbuf[1024];
+                       if ((errno == EAGAIN) || (errno == EINTR))
+                               continue;
+                       ERROR ("zookeeper: Error reading from socket: %s",
+                                  sstrerror (errno, errbuf, sizeof (errbuf)));
+                       close (sk);
+                       return (-1);
+               }
+
+               buffer_fill += (size_t) status;
+               if (status == 0)
+               {
+                       /* done reading from the socket */
+                       break;
+               }
+       } /* while (recv) */
+
+       status = 0;
+       if (buffer_fill == 0)
+       {
+               WARNING ("zookeeper: No data returned by MNTR command.");
+               status = -1;
+       }
+
+       close(sk);
+       return (status);
+} /* int zookeeper_query */
+
+
+static int zookeeper_read (void) {
+       char buf[4096];
+       char *ptr;
+       char *save_ptr;
+       char *line;
+       char *fields[2];
+
+       if (zookeeper_query (buf, sizeof (buf)) < 0)
+       {
+               return (-1);
+       }
+
+       ptr = buf;
+       save_ptr = NULL;
+       while ((line = strtok_r (ptr, "\n\r", &save_ptr)) != NULL)
+       {
+               ptr = NULL;
+               if (strsplit(line, fields, 2) != 2)
+               {
+                       continue;
+               }
+#define FIELD_CHECK(check, expected) \
+       (strncmp (check, expected, strlen(expected)) == 0)
+
+               if (FIELD_CHECK (fields[0], "zk_avg_latency"))
+               {
+                       zookeeper_submit_gauge ("latency", "avg", atol(fields[1]));
+               }
+               else if (FIELD_CHECK(fields[0], "zk_min_latency"))
+               {
+                       zookeeper_submit_gauge ("latency", "min", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_max_latency"))
+               {
+                       zookeeper_submit_gauge ("latency", "max", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_packets_received"))
+               {
+                       zookeeper_submit_derive ("packets", "received", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_packets_sent"))
+               {
+                       zookeeper_submit_derive ("packets", "sent", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_num_alive_connections"))
+               {
+                       zookeeper_submit_gauge ("current_connections", NULL, atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_outstanding_requests"))
+               {
+                       zookeeper_submit_gauge ("requests", "outstanding", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_znode_count"))
+               {
+                       zookeeper_submit_gauge ("gauge", "znode", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_watch_count"))
+               {
+                       zookeeper_submit_gauge ("gauge", "watch", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_ephemerals_count"))
+               {
+                       zookeeper_submit_gauge ("gauge", "ephemerals", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_ephemerals_count"))
+               {
+                       zookeeper_submit_gauge ("gauge", "ephemerals", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_ephemerals_count"))
+               {
+                       zookeeper_submit_gauge ("gauge", "ephemerals", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_approximate_data_size"))
+               {
+                       zookeeper_submit_gauge ("bytes", "approximate_data_size", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_followers"))
+               {
+                       zookeeper_submit_gauge ("count", "followers", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_synced_followers"))
+               {
+                       zookeeper_submit_gauge ("count", "synced_followers", atol(fields[1]));
+               }
+               else if (FIELD_CHECK (fields[0], "zk_pending_syncs"))
+               {
+                       zookeeper_submit_gauge ("count", "pending_syncs", atol(fields[1]));
+               }
+               else
+               {
+                       DEBUG("Uncollected zookeeper MNTR field %s", fields[0]);
+               }
+       }
+
+       return (0);
+} /* zookeeper_read */
+
+void module_register (void)
+{
+       plugin_register_config ("zookeeper", zookeeper_config, config_keys, config_keys_num);
+       plugin_register_read ("zookeeper", zookeeper_read);
+} /* void module_register */
diff --git a/version-gen.sh b/version-gen.sh
new file mode 100755 (executable)
index 0000000..b09be8e
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+DEFAULT_VERSION="5.5.0.git"
+
+VERSION="`git describe 2> /dev/null | grep collectd | sed -e 's/^collectd-//'`"
+
+if test -z "$VERSION"; then
+       VERSION="$DEFAULT_VERSION"
+fi
+
+VERSION="`echo \"$VERSION\" | sed -e 's/-/./g'`"
+
+printf "%s" "$VERSION"
diff --git a/ylwrap b/ylwrap
new file mode 100755 (executable)
index 0000000..84d5634
--- /dev/null
+++ b/ylwrap
@@ -0,0 +1,222 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
+# 2007, 2009 Free Software Foundation, Inc.
+#
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case "$1" in
+  '')
+    echo "$0: No files given.  Try \`$0 --help' for more information." 1>&2
+    exit 1
+    ;;
+  --basedir)
+    basedir=$2
+    shift 2
+    ;;
+  -h|--h*)
+    cat <<\EOF
+Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+
+Wrapper for lex/yacc invocations, renaming files as desired.
+
+  INPUT is the input file
+  OUTPUT is one file PROG generates
+  DESIRED is the file we actually want instead of OUTPUT
+  PROGRAM is program to run
+  ARGS are passed to PROG
+
+Any number of OUTPUT,DESIRED pairs may be used.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v|--v*)
+    echo "ylwrap $scriptversion"
+    exit $?
+    ;;
+esac
+
+
+# The input.
+input="$1"
+shift
+case "$input" in
+  [\\/]* | ?:[\\/]*)
+    # Absolute path; do nothing.
+    ;;
+  *)
+    # Relative path.  Make it absolute.
+    input="`pwd`/$input"
+    ;;
+esac
+
+pairlist=
+while test "$#" -ne 0; do
+  if test "$1" = "--"; then
+    shift
+    break
+  fi
+  pairlist="$pairlist $1"
+  shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+  [\\/]* | ?:[\\/]*) ;;
+  *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines.  But that might take us over the 14-char limit.
+dirname=ylwrap$$
+trap "cd '`pwd`'; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+case $# in
+  0) "$prog" "$input" ;;
+  *) "$prog" "$@" "$input" ;;
+esac
+ret=$?
+
+if test $ret -eq 0; then
+  set X $pairlist
+  shift
+  first=yes
+  # Since DOS filename conventions don't allow two dots,
+  # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+  # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+  y_tab_nodot="no"
+  if test -f y_tab.c || test -f y_tab.h; then
+    y_tab_nodot="yes"
+  fi
+
+  # The directory holding the input.
+  input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+  # Quote $INPUT_DIR so we can use it in a regexp.
+  # FIXME: really we should care about more than `.' and `\'.
+  input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
+
+  while test "$#" -ne 0; do
+    from="$1"
+    # Handle y_tab.c and y_tab.h output by DOS
+    if test $y_tab_nodot = "yes"; then
+      if test $from = "y.tab.c"; then
+       from="y_tab.c"
+      else
+       if test $from = "y.tab.h"; then
+         from="y_tab.h"
+       fi
+      fi
+    fi
+    if test -f "$from"; then
+      # If $2 is an absolute path name, then just use that,
+      # otherwise prepend `../'.
+      case "$2" in
+       [\\/]* | ?:[\\/]*) target="$2";;
+       *) target="../$2";;
+      esac
+
+      # We do not want to overwrite a header file if it hasn't
+      # changed.  This avoid useless recompilations.  However the
+      # parser itself (the first file) should always be updated,
+      # because it is the destination of the .y.c rule in the
+      # Makefile.  Divert the output of all other files to a temporary
+      # file so we can compare them to existing versions.
+      if test $first = no; then
+       realtarget="$target"
+       target="tmp-`echo $target | sed s/.*[\\/]//g`"
+      fi
+      # Edit out `#line' or `#' directives.
+      #
+      # We don't want the resulting debug information to point at
+      # an absolute srcdir; it is better for it to just mention the
+      # .y file with no path.
+      #
+      # We want to use the real output file name, not yy.lex.c for
+      # instance.
+      #
+      # We want the include guards to be adjusted too.
+      FROM=`echo "$from" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+      TARGET=`echo "$2" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+
+      sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
+          -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
+
+      # Check whether header files must be updated.
+      if test $first = no; then
+       if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
+         echo "$2" is unchanged
+         rm -f "$target"
+       else
+          echo updating "$2"
+          mv -f "$target" "$realtarget"
+        fi
+      fi
+    else
+      # A missing file is only an error for the first file.  This
+      # is a blatant hack to let us support using "yacc -d".  If -d
+      # is not specified, we don't want an error when the header
+      # file is "missing".
+      if test $first = yes; then
+        ret=1
+      fi
+    fi
+    shift
+    shift
+    first=no
+  done
+else
+  ret=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End: